mirror of
https://github.com/python/cpython.git
synced 2025-07-09 20:35:26 +00:00
GH-103082: Implementation of PEP 669: Low Impact Monitoring for CPython (GH-103083)
* The majority of the monitoring code is in instrumentation.c * The new instrumentation bytecodes are in bytecodes.c * legacy_tracing.c adapts the new API to the old sys.setrace and sys.setprofile APIs
This commit is contained in:
parent
dce2d38cb0
commit
411b169281
44 changed files with 6029 additions and 1625 deletions
|
@ -431,13 +431,13 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
|
|||
if (_Py_next_func_version != 0) {
|
||||
_Py_next_func_version++;
|
||||
}
|
||||
co->_co_monitoring = NULL;
|
||||
co->_co_instrumentation_version = 0;
|
||||
/* not set */
|
||||
co->co_weakreflist = NULL;
|
||||
co->co_extra = NULL;
|
||||
co->_co_cached = NULL;
|
||||
|
||||
co->_co_linearray_entry_size = 0;
|
||||
co->_co_linearray = NULL;
|
||||
memcpy(_PyCode_CODE(co), PyBytes_AS_STRING(con->code),
|
||||
PyBytes_GET_SIZE(con->code));
|
||||
int entry_point = 0;
|
||||
|
@ -816,54 +816,6 @@ failed:
|
|||
* source location tracking (co_lines/co_positions)
|
||||
******************/
|
||||
|
||||
/* Use co_linetable to compute the line number from a bytecode index, addrq. See
|
||||
lnotab_notes.txt for the details of the lnotab representation.
|
||||
*/
|
||||
|
||||
int
|
||||
_PyCode_CreateLineArray(PyCodeObject *co)
|
||||
{
|
||||
assert(co->_co_linearray == NULL);
|
||||
PyCodeAddressRange bounds;
|
||||
int size;
|
||||
int max_line = 0;
|
||||
_PyCode_InitAddressRange(co, &bounds);
|
||||
while(_PyLineTable_NextAddressRange(&bounds)) {
|
||||
if (bounds.ar_line > max_line) {
|
||||
max_line = bounds.ar_line;
|
||||
}
|
||||
}
|
||||
if (max_line < (1 << 15)) {
|
||||
size = 2;
|
||||
}
|
||||
else {
|
||||
size = 4;
|
||||
}
|
||||
co->_co_linearray = PyMem_Malloc(Py_SIZE(co)*size);
|
||||
if (co->_co_linearray == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
co->_co_linearray_entry_size = size;
|
||||
_PyCode_InitAddressRange(co, &bounds);
|
||||
while(_PyLineTable_NextAddressRange(&bounds)) {
|
||||
int start = bounds.ar_start / sizeof(_Py_CODEUNIT);
|
||||
int end = bounds.ar_end / sizeof(_Py_CODEUNIT);
|
||||
for (int index = start; index < end; index++) {
|
||||
assert(index < (int)Py_SIZE(co));
|
||||
if (size == 2) {
|
||||
assert(((int16_t)bounds.ar_line) == bounds.ar_line);
|
||||
((int16_t *)co->_co_linearray)[index] = bounds.ar_line;
|
||||
}
|
||||
else {
|
||||
assert(size == 4);
|
||||
((int32_t *)co->_co_linearray)[index] = bounds.ar_line;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PyCode_Addr2Line(PyCodeObject *co, int addrq)
|
||||
{
|
||||
|
@ -871,9 +823,6 @@ PyCode_Addr2Line(PyCodeObject *co, int addrq)
|
|||
return co->co_firstlineno;
|
||||
}
|
||||
assert(addrq >= 0 && addrq < _PyCode_NBYTES(co));
|
||||
if (co->_co_linearray) {
|
||||
return _PyCode_LineNumberFromArray(co, addrq / sizeof(_Py_CODEUNIT));
|
||||
}
|
||||
PyCodeAddressRange bounds;
|
||||
_PyCode_InitAddressRange(co, &bounds);
|
||||
return _PyCode_CheckLineNumber(addrq, &bounds);
|
||||
|
@ -1531,17 +1480,17 @@ PyCode_GetFreevars(PyCodeObject *code)
|
|||
}
|
||||
|
||||
static void
|
||||
deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len)
|
||||
deopt_code(PyCodeObject *code, _Py_CODEUNIT *instructions)
|
||||
{
|
||||
Py_ssize_t len = Py_SIZE(code);
|
||||
for (int i = 0; i < len; i++) {
|
||||
_Py_CODEUNIT instruction = instructions[i];
|
||||
int opcode = _PyOpcode_Deopt[instruction.op.code];
|
||||
int opcode = _Py_GetBaseOpcode(code, i);
|
||||
int caches = _PyOpcode_Caches[opcode];
|
||||
instructions[i].op.code = opcode;
|
||||
while (caches--) {
|
||||
instructions[++i].op.code = CACHE;
|
||||
instructions[i].op.arg = 0;
|
||||
for (int j = 1; j <= caches; j++) {
|
||||
instructions[i+j].cache = 0;
|
||||
}
|
||||
i += caches;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1559,7 +1508,7 @@ _PyCode_GetCode(PyCodeObject *co)
|
|||
if (code == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
deopt_code((_Py_CODEUNIT *)PyBytes_AS_STRING(code), Py_SIZE(co));
|
||||
deopt_code(co, (_Py_CODEUNIT *)PyBytes_AS_STRING(code));
|
||||
assert(co->_co_cached->_co_code == NULL);
|
||||
co->_co_cached->_co_code = Py_NewRef(code);
|
||||
return code;
|
||||
|
@ -1693,6 +1642,30 @@ code_new_impl(PyTypeObject *type, int argcount, int posonlyargcount,
|
|||
return co;
|
||||
}
|
||||
|
||||
static void
|
||||
free_monitoring_data(_PyCoMonitoringData *data)
|
||||
{
|
||||
if (data == NULL) {
|
||||
return;
|
||||
}
|
||||
if (data->tools) {
|
||||
PyMem_Free(data->tools);
|
||||
}
|
||||
if (data->lines) {
|
||||
PyMem_Free(data->lines);
|
||||
}
|
||||
if (data->line_tools) {
|
||||
PyMem_Free(data->line_tools);
|
||||
}
|
||||
if (data->per_instruction_opcodes) {
|
||||
PyMem_Free(data->per_instruction_opcodes);
|
||||
}
|
||||
if (data->per_instruction_tools) {
|
||||
PyMem_Free(data->per_instruction_tools);
|
||||
}
|
||||
PyMem_Free(data);
|
||||
}
|
||||
|
||||
static void
|
||||
code_dealloc(PyCodeObject *co)
|
||||
{
|
||||
|
@ -1739,9 +1712,7 @@ code_dealloc(PyCodeObject *co)
|
|||
if (co->co_weakreflist != NULL) {
|
||||
PyObject_ClearWeakRefs((PyObject*)co);
|
||||
}
|
||||
if (co->_co_linearray) {
|
||||
PyMem_Free(co->_co_linearray);
|
||||
}
|
||||
free_monitoring_data(co->_co_monitoring);
|
||||
PyObject_Free(co);
|
||||
}
|
||||
|
||||
|
@ -1885,7 +1856,7 @@ code_hash(PyCodeObject *co)
|
|||
SCRAMBLE_IN(co->co_firstlineno);
|
||||
SCRAMBLE_IN(Py_SIZE(co));
|
||||
for (int i = 0; i < Py_SIZE(co); i++) {
|
||||
int deop = _PyOpcode_Deopt[_PyCode_CODE(co)[i].op.code];
|
||||
int deop = _Py_GetBaseOpcode(co, i);
|
||||
SCRAMBLE_IN(deop);
|
||||
SCRAMBLE_IN(_PyCode_CODE(co)[i].op.arg);
|
||||
i += _PyOpcode_Caches[deop];
|
||||
|
@ -2314,7 +2285,7 @@ _PyCode_ConstantKey(PyObject *op)
|
|||
void
|
||||
_PyStaticCode_Fini(PyCodeObject *co)
|
||||
{
|
||||
deopt_code(_PyCode_CODE(co), Py_SIZE(co));
|
||||
deopt_code(co, _PyCode_CODE(co));
|
||||
PyMem_Free(co->co_extra);
|
||||
if (co->_co_cached != NULL) {
|
||||
Py_CLEAR(co->_co_cached->_co_code);
|
||||
|
@ -2329,10 +2300,8 @@ _PyStaticCode_Fini(PyCodeObject *co)
|
|||
PyObject_ClearWeakRefs((PyObject *)co);
|
||||
co->co_weakreflist = NULL;
|
||||
}
|
||||
if (co->_co_linearray) {
|
||||
PyMem_Free(co->_co_linearray);
|
||||
co->_co_linearray = NULL;
|
||||
}
|
||||
free_monitoring_data(co->_co_monitoring);
|
||||
co->_co_monitoring = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue