mirror of https://github.com/python/cpython
bpo-47177: Replace `f_lasti` with `prev_instr` (GH-32208)
This commit is contained in:
parent
87eec70d97
commit
ef6a482b02
|
@ -39,11 +39,6 @@ enum _frameowner {
|
||||||
FRAME_OWNED_BY_FRAME_OBJECT = 2
|
FRAME_OWNED_BY_FRAME_OBJECT = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
frame->f_lasti refers to the index of the last instruction,
|
|
||||||
unless it's -1 in which case next_instr should be first_instr.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct _PyInterpreterFrame {
|
typedef struct _PyInterpreterFrame {
|
||||||
PyFunctionObject *f_func; /* Strong reference */
|
PyFunctionObject *f_func; /* Strong reference */
|
||||||
PyObject *f_globals; /* Borrowed reference */
|
PyObject *f_globals; /* Borrowed reference */
|
||||||
|
@ -52,13 +47,20 @@ typedef struct _PyInterpreterFrame {
|
||||||
PyCodeObject *f_code; /* Strong reference */
|
PyCodeObject *f_code; /* Strong reference */
|
||||||
PyFrameObject *frame_obj; /* Strong reference, may be NULL */
|
PyFrameObject *frame_obj; /* Strong reference, may be NULL */
|
||||||
struct _PyInterpreterFrame *previous;
|
struct _PyInterpreterFrame *previous;
|
||||||
int f_lasti; /* Last instruction if called */
|
// NOTE: This is not necessarily the last instruction started in the given
|
||||||
|
// frame. Rather, it is the code unit *prior to* the *next* instruction. For
|
||||||
|
// example, it may be an inline CACHE entry, an instruction we just jumped
|
||||||
|
// over, or (in the case of a newly-created frame) a totally invalid value:
|
||||||
|
_Py_CODEUNIT *prev_instr;
|
||||||
int stacktop; /* Offset of TOS from localsplus */
|
int stacktop; /* Offset of TOS from localsplus */
|
||||||
bool is_entry; // Whether this is the "root" frame for the current _PyCFrame.
|
bool is_entry; // Whether this is the "root" frame for the current _PyCFrame.
|
||||||
char owner;
|
char owner;
|
||||||
PyObject *localsplus[1];
|
PyObject *localsplus[1];
|
||||||
} _PyInterpreterFrame;
|
} _PyInterpreterFrame;
|
||||||
|
|
||||||
|
#define _PyInterpreterFrame_LASTI(IF) \
|
||||||
|
((int)((IF)->prev_instr - _PyCode_CODE((IF)->f_code)))
|
||||||
|
|
||||||
static inline PyObject **_PyFrame_Stackbase(_PyInterpreterFrame *f) {
|
static inline PyObject **_PyFrame_Stackbase(_PyInterpreterFrame *f) {
|
||||||
return f->localsplus + f->f_code->co_nlocalsplus;
|
return f->localsplus + f->f_code->co_nlocalsplus;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +99,7 @@ _PyFrame_InitializeSpecials(
|
||||||
frame->f_locals = Py_XNewRef(locals);
|
frame->f_locals = Py_XNewRef(locals);
|
||||||
frame->stacktop = nlocalsplus;
|
frame->stacktop = nlocalsplus;
|
||||||
frame->frame_obj = NULL;
|
frame->frame_obj = NULL;
|
||||||
frame->f_lasti = -1;
|
frame->prev_instr = _PyCode_CODE(frame->f_code) - 1;
|
||||||
frame->is_entry = false;
|
frame->is_entry = false;
|
||||||
frame->owner = FRAME_OWNED_BY_THREAD;
|
frame->owner = FRAME_OWNED_BY_THREAD;
|
||||||
}
|
}
|
||||||
|
@ -186,6 +188,7 @@ void _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame *frame);
|
||||||
_PyInterpreterFrame *
|
_PyInterpreterFrame *
|
||||||
_PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func);
|
_PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func);
|
||||||
|
|
||||||
|
int _PyInterpreterFrame_GetLine(_PyInterpreterFrame *frame);
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame)
|
PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Replace the ``f_lasti`` member of the internal ``_PyInterpreterFrame`` structure with a ``prev_instr`` pointer, which reduces overhead in the main interpreter loop. The ``f_lasti`` attribute of Python-layer frame objects is preserved for backward-compatibility.
|
|
@ -308,7 +308,7 @@ static void
|
||||||
tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame)
|
tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame)
|
||||||
{
|
{
|
||||||
frame->filename = &_Py_STR(anon_unknown);
|
frame->filename = &_Py_STR(anon_unknown);
|
||||||
int lineno = PyCode_Addr2Line(pyframe->f_code, pyframe->f_lasti*sizeof(_Py_CODEUNIT));
|
int lineno = _PyInterpreterFrame_GetLine(pyframe);
|
||||||
if (lineno < 0) {
|
if (lineno < 0) {
|
||||||
lineno = 0;
|
lineno = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ PyFrame_GetLineNumber(PyFrameObject *f)
|
||||||
return f->f_lineno;
|
return f->f_lineno;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return PyCode_Addr2Line(f->f_frame->f_code, f->f_frame->f_lasti*sizeof(_Py_CODEUNIT));
|
return _PyInterpreterFrame_GetLine(f->f_frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,10 +58,11 @@ frame_getlineno(PyFrameObject *f, void *closure)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
frame_getlasti(PyFrameObject *f, void *closure)
|
frame_getlasti(PyFrameObject *f, void *closure)
|
||||||
{
|
{
|
||||||
if (f->f_frame->f_lasti < 0) {
|
int lasti = _PyInterpreterFrame_LASTI(f->f_frame);
|
||||||
|
if (lasti < 0) {
|
||||||
return PyLong_FromLong(-1);
|
return PyLong_FromLong(-1);
|
||||||
}
|
}
|
||||||
return PyLong_FromLong(f->f_frame->f_lasti*sizeof(_Py_CODEUNIT));
|
return PyLong_FromLong(lasti * sizeof(_Py_CODEUNIT));
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -419,12 +420,11 @@ _PyFrame_GetState(PyFrameObject *frame)
|
||||||
}
|
}
|
||||||
case FRAME_OWNED_BY_THREAD:
|
case FRAME_OWNED_BY_THREAD:
|
||||||
{
|
{
|
||||||
if (frame->f_frame->f_lasti < 0) {
|
if (_PyInterpreterFrame_LASTI(frame->f_frame) < 0) {
|
||||||
return FRAME_CREATED;
|
return FRAME_CREATED;
|
||||||
}
|
}
|
||||||
uint8_t *code = (uint8_t *)frame->f_frame->f_code->co_code_adaptive;
|
switch (_PyOpcode_Deopt[_Py_OPCODE(*frame->f_frame->prev_instr)])
|
||||||
int opcode = code[frame->f_frame->f_lasti*sizeof(_Py_CODEUNIT)];
|
{
|
||||||
switch(_PyOpcode_Deopt[opcode]) {
|
|
||||||
case COPY_FREE_VARS:
|
case COPY_FREE_VARS:
|
||||||
case MAKE_CELL:
|
case MAKE_CELL:
|
||||||
case RETURN_GENERATOR:
|
case RETURN_GENERATOR:
|
||||||
|
@ -555,7 +555,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
|
||||||
|
|
||||||
int64_t best_stack = OVERFLOWED;
|
int64_t best_stack = OVERFLOWED;
|
||||||
int best_addr = -1;
|
int best_addr = -1;
|
||||||
int64_t start_stack = stacks[f->f_frame->f_lasti];
|
int64_t start_stack = stacks[_PyInterpreterFrame_LASTI(f->f_frame)];
|
||||||
int err = -1;
|
int err = -1;
|
||||||
const char *msg = "cannot find bytecode for specified line";
|
const char *msg = "cannot find bytecode for specified line";
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
|
@ -598,7 +598,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
|
||||||
}
|
}
|
||||||
/* Finally set the new lasti and return OK. */
|
/* Finally set the new lasti and return OK. */
|
||||||
f->f_lineno = 0;
|
f->f_lineno = 0;
|
||||||
f->f_frame->f_lasti = best_addr;
|
f->f_frame->prev_instr = _PyCode_CODE(f->f_frame->f_code) + best_addr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -880,10 +880,11 @@ _PyFrame_OpAlreadyRan(_PyInterpreterFrame *frame, int opcode, int oparg)
|
||||||
// This only works when opcode is a non-quickened form:
|
// This only works when opcode is a non-quickened form:
|
||||||
assert(_PyOpcode_Deopt[opcode] == opcode);
|
assert(_PyOpcode_Deopt[opcode] == opcode);
|
||||||
int check_oparg = 0;
|
int check_oparg = 0;
|
||||||
for (int i = 0; i < frame->f_lasti; i++) {
|
for (_Py_CODEUNIT *instruction = _PyCode_CODE(frame->f_code);
|
||||||
_Py_CODEUNIT instruction = _PyCode_CODE(frame->f_code)[i];
|
instruction < frame->prev_instr; instruction++)
|
||||||
int check_opcode = _PyOpcode_Deopt[_Py_OPCODE(instruction)];
|
{
|
||||||
check_oparg |= _Py_OPARG(instruction);
|
int check_opcode = _PyOpcode_Deopt[_Py_OPCODE(*instruction)];
|
||||||
|
check_oparg |= _Py_OPARG(*instruction);
|
||||||
if (check_opcode == opcode && check_oparg == oparg) {
|
if (check_opcode == opcode && check_oparg == oparg) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -893,7 +894,7 @@ _PyFrame_OpAlreadyRan(_PyInterpreterFrame *frame, int opcode, int oparg)
|
||||||
else {
|
else {
|
||||||
check_oparg = 0;
|
check_oparg = 0;
|
||||||
}
|
}
|
||||||
i += _PyOpcode_Caches[check_opcode];
|
instruction += _PyOpcode_Caches[check_opcode];
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -914,8 +915,8 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame) {
|
||||||
fast = _PyFrame_GetLocalsArray(frame);
|
fast = _PyFrame_GetLocalsArray(frame);
|
||||||
// COPY_FREE_VARS has no quickened forms, so no need to use _PyOpcode_Deopt
|
// COPY_FREE_VARS has no quickened forms, so no need to use _PyOpcode_Deopt
|
||||||
// here:
|
// here:
|
||||||
if (frame->f_lasti < 0 && _Py_OPCODE(_PyCode_CODE(co)[0]) == COPY_FREE_VARS)
|
int lasti = _PyInterpreterFrame_LASTI(frame);
|
||||||
{
|
if (lasti < 0 && _Py_OPCODE(_PyCode_CODE(co)[0]) == COPY_FREE_VARS) {
|
||||||
/* Free vars have not been initialized -- Do that */
|
/* Free vars have not been initialized -- Do that */
|
||||||
PyCodeObject *co = frame->f_code;
|
PyCodeObject *co = frame->f_code;
|
||||||
PyObject *closure = frame->f_func->func_closure;
|
PyObject *closure = frame->f_func->func_closure;
|
||||||
|
@ -926,7 +927,7 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame) {
|
||||||
frame->localsplus[offset + i] = o;
|
frame->localsplus[offset + i] = o;
|
||||||
}
|
}
|
||||||
// COPY_FREE_VARS doesn't have inline CACHEs, either:
|
// COPY_FREE_VARS doesn't have inline CACHEs, either:
|
||||||
frame->f_lasti = 0;
|
frame->prev_instr = _PyCode_CODE(frame->f_code);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < co->co_nlocalsplus; i++) {
|
for (int i = 0; i < co->co_nlocalsplus; i++) {
|
||||||
_PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);
|
_PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);
|
||||||
|
|
|
@ -352,14 +352,14 @@ _PyGen_yf(PyGenObject *gen)
|
||||||
if (gen->gi_frame_state < FRAME_CLEARED) {
|
if (gen->gi_frame_state < FRAME_CLEARED) {
|
||||||
_PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe;
|
_PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe;
|
||||||
|
|
||||||
if (frame->f_lasti < 1) {
|
if (gen->gi_frame_state == FRAME_CREATED) {
|
||||||
/* Return immediately if the frame didn't start yet. SEND
|
/* Return immediately if the frame didn't start yet. SEND
|
||||||
always come after LOAD_CONST: a code object should not start
|
always come after LOAD_CONST: a code object should not start
|
||||||
with SEND */
|
with SEND */
|
||||||
assert(_Py_OPCODE(_PyCode_CODE(gen->gi_code)[0]) != SEND);
|
assert(_Py_OPCODE(_PyCode_CODE(gen->gi_code)[0]) != SEND);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
_Py_CODEUNIT next = _PyCode_CODE(gen->gi_code)[frame->f_lasti + 1];
|
_Py_CODEUNIT next = frame->prev_instr[1];
|
||||||
if (_PyOpcode_Deopt[_Py_OPCODE(next)] != RESUME || _Py_OPARG(next) < 2)
|
if (_PyOpcode_Deopt[_Py_OPCODE(next)] != RESUME || _Py_OPARG(next) < 2)
|
||||||
{
|
{
|
||||||
/* Not in a yield from */
|
/* Not in a yield from */
|
||||||
|
@ -490,13 +490,11 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
|
||||||
// XXX: Performing this jump ourselves is awkward and problematic.
|
// XXX: Performing this jump ourselves is awkward and problematic.
|
||||||
// See https://github.com/python/cpython/pull/31968.
|
// See https://github.com/python/cpython/pull/31968.
|
||||||
/* Termination repetition of SEND loop */
|
/* Termination repetition of SEND loop */
|
||||||
assert(frame->f_lasti >= 0);
|
assert(_PyInterpreterFrame_LASTI(frame) >= 0);
|
||||||
_Py_CODEUNIT *code = _PyCode_CODE(gen->gi_code);
|
|
||||||
/* Backup to SEND */
|
/* Backup to SEND */
|
||||||
frame->f_lasti--;
|
assert(_Py_OPCODE(frame->prev_instr[-1]) == SEND);
|
||||||
assert(_Py_OPCODE(code[frame->f_lasti]) == SEND);
|
int jump = _Py_OPARG(frame->prev_instr[-1]);
|
||||||
int jump = _Py_OPARG(code[frame->f_lasti]);
|
frame->prev_instr += jump - 1;
|
||||||
frame->f_lasti += jump;
|
|
||||||
if (_PyGen_FetchStopIterationValue(&val) == 0) {
|
if (_PyGen_FetchStopIterationValue(&val) == 0) {
|
||||||
ret = gen_send(gen, val);
|
ret = gen_send(gen, val);
|
||||||
Py_DECREF(val);
|
Py_DECREF(val);
|
||||||
|
@ -1344,9 +1342,8 @@ compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame)
|
||||||
frame = current_frame;
|
frame = current_frame;
|
||||||
for (int i = 0; i < frame_count; ++i) {
|
for (int i = 0; i < frame_count; ++i) {
|
||||||
PyCodeObject *code = frame->f_code;
|
PyCodeObject *code = frame->f_code;
|
||||||
PyObject *frameinfo = Py_BuildValue("OiO",
|
int line = _PyInterpreterFrame_GetLine(frame);
|
||||||
code->co_filename,
|
PyObject *frameinfo = Py_BuildValue("OiO", code->co_filename, line,
|
||||||
PyCode_Addr2Line(frame->f_code, frame->f_lasti*sizeof(_Py_CODEUNIT)),
|
|
||||||
code->co_name);
|
code->co_name);
|
||||||
if (!frameinfo) {
|
if (!frameinfo) {
|
||||||
Py_DECREF(cr_origin);
|
Py_DECREF(cr_origin);
|
||||||
|
|
|
@ -8980,7 +8980,7 @@ super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co,
|
||||||
if (firstarg != NULL && (_PyLocals_GetKind(co->co_localspluskinds, 0) & CO_FAST_CELL)) {
|
if (firstarg != NULL && (_PyLocals_GetKind(co->co_localspluskinds, 0) & CO_FAST_CELL)) {
|
||||||
// "firstarg" is a cell here unless (very unlikely) super()
|
// "firstarg" is a cell here unless (very unlikely) super()
|
||||||
// was called from the C-API before the first MAKE_CELL op.
|
// was called from the C-API before the first MAKE_CELL op.
|
||||||
if (cframe->f_lasti >= 0) {
|
if (_PyInterpreterFrame_LASTI(cframe) >= 0) {
|
||||||
// MAKE_CELL and COPY_FREE_VARS have no quickened forms, so no need
|
// MAKE_CELL and COPY_FREE_VARS have no quickened forms, so no need
|
||||||
// to use _PyOpcode_Deopt here:
|
// to use _PyOpcode_Deopt here:
|
||||||
assert(_Py_OPCODE(_PyCode_CODE(co)[0]) == MAKE_CELL ||
|
assert(_Py_OPCODE(_PyCode_CODE(co)[0]) == MAKE_CELL ||
|
||||||
|
|
|
@ -58,12 +58,10 @@ static int prtrace(PyThreadState *, PyObject *, const char *);
|
||||||
static void lltrace_instruction(_PyInterpreterFrame *frame, int opcode, int oparg)
|
static void lltrace_instruction(_PyInterpreterFrame *frame, int opcode, int oparg)
|
||||||
{
|
{
|
||||||
if (HAS_ARG(opcode)) {
|
if (HAS_ARG(opcode)) {
|
||||||
printf("%d: %d, %d\n",
|
printf("%d: %d, %d\n", _PyInterpreterFrame_LASTI(frame), opcode, oparg);
|
||||||
frame->f_lasti, opcode, oparg);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("%d: %d\n",
|
printf("%d: %d\n", _PyInterpreterFrame_LASTI(frame), opcode);
|
||||||
frame->f_lasti, opcode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1249,14 +1247,13 @@ eval_frame_handle_pending(PyThreadState *tstate)
|
||||||
#ifdef Py_STATS
|
#ifdef Py_STATS
|
||||||
#define INSTRUCTION_START(op) \
|
#define INSTRUCTION_START(op) \
|
||||||
do { \
|
do { \
|
||||||
frame->f_lasti = INSTR_OFFSET(); \
|
frame->prev_instr = next_instr++; \
|
||||||
next_instr++; \
|
|
||||||
OPCODE_EXE_INC(op); \
|
OPCODE_EXE_INC(op); \
|
||||||
_py_stats.opcode_stats[lastopcode].pair_count[op]++; \
|
_py_stats.opcode_stats[lastopcode].pair_count[op]++; \
|
||||||
lastopcode = op; \
|
lastopcode = op; \
|
||||||
} while (0)
|
} while (0)
|
||||||
#else
|
#else
|
||||||
#define INSTRUCTION_START(op) frame->f_lasti = INSTR_OFFSET(); next_instr++
|
#define INSTRUCTION_START(op) (frame->prev_instr = next_instr++)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if USE_COMPUTED_GOTOS
|
#if USE_COMPUTED_GOTOS
|
||||||
|
@ -1646,9 +1643,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
|
||||||
consts = co->co_consts; \
|
consts = co->co_consts; \
|
||||||
first_instr = _PyCode_CODE(co); \
|
first_instr = _PyCode_CODE(co); \
|
||||||
} \
|
} \
|
||||||
assert(frame->f_lasti >= -1); \
|
assert(_PyInterpreterFrame_LASTI(frame) >= -1); \
|
||||||
/* Jump back to the last instruction executed... */ \
|
/* Jump back to the last instruction executed... */ \
|
||||||
next_instr = first_instr + frame->f_lasti + 1; \
|
next_instr = frame->prev_instr + 1; \
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame); \
|
stack_pointer = _PyFrame_GetStackPointer(frame); \
|
||||||
/* Set stackdepth to -1. \
|
/* Set stackdepth to -1. \
|
||||||
Update when returning or calling trace function. \
|
Update when returning or calling trace function. \
|
||||||
|
@ -2204,7 +2201,8 @@ handle_eval_breaker:
|
||||||
new_frame->localsplus[i] = NULL;
|
new_frame->localsplus[i] = NULL;
|
||||||
}
|
}
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
frame->f_lasti += INLINE_CACHE_ENTRIES_BINARY_SUBSCR;
|
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
|
||||||
|
frame->prev_instr = next_instr - 1;
|
||||||
new_frame->previous = frame;
|
new_frame->previous = frame;
|
||||||
frame = cframe.current_frame = new_frame;
|
frame = cframe.current_frame = new_frame;
|
||||||
CALL_STAT_INC(inlined_py_calls);
|
CALL_STAT_INC(inlined_py_calls);
|
||||||
|
@ -2605,7 +2603,7 @@ handle_eval_breaker:
|
||||||
if (oparg) {
|
if (oparg) {
|
||||||
PyObject *lasti = PEEK(oparg + 1);
|
PyObject *lasti = PEEK(oparg + 1);
|
||||||
if (PyLong_Check(lasti)) {
|
if (PyLong_Check(lasti)) {
|
||||||
frame->f_lasti = PyLong_AsLong(lasti);
|
frame->prev_instr = first_instr + PyLong_AsLong(lasti);
|
||||||
assert(!_PyErr_Occurred(tstate));
|
assert(!_PyErr_Occurred(tstate));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -4603,7 +4601,8 @@ handle_eval_breaker:
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
frame->f_lasti += INLINE_CACHE_ENTRIES_CALL;
|
JUMPBY(INLINE_CACHE_ENTRIES_CALL);
|
||||||
|
frame->prev_instr = next_instr - 1;
|
||||||
new_frame->previous = frame;
|
new_frame->previous = frame;
|
||||||
cframe.current_frame = frame = new_frame;
|
cframe.current_frame = frame = new_frame;
|
||||||
CALL_STAT_INC(inlined_py_calls);
|
CALL_STAT_INC(inlined_py_calls);
|
||||||
|
@ -4708,7 +4707,8 @@ handle_eval_breaker:
|
||||||
}
|
}
|
||||||
STACK_SHRINK(2-is_meth);
|
STACK_SHRINK(2-is_meth);
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
frame->f_lasti += INLINE_CACHE_ENTRIES_CALL;
|
JUMPBY(INLINE_CACHE_ENTRIES_CALL);
|
||||||
|
frame->prev_instr = next_instr - 1;
|
||||||
new_frame->previous = frame;
|
new_frame->previous = frame;
|
||||||
frame = cframe.current_frame = new_frame;
|
frame = cframe.current_frame = new_frame;
|
||||||
goto start_frame;
|
goto start_frame;
|
||||||
|
@ -4748,7 +4748,8 @@ handle_eval_breaker:
|
||||||
}
|
}
|
||||||
STACK_SHRINK(2-is_meth);
|
STACK_SHRINK(2-is_meth);
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
frame->f_lasti += INLINE_CACHE_ENTRIES_CALL;
|
JUMPBY(INLINE_CACHE_ENTRIES_CALL);
|
||||||
|
frame->prev_instr = next_instr - 1;
|
||||||
new_frame->previous = frame;
|
new_frame->previous = frame;
|
||||||
frame = cframe.current_frame = new_frame;
|
frame = cframe.current_frame = new_frame;
|
||||||
goto start_frame;
|
goto start_frame;
|
||||||
|
@ -5435,8 +5436,8 @@ handle_eval_breaker:
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (tstate->tracing == 0) {
|
if (tstate->tracing == 0) {
|
||||||
int instr_prev = frame->f_lasti;
|
int instr_prev = _PyInterpreterFrame_LASTI(frame);
|
||||||
frame->f_lasti = INSTR_OFFSET();
|
frame->prev_instr = next_instr;
|
||||||
TRACING_NEXTOPARG();
|
TRACING_NEXTOPARG();
|
||||||
switch(opcode) {
|
switch(opcode) {
|
||||||
case COPY_FREE_VARS:
|
case COPY_FREE_VARS:
|
||||||
|
@ -5474,7 +5475,7 @@ handle_eval_breaker:
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
/* Reload possibly changed frame fields */
|
/* Reload possibly changed frame fields */
|
||||||
JUMPTO(frame->f_lasti);
|
next_instr = frame->prev_instr;
|
||||||
|
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
frame->stacktop = -1;
|
frame->stacktop = -1;
|
||||||
|
@ -5491,10 +5492,8 @@ handle_eval_breaker:
|
||||||
#else
|
#else
|
||||||
default:
|
default:
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr,
|
fprintf(stderr, "XXX lineno: %d, opcode: %d\n",
|
||||||
"XXX lineno: %d, opcode: %d\n",
|
_PyInterpreterFrame_GetLine(frame), opcode);
|
||||||
PyCode_Addr2Line(frame->f_code, frame->f_lasti*sizeof(_Py_CODEUNIT)),
|
|
||||||
opcode);
|
|
||||||
_PyErr_SetString(tstate, PyExc_SystemError, "unknown opcode");
|
_PyErr_SetString(tstate, PyExc_SystemError, "unknown opcode");
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
@ -5598,7 +5597,8 @@ exception_unwind:
|
||||||
}
|
}
|
||||||
PyObject *exc, *val, *tb;
|
PyObject *exc, *val, *tb;
|
||||||
if (lasti) {
|
if (lasti) {
|
||||||
PyObject *lasti = PyLong_FromLong(frame->f_lasti);
|
int frame_lasti = _PyInterpreterFrame_LASTI(frame);
|
||||||
|
PyObject *lasti = PyLong_FromLong(frame_lasti);
|
||||||
if (lasti == NULL) {
|
if (lasti == NULL) {
|
||||||
goto exception_unwind;
|
goto exception_unwind;
|
||||||
}
|
}
|
||||||
|
@ -6690,9 +6690,10 @@ call_trace(Py_tracefunc func, PyObject *obj,
|
||||||
int old_what = tstate->tracing_what;
|
int old_what = tstate->tracing_what;
|
||||||
tstate->tracing_what = what;
|
tstate->tracing_what = what;
|
||||||
PyThreadState_EnterTracing(tstate);
|
PyThreadState_EnterTracing(tstate);
|
||||||
assert(frame->f_lasti >= 0);
|
assert(_PyInterpreterFrame_LASTI(frame) >= 0);
|
||||||
initialize_trace_info(&tstate->trace_info, frame);
|
initialize_trace_info(&tstate->trace_info, frame);
|
||||||
f->f_lineno = _PyCode_CheckLineNumber(frame->f_lasti*sizeof(_Py_CODEUNIT), &tstate->trace_info.bounds);
|
int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
|
||||||
|
f->f_lineno = _PyCode_CheckLineNumber(addr, &tstate->trace_info.bounds);
|
||||||
result = func(obj, f, what, arg);
|
result = func(obj, f, what, arg);
|
||||||
f->f_lineno = 0;
|
f->f_lineno = 0;
|
||||||
PyThreadState_LeaveTracing(tstate);
|
PyThreadState_LeaveTracing(tstate);
|
||||||
|
@ -6742,7 +6743,8 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
|
||||||
else {
|
else {
|
||||||
lastline = _PyCode_CheckLineNumber(instr_prev*sizeof(_Py_CODEUNIT), &tstate->trace_info.bounds);
|
lastline = _PyCode_CheckLineNumber(instr_prev*sizeof(_Py_CODEUNIT), &tstate->trace_info.bounds);
|
||||||
}
|
}
|
||||||
int line = _PyCode_CheckLineNumber(frame->f_lasti*sizeof(_Py_CODEUNIT), &tstate->trace_info.bounds);
|
int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
|
||||||
|
int line = _PyCode_CheckLineNumber(addr, &tstate->trace_info.bounds);
|
||||||
PyFrameObject *f = _PyFrame_GetFrameObject(frame);
|
PyFrameObject *f = _PyFrame_GetFrameObject(frame);
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -6750,10 +6752,10 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
|
||||||
if (line != -1 && f->f_trace_lines) {
|
if (line != -1 && f->f_trace_lines) {
|
||||||
/* Trace backward edges (except in 'yield from') or if line number has changed */
|
/* Trace backward edges (except in 'yield from') or if line number has changed */
|
||||||
int trace = line != lastline ||
|
int trace = line != lastline ||
|
||||||
(frame->f_lasti < instr_prev &&
|
(_PyInterpreterFrame_LASTI(frame) < instr_prev &&
|
||||||
// SEND has no quickened forms, so no need to use _PyOpcode_Deopt
|
// SEND has no quickened forms, so no need to use _PyOpcode_Deopt
|
||||||
// here:
|
// here:
|
||||||
_Py_OPCODE(_PyCode_CODE(frame->f_code)[frame->f_lasti]) != SEND);
|
_Py_OPCODE(*frame->prev_instr) != SEND);
|
||||||
if (trace) {
|
if (trace) {
|
||||||
result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None);
|
result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None);
|
||||||
}
|
}
|
||||||
|
@ -7685,7 +7687,7 @@ dtrace_function_entry(_PyInterpreterFrame *frame)
|
||||||
PyCodeObject *code = frame->f_code;
|
PyCodeObject *code = frame->f_code;
|
||||||
filename = PyUnicode_AsUTF8(code->co_filename);
|
filename = PyUnicode_AsUTF8(code->co_filename);
|
||||||
funcname = PyUnicode_AsUTF8(code->co_name);
|
funcname = PyUnicode_AsUTF8(code->co_name);
|
||||||
lineno = PyCode_Addr2Line(frame->f_code, frame->f_lasti*sizeof(_Py_CODEUNIT));
|
lineno = _PyInterpreterFrame_GetLine(frame);
|
||||||
|
|
||||||
PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno);
|
PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno);
|
||||||
}
|
}
|
||||||
|
@ -7700,7 +7702,7 @@ dtrace_function_return(_PyInterpreterFrame *frame)
|
||||||
PyCodeObject *code = frame->f_code;
|
PyCodeObject *code = frame->f_code;
|
||||||
filename = PyUnicode_AsUTF8(code->co_filename);
|
filename = PyUnicode_AsUTF8(code->co_filename);
|
||||||
funcname = PyUnicode_AsUTF8(code->co_name);
|
funcname = PyUnicode_AsUTF8(code->co_name);
|
||||||
lineno = PyCode_Addr2Line(frame->f_code, frame->f_lasti*sizeof(_Py_CODEUNIT));
|
lineno = _PyInterpreterFrame_GetLine(frame);
|
||||||
|
|
||||||
PyDTrace_FUNCTION_RETURN(filename, funcname, lineno);
|
PyDTrace_FUNCTION_RETURN(filename, funcname, lineno);
|
||||||
}
|
}
|
||||||
|
@ -7718,11 +7720,12 @@ maybe_dtrace_line(_PyInterpreterFrame *frame,
|
||||||
*/
|
*/
|
||||||
initialize_trace_info(trace_info, frame);
|
initialize_trace_info(trace_info, frame);
|
||||||
int lastline = _PyCode_CheckLineNumber(instr_prev*sizeof(_Py_CODEUNIT), &trace_info->bounds);
|
int lastline = _PyCode_CheckLineNumber(instr_prev*sizeof(_Py_CODEUNIT), &trace_info->bounds);
|
||||||
int line = _PyCode_CheckLineNumber(frame->f_lasti*sizeof(_Py_CODEUNIT), &trace_info->bounds);
|
int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
|
||||||
|
int line = _PyCode_CheckLineNumber(addr, &trace_info->bounds);
|
||||||
if (line != -1) {
|
if (line != -1) {
|
||||||
/* Trace backward edges or first instruction of a new line */
|
/* Trace backward edges or first instruction of a new line */
|
||||||
if (frame->f_lasti < instr_prev ||
|
if (_PyInterpreterFrame_LASTI(frame) < instr_prev ||
|
||||||
(line != lastline && frame->f_lasti*sizeof(_Py_CODEUNIT) == (unsigned int)trace_info->bounds.ar_start))
|
(line != lastline && addr == trace_info->bounds.ar_start))
|
||||||
{
|
{
|
||||||
co_filename = PyUnicode_AsUTF8(frame->f_code->co_filename);
|
co_filename = PyUnicode_AsUTF8(frame->f_code->co_filename);
|
||||||
if (!co_filename) {
|
if (!co_filename) {
|
||||||
|
|
|
@ -127,3 +127,10 @@ _PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func)
|
||||||
_PyFrame_InitializeSpecials(new_frame, func, NULL, code->co_nlocalsplus);
|
_PyFrame_InitializeSpecials(new_frame, func, NULL, code->co_nlocalsplus);
|
||||||
return new_frame;
|
return new_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyInterpreterFrame_GetLine(_PyInterpreterFrame *frame)
|
||||||
|
{
|
||||||
|
int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
|
||||||
|
return PyCode_Addr2Line(frame->f_code, addr);
|
||||||
|
}
|
||||||
|
|
|
@ -238,8 +238,8 @@ _PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame)
|
||||||
{
|
{
|
||||||
assert(tb_next == NULL || PyTraceBack_Check(tb_next));
|
assert(tb_next == NULL || PyTraceBack_Check(tb_next));
|
||||||
assert(frame != NULL);
|
assert(frame != NULL);
|
||||||
|
int addr = _PyInterpreterFrame_LASTI(frame->f_frame) * sizeof(_Py_CODEUNIT);
|
||||||
return tb_create_raw((PyTracebackObject *)tb_next, frame, frame->f_frame->f_lasti*sizeof(_Py_CODEUNIT),
|
return tb_create_raw((PyTracebackObject *)tb_next, frame, addr,
|
||||||
PyFrame_GetLineNumber(frame));
|
PyFrame_GetLineNumber(frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1180,7 +1180,7 @@ dump_frame(int fd, _PyInterpreterFrame *frame)
|
||||||
PUTS(fd, "???");
|
PUTS(fd, "???");
|
||||||
}
|
}
|
||||||
|
|
||||||
int lineno = PyCode_Addr2Line(code, frame->f_lasti*sizeof(_Py_CODEUNIT));
|
int lineno = _PyInterpreterFrame_GetLine(frame);
|
||||||
PUTS(fd, ", line ");
|
PUTS(fd, ", line ");
|
||||||
if (lineno >= 0) {
|
if (lineno >= 0) {
|
||||||
_Py_DumpDecimal(fd, (size_t)lineno);
|
_Py_DumpDecimal(fd, (size_t)lineno);
|
||||||
|
|
|
@ -1015,7 +1015,10 @@ class PyFramePtr:
|
||||||
return self._f_special("nlocalsplus", int_from_int)
|
return self._f_special("nlocalsplus", int_from_int)
|
||||||
|
|
||||||
def _f_lasti(self):
|
def _f_lasti(self):
|
||||||
return self._f_special("f_lasti", int_from_int)
|
codeunit_p = gdb.lookup_type("_Py_CODEUNIT").pointer()
|
||||||
|
prev_instr = self._gdbval["prev_instr"]
|
||||||
|
first_instr = self._f_code().field("co_code_adaptive").cast(codeunit_p)
|
||||||
|
return int(prev_instr - first_instr)
|
||||||
|
|
||||||
def is_entry(self):
|
def is_entry(self):
|
||||||
return self._f_special("is_entry", bool)
|
return self._f_special("is_entry", bool)
|
||||||
|
|
Loading…
Reference in New Issue