mirror of
https://github.com/python/cpython.git
synced 2025-08-30 21:48:47 +00:00
gh-104909: Split some more insts into ops (#109943)
These are the most popular specializations of `LOAD_ATTR` and `STORE_ATTR` that weren't already viable uops: * Split LOAD_ATTR_METHOD_WITH_VALUES * Split LOAD_ATTR_METHOD_NO_DICT * Split LOAD_ATTR_SLOT * Split STORE_ATTR_SLOT * Split STORE_ATTR_INSTANCE_VALUE Also: * Add `-v` flag to code generator which prints a list of non-viable uops (easter-egg: it can print execution counts -- see source) * Double _Py_UOP_MAX_TRACE_LENGTH to 128 I had dropped one of the DEOPT_IF() calls! :-(
This commit is contained in:
parent
45cf5b0c69
commit
5bb6f0fcba
8 changed files with 519 additions and 115 deletions
47
Python/abstract_interp_cases.c.h
generated
47
Python/abstract_interp_cases.c.h
generated
|
@ -474,6 +474,31 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _LOAD_ATTR_SLOT: {
|
||||
STACK_GROW(((oparg & 1) ? 1 : 0));
|
||||
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1 - (oparg & 1 ? 1 : 0))), true);
|
||||
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-(oparg & 1 ? 1 : 0))), true);
|
||||
break;
|
||||
}
|
||||
|
||||
case _GUARD_DORV_VALUES: {
|
||||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_INSTANCE_VALUE: {
|
||||
STACK_SHRINK(2);
|
||||
break;
|
||||
}
|
||||
|
||||
case _GUARD_TYPE_VERSION_STORE: {
|
||||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_SLOT: {
|
||||
STACK_SHRINK(2);
|
||||
break;
|
||||
}
|
||||
|
||||
case COMPARE_OP: {
|
||||
STACK_SHRINK(1);
|
||||
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
|
||||
|
@ -627,6 +652,28 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT: {
|
||||
break;
|
||||
}
|
||||
|
||||
case _GUARD_KEYS_VERSION: {
|
||||
break;
|
||||
}
|
||||
|
||||
case _LOAD_ATTR_METHOD_WITH_VALUES: {
|
||||
STACK_GROW(1);
|
||||
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-2)), true);
|
||||
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
|
||||
break;
|
||||
}
|
||||
|
||||
case _LOAD_ATTR_METHOD_NO_DICT: {
|
||||
STACK_GROW(1);
|
||||
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-2)), true);
|
||||
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
|
||||
break;
|
||||
}
|
||||
|
||||
case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1939,10 +1939,7 @@ dummy_func(
|
|||
DECREF_INPUTS();
|
||||
}
|
||||
|
||||
inst(LOAD_ATTR_SLOT, (unused/1, type_version/2, index/1, unused/5, owner -- attr, null if (oparg & 1))) {
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
|
||||
op(_LOAD_ATTR_SLOT, (index/1, owner -- attr, null if (oparg & 1))) {
|
||||
char *addr = (char *)owner + index;
|
||||
attr = *(PyObject **)addr;
|
||||
DEOPT_IF(attr == NULL, LOAD_ATTR);
|
||||
|
@ -1952,6 +1949,12 @@ dummy_func(
|
|||
DECREF_INPUTS();
|
||||
}
|
||||
|
||||
macro(LOAD_ATTR_SLOT) =
|
||||
unused/1 +
|
||||
_GUARD_TYPE_VERSION +
|
||||
_LOAD_ATTR_SLOT + // NOTE: This action may also deopt
|
||||
unused/5;
|
||||
|
||||
inst(LOAD_ATTR_CLASS, (unused/1, type_version/2, unused/2, descr/4, owner -- attr, null if (oparg & 1))) {
|
||||
|
||||
DEOPT_IF(!PyType_Check(owner), LOAD_ATTR);
|
||||
|
@ -2019,13 +2022,15 @@ dummy_func(
|
|||
DISPATCH_INLINED(new_frame);
|
||||
}
|
||||
|
||||
inst(STORE_ATTR_INSTANCE_VALUE, (unused/1, type_version/2, index/1, value, owner --)) {
|
||||
op(_GUARD_DORV_VALUES, (owner -- owner)) {
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
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);
|
||||
}
|
||||
|
||||
op(_STORE_ATTR_INSTANCE_VALUE, (index/1, value, owner --)) {
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyDictValues *values = _PyDictOrValues_GetValues(dorv);
|
||||
PyObject *old_value = values->values[index];
|
||||
|
@ -2039,6 +2044,12 @@ dummy_func(
|
|||
Py_DECREF(owner);
|
||||
}
|
||||
|
||||
macro(STORE_ATTR_INSTANCE_VALUE) =
|
||||
unused/1 +
|
||||
_GUARD_TYPE_VERSION_STORE +
|
||||
_GUARD_DORV_VALUES +
|
||||
_STORE_ATTR_INSTANCE_VALUE;
|
||||
|
||||
inst(STORE_ATTR_WITH_HINT, (unused/1, type_version/2, hint/1, value, owner --)) {
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
assert(type_version != 0);
|
||||
|
@ -2080,10 +2091,13 @@ dummy_func(
|
|||
Py_DECREF(owner);
|
||||
}
|
||||
|
||||
inst(STORE_ATTR_SLOT, (unused/1, type_version/2, index/1, value, owner --)) {
|
||||
op(_GUARD_TYPE_VERSION_STORE, (type_version/2, owner -- owner)) {
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
|
||||
}
|
||||
|
||||
op(_STORE_ATTR_SLOT, (index/1, value, owner --)) {
|
||||
char *addr = (char *)owner + index;
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyObject *old_value = *(PyObject **)addr;
|
||||
|
@ -2092,6 +2106,11 @@ dummy_func(
|
|||
Py_DECREF(owner);
|
||||
}
|
||||
|
||||
macro(STORE_ATTR_SLOT) =
|
||||
unused/1 +
|
||||
_GUARD_TYPE_VERSION_STORE +
|
||||
_STORE_ATTR_SLOT;
|
||||
|
||||
family(COMPARE_OP, INLINE_CACHE_ENTRIES_COMPARE_OP) = {
|
||||
COMPARE_OP_FLOAT,
|
||||
COMPARE_OP_INT,
|
||||
|
@ -2769,20 +2788,25 @@ dummy_func(
|
|||
exc_info->exc_value = Py_NewRef(new_exc);
|
||||
}
|
||||
|
||||
inst(LOAD_ATTR_METHOD_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, owner -- attr, self if (1))) {
|
||||
assert(oparg & 1);
|
||||
/* Cached method object */
|
||||
op(_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, (owner -- owner)) {
|
||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(owner_cls->tp_version_tag != type_version, LOAD_ATTR);
|
||||
assert(owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) &&
|
||||
!_PyObject_MakeInstanceAttributesFromDict(owner, dorv),
|
||||
LOAD_ATTR);
|
||||
}
|
||||
|
||||
op(_GUARD_KEYS_VERSION, (keys_version/2, owner -- owner)) {
|
||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
|
||||
DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version !=
|
||||
keys_version, LOAD_ATTR);
|
||||
}
|
||||
|
||||
op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self if (1))) {
|
||||
assert(oparg & 1);
|
||||
/* Cached method object */
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
assert(descr != NULL);
|
||||
attr = Py_NewRef(descr);
|
||||
|
@ -2790,10 +2814,16 @@ dummy_func(
|
|||
self = owner;
|
||||
}
|
||||
|
||||
inst(LOAD_ATTR_METHOD_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, owner -- attr, self if (1))) {
|
||||
macro(LOAD_ATTR_METHOD_WITH_VALUES) =
|
||||
unused/1 +
|
||||
_GUARD_TYPE_VERSION +
|
||||
_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT +
|
||||
_GUARD_KEYS_VERSION +
|
||||
_LOAD_ATTR_METHOD_WITH_VALUES;
|
||||
|
||||
op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self if (1))) {
|
||||
assert(oparg & 1);
|
||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||
DEOPT_IF(owner_cls->tp_version_tag != type_version, LOAD_ATTR);
|
||||
assert(owner_cls->tp_dictoffset == 0);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
assert(descr != NULL);
|
||||
|
@ -2802,6 +2832,12 @@ dummy_func(
|
|||
self = owner;
|
||||
}
|
||||
|
||||
macro(LOAD_ATTR_METHOD_NO_DICT) =
|
||||
unused/1 +
|
||||
_GUARD_TYPE_VERSION +
|
||||
unused/2 +
|
||||
_LOAD_ATTR_METHOD_NO_DICT;
|
||||
|
||||
inst(LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, owner -- attr, unused if (0))) {
|
||||
assert((oparg & 1) == 0);
|
||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||
|
|
139
Python/executor_cases.c.h
generated
139
Python/executor_cases.c.h
generated
|
@ -1714,6 +1714,83 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _LOAD_ATTR_SLOT: {
|
||||
PyObject *owner;
|
||||
PyObject *attr;
|
||||
PyObject *null = NULL;
|
||||
owner = stack_pointer[-1];
|
||||
uint16_t index = (uint16_t)operand;
|
||||
char *addr = (char *)owner + index;
|
||||
attr = *(PyObject **)addr;
|
||||
DEOPT_IF(attr == NULL, LOAD_ATTR);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
Py_INCREF(attr);
|
||||
null = NULL;
|
||||
Py_DECREF(owner);
|
||||
STACK_GROW(((oparg & 1) ? 1 : 0));
|
||||
stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
|
||||
if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
|
||||
break;
|
||||
}
|
||||
|
||||
case _GUARD_DORV_VALUES: {
|
||||
PyObject *owner;
|
||||
owner = stack_pointer[-1];
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(!_PyDictOrValues_IsValues(dorv), STORE_ATTR);
|
||||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_INSTANCE_VALUE: {
|
||||
PyObject *owner;
|
||||
PyObject *value;
|
||||
owner = stack_pointer[-1];
|
||||
value = stack_pointer[-2];
|
||||
uint16_t index = (uint16_t)operand;
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyDictValues *values = _PyDictOrValues_GetValues(dorv);
|
||||
PyObject *old_value = values->values[index];
|
||||
values->values[index] = value;
|
||||
if (old_value == NULL) {
|
||||
_PyDictValues_AddToInsertionOrder(values, index);
|
||||
}
|
||||
else {
|
||||
Py_DECREF(old_value);
|
||||
}
|
||||
Py_DECREF(owner);
|
||||
STACK_SHRINK(2);
|
||||
break;
|
||||
}
|
||||
|
||||
case _GUARD_TYPE_VERSION_STORE: {
|
||||
PyObject *owner;
|
||||
owner = stack_pointer[-1];
|
||||
uint32_t type_version = (uint32_t)operand;
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
|
||||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_SLOT: {
|
||||
PyObject *owner;
|
||||
PyObject *value;
|
||||
owner = stack_pointer[-1];
|
||||
value = stack_pointer[-2];
|
||||
uint16_t index = (uint16_t)operand;
|
||||
char *addr = (char *)owner + index;
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyObject *old_value = *(PyObject **)addr;
|
||||
*(PyObject **)addr = value;
|
||||
Py_XDECREF(old_value);
|
||||
Py_DECREF(owner);
|
||||
STACK_SHRINK(2);
|
||||
break;
|
||||
}
|
||||
|
||||
case COMPARE_OP: {
|
||||
PyObject *right;
|
||||
PyObject *left;
|
||||
|
@ -2219,6 +2296,68 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT: {
|
||||
PyObject *owner;
|
||||
owner = stack_pointer[-1];
|
||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||
assert(owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) &&
|
||||
!_PyObject_MakeInstanceAttributesFromDict(owner, dorv),
|
||||
LOAD_ATTR);
|
||||
break;
|
||||
}
|
||||
|
||||
case _GUARD_KEYS_VERSION: {
|
||||
PyObject *owner;
|
||||
owner = stack_pointer[-1];
|
||||
uint32_t keys_version = (uint32_t)operand;
|
||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
|
||||
DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version !=
|
||||
keys_version, LOAD_ATTR);
|
||||
break;
|
||||
}
|
||||
|
||||
case _LOAD_ATTR_METHOD_WITH_VALUES: {
|
||||
PyObject *owner;
|
||||
PyObject *attr;
|
||||
PyObject *self;
|
||||
owner = stack_pointer[-1];
|
||||
PyObject *descr = (PyObject *)operand;
|
||||
assert(oparg & 1);
|
||||
/* Cached method object */
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
assert(descr != NULL);
|
||||
attr = Py_NewRef(descr);
|
||||
assert(_PyType_HasFeature(Py_TYPE(attr), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
||||
self = owner;
|
||||
STACK_GROW(1);
|
||||
stack_pointer[-2] = attr;
|
||||
stack_pointer[-1] = self;
|
||||
break;
|
||||
}
|
||||
|
||||
case _LOAD_ATTR_METHOD_NO_DICT: {
|
||||
PyObject *owner;
|
||||
PyObject *attr;
|
||||
PyObject *self;
|
||||
owner = stack_pointer[-1];
|
||||
PyObject *descr = (PyObject *)operand;
|
||||
assert(oparg & 1);
|
||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||
assert(owner_cls->tp_dictoffset == 0);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
assert(descr != NULL);
|
||||
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
||||
attr = Py_NewRef(descr);
|
||||
self = owner;
|
||||
STACK_GROW(1);
|
||||
stack_pointer[-2] = attr;
|
||||
stack_pointer[-1] = self;
|
||||
break;
|
||||
}
|
||||
|
||||
case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
|
||||
PyObject *null;
|
||||
PyObject *callable;
|
||||
|
|
191
Python/generated_cases.c.h
generated
191
Python/generated_cases.c.h
generated
|
@ -2504,19 +2504,25 @@
|
|||
PyObject *owner;
|
||||
PyObject *attr;
|
||||
PyObject *null = NULL;
|
||||
// _GUARD_TYPE_VERSION
|
||||
owner = stack_pointer[-1];
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
uint16_t index = read_u16(&next_instr[3].cache);
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
|
||||
char *addr = (char *)owner + index;
|
||||
attr = *(PyObject **)addr;
|
||||
DEOPT_IF(attr == NULL, LOAD_ATTR);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
Py_INCREF(attr);
|
||||
null = NULL;
|
||||
Py_DECREF(owner);
|
||||
{
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
|
||||
}
|
||||
// _LOAD_ATTR_SLOT
|
||||
{
|
||||
uint16_t index = read_u16(&next_instr[3].cache);
|
||||
char *addr = (char *)owner + index;
|
||||
attr = *(PyObject **)addr;
|
||||
DEOPT_IF(attr == NULL, LOAD_ATTR);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
Py_INCREF(attr);
|
||||
null = NULL;
|
||||
Py_DECREF(owner);
|
||||
}
|
||||
STACK_GROW(((oparg & 1) ? 1 : 0));
|
||||
stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
|
||||
if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
|
||||
|
@ -2615,27 +2621,38 @@
|
|||
TARGET(STORE_ATTR_INSTANCE_VALUE) {
|
||||
PyObject *owner;
|
||||
PyObject *value;
|
||||
// _GUARD_TYPE_VERSION_STORE
|
||||
owner = stack_pointer[-1];
|
||||
{
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
|
||||
}
|
||||
// _GUARD_DORV_VALUES
|
||||
{
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(!_PyDictOrValues_IsValues(dorv), STORE_ATTR);
|
||||
}
|
||||
// _STORE_ATTR_INSTANCE_VALUE
|
||||
value = stack_pointer[-2];
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
uint16_t index = read_u16(&next_instr[3].cache);
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
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);
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyDictValues *values = _PyDictOrValues_GetValues(dorv);
|
||||
PyObject *old_value = values->values[index];
|
||||
values->values[index] = value;
|
||||
if (old_value == NULL) {
|
||||
_PyDictValues_AddToInsertionOrder(values, index);
|
||||
{
|
||||
uint16_t index = read_u16(&next_instr[3].cache);
|
||||
PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyDictValues *values = _PyDictOrValues_GetValues(dorv);
|
||||
PyObject *old_value = values->values[index];
|
||||
values->values[index] = value;
|
||||
if (old_value == NULL) {
|
||||
_PyDictValues_AddToInsertionOrder(values, index);
|
||||
}
|
||||
else {
|
||||
Py_DECREF(old_value);
|
||||
}
|
||||
Py_DECREF(owner);
|
||||
}
|
||||
else {
|
||||
Py_DECREF(old_value);
|
||||
}
|
||||
Py_DECREF(owner);
|
||||
STACK_SHRINK(2);
|
||||
next_instr += 4;
|
||||
DISPATCH();
|
||||
|
@ -2694,19 +2711,25 @@
|
|||
TARGET(STORE_ATTR_SLOT) {
|
||||
PyObject *owner;
|
||||
PyObject *value;
|
||||
// _GUARD_TYPE_VERSION_STORE
|
||||
owner = stack_pointer[-1];
|
||||
{
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
|
||||
}
|
||||
// _STORE_ATTR_SLOT
|
||||
value = stack_pointer[-2];
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
uint16_t index = read_u16(&next_instr[3].cache);
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
|
||||
char *addr = (char *)owner + index;
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyObject *old_value = *(PyObject **)addr;
|
||||
*(PyObject **)addr = value;
|
||||
Py_XDECREF(old_value);
|
||||
Py_DECREF(owner);
|
||||
{
|
||||
uint16_t index = read_u16(&next_instr[3].cache);
|
||||
char *addr = (char *)owner + index;
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyObject *old_value = *(PyObject **)addr;
|
||||
*(PyObject **)addr = value;
|
||||
Py_XDECREF(old_value);
|
||||
Py_DECREF(owner);
|
||||
}
|
||||
STACK_SHRINK(2);
|
||||
next_instr += 4;
|
||||
DISPATCH();
|
||||
|
@ -3557,28 +3580,42 @@
|
|||
PyObject *owner;
|
||||
PyObject *attr;
|
||||
PyObject *self;
|
||||
// _GUARD_TYPE_VERSION
|
||||
owner = stack_pointer[-1];
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
uint32_t keys_version = read_u32(&next_instr[3].cache);
|
||||
PyObject *descr = read_obj(&next_instr[5].cache);
|
||||
assert(oparg & 1);
|
||||
/* Cached method object */
|
||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(owner_cls->tp_version_tag != type_version, LOAD_ATTR);
|
||||
assert(owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) &&
|
||||
!_PyObject_MakeInstanceAttributesFromDict(owner, dorv),
|
||||
LOAD_ATTR);
|
||||
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
|
||||
DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version !=
|
||||
keys_version, LOAD_ATTR);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
assert(descr != NULL);
|
||||
attr = Py_NewRef(descr);
|
||||
assert(_PyType_HasFeature(Py_TYPE(attr), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
||||
self = owner;
|
||||
{
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
|
||||
}
|
||||
// _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT
|
||||
{
|
||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||
assert(owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
|
||||
DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) &&
|
||||
!_PyObject_MakeInstanceAttributesFromDict(owner, dorv),
|
||||
LOAD_ATTR);
|
||||
}
|
||||
// _GUARD_KEYS_VERSION
|
||||
{
|
||||
uint32_t keys_version = read_u32(&next_instr[3].cache);
|
||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||
PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
|
||||
DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version !=
|
||||
keys_version, LOAD_ATTR);
|
||||
}
|
||||
// _LOAD_ATTR_METHOD_WITH_VALUES
|
||||
{
|
||||
PyObject *descr = read_obj(&next_instr[5].cache);
|
||||
assert(oparg & 1);
|
||||
/* Cached method object */
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
assert(descr != NULL);
|
||||
attr = Py_NewRef(descr);
|
||||
assert(_PyType_HasFeature(Py_TYPE(attr), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
||||
self = owner;
|
||||
}
|
||||
STACK_GROW(1);
|
||||
stack_pointer[-2] = attr;
|
||||
stack_pointer[-1] = self;
|
||||
|
@ -3590,18 +3627,26 @@
|
|||
PyObject *owner;
|
||||
PyObject *attr;
|
||||
PyObject *self;
|
||||
// _GUARD_TYPE_VERSION
|
||||
owner = stack_pointer[-1];
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
PyObject *descr = read_obj(&next_instr[5].cache);
|
||||
assert(oparg & 1);
|
||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||
DEOPT_IF(owner_cls->tp_version_tag != type_version, LOAD_ATTR);
|
||||
assert(owner_cls->tp_dictoffset == 0);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
assert(descr != NULL);
|
||||
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
||||
attr = Py_NewRef(descr);
|
||||
self = owner;
|
||||
{
|
||||
uint32_t type_version = read_u32(&next_instr[1].cache);
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
assert(type_version != 0);
|
||||
DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
|
||||
}
|
||||
// _LOAD_ATTR_METHOD_NO_DICT
|
||||
{
|
||||
PyObject *descr = read_obj(&next_instr[5].cache);
|
||||
assert(oparg & 1);
|
||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||
assert(owner_cls->tp_dictoffset == 0);
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
assert(descr != NULL);
|
||||
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
|
||||
attr = Py_NewRef(descr);
|
||||
self = owner;
|
||||
}
|
||||
STACK_GROW(1);
|
||||
stack_pointer[-2] = attr;
|
||||
stack_pointer[-1] = self;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue