GH-122390: Replace _Py_GetbaseOpcode with _Py_GetBaseCodeUnit (GH-122942)

This commit is contained in:
Mark Shannon 2024-08-13 14:22:57 +01:00 committed by GitHub
parent fe23f8ed97
commit 7a65439b93
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 299 additions and 326 deletions

View file

@ -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;