diff --git a/Include/cpython/code.h b/Include/cpython/code.h index f544ea87406e25..1812617d3c3067 100644 --- a/Include/cpython/code.h +++ b/Include/cpython/code.h @@ -89,6 +89,7 @@ typedef uint16_t _Py_CODEUNIT; PyObject *co_linetable; /* bytes object that holds location info */ \ PyObject *co_weakreflist; /* to support weakrefs to code objects */ \ void *_co_code; /* cached co_code object/attribute */ \ + 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 0996cc7eb0f6cd..8ae997e4b6bc6f 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -177,7 +177,7 @@ def jabs_op(name, op): hasfree.append(148) def_op('COPY_FREE_VARS', 149) def_op('YIELD_VALUE', 150) -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 2a2f132a6ef624..8ac4e9914f8887 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -339,6 +339,12 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con) co->co_warmup = QUICKENING_INITIAL_WARMUP_VALUE; 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 0e8186347cd895..341d1d23ad99ea 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5568,57 +5568,47 @@ _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 + ) { 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(); @@ -6855,13 +6845,8 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj, then call the trace function if we're tracing source lines. */ initialize_trace_info(&tstate->trace_info, frame); - 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 ac2076708a156f..443fcf2274909c 100644 --- a/Tools/scripts/deepfreeze.py +++ b/Tools/scripts/deepfreeze.py @@ -20,6 +20,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) @@ -267,6 +270,10 @@ def generate_code(self, name: str, code: types.CodeType) -> str: self.write(f".co_qualname = {co_qualname},") self.write(f".co_linetable = {co_linetable},") 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