aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python
diff options
context:
space:
mode:
Diffstat (limited to 'Python')
-rw-r--r--Python/bytecodes.c30
-rw-r--r--Python/executor_cases.c.h34
-rw-r--r--Python/generated_cases.c.h79
-rw-r--r--Python/optimizer.c5
-rw-r--r--Python/optimizer_cases.c.h7
-rw-r--r--Python/specialize.c5
6 files changed, 112 insertions, 48 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index b161fc0ede1..d356fc9bfdd 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -2243,32 +2243,30 @@ dummy_func(
unused/2 +
_LOAD_ATTR_CLASS;
- inst(LOAD_ATTR_PROPERTY, (unused/1, type_version/2, func_version/2, fget/4, owner -- unused, unused if (0))) {
- PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
-
+ op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame: _PyInterpreterFrame *)) {
assert((oparg & 1) == 0);
- DEOPT_IF(tstate->interp->eval_frame);
-
- PyTypeObject *cls = Py_TYPE(owner_o);
- assert(type_version != 0);
- DEOPT_IF(cls->tp_version_tag != type_version);
assert(Py_IS_TYPE(fget, &PyFunction_Type));
PyFunctionObject *f = (PyFunctionObject *)fget;
- assert(func_version != 0);
- DEOPT_IF(f->func_version != func_version);
PyCodeObject *code = (PyCodeObject *)f->func_code;
- assert(code->co_argcount == 1);
+ DEOPT_IF((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED);
+ DEOPT_IF(code->co_kwonlyargcount);
+ DEOPT_IF(code->co_argcount != 1);
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize));
STAT_INC(LOAD_ATTR, hit);
Py_INCREF(fget);
- _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 1);
- // Manipulate stack directly because we exit with DISPATCH_INLINED().
- STACK_SHRINK(1);
+ new_frame = _PyFrame_PushUnchecked(tstate, f, 1);
new_frame->localsplus[0] = owner;
- frame->return_offset = (uint16_t)(next_instr - this_instr);
- DISPATCH_INLINED(new_frame);
}
+ macro(LOAD_ATTR_PROPERTY) =
+ unused/1 +
+ _CHECK_PEP_523 +
+ _GUARD_TYPE_VERSION +
+ unused/2 +
+ _LOAD_ATTR_PROPERTY_FRAME +
+ _SAVE_RETURN_OFFSET +
+ _PUSH_FRAME;
+
inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, (unused/1, type_version/2, func_version/2, getattribute/4, owner -- unused, unused if (0))) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 87c9255ef79..b8343f9ffd5 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -2507,7 +2507,39 @@
/* _LOAD_ATTR_CLASS is split on (oparg & 1) */
- /* _LOAD_ATTR_PROPERTY is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */
+ case _LOAD_ATTR_PROPERTY_FRAME: {
+ _PyStackRef owner;
+ _PyInterpreterFrame *new_frame;
+ oparg = CURRENT_OPARG();
+ owner = stack_pointer[-1];
+ PyObject *fget = (PyObject *)CURRENT_OPERAND();
+ assert((oparg & 1) == 0);
+ assert(Py_IS_TYPE(fget, &PyFunction_Type));
+ PyFunctionObject *f = (PyFunctionObject *)fget;
+ PyCodeObject *code = (PyCodeObject *)f->func_code;
+ if ((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ if (code->co_kwonlyargcount) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ if (code->co_argcount != 1) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ STAT_INC(LOAD_ATTR, hit);
+ Py_INCREF(fget);
+ new_frame = _PyFrame_PushUnchecked(tstate, f, 1);
+ new_frame->localsplus[0] = owner;
+ stack_pointer[-1].bits = (uintptr_t)new_frame;
+ break;
+ }
/* _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index f15a829ea3e..6f996f91921 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -4429,32 +4429,63 @@
INSTRUCTION_STATS(LOAD_ATTR_PROPERTY);
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
_PyStackRef owner;
+ _PyInterpreterFrame *new_frame;
/* Skip 1 cache entry */
+ // _CHECK_PEP_523
+ {
+ DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR);
+ }
+ // _GUARD_TYPE_VERSION
owner = stack_pointer[-1];
- uint32_t type_version = read_u32(&this_instr[2].cache);
- uint32_t func_version = read_u32(&this_instr[4].cache);
- PyObject *fget = read_obj(&this_instr[6].cache);
- PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
- assert((oparg & 1) == 0);
- DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR);
- PyTypeObject *cls = Py_TYPE(owner_o);
- assert(type_version != 0);
- DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR);
- assert(Py_IS_TYPE(fget, &PyFunction_Type));
- PyFunctionObject *f = (PyFunctionObject *)fget;
- assert(func_version != 0);
- DEOPT_IF(f->func_version != func_version, LOAD_ATTR);
- PyCodeObject *code = (PyCodeObject *)f->func_code;
- assert(code->co_argcount == 1);
- DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR);
- STAT_INC(LOAD_ATTR, hit);
- Py_INCREF(fget);
- _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 1);
- // Manipulate stack directly because we exit with DISPATCH_INLINED().
- STACK_SHRINK(1);
- new_frame->localsplus[0] = owner;
- frame->return_offset = (uint16_t)(next_instr - this_instr);
- DISPATCH_INLINED(new_frame);
+ {
+ uint32_t type_version = read_u32(&this_instr[2].cache);
+ PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner));
+ assert(type_version != 0);
+ DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);
+ }
+ /* Skip 2 cache entries */
+ // _LOAD_ATTR_PROPERTY_FRAME
+ {
+ PyObject *fget = read_obj(&this_instr[6].cache);
+ assert((oparg & 1) == 0);
+ assert(Py_IS_TYPE(fget, &PyFunction_Type));
+ PyFunctionObject *f = (PyFunctionObject *)fget;
+ PyCodeObject *code = (PyCodeObject *)f->func_code;
+ DEOPT_IF((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED, LOAD_ATTR);
+ DEOPT_IF(code->co_kwonlyargcount, LOAD_ATTR);
+ DEOPT_IF(code->co_argcount != 1, LOAD_ATTR);
+ DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR);
+ STAT_INC(LOAD_ATTR, hit);
+ Py_INCREF(fget);
+ new_frame = _PyFrame_PushUnchecked(tstate, f, 1);
+ new_frame->localsplus[0] = owner;
+ }
+ // _SAVE_RETURN_OFFSET
+ {
+ #if TIER_ONE
+ frame->return_offset = (uint16_t)(next_instr - this_instr);
+ #endif
+ #if TIER_TWO
+ frame->return_offset = oparg;
+ #endif
+ }
+ // _PUSH_FRAME
+ {
+ // Write it out explicitly because it's subtly different.
+ // Eventually this should be the only occurrence of this code.
+ assert(tstate->interp->eval_frame == NULL);
+ stack_pointer += -1;
+ assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ new_frame->previous = frame;
+ CALL_STAT_INC(inlined_py_calls);
+ frame = tstate->current_frame = new_frame;
+ tstate->py_recursion_remaining--;
+ LOAD_SP();
+ LOAD_IP(0);
+ LLTRACE_RESUME_FRAME();
+ }
+ DISPATCH();
}
TARGET(LOAD_ATTR_SLOT) {
diff --git a/Python/optimizer.c b/Python/optimizer.c
index 73316b3587f..e08c1dc9936 100644
--- a/Python/optimizer.c
+++ b/Python/optimizer.c
@@ -797,7 +797,10 @@ top: // Jump here after _PUSH_FRAME or likely branches
if (uop == _PUSH_FRAME) {
assert(i + 1 == nuops);
- if (opcode == FOR_ITER_GEN || opcode == SEND_GEN) {
+ if (opcode == FOR_ITER_GEN ||
+ opcode == LOAD_ATTR_PROPERTY ||
+ opcode == SEND_GEN)
+ {
DPRINTF(2, "Bailing due to dynamic target\n");
ADD_TO_TRACE(uop, oparg, 0, target);
ADD_TO_TRACE(_DYNAMIC_EXIT, 0, 0, 0);
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 8077badce78..8c2b1ac7926 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -1160,7 +1160,12 @@
break;
}
- /* _LOAD_ATTR_PROPERTY is not a viable micro-op for tier 2 */
+ case _LOAD_ATTR_PROPERTY_FRAME: {
+ _PyInterpreterFrame *new_frame;
+ new_frame = sym_new_not_null(ctx);
+ stack_pointer[-1] = (_Py_UopsSymbol *)new_frame;
+ break;
+ }
/* _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN is not a viable micro-op for tier 2 */
diff --git a/Python/specialize.c b/Python/specialize.c
index 3af0deabb9b..c354a907901 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -963,15 +963,10 @@ _Py_Specialize_LoadAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *nam
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
goto fail;
}
- uint32_t version = function_get_version(fget, LOAD_ATTR);
- if (version == 0) {
- goto fail;
- }
if (_PyInterpreterState_GET()->eval_frame) {
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
goto fail;
}
- write_u32(lm_cache->keys_version, version);
assert(type->tp_version_tag != 0);
write_u32(lm_cache->type_version, type->tp_version_tag);
/* borrowed */