GH-100987: Allow objects other than code objects as the "executable" of an internal frame. (GH-105727)

* Add table describing possible executable classes for out-of-process debuggers.

* Remove shim code object creation code as it is no longer needed.

* Make lltrace a bit more robust w.r.t. non-standard frames.
This commit is contained in:
Mark Shannon 2023-06-14 13:46:37 +01:00 committed by GitHub
parent ad56340b66
commit 7199584ac8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 541 additions and 606 deletions

View file

@ -898,7 +898,7 @@ setup_context(Py_ssize_t stack_level,
}
else {
globals = f->f_frame->f_globals;
*filename = Py_NewRef(f->f_frame->f_code->co_filename);
*filename = Py_NewRef(_PyFrame_GetCode(f->f_frame)->co_filename);
*lineno = PyFrame_GetLineNumber(f);
Py_DECREF(f);
}

View file

@ -137,8 +137,8 @@ dummy_func(
assert(tstate->cframe == &cframe);
assert(frame == cframe.current_frame);
/* Possibly combine this with eval breaker */
if (frame->f_code->_co_instrumentation_version != tstate->interp->monitoring_version) {
int err = _Py_Instrument(frame->f_code, tstate->interp);
if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) {
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
ERROR_IF(err, error);
next_instr--;
}
@ -152,8 +152,8 @@ dummy_func(
* We need to check the eval breaker anyway, can we
* combine the instrument verison check and the eval breaker test?
*/
if (frame->f_code->_co_instrumentation_version != tstate->interp->monitoring_version) {
if (_Py_Instrument(frame->f_code, tstate->interp)) {
if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) {
if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) {
goto error;
}
next_instr--;
@ -666,8 +666,6 @@ dummy_func(
inst(INTERPRETER_EXIT, (retval --)) {
assert(frame == &entry_frame);
assert(_PyFrame_IsIncomplete(frame));
STACK_SHRINK(1); // Since we're not going to DISPATCH()
assert(EMPTY());
/* Restore previous cframe and return. */
tstate->cframe = cframe.previous;
assert(tstate->cframe->current_frame == frame->previous);
@ -971,7 +969,7 @@ dummy_func(
if (oparg) {
PyObject *lasti = values[0];
if (PyLong_Check(lasti)) {
frame->prev_instr = _PyCode_CODE(frame->f_code) + PyLong_AsLong(lasti);
frame->prev_instr = _PyCode_CODE(_PyFrame_GetCode(frame)) + PyLong_AsLong(lasti);
assert(!_PyErr_Occurred(tstate));
}
else {
@ -1385,7 +1383,7 @@ dummy_func(
// Can't use ERROR_IF here.
// Fortunately we don't need its superpower.
if (oldobj == NULL) {
format_exc_unbound(tstate, frame->f_code, oparg);
format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
goto error;
}
PyCell_SET(cell, NULL);
@ -1395,8 +1393,8 @@ dummy_func(
inst(LOAD_FROM_DICT_OR_DEREF, (class_dict -- value)) {
PyObject *name;
assert(class_dict);
assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus);
name = PyTuple_GET_ITEM(frame->f_code->co_localsplusnames, oparg);
assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus);
name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg);
if (PyDict_CheckExact(class_dict)) {
value = PyDict_GetItemWithError(class_dict, name);
if (value != NULL) {
@ -1422,7 +1420,7 @@ dummy_func(
PyObject *cell = GETLOCAL(oparg);
value = PyCell_GET(cell);
if (value == NULL) {
format_exc_unbound(tstate, frame->f_code, oparg);
format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
goto error;
}
Py_INCREF(value);
@ -1433,7 +1431,7 @@ dummy_func(
PyObject *cell = GETLOCAL(oparg);
value = PyCell_GET(cell);
if (value == NULL) {
format_exc_unbound(tstate, frame->f_code, oparg);
format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
ERROR_IF(true, error);
}
Py_INCREF(value);
@ -1448,7 +1446,7 @@ dummy_func(
inst(COPY_FREE_VARS, (--)) {
/* Copy closure variables to free variables */
PyCodeObject *co = frame->f_code;
PyCodeObject *co = _PyFrame_GetCode(frame);
assert(PyFunction_Check(frame->f_funcobj));
PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
assert(oparg == co->co_nfreevars);
@ -2175,7 +2173,8 @@ dummy_func(
};
inst(ENTER_EXECUTOR, (--)) {
_PyExecutorObject *executor = (_PyExecutorObject *)frame->f_code->co_executors->executors[oparg];
PyCodeObject *code = _PyFrame_GetCode(frame);
_PyExecutorObject *executor = (_PyExecutorObject *)code->co_executors->executors[oparg];
Py_INCREF(executor);
frame = executor->execute(executor, frame, stack_pointer);
if (frame == NULL) {
@ -2292,7 +2291,7 @@ dummy_func(
/* before: [obj]; after [getiter(obj)] */
if (PyCoro_CheckExact(iterable)) {
/* `iterable` is a coroutine */
if (!(frame->f_code->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
/* and it is used in a 'yield from' expression of a
regular generator. */
_PyErr_SetString(tstate, PyExc_TypeError,

View file

@ -129,6 +129,9 @@ lltrace_instruction(_PyInterpreterFrame *frame,
PyObject **stack_pointer,
_Py_CODEUNIT *next_instr)
{
if (frame->owner == FRAME_OWNED_BY_CSTACK) {
return;
}
/* This dump_stack() operation is risky, since the repr() of some
objects enters the interpreter recursively. It is also slow.
So you might want to comment it out. */
@ -137,7 +140,7 @@ lltrace_instruction(_PyInterpreterFrame *frame,
int opcode = next_instr->op.code;
const char *opname = _PyOpcode_OpName[opcode];
assert(opname != NULL);
int offset = (int)(next_instr - _PyCode_CODE(frame->f_code));
int offset = (int)(next_instr - _PyCode_CODE(_PyFrame_GetCode(frame)));
if (HAS_ARG((int)_PyOpcode_Deopt[opcode])) {
printf("%d: %s %d\n", offset * 2, opname, oparg);
}
@ -150,7 +153,7 @@ static void
lltrace_resume_frame(_PyInterpreterFrame *frame)
{
PyObject *fobj = frame->f_funcobj;
if (frame->owner == FRAME_OWNED_BY_CSTACK ||
if (!PyCode_Check(frame->f_executable) ||
fobj == NULL ||
!PyFunction_Check(fobj)
) {
@ -621,6 +624,13 @@ static inline void _Py_LeaveRecursiveCallPy(PyThreadState *tstate) {
tstate->py_recursion_remaining++;
}
static const _Py_CODEUNIT _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS[] = {
/* Put a NOP at the start, so that the IP points into
* the code, rather than before it */
{ .op.code = NOP, .op.arg = 0 },
{ .op.code = INTERPRETER_EXIT, .op.arg = 0 },
{ .op.code = RESUME, .op.arg = 0 }
};
/* Disable unused label warnings. They are handy for debugging, even
if computed gotos aren't used. */
@ -668,7 +678,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
cframe.previous = prev_cframe;
tstate->cframe = &cframe;
assert(tstate->interp->interpreter_trampoline != NULL);
#ifdef Py_DEBUG
/* Set these to invalid but identifiable values for debugging. */
entry_frame.f_funcobj = (PyObject*)0xaaa0;
@ -677,9 +686,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
entry_frame.f_globals = (PyObject*)0xaaa3;
entry_frame.f_builtins = (PyObject*)0xaaa4;
#endif
entry_frame.f_code = tstate->interp->interpreter_trampoline;
entry_frame.prev_instr =
_PyCode_CODE(tstate->interp->interpreter_trampoline);
entry_frame.f_executable = Py_None;
entry_frame.prev_instr = (_Py_CODEUNIT *)_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS;
entry_frame.stacktop = 0;
entry_frame.owner = FRAME_OWNED_BY_CSTACK;
entry_frame.return_offset = 0;
@ -701,7 +709,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
}
/* Because this avoids the RESUME,
* we need to update instrumentation */
_Py_Instrument(frame->f_code, tstate->interp);
_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
monitor_throw(tstate, frame, frame->prev_instr);
/* TO DO -- Monitor throw entry. */
goto resume_with_error;
@ -715,7 +723,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
/* Sets the above local variables from the frame */
#define SET_LOCALS_FROM_FRAME() \
assert(_PyInterpreterFrame_LASTI(frame) >= -1); \
/* Jump back to the last instruction executed... */ \
next_instr = frame->prev_instr + 1; \
stack_pointer = _PyFrame_GetStackPointer(frame);
@ -874,7 +881,7 @@ handle_eval_breaker:
opcode = next_instr->op.code;
_PyErr_Format(tstate, PyExc_SystemError,
"%U:%d: unknown opcode %d",
frame->f_code->co_filename,
_PyFrame_GetCode(frame)->co_filename,
PyUnstable_InterpreterFrame_GetLine(frame),
opcode);
goto error;
@ -889,7 +896,7 @@ unbound_local_error:
{
format_exc_check_arg(tstate, PyExc_UnboundLocalError,
UNBOUNDLOCAL_ERROR_MSG,
PyTuple_GetItem(frame->f_code->co_localsplusnames, oparg)
PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg)
);
goto error;
}
@ -929,7 +936,7 @@ exception_unwind:
/* We can't use frame->f_lasti here, as RERAISE may have set it */
int offset = INSTR_OFFSET()-1;
int level, handler, lasti;
if (get_exception_handler(frame->f_code, offset, &level, &handler, &lasti) == 0) {
if (get_exception_handler(_PyFrame_GetCode(frame), offset, &level, &handler, &lasti) == 0) {
// No handlers, so exit.
assert(_PyErr_Occurred(tstate));
@ -1523,12 +1530,12 @@ clear_thread_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)
assert(frame->owner == FRAME_OWNED_BY_THREAD);
// Make sure that this is, indeed, the top frame. We can't check this in
// _PyThreadState_PopFrame, since f_code is already cleared at that point:
assert((PyObject **)frame + frame->f_code->co_framesize ==
assert((PyObject **)frame + _PyFrame_GetCode(frame)->co_framesize ==
tstate->datastack_top);
tstate->c_recursion_remaining--;
assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);
_PyFrame_ClearExceptCode(frame);
Py_DECREF(frame->f_code);
Py_DECREF(frame->f_executable);
tstate->c_recursion_remaining++;
_PyThreadState_PopFrame(tstate, frame);
}
@ -2013,7 +2020,7 @@ do_monitor_exc(PyThreadState *tstate, _PyInterpreterFrame *frame,
static inline int
no_tools_for_event(PyThreadState *tstate, _PyInterpreterFrame *frame, int event)
{
_PyCoMonitoringData *data = frame->f_code->_co_monitoring;
_PyCoMonitoringData *data = _PyFrame_GetCode(frame)->_co_monitoring;
if (data) {
if (data->active_monitors.tools[event] == 0) {
return 1;
@ -2331,7 +2338,7 @@ PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
int result = cf->cf_flags != 0;
if (current_frame != NULL) {
const int codeflags = current_frame->f_code->co_flags;
const int codeflags = _PyFrame_GetCode(current_frame)->co_flags;
const int compilerflags = codeflags & PyCF_MASK;
if (compilerflags) {
result = 1;

View file

@ -138,13 +138,13 @@ GETITEM(PyObject *v, Py_ssize_t i) {
/* Code access macros */
/* The integer overflow is checked by an assertion below. */
#define INSTR_OFFSET() ((int)(next_instr - _PyCode_CODE(frame->f_code)))
#define INSTR_OFFSET() ((int)(next_instr - _PyCode_CODE(_PyFrame_GetCode(frame))))
#define NEXTOPARG() do { \
_Py_CODEUNIT word = *next_instr; \
opcode = word.op.code; \
oparg = word.op.arg; \
} while (0)
#define JUMPTO(x) (next_instr = _PyCode_CODE(frame->f_code) + (x))
#define JUMPTO(x) (next_instr = _PyCode_CODE(_PyFrame_GetCode(frame)) + (x))
#define JUMPBY(x) (next_instr += (x))
/* OpCode prediction macros
@ -182,7 +182,7 @@ GETITEM(PyObject *v, Py_ssize_t i) {
/* The stack can grow at most MAXINT deep, as co_nlocals and
co_stacksize are ints. */
#define STACK_LEVEL() ((int)(stack_pointer - _PyFrame_Stackbase(frame)))
#define STACK_SIZE() (frame->f_code->co_stacksize)
#define STACK_SIZE() (_PyFrame_GetCode(frame)->co_stacksize)
#define EMPTY() (STACK_LEVEL() == 0)
#define TOP() (stack_pointer[-1])
#define SECOND() (stack_pointer[-2])
@ -221,8 +221,8 @@ GETITEM(PyObject *v, Py_ssize_t i) {
/* Data access macros */
#define FRAME_CO_CONSTS (frame->f_code->co_consts)
#define FRAME_CO_NAMES (frame->f_code->co_names)
#define FRAME_CO_CONSTS (_PyFrame_GetCode(frame)->co_consts)
#define FRAME_CO_NAMES (_PyFrame_GetCode(frame)->co_names)
/* Local variable macros */
@ -270,6 +270,8 @@ GETITEM(PyObject *v, Py_ssize_t i) {
#define GLOBALS() frame->f_globals
#define BUILTINS() frame->f_builtins
#define LOCALS() frame->f_locals
#define CONSTS() _PyFrame_GetCode(frame)->co_consts
#define NAMES() _PyFrame_GetCode(frame)->co_names
#define DTRACE_FUNCTION_ENTRY() \
if (PyDTrace_FUNCTION_ENTRY_ENABLED()) { \

View file

@ -14,7 +14,7 @@ _PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg)
Py_VISIT(frame->frame_obj);
Py_VISIT(frame->f_locals);
Py_VISIT(frame->f_funcobj);
Py_VISIT(frame->f_code);
Py_VISIT(_PyFrame_GetCode(frame));
/* locals */
PyObject **locals = _PyFrame_GetLocalsArray(frame);
int i = 0;
@ -31,7 +31,7 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
assert(frame->frame_obj == NULL);
PyObject *exc = PyErr_GetRaisedException();
PyFrameObject *f = _PyFrame_New_NoTrack(frame->f_code);
PyFrameObject *f = _PyFrame_New_NoTrack(_PyFrame_GetCode(frame));
if (f == NULL) {
Py_XDECREF(exc);
return NULL;
@ -65,7 +65,7 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
void
_PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)
{
assert(src->stacktop >= src->f_code->co_nlocalsplus);
assert(src->stacktop >= _PyFrame_GetCode(src)->co_nlocalsplus);
Py_ssize_t size = ((char*)&src->localsplus[src->stacktop]) - (char *)src;
memcpy(dest, src, size);
// Don't leave a dangling pointer to the old frame when creating generators
@ -81,7 +81,7 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);
assert(frame->owner != FRAME_CLEARED);
Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char *)frame;
Py_INCREF(frame->f_code);
Py_INCREF(_PyFrame_GetCode(frame));
memcpy((_PyInterpreterFrame *)f->_f_frame_data, frame, size);
frame = (_PyInterpreterFrame *)f->_f_frame_data;
f->f_frame = frame;
@ -89,7 +89,7 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
if (_PyFrame_IsIncomplete(frame)) {
// This may be a newly-created generator or coroutine frame. Since it's
// dead anyways, just pretend that the first RESUME ran:
PyCodeObject *code = frame->f_code;
PyCodeObject *code = _PyFrame_GetCode(frame);
frame->prev_instr = _PyCode_CODE(code) + code->_co_firsttraceable;
}
assert(!_PyFrame_IsIncomplete(frame));
@ -149,7 +149,7 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
PyObject *
PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame)
{
PyObject *code = (PyObject *)frame->f_code;
PyObject *code = frame->f_executable;
Py_INCREF(code);
return code;
}
@ -164,5 +164,13 @@ int
PyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame)
{
int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
return PyCode_Addr2Line(frame->f_code, addr);
return PyCode_Addr2Line(_PyFrame_GetCode(frame), addr);
}
const PyTypeObject *const PyUnstable_ExecutableKinds[PY_EXECUTABLE_KINDS+1] = {
[PY_EXECUTABLE_KIND_SKIP] = &_PyNone_Type,
[PY_EXECUTABLE_KIND_PY_FUNCTION] = &PyCode_Type,
[PY_EXECUTABLE_KIND_BUILTIN_FUNCTION] = &PyMethod_Type,
[PY_EXECUTABLE_KIND_METHOD_DESCRIPTOR] = &PyMethodDescr_Type,
[PY_EXECUTABLE_KINDS] = NULL,
};

File diff suppressed because it is too large Load diff

View file

@ -936,7 +936,7 @@ call_instrumentation_vector(
}
assert(!_PyErr_Occurred(tstate));
assert(args[0] == NULL);
PyCodeObject *code = frame->f_code;
PyCodeObject *code = _PyFrame_GetCode(frame);
assert(code->_co_instrumentation_version == tstate->interp->monitoring_version);
assert(is_version_up_to_date(code, tstate->interp));
assert(instrumentation_cross_checks(tstate->interp, code));
@ -1017,7 +1017,7 @@ _Py_call_instrumentation_jump(
assert(frame->prev_instr == instr);
/* Event should occur after the jump */
frame->prev_instr = target;
PyCodeObject *code = frame->f_code;
PyCodeObject *code = _PyFrame_GetCode(frame);
int to = (int)(target - _PyCode_CODE(code));
PyObject *to_obj = PyLong_FromLong(to * (int)sizeof(_Py_CODEUNIT));
if (to_obj == NULL) {
@ -1094,7 +1094,7 @@ int
_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev)
{
frame->prev_instr = instr;
PyCodeObject *code = frame->f_code;
PyCodeObject *code = _PyFrame_GetCode(frame);
assert(is_version_up_to_date(code, tstate->interp));
assert(instrumentation_cross_checks(tstate->interp, code));
int i = (int)(instr - _PyCode_CODE(code));
@ -1162,7 +1162,7 @@ done:
int
_Py_call_instrumentation_instruction(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr)
{
PyCodeObject *code = frame->f_code;
PyCodeObject *code = _PyFrame_GetCode(frame);
assert(is_version_up_to_date(code, tstate->interp));
assert(instrumentation_cross_checks(tstate->interp, code));
int offset = (int)(instr - _PyCode_CODE(code));
@ -1632,7 +1632,7 @@ instrument_all_executing_code_objects(PyInterpreterState *interp) {
_PyInterpreterFrame *frame = ts->cframe->current_frame;
while (frame) {
if (frame->owner != FRAME_OWNED_BY_CSTACK) {
if (_Py_Instrument(frame->f_code, interp)) {
if (_Py_Instrument(_PyFrame_GetCode(frame), interp)) {
return -1;
}
}

View file

@ -148,14 +148,14 @@ stopiteration_error(PyThreadState* tstate, PyObject *exc)
const char *msg = NULL;
if (PyErr_GivenExceptionMatches(exc, PyExc_StopIteration)) {
msg = "generator raised StopIteration";
if (frame->f_code->co_flags & CO_ASYNC_GENERATOR) {
if (_PyFrame_GetCode(frame)->co_flags & CO_ASYNC_GENERATOR) {
msg = "async generator raised StopIteration";
}
else if (frame->f_code->co_flags & CO_COROUTINE) {
else if (_PyFrame_GetCode(frame)->co_flags & CO_COROUTINE) {
msg = "coroutine raised StopIteration";
}
}
else if ((frame->f_code->co_flags & CO_ASYNC_GENERATOR) &&
else if ((_PyFrame_GetCode(frame)->co_flags & CO_ASYNC_GENERATOR) &&
PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration))
{
/* code in `gen` raised a StopAsyncIteration error:

View file

@ -244,7 +244,7 @@ sys_trace_line_func(
"Missing frame when calling trace function.");
return NULL;
}
assert(args[0] == (PyObject *)frame->f_frame->f_code);
assert(args[0] == (PyObject *)_PyFrame_GetCode(frame->f_frame));
return trace_line(tstate, self, frame, line);
}
@ -286,7 +286,6 @@ sys_trace_jump_func(
"Missing frame when calling trace function.");
return NULL;
}
assert(code == frame->f_frame->f_code);
if (!frame->f_trace_lines) {
Py_RETURN_NONE;
}

View file

@ -148,15 +148,17 @@ PyUnstable_SetOptimizer(_PyOptimizerObject *optimizer)
_PyInterpreterFrame *
_PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest, PyObject **stack_pointer)
{
PyCodeObject *code = (PyCodeObject *)frame->f_executable;
assert(PyCode_Check(code));
PyInterpreterState *interp = PyInterpreterState_Get();
int index = get_executor_index(frame->f_code, src);
int index = get_executor_index(code, src);
if (index < 0) {
_PyFrame_SetStackPointer(frame, stack_pointer);
return frame;
}
_PyOptimizerObject *opt = interp->optimizer;
_PyExecutorObject *executor;
int err = opt->optimize(opt, frame->f_code, dest, &executor);
int err = opt->optimize(opt, code, dest, &executor);
if (err <= 0) {
if (err < 0) {
return NULL;
@ -164,7 +166,7 @@ _PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNI
_PyFrame_SetStackPointer(frame, stack_pointer);
return frame;
}
insert_executor(frame->f_code, src, index, executor);
insert_executor(code, src, index, executor);
return executor->execute(executor, frame, stack_pointer);
}

View file

@ -335,7 +335,7 @@ py_trampoline_evaluator(PyThreadState *ts, _PyInterpreterFrame *frame,
perf_status == PERF_STATUS_NO_INIT) {
goto default_eval;
}
PyCodeObject *co = frame->f_code;
PyCodeObject *co = _PyFrame_GetCode(frame);
py_trampoline f = NULL;
assert(extra_code_index != -1);
int ret = _PyCode_GetExtra((PyObject *)co, extra_code_index, (void **)&f);

View file

@ -737,22 +737,6 @@ pycore_init_types(PyInterpreterState *interp)
return _PyStatus_OK();
}
static const uint8_t INTERPRETER_TRAMPOLINE_INSTRUCTIONS[] = {
/* Put a NOP at the start, so that the IP points into
* the code, rather than before it */
NOP, 0,
INTERPRETER_EXIT, 0,
/* RESUME at end makes sure that the frame appears incomplete */
RESUME, 0
};
static const _PyShimCodeDef INTERPRETER_TRAMPOLINE_CODEDEF = {
INTERPRETER_TRAMPOLINE_INSTRUCTIONS,
sizeof(INTERPRETER_TRAMPOLINE_INSTRUCTIONS),
1,
"<interpreter trampoline>"
};
static PyStatus
pycore_init_builtins(PyThreadState *tstate)
{
@ -786,10 +770,6 @@ pycore_init_builtins(PyThreadState *tstate)
PyObject *object__getattribute__ = _PyType_Lookup(&PyBaseObject_Type, &_Py_ID(__getattribute__));
assert(object__getattribute__);
interp->callable_cache.object__getattribute__ = object__getattribute__;
interp->interpreter_trampoline = _Py_MakeShimCode(&INTERPRETER_TRAMPOLINE_CODEDEF);
if (interp->interpreter_trampoline == NULL) {
return _PyStatus_ERR("failed to create interpreter trampoline.");
}
if (_PyBuiltins_AddExceptions(bimod) < 0) {
return _PyStatus_ERR("failed to add exceptions to builtins");
}

View file

@ -892,7 +892,6 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
PyDict_Clear(interp->builtins);
Py_CLEAR(interp->sysdict);
Py_CLEAR(interp->builtins);
Py_CLEAR(interp->interpreter_trampoline);
if (tstate->interp == interp) {
/* We are now safe to fix tstate->_status.cleared. */

View file

@ -785,7 +785,7 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen
}
int code_offset = tb->tb_lasti;
PyCodeObject* code = frame->f_frame->f_code;
PyCodeObject* code = _PyFrame_GetCode(frame->f_frame);
const Py_ssize_t source_line_len = PyUnicode_GET_LENGTH(source_line);
int start_line;
@ -1164,7 +1164,7 @@ done:
static void
dump_frame(int fd, _PyInterpreterFrame *frame)
{
PyCodeObject *code = frame->f_code;
PyCodeObject *code =_PyFrame_GetCode(frame);
PUTS(fd, " File ");
if (code->co_filename != NULL
&& PyUnicode_Check(code->co_filename))

View file

@ -249,6 +249,7 @@ hashtable_compare_traceback(const void *key1, const void *key2)
static void
tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame)
{
assert(PyCode_Check(pyframe->f_executable));
frame->filename = &_Py_STR(anon_unknown);
int lineno = PyUnstable_InterpreterFrame_GetLine(pyframe);
if (lineno < 0) {
@ -256,7 +257,7 @@ tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame)
}
frame->lineno = (unsigned int)lineno;
PyObject *filename = pyframe->f_code->co_filename;
PyObject *filename = filename = ((PyCodeObject *)pyframe->f_executable)->co_filename;
if (filename == NULL) {
#ifdef TRACE_DEBUG