summaryrefslogtreecommitdiffstats
path: root/Objects/object.c
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2022-08-01 13:34:54 (GMT)
committerGitHub <noreply@github.com>2022-08-01 13:34:54 (GMT)
commitde388c0a7b71c094d36ce40fecef87bdbb8a87d3 (patch)
treeb2318318e6c9a80bc9f45ecf5fc05aa66efb7825 /Objects/object.c
parentfb75d015f487e50079e8d2ea7859750684b124e4 (diff)
downloadcpython-de388c0a7b71c094d36ce40fecef87bdbb8a87d3.zip
cpython-de388c0a7b71c094d36ce40fecef87bdbb8a87d3.tar.gz
cpython-de388c0a7b71c094d36ce40fecef87bdbb8a87d3.tar.bz2
GH-95245: Store object values and dict pointers in single tagged pointer. (GH-95278)
Diffstat (limited to 'Objects/object.c')
-rw-r--r--Objects/object.c168
1 files changed, 90 insertions, 78 deletions
diff --git a/Objects/object.c b/Objects/object.c
index 758b79e..f0c0434 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1054,14 +1054,12 @@ PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
}
PyObject **
-_PyObject_DictPointer(PyObject *obj)
+_PyObject_ComputedDictPointer(PyObject *obj)
{
Py_ssize_t dictoffset;
PyTypeObject *tp = Py_TYPE(obj);
- if (tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
- return _PyObject_ManagedDictPointer(obj);
- }
+ assert((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0);
dictoffset = tp->tp_dictoffset;
if (dictoffset == 0)
return NULL;
@@ -1086,22 +1084,18 @@ PyObject **
_PyObject_GetDictPtr(PyObject *obj)
{
if ((Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
- return _PyObject_DictPointer(obj);
- }
- PyObject **dict_ptr = _PyObject_ManagedDictPointer(obj);
- PyDictValues **values_ptr = _PyObject_ValuesPointer(obj);
- if (*values_ptr == NULL) {
- return dict_ptr;
+ return _PyObject_ComputedDictPointer(obj);
}
- assert(*dict_ptr == NULL);
- PyObject *dict = _PyObject_MakeDictFromInstanceAttributes(obj, *values_ptr);
- if (dict == NULL) {
- PyErr_Clear();
- return NULL;
+ PyDictOrValues *dorv_ptr = _PyObject_DictOrValuesPointer(obj);
+ if (_PyDictOrValues_IsValues(*dorv_ptr)) {
+ PyObject *dict = _PyObject_MakeDictFromInstanceAttributes(obj, _PyDictOrValues_GetValues(*dorv_ptr));
+ if (dict == NULL) {
+ PyErr_Clear();
+ return NULL;
+ }
+ dorv_ptr->dict = dict;
}
- *values_ptr = NULL;
- *dict_ptr = dict;
- return dict_ptr;
+ return &dorv_ptr->dict;
}
PyObject *
@@ -1170,36 +1164,46 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method)
}
}
}
- PyDictValues *values;
- if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) &&
- (values = *_PyObject_ValuesPointer(obj)))
- {
- assert(*_PyObject_DictPointer(obj) == NULL);
- PyObject *attr = _PyObject_GetInstanceAttribute(obj, values, name);
- if (attr != NULL) {
- *method = attr;
- Py_XDECREF(descr);
- return 0;
- }
- }
- else {
- PyObject **dictptr = _PyObject_DictPointer(obj);
- PyObject *dict;
- if (dictptr != NULL && (dict = *dictptr) != NULL) {
- Py_INCREF(dict);
- PyObject *attr = PyDict_GetItemWithError(dict, name);
+ PyObject *dict;
+ if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) {
+ PyDictOrValues* dorv_ptr = _PyObject_DictOrValuesPointer(obj);
+ if (_PyDictOrValues_IsValues(*dorv_ptr)) {
+ PyDictValues *values = _PyDictOrValues_GetValues(*dorv_ptr);
+ PyObject *attr = _PyObject_GetInstanceAttribute(obj, values, name);
if (attr != NULL) {
- *method = Py_NewRef(attr);
- Py_DECREF(dict);
+ *method = attr;
Py_XDECREF(descr);
return 0;
}
+ dict = NULL;
+ }
+ else {
+ dict = dorv_ptr->dict;
+ }
+ }
+ else {
+ PyObject **dictptr = _PyObject_ComputedDictPointer(obj);
+ if (dictptr != NULL) {
+ dict = *dictptr;
+ }
+ else {
+ dict = NULL;
+ }
+ }
+ if (dict != NULL) {
+ Py_INCREF(dict);
+ PyObject *attr = PyDict_GetItemWithError(dict, name);
+ if (attr != NULL) {
+ *method = Py_NewRef(attr);
Py_DECREF(dict);
+ Py_XDECREF(descr);
+ return 0;
+ }
+ Py_DECREF(dict);
- if (PyErr_Occurred()) {
- Py_XDECREF(descr);
- return 0;
- }
+ if (PyErr_Occurred()) {
+ Py_XDECREF(descr);
+ return 0;
}
}
@@ -1243,7 +1247,6 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name,
PyObject *descr = NULL;
PyObject *res = NULL;
descrgetfunc f;
- PyObject **dictptr;
if (!PyUnicode_Check(name)){
PyErr_Format(PyExc_TypeError,
@@ -1274,30 +1277,31 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name,
}
}
if (dict == NULL) {
- if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) &&
- *_PyObject_ValuesPointer(obj))
- {
- PyDictValues **values_ptr = _PyObject_ValuesPointer(obj);
- if (PyUnicode_CheckExact(name)) {
- assert(*_PyObject_DictPointer(obj) == NULL);
- res = _PyObject_GetInstanceAttribute(obj, *values_ptr, name);
- if (res != NULL) {
- goto done;
+ if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) {
+ PyDictOrValues* dorv_ptr = _PyObject_DictOrValuesPointer(obj);
+ if (_PyDictOrValues_IsValues(*dorv_ptr)) {
+ PyDictValues *values = _PyDictOrValues_GetValues(*dorv_ptr);
+ if (PyUnicode_CheckExact(name)) {
+ res = _PyObject_GetInstanceAttribute(obj, values, name);
+ if (res != NULL) {
+ goto done;
+ }
+ }
+ else {
+ dict = _PyObject_MakeDictFromInstanceAttributes(obj, values);
+ if (dict == NULL) {
+ res = NULL;
+ goto done;
+ }
+ dorv_ptr->dict = dict;
}
}
else {
- dictptr = _PyObject_DictPointer(obj);
- assert(dictptr != NULL && *dictptr == NULL);
- *dictptr = dict = _PyObject_MakeDictFromInstanceAttributes(obj, *values_ptr);
- if (dict == NULL) {
- res = NULL;
- goto done;
- }
- *values_ptr = NULL;
+ dict = _PyDictOrValues_GetDict(*dorv_ptr);
}
}
else {
- dictptr = _PyObject_DictPointer(obj);
+ PyObject **dictptr = _PyObject_ComputedDictPointer(obj);
if (dictptr) {
dict = *dictptr;
}
@@ -1389,27 +1393,34 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
}
if (dict == NULL) {
- if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) && *_PyObject_ValuesPointer(obj)) {
- res = _PyObject_StoreInstanceAttribute(obj, *_PyObject_ValuesPointer(obj), name, value);
+ PyObject **dictptr;
+ if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) {
+ PyDictOrValues *dorv_ptr = _PyObject_DictOrValuesPointer(obj);
+ if (_PyDictOrValues_IsValues(*dorv_ptr)) {
+ res = _PyObject_StoreInstanceAttribute(
+ obj, _PyDictOrValues_GetValues(*dorv_ptr), name, value);
+ goto error_check;
+ }
+ dictptr = &dorv_ptr->dict;
}
else {
- PyObject **dictptr = _PyObject_DictPointer(obj);
- if (dictptr == NULL) {
- if (descr == NULL) {
- PyErr_Format(PyExc_AttributeError,
- "'%.100s' object has no attribute '%U'",
- tp->tp_name, name);
- }
- else {
- PyErr_Format(PyExc_AttributeError,
- "'%.50s' object attribute '%U' is read-only",
- tp->tp_name, name);
- }
- goto done;
+ dictptr = _PyObject_ComputedDictPointer(obj);
+ }
+ if (dictptr == NULL) {
+ if (descr == NULL) {
+ PyErr_Format(PyExc_AttributeError,
+ "'%.100s' object has no attribute '%U'",
+ tp->tp_name, name);
}
else {
- res = _PyObjectDict_SetItem(tp, dictptr, name, value);
+ PyErr_Format(PyExc_AttributeError,
+ "'%.50s' object attribute '%U' is read-only",
+ tp->tp_name, name);
}
+ goto done;
+ }
+ else {
+ res = _PyObjectDict_SetItem(tp, dictptr, name, value);
}
}
else {
@@ -1420,6 +1431,7 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
res = PyDict_SetItem(dict, name, value);
Py_DECREF(dict);
}
+ error_check:
if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) {
if (PyType_IsSubtype(tp, &PyType_Type)) {
PyErr_Format(PyExc_AttributeError,
@@ -1451,7 +1463,7 @@ PyObject_GenericSetDict(PyObject *obj, PyObject *value, void *context)
PyObject **dictptr = _PyObject_GetDictPtr(obj);
if (dictptr == NULL) {
if (_PyType_HasFeature(Py_TYPE(obj), Py_TPFLAGS_MANAGED_DICT) &&
- *_PyObject_ValuesPointer(obj) != NULL)
+ _PyDictOrValues_IsValues(*_PyObject_DictOrValuesPointer(obj)))
{
/* Was unable to convert to dict */
PyErr_NoMemory();