GH-95245: Store object values and dict pointers in single tagged pointer. (GH-95278)

This commit is contained in:
Mark Shannon 2022-08-01 14:34:54 +01:00 committed by GitHub
parent fb75d015f4
commit de388c0a7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 271 additions and 203 deletions

View file

@ -1310,15 +1310,13 @@ subtype_traverse(PyObject *self, visitproc visit, void *arg)
}
if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
assert(type->tp_dictoffset);
int err = _PyObject_VisitInstanceAttributes(self, visit, arg);
int err = _PyObject_VisitManagedDict(self, visit, arg);
if (err) {
return err;
}
}
if (type->tp_dictoffset != base->tp_dictoffset) {
PyObject **dictptr = _PyObject_DictPointer(self);
else if (type->tp_dictoffset != base->tp_dictoffset) {
PyObject **dictptr = _PyObject_ComputedDictPointer(self);
if (dictptr && *dictptr)
Py_VISIT(*dictptr);
}
@ -1379,10 +1377,10 @@ subtype_clear(PyObject *self)
/* Clear the instance dict (if any), to break cycles involving only
__dict__ slots (as in the case 'self.__dict__ is self'). */
if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
_PyObject_ClearInstanceAttributes(self);
_PyObject_ClearManagedDict(self);
}
if (type->tp_dictoffset != base->tp_dictoffset) {
PyObject **dictptr = _PyObject_DictPointer(self);
else if (type->tp_dictoffset != base->tp_dictoffset) {
PyObject **dictptr = _PyObject_ComputedDictPointer(self);
if (dictptr && *dictptr)
Py_CLEAR(*dictptr);
}
@ -1526,18 +1524,17 @@ subtype_dealloc(PyObject *self)
/* If we added a dict, DECREF it, or free inline values. */
if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
PyObject **dictptr = _PyObject_ManagedDictPointer(self);
if (*dictptr != NULL) {
assert(*_PyObject_ValuesPointer(self) == NULL);
Py_DECREF(*dictptr);
*dictptr = NULL;
}
else {
PyDictOrValues *dorv_ptr = _PyObject_DictOrValuesPointer(self);
if (_PyDictOrValues_IsValues(*dorv_ptr)) {
_PyObject_FreeInstanceAttributes(self);
}
else {
Py_XDECREF(_PyDictOrValues_GetDict(*dorv_ptr));
}
dorv_ptr->values = NULL;
}
else if (type->tp_dictoffset && !base->tp_dictoffset) {
PyObject **dictptr = _PyObject_DictPointer(self);
PyObject **dictptr = _PyObject_ComputedDictPointer(self);
if (dictptr != NULL) {
PyObject *dict = *dictptr;
if (dict != NULL) {
@ -5137,7 +5134,9 @@ object_set_class(PyObject *self, PyObject *value, void *closure)
* so we must materialize the dictionary first. */
assert((oldto->tp_flags & Py_TPFLAGS_MANAGED_DICT) == (newto->tp_flags & Py_TPFLAGS_MANAGED_DICT));
_PyObject_GetDictPtr(self);
if (oldto->tp_flags & Py_TPFLAGS_MANAGED_DICT && *_PyObject_ValuesPointer(self)) {
if (oldto->tp_flags & Py_TPFLAGS_MANAGED_DICT &&
_PyDictOrValues_IsValues(*_PyObject_DictOrValuesPointer(self)))
{
/* Was unable to convert to dict */
PyErr_NoMemory();
return -1;