mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00:00
GH-122390: Replace _Py_GetbaseOpcode
with _Py_GetBaseCodeUnit
(GH-122942)
This commit is contained in:
parent
fe23f8ed97
commit
7a65439b93
16 changed files with 299 additions and 326 deletions
|
@ -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;
|
||||
|
|
4
Python/opcode_targets.h
generated
4
Python/opcode_targets.h
generated
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue