GH-95245: Store object values and dict pointers in single tagged poin… · python/cpython@de388c0 · GitHub
Skip to content

Commit de388c0

Browse files
authored
GH-95245: Store object values and dict pointers in single tagged pointer. (GH-95278)
1 parent fb75d01 commit de388c0

10 files changed

Lines changed: 269 additions & 201 deletions

File tree

Include/cpython/dictobject.h

Lines changed: 0 additions & 3 deletions

Include/cpython/object.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,3 +510,7 @@ Py_DEPRECATED(3.11) typedef int UsingDeprecatedTrashcanMacro;
510510
#define Py_TRASHCAN_SAFE_END(op) \
511511
Py_TRASHCAN_END; \
512512
} while(0);
513+
514+
515+
PyAPI_FUNC(int) _PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg);
516+
PyAPI_FUNC(void) _PyObject_ClearManagedDict(PyObject *obj);

Include/internal/pycore_object.h

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -274,24 +274,49 @@ extern int _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
274274
PyObject * _PyObject_GetInstanceAttribute(PyObject *obj, PyDictValues *values,
275275
PyObject *name);
276276

277-
static inline PyDictValues **_PyObject_ValuesPointer(PyObject *obj)
277+
typedef union {
278+
PyObject *dict;
279+
/* Use a char* to generate a warning if directly assigning a PyDictValues */
280+
char *values;
281+
} PyDictOrValues;
282+
283+
static inline PyDictOrValues *
284+
_PyObject_DictOrValuesPointer(PyObject *obj)
278285
{
279286
assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
280-
return ((PyDictValues **)obj)-4;
287+
return ((PyDictOrValues *)obj)-3;
281288
}
282289

283-
static inline PyObject **_PyObject_ManagedDictPointer(PyObject *obj)
290+
static inline int
291+
_PyDictOrValues_IsValues(PyDictOrValues dorv)
284292
{
285-
assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
286-
return ((PyObject **)obj)-3;
293+
return ((uintptr_t)dorv.values) & 1;
294+
}
295+
296+
static inline PyDictValues *
297+
_PyDictOrValues_GetValues(PyDictOrValues dorv)
298+
{
299+
assert(_PyDictOrValues_IsValues(dorv));
300+
return (PyDictValues *)(dorv.values + 1);
301+
}
302+
303+
static inline PyObject *
304+
_PyDictOrValues_GetDict(PyDictOrValues dorv)
305+
{
306+
assert(!_PyDictOrValues_IsValues(dorv));
307+
return dorv.dict;
308+
}
309+
310+
static inline void
311+
_PyDictOrValues_SetValues(PyDictOrValues *ptr, PyDictValues *values)
312+
{
313+
ptr->values = ((char *)values) - 1;
287314
}
288315

289316
#define MANAGED_DICT_OFFSET (((int)sizeof(PyObject *))*-3)
290317

291-
extern PyObject ** _PyObject_DictPointer(PyObject *);
292-
extern int _PyObject_VisitInstanceAttributes(PyObject *self, visitproc visit, void *arg);
293-
extern void _PyObject_ClearInstanceAttributes(PyObject *self);
294-
extern void _PyObject_FreeInstanceAttributes(PyObject *self);
318+
extern PyObject ** _PyObject_ComputedDictPointer(PyObject *);
319+
extern void _PyObject_FreeInstanceAttributes(PyObject *obj);
295320
extern int _PyObject_IsInstanceDictEmpty(PyObject *);
296321
extern PyObject* _PyType_GetSubclasses(PyTypeObject *);
297322

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Merge managed dict and values pointer into a single tagged pointer to save
2+
one word in the pre-header.

Objects/dictobject.c

Lines changed: 90 additions & 71 deletions

0 commit comments

Comments
 (0)