mirror of https://github.com/python/cpython
bpo-44990: Change layout of evaluation frames. "Layout B" (GH-27933)
Places the locals between the specials and stack. This is the more "natural" layout for a C struct, makes the code simpler and gives a slight speedup (~1%)
This commit is contained in:
parent
214c2e5d91
commit
f9242d50b1
|
@ -29,10 +29,9 @@ typedef struct _interpreter_frame {
|
||||||
PyObject *generator;
|
PyObject *generator;
|
||||||
struct _interpreter_frame *previous;
|
struct _interpreter_frame *previous;
|
||||||
int f_lasti; /* Last instruction if called */
|
int f_lasti; /* Last instruction if called */
|
||||||
int stackdepth; /* Depth of value stack */
|
int stacktop; /* Offset of TOS from localsplus */
|
||||||
int nlocalsplus;
|
PyFrameState f_state; /* What state the frame is in */
|
||||||
PyFrameState f_state; /* What state the frame is in */
|
PyObject *localsplus[1];
|
||||||
PyObject *stack[1];
|
|
||||||
} InterpreterFrame;
|
} InterpreterFrame;
|
||||||
|
|
||||||
static inline int _PyFrame_IsRunnable(InterpreterFrame *f) {
|
static inline int _PyFrame_IsRunnable(InterpreterFrame *f) {
|
||||||
|
@ -47,6 +46,26 @@ static inline int _PyFrameHasCompleted(InterpreterFrame *f) {
|
||||||
return f->f_state > FRAME_EXECUTING;
|
return f->f_state > FRAME_EXECUTING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline PyObject **_PyFrame_Stackbase(InterpreterFrame *f) {
|
||||||
|
return f->localsplus + f->f_code->co_nlocalsplus;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline PyObject *_PyFrame_StackPeek(InterpreterFrame *f) {
|
||||||
|
assert(f->stacktop > f->f_code->co_nlocalsplus);
|
||||||
|
return f->localsplus[f->stacktop-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline PyObject *_PyFrame_StackPop(InterpreterFrame *f) {
|
||||||
|
assert(f->stacktop > f->f_code->co_nlocalsplus);
|
||||||
|
f->stacktop--;
|
||||||
|
return f->localsplus[f->stacktop];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _PyFrame_StackPush(InterpreterFrame *f, PyObject *value) {
|
||||||
|
f->localsplus[f->stacktop] = value;
|
||||||
|
f->stacktop++;
|
||||||
|
}
|
||||||
|
|
||||||
#define FRAME_SPECIALS_SIZE ((sizeof(InterpreterFrame)-1)/sizeof(PyObject *))
|
#define FRAME_SPECIALS_SIZE ((sizeof(InterpreterFrame)-1)/sizeof(PyObject *))
|
||||||
|
|
||||||
InterpreterFrame *
|
InterpreterFrame *
|
||||||
|
@ -61,8 +80,7 @@ _PyFrame_InitializeSpecials(
|
||||||
frame->f_builtins = Py_NewRef(con->fc_builtins);
|
frame->f_builtins = Py_NewRef(con->fc_builtins);
|
||||||
frame->f_globals = Py_NewRef(con->fc_globals);
|
frame->f_globals = Py_NewRef(con->fc_globals);
|
||||||
frame->f_locals = Py_XNewRef(locals);
|
frame->f_locals = Py_XNewRef(locals);
|
||||||
frame->nlocalsplus = nlocalsplus;
|
frame->stacktop = nlocalsplus;
|
||||||
frame->stackdepth = 0;
|
|
||||||
frame->frame_obj = NULL;
|
frame->frame_obj = NULL;
|
||||||
frame->generator = NULL;
|
frame->generator = NULL;
|
||||||
frame->f_lasti = -1;
|
frame->f_lasti = -1;
|
||||||
|
@ -75,7 +93,19 @@ _PyFrame_InitializeSpecials(
|
||||||
static inline PyObject**
|
static inline PyObject**
|
||||||
_PyFrame_GetLocalsArray(InterpreterFrame *frame)
|
_PyFrame_GetLocalsArray(InterpreterFrame *frame)
|
||||||
{
|
{
|
||||||
return ((PyObject **)frame) - frame->nlocalsplus;
|
return frame->localsplus;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline PyObject**
|
||||||
|
_PyFrame_GetStackPointer(InterpreterFrame *frame)
|
||||||
|
{
|
||||||
|
return frame->localsplus+frame->stacktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_PyFrame_SetStackPointer(InterpreterFrame *frame, PyObject **stack_pointer)
|
||||||
|
{
|
||||||
|
frame->stacktop = (int)(stack_pointer - frame->localsplus);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For use by _PyFrame_GetFrameObject
|
/* For use by _PyFrame_GetFrameObject
|
||||||
|
|
|
@ -397,9 +397,7 @@ first_line_not_before(int *lines, int len, int line)
|
||||||
static void
|
static void
|
||||||
frame_stack_pop(PyFrameObject *f)
|
frame_stack_pop(PyFrameObject *f)
|
||||||
{
|
{
|
||||||
assert(f->f_frame->stackdepth > 0);
|
PyObject *v = _PyFrame_StackPop(f->f_frame);
|
||||||
f->f_frame->stackdepth--;
|
|
||||||
PyObject *v = f->f_frame->stack[f->f_frame->stackdepth];
|
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,14 +631,10 @@ frame_dealloc(PyFrameObject *f)
|
||||||
Py_CLEAR(frame->f_builtins);
|
Py_CLEAR(frame->f_builtins);
|
||||||
Py_CLEAR(frame->f_locals);
|
Py_CLEAR(frame->f_locals);
|
||||||
PyObject **locals = _PyFrame_GetLocalsArray(frame);
|
PyObject **locals = _PyFrame_GetLocalsArray(frame);
|
||||||
for (int i = 0; i < co->co_nlocalsplus; i++) {
|
for (int i = 0; i < frame->stacktop; i++) {
|
||||||
Py_CLEAR(locals[i]);
|
Py_CLEAR(locals[i]);
|
||||||
}
|
}
|
||||||
/* stack */
|
PyMem_Free(frame);
|
||||||
for (int i = 0; i < frame->stackdepth; i++) {
|
|
||||||
Py_CLEAR(frame->stack[i]);
|
|
||||||
}
|
|
||||||
PyMem_Free(locals);
|
|
||||||
}
|
}
|
||||||
Py_CLEAR(f->f_back);
|
Py_CLEAR(f->f_back);
|
||||||
Py_CLEAR(f->f_trace);
|
Py_CLEAR(f->f_trace);
|
||||||
|
@ -686,17 +680,13 @@ frame_tp_clear(PyFrameObject *f)
|
||||||
|
|
||||||
Py_CLEAR(f->f_trace);
|
Py_CLEAR(f->f_trace);
|
||||||
|
|
||||||
/* locals */
|
/* locals and stack */
|
||||||
PyObject **locals = _PyFrame_GetLocalsArray(f->f_frame);
|
PyObject **locals = _PyFrame_GetLocalsArray(f->f_frame);
|
||||||
for (int i = 0; i < f->f_frame->nlocalsplus; i++) {
|
assert(f->f_frame->stacktop >= 0);
|
||||||
|
for (int i = 0; i < f->f_frame->stacktop; i++) {
|
||||||
Py_CLEAR(locals[i]);
|
Py_CLEAR(locals[i]);
|
||||||
}
|
}
|
||||||
|
f->f_frame->stacktop = 0;
|
||||||
/* stack */
|
|
||||||
for (int i = 0; i < f->f_frame->stackdepth; i++) {
|
|
||||||
Py_CLEAR(f->f_frame->stack[i]);
|
|
||||||
}
|
|
||||||
f->f_frame->stackdepth = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,8 +190,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
|
||||||
/* Push arg onto the frame's value stack */
|
/* Push arg onto the frame's value stack */
|
||||||
result = arg ? arg : Py_None;
|
result = arg ? arg : Py_None;
|
||||||
Py_INCREF(result);
|
Py_INCREF(result);
|
||||||
frame->stack[frame->stackdepth] = result;
|
_PyFrame_StackPush(frame, result);
|
||||||
frame->stackdepth++;
|
|
||||||
|
|
||||||
frame->previous = tstate->frame;
|
frame->previous = tstate->frame;
|
||||||
|
|
||||||
|
@ -350,8 +349,7 @@ _PyGen_yf(PyGenObject *gen)
|
||||||
|
|
||||||
if (code[(frame->f_lasti+1)*sizeof(_Py_CODEUNIT)] != YIELD_FROM)
|
if (code[(frame->f_lasti+1)*sizeof(_Py_CODEUNIT)] != YIELD_FROM)
|
||||||
return NULL;
|
return NULL;
|
||||||
assert(frame->stackdepth > 0);
|
yf = _PyFrame_StackPeek(frame);
|
||||||
yf = frame->stack[frame->stackdepth-1];
|
|
||||||
Py_INCREF(yf);
|
Py_INCREF(yf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,9 +467,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
PyObject *val;
|
PyObject *val;
|
||||||
/* Pop subiterator from stack */
|
/* Pop subiterator from stack */
|
||||||
assert(gen->gi_xframe->stackdepth > 0);
|
ret = _PyFrame_StackPop(gen->gi_xframe);
|
||||||
gen->gi_xframe->stackdepth--;
|
|
||||||
ret = gen->gi_xframe->stack[gen->gi_xframe->stackdepth];
|
|
||||||
assert(ret == yf);
|
assert(ret == yf);
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
/* Termination repetition of YIELD_FROM */
|
/* Termination repetition of YIELD_FROM */
|
||||||
|
|
|
@ -8874,7 +8874,7 @@ super_init_without_args(PyFrameObject *f, PyCodeObject *co,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(f->f_frame->nlocalsplus > 0);
|
assert(f->f_frame->f_code->co_nlocalsplus > 0);
|
||||||
PyObject *firstarg = _PyFrame_GetLocalsArray(f->f_frame)[0];
|
PyObject *firstarg = _PyFrame_GetLocalsArray(f->f_frame)[0];
|
||||||
// The first argument might be a cell.
|
// The first argument might be a cell.
|
||||||
if (firstarg != NULL && (_PyLocals_GetKind(co->co_localspluskinds, 0) & CO_FAST_CELL)) {
|
if (firstarg != NULL && (_PyLocals_GetKind(co->co_localspluskinds, 0) & CO_FAST_CELL)) {
|
||||||
|
|
|
@ -1367,7 +1367,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
|
||||||
|
|
||||||
/* The stack can grow at most MAXINT deep, as co_nlocals and
|
/* The stack can grow at most MAXINT deep, as co_nlocals and
|
||||||
co_stacksize are ints. */
|
co_stacksize are ints. */
|
||||||
#define STACK_LEVEL() ((int)(stack_pointer - frame->stack))
|
#define STACK_LEVEL() ((int)(stack_pointer - _PyFrame_Stackbase(frame)))
|
||||||
#define EMPTY() (STACK_LEVEL() == 0)
|
#define EMPTY() (STACK_LEVEL() == 0)
|
||||||
#define TOP() (stack_pointer[-1])
|
#define TOP() (stack_pointer[-1])
|
||||||
#define SECOND() (stack_pointer[-2])
|
#define SECOND() (stack_pointer[-2])
|
||||||
|
@ -1413,7 +1413,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
|
||||||
|
|
||||||
/* Local variable macros */
|
/* Local variable macros */
|
||||||
|
|
||||||
#define GETLOCAL(i) (localsplus[i])
|
#define GETLOCAL(i) (frame->localsplus[i])
|
||||||
|
|
||||||
/* The SETLOCAL() macro must not DECREF the local variable in-place and
|
/* The SETLOCAL() macro must not DECREF the local variable in-place and
|
||||||
then store the new value; it must copy the old value to a temporary
|
then store the new value; it must copy the old value to a temporary
|
||||||
|
@ -1559,7 +1559,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
|
||||||
|
|
||||||
PyObject *names = co->co_names;
|
PyObject *names = co->co_names;
|
||||||
PyObject *consts = co->co_consts;
|
PyObject *consts = co->co_consts;
|
||||||
PyObject **localsplus = _PyFrame_GetLocalsArray(frame);
|
|
||||||
_Py_CODEUNIT *first_instr = co->co_firstinstr;
|
_Py_CODEUNIT *first_instr = co->co_firstinstr;
|
||||||
/*
|
/*
|
||||||
frame->f_lasti refers to the index of the last instruction,
|
frame->f_lasti refers to the index of the last instruction,
|
||||||
|
@ -1578,14 +1577,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
|
||||||
*/
|
*/
|
||||||
assert(frame->f_lasti >= -1);
|
assert(frame->f_lasti >= -1);
|
||||||
_Py_CODEUNIT *next_instr = first_instr + frame->f_lasti + 1;
|
_Py_CODEUNIT *next_instr = first_instr + frame->f_lasti + 1;
|
||||||
PyObject **stack_pointer = frame->stack + frame->stackdepth;
|
PyObject **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.
|
||||||
Having f_stackdepth <= 0 ensures that invalid
|
Having stackdepth <= 0 ensures that invalid
|
||||||
values are not visible to the cycle GC.
|
values are not visible to the cycle GC.
|
||||||
We choose -1 rather than 0 to assist debugging.
|
We choose -1 rather than 0 to assist debugging.
|
||||||
*/
|
*/
|
||||||
frame->stackdepth = -1;
|
frame->stacktop = -1;
|
||||||
frame->f_state = FRAME_EXECUTING;
|
frame->f_state = FRAME_EXECUTING;
|
||||||
|
|
||||||
#ifdef LLTRACE
|
#ifdef LLTRACE
|
||||||
|
@ -1668,7 +1667,7 @@ check_eval_breaker:
|
||||||
int err;
|
int err;
|
||||||
/* see maybe_call_line_trace()
|
/* see maybe_call_line_trace()
|
||||||
for expository comments */
|
for expository comments */
|
||||||
frame->stackdepth = (int)(stack_pointer - frame->stack);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
|
|
||||||
err = maybe_call_line_trace(tstate->c_tracefunc,
|
err = maybe_call_line_trace(tstate->c_tracefunc,
|
||||||
tstate->c_traceobj,
|
tstate->c_traceobj,
|
||||||
|
@ -1679,8 +1678,9 @@ check_eval_breaker:
|
||||||
}
|
}
|
||||||
/* Reload possibly changed frame fields */
|
/* Reload possibly changed frame fields */
|
||||||
JUMPTO(frame->f_lasti);
|
JUMPTO(frame->f_lasti);
|
||||||
stack_pointer = frame->stack+frame->stackdepth;
|
|
||||||
frame->stackdepth = -1;
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
frame->stacktop = -1;
|
||||||
TRACING_NEXTOPARG();
|
TRACING_NEXTOPARG();
|
||||||
}
|
}
|
||||||
PRE_DISPATCH_GOTO();
|
PRE_DISPATCH_GOTO();
|
||||||
|
@ -2439,7 +2439,7 @@ check_eval_breaker:
|
||||||
retval = POP();
|
retval = POP();
|
||||||
assert(EMPTY());
|
assert(EMPTY());
|
||||||
frame->f_state = FRAME_RETURNED;
|
frame->f_state = FRAME_RETURNED;
|
||||||
frame->stackdepth = 0;
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
goto exiting;
|
goto exiting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2627,7 +2627,7 @@ check_eval_breaker:
|
||||||
assert(frame->f_lasti > 0);
|
assert(frame->f_lasti > 0);
|
||||||
frame->f_lasti -= 1;
|
frame->f_lasti -= 1;
|
||||||
frame->f_state = FRAME_SUSPENDED;
|
frame->f_state = FRAME_SUSPENDED;
|
||||||
frame->stackdepth = (int)(stack_pointer - frame->stack);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
goto exiting;
|
goto exiting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2644,7 +2644,7 @@ check_eval_breaker:
|
||||||
retval = w;
|
retval = w;
|
||||||
}
|
}
|
||||||
frame->f_state = FRAME_SUSPENDED;
|
frame->f_state = FRAME_SUSPENDED;
|
||||||
frame->stackdepth = (int)(stack_pointer - frame->stack);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
goto exiting;
|
goto exiting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4346,7 +4346,7 @@ check_eval_breaker:
|
||||||
oparg = cache->adaptive.original_oparg;
|
oparg = cache->adaptive.original_oparg;
|
||||||
STAT_DEC(LOAD_METHOD, unquickened);
|
STAT_DEC(LOAD_METHOD, unquickened);
|
||||||
JUMP_TO_INSTRUCTION(LOAD_METHOD);
|
JUMP_TO_INSTRUCTION(LOAD_METHOD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(LOAD_METHOD_CACHED): {
|
TARGET(LOAD_METHOD_CACHED): {
|
||||||
|
@ -4364,7 +4364,7 @@ check_eval_breaker:
|
||||||
assert(cache1->tp_version != 0);
|
assert(cache1->tp_version != 0);
|
||||||
assert(self_cls->tp_dictoffset >= 0);
|
assert(self_cls->tp_dictoffset >= 0);
|
||||||
assert(Py_TYPE(self_cls)->tp_dictoffset > 0);
|
assert(Py_TYPE(self_cls)->tp_dictoffset > 0);
|
||||||
|
|
||||||
// inline version of _PyObject_GetDictPtr for offset >= 0
|
// inline version of _PyObject_GetDictPtr for offset >= 0
|
||||||
PyObject *dict = self_cls->tp_dictoffset != 0 ?
|
PyObject *dict = self_cls->tp_dictoffset != 0 ?
|
||||||
*(PyObject **) ((char *)self + self_cls->tp_dictoffset) : NULL;
|
*(PyObject **) ((char *)self + self_cls->tp_dictoffset) : NULL;
|
||||||
|
@ -4817,17 +4817,20 @@ exception_unwind:
|
||||||
assert(_PyErr_Occurred(tstate));
|
assert(_PyErr_Occurred(tstate));
|
||||||
|
|
||||||
/* Pop remaining stack entries. */
|
/* Pop remaining stack entries. */
|
||||||
while (!EMPTY()) {
|
PyObject **stackbase = _PyFrame_Stackbase(frame);
|
||||||
|
while (stack_pointer > stackbase) {
|
||||||
PyObject *o = POP();
|
PyObject *o = POP();
|
||||||
Py_XDECREF(o);
|
Py_XDECREF(o);
|
||||||
}
|
}
|
||||||
frame->stackdepth = 0;
|
assert(STACK_LEVEL() == 0);
|
||||||
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
frame->f_state = FRAME_RAISED;
|
frame->f_state = FRAME_RAISED;
|
||||||
goto exiting;
|
goto exiting;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(STACK_LEVEL() >= level);
|
assert(STACK_LEVEL() >= level);
|
||||||
while (STACK_LEVEL() > level) {
|
PyObject **new_top = _PyFrame_Stackbase(frame) + level;
|
||||||
|
while (stack_pointer > new_top) {
|
||||||
PyObject *v = POP();
|
PyObject *v = POP();
|
||||||
Py_XDECREF(v);
|
Py_XDECREF(v);
|
||||||
}
|
}
|
||||||
|
@ -4981,7 +4984,7 @@ missing_arguments(PyThreadState *tstate, PyCodeObject *co,
|
||||||
end = start + co->co_kwonlyargcount;
|
end = start + co->co_kwonlyargcount;
|
||||||
}
|
}
|
||||||
for (i = start; i < end; i++) {
|
for (i = start; i < end; i++) {
|
||||||
if (GETLOCAL(i) == NULL) {
|
if (localsplus[i] == NULL) {
|
||||||
PyObject *raw = PyTuple_GET_ITEM(co->co_localsplusnames, i);
|
PyObject *raw = PyTuple_GET_ITEM(co->co_localsplusnames, i);
|
||||||
PyObject *name = PyObject_Repr(raw);
|
PyObject *name = PyObject_Repr(raw);
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
|
@ -5010,7 +5013,7 @@ too_many_positional(PyThreadState *tstate, PyCodeObject *co,
|
||||||
assert((co->co_flags & CO_VARARGS) == 0);
|
assert((co->co_flags & CO_VARARGS) == 0);
|
||||||
/* Count missing keyword-only args. */
|
/* Count missing keyword-only args. */
|
||||||
for (i = co_argcount; i < co_argcount + co->co_kwonlyargcount; i++) {
|
for (i = co_argcount; i < co_argcount + co->co_kwonlyargcount; i++) {
|
||||||
if (GETLOCAL(i) != NULL) {
|
if (localsplus[i] != NULL) {
|
||||||
kwonly_given++;
|
kwonly_given++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5217,7 +5220,8 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
|
||||||
if (co->co_flags & CO_VARARGS) {
|
if (co->co_flags & CO_VARARGS) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
SETLOCAL(i, kwdict);
|
assert(localsplus[i] == NULL);
|
||||||
|
localsplus[i] = kwdict;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
kwdict = NULL;
|
kwdict = NULL;
|
||||||
|
@ -5234,7 +5238,8 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
|
||||||
for (j = 0; j < n; j++) {
|
for (j = 0; j < n; j++) {
|
||||||
PyObject *x = args[j];
|
PyObject *x = args[j];
|
||||||
Py_INCREF(x);
|
Py_INCREF(x);
|
||||||
SETLOCAL(j, x);
|
assert(localsplus[j] == NULL);
|
||||||
|
localsplus[j] = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pack other positional arguments into the *args argument */
|
/* Pack other positional arguments into the *args argument */
|
||||||
|
@ -5243,7 +5248,8 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
|
||||||
if (u == NULL) {
|
if (u == NULL) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
SETLOCAL(total_args, u);
|
assert(localsplus[total_args] == NULL);
|
||||||
|
localsplus[total_args] = u;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle keyword arguments */
|
/* Handle keyword arguments */
|
||||||
|
@ -5307,14 +5313,14 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
kw_found:
|
kw_found:
|
||||||
if (GETLOCAL(j) != NULL) {
|
if (localsplus[j] != NULL) {
|
||||||
_PyErr_Format(tstate, PyExc_TypeError,
|
_PyErr_Format(tstate, PyExc_TypeError,
|
||||||
"%U() got multiple values for argument '%S'",
|
"%U() got multiple values for argument '%S'",
|
||||||
con->fc_qualname, keyword);
|
con->fc_qualname, keyword);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
Py_INCREF(value);
|
Py_INCREF(value);
|
||||||
SETLOCAL(j, value);
|
localsplus[j] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5331,7 +5337,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
|
||||||
Py_ssize_t m = co->co_argcount - defcount;
|
Py_ssize_t m = co->co_argcount - defcount;
|
||||||
Py_ssize_t missing = 0;
|
Py_ssize_t missing = 0;
|
||||||
for (i = argcount; i < m; i++) {
|
for (i = argcount; i < m; i++) {
|
||||||
if (GETLOCAL(i) == NULL) {
|
if (localsplus[i] == NULL) {
|
||||||
missing++;
|
missing++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5347,10 +5353,10 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
|
||||||
if (defcount) {
|
if (defcount) {
|
||||||
PyObject **defs = &PyTuple_GET_ITEM(con->fc_defaults, 0);
|
PyObject **defs = &PyTuple_GET_ITEM(con->fc_defaults, 0);
|
||||||
for (; i < defcount; i++) {
|
for (; i < defcount; i++) {
|
||||||
if (GETLOCAL(m+i) == NULL) {
|
if (localsplus[m+i] == NULL) {
|
||||||
PyObject *def = defs[i];
|
PyObject *def = defs[i];
|
||||||
Py_INCREF(def);
|
Py_INCREF(def);
|
||||||
SETLOCAL(m+i, def);
|
localsplus[m+i] = def;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5360,14 +5366,14 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
|
||||||
if (co->co_kwonlyargcount > 0) {
|
if (co->co_kwonlyargcount > 0) {
|
||||||
Py_ssize_t missing = 0;
|
Py_ssize_t missing = 0;
|
||||||
for (i = co->co_argcount; i < total_args; i++) {
|
for (i = co->co_argcount; i < total_args; i++) {
|
||||||
if (GETLOCAL(i) != NULL)
|
if (localsplus[i] != NULL)
|
||||||
continue;
|
continue;
|
||||||
PyObject *varname = PyTuple_GET_ITEM(co->co_localsplusnames, i);
|
PyObject *varname = PyTuple_GET_ITEM(co->co_localsplusnames, i);
|
||||||
if (con->fc_kwdefaults != NULL) {
|
if (con->fc_kwdefaults != NULL) {
|
||||||
PyObject *def = PyDict_GetItemWithError(con->fc_kwdefaults, varname);
|
PyObject *def = PyDict_GetItemWithError(con->fc_kwdefaults, varname);
|
||||||
if (def) {
|
if (def) {
|
||||||
Py_INCREF(def);
|
Py_INCREF(def);
|
||||||
SETLOCAL(i, def);
|
localsplus[i] = def;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (_PyErr_Occurred(tstate)) {
|
else if (_PyErr_Occurred(tstate)) {
|
||||||
|
@ -5407,18 +5413,17 @@ make_coro_frame(PyThreadState *tstate,
|
||||||
assert(con->fc_defaults == NULL || PyTuple_CheckExact(con->fc_defaults));
|
assert(con->fc_defaults == NULL || PyTuple_CheckExact(con->fc_defaults));
|
||||||
PyCodeObject *code = (PyCodeObject *)con->fc_code;
|
PyCodeObject *code = (PyCodeObject *)con->fc_code;
|
||||||
int size = code->co_nlocalsplus+code->co_stacksize + FRAME_SPECIALS_SIZE;
|
int size = code->co_nlocalsplus+code->co_stacksize + FRAME_SPECIALS_SIZE;
|
||||||
PyObject **localsarray = PyMem_Malloc(sizeof(PyObject *)*size);
|
InterpreterFrame *frame = (InterpreterFrame *)PyMem_Malloc(sizeof(PyObject *)*size);
|
||||||
if (localsarray == NULL) {
|
if (frame == NULL) {
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (Py_ssize_t i=0; i < code->co_nlocalsplus; i++) {
|
for (Py_ssize_t i=0; i < code->co_nlocalsplus; i++) {
|
||||||
localsarray[i] = NULL;
|
frame->localsplus[i] = NULL;
|
||||||
}
|
}
|
||||||
InterpreterFrame *frame = (InterpreterFrame *)(localsarray + code->co_nlocalsplus);
|
|
||||||
_PyFrame_InitializeSpecials(frame, con, locals, code->co_nlocalsplus);
|
_PyFrame_InitializeSpecials(frame, con, locals, code->co_nlocalsplus);
|
||||||
assert(frame->frame_obj == NULL);
|
assert(frame->frame_obj == NULL);
|
||||||
if (initialize_locals(tstate, con, localsarray, args, argcount, kwnames)) {
|
if (initialize_locals(tstate, con, frame->localsplus, args, argcount, kwnames)) {
|
||||||
_PyFrame_Clear(frame, 1);
|
_PyFrame_Clear(frame, 1);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -5497,7 +5502,7 @@ _PyEval_Vector(PyThreadState *tstate, PyFrameConstructor *con,
|
||||||
}
|
}
|
||||||
assert (tstate->interp->eval_frame != NULL);
|
assert (tstate->interp->eval_frame != NULL);
|
||||||
PyObject *retval = _PyEval_EvalFrame(tstate, frame, 0);
|
PyObject *retval = _PyEval_EvalFrame(tstate, frame, 0);
|
||||||
assert(frame->stackdepth == 0);
|
assert(_PyFrame_GetStackPointer(frame) == _PyFrame_Stackbase(frame));
|
||||||
if (_PyEvalFrameClearAndPop(tstate, frame)) {
|
if (_PyEvalFrameClearAndPop(tstate, frame)) {
|
||||||
retval = NULL;
|
retval = NULL;
|
||||||
}
|
}
|
||||||
|
@ -6764,7 +6769,6 @@ unicode_concatenate(PyThreadState *tstate, PyObject *v, PyObject *w,
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case STORE_FAST:
|
case STORE_FAST:
|
||||||
{
|
{
|
||||||
PyObject **localsplus = _PyFrame_GetLocalsArray(frame);
|
|
||||||
if (GETLOCAL(oparg) == v)
|
if (GETLOCAL(oparg) == v)
|
||||||
SETLOCAL(oparg, NULL);
|
SETLOCAL(oparg, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -14,13 +14,11 @@ _PyFrame_Traverse(InterpreterFrame *frame, visitproc visit, void *arg)
|
||||||
Py_VISIT(frame->f_code);
|
Py_VISIT(frame->f_code);
|
||||||
/* locals */
|
/* locals */
|
||||||
PyObject **locals = _PyFrame_GetLocalsArray(frame);
|
PyObject **locals = _PyFrame_GetLocalsArray(frame);
|
||||||
for (int i = 0; i < frame->nlocalsplus; i++) {
|
int i = 0;
|
||||||
|
/* locals and stack */
|
||||||
|
for (; i <frame->stacktop; i++) {
|
||||||
Py_VISIT(locals[i]);
|
Py_VISIT(locals[i]);
|
||||||
}
|
}
|
||||||
/* stack */
|
|
||||||
for (int i = 0; i <frame->stackdepth; i++) {
|
|
||||||
Py_VISIT(frame->stack[i]);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,17 +45,15 @@ _PyFrame_MakeAndSetFrameObject(InterpreterFrame *frame)
|
||||||
static InterpreterFrame *
|
static InterpreterFrame *
|
||||||
copy_frame_to_heap(InterpreterFrame *frame)
|
copy_frame_to_heap(InterpreterFrame *frame)
|
||||||
{
|
{
|
||||||
|
assert(frame->stacktop >= frame->f_code->co_nlocalsplus);
|
||||||
Py_ssize_t size = ((char*)&frame->stack[frame->stackdepth]) - (char *)_PyFrame_GetLocalsArray(frame);
|
Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char *)frame;
|
||||||
PyObject **copy = PyMem_Malloc(size);
|
InterpreterFrame *copy = PyMem_Malloc(size);
|
||||||
if (copy == NULL) {
|
if (copy == NULL) {
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyObject **locals = _PyFrame_GetLocalsArray(frame);
|
memcpy(copy, frame, size);
|
||||||
memcpy(copy, locals, size);
|
return copy;
|
||||||
InterpreterFrame *res = (InterpreterFrame *)(copy + frame->nlocalsplus);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -103,7 +99,6 @@ take_ownership(PyFrameObject *f, InterpreterFrame *frame)
|
||||||
int
|
int
|
||||||
_PyFrame_Clear(InterpreterFrame * frame, int take)
|
_PyFrame_Clear(InterpreterFrame * frame, int take)
|
||||||
{
|
{
|
||||||
PyObject **localsarray = ((PyObject **)frame)-frame->nlocalsplus;
|
|
||||||
if (frame->frame_obj) {
|
if (frame->frame_obj) {
|
||||||
PyFrameObject *f = frame->frame_obj;
|
PyFrameObject *f = frame->frame_obj;
|
||||||
frame->frame_obj = NULL;
|
frame->frame_obj = NULL;
|
||||||
|
@ -120,16 +115,13 @@ _PyFrame_Clear(InterpreterFrame * frame, int take)
|
||||||
}
|
}
|
||||||
Py_DECREF(f);
|
Py_DECREF(f);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < frame->nlocalsplus; i++) {
|
assert(_PyFrame_GetStackPointer(frame) >= _PyFrame_Stackbase(frame));
|
||||||
Py_XDECREF(localsarray[i]);
|
for (int i = 0; i < frame->stacktop; i++) {
|
||||||
}
|
Py_XDECREF(frame->localsplus[i]);
|
||||||
assert(frame->stackdepth >= 0);
|
|
||||||
for (int i = 0; i < frame->stackdepth; i++) {
|
|
||||||
Py_DECREF(frame->stack[i]);
|
|
||||||
}
|
}
|
||||||
clear_specials(frame);
|
clear_specials(frame);
|
||||||
if (take) {
|
if (take) {
|
||||||
PyMem_Free(_PyFrame_GetLocalsArray(frame));
|
PyMem_Free(frame);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2045,21 +2045,21 @@ _PyThreadState_PushFrame(PyThreadState *tstate, PyFrameConstructor *con, PyObjec
|
||||||
size_t size = nlocalsplus + code->co_stacksize +
|
size_t size = nlocalsplus + code->co_stacksize +
|
||||||
FRAME_SPECIALS_SIZE;
|
FRAME_SPECIALS_SIZE;
|
||||||
assert(size < INT_MAX/sizeof(PyObject *));
|
assert(size < INT_MAX/sizeof(PyObject *));
|
||||||
PyObject **localsarray = tstate->datastack_top;
|
PyObject **base = tstate->datastack_top;
|
||||||
PyObject **top = localsarray + size;
|
PyObject **top = base + size;
|
||||||
if (top >= tstate->datastack_limit) {
|
if (top >= tstate->datastack_limit) {
|
||||||
localsarray = push_chunk(tstate, (int)size);
|
base = push_chunk(tstate, (int)size);
|
||||||
if (localsarray == NULL) {
|
if (base == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tstate->datastack_top = top;
|
tstate->datastack_top = top;
|
||||||
}
|
}
|
||||||
InterpreterFrame * frame = (InterpreterFrame *)(localsarray + nlocalsplus);
|
InterpreterFrame *frame = (InterpreterFrame *)base;
|
||||||
_PyFrame_InitializeSpecials(frame, con, locals, nlocalsplus);
|
_PyFrame_InitializeSpecials(frame, con, locals, nlocalsplus);
|
||||||
for (int i=0; i < nlocalsplus; i++) {
|
for (int i=0; i < nlocalsplus; i++) {
|
||||||
localsarray[i] = NULL;
|
frame->localsplus[i] = NULL;
|
||||||
}
|
}
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
@ -2067,8 +2067,8 @@ _PyThreadState_PushFrame(PyThreadState *tstate, PyFrameConstructor *con, PyObjec
|
||||||
void
|
void
|
||||||
_PyThreadState_PopFrame(PyThreadState *tstate, InterpreterFrame * frame)
|
_PyThreadState_PopFrame(PyThreadState *tstate, InterpreterFrame * frame)
|
||||||
{
|
{
|
||||||
PyObject **locals = _PyFrame_GetLocalsArray(frame);
|
PyObject **base = (PyObject **)frame;
|
||||||
if (locals == &tstate->datastack_chunk->data[0]) {
|
if (base == &tstate->datastack_chunk->data[0]) {
|
||||||
_PyStackChunk *chunk = tstate->datastack_chunk;
|
_PyStackChunk *chunk = tstate->datastack_chunk;
|
||||||
_PyStackChunk *previous = chunk->previous;
|
_PyStackChunk *previous = chunk->previous;
|
||||||
tstate->datastack_top = &previous->data[previous->top];
|
tstate->datastack_top = &previous->data[previous->top];
|
||||||
|
@ -2077,8 +2077,8 @@ _PyThreadState_PopFrame(PyThreadState *tstate, InterpreterFrame * frame)
|
||||||
tstate->datastack_limit = (PyObject **)(((char *)previous) + previous->size);
|
tstate->datastack_limit = (PyObject **)(((char *)previous) + previous->size);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert(tstate->datastack_top >= locals);
|
assert(tstate->datastack_top >= base);
|
||||||
tstate->datastack_top = locals;
|
tstate->datastack_top = base;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -958,9 +958,11 @@ class PyFramePtr:
|
||||||
if self.is_optimized_out():
|
if self.is_optimized_out():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
obj_ptr_ptr = gdb.lookup_type("PyObject").pointer().pointer()
|
obj_ptr_ptr = gdb.lookup_type("PyObject").pointer().pointer()
|
||||||
base = self._gdbval.cast(obj_ptr_ptr)
|
|
||||||
localsplus = base - self._f_nlocalsplus()
|
localsplus = self._gdbval["localsplus"].cast(obj_ptr_ptr)
|
||||||
|
|
||||||
for i in safe_range(self.co_nlocals):
|
for i in safe_range(self.co_nlocals):
|
||||||
pyop_value = PyObjectPtr.from_pyobject_ptr(localsplus[i])
|
pyop_value = PyObjectPtr.from_pyobject_ptr(localsplus[i])
|
||||||
if pyop_value.is_null():
|
if pyop_value.is_null():
|
||||||
|
|
Loading…
Reference in New Issue