From e7133f1bd9d830d25b52f467c8b4716622d0633a Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 14 Dec 2023 21:34:53 +0000 Subject: [PATCH 1/8] Move macros out of function to improve readability --- Python/optimizer.c | 64 +++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/Python/optimizer.c b/Python/optimizer.c index d44e733bc346fa..aed8f10fefa371 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -412,38 +412,6 @@ BRANCH_TO_GUARD[4][2] = { #define CONFIDENCE_RANGE 1000 #define CONFIDENCE_CUTOFF 333 -/* Returns 1 on success, - * 0 if it failed to produce a worthwhile trace, - * and -1 on an error. - */ -static int -translate_bytecode_to_trace( - PyCodeObject *code, - _Py_CODEUNIT *instr, - _PyUOpInstruction *trace, - int buffer_size, - _PyBloomFilter *dependencies) -{ - PyCodeObject *initial_code = code; - _Py_BloomFilter_Add(dependencies, initial_code); - _Py_CODEUNIT *initial_instr = instr; - int trace_length = 0; - int max_length = buffer_size; - struct { - PyCodeObject *code; - _Py_CODEUNIT *instr; - } trace_stack[TRACE_STACK_SIZE]; - int trace_stack_depth = 0; - int confidence = CONFIDENCE_RANGE; // Adjusted by branch instructions - -#ifdef Py_DEBUG - char *python_lltrace = Py_GETENV("PYTHON_LLTRACE"); - int lltrace = 0; - if (python_lltrace != NULL && *python_lltrace >= '0') { - lltrace = *python_lltrace - '0'; // TODO: Parse an int and all that - } -#endif - #ifdef Py_DEBUG #define DPRINTF(level, ...) \ if (lltrace >= (level)) { printf(__VA_ARGS__); } @@ -499,6 +467,38 @@ translate_bytecode_to_trace( code = trace_stack[trace_stack_depth].code; \ instr = trace_stack[trace_stack_depth].instr; +/* Returns 1 on success, + * 0 if it failed to produce a worthwhile trace, + * and -1 on an error. + */ +static int +translate_bytecode_to_trace( + PyCodeObject *code, + _Py_CODEUNIT *instr, + _PyUOpInstruction *trace, + int buffer_size, + _PyBloomFilter *dependencies) +{ + PyCodeObject *initial_code = code; + _Py_BloomFilter_Add(dependencies, initial_code); + _Py_CODEUNIT *initial_instr = instr; + int trace_length = 0; + int max_length = buffer_size; + struct { + PyCodeObject *code; + _Py_CODEUNIT *instr; + } trace_stack[TRACE_STACK_SIZE]; + int trace_stack_depth = 0; + int confidence = CONFIDENCE_RANGE; // Adjusted by branch instructions + +#ifdef Py_DEBUG + char *python_lltrace = Py_GETENV("PYTHON_LLTRACE"); + int lltrace = 0; + if (python_lltrace != NULL && *python_lltrace >= '0') { + lltrace = *python_lltrace - '0'; // TODO: Parse an int and all that + } +#endif + DPRINTF(4, "Optimizing %s (%s:%d) at byte offset %d\n", PyUnicode_AsUTF8(code->co_qualname), From cd586a67bb920fafaff905aafd647067f40dfc11 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 15 Dec 2023 01:03:22 +0000 Subject: [PATCH 2/8] Guarantee progress in executors by de-specializing the first instruction. --- Include/cpython/optimizer.h | 2 +- Python/bytecodes.c | 12 ++++++--- Python/generated_cases.c.h | 12 ++++++--- Python/optimizer.c | 52 ++++++++++++++++++++++++++----------- 4 files changed, 56 insertions(+), 22 deletions(-) diff --git a/Include/cpython/optimizer.h b/Include/cpython/optimizer.h index d521eac79d1b97..5234c65c8ad184 100644 --- a/Include/cpython/optimizer.h +++ b/Include/cpython/optimizer.h @@ -61,7 +61,7 @@ PyAPI_FUNC(_PyOptimizerObject *) PyUnstable_GetOptimizer(void); PyAPI_FUNC(_PyExecutorObject *) PyUnstable_GetExecutor(PyCodeObject *code, int offset); int -_PyOptimizer_BackEdge(struct _PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest, PyObject **stack_pointer); +_PyOptimizer_Optimize(struct _PyInterpreterFrame *frame, _Py_CODEUNIT *start, PyObject **stack_pointer); extern _PyOptimizerObject _PyOptimizer_Default; diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 19e2268046fcdc..1d7a83d1d78e42 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2317,12 +2317,18 @@ dummy_func( // Double-check that the opcode isn't instrumented or something: if (ucounter > threshold && this_instr->op.code == JUMP_BACKWARD) { OPT_STAT_INC(attempts); - int optimized = _PyOptimizer_BackEdge(frame, this_instr, next_instr, stack_pointer); + _Py_CODEUNIT *start = this_instr; + /* Back up over EXTENDED_ARGs so optimizer sees the whole instruction */ + while (oparg > 255) { + oparg >>= 8; + start--; + } + int optimized = _PyOptimizer_Optimize(frame, start, stack_pointer); ERROR_IF(optimized < 0, error); if (optimized) { // Rewind and enter the executor: - assert(this_instr->op.code == ENTER_EXECUTOR); - next_instr = this_instr; + assert(start->op.code == ENTER_EXECUTOR); + next_instr = start; this_instr[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) - 1); } else { diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index a274427a699a43..53e9723112123a 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -3277,12 +3277,18 @@ // Double-check that the opcode isn't instrumented or something: if (ucounter > threshold && this_instr->op.code == JUMP_BACKWARD) { OPT_STAT_INC(attempts); - int optimized = _PyOptimizer_BackEdge(frame, this_instr, next_instr, stack_pointer); + _Py_CODEUNIT *start = this_instr; + /* Back up over EXTENDED_ARGs so optimizer sees start of instruction */ + while (oparg > 255) { + oparg >>= 8; + start--; + } + int optimized = _PyOptimizer_Optimize(frame, start, stack_pointer); if (optimized < 0) goto error; if (optimized) { // Rewind and enter the executor: - assert(this_instr->op.code == ENTER_EXECUTOR); - next_instr = this_instr; + assert(start->op.code == ENTER_EXECUTOR); + next_instr = start; this_instr[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) - 1); } else { diff --git a/Python/optimizer.c b/Python/optimizer.c index aed8f10fefa371..4b05f3678004c6 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -156,24 +156,23 @@ PyUnstable_SetOptimizer(_PyOptimizerObject *optimizer) } int -_PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest, PyObject **stack_pointer) +_PyOptimizer_Optimize(_PyInterpreterFrame *frame, _Py_CODEUNIT *start, PyObject **stack_pointer) { - assert(src->op.code == JUMP_BACKWARD); PyCodeObject *code = (PyCodeObject *)frame->f_executable; assert(PyCode_Check(code)); PyInterpreterState *interp = _PyInterpreterState_GET(); - if (!has_space_for_executor(code, src)) { + if (!has_space_for_executor(code, start)) { return 0; } _PyOptimizerObject *opt = interp->optimizer; _PyExecutorObject *executor = NULL; /* Start optimizing at the destination to guarantee forward progress */ - int err = opt->optimize(opt, code, dest, &executor, (int)(stack_pointer - _PyFrame_Stackbase(frame))); + int err = opt->optimize(opt, code, start, &executor, (int)(stack_pointer - _PyFrame_Stackbase(frame))); if (err <= 0) { assert(executor == NULL); return err; } - int index = get_index_for_executor(code, src); + int index = get_index_for_executor(code, start); if (index < 0) { /* Out of memory. Don't raise and assume that the * error will show up elsewhere. @@ -184,7 +183,7 @@ _PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNI Py_DECREF(executor); return 0; } - insert_executor(code, src, index, executor); + insert_executor(code, start, index, executor); Py_DECREF(executor); return 1; } @@ -266,6 +265,9 @@ counter_optimize( int Py_UNUSED(curr_stackentries) ) { + if (instr->op.code != JUMP_BACKWARD) { + PyErr_Format(PyExc_ValueError, "Counter optimizer can only handle backward edges"); + } _PyCounterExecutorObject *executor = (_PyCounterExecutorObject *)_PyObject_New(&_PyCounterExecutor_Type); if (executor == NULL) { return -1; @@ -273,7 +275,7 @@ counter_optimize( executor->executor.execute = counter_execute; Py_INCREF(self); executor->optimizer = (_PyCounterOptimizerObject *)self; - executor->next_instr = instr; + executor->next_instr = instr + 2 - instr->op.arg; *exec_ptr = (_PyExecutorObject *)executor; _PyBloomFilter empty; _Py_BloomFilter_Init(&empty); @@ -479,6 +481,7 @@ translate_bytecode_to_trace( int buffer_size, _PyBloomFilter *dependencies) { + bool progress_needed = true; PyCodeObject *initial_code = code; _Py_BloomFilter_Add(dependencies, initial_code); _Py_CODEUNIT *initial_instr = instr; @@ -506,6 +509,7 @@ translate_bytecode_to_trace( code->co_firstlineno, 2 * INSTR_IP(initial_instr, code)); uint32_t target = 0; + top: // Jump here after _PUSH_FRAME or likely branches for (;;) { target = INSTR_IP(instr, code); @@ -536,6 +540,24 @@ translate_bytecode_to_trace( oparg = (oparg & 0xffffff00) | executor->vm_data.oparg; } + if (progress_needed) { + progress_needed = false; + /* Special case the first instruction, so that we can guarantee + * forward progress */ + if (opcode == JUMP_BACKWARD) { + instr += 2 - oparg; + continue; + } + else { + if (OPCODE_HAS_DEOPT(opcode)) { + opcode = _PyOpcode_Deopt[opcode]; + } + if (OPCODE_HAS_DEOPT(opcode)) { + return 0; + } + } + } + switch (opcode) { case POP_JUMP_IF_NONE: case POP_JUMP_IF_NOT_NONE: @@ -575,14 +597,8 @@ translate_bytecode_to_trace( case JUMP_BACKWARD: { - if (instr + 2 - oparg == initial_instr && code == initial_code) { - RESERVE(1); - ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0); - } - else { - OPT_STAT_INC(inner_loop); - DPRINTF(2, "JUMP_BACKWARD not to top ends trace\n"); - } + OPT_STAT_INC(inner_loop); + DPRINTF(2, "JUMP_BACKWARD not to top ends trace\n"); goto done; } @@ -736,6 +752,12 @@ translate_bytecode_to_trace( instr++; // Add cache size for opcode instr += _PyOpcode_Caches[_PyOpcode_Deopt[opcode]]; + progress_needed = false; + /* Stop if we have reached the start */ + if (instr == initial_instr) { + RESERVE(1); + ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0); + } } // End for (;;) done: From 1501bcaab48a7b35f95505517accd0a59d1badd8 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 8 Jan 2024 00:36:09 +0000 Subject: [PATCH 3/8] Fix 'counter' optimizer --- Python/optimizer.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Python/optimizer.c b/Python/optimizer.c index eb9a8af37a7ef8..a414ba95b21f03 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -271,8 +271,14 @@ counter_optimize( int Py_UNUSED(curr_stackentries) ) { + int oparg = instr->op.arg; + while (instr->op.code == EXTENDED_ARG) { + instr++; + oparg = (oparg << 8) | instr->op.arg; + } if (instr->op.code != JUMP_BACKWARD) { PyErr_Format(PyExc_ValueError, "Counter optimizer can only handle backward edges"); + return -1; } _PyCounterExecutorObject *executor = (_PyCounterExecutorObject *)_PyObject_New(&_PyCounterExecutor_Type); if (executor == NULL) { @@ -281,7 +287,7 @@ counter_optimize( executor->executor.execute = counter_execute; Py_INCREF(self); executor->optimizer = (_PyCounterOptimizerObject *)self; - executor->next_instr = instr + 2 - instr->op.arg; + executor->next_instr = instr + 2 - oparg; *exec_ptr = (_PyExecutorObject *)executor; _PyBloomFilter empty; _Py_BloomFilter_Init(&empty); @@ -548,7 +554,7 @@ translate_bytecode_to_trace( /* Special case the first instruction, so that we can guarantee * forward progress */ if (opcode == JUMP_BACKWARD) { - instr += 2 - oparg; + instr += 2 - (int32_t)oparg; continue; } else { From 4960065092386956da149201f5f062f5c674be0d Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 8 Jan 2024 05:35:21 +0000 Subject: [PATCH 4/8] Remove redundant code --- Python/optimizer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Python/optimizer.c b/Python/optimizer.c index a414ba95b21f03..4fda19fd317236 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -754,7 +754,6 @@ translate_bytecode_to_trace( instr++; // Add cache size for opcode instr += _PyOpcode_Caches[_PyOpcode_Deopt[opcode]]; - progress_needed = false; /* Stop if we have reached the start */ if (instr == initial_instr) { RESERVE(1); From e8300e2e3b19ff3c9e5e1db26f2d6af841bc8201 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 8 Jan 2024 05:47:35 +0000 Subject: [PATCH 5/8] Add news --- .../2024-01-08-05-36-59.gh-issue-113853.lm-6_a.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-01-08-05-36-59.gh-issue-113853.lm-6_a.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-08-05-36-59.gh-issue-113853.lm-6_a.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-08-05-36-59.gh-issue-113853.lm-6_a.rst new file mode 100644 index 00000000000000..d4f0a764153579 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-01-08-05-36-59.gh-issue-113853.lm-6_a.rst @@ -0,0 +1,2 @@ +Guarantee that all executors make progress. This then guarantees that tier 2 +execution always makes progress. From f9e1464a38c17baeae4432b4d8034026c7e45efa Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 10 Jan 2024 11:55:33 +0000 Subject: [PATCH 6/8] Address review comments --- Python/bytecodes.c | 6 ++-- Python/optimizer.c | 83 +++++++++++++++++++++++----------------------- 2 files changed, 46 insertions(+), 43 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 2355298e3a9c61..406900fa13f580 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2384,10 +2384,12 @@ dummy_func( stack_pointer = _PyFrame_GetStackPointer(frame); } else { - code->co_executors->executors[oparg & 255] = NULL; + /* ENTER_EXECUTOR will be the first code unit of the instruction */ + assert(oparg < 256); + code->co_executors->executors[oparg] = NULL; opcode = this_instr->op.code = executor->vm_data.opcode; this_instr->op.arg = executor->vm_data.oparg; - oparg = (oparg & (~255)) | executor->vm_data.oparg; + oparg = executor->vm_data.oparg; Py_DECREF(executor); next_instr = this_instr; DISPATCH_GOTO(); diff --git a/Python/optimizer.c b/Python/optimizer.c index 4fda19fd317236..90b3a991a07764 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -172,7 +172,6 @@ _PyOptimizer_Optimize(_PyInterpreterFrame *frame, _Py_CODEUNIT *start, PyObject } _PyOptimizerObject *opt = interp->optimizer; _PyExecutorObject *executor = NULL; - /* Start optimizing at the destination to guarantee forward progress */ int err = opt->optimize(opt, code, start, &executor, (int)(stack_pointer - _PyFrame_Stackbase(frame))); if (err <= 0) { assert(executor == NULL); @@ -277,8 +276,8 @@ counter_optimize( oparg = (oparg << 8) | instr->op.arg; } if (instr->op.code != JUMP_BACKWARD) { - PyErr_Format(PyExc_ValueError, "Counter optimizer can only handle backward edges"); - return -1; + /* Counter optimizer can only handle backward edges */ + return 0; } _PyCounterExecutorObject *executor = (_PyCounterExecutorObject *)_PyObject_New(&_PyCounterExecutor_Type); if (executor == NULL) { @@ -287,7 +286,7 @@ counter_optimize( executor->executor.execute = counter_execute; Py_INCREF(self); executor->optimizer = (_PyCounterOptimizerObject *)self; - executor->next_instr = instr + 2 - oparg; + executor->next_instr = instr + 1 + _PyOpcode_Caches[JUMP_BACKWARD] - oparg; *exec_ptr = (_PyExecutorObject *)executor; _PyBloomFilter empty; _Py_BloomFilter_Init(&empty); @@ -530,6 +529,15 @@ translate_bytecode_to_trace( uint32_t oparg = instr->op.arg; uint32_t extended = 0; + + if (opcode == ENTER_EXECUTOR) { + _PyExecutorObject *executor = + (_PyExecutorObject *)code->co_executors->executors[oparg]; + opcode = executor->vm_data.opcode; + DPRINTF(2, " * ENTER_EXECUTOR -> %s\n", _PyOpcode_OpName[opcode]); + oparg = executor->vm_data.oparg; + } + if (opcode == EXTENDED_ARG) { instr++; extended = 1; @@ -540,30 +548,22 @@ translate_bytecode_to_trace( goto done; } } + assert(opcode != ENTER_EXECUTOR && opcode != EXTENDED_ARG); - if (opcode == ENTER_EXECUTOR) { - _PyExecutorObject *executor = - (_PyExecutorObject *)code->co_executors->executors[oparg&255]; - opcode = executor->vm_data.opcode; - DPRINTF(2, " * ENTER_EXECUTOR -> %s\n", _PyOpcode_OpName[opcode]); - oparg = (oparg & 0xffffff00) | executor->vm_data.oparg; - } - + /* Special case the first instruction, + * so that we can guarantee forward progress */ if (progress_needed) { progress_needed = false; - /* Special case the first instruction, so that we can guarantee - * forward progress */ - if (opcode == JUMP_BACKWARD) { - instr += 2 - (int32_t)oparg; + if (opcode == JUMP_BACKWARD || opcode == JUMP_BACKWARD_NO_INTERRUPT) { + instr += 1 + _PyOpcode_Caches[opcode] - (int32_t)oparg; + initial_instr = instr; continue; } else { if (OPCODE_HAS_DEOPT(opcode)) { opcode = _PyOpcode_Deopt[opcode]; } - if (OPCODE_HAS_DEOPT(opcode)) { - return 0; - } + assert(!OPCODE_HAS_DEOPT(opcode)); } } @@ -607,8 +607,16 @@ translate_bytecode_to_trace( case JUMP_BACKWARD: case JUMP_BACKWARD_NO_INTERRUPT: { - OPT_STAT_INC(inner_loop); - DPRINTF(2, "JUMP_BACKWARD not to top ends trace\n"); + _Py_CODEUNIT *target = instr + 1 + _PyOpcode_Caches[opcode] - (int)oparg; + if (target == initial_instr) { + /* We have looped round to the start */ + RESERVE(1); + ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0); + } + else { + OPT_STAT_INC(inner_loop); + DPRINTF(2, "JUMP_BACKWARD not to top ends trace\n"); + } goto done; } @@ -754,11 +762,6 @@ translate_bytecode_to_trace( instr++; // Add cache size for opcode instr += _PyOpcode_Caches[_PyOpcode_Deopt[opcode]]; - /* Stop if we have reached the start */ - if (instr == initial_instr) { - RESERVE(1); - ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0); - } } // End for (;;) done: @@ -767,19 +770,7 @@ translate_bytecode_to_trace( } assert(code == initial_code); // Skip short traces like _SET_IP, LOAD_FAST, _SET_IP, _EXIT_TRACE - if (trace_length > 4) { - ADD_TO_TRACE(_EXIT_TRACE, 0, 0, target); - DPRINTF(1, - "Created a trace for %s (%s:%d) at byte offset %d -- length %d\n", - PyUnicode_AsUTF8(code->co_qualname), - PyUnicode_AsUTF8(code->co_filename), - code->co_firstlineno, - 2 * INSTR_IP(initial_instr, code), - trace_length); - OPT_HIST(trace_length + buffer_size - max_length, trace_length_hist); - return 1; - } - else { + if (progress_needed || trace_length < 5) { OPT_STAT_INC(trace_too_short); DPRINTF(4, "No trace for %s (%s:%d) at byte offset %d\n", @@ -787,15 +778,25 @@ translate_bytecode_to_trace( PyUnicode_AsUTF8(code->co_filename), code->co_firstlineno, 2 * INSTR_IP(initial_instr, code)); + return 0; } - return 0; + ADD_TO_TRACE(_EXIT_TRACE, 0, 0, target); + DPRINTF(1, + "Created a trace for %s (%s:%d) at byte offset %d -- length %d\n", + PyUnicode_AsUTF8(code->co_qualname), + PyUnicode_AsUTF8(code->co_filename), + code->co_firstlineno, + 2 * INSTR_IP(initial_instr, code), + trace_length); + OPT_HIST(trace_length + buffer_size - max_length, trace_length_hist); + return 1; +} #undef RESERVE #undef RESERVE_RAW #undef INSTR_IP #undef ADD_TO_TRACE #undef DPRINTF -} #define UNSET_BIT(array, bit) (array[(bit)>>5] &= ~(1<<((bit)&31))) #define SET_BIT(array, bit) (array[(bit)>>5] |= (1<<((bit)&31))) From 93efad460db1a7c7915a18e3c14cd13088a1fe94 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 10 Jan 2024 22:11:19 +0000 Subject: [PATCH 7/8] Address review comment --- Python/optimizer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/optimizer.c b/Python/optimizer.c index cf7657f006a79a..227d6be0092419 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -421,8 +421,8 @@ translate_bytecode_to_trace( uint32_t oparg = instr->op.arg; uint32_t extended = 0; - if (opcode == ENTER_EXECUTOR) { + assert(oparg < 256); _PyExecutorObject *executor = (_PyExecutorObject *)code->co_executors->executors[oparg]; opcode = executor->vm_data.opcode; From 902fd4b76b24438a81e20212730f46836218989d Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 10 Jan 2024 22:12:56 +0000 Subject: [PATCH 8/8] Regen cases --- Python/generated_cases.c.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index c64565eec95632..1e995b62a72fcf 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2384,10 +2384,12 @@ GOTO_TIER_TWO(); } else { - code->co_executors->executors[oparg & 255] = NULL; + /* ENTER_EXECUTOR will be the first code unit of the instruction */ + assert(oparg < 256); + code->co_executors->executors[oparg] = NULL; opcode = this_instr->op.code = executor->vm_data.opcode; this_instr->op.arg = executor->vm_data.oparg; - oparg = (oparg & (~255)) | executor->vm_data.oparg; + oparg = executor->vm_data.oparg; Py_DECREF(executor); next_instr = this_instr; DISPATCH_GOTO();