mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
GH-115776: Embed the values array into the object, for "normal" Python objects. (GH-116115)
This commit is contained in:
parent
c97d3af239
commit
c32dc47aca
35 changed files with 787 additions and 537 deletions
|
@ -359,11 +359,10 @@ def has_error_without_pop(op: parser.InstDef) -> bool:
|
|||
|
||||
NON_ESCAPING_FUNCTIONS = (
|
||||
"Py_INCREF",
|
||||
"_PyDictOrValues_IsValues",
|
||||
"_PyObject_DictOrValuesPointer",
|
||||
"_PyDictOrValues_GetValues",
|
||||
"_PyManagedDictPointer_IsValues",
|
||||
"_PyObject_ManagedDictPointer",
|
||||
"_PyObject_InlineValues",
|
||||
"_PyDictValues_AddToInsertionOrder",
|
||||
"_PyObject_MakeInstanceAttributesFromDict",
|
||||
"Py_DECREF",
|
||||
"_Py_DECREF_SPECIALIZED",
|
||||
"DECREF_INPUTS_AND_REUSE_FLOAT",
|
||||
|
|
|
@ -66,10 +66,12 @@ def _type_unsigned_short_ptr():
|
|||
def _type_unsigned_int_ptr():
|
||||
return gdb.lookup_type('unsigned int').pointer()
|
||||
|
||||
|
||||
def _sizeof_void_p():
|
||||
return gdb.lookup_type('void').pointer().sizeof
|
||||
|
||||
def _sizeof_pyobject():
|
||||
return gdb.lookup_type('PyObject').sizeof
|
||||
|
||||
def _managed_dict_offset():
|
||||
# See pycore_object.h
|
||||
pyobj = gdb.lookup_type("PyObject")
|
||||
|
@ -79,6 +81,7 @@ def _managed_dict_offset():
|
|||
return -3 * _sizeof_void_p()
|
||||
|
||||
|
||||
Py_TPFLAGS_INLINE_VALUES = (1 << 2)
|
||||
Py_TPFLAGS_MANAGED_DICT = (1 << 4)
|
||||
Py_TPFLAGS_HEAPTYPE = (1 << 9)
|
||||
Py_TPFLAGS_LONG_SUBCLASS = (1 << 24)
|
||||
|
@ -493,11 +496,12 @@ class HeapTypeObjectPtr(PyObjectPtr):
|
|||
has_values = int_from_int(typeobj.field('tp_flags')) & Py_TPFLAGS_MANAGED_DICT
|
||||
if not has_values:
|
||||
return None
|
||||
ptr = self._gdbval.cast(_type_char_ptr()) + _managed_dict_offset()
|
||||
char_ptr = ptr.cast(_type_char_ptr().pointer()).dereference()
|
||||
if (int(char_ptr) & 1) == 0:
|
||||
obj_ptr = self._gdbval.cast(_type_char_ptr())
|
||||
dict_ptr_ptr = obj_ptr + _managed_dict_offset()
|
||||
dict_ptr = dict_ptr_ptr.cast(_type_char_ptr().pointer()).dereference()
|
||||
if int(dict_ptr):
|
||||
return None
|
||||
char_ptr += 1
|
||||
char_ptr = obj_ptr + _sizeof_pyobject()
|
||||
values_ptr = char_ptr.cast(gdb.lookup_type("PyDictValues").pointer())
|
||||
values = values_ptr['values']
|
||||
return PyKeysValuesPair(self.get_cached_keys(), values)
|
||||
|
|
|
@ -394,7 +394,7 @@ class Stats:
|
|||
return result
|
||||
|
||||
def get_object_stats(self) -> dict[str, tuple[int, int]]:
|
||||
total_materializations = self._data.get("Object new values", 0)
|
||||
total_materializations = self._data.get("Object inline values", 0)
|
||||
total_allocations = self._data.get("Object allocations", 0) + self._data.get(
|
||||
"Object allocations from freelist", 0
|
||||
)
|
||||
|
@ -1094,8 +1094,7 @@ def object_stats_section() -> Section:
|
|||
Below, "allocations" means "allocations that are not from a freelist".
|
||||
Total allocations = "Allocations from freelist" + "Allocations".
|
||||
|
||||
"New values" is the number of values arrays created for objects with
|
||||
managed dicts.
|
||||
"Inline values" is the number of values arrays inlined into objects.
|
||||
|
||||
The cache hit/miss numbers are for the MRO cache, split into dunder and
|
||||
other names.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue