Skip to content

Commit 8a25bfb

Browse files
Address Sam's reviews
1 parent a88d238 commit 8a25bfb

File tree

3 files changed

+53
-44
lines changed

3 files changed

+53
-44
lines changed

Include/internal/pycore_dict.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ _PyInlineValuesSize(PyTypeObject *tp)
323323
int
324324
_PyDict_DetachFromObject(PyDictObject *dict, PyObject *obj);
325325

326-
PyDictObject *_PyObject_materialize_managed_dict_lock_held(PyObject *);
326+
PyDictObject *_PyObject_MaterializeManagedDict_LockHeld(PyObject *);
327327

328328
#ifdef __cplusplus
329329
}

Objects/dictobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6709,7 +6709,7 @@ make_dict_from_instance_attributes(PyInterpreterState *interp,
67096709
}
67106710

67116711
PyDictObject *
6712-
_PyObject_materialize_managed_dict_lock_held(PyObject *obj)
6712+
_PyObject_MaterializeManagedDict_LockHeld(PyObject *obj)
67136713
{
67146714
ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(obj);
67156715

@@ -6740,7 +6740,7 @@ _PyObject_MaterializeManagedDict(PyObject *obj)
67406740
goto exit;
67416741
}
67426742
#endif
6743-
dict = _PyObject_materialize_managed_dict_lock_held(obj);
6743+
dict = _PyObject_MaterializeManagedDict_LockHeld(obj);
67446744

67456745
#ifdef Py_GIL_DISABLED
67466746
exit:

Objects/typeobject.c

Lines changed: 50 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6604,34 +6604,11 @@ compatible_for_assignment(PyTypeObject* oldto, PyTypeObject* newto, const char*
66046604
return 0;
66056605
}
66066606

6607-
static int
6608-
object_set_class(PyObject *self, PyObject *value, void *closure)
6609-
{
6610-
6611-
if (value == NULL) {
6612-
PyErr_SetString(PyExc_TypeError,
6613-
"can't delete __class__ attribute");
6614-
return -1;
6615-
}
6616-
if (!PyType_Check(value)) {
6617-
PyErr_Format(PyExc_TypeError,
6618-
"__class__ must be set to a class, not '%s' object",
6619-
Py_TYPE(value)->tp_name);
6620-
return -1;
6621-
}
6622-
PyTypeObject *newto = (PyTypeObject *)value;
66236607

6624-
if (PySys_Audit("object.__setattr__", "OsO",
6625-
self, "__class__", value) < 0) {
6626-
return -1;
6627-
}
66286608

6629-
#ifdef Py_GIL_DISABLED
6630-
PyInterpreterState *interp = _PyInterpreterState_GET();
6631-
// The real Py_TYPE(self) (`oldto`) may have changed from
6632-
// underneath us in another thread, so we stop the world.
6633-
_PyEval_StopTheWorld(interp);
6634-
#endif
6609+
static int
6610+
object_set_class_no_world_stopped(PyObject *self, PyTypeObject *newto, PyTypeObject **oldto_p)
6611+
{
66356612
PyTypeObject *oldto = Py_TYPE(self);
66366613

66376614
/* In versions of CPython prior to 3.5, the code in
@@ -6690,7 +6667,7 @@ object_set_class(PyObject *self, PyObject *value, void *closure)
66906667
PyErr_Format(PyExc_TypeError,
66916668
"__class__ assignment only supported for mutable types "
66926669
"or ModuleType subclasses");
6693-
goto err;
6670+
return -1;
66946671
}
66956672

66966673
if (compatible_for_assignment(oldto, newto, "__class__")) {
@@ -6699,9 +6676,9 @@ object_set_class(PyObject *self, PyObject *value, void *closure)
66996676
if (oldto->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
67006677
PyDictObject *dict = _PyObject_GetManagedDict(self);
67016678
if (dict == NULL) {
6702-
dict = _PyObject_materialize_managed_dict_lock_held(self);
6679+
dict = _PyObject_MaterializeManagedDict_LockHeld(self);
67036680
if (dict == NULL) {
6704-
goto err;
6681+
return -1;
67056682
}
67066683
}
67076684

@@ -6714,35 +6691,67 @@ object_set_class(PyObject *self, PyObject *value, void *closure)
67146691
dict->ma_values != _PyObject_InlineValues(self));
67156692

67166693
if (_PyDict_DetachFromObject(dict, self) < 0) {
6717-
goto err;
6694+
return -1;
67186695
}
67196696

67206697
}
67216698
if (newto->tp_flags & Py_TPFLAGS_HEAPTYPE) {
67226699
Py_INCREF(newto);
67236700
}
67246701

6725-
#ifdef Py_GIL_DISABLED
6726-
_PyEval_StartTheWorld(interp);
6727-
#endif
67286702
Py_SET_TYPE(self, newto);
67296703

6730-
if (oldto->tp_flags & Py_TPFLAGS_HEAPTYPE) {
6731-
Py_DECREF(oldto);
6732-
}
6733-
6734-
RARE_EVENT_INC(set_class);
6704+
*oldto_p = oldto;
67356705

67366706
return 0;
67376707
}
67386708
else {
6739-
goto err;
6709+
return -1;
67406710
}
6741-
err:
6711+
}
6712+
6713+
static int
6714+
object_set_class(PyObject *self, PyObject *value, void *closure)
6715+
{
6716+
6717+
if (value == NULL) {
6718+
PyErr_SetString(PyExc_TypeError,
6719+
"can't delete __class__ attribute");
6720+
return -1;
6721+
}
6722+
if (!PyType_Check(value)) {
6723+
PyErr_Format(PyExc_TypeError,
6724+
"__class__ must be set to a class, not '%s' object",
6725+
Py_TYPE(value)->tp_name);
6726+
return -1;
6727+
}
6728+
PyTypeObject *newto = (PyTypeObject *)value;
6729+
6730+
if (PySys_Audit("object.__setattr__", "OsO",
6731+
self, "__class__", value) < 0) {
6732+
return -1;
6733+
}
6734+
6735+
#ifdef Py_GIL_DISABLED
6736+
PyInterpreterState *interp = _PyInterpreterState_GET();
6737+
// The real Py_TYPE(self) (`oldto`) may have changed from
6738+
// underneath us in another thread, so we stop the world.
6739+
_PyEval_StopTheWorld(interp);
6740+
#endif
6741+
PyTypeObject *oldto;
6742+
int res = object_set_class_no_world_stopped(self, newto, &oldto);
67426743
#ifdef Py_GIL_DISABLED
67436744
_PyEval_StartTheWorld(interp);
67446745
#endif
6745-
return -1;
6746+
if (res == 0) {
6747+
if (oldto->tp_flags & Py_TPFLAGS_HEAPTYPE) {
6748+
Py_DECREF(oldto);
6749+
}
6750+
6751+
RARE_EVENT_INC(set_class);
6752+
return 0;
6753+
}
6754+
return res;
67466755
}
67476756

67486757
static PyGetSetDef object_getsets[] = {

0 commit comments

Comments
 (0)