summaryrefslogtreecommitdiffstats
path: root/Objects/codeobject.c
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2023-04-12 11:04:55 (GMT)
committerGitHub <noreply@github.com>2023-04-12 11:04:55 (GMT)
commit411b1692811b2ecac59cb0df0f920861c7cf179a (patch)
tree64f7234e9d35623565ff1bb7fbd2c4688e8d3774 /Objects/codeobject.c
parentdce2d38cb04b541bad477ccc1040a68fa70a9a69 (diff)
downloadcpython-411b1692811b2ecac59cb0df0f920861c7cf179a.zip
cpython-411b1692811b2ecac59cb0df0f920861c7cf179a.tar.gz
cpython-411b1692811b2ecac59cb0df0f920861c7cf179a.tar.bz2
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
Diffstat (limited to 'Objects/codeobject.c')
-rw-r--r--Objects/codeobject.c107
1 files changed, 38 insertions, 69 deletions
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index 755d0b8..9b54c61 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -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;
@@ -1694,6 +1643,30 @@ code_new_impl(PyTypeObject *type, int argcount, int posonlyargcount,
}
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)
{
assert(Py_REFCNT(co) == 0);
@@ -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