mirror of
https://github.com/python/cpython.git
synced 2025-07-16 15:55:18 +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
|
@ -1897,14 +1897,12 @@ dummy_func(
|
|||
|
||||
op(_CHECK_MANAGED_OBJECT_HAS_VALUES, (owner -- owner)) {
|
||||
assert(Py_TYPE(owner)->tp_dictoffset < 0);
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv));
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
DEOPT_IF(!_PyObject_InlineValues(owner)->valid);
|
||||
}
|
||||
|
||||
split op(_LOAD_ATTR_INSTANCE_VALUE, (index/1, owner -- attr, null if (oparg & 1))) {
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
attr = _PyDictOrValues_GetValues(dorv)->values[index];
|
||||
attr = _PyObject_InlineValues(owner)->values[index];
|
||||
DEOPT_IF(attr == NULL);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
Py_INCREF(attr);
|
||||
|
@ -1947,16 +1945,15 @@ dummy_func(
|
|||
|
||||
op(_CHECK_ATTR_WITH_HINT, (owner -- owner)) {
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(_PyDictOrValues_IsValues(dorv));
|
||||
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
DEOPT_IF(dict == NULL);
|
||||
assert(PyDict_CheckExact((PyObject *)dict));
|
||||
}
|
||||
|
||||
op(_LOAD_ATTR_WITH_HINT, (hint/1, owner -- attr, null if (oparg & 1))) {
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries);
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
|
||||
if (DK_IS_UNICODE(dict->ma_keys)) {
|
||||
|
@ -2070,16 +2067,17 @@ dummy_func(
|
|||
DISPATCH_INLINED(new_frame);
|
||||
}
|
||||
|
||||
op(_GUARD_DORV_VALUES, (owner -- owner)) {
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(!_PyDictOrValues_IsValues(dorv));
|
||||
op(_GUARD_DORV_NO_DICT, (owner -- owner)) {
|
||||
assert(Py_TYPE(owner)->tp_dictoffset < 0);
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
DEOPT_IF(_PyObject_ManagedDictPointer(owner)->dict);
|
||||
DEOPT_IF(_PyObject_InlineValues(owner)->valid == 0);
|
||||
}
|
||||
|
||||
op(_STORE_ATTR_INSTANCE_VALUE, (index/1, value, owner --)) {
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyDictValues *values = _PyDictOrValues_GetValues(dorv);
|
||||
assert(_PyObject_ManagedDictPointer(owner)->dict == NULL);
|
||||
PyDictValues *values = _PyObject_InlineValues(owner);
|
||||
PyObject *old_value = values->values[index];
|
||||
values->values[index] = value;
|
||||
if (old_value == NULL) {
|
||||
|
@ -2094,7 +2092,7 @@ dummy_func(
|
|||
macro(STORE_ATTR_INSTANCE_VALUE) =
|
||||
unused/1 +
|
||||
_GUARD_TYPE_VERSION +
|
||||
_GUARD_DORV_VALUES +
|
||||
_GUARD_DORV_NO_DICT +
|
||||
_STORE_ATTR_INSTANCE_VALUE;
|
||||
|
||||
inst(STORE_ATTR_WITH_HINT, (unused/1, type_version/2, hint/1, value, owner --)) {
|
||||
|
@ -2102,9 +2100,8 @@ dummy_func(
|
|||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version);
|
||||
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(_PyDictOrValues_IsValues(dorv));
|
||||
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
DEOPT_IF(dict == NULL);
|
||||
assert(PyDict_CheckExact((PyObject *)dict));
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
||||
|
@ -2898,9 +2895,8 @@ dummy_func(
|
|||
}
|
||||
|
||||
op(_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, (owner -- owner)) {
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv));
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
DEOPT_IF(!_PyObject_InlineValues(owner)->valid);
|
||||
}
|
||||
|
||||
op(_GUARD_KEYS_VERSION, (keys_version/2, owner -- owner)) {
|
||||
|
@ -2972,10 +2968,9 @@ dummy_func(
|
|||
unused/2 +
|
||||
_LOAD_ATTR_NONDESCRIPTOR_NO_DICT;
|
||||
|
||||
op(_CHECK_ATTR_METHOD_LAZY_DICT, (owner -- owner)) {
|
||||
Py_ssize_t dictoffset = Py_TYPE(owner)->tp_dictoffset;
|
||||
assert(dictoffset > 0);
|
||||
PyObject *dict = *(PyObject **)((char *)owner + dictoffset);
|
||||
op(_CHECK_ATTR_METHOD_LAZY_DICT, (dictoffset/1, owner -- owner)) {
|
||||
char *ptr = ((char *)owner) + MANAGED_DICT_OFFSET + dictoffset;
|
||||
PyObject *dict = *(PyObject **)ptr;
|
||||
/* This object has a __dict__, just not yet created */
|
||||
DEOPT_IF(dict != NULL);
|
||||
}
|
||||
|
@ -2993,7 +2988,7 @@ dummy_func(
|
|||
unused/1 +
|
||||
_GUARD_TYPE_VERSION +
|
||||
_CHECK_ATTR_METHOD_LAZY_DICT +
|
||||
unused/2 +
|
||||
unused/1 +
|
||||
_LOAD_ATTR_METHOD_LAZY_DICT;
|
||||
|
||||
inst(INSTRUMENTED_CALL, (unused/3 -- )) {
|
||||
|
@ -3294,6 +3289,7 @@ dummy_func(
|
|||
DEOPT_IF(!PyType_Check(callable));
|
||||
PyTypeObject *tp = (PyTypeObject *)callable;
|
||||
DEOPT_IF(tp->tp_version_tag != read_u32(cache->func_version));
|
||||
assert(tp->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
PyHeapTypeObject *cls = (PyHeapTypeObject *)callable;
|
||||
PyFunctionObject *init = (PyFunctionObject *)cls->_spec_cache.init;
|
||||
PyCodeObject *code = (PyCodeObject *)init->func_code;
|
||||
|
|
44
Python/executor_cases.c.h
generated
44
Python/executor_cases.c.h
generated
|
@ -1753,9 +1753,8 @@
|
|||
PyObject *owner;
|
||||
owner = stack_pointer[-1];
|
||||
assert(Py_TYPE(owner)->tp_dictoffset < 0);
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||
if (!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv)) JUMP_TO_JUMP_TARGET();
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
if (!_PyObject_InlineValues(owner)->valid) JUMP_TO_JUMP_TARGET();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1766,8 +1765,7 @@
|
|||
(void)null;
|
||||
owner = stack_pointer[-1];
|
||||
uint16_t index = (uint16_t)CURRENT_OPERAND();
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
attr = _PyDictOrValues_GetValues(dorv)->values[index];
|
||||
attr = _PyObject_InlineValues(owner)->values[index];
|
||||
if (attr == NULL) JUMP_TO_JUMP_TARGET();
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
Py_INCREF(attr);
|
||||
|
@ -1784,8 +1782,7 @@
|
|||
(void)null;
|
||||
owner = stack_pointer[-1];
|
||||
uint16_t index = (uint16_t)CURRENT_OPERAND();
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
attr = _PyDictOrValues_GetValues(dorv)->values[index];
|
||||
attr = _PyObject_InlineValues(owner)->values[index];
|
||||
if (attr == NULL) JUMP_TO_JUMP_TARGET();
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
Py_INCREF(attr);
|
||||
|
@ -1837,9 +1834,8 @@
|
|||
PyObject *owner;
|
||||
owner = stack_pointer[-1];
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
if (_PyDictOrValues_IsValues(dorv)) JUMP_TO_JUMP_TARGET();
|
||||
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
if (dict == NULL) JUMP_TO_JUMP_TARGET();
|
||||
assert(PyDict_CheckExact((PyObject *)dict));
|
||||
break;
|
||||
|
@ -1852,8 +1848,8 @@
|
|||
oparg = CURRENT_OPARG();
|
||||
owner = stack_pointer[-1];
|
||||
uint16_t hint = (uint16_t)CURRENT_OPERAND();
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
if (hint >= (size_t)dict->ma_keys->dk_nentries) JUMP_TO_JUMP_TARGET();
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
|
||||
if (DK_IS_UNICODE(dict->ma_keys)) {
|
||||
|
@ -1967,12 +1963,13 @@
|
|||
|
||||
/* _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */
|
||||
|
||||
case _GUARD_DORV_VALUES: {
|
||||
case _GUARD_DORV_NO_DICT: {
|
||||
PyObject *owner;
|
||||
owner = stack_pointer[-1];
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
if (!_PyDictOrValues_IsValues(dorv)) JUMP_TO_JUMP_TARGET();
|
||||
assert(Py_TYPE(owner)->tp_dictoffset < 0);
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
if (_PyObject_ManagedDictPointer(owner)->dict) JUMP_TO_JUMP_TARGET();
|
||||
if (_PyObject_InlineValues(owner)->valid == 0) JUMP_TO_JUMP_TARGET();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1982,9 +1979,9 @@
|
|||
owner = stack_pointer[-1];
|
||||
value = stack_pointer[-2];
|
||||
uint16_t index = (uint16_t)CURRENT_OPERAND();
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyDictValues *values = _PyDictOrValues_GetValues(dorv);
|
||||
assert(_PyObject_ManagedDictPointer(owner)->dict == NULL);
|
||||
PyDictValues *values = _PyObject_InlineValues(owner);
|
||||
PyObject *old_value = values->values[index];
|
||||
values->values[index] = value;
|
||||
if (old_value == NULL) {
|
||||
|
@ -2568,9 +2565,8 @@
|
|||
case _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT: {
|
||||
PyObject *owner;
|
||||
owner = stack_pointer[-1];
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||
if (!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv)) JUMP_TO_JUMP_TARGET();
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
if (!_PyObject_InlineValues(owner)->valid) JUMP_TO_JUMP_TARGET();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2658,9 +2654,9 @@
|
|||
case _CHECK_ATTR_METHOD_LAZY_DICT: {
|
||||
PyObject *owner;
|
||||
owner = stack_pointer[-1];
|
||||
Py_ssize_t dictoffset = Py_TYPE(owner)->tp_dictoffset;
|
||||
assert(dictoffset > 0);
|
||||
PyObject *dict = *(PyObject **)((char *)owner + dictoffset);
|
||||
uint16_t dictoffset = (uint16_t)CURRENT_OPERAND();
|
||||
char *ptr = ((char *)owner) + MANAGED_DICT_OFFSET + dictoffset;
|
||||
PyObject *dict = *(PyObject **)ptr;
|
||||
/* This object has a __dict__, just not yet created */
|
||||
if (dict != NULL) JUMP_TO_JUMP_TARGET();
|
||||
break;
|
||||
|
|
|
@ -2031,11 +2031,16 @@ gc_alloc(PyTypeObject *tp, size_t basicsize, size_t presize)
|
|||
return op;
|
||||
}
|
||||
|
||||
|
||||
PyObject *
|
||||
_PyObject_GC_New(PyTypeObject *tp)
|
||||
{
|
||||
size_t presize = _PyType_PreHeaderSize(tp);
|
||||
PyObject *op = gc_alloc(tp, _PyObject_SIZE(tp), presize);
|
||||
size_t size = _PyObject_SIZE(tp);
|
||||
if (_PyType_HasFeature(tp, Py_TPFLAGS_INLINE_VALUES)) {
|
||||
size += _PyInlineValuesSize(tp);
|
||||
}
|
||||
PyObject *op = gc_alloc(tp, size, presize);
|
||||
if (op == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1639,7 +1639,11 @@ PyObject *
|
|||
_PyObject_GC_New(PyTypeObject *tp)
|
||||
{
|
||||
size_t presize = _PyType_PreHeaderSize(tp);
|
||||
PyObject *op = gc_alloc(tp, _PyObject_SIZE(tp), presize);
|
||||
size_t size = _PyObject_SIZE(tp);
|
||||
if (_PyType_HasFeature(tp, Py_TPFLAGS_INLINE_VALUES)) {
|
||||
size += _PyInlineValuesSize(tp);
|
||||
}
|
||||
PyObject *op = gc_alloc(tp, size, presize);
|
||||
if (op == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
54
Python/generated_cases.c.h
generated
54
Python/generated_cases.c.h
generated
|
@ -870,6 +870,7 @@
|
|||
DEOPT_IF(!PyType_Check(callable), CALL);
|
||||
PyTypeObject *tp = (PyTypeObject *)callable;
|
||||
DEOPT_IF(tp->tp_version_tag != read_u32(cache->func_version), CALL);
|
||||
assert(tp->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
PyHeapTypeObject *cls = (PyHeapTypeObject *)callable;
|
||||
PyFunctionObject *init = (PyFunctionObject *)cls->_spec_cache.init;
|
||||
PyCodeObject *code = (PyCodeObject *)init->func_code;
|
||||
|
@ -3680,15 +3681,13 @@
|
|||
// _CHECK_MANAGED_OBJECT_HAS_VALUES
|
||||
{
|
||||
assert(Py_TYPE(owner)->tp_dictoffset < 0);
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv), LOAD_ATTR);
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
DEOPT_IF(!_PyObject_InlineValues(owner)->valid, LOAD_ATTR);
|
||||
}
|
||||
// _LOAD_ATTR_INSTANCE_VALUE
|
||||
{
|
||||
uint16_t index = read_u16(&this_instr[4].cache);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
attr = _PyDictOrValues_GetValues(dorv)->values[index];
|
||||
attr = _PyObject_InlineValues(owner)->values[index];
|
||||
DEOPT_IF(attr == NULL, LOAD_ATTR);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
Py_INCREF(attr);
|
||||
|
@ -3721,13 +3720,13 @@
|
|||
}
|
||||
// _CHECK_ATTR_METHOD_LAZY_DICT
|
||||
{
|
||||
Py_ssize_t dictoffset = Py_TYPE(owner)->tp_dictoffset;
|
||||
assert(dictoffset > 0);
|
||||
PyObject *dict = *(PyObject **)((char *)owner + dictoffset);
|
||||
uint16_t dictoffset = read_u16(&this_instr[4].cache);
|
||||
char *ptr = ((char *)owner) + MANAGED_DICT_OFFSET + dictoffset;
|
||||
PyObject *dict = *(PyObject **)ptr;
|
||||
/* This object has a __dict__, just not yet created */
|
||||
DEOPT_IF(dict != NULL, LOAD_ATTR);
|
||||
}
|
||||
/* Skip 2 cache entries */
|
||||
/* Skip 1 cache entry */
|
||||
// _LOAD_ATTR_METHOD_LAZY_DICT
|
||||
{
|
||||
PyObject *descr = read_obj(&this_instr[6].cache);
|
||||
|
@ -3798,9 +3797,8 @@
|
|||
}
|
||||
// _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT
|
||||
{
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv), LOAD_ATTR);
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
DEOPT_IF(!_PyObject_InlineValues(owner)->valid, LOAD_ATTR);
|
||||
}
|
||||
// _GUARD_KEYS_VERSION
|
||||
{
|
||||
|
@ -3914,9 +3912,8 @@
|
|||
}
|
||||
// _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT
|
||||
{
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv), LOAD_ATTR);
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
DEOPT_IF(!_PyObject_InlineValues(owner)->valid, LOAD_ATTR);
|
||||
}
|
||||
// _GUARD_KEYS_VERSION
|
||||
{
|
||||
|
@ -4026,17 +4023,16 @@
|
|||
// _CHECK_ATTR_WITH_HINT
|
||||
{
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(_PyDictOrValues_IsValues(dorv), LOAD_ATTR);
|
||||
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
DEOPT_IF(dict == NULL, LOAD_ATTR);
|
||||
assert(PyDict_CheckExact((PyObject *)dict));
|
||||
}
|
||||
// _LOAD_ATTR_WITH_HINT
|
||||
{
|
||||
uint16_t hint = read_u16(&this_instr[4].cache);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR);
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
|
||||
if (DK_IS_UNICODE(dict->ma_keys)) {
|
||||
|
@ -5315,19 +5311,20 @@
|
|||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
|
||||
}
|
||||
// _GUARD_DORV_VALUES
|
||||
// _GUARD_DORV_NO_DICT
|
||||
{
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(!_PyDictOrValues_IsValues(dorv), STORE_ATTR);
|
||||
assert(Py_TYPE(owner)->tp_dictoffset < 0);
|
||||
assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
|
||||
DEOPT_IF(_PyObject_ManagedDictPointer(owner)->dict, STORE_ATTR);
|
||||
DEOPT_IF(_PyObject_InlineValues(owner)->valid == 0, STORE_ATTR);
|
||||
}
|
||||
// _STORE_ATTR_INSTANCE_VALUE
|
||||
value = stack_pointer[-2];
|
||||
{
|
||||
uint16_t index = read_u16(&this_instr[4].cache);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyDictValues *values = _PyDictOrValues_GetValues(dorv);
|
||||
assert(_PyObject_ManagedDictPointer(owner)->dict == NULL);
|
||||
PyDictValues *values = _PyObject_InlineValues(owner);
|
||||
PyObject *old_value = values->values[index];
|
||||
values->values[index] = value;
|
||||
if (old_value == NULL) {
|
||||
|
@ -5389,9 +5386,8 @@
|
|||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
|
||||
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(_PyDictOrValues_IsValues(dorv), STORE_ATTR);
|
||||
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
DEOPT_IF(dict == NULL, STORE_ATTR);
|
||||
assert(PyDict_CheckExact((PyObject *)dict));
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
||||
|
|
2
Python/optimizer_cases.c.h
generated
2
Python/optimizer_cases.c.h
generated
|
@ -1104,7 +1104,7 @@
|
|||
|
||||
/* _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN is not a viable micro-op for tier 2 */
|
||||
|
||||
case _GUARD_DORV_VALUES: {
|
||||
case _GUARD_DORV_NO_DICT: {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ print_object_stats(FILE *out, ObjectStats *stats)
|
|||
fprintf(out, "Object allocations to 4 kbytes: %" PRIu64 "\n", stats->allocations4k);
|
||||
fprintf(out, "Object allocations over 4 kbytes: %" PRIu64 "\n", stats->allocations_big);
|
||||
fprintf(out, "Object frees: %" PRIu64 "\n", stats->frees);
|
||||
fprintf(out, "Object new values: %" PRIu64 "\n", stats->new_values);
|
||||
fprintf(out, "Object inline values: %" PRIu64 "\n", stats->inline_values);
|
||||
fprintf(out, "Object interpreter increfs: %" PRIu64 "\n", stats->interpreter_increfs);
|
||||
fprintf(out, "Object interpreter decrefs: %" PRIu64 "\n", stats->interpreter_decrefs);
|
||||
fprintf(out, "Object increfs: %" PRIu64 "\n", stats->increfs);
|
||||
|
@ -197,7 +197,6 @@ print_object_stats(FILE *out, ObjectStats *stats)
|
|||
fprintf(out, "Object materialize dict (new key): %" PRIu64 "\n", stats->dict_materialized_new_key);
|
||||
fprintf(out, "Object materialize dict (too big): %" PRIu64 "\n", stats->dict_materialized_too_big);
|
||||
fprintf(out, "Object materialize dict (str subclass): %" PRIu64 "\n", stats->dict_materialized_str_subclass);
|
||||
fprintf(out, "Object dematerialize dict: %" PRIu64 "\n", stats->dict_dematerialized);
|
||||
fprintf(out, "Object method cache hits: %" PRIu64 "\n", stats->type_cache_hits);
|
||||
fprintf(out, "Object method cache misses: %" PRIu64 "\n", stats->type_cache_misses);
|
||||
fprintf(out, "Object method cache collisions: %" PRIu64 "\n", stats->type_cache_collisions);
|
||||
|
@ -479,12 +478,11 @@ _PyCode_Quicken(PyCodeObject *code)
|
|||
#define SPEC_FAIL_ATTR_NOT_MANAGED_DICT 18
|
||||
#define SPEC_FAIL_ATTR_NON_STRING_OR_SPLIT 19
|
||||
#define SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND 20
|
||||
|
||||
#define SPEC_FAIL_ATTR_SHADOWED 21
|
||||
#define SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD 22
|
||||
#define SPEC_FAIL_ATTR_CLASS_METHOD_OBJ 23
|
||||
#define SPEC_FAIL_ATTR_OBJECT_SLOT 24
|
||||
#define SPEC_FAIL_ATTR_HAS_MANAGED_DICT 25
|
||||
|
||||
#define SPEC_FAIL_ATTR_INSTANCE_ATTRIBUTE 26
|
||||
#define SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE 27
|
||||
#define SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION 28
|
||||
|
@ -558,6 +556,7 @@ _PyCode_Quicken(PyCodeObject *code)
|
|||
#define SPEC_FAIL_CALL_OPERATOR_WRAPPER 29
|
||||
#define SPEC_FAIL_CALL_INIT_NOT_SIMPLE 30
|
||||
#define SPEC_FAIL_CALL_METACLASS 31
|
||||
#define SPEC_FAIL_CALL_INIT_NOT_INLINE_VALUES 32
|
||||
|
||||
/* COMPARE_OP */
|
||||
#define SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES 12
|
||||
|
@ -829,11 +828,7 @@ specialize_dict_access(
|
|||
return 0;
|
||||
}
|
||||
_PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
|
||||
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||
if (_PyDictOrValues_IsValues(*dorv) ||
|
||||
_PyObject_MakeInstanceAttributesFromDict(owner, dorv))
|
||||
{
|
||||
// Virtual dictionary
|
||||
if (type->tp_flags & Py_TPFLAGS_INLINE_VALUES && _PyObject_InlineValues(owner)->valid) {
|
||||
PyDictKeysObject *keys = ((PyHeapTypeObject *)type)->ht_cached_keys;
|
||||
assert(PyUnicode_CheckExact(name));
|
||||
Py_ssize_t index = _PyDictKeys_StringLookup(keys, name);
|
||||
|
@ -850,7 +845,8 @@ specialize_dict_access(
|
|||
instr->op.code = values_op;
|
||||
}
|
||||
else {
|
||||
PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(*dorv);
|
||||
PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner);
|
||||
PyDictObject *dict = managed_dict->dict;
|
||||
if (dict == NULL || !PyDict_CheckExact(dict)) {
|
||||
SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NO_DICT);
|
||||
return 0;
|
||||
|
@ -1258,15 +1254,8 @@ PyObject *descr, DescriptorClassification kind, bool is_method)
|
|||
|
||||
assert(descr != NULL);
|
||||
assert((is_method && kind == METHOD) || (!is_method && kind == NON_DESCRIPTOR));
|
||||
if (owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
|
||||
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||
if (owner_cls->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
|
||||
PyDictKeysObject *keys = ((PyHeapTypeObject *)owner_cls)->ht_cached_keys;
|
||||
if (!_PyDictOrValues_IsValues(*dorv) &&
|
||||
!_PyObject_MakeInstanceAttributesFromDict(owner, dorv))
|
||||
{
|
||||
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_HAS_MANAGED_DICT);
|
||||
return 0;
|
||||
}
|
||||
Py_ssize_t index = _PyDictKeys_StringLookup(keys, name);
|
||||
if (index != DKIX_EMPTY) {
|
||||
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_SHADOWED);
|
||||
|
@ -1282,10 +1271,16 @@ PyObject *descr, DescriptorClassification kind, bool is_method)
|
|||
instr->op.code = is_method ? LOAD_ATTR_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES;
|
||||
}
|
||||
else {
|
||||
Py_ssize_t dictoffset = owner_cls->tp_dictoffset;
|
||||
if (dictoffset < 0 || dictoffset > INT16_MAX) {
|
||||
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
|
||||
return 0;
|
||||
Py_ssize_t dictoffset;
|
||||
if (owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
|
||||
dictoffset = MANAGED_DICT_OFFSET;
|
||||
}
|
||||
else {
|
||||
dictoffset = owner_cls->tp_dictoffset;
|
||||
if (dictoffset < 0 || dictoffset > INT16_MAX + MANAGED_DICT_OFFSET) {
|
||||
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (dictoffset == 0) {
|
||||
instr->op.code = is_method ? LOAD_ATTR_METHOD_NO_DICT : LOAD_ATTR_NONDESCRIPTOR_NO_DICT;
|
||||
|
@ -1296,8 +1291,12 @@ PyObject *descr, DescriptorClassification kind, bool is_method)
|
|||
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
|
||||
return 0;
|
||||
}
|
||||
assert(owner_cls->tp_dictoffset > 0);
|
||||
assert(owner_cls->tp_dictoffset <= INT16_MAX);
|
||||
/* Cache entries must be unsigned values, so we offset the
|
||||
* dictoffset by MANAGED_DICT_OFFSET.
|
||||
* We do the reverese offset in LOAD_ATTR_METHOD_LAZY_DICT */
|
||||
dictoffset -= MANAGED_DICT_OFFSET;
|
||||
assert(((uint16_t)dictoffset) == dictoffset);
|
||||
cache->dict_offset = (uint16_t)dictoffset;
|
||||
instr->op.code = LOAD_ATTR_METHOD_LAZY_DICT;
|
||||
}
|
||||
else {
|
||||
|
@ -1729,8 +1728,8 @@ get_init_for_simple_managed_python_class(PyTypeObject *tp)
|
|||
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OVERRIDDEN);
|
||||
return NULL;
|
||||
}
|
||||
if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
|
||||
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_NO_DICT);
|
||||
if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) == 0) {
|
||||
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_INIT_NOT_INLINE_VALUES);
|
||||
return NULL;
|
||||
}
|
||||
if (!(tp->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue