diff options
author | Mark Shannon <mark@hotpy.org> | 2024-08-13 13:22:57 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-13 13:22:57 (GMT) |
commit | 7a65439b93d6ee4d4e32757b55909b882f9a2056 (patch) | |
tree | 0df6d926c920125cf98e02ab7d8c0612565b055e /Python | |
parent | fe23f8ed970425828de20fb48750fa89da914886 (diff) | |
download | cpython-7a65439b93d6ee4d4e32757b55909b882f9a2056.zip cpython-7a65439b93d6ee4d4e32757b55909b882f9a2056.tar.gz cpython-7a65439b93d6ee4d4e32757b55909b882f9a2056.tar.bz2 |
GH-122390: Replace `_Py_GetbaseOpcode` with `_Py_GetBaseCodeUnit` (GH-122942)
Diffstat (limited to 'Python')
-rw-r--r-- | Python/instrumentation.c | 69 | ||||
-rw-r--r-- | Python/opcode_targets.h | 4 | ||||
-rw-r--r-- | Python/optimizer.c | 19 | ||||
-rw-r--r-- | Python/specialize.c | 6 |
4 files changed, 52 insertions, 46 deletions
diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 3481b5d..5e51a9c 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -165,6 +165,7 @@ is_instrumented(int opcode) { assert(opcode != 0); assert(opcode != RESERVED); + assert(opcode != ENTER_EXECUTOR); return opcode >= MIN_INSTRUMENTED_OPCODE; } @@ -330,13 +331,12 @@ _PyInstruction_GetLength(PyCodeObject *code, int offset) opcode = _PyOpcode_Deopt[opcode]; } assert(opcode != 0); - assert(!is_instrumented(opcode)); if (opcode == ENTER_EXECUTOR) { int exec_index = _PyCode_CODE(code)[offset].op.arg; _PyExecutorObject *exec = code->co_executors->executors[exec_index]; opcode = _PyOpcode_Deopt[exec->vm_data.opcode]; - } + assert(!is_instrumented(opcode)); assert(opcode != ENTER_EXECUTOR); assert(opcode == _PyOpcode_Deopt[opcode]); return 1 + _PyOpcode_Caches[opcode]; @@ -507,7 +507,7 @@ sanity_check_instrumentation(PyCodeObject *code) for (int i = 0; i < code_len;) { _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i]; int opcode = instr->op.code; - int base_opcode = _Py_GetBaseOpcode(code, i); + int base_opcode = _Py_GetBaseCodeUnit(code, offset).op.code; CHECK(valid_opcode(opcode)); CHECK(valid_opcode(base_opcode)); if (opcode == INSTRUMENTED_INSTRUCTION) { @@ -579,10 +579,26 @@ sanity_check_instrumentation(PyCodeObject *code) #endif -/* Get the underlying opcode, stripping instrumentation */ -int _Py_GetBaseOpcode(PyCodeObject *code, int i) +/* Get the underlying code unit, stripping instrumentation and ENTER_EXECUTOR */ +_Py_CODEUNIT +_Py_GetBaseCodeUnit(PyCodeObject *code, int i) { - int opcode = _PyCode_CODE(code)[i].op.code; + _Py_CODEUNIT inst = _PyCode_CODE(code)[i]; + int opcode = inst.op.code; + if (opcode < MIN_INSTRUMENTED_OPCODE) { + inst.op.code = _PyOpcode_Deopt[opcode]; + assert(inst.op.code <= RESUME); + return inst; + } + if (opcode == ENTER_EXECUTOR) { + _PyExecutorObject *exec = code->co_executors->executors[inst.op.arg]; + opcode = _PyOpcode_Deopt[exec->vm_data.opcode]; + inst.op.code = opcode; + assert(opcode <= RESUME); + inst.op.arg = exec->vm_data.oparg; + assert(inst.op.code <= RESUME); + return inst; + } if (opcode == INSTRUMENTED_LINE) { opcode = code->_co_monitoring->lines[i].original_opcode; } @@ -593,9 +609,13 @@ int _Py_GetBaseOpcode(PyCodeObject *code, int i) CHECK(opcode != INSTRUMENTED_LINE); int deinstrumented = DE_INSTRUMENT[opcode]; if (deinstrumented) { - return deinstrumented; + inst.op.code = deinstrumented; } - return _PyOpcode_Deopt[opcode]; + else { + inst.op.code = _PyOpcode_Deopt[opcode]; + } + assert(inst.op.code < MIN_SPECIALIZED_OPCODE); + return inst; } static void @@ -756,7 +776,7 @@ remove_tools(PyCodeObject * code, int offset, int event, int tools) assert(event != PY_MONITORING_EVENT_LINE); assert(event != PY_MONITORING_EVENT_INSTRUCTION); assert(PY_MONITORING_IS_INSTRUMENTED_EVENT(event)); - assert(opcode_has_event(_Py_GetBaseOpcode(code, offset))); + assert(opcode_has_event(_Py_GetBaseCodeUnit(code, offset).op.code)); _PyCoMonitoringData *monitoring = code->_co_monitoring; if (monitoring && monitoring->tools) { monitoring->tools[offset] &= ~tools; @@ -1479,7 +1499,7 @@ initialize_lines(PyCodeObject *code) } int current_line = -1; for (int i = code->_co_firsttraceable; i < code_len; ) { - int opcode = _Py_GetBaseOpcode(code, i); + int opcode = _Py_GetBaseCodeUnit(code, i).op.code; int line = _PyCode_CheckLineNumber(i*(int)sizeof(_Py_CODEUNIT), &range); line_data[i].line_delta = compute_line_delta(code, i, line); int length = _PyInstruction_GetLength(code, i); @@ -1522,14 +1542,16 @@ initialize_lines(PyCodeObject *code) i += length; } for (int i = code->_co_firsttraceable; i < code_len; ) { - int opcode = _Py_GetBaseOpcode(code, i); + _Py_CODEUNIT inst =_Py_GetBaseCodeUnit(code, i); + int opcode = inst.op.code; int oparg = 0; while (opcode == EXTENDED_ARG) { - oparg = (oparg << 8) | _PyCode_CODE(code)[i].op.arg; + oparg = (oparg << 8) | inst.op.arg; i++; - opcode = _Py_GetBaseOpcode(code, i); + inst =_Py_GetBaseCodeUnit(code, i); + opcode = inst.op.code; } - oparg = (oparg << 8) | _PyCode_CODE(code)[i].op.arg; + oparg = (oparg << 8) | inst.op.arg; i += _PyInstruction_GetLength(code, i); int target = -1; switch (opcode) { @@ -1560,7 +1582,7 @@ initialize_lines(PyCodeObject *code) } assert(target >= 0); if (line_data[target].line_delta != NO_LINE) { - line_data[target].original_opcode = _Py_GetBaseOpcode(code, target); + line_data[target].original_opcode = _Py_GetBaseCodeUnit(code, target).op.code; if (line_data[target].line_delta == COMPUTED_LINE_LINENO_CHANGE) { // If the line is a jump target, we are not sure if the line // number changes, so we set it to COMPUTED_LINE. @@ -1582,7 +1604,7 @@ initialize_lines(PyCodeObject *code) assert(handler >= 0 && handler < code_len); int depth_and_lasti; scan = parse_varint(scan, &depth_and_lasti); - int original_opcode = _Py_GetBaseOpcode(code, handler); + int original_opcode = _Py_GetBaseCodeUnit(code, handler).op.code; /* Skip if not the start of a line. * END_ASYNC_FOR is a bit special as it marks the end of * an `async for` loop, which should not generate its own @@ -1740,15 +1762,14 @@ force_instrument_lock_held(PyCodeObject *code, PyInterpreterState *interp) } /* Insert instrumentation */ for (int i = code->_co_firsttraceable; i < code_len; i+= _PyInstruction_GetLength(code, i)) { - _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i]; - CHECK(instr->op.code != 0); - assert(instr->op.code != ENTER_EXECUTOR); - int base_opcode = _Py_GetBaseOpcode(code, i); - assert(base_opcode != ENTER_EXECUTOR); + assert(_PyCode_CODE(code)[i].op.code != ENTER_EXECUTOR); + _Py_CODEUNIT instr = _Py_GetBaseCodeUnit(code, i); + CHECK(instr.op.code != 0); + int base_opcode = instr.op.code; if (opcode_has_event(base_opcode)) { int8_t event; if (base_opcode == RESUME) { - event = instr->op.arg > 0; + event = instr.op.arg > 0; } else { event = EVENT_FOR_OPCODE[base_opcode]; @@ -1781,7 +1802,7 @@ force_instrument_lock_held(PyCodeObject *code, PyInterpreterState *interp) } if (removed_per_instruction_tools) { for (int i = code->_co_firsttraceable; i < code_len;) { - int opcode = _Py_GetBaseOpcode(code, i); + int opcode = _Py_GetBaseCodeUnit(code, i).op.code; if (opcode == RESUME || opcode == END_FOR) { i += _PyInstruction_GetLength(code, i); continue; @@ -1808,7 +1829,7 @@ force_instrument_lock_held(PyCodeObject *code, PyInterpreterState *interp) } if (new_per_instruction_tools) { for (int i = code->_co_firsttraceable; i < code_len;) { - int opcode = _Py_GetBaseOpcode(code, i); + int opcode = _Py_GetBaseCodeUnit(code, i).op.code; if (opcode == RESUME || opcode == END_FOR) { i += _PyInstruction_GetLength(code, i); continue; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 6b5f231..db92b02 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -65,7 +65,6 @@ static void *opcode_targets[256] = { &&TARGET_DELETE_NAME, &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, - &&TARGET_ENTER_EXECUTOR, &&TARGET_EXTENDED_ARG, &&TARGET_FOR_ITER, &&TARGET_GET_AWAITABLE, @@ -148,6 +147,7 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_RESUME, &&TARGET_BINARY_OP_ADD_FLOAT, &&TARGET_BINARY_OP_ADD_INT, @@ -254,5 +254,5 @@ static void *opcode_targets[256] = { &&TARGET_INSTRUMENTED_YIELD_VALUE, &&TARGET_INSTRUMENTED_CALL, &&TARGET_INSTRUMENTED_LINE, - &&_unknown_opcode, + &&TARGET_ENTER_EXECUTOR, }; diff --git a/Python/optimizer.c b/Python/optimizer.c index 1758329..dbd5467 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -22,20 +22,6 @@ #define MAX_EXECUTORS_SIZE 256 -#ifdef Py_DEBUG -static int -base_opcode(PyCodeObject *code, int offset) -{ - int opcode = _Py_GetBaseOpcode(code, offset); - if (opcode == ENTER_EXECUTOR) { - int oparg = _PyCode_CODE(code)[offset].op.arg; - _PyExecutorObject *ex = code->co_executors->executors[oparg]; - return ex->vm_data.opcode; - } - return opcode; -} -#endif - static bool has_space_for_executor(PyCodeObject *code, _Py_CODEUNIT *instr) { @@ -771,9 +757,8 @@ translate_bytecode_to_trace( { uint32_t next_inst = target + 1 + INLINE_CACHE_ENTRIES_FOR_ITER + (oparg > 255); uint32_t jump_target = next_inst + oparg; - assert(base_opcode(code, jump_target) == END_FOR || - base_opcode(code, jump_target) == INSTRUMENTED_END_FOR); - assert(base_opcode(code, jump_target+1) == POP_TOP); + assert(_Py_GetBaseCodeUnit(code, jump_target).op.code == END_FOR); + assert(_Py_GetBaseCodeUnit(code, jump_target+1).op.code == POP_TOP); } #endif break; diff --git a/Python/specialize.c b/Python/specialize.c index c354a90..4a22738 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -428,9 +428,9 @@ _PyCode_Quicken(PyCodeObject *code) #if ENABLE_SPECIALIZATION int opcode = 0; _Py_CODEUNIT *instructions = _PyCode_CODE(code); - for (int i = 0; i < Py_SIZE(code); i++) { - opcode = _Py_GetBaseOpcode(code, i); - assert(opcode < MIN_INSTRUMENTED_OPCODE); + /* The last code unit cannot have a cache, so we don't need to check it */ + for (int i = 0; i < Py_SIZE(code)-1; i++) { + opcode = instructions[i].op.code; int caches = _PyOpcode_Caches[opcode]; if (caches) { // The initial value depends on the opcode |