mirror of
https://github.com/python/cpython.git
synced 2026-04-20 10:51:00 +00:00
gh-148510: restore func_version check in _LOAD_ATTR_PROPERTY_FRAME (GH-148528)
This commit is contained in:
parent
4af46b4ab5
commit
52a7f1b7f8
13 changed files with 603 additions and 429 deletions
|
|
@ -2919,14 +2919,12 @@ dummy_func(
|
|||
_LOAD_ATTR_CLASS +
|
||||
_PUSH_NULL_CONDITIONAL;
|
||||
|
||||
op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame)) {
|
||||
op(_LOAD_ATTR_PROPERTY_FRAME, (func_version/2, fget/4, owner -- new_frame)) {
|
||||
assert((oparg & 1) == 0);
|
||||
assert(Py_IS_TYPE(fget, &PyFunction_Type));
|
||||
PyFunctionObject *f = (PyFunctionObject *)fget;
|
||||
EXIT_IF(f->func_version != func_version);
|
||||
PyCodeObject *code = (PyCodeObject *)f->func_code;
|
||||
EXIT_IF((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED);
|
||||
EXIT_IF(code->co_kwonlyargcount);
|
||||
EXIT_IF(code->co_argcount != 1);
|
||||
EXIT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize));
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
_PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame);
|
||||
|
|
@ -2940,7 +2938,6 @@ dummy_func(
|
|||
_RECORD_TOS_TYPE +
|
||||
_GUARD_TYPE_VERSION +
|
||||
_CHECK_PEP_523 +
|
||||
unused/2 +
|
||||
_LOAD_ATTR_PROPERTY_FRAME +
|
||||
_SAVE_RETURN_OFFSET +
|
||||
_PUSH_FRAME;
|
||||
|
|
|
|||
148
Python/executor_cases.c.h
generated
148
Python/executor_cases.c.h
generated
|
|
@ -11450,6 +11450,41 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _LOAD_ATTR_PROPERTY_FRAME_r01: {
|
||||
CHECK_CURRENT_CACHED_VALUES(0);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef owner;
|
||||
_PyStackRef new_frame;
|
||||
oparg = CURRENT_OPARG();
|
||||
owner = stack_pointer[-1];
|
||||
uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32();
|
||||
PyObject *fget = (PyObject *)CURRENT_OPERAND1_64();
|
||||
assert((oparg & 1) == 0);
|
||||
assert(Py_IS_TYPE(fget, &PyFunction_Type));
|
||||
PyFunctionObject *f = (PyFunctionObject *)fget;
|
||||
if (f->func_version != func_version) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
SET_CURRENT_CACHED_VALUES(0);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
PyCodeObject *code = (PyCodeObject *)f->func_code;
|
||||
if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
SET_CURRENT_CACHED_VALUES(0);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
_PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame);
|
||||
pushed_frame->localsplus[0] = owner;
|
||||
new_frame = PyStackRef_Wrap(pushed_frame);
|
||||
_tos_cache0 = new_frame;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
||||
case _LOAD_ATTR_PROPERTY_FRAME_r11: {
|
||||
CHECK_CURRENT_CACHED_VALUES(1);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
|
|
@ -11458,29 +11493,18 @@
|
|||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
oparg = CURRENT_OPARG();
|
||||
owner = _stack_item_0;
|
||||
PyObject *fget = (PyObject *)CURRENT_OPERAND0_64();
|
||||
uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32();
|
||||
PyObject *fget = (PyObject *)CURRENT_OPERAND1_64();
|
||||
assert((oparg & 1) == 0);
|
||||
assert(Py_IS_TYPE(fget, &PyFunction_Type));
|
||||
PyFunctionObject *f = (PyFunctionObject *)fget;
|
||||
if (f->func_version != func_version) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache0 = owner;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
PyCodeObject *code = (PyCodeObject *)f->func_code;
|
||||
if ((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache0 = owner;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
if (code->co_kwonlyargcount) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache0 = owner;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
if (code->co_argcount != 1) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache0 = owner;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache0 = owner;
|
||||
|
|
@ -11492,13 +11516,95 @@
|
|||
pushed_frame->localsplus[0] = owner;
|
||||
new_frame = PyStackRef_Wrap(pushed_frame);
|
||||
_tos_cache0 = new_frame;
|
||||
_tos_cache1 = PyStackRef_ZERO_BITS;
|
||||
_tos_cache2 = PyStackRef_ZERO_BITS;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
||||
case _LOAD_ATTR_PROPERTY_FRAME_r22: {
|
||||
CHECK_CURRENT_CACHED_VALUES(2);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef owner;
|
||||
_PyStackRef new_frame;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
_PyStackRef _stack_item_1 = _tos_cache1;
|
||||
oparg = CURRENT_OPARG();
|
||||
owner = _stack_item_1;
|
||||
uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32();
|
||||
PyObject *fget = (PyObject *)CURRENT_OPERAND1_64();
|
||||
assert((oparg & 1) == 0);
|
||||
assert(Py_IS_TYPE(fget, &PyFunction_Type));
|
||||
PyFunctionObject *f = (PyFunctionObject *)fget;
|
||||
if (f->func_version != func_version) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache1 = owner;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(2);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
PyCodeObject *code = (PyCodeObject *)f->func_code;
|
||||
if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache1 = owner;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(2);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
_PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame);
|
||||
pushed_frame->localsplus[0] = owner;
|
||||
new_frame = PyStackRef_Wrap(pushed_frame);
|
||||
_tos_cache1 = new_frame;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(2);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
||||
case _LOAD_ATTR_PROPERTY_FRAME_r33: {
|
||||
CHECK_CURRENT_CACHED_VALUES(3);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef owner;
|
||||
_PyStackRef new_frame;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
_PyStackRef _stack_item_1 = _tos_cache1;
|
||||
_PyStackRef _stack_item_2 = _tos_cache2;
|
||||
oparg = CURRENT_OPARG();
|
||||
owner = _stack_item_2;
|
||||
uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32();
|
||||
PyObject *fget = (PyObject *)CURRENT_OPERAND1_64();
|
||||
assert((oparg & 1) == 0);
|
||||
assert(Py_IS_TYPE(fget, &PyFunction_Type));
|
||||
PyFunctionObject *f = (PyFunctionObject *)fget;
|
||||
if (f->func_version != func_version) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache2 = owner;
|
||||
_tos_cache1 = _stack_item_1;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(3);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
PyCodeObject *code = (PyCodeObject *)f->func_code;
|
||||
if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache2 = owner;
|
||||
_tos_cache1 = _stack_item_1;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(3);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
STAT_INC(LOAD_ATTR, hit);
|
||||
_PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame);
|
||||
pushed_frame->localsplus[0] = owner;
|
||||
new_frame = PyStackRef_Wrap(pushed_frame);
|
||||
_tos_cache2 = new_frame;
|
||||
_tos_cache1 = _stack_item_1;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(3);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
||||
/* _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN is not a viable micro-op for tier 2 because it has too many cache entries */
|
||||
|
||||
case _GUARD_DORV_NO_DICT_r01: {
|
||||
|
|
|
|||
22
Python/generated_cases.c.h
generated
22
Python/generated_cases.c.h
generated
|
|
@ -8839,29 +8839,19 @@
|
|||
JUMP_TO_PREDICTED(LOAD_ATTR);
|
||||
}
|
||||
}
|
||||
/* Skip 2 cache entries */
|
||||
// _LOAD_ATTR_PROPERTY_FRAME
|
||||
{
|
||||
uint32_t func_version = read_u32(&this_instr[4].cache);
|
||||
PyObject *fget = read_obj(&this_instr[6].cache);
|
||||
assert((oparg & 1) == 0);
|
||||
assert(Py_IS_TYPE(fget, &PyFunction_Type));
|
||||
PyFunctionObject *f = (PyFunctionObject *)fget;
|
||||
if (f->func_version != func_version) {
|
||||
UPDATE_MISS_STATS(LOAD_ATTR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR));
|
||||
JUMP_TO_PREDICTED(LOAD_ATTR);
|
||||
}
|
||||
PyCodeObject *code = (PyCodeObject *)f->func_code;
|
||||
if ((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED) {
|
||||
UPDATE_MISS_STATS(LOAD_ATTR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR));
|
||||
JUMP_TO_PREDICTED(LOAD_ATTR);
|
||||
}
|
||||
if (code->co_kwonlyargcount) {
|
||||
UPDATE_MISS_STATS(LOAD_ATTR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR));
|
||||
JUMP_TO_PREDICTED(LOAD_ATTR);
|
||||
}
|
||||
if (code->co_argcount != 1) {
|
||||
UPDATE_MISS_STATS(LOAD_ATTR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR));
|
||||
JUMP_TO_PREDICTED(LOAD_ATTR);
|
||||
}
|
||||
if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) {
|
||||
UPDATE_MISS_STATS(LOAD_ATTR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR));
|
||||
|
|
|
|||
|
|
@ -257,6 +257,7 @@ add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr,
|
|||
#define sym_get_probable_type _Py_uop_sym_get_probable_type
|
||||
#define sym_matches_type _Py_uop_sym_matches_type
|
||||
#define sym_matches_type_version _Py_uop_sym_matches_type_version
|
||||
#define sym_get_type_version _Py_uop_sym_get_type_version
|
||||
#define sym_set_null(SYM) _Py_uop_sym_set_null(ctx, SYM)
|
||||
#define sym_set_non_null(SYM) _Py_uop_sym_set_non_null(ctx, SYM)
|
||||
#define sym_set_type(SYM, TYPE) _Py_uop_sym_set_type(ctx, SYM, TYPE)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
|
|||
#define sym_new_null _Py_uop_sym_new_null
|
||||
#define sym_matches_type _Py_uop_sym_matches_type
|
||||
#define sym_matches_type_version _Py_uop_sym_matches_type_version
|
||||
#define sym_get_type_version _Py_uop_sym_get_type_version
|
||||
#define sym_get_type _Py_uop_sym_get_type
|
||||
#define sym_has_type _Py_uop_sym_has_type
|
||||
#define sym_set_null(SYM) _Py_uop_sym_set_null(ctx, SYM)
|
||||
|
|
@ -138,15 +139,24 @@ dummy_func(void) {
|
|||
assert(type_version);
|
||||
if (sym_matches_type_version(owner, type_version)) {
|
||||
ADD_OP(_NOP, 0, 0);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
PyTypeObject *probable_type = sym_get_probable_type(owner);
|
||||
if (probable_type->tp_version_tag == type_version && sym_set_type_version(owner, type_version)) {
|
||||
if (probable_type != NULL &&
|
||||
probable_type->tp_version_tag == type_version) {
|
||||
// Promote the probable type version to a known one.
|
||||
sym_set_type(owner, probable_type);
|
||||
sym_set_type_version(owner, type_version);
|
||||
if ((probable_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) {
|
||||
PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type);
|
||||
_Py_BloomFilter_Add(dependencies, probable_type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx->contradiction = true;
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -239,20 +249,20 @@ dummy_func(void) {
|
|||
assert(this_instr[-1].opcode == _RECORD_TOS_TYPE);
|
||||
if (sym_matches_type_version(owner, type_version)) {
|
||||
ADD_OP(_NOP, 0, 0);
|
||||
} else {
|
||||
// add watcher so that whenever the type changes we invalidate this
|
||||
PyTypeObject *type = _PyType_LookupByVersion(type_version);
|
||||
// if the type is null, it was not found in the cache (there was a conflict)
|
||||
// with the key, in which case we can't trust the version
|
||||
if (type) {
|
||||
// if the type version was set properly, then add a watcher
|
||||
// if it wasn't this means that the type version was previously set to something else
|
||||
// and we set the owner to bottom, so we don't need to add a watcher because we must have
|
||||
// already added one earlier.
|
||||
if (sym_set_type_version(owner, type_version)) {
|
||||
PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type);
|
||||
_Py_BloomFilter_Add(dependencies, type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyTypeObject *probable_type = sym_get_probable_type(owner);
|
||||
if (probable_type != NULL &&
|
||||
probable_type->tp_version_tag == type_version) {
|
||||
sym_set_type(owner, probable_type);
|
||||
sym_set_type_version(owner, type_version);
|
||||
PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type);
|
||||
_Py_BloomFilter_Add(dependencies, probable_type);
|
||||
}
|
||||
else {
|
||||
ctx->contradiction = true;
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -983,15 +993,22 @@ dummy_func(void) {
|
|||
_LOAD_CONST_INLINE, _SWAP);
|
||||
}
|
||||
|
||||
op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame)) {
|
||||
// + 1 for _SAVE_RETURN_OFFSET
|
||||
// FIX ME -- This needs a version check and function watcher
|
||||
PyCodeObject *co = (PyCodeObject *)((PyFunctionObject *)fget)->func_code;
|
||||
op(_LOAD_ATTR_PROPERTY_FRAME, (func_version/2, fget/4, owner -- new_frame)) {
|
||||
PyFunctionObject *func = (PyFunctionObject *)fget;
|
||||
if (sym_get_type_version(owner) == 0 ||
|
||||
func->func_version != func_version) {
|
||||
ctx->contradiction = true;
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
_Py_BloomFilter_Add(dependencies, fget);
|
||||
PyCodeObject *co = (PyCodeObject *)func->func_code;
|
||||
_Py_UOpsAbstractFrame *f = frame_new(ctx, co, NULL, 0);
|
||||
if (f == NULL) {
|
||||
break;
|
||||
}
|
||||
f->locals[0] = owner;
|
||||
f->func = func;
|
||||
new_frame = PyJitRef_WrapInvalid(f);
|
||||
}
|
||||
|
||||
|
|
|
|||
48
Python/optimizer_cases.c.h
generated
48
Python/optimizer_cases.c.h
generated
|
|
@ -2429,13 +2429,20 @@
|
|||
assert(this_instr[-1].opcode == _RECORD_TOS_TYPE);
|
||||
if (sym_matches_type_version(owner, type_version)) {
|
||||
ADD_OP(_NOP, 0, 0);
|
||||
} else {
|
||||
PyTypeObject *type = _PyType_LookupByVersion(type_version);
|
||||
if (type) {
|
||||
if (sym_set_type_version(owner, type_version)) {
|
||||
PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type);
|
||||
_Py_BloomFilter_Add(dependencies, type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyTypeObject *probable_type = sym_get_probable_type(owner);
|
||||
if (probable_type != NULL &&
|
||||
probable_type->tp_version_tag == type_version) {
|
||||
sym_set_type(owner, probable_type);
|
||||
sym_set_type_version(owner, type_version);
|
||||
PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type);
|
||||
_Py_BloomFilter_Add(dependencies, probable_type);
|
||||
}
|
||||
else {
|
||||
ctx->contradiction = true;
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -2448,14 +2455,23 @@
|
|||
assert(type_version);
|
||||
if (sym_matches_type_version(owner, type_version)) {
|
||||
ADD_OP(_NOP, 0, 0);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
PyTypeObject *probable_type = sym_get_probable_type(owner);
|
||||
if (probable_type->tp_version_tag == type_version && sym_set_type_version(owner, type_version)) {
|
||||
if (probable_type != NULL &&
|
||||
probable_type->tp_version_tag == type_version) {
|
||||
sym_set_type(owner, probable_type);
|
||||
sym_set_type_version(owner, type_version);
|
||||
if ((probable_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) {
|
||||
PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type);
|
||||
_Py_BloomFilter_Add(dependencies, probable_type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx->contradiction = true;
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -2598,13 +2614,23 @@
|
|||
JitOptRef owner;
|
||||
JitOptRef new_frame;
|
||||
owner = stack_pointer[-1];
|
||||
PyObject *fget = (PyObject *)this_instr->operand0;
|
||||
PyCodeObject *co = (PyCodeObject *)((PyFunctionObject *)fget)->func_code;
|
||||
uint32_t func_version = (uint32_t)this_instr->operand0;
|
||||
PyObject *fget = (PyObject *)this_instr->operand1;
|
||||
PyFunctionObject *func = (PyFunctionObject *)fget;
|
||||
if (sym_get_type_version(owner) == 0 ||
|
||||
func->func_version != func_version) {
|
||||
ctx->contradiction = true;
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
_Py_BloomFilter_Add(dependencies, fget);
|
||||
PyCodeObject *co = (PyCodeObject *)func->func_code;
|
||||
_Py_UOpsAbstractFrame *f = frame_new(ctx, co, NULL, 0);
|
||||
if (f == NULL) {
|
||||
break;
|
||||
}
|
||||
f->locals[0] = owner;
|
||||
f->func = func;
|
||||
new_frame = PyJitRef_WrapInvalid(f);
|
||||
stack_pointer[-1] = new_frame;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -846,8 +846,13 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
|
|||
return -1;
|
||||
}
|
||||
#endif
|
||||
uint32_t func_version = function_get_version(fget, LOAD_ATTR);
|
||||
if (func_version == 0) {
|
||||
return -1;
|
||||
}
|
||||
assert(tp_version != 0);
|
||||
write_u32(lm_cache->type_version, tp_version);
|
||||
write_u32(lm_cache->keys_version, func_version);
|
||||
/* borrowed */
|
||||
write_ptr(lm_cache->descr, fget);
|
||||
specialize(instr, LOAD_ATTR_PROPERTY);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue