[3.14] gh-148037: remove critical section from PyCode_Addr2Line (GH… (#148353)

[3.14] gh-148037: remove critical section from `PyCode_Addr2Line` (GH-148103)
(cherry picked from commit d3b7b93cbb)
This commit is contained in:
Kumar Aditya 2026-04-10 23:59:38 +05:30 committed by GitHub
parent 288cbacfb9
commit f36da66c71
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 33 additions and 42 deletions

View file

@ -1285,13 +1285,10 @@ _Py_call_instrumentation_exc2(
}
int
_Py_Instrumentation_GetLine(PyCodeObject *code, int index)
_Py_Instrumentation_GetLine(PyCodeObject *code, _PyCoLineInstrumentationData *line_data, int index)
{
_PyCoMonitoringData *monitoring = code->_co_monitoring;
assert(monitoring != NULL);
assert(monitoring->lines != NULL);
assert(line_data != NULL);
assert(index < Py_SIZE(code));
_PyCoLineInstrumentationData *line_data = monitoring->lines;
int line_delta = get_line_delta(line_data, index);
int line = compute_line(code, line_delta);
return line;
@ -1309,11 +1306,11 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame,
_PyCoMonitoringData *monitoring = code->_co_monitoring;
_PyCoLineInstrumentationData *line_data = monitoring->lines;
PyInterpreterState *interp = tstate->interp;
int line = _Py_Instrumentation_GetLine(code, i);
int line = _Py_Instrumentation_GetLine(code, line_data, i);
assert(line >= 0);
assert(prev != NULL);
int prev_index = (int)(prev - bytecode);
int prev_line = _Py_Instrumentation_GetLine(code, prev_index);
int prev_line = _Py_Instrumentation_GetLine(code, line_data, prev_index);
if (prev_line == line) {
int prev_opcode = bytecode[prev_index].op.code;
/* RESUME and INSTRUMENTED_RESUME are needed for the operation of
@ -1510,11 +1507,9 @@ initialize_tools(PyCodeObject *code)
}
static void
initialize_lines(PyCodeObject *code, int bytes_per_entry)
initialize_lines(_PyCoLineInstrumentationData *line_data, PyCodeObject *code, int bytes_per_entry)
{
ASSERT_WORLD_STOPPED_OR_LOCKED(code);
_PyCoLineInstrumentationData *line_data = code->_co_monitoring->lines;
assert(line_data != NULL);
line_data->bytes_per_entry = bytes_per_entry;
int code_len = (int)Py_SIZE(code);
@ -1655,18 +1650,19 @@ allocate_instrumentation_data(PyCodeObject *code)
ASSERT_WORLD_STOPPED_OR_LOCKED(code);
if (code->_co_monitoring == NULL) {
code->_co_monitoring = PyMem_Malloc(sizeof(_PyCoMonitoringData));
if (code->_co_monitoring == NULL) {
_PyCoMonitoringData *monitoring = PyMem_Malloc(sizeof(_PyCoMonitoringData));
if (monitoring == NULL) {
PyErr_NoMemory();
return -1;
}
code->_co_monitoring->local_monitors = (_Py_LocalMonitors){ 0 };
code->_co_monitoring->active_monitors = (_Py_LocalMonitors){ 0 };
code->_co_monitoring->tools = NULL;
code->_co_monitoring->lines = NULL;
code->_co_monitoring->line_tools = NULL;
code->_co_monitoring->per_instruction_opcodes = NULL;
code->_co_monitoring->per_instruction_tools = NULL;
monitoring->local_monitors = (_Py_LocalMonitors){ 0 };
monitoring->active_monitors = (_Py_LocalMonitors){ 0 };
monitoring->tools = NULL;
monitoring->lines = NULL;
monitoring->line_tools = NULL;
monitoring->per_instruction_opcodes = NULL;
monitoring->per_instruction_tools = NULL;
_Py_atomic_store_ptr_release(&code->_co_monitoring, monitoring);
}
return 0;
}
@ -1731,12 +1727,13 @@ update_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp)
else {
bytes_per_entry = 5;
}
code->_co_monitoring->lines = PyMem_Malloc(1 + code_len * bytes_per_entry);
if (code->_co_monitoring->lines == NULL) {
_PyCoLineInstrumentationData *lines = PyMem_Malloc(1 + code_len * bytes_per_entry);
if (lines == NULL) {
PyErr_NoMemory();
return -1;
}
initialize_lines(code, bytes_per_entry);
initialize_lines(lines, code, bytes_per_entry);
_Py_atomic_store_ptr_release(&code->_co_monitoring->lines, lines);
}
if (multitools && code->_co_monitoring->line_tools == NULL) {
code->_co_monitoring->line_tools = PyMem_Malloc(code_len);

View file

@ -398,8 +398,8 @@ sys_trace_jump_func(
assert(PyCode_Check(code));
/* We can call _Py_Instrumentation_GetLine because we always set
* line events for tracing */
int to_line = _Py_Instrumentation_GetLine(code, to);
int from_line = _Py_Instrumentation_GetLine(code, from);
int to_line = _Py_Instrumentation_GetLine(code, code->_co_monitoring->lines, to);
int from_line = _Py_Instrumentation_GetLine(code, code->_co_monitoring->lines, from);
if (to_line != from_line) {
/* Will be handled by target INSTRUMENTED_LINE */
return &_PyInstrumentation_DISABLE;