summaryrefslogtreecommitdiffstats
path: root/Python/bytecodes.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/bytecodes.c')
-rw-r--r--Python/bytecodes.c60
1 files changed, 48 insertions, 12 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 4855049..fe3d613 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -1109,6 +1109,10 @@ dummy_func(
_PyFrame_StackPush(frame, retval);
/* We don't know which of these is relevant here, so keep them equal */
assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER);
+ assert(_PyOpcode_Deopt[frame->instr_ptr->op.code] == SEND ||
+ _PyOpcode_Deopt[frame->instr_ptr->op.code] == FOR_ITER ||
+ _PyOpcode_Deopt[frame->instr_ptr->op.code] == INTERPRETER_EXIT ||
+ _PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR);
LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND);
goto resume_frame;
}
@@ -2759,24 +2763,26 @@ dummy_func(
_ITER_JUMP_RANGE +
_ITER_NEXT_RANGE;
- inst(FOR_ITER_GEN, (unused/1, iter -- iter, unused)) {
- DEOPT_IF(tstate->interp->eval_frame);
+ op(_FOR_ITER_GEN_FRAME, (iter -- iter, gen_frame: _PyInterpreterFrame*)) {
PyGenObject *gen = (PyGenObject *)iter;
DEOPT_IF(Py_TYPE(gen) != &PyGen_Type);
DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING);
STAT_INC(FOR_ITER, hit);
- _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;
+ gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;
_PyFrame_StackPush(gen_frame, Py_None);
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[oparg].op.code == END_FOR ||
- next_instr[oparg].op.code == INSTRUMENTED_END_FOR);
- assert(next_instr - this_instr + oparg <= UINT16_MAX);
- frame->return_offset = (uint16_t)(next_instr - this_instr + oparg);
- DISPATCH_INLINED(gen_frame);
+ // oparg is the return offset from the next instruction.
+ frame->return_offset = (uint16_t)(1 + INLINE_CACHE_ENTRIES_FOR_ITER + oparg);
}
+ macro(FOR_ITER_GEN) =
+ unused/1 +
+ _CHECK_PEP_523 +
+ _FOR_ITER_GEN_FRAME +
+ _PUSH_FRAME;
+
inst(BEFORE_ASYNC_WITH, (mgr -- exit, res)) {
PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__));
if (enter == NULL) {
@@ -3166,10 +3172,7 @@ dummy_func(
}
}
- // The 'unused' output effect represents the return value
- // (which will be pushed when the frame returns).
- // It is needed so CALL_PY_EXACT_ARGS matches its family.
- op(_PUSH_FRAME, (new_frame: _PyInterpreterFrame* -- unused if (0))) {
+ op(_PUSH_FRAME, (new_frame: _PyInterpreterFrame* -- )) {
// 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);
@@ -4189,6 +4192,38 @@ dummy_func(
GOTO_TIER_TWO(executor);
}
+ tier2 op(_DYNAMIC_EXIT, (--)) {
+ tstate->previous_executor = (PyObject *)current_executor;
+ _PyExitData *exit = (_PyExitData *)&current_executor->exits[oparg];
+ _Py_CODEUNIT *target = frame->instr_ptr;
+ _PyExecutorObject *executor;
+ if (target->op.code == ENTER_EXECUTOR) {
+ PyCodeObject *code = (PyCodeObject *)frame->f_executable;
+ executor = code->co_executors->executors[target->op.arg];
+ Py_INCREF(executor);
+ }
+ else {
+ if (!backoff_counter_triggers(exit->temperature)) {
+ exit->temperature = advance_backoff_counter(exit->temperature);
+ GOTO_TIER_ONE(target);
+ }
+ int optimized = _PyOptimizer_Optimize(frame, target, stack_pointer, &executor);
+ if (optimized <= 0) {
+ exit->temperature = restart_backoff_counter(exit->temperature);
+ if (optimized < 0) {
+ Py_DECREF(current_executor);
+ tstate->previous_executor = Py_None;
+ GOTO_UNWIND();
+ }
+ GOTO_TIER_ONE(target);
+ }
+ else {
+ exit->temperature = initial_temperature_backoff_counter();
+ }
+ }
+ GOTO_TIER_TWO(executor);
+ }
+
tier2 op(_START_EXECUTOR, (executor/4 --)) {
Py_DECREF(tstate->previous_executor);
tstate->previous_executor = NULL;
@@ -4222,6 +4257,7 @@ dummy_func(
GOTO_UNWIND();
}
+
// END BYTECODES //
}