summaryrefslogtreecommitdiffstats
path: root/Tools
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2024-04-02 10:59:21 (GMT)
committerGitHub <noreply@github.com>2024-04-02 10:59:21 (GMT)
commitc32dc47aca6e8fac152699bc613e015c44ccdba9 (patch)
treee183f7c56ad5e081879c3dd75f7e11887fe7e26c /Tools
parentc97d3af2391e62ef456ef2365d48ab9b8cdbe27b (diff)
downloadcpython-c32dc47aca6e8fac152699bc613e015c44ccdba9.zip
cpython-c32dc47aca6e8fac152699bc613e015c44ccdba9.tar.gz
cpython-c32dc47aca6e8fac152699bc613e015c44ccdba9.tar.bz2
GH-115776: Embed the values array into the object, for "normal" Python objects. (GH-116115)
Diffstat (limited to 'Tools')
-rw-r--r--Tools/cases_generator/analyzer.py7
-rwxr-xr-xTools/gdb/libpython.py14
-rw-r--r--Tools/scripts/summarize_stats.py5
3 files changed, 14 insertions, 12 deletions
diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py
index ddafcf9..4261378 100644
--- a/Tools/cases_generator/analyzer.py
+++ b/Tools/cases_generator/analyzer.py
@@ -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",
diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py
index 656667a..74165ac 100755
--- a/Tools/gdb/libpython.py
+++ b/Tools/gdb/libpython.py
@@ -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)
diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py
index 8dc590b..f7ed98f 100644
--- a/Tools/scripts/summarize_stats.py
+++ b/Tools/scripts/summarize_stats.py
@@ -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.