Skip to content

Commit 9618e73

Browse files
committed
Regions: Migrate descriptor objects
1 parent f709295 commit 9618e73

6 files changed

Lines changed: 76 additions & 26 deletions

File tree

Include/descrobject.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,16 @@ struct PyMemberDef {
8787
// TODO(Immutable): Could use this to mark members as needing a lock.
8888

8989
PyAPI_FUNC(PyObject *) PyMember_GetOne(const char *, PyMemberDef *);
90+
91+
// TODO(regions): xFrednet: This function is used to modify Python objects
92+
// but we can't really add a region write barrier, because we don't
93+
// have the reference source.
94+
// I see two solutions:
95+
// (1) Break the public API (Which I'm doing in this patch)
96+
// (2) Deprecate this function in favor of a new one. Usage of this
97+
// old API will result in regions being marked as dirty.
9098
PyAPI_FUNC(int) PyMember_SetOne(char *, PyMemberDef *, PyObject *);
99+
PyAPI_FUNC(int) PyMember_SetOneOn(PyObject* obj, char *, PyMemberDef *, PyObject *);
91100

92101
#ifndef Py_LIMITED_API
93102
# define Py_CPYTHON_DESCROBJECT_H

Modules/_testlimitedcapi/heaptype_relative.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ static PyObject *
217217
heaptype_with_member_set_memb(PyObject *self, PyObject *value)
218218
{
219219
PyMemberDef *def = heaptype_with_member_extract_and_check_memb(self);
220-
int r = PyMember_SetOne((char *)self, def, value);
220+
int r = PyMember_SetOneOn(self, (char *)self, def, value);
221221
if (r < 0) {
222222
return NULL;
223223
}
@@ -242,7 +242,7 @@ static PyObject *
242242
heaptype_with_member_set_memb_relative(PyObject *self, PyObject *value)
243243
{
244244
PyMemberDef def = {"memb", Py_T_BYTE, sizeof(PyObject), Py_RELATIVE_OFFSET};
245-
int r = PyMember_SetOne((char *)self, &def, value);
245+
int r = PyMember_SetOneOn(self, (char *)self, &def, value);
246246
if (r < 0) {
247247
return NULL;
248248
}

Objects/descrobject.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ method_get(PyObject *self, PyObject *obj, PyObject *type)
139139
{
140140
PyMethodDescrObject *descr = (PyMethodDescrObject *)self;
141141
if (obj == NULL) {
142-
return Py_NewRef(descr);
142+
return PyRegion_NewRef(descr);
143143
}
144144
if (descr_check((PyDescrObject *)descr, obj) < 0) {
145145
return NULL;
@@ -164,7 +164,7 @@ member_get(PyObject *self, PyObject *obj, PyObject *type)
164164
{
165165
PyMemberDescrObject *descr = (PyMemberDescrObject *)self;
166166
if (obj == NULL) {
167-
return Py_NewRef(descr);
167+
return PyRegion_NewRef(descr);
168168
}
169169
if (descr_check((PyDescrObject *)descr, obj) < 0) {
170170
return NULL;
@@ -242,7 +242,7 @@ member_set(PyObject *self, PyObject *obj, PyObject *value)
242242
if (descr_setcheck((PyDescrObject *)descr, obj, value) < 0) {
243243
return -1;
244244
}
245-
return PyMember_SetOne((char *)obj, descr->d_member, value);
245+
return PyMember_SetOneOn(obj, (char *)obj, descr->d_member, value);
246246
}
247247

248248
static int
@@ -519,7 +519,7 @@ classmethoddescr_call(PyObject *_descr, PyObject *args,
519519
}
520520
PyObject *res = PyObject_VectorcallDict(bound, _PyTuple_ITEMS(args)+1,
521521
argc-1, kwds);
522-
Py_DECREF(bound);
522+
PyRegion_CLEARLOCAL(bound);
523523
return res;
524524
}
525525

@@ -540,6 +540,13 @@ wrapperdescr_raw_call(PyWrapperDescrObject *descr, PyObject *self,
540540
descr->d_base->name);
541541
return NULL;
542542
}
543+
544+
if (descr->d_common.d_type) {
545+
PyRegion_NotifyTypeUse(descr->d_common.d_type);
546+
} else {
547+
PyRegion_DirtyAllRegions("A descriptor without a type was called");
548+
}
549+
543550
return (*wrapper)(self, args, descr->d_wrapped);
544551
}
545552

@@ -579,7 +586,7 @@ wrapperdescr_call(PyObject *_descr, PyObject *args, PyObject *kwds)
579586
return NULL;
580587
}
581588
result = wrapperdescr_raw_call(descr, self, args, kwds);
582-
Py_DECREF(args);
589+
PyRegion_CLEARLOCAL(args);
583590
return result;
584591
}
585592

@@ -619,12 +626,12 @@ calculate_qualname(PyDescrObject *descr)
619626
if (!PyUnicode_Check(type_qualname)) {
620627
PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__."
621628
"__qualname__ is not a unicode object");
622-
Py_XDECREF(type_qualname);
629+
PyRegion_CLEARLOCAL(type_qualname);
623630
return NULL;
624631
}
625632

626633
res = PyUnicode_FromFormat("%S.%S", type_qualname, descr->d_name);
627-
Py_DECREF(type_qualname);
634+
PyRegion_CLEARLOCAL(type_qualname);
628635
return res;
629636
}
630637

@@ -763,6 +770,7 @@ PyTypeObject PyMethodDescr_Type = {
763770
method_get, /* tp_descr_get */
764771
0, /* tp_descr_set */
765772
.tp_reachable = _PyObject_ReachableVisitType,
773+
.tp_flags2 = Py_TPFLAGS2_REGION_AWARE,
766774
};
767775

768776
/* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */
@@ -802,6 +810,7 @@ PyTypeObject PyClassMethodDescr_Type = {
802810
classmethod_get, /* tp_descr_get */
803811
0, /* tp_descr_set */
804812
.tp_reachable = _PyObject_ReachableVisitType,
813+
.tp_flags2 = Py_TPFLAGS2_REGION_AWARE,
805814
};
806815

807816
PyTypeObject PyMemberDescr_Type = {
@@ -840,6 +849,7 @@ PyTypeObject PyMemberDescr_Type = {
840849
member_get, /* tp_descr_get */
841850
member_set, /* tp_descr_set */
842851
.tp_reachable = _PyObject_ReachableVisitType,
852+
.tp_flags2 = Py_TPFLAGS2_REGION_AWARE,
843853
};
844854

845855
PyTypeObject PyGetSetDescr_Type = {
@@ -879,6 +889,7 @@ PyTypeObject PyGetSetDescr_Type = {
879889
getset_set, /* tp_descr_set */
880890
.tp_reachable = _PyObject_ReachableVisitType,
881891
.tp_flags2 = Py_TPFLAGS2_REGION_AWARE
892+
.tp_flags2 = Py_TPFLAGS2_REGION_AWARE,
882893
};
883894

884895
PyTypeObject PyWrapperDescr_Type = {
@@ -918,6 +929,7 @@ PyTypeObject PyWrapperDescr_Type = {
918929
wrapperdescr_get, /* tp_descr_get */
919930
0, /* tp_descr_set */
920931
.tp_reachable = _PyObject_ReachableVisitType,
932+
.tp_flags2 = Py_TPFLAGS2_REGION_AWARE,
921933
};
922934

923935
static PyDescrObject *
@@ -1533,7 +1545,7 @@ PyWrapper_New(PyObject *d, PyObject *self)
15331545
wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type);
15341546
if (wp == NULL)
15351547
return NULL;
1536-
if (PyRegion_AddRef(wp, descr)){
1548+
if (PyRegion_AddRefs(wp, descr, self)){
15371549
Py_DECREF(wp);
15381550
return NULL;
15391551
}

Objects/methodobject.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject *module, PyTypeObject *c
9494
return NULL;
9595
}
9696
}
97+
if (PyRegion_AddRef(om, cls)) {
98+
Py_DECREF(om);
99+
return NULL;
100+
}
97101
om->mm_class = (PyTypeObject*)Py_NewRef(cls);
98102
op = (PyCFunctionObject *)om;
99103
} else {
@@ -112,6 +116,10 @@ PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject *module, PyTypeObject *c
112116
}
113117
}
114118

119+
if (PyRegion_AddRefs(op, self, module)) {
120+
Py_DECREF(op);
121+
return NULL;
122+
}
115123
op->m_weakreflist = NULL;
116124
op->m_ml = ml;
117125
op->m_self = Py_XNewRef(self);

Python/structmember.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
9595
Py_END_CRITICAL_SECTION();
9696
}
9797
#else
98+
if (PyRegion_AddLocalRef(v)) {
99+
return NULL;
100+
}
98101
Py_INCREF(v);
99102
#endif
100103
}
@@ -105,6 +108,9 @@ PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
105108
case Py_T_OBJECT_EX:
106109
v = member_get_object(addr, obj_addr, l);
107110
#ifndef Py_GIL_DISABLED
111+
if (PyRegion_AddLocalRef(v)) {
112+
return NULL;
113+
}
108114
Py_XINCREF(v);
109115
#else
110116
if (v != NULL) {
@@ -141,7 +147,12 @@ PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
141147
} while (0)
142148

143149
int
144-
PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
150+
PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) {
151+
return PyMember_SetOneOn(NULL, addr, l, v);
152+
}
153+
154+
int
155+
PyMember_SetOneOn(PyObject* target, char *addr, PyMemberDef *l, PyObject *v)
145156
{
146157
PyObject *oldv;
147158
if (l->flags & Py_RELATIVE_OFFSET) {
@@ -244,7 +255,7 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
244255
}
245256
if (_PyLong_IsNegative((PyLongObject *)v)) {
246257
long long_val = PyLong_AsLong(v);
247-
Py_DECREF(v);
258+
PyRegion_CLEARLOCAL(v);
248259
if (long_val == -1 && PyErr_Occurred()) {
249260
return -1;
250261
}
@@ -253,7 +264,7 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
253264
}
254265
else {
255266
unsigned long ulong_val = PyLong_AsUnsignedLong(v);
256-
Py_DECREF(v);
267+
PyRegion_CLEARLOCAL(v);
257268
if (ulong_val == (unsigned long)-1 && PyErr_Occurred()) {
258269
return -1;
259270
}
@@ -280,7 +291,7 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
280291
}
281292
if (_PyLong_IsNegative((PyLongObject *)v)) {
282293
long long_val = PyLong_AsLong(v);
283-
Py_DECREF(v);
294+
PyRegion_CLEARLOCAL(v);
284295
if (long_val == -1 && PyErr_Occurred()) {
285296
return -1;
286297
}
@@ -289,7 +300,7 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
289300
}
290301
else {
291302
unsigned long ulong_val = PyLong_AsUnsignedLong(v);
292-
Py_DECREF(v);
303+
PyRegion_CLEARLOCAL(v);
293304
if (ulong_val == (unsigned long)-1 && PyErr_Occurred()) {
294305
return -1;
295306
}
@@ -320,6 +331,12 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
320331
}
321332
case _Py_T_OBJECT:
322333
case Py_T_OBJECT_EX:
334+
335+
if (target == NULL) {
336+
PyRegion_DirtyAllRegions("Call of `PyMember_SetOne`");
337+
} else if (PyRegion_AddRef(target, v)) {
338+
return -1;
339+
}
323340
Py_BEGIN_CRITICAL_SECTION(obj);
324341
oldv = *(PyObject **)addr;
325342
FT_ATOMIC_STORE_PTR_RELEASE(*(PyObject **)addr, Py_XNewRef(v));
@@ -356,7 +373,7 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
356373
}
357374
if (_PyLong_IsNegative((PyLongObject *)v)) {
358375
long long_val = PyLong_AsLong(v);
359-
Py_DECREF(v);
376+
PyRegion_CLEARLOCAL(v);
360377
if (long_val == -1 && PyErr_Occurred()) {
361378
return -1;
362379
}
@@ -365,7 +382,7 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
365382
}
366383
else {
367384
unsigned long long ulonglong_val = PyLong_AsUnsignedLongLong(v);
368-
Py_DECREF(v);
385+
PyRegion_CLEARLOCAL(v);
369386
if (ulonglong_val == (unsigned long long)-1 && PyErr_Occurred()) {
370387
return -1;
371388
}

Python/sysmodule.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,10 @@ sys_audit_tstate(PyThreadState *ts, const char *event,
278278
eventArgs = Py_VaBuildValue(argFormat, vargs);
279279
if (eventArgs && !PyTuple_Check(eventArgs)) {
280280
PyObject *argTuple = PyTuple_Pack(1, eventArgs);
281-
Py_SETREF(eventArgs, argTuple);
281+
if (PyRegion_XSETLOCALREF(eventArgs, argTuple)) {
282+
Py_DECREF(argTuple);
283+
goto exit;
284+
}
282285
}
283286
}
284287
else {
@@ -294,6 +297,7 @@ sys_audit_tstate(PyThreadState *ts, const char *event,
294297
* since that would not leave is in an inconsistent state. */
295298
_Py_AuditHookEntry *e = is->runtime->audit_hooks.head;
296299
for (; e; e = e->next) {
300+
PyRegion_DirtyAllRegions("Calling unknown `_Py_AuditHookEntry`");
297301
if (e->hookCFunction(event, eventArgs, e->userData) < 0) {
298302
goto exit;
299303
}
@@ -323,7 +327,7 @@ sys_audit_tstate(PyThreadState *ts, const char *event,
323327
int canTrace = PyObject_GetOptionalAttr(hook, &_Py_ID(__cantrace__), &o);
324328
if (o) {
325329
canTrace = PyObject_IsTrue(o);
326-
Py_DECREF(o);
330+
PyRegion_CLEARLOCAL(o);
327331
}
328332
if (canTrace < 0) {
329333
break;
@@ -339,8 +343,8 @@ sys_audit_tstate(PyThreadState *ts, const char *event,
339343
if (!o) {
340344
break;
341345
}
342-
Py_DECREF(o);
343-
Py_CLEAR(hook);
346+
PyRegion_CLEARLOCAL(o);
347+
PyRegion_CLEARLOCAL(hook);
344348
}
345349
PyThreadState_LeaveTracing(ts);
346350
if (_PyErr_Occurred(ts)) {
@@ -351,17 +355,17 @@ sys_audit_tstate(PyThreadState *ts, const char *event,
351355
res = 0;
352356

353357
exit:
354-
Py_XDECREF(hook);
355-
Py_XDECREF(hooks);
356-
Py_XDECREF(eventName);
357-
Py_XDECREF(eventArgs);
358+
PyRegion_CLEARLOCAL(hook);
359+
PyRegion_CLEARLOCAL(hooks);
360+
PyRegion_CLEARLOCAL(eventName);
361+
PyRegion_CLEARLOCAL(eventArgs);
358362

359363
if (!res) {
360364
_PyErr_SetRaisedException(ts, exc);
361365
}
362366
else {
363367
assert(_PyErr_Occurred(ts));
364-
Py_XDECREF(exc);
368+
PyRegion_CLEARLOCAL(exc);
365369
}
366370

367371
return res;

0 commit comments

Comments
 (0)