mirror of https://github.com/python/cpython
bpo-44821: Eagerly assign __dict__ for new objects. (GH-27589)
This commit is contained in:
parent
c83919bd63
commit
cee67fa661
|
@ -180,6 +180,8 @@ extern int _Py_CheckSlotResult(
|
||||||
|
|
||||||
extern PyObject* _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems);
|
extern PyObject* _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems);
|
||||||
|
|
||||||
|
extern int _PyObject_InitializeDict(PyObject *obj);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -323,9 +323,13 @@ class CAPITest(unittest.TestCase):
|
||||||
break
|
break
|
||||||
"""
|
"""
|
||||||
rc, out, err = assert_python_ok('-c', code)
|
rc, out, err = assert_python_ok('-c', code)
|
||||||
self.assertIn(b'MemoryError 1', out)
|
lines = out.splitlines()
|
||||||
self.assertIn(b'MemoryError 2 20', out)
|
for i, line in enumerate(lines, 1):
|
||||||
self.assertIn(b'MemoryError 3 30', out)
|
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):
|
def test_mapping_keys_values_items(self):
|
||||||
class Mapping1(dict):
|
class Mapping1(dict):
|
||||||
|
|
|
@ -566,7 +566,7 @@ id(foo)''')
|
||||||
# http://bugs.python.org/issue8032#msg100537 )
|
# http://bugs.python.org/issue8032#msg100537 )
|
||||||
gdb_repr, gdb_output = self.get_gdb_repr('id(__builtins__.help)', import_site=True)
|
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,
|
self.assertTrue(m,
|
||||||
msg='Unexpected rendering %r' % gdb_repr)
|
msg='Unexpected rendering %r' % gdb_repr)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Create instance dictionaries (__dict__) eagerly, to improve regularity of
|
||||||
|
object layout and assist specialization.
|
|
@ -4866,19 +4866,44 @@ _PyDict_NewKeysForClass(void)
|
||||||
|
|
||||||
#define CACHED_KEYS(tp) (((PyHeapTypeObject*)tp)->ht_cached_keys)
|
#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 *
|
||||||
PyObject_GenericGetDict(PyObject *obj, void *context)
|
PyObject_GenericGetDict(PyObject *obj, void *context)
|
||||||
{
|
{
|
||||||
PyObject *dict, **dictptr = _PyObject_GetDictPtr(obj);
|
PyObject **dictptr = _PyObject_GetDictPtr(obj);
|
||||||
if (dictptr == NULL) {
|
if (dictptr == NULL) {
|
||||||
PyErr_SetString(PyExc_AttributeError,
|
PyErr_SetString(PyExc_AttributeError,
|
||||||
"This object has no __dict__");
|
"This object has no __dict__");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
dict = *dictptr;
|
PyObject *dict = *dictptr;
|
||||||
if (dict == NULL) {
|
if (dict == NULL) {
|
||||||
PyTypeObject *tp = Py_TYPE(obj);
|
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));
|
dictkeys_incref(CACHED_KEYS(tp));
|
||||||
*dictptr = dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
|
*dictptr = dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4505,7 +4505,15 @@ object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
Py_DECREF(joined);
|
Py_DECREF(joined);
|
||||||
return NULL;
|
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
|
static void
|
||||||
|
|
Loading…
Reference in New Issue