mirror of
https://github.com/python/cpython.git
synced 2026-05-06 12:49:07 -04:00
gh-148037: remove critical section from PyCode_Addr2Line (#148103)
This commit is contained in:
@@ -64,9 +64,6 @@ PyAPI_FUNC(void)
|
||||
_Py_call_instrumentation_exc2(PyThreadState *tstate, int event,
|
||||
_PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1);
|
||||
|
||||
extern int
|
||||
_Py_Instrumentation_GetLine(PyCodeObject *code, int index);
|
||||
|
||||
PyAPI_DATA(PyObject) _PyInstrumentation_MISSING;
|
||||
PyAPI_DATA(PyObject) _PyInstrumentation_DISABLE;
|
||||
|
||||
@@ -122,6 +119,8 @@ typedef struct _PyCoMonitoringData {
|
||||
uint8_t *per_instruction_tools;
|
||||
} _PyCoMonitoringData;
|
||||
|
||||
extern int
|
||||
_Py_Instrumentation_GetLine(PyCodeObject *code, _PyCoLineInstrumentationData *line_data, int index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Remove critical section from :c:func:`!PyCode_Addr2Line` in free-threading.
|
||||
+9
-15
@@ -1008,14 +1008,18 @@ failed:
|
||||
* source location tracking (co_lines/co_positions)
|
||||
******************/
|
||||
|
||||
static int
|
||||
_PyCode_Addr2Line(PyCodeObject *co, int addrq)
|
||||
int
|
||||
PyCode_Addr2Line(PyCodeObject *co, int addrq)
|
||||
{
|
||||
if (addrq < 0) {
|
||||
return co->co_firstlineno;
|
||||
}
|
||||
if (co->_co_monitoring && co->_co_monitoring->lines) {
|
||||
return _Py_Instrumentation_GetLine(co, addrq/sizeof(_Py_CODEUNIT));
|
||||
_PyCoMonitoringData *data = _Py_atomic_load_ptr_acquire(&co->_co_monitoring);
|
||||
if (data) {
|
||||
_PyCoLineInstrumentationData *lines = _Py_atomic_load_ptr_acquire(&data->lines);
|
||||
if (lines) {
|
||||
return _Py_Instrumentation_GetLine(co, lines, addrq/sizeof(_Py_CODEUNIT));
|
||||
}
|
||||
}
|
||||
assert(addrq >= 0 && addrq < _PyCode_NBYTES(co));
|
||||
PyCodeAddressRange bounds;
|
||||
@@ -1030,7 +1034,7 @@ _PyCode_SafeAddr2Line(PyCodeObject *co, int addrq)
|
||||
return co->co_firstlineno;
|
||||
}
|
||||
if (co->_co_monitoring && co->_co_monitoring->lines) {
|
||||
return _Py_Instrumentation_GetLine(co, addrq/sizeof(_Py_CODEUNIT));
|
||||
return _Py_Instrumentation_GetLine(co, co->_co_monitoring->lines, addrq/sizeof(_Py_CODEUNIT));
|
||||
}
|
||||
if (!(addrq >= 0 && addrq < _PyCode_NBYTES(co))) {
|
||||
return -1;
|
||||
@@ -1040,16 +1044,6 @@ _PyCode_SafeAddr2Line(PyCodeObject *co, int addrq)
|
||||
return _PyCode_CheckLineNumber(addrq, &bounds);
|
||||
}
|
||||
|
||||
int
|
||||
PyCode_Addr2Line(PyCodeObject *co, int addrq)
|
||||
{
|
||||
int lineno;
|
||||
Py_BEGIN_CRITICAL_SECTION(co);
|
||||
lineno = _PyCode_Addr2Line(co, addrq);
|
||||
Py_END_CRITICAL_SECTION();
|
||||
return lineno;
|
||||
}
|
||||
|
||||
void
|
||||
_PyLineTable_InitAddressRange(const char *linetable, Py_ssize_t length, int firstlineno, PyCodeAddressRange *range)
|
||||
{
|
||||
|
||||
+19
-22
@@ -1286,13 +1286,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;
|
||||
@@ -1310,11 +1307,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
|
||||
@@ -1511,11 +1508,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);
|
||||
@@ -1656,18 +1651,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;
|
||||
}
|
||||
@@ -1732,12 +1728,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);
|
||||
|
||||
@@ -391,8 +391,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;
|
||||
|
||||
Reference in New Issue
Block a user