summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/internal/pycore_object.h2
-rw-r--r--Lib/test/test_capi.py10
-rw-r--r--Lib/test/test_gdb.py2
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2021-08-04-11-37-38.bpo-44821.67YHGI.rst2
-rw-r--r--Objects/dictobject.c31
-rw-r--r--Objects/typeobject.c10
6 files changed, 49 insertions, 8 deletions
diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h
index 4091f51..744b41a 100644
--- a/Include/internal/pycore_object.h
+++ b/Include/internal/pycore_object.h
@@ -180,6 +180,8 @@ extern int _Py_CheckSlotResult(
extern PyObject* _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems);
+extern int _PyObject_InitializeDict(PyObject *obj);
+
#ifdef __cplusplus
}
#endif
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
index 169e7ac..9165f45 100644
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -323,9 +323,13 @@ class CAPITest(unittest.TestCase):
break
"""
rc, out, err = assert_python_ok('-c', code)
- self.assertIn(b'MemoryError 1', out)
- self.assertIn(b'MemoryError 2 20', out)
- self.assertIn(b'MemoryError 3 30', out)
+ lines = out.splitlines()
+ for i, line in enumerate(lines, 1):
+ self.assertIn(b'MemoryError', out)
+ *_, count = line.split(b' ')
+ count = int(count)
+ self.assertLessEqual(count, i*5)
+ self.assertGreaterEqual(count, i*5-1)
def test_mapping_keys_values_items(self):
class Mapping1(dict):
diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py
index 7bdef25..98b36d6 100644
--- a/Lib/test/test_gdb.py
+++ b/Lib/test/test_gdb.py
@@ -566,7 +566,7 @@ id(foo)''')
# http://bugs.python.org/issue8032#msg100537 )
gdb_repr, gdb_output = self.get_gdb_repr('id(__builtins__.help)', import_site=True)
- m = re.match(r'<_Helper at remote 0x-?[0-9a-f]+>', gdb_repr)
+ m = re.match(r'<_Helper\(\) at remote 0x-?[0-9a-f]+>', gdb_repr)
self.assertTrue(m,
msg='Unexpected rendering %r' % gdb_repr)
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-08-04-11-37-38.bpo-44821.67YHGI.rst b/Misc/NEWS.d/next/Core and Builtins/2021-08-04-11-37-38.bpo-44821.67YHGI.rst
new file mode 100644
index 0000000..1e254a6
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2021-08-04-11-37-38.bpo-44821.67YHGI.rst
@@ -0,0 +1,2 @@
+Create instance dictionaries (__dict__) eagerly, to improve regularity of
+object layout and assist specialization.
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 5fb9d01..5ad630f 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -4866,19 +4866,44 @@ _PyDict_NewKeysForClass(void)
#define CACHED_KEYS(tp) (((PyHeapTypeObject*)tp)->ht_cached_keys)
+int
+_PyObject_InitializeDict(PyObject *obj)
+{
+ PyObject **dictptr = _PyObject_GetDictPtr(obj);
+ if (dictptr == NULL) {
+ return 0;
+ }
+ assert(*dictptr == NULL);
+ PyTypeObject *tp = Py_TYPE(obj);
+ PyObject *dict;
+ if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
+ dictkeys_incref(CACHED_KEYS(tp));
+ dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
+ }
+ else {
+ dict = PyDict_New();
+ }
+ if (dict == NULL) {
+ return -1;
+ }
+ *dictptr = dict;
+ return 0;
+}
+
+
PyObject *
PyObject_GenericGetDict(PyObject *obj, void *context)
{
- PyObject *dict, **dictptr = _PyObject_GetDictPtr(obj);
+ PyObject **dictptr = _PyObject_GetDictPtr(obj);
if (dictptr == NULL) {
PyErr_SetString(PyExc_AttributeError,
"This object has no __dict__");
return NULL;
}
- dict = *dictptr;
+ PyObject *dict = *dictptr;
if (dict == NULL) {
PyTypeObject *tp = Py_TYPE(obj);
- if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
+ if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
dictkeys_incref(CACHED_KEYS(tp));
*dictptr = dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
}
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 2240f78..7ae50c4 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -4505,7 +4505,15 @@ object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Py_DECREF(joined);
return NULL;
}
- return type->tp_alloc(type, 0);
+ PyObject *obj = type->tp_alloc(type, 0);
+ if (obj == NULL) {
+ return NULL;
+ }
+ if (_PyObject_InitializeDict(obj)) {
+ Py_DECREF(obj);
+ return NULL;
+ }
+ return obj;
}
static void