diff --git a/Include/cpython/code.h b/Include/cpython/code.h
index 66cf4eccb8fcc9..ef8c6422046dc7 100644
--- a/Include/cpython/code.h
+++ b/Include/cpython/code.h
@@ -91,6 +91,7 @@ typedef uint16_t _Py_CODEUNIT;
PyObject *co_weakreflist; /* to support weakrefs to code objects */ \
PyObject *_co_code; /* cached co_code object/attribute */ \
char *_co_linearray; /* array of line offsets */ \
+ int _co_firsttraceable; /* index of first traceable instruction */ \
/* Scratch space for extra data relating to the code object. \
Type is a void* to keep the format private in codeobject.c to force \
people to go through the proper APIs. */ \
diff --git a/Lib/opcode.py b/Lib/opcode.py
index 310582874dc8f0..bc3c02af2bccb3 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -175,7 +175,7 @@ def jabs_op(name, op):
hasfree.append(148)
def_op('COPY_FREE_VARS', 149)
-def_op('RESUME', 151)
+def_op('RESUME', 151) # This must be kept in sync with deepfreeze.py
def_op('MATCH_CLASS', 152)
def_op('FORMAT_VALUE', 155)
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-06-13-13-55-34.gh-issue-93516.HILrDl.rst b/Misc/NEWS.d/next/Core and Builtins/2022-06-13-13-55-34.gh-issue-93516.HILrDl.rst
new file mode 100644
index 00000000000000..a324c2dbcbe8a6
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-06-13-13-55-34.gh-issue-93516.HILrDl.rst
@@ -0,0 +1,2 @@
+Store offset of first traceable instruction in code object to avoid having
+to recompute it for each instruction when tracing.
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index 8b9ca890431c6c..fddb42425ba068 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -341,6 +341,12 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
co->_co_linearray = NULL;
memcpy(_PyCode_CODE(co), PyBytes_AS_STRING(con->code),
PyBytes_GET_SIZE(con->code));
+ int entry_point = 0;
+ while (entry_point < Py_SIZE(co) &&
+ _Py_OPCODE(_PyCode_CODE(co)[entry_point]) != RESUME) {
+ entry_point++;
+ }
+ co->_co_firsttraceable = entry_point;
}
static int
diff --git a/Python/ceval.c b/Python/ceval.c
index 763187a8317af4..2d794837ce3d7e 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -5608,57 +5608,51 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
case DO_TRACING:
#endif
{
- if (tstate->tracing == 0) {
+ if (tstate->tracing == 0 &&
+ INSTR_OFFSET() >= frame->f_code->_co_firsttraceable
+ ) {
+ assert(
+ _PyOpcode_Deopt[first_instr[frame->f_code->_co_firsttraceable]]
+ == RESUME
+ );
int instr_prev = _PyInterpreterFrame_LASTI(frame);
frame->prev_instr = next_instr;
TRACING_NEXTOPARG();
- switch(opcode) {
- case COPY_FREE_VARS:
- case MAKE_CELL:
- case RETURN_GENERATOR:
- /* Frame not fully initialized */
- break;
- case RESUME:
- if (oparg < 2) {
- CHECK_EVAL_BREAKER();
- }
- /* Call tracing */
- TRACE_FUNCTION_ENTRY();
- DTRACE_FUNCTION_ENTRY();
- break;
- case POP_TOP:
- if (_Py_OPCODE(next_instr[-1]) == RETURN_GENERATOR) {
- /* Frame not fully initialized */
- break;
- }
- /* fall through */
- default:
- /* line-by-line tracing support */
- if (PyDTrace_LINE_ENABLED()) {
- maybe_dtrace_line(frame, &tstate->trace_info, instr_prev);
- }
-
- if (cframe.use_tracing &&
- tstate->c_tracefunc != NULL && !tstate->tracing) {
- int err;
- /* see maybe_call_line_trace()
- for expository comments */
- _PyFrame_SetStackPointer(frame, stack_pointer);
-
- err = maybe_call_line_trace(tstate->c_tracefunc,
- tstate->c_traceobj,
- tstate, frame, instr_prev);
- if (err) {
- /* trace function raised an exception */
- next_instr++;
- goto error;
- }
- /* Reload possibly changed frame fields */
- next_instr = frame->prev_instr;
+ if (opcode == RESUME) {
+ if (oparg < 2) {
+ CHECK_EVAL_BREAKER();
+ }
+ /* Call tracing */
+ TRACE_FUNCTION_ENTRY();
+ DTRACE_FUNCTION_ENTRY();
+ }
+ else {
+ /* line-by-line tracing support */
+ if (PyDTrace_LINE_ENABLED()) {
+ maybe_dtrace_line(frame, &tstate->trace_info, instr_prev);
+ }
- stack_pointer = _PyFrame_GetStackPointer(frame);
- frame->stacktop = -1;
+ if (cframe.use_tracing &&
+ tstate->c_tracefunc != NULL && !tstate->tracing) {
+ int err;
+ /* see maybe_call_line_trace()
+ for expository comments */
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+
+ err = maybe_call_line_trace(tstate->c_tracefunc,
+ tstate->c_traceobj,
+ tstate, frame, instr_prev);
+ if (err) {
+ /* trace function raised an exception */
+ next_instr++;
+ goto error;
}
+ /* Reload possibly changed frame fields */
+ next_instr = frame->prev_instr;
+
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ frame->stacktop = -1;
+ }
}
}
TRACING_NEXTOPARG();
@@ -6896,13 +6890,8 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
if (_PyCode_InitLineArray(frame->f_code)) {
return -1;
}
- int entry_point = 0;
- _Py_CODEUNIT *code = _PyCode_CODE(frame->f_code);
- while (_PyOpcode_Deopt[_Py_OPCODE(code[entry_point])] != RESUME) {
- entry_point++;
- }
int lastline;
- if (instr_prev <= entry_point) {
+ if (instr_prev <= frame->f_code->_co_firsttraceable) {
lastline = -1;
}
else {
diff --git a/Tools/scripts/deepfreeze.py b/Tools/scripts/deepfreeze.py
index 5aca79a722e11e..5a64c1ec2e61f7 100644
--- a/Tools/scripts/deepfreeze.py
+++ b/Tools/scripts/deepfreeze.py
@@ -22,6 +22,9 @@
verbose = False
identifiers, strings = get_identifiers_and_strings()
+# This must be kept in sync with opcode.py
+RESUME = 151
+
def isprintable(b: bytes) -> bool:
return all(0x20 <= c < 0x7f for c in b)
@@ -284,6 +287,10 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
self.write(f"._co_code = NULL,")
self.write("._co_linearray = NULL,")
self.write(f".co_code_adaptive = {co_code_adaptive},")
+ for i, op in enumerate(code.co_code[::2]):
+ if op == RESUME:
+ self.write(f"._co_firsttraceable = {i},")
+ break
name_as_code = f"(PyCodeObject *)&{name}"
self.deallocs.append(f"_PyStaticCode_Dealloc({name_as_code});")
self.interns.append(f"_PyStaticCode_InternStrings({name_as_code})")
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy