diff options
Diffstat (limited to 'Python')
-rw-r--r-- | Python/bytecodes.c | 58 | ||||
-rw-r--r-- | Python/ceval.c | 11 | ||||
-rw-r--r-- | Python/executor_cases.c.h | 163 | ||||
-rw-r--r-- | Python/generated_cases.c.h | 90 | ||||
-rw-r--r-- | Python/optimizer.c | 18 | ||||
-rw-r--r-- | Python/optimizer_bytecodes.c | 5 | ||||
-rw-r--r-- | Python/optimizer_cases.c.h | 48 |
7 files changed, 311 insertions, 82 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 142f97d..4800450 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1154,23 +1154,26 @@ dummy_func( macro(SEND) = _SPECIALIZE_SEND + _SEND; - inst(SEND_GEN, (unused/1, receiver, v -- receiver, unused)) { - DEOPT_IF(tstate->interp->eval_frame); + op(_SEND_GEN_FRAME, (receiver, v -- receiver, gen_frame: _PyInterpreterFrame *)) { PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver); DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type); DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING); STAT_INC(SEND, hit); - _PyInterpreterFrame *gen_frame = &gen->gi_iframe; - STACK_SHRINK(1); + gen_frame = &gen->gi_iframe; _PyFrame_StackPush(gen_frame, v); gen->gi_frame_state = FRAME_EXECUTING; gen->gi_exc_state.previous_item = tstate->exc_info; tstate->exc_info = &gen->gi_exc_state; - assert(next_instr - this_instr + oparg <= UINT16_MAX); - frame->return_offset = (uint16_t)(next_instr - this_instr + oparg); - DISPATCH_INLINED(gen_frame); + assert(1 + INLINE_CACHE_ENTRIES_SEND + oparg <= UINT16_MAX); + frame->return_offset = (uint16_t)(1 + INLINE_CACHE_ENTRIES_SEND + oparg); } + macro(SEND_GEN) = + unused/1 + + _CHECK_PEP_523 + + _SEND_GEN_FRAME + + _PUSH_FRAME; + inst(INSTRUMENTED_YIELD_VALUE, (retval -- unused)) { assert(frame != &entry_frame); frame->instr_ptr = next_instr; @@ -1547,22 +1550,16 @@ dummy_func( ERROR_IF(true, error); } PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v_o) < 0) { - ERROR_NO_POP(); - } + ERROR_IF(PyMapping_GetOptionalItem(mod_or_class_dict, name, &v_o) < 0, error); if (v_o == NULL) { - if (PyDict_GetItemRef(GLOBALS(), name, &v_o) < 0) { - ERROR_NO_POP(); - } + ERROR_IF(PyDict_GetItemRef(GLOBALS(), name, &v_o) < 0, error); if (v_o == NULL) { - if (PyMapping_GetOptionalItem(BUILTINS(), name, &v_o) < 0) { - ERROR_NO_POP(); - } + ERROR_IF(PyMapping_GetOptionalItem(BUILTINS(), name, &v_o) < 0, error); if (v_o == NULL) { _PyEval_FormatExcCheckArg( tstate, PyExc_NameError, NAME_ERROR_MSG, name); - ERROR_NO_POP(); + ERROR_IF(true, error); } } } @@ -1828,7 +1825,8 @@ dummy_func( inst(BUILD_SET, (values[oparg] -- set)) { PyObject *set_o = PySet_New(NULL); if (set_o == NULL) { - ERROR_NO_POP(); + DECREF_INPUTS(); + ERROR_IF(true, error); } int err = 0; for (int i = 0; i < oparg; i++) { @@ -2616,9 +2614,9 @@ dummy_func( b = res ? PyStackRef_True : PyStackRef_False; } - tier1 inst(IMPORT_NAME, (level, fromlist -- res)) { + inst(IMPORT_NAME, (level, fromlist -- res)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - PyObject *res_o = import_name(tstate, frame, name, + PyObject *res_o = _PyEval_ImportName(tstate, frame, name, PyStackRef_AsPyObjectBorrow(fromlist), PyStackRef_AsPyObjectBorrow(level)); DECREF_INPUTS(); @@ -2626,9 +2624,9 @@ dummy_func( res = PyStackRef_FromPyObjectSteal(res_o); } - tier1 inst(IMPORT_FROM, (from -- from, res)) { + inst(IMPORT_FROM, (from -- from, res)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - PyObject *res_o = import_from(tstate, PyStackRef_AsPyObjectBorrow(from), name); + PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -2898,7 +2896,7 @@ dummy_func( } /* iterator ended normally */ /* The translator sets the deopt target just past the matching END_FOR */ - DEOPT_IF(true); + EXIT_IF(true); } next = PyStackRef_FromPyObjectSteal(next_o); // Common case: no jump, leave it to the code generator @@ -3942,7 +3940,7 @@ dummy_func( } // This is secretly a super-instruction - tier1 inst(CALL_LIST_APPEND, (unused/1, unused/2, callable, self, arg -- unused)) { + inst(CALL_LIST_APPEND, (unused/1, unused/2, callable, self, arg -- )) { assert(oparg == 1); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *self_o = PyStackRef_AsPyObjectBorrow(self); @@ -3952,16 +3950,16 @@ dummy_func( assert(self_o != NULL); DEOPT_IF(!PyList_Check(self_o)); STAT_INC(CALL, hit); - if (_PyList_AppendTakeRef((PyListObject *)self_o, PyStackRef_AsPyObjectSteal(arg)) < 0) { - goto pop_1_error; // Since arg is DECREF'ed already - } + int err = _PyList_AppendTakeRef((PyListObject *)self_o, PyStackRef_AsPyObjectSteal(arg)); PyStackRef_CLOSE(self); PyStackRef_CLOSE(callable); - STACK_SHRINK(3); - // Skip POP_TOP + ERROR_IF(err, error); + #if TIER_ONE + // Skip the following POP_TOP. This is done here in tier one, and + // during trace projection in tier two: assert(next_instr->op.code == POP_TOP); SKIP_OVER(1); - DISPATCH(); + #endif } op(_CALL_METHOD_DESCRIPTOR_O, (callable, self_or_null, args[oparg] -- res)) { diff --git a/Python/ceval.c b/Python/ceval.c index 97d4b82..1e911d3 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -245,9 +245,6 @@ static void monitor_throw(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr); -static PyObject * import_name(PyThreadState *, _PyInterpreterFrame *, - PyObject *, PyObject *, PyObject *); -static PyObject * import_from(PyThreadState *, PyObject *, PyObject *); static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg); static int get_exception_handler(PyCodeObject *, int, int*, int*, int*); static _PyInterpreterFrame * @@ -2727,8 +2724,8 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi) return 1; } -static PyObject * -import_name(PyThreadState *tstate, _PyInterpreterFrame *frame, +PyObject * +_PyEval_ImportName(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *name, PyObject *fromlist, PyObject *level) { PyObject *import_func; @@ -2766,8 +2763,8 @@ import_name(PyThreadState *tstate, _PyInterpreterFrame *frame, return res; } -static PyObject * -import_from(PyThreadState *tstate, PyObject *v, PyObject *name) +PyObject * +_PyEval_ImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name) { PyObject *x; PyObject *fullmodname, *pkgname, *pkgpath, *pkgname_or_unknown, *errmsg; diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 375e1fb..e9f73f0 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -1227,7 +1227,33 @@ /* _SEND is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ - /* _SEND_GEN is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ + case _SEND_GEN_FRAME: { + _PyStackRef v; + _PyStackRef receiver; + _PyInterpreterFrame *gen_frame; + oparg = CURRENT_OPARG(); + v = stack_pointer[-1]; + receiver = stack_pointer[-2]; + PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver); + if (Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + if (gen->gi_frame_state >= FRAME_EXECUTING) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(SEND, hit); + gen_frame = &gen->gi_iframe; + _PyFrame_StackPush(gen_frame, v); + gen->gi_frame_state = FRAME_EXECUTING; + gen->gi_exc_state.previous_item = tstate->exc_info; + tstate->exc_info = &gen->gi_exc_state; + assert(1 + INLINE_CACHE_ENTRIES_SEND + oparg <= UINT16_MAX); + frame->return_offset = (uint16_t)(1 + INLINE_CACHE_ENTRIES_SEND + oparg); + stack_pointer[-1].bits = (uintptr_t)gen_frame; + break; + } /* _INSTRUMENTED_YIELD_VALUE is not a viable micro-op for tier 2 because it is instrumented */ @@ -1551,7 +1577,36 @@ /* _LOAD_FROM_DICT_OR_GLOBALS is not a viable micro-op for tier 2 because it has both popping and not-popping errors */ - /* _LOAD_NAME is not a viable micro-op for tier 2 because it has both popping and not-popping errors */ + case _LOAD_NAME: { + _PyStackRef v; + oparg = CURRENT_OPARG(); + PyObject *v_o; + PyObject *mod_or_class_dict = LOCALS(); + if (mod_or_class_dict == NULL) { + _PyErr_SetString(tstate, PyExc_SystemError, + "no locals found"); + if (true) JUMP_TO_ERROR(); + } + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v_o) < 0) JUMP_TO_ERROR(); + if (v_o == NULL) { + if (PyDict_GetItemRef(GLOBALS(), name, &v_o) < 0) JUMP_TO_ERROR(); + if (v_o == NULL) { + if (PyMapping_GetOptionalItem(BUILTINS(), name, &v_o) < 0) JUMP_TO_ERROR(); + if (v_o == NULL) { + _PyEval_FormatExcCheckArg( + tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + if (true) JUMP_TO_ERROR(); + } + } + } + v = PyStackRef_FromPyObjectSteal(v_o); + stack_pointer[0] = v; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + break; + } case _LOAD_GLOBAL: { _PyStackRef res; @@ -1890,7 +1945,36 @@ break; } - /* _BUILD_SET is not a viable micro-op for tier 2 because it has both popping and not-popping errors */ + case _BUILD_SET: { + _PyStackRef *values; + _PyStackRef set; + oparg = CURRENT_OPARG(); + values = &stack_pointer[-oparg]; + PyObject *set_o = PySet_New(NULL); + if (set_o == NULL) { + for (int _i = oparg; --_i >= 0;) { + PyStackRef_CLOSE(values[_i]); + } + if (true) JUMP_TO_ERROR(); + } + int err = 0; + for (int i = 0; i < oparg; i++) { + PyObject *item = PyStackRef_AsPyObjectSteal(values[i]); + if (err == 0) { + err = PySet_Add(set_o, item); + } + Py_DECREF(item); + } + if (err != 0) { + Py_DECREF(set_o); + if (true) JUMP_TO_ERROR(); + } + set = PyStackRef_FromPyObjectSteal(set_o); + stack_pointer[-oparg] = set; + stack_pointer += 1 - oparg; + assert(WITHIN_STACK_BOUNDS()); + break; + } case _BUILD_MAP: { _PyStackRef *values; @@ -2843,6 +2927,42 @@ break; } + case _IMPORT_NAME: { + _PyStackRef fromlist; + _PyStackRef level; + _PyStackRef res; + oparg = CURRENT_OPARG(); + fromlist = stack_pointer[-1]; + level = stack_pointer[-2]; + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + PyObject *res_o = _PyEval_ImportName(tstate, frame, name, + PyStackRef_AsPyObjectBorrow(fromlist), + PyStackRef_AsPyObjectBorrow(level)); + PyStackRef_CLOSE(level); + PyStackRef_CLOSE(fromlist); + if (res_o == NULL) JUMP_TO_ERROR(); + res = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[-2] = res; + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + break; + } + + case _IMPORT_FROM: { + _PyStackRef from; + _PyStackRef res; + oparg = CURRENT_OPARG(); + from = stack_pointer[-1]; + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name); + if (res_o == NULL) JUMP_TO_ERROR(); + res = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer[0] = res; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + break; + } + /* _POP_JUMP_IF_FALSE is not a viable micro-op for tier 2 because it is replaced */ /* _POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 because it is replaced */ @@ -4251,6 +4371,43 @@ break; } + case _CALL_LIST_APPEND: { + _PyStackRef arg; + _PyStackRef self; + _PyStackRef callable; + oparg = CURRENT_OPARG(); + arg = stack_pointer[-1]; + self = stack_pointer[-2]; + callable = stack_pointer[-3]; + assert(oparg == 1); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *self_o = PyStackRef_AsPyObjectBorrow(self); + PyInterpreterState *interp = tstate->interp; + if (callable_o != interp->callable_cache.list_append) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + assert(self_o != NULL); + if (!PyList_Check(self_o)) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(CALL, hit); + int err = _PyList_AppendTakeRef((PyListObject *)self_o, PyStackRef_AsPyObjectSteal(arg)); + PyStackRef_CLOSE(self); + PyStackRef_CLOSE(callable); + if (err) JUMP_TO_ERROR(); + #if TIER_ONE + // Skip the following POP_TOP. This is done here in tier one, and + // during trace projection in tier two: + assert(next_instr->op.code == POP_TOP); + SKIP_OVER(1); + #endif + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); + break; + } + case _CALL_METHOD_DESCRIPTOR_O: { _PyStackRef *args; _PyStackRef self_or_null; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 3822884..585e682 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -688,7 +688,10 @@ values = &stack_pointer[-oparg]; PyObject *set_o = PySet_New(NULL); if (set_o == NULL) { - goto error; + for (int _i = oparg; --_i >= 0;) { + PyStackRef_CLOSE(values[_i]); + } + if (true) { stack_pointer += -oparg; goto error; } } int err = 0; for (int i = 0; i < oparg; i++) { @@ -1744,15 +1747,18 @@ assert(self_o != NULL); DEOPT_IF(!PyList_Check(self_o), CALL); STAT_INC(CALL, hit); - if (_PyList_AppendTakeRef((PyListObject *)self_o, PyStackRef_AsPyObjectSteal(arg)) < 0) { - goto pop_1_error; // Since arg is DECREF'ed already - } + int err = _PyList_AppendTakeRef((PyListObject *)self_o, PyStackRef_AsPyObjectSteal(arg)); PyStackRef_CLOSE(self); PyStackRef_CLOSE(callable); - STACK_SHRINK(3); - // Skip POP_TOP + if (err) goto pop_3_error; + #if TIER_ONE + // Skip the following POP_TOP. This is done here in tier one, and + // during trace projection in tier two: assert(next_instr->op.code == POP_TOP); SKIP_OVER(1); + #endif + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -3488,7 +3494,7 @@ _PyStackRef res; from = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - PyObject *res_o = import_from(tstate, PyStackRef_AsPyObjectBorrow(from), name); + PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name); if (res_o == NULL) goto error; res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[0] = res; @@ -3507,7 +3513,7 @@ fromlist = stack_pointer[-1]; level = stack_pointer[-2]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - PyObject *res_o = import_name(tstate, frame, name, + PyObject *res_o = _PyEval_ImportName(tstate, frame, name, PyStackRef_AsPyObjectBorrow(fromlist), PyStackRef_AsPyObjectBorrow(level)); PyStackRef_CLOSE(level); @@ -4980,22 +4986,16 @@ if (true) goto error; } PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); - if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v_o) < 0) { - goto error; - } + if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v_o) < 0) goto error; if (v_o == NULL) { - if (PyDict_GetItemRef(GLOBALS(), name, &v_o) < 0) { - goto error; - } + if (PyDict_GetItemRef(GLOBALS(), name, &v_o) < 0) goto error; if (v_o == NULL) { - if (PyMapping_GetOptionalItem(BUILTINS(), name, &v_o) < 0) { - goto error; - } + if (PyMapping_GetOptionalItem(BUILTINS(), name, &v_o) < 0) goto error; if (v_o == NULL) { _PyEval_FormatExcCheckArg( tstate, PyExc_NameError, NAME_ERROR_MSG, name); - goto error; + if (true) goto error; } } } @@ -5806,29 +5806,53 @@ } TARGET(SEND_GEN) { - _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + frame->instr_ptr = next_instr; next_instr += 2; INSTRUCTION_STATS(SEND_GEN); static_assert(INLINE_CACHE_ENTRIES_SEND == 1, "incorrect cache size"); _PyStackRef receiver; _PyStackRef v; + _PyInterpreterFrame *gen_frame; + _PyInterpreterFrame *new_frame; /* Skip 1 cache entry */ + // _CHECK_PEP_523 + { + DEOPT_IF(tstate->interp->eval_frame, SEND); + } + // _SEND_GEN_FRAME v = stack_pointer[-1]; receiver = stack_pointer[-2]; - DEOPT_IF(tstate->interp->eval_frame, SEND); - PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver); - DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type, SEND); - DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, SEND); - STAT_INC(SEND, hit); - _PyInterpreterFrame *gen_frame = &gen->gi_iframe; - STACK_SHRINK(1); - _PyFrame_StackPush(gen_frame, v); - gen->gi_frame_state = FRAME_EXECUTING; - gen->gi_exc_state.previous_item = tstate->exc_info; - tstate->exc_info = &gen->gi_exc_state; - assert(next_instr - this_instr + oparg <= UINT16_MAX); - frame->return_offset = (uint16_t)(next_instr - this_instr + oparg); - DISPATCH_INLINED(gen_frame); + { + PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver); + DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type, SEND); + DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, SEND); + STAT_INC(SEND, hit); + gen_frame = &gen->gi_iframe; + _PyFrame_StackPush(gen_frame, v); + gen->gi_frame_state = FRAME_EXECUTING; + gen->gi_exc_state.previous_item = tstate->exc_info; + tstate->exc_info = &gen->gi_exc_state; + assert(1 + INLINE_CACHE_ENTRIES_SEND + oparg <= UINT16_MAX); + frame->return_offset = (uint16_t)(1 + INLINE_CACHE_ENTRIES_SEND + oparg); + } + // _PUSH_FRAME + new_frame = gen_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(SETUP_ANNOTATIONS) { diff --git a/Python/optimizer.c b/Python/optimizer.c index 561ec4e..a43eed4 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -797,6 +797,13 @@ 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) { + DPRINTF(2, "Bailing due to dynamic target\n"); + ADD_TO_TRACE(uop, oparg, 0, target); + ADD_TO_TRACE(_DYNAMIC_EXIT, 0, 0, 0); + goto done; + } + assert(_PyOpcode_Deopt[opcode] == CALL); int func_version_offset = offsetof(_PyCallCache, func_version)/sizeof(_Py_CODEUNIT) // Add one to account for the actual opcode/oparg pair: @@ -828,12 +835,6 @@ top: // Jump here after _PUSH_FRAME or likely branches ADD_TO_TRACE(_EXIT_TRACE, 0, 0, 0); goto done; } - if (opcode == FOR_ITER_GEN) { - DPRINTF(2, "Bailing due to dynamic target\n"); - ADD_TO_TRACE(uop, oparg, 0, target); - ADD_TO_TRACE(_DYNAMIC_EXIT, 0, 0, 0); - goto done; - } // Increment IP to the return address instr += _PyOpcode_Caches[_PyOpcode_Deopt[opcode]] + 1; TRACE_STACK_PUSH(); @@ -886,6 +887,11 @@ top: // Jump here after _PUSH_FRAME or likely branches instr++; // Add cache size for opcode instr += _PyOpcode_Caches[_PyOpcode_Deopt[opcode]]; + + if (opcode == CALL_LIST_APPEND) { + assert(instr->op.code == POP_TOP); + instr++; + } } // End for (;;) done: diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 2ea839f..a506f99 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -658,6 +658,11 @@ dummy_func(void) { ctx->done = true; } + op(_SEND_GEN_FRAME, ( -- )) { + // We are about to hit the end of the trace: + ctx->done = true; + } + op(_CHECK_STACK_SPACE, ( --)) { assert(corresponding_check_stack == NULL); corresponding_check_stack = this_instr; diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 978aa91..60cfb21 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -644,7 +644,11 @@ /* _SEND is not a viable micro-op for tier 2 */ - /* _SEND_GEN is not a viable micro-op for tier 2 */ + case _SEND_GEN_FRAME: { + // We are about to hit the end of the trace: + ctx->done = true; + break; + } /* _INSTRUMENTED_YIELD_VALUE is not a viable micro-op for tier 2 */ @@ -787,7 +791,14 @@ /* _LOAD_FROM_DICT_OR_GLOBALS is not a viable micro-op for tier 2 */ - /* _LOAD_NAME is not a viable micro-op for tier 2 */ + case _LOAD_NAME: { + _Py_UopsSymbol *v; + v = sym_new_not_null(ctx); + stack_pointer[0] = v; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + break; + } case _LOAD_GLOBAL: { _Py_UopsSymbol *res; @@ -910,7 +921,14 @@ break; } - /* _BUILD_SET is not a viable micro-op for tier 2 */ + case _BUILD_SET: { + _Py_UopsSymbol *set; + set = sym_new_not_null(ctx); + stack_pointer[-oparg] = set; + stack_pointer += 1 - oparg; + assert(WITHIN_STACK_BOUNDS()); + break; + } case _BUILD_MAP: { _Py_UopsSymbol *map; @@ -1307,6 +1325,24 @@ break; } + case _IMPORT_NAME: { + _Py_UopsSymbol *res; + res = sym_new_not_null(ctx); + stack_pointer[-2] = res; + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + break; + } + + case _IMPORT_FROM: { + _Py_UopsSymbol *res; + res = sym_new_not_null(ctx); + stack_pointer[0] = res; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + break; + } + /* _POP_JUMP_IF_FALSE is not a viable micro-op for tier 2 */ /* _POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */ @@ -1846,6 +1882,12 @@ break; } + case _CALL_LIST_APPEND: { + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); + break; + } + case _CALL_METHOD_DESCRIPTOR_O: { _Py_UopsSymbol *res; res = sym_new_not_null(ctx); |