PyObject *f_locals; /* Strong reference, may be NULL. Only valid if not on C stack */
PyFrameObject *frame_obj; /* Strong reference, may be NULL. Only valid if not on C stack */
_Py_CODEUNIT *instr_ptr; /* Instruction currently executing (or about to begin) */
- int stacktop; /* Offset of TOS from localsplus */
+ _PyStackRef *stackpointer;
uint16_t return_offset; /* Only relevant during a function call */
char owner;
/* Locals and stack */
}
static inline _PyStackRef _PyFrame_StackPeek(_PyInterpreterFrame *f) {
- assert(f->stacktop > _PyFrame_GetCode(f)->co_nlocalsplus);
- assert(!PyStackRef_IsNull(f->localsplus[f->stacktop-1]));
- return f->localsplus[f->stacktop-1];
+ assert(f->stackpointer > f->localsplus + _PyFrame_GetCode(f)->co_nlocalsplus);
+ assert(!PyStackRef_IsNull(f->stackpointer[-1]));
+ return f->stackpointer[-1];
}
static inline _PyStackRef _PyFrame_StackPop(_PyInterpreterFrame *f) {
- assert(f->stacktop > _PyFrame_GetCode(f)->co_nlocalsplus);
- f->stacktop--;
- return f->localsplus[f->stacktop];
+ assert(f->stackpointer > f->localsplus + _PyFrame_GetCode(f)->co_nlocalsplus);
+ f->stackpointer--;
+ return *f->stackpointer;
}
static inline void _PyFrame_StackPush(_PyInterpreterFrame *f, _PyStackRef value) {
- f->localsplus[f->stacktop] = value;
- f->stacktop++;
+ *f->stackpointer = value;
+ f->stackpointer++;
}
#define FRAME_SPECIALS_SIZE ((int)((sizeof(_PyInterpreterFrame)-1)/sizeof(PyObject *)))
static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)
{
- assert(src->stacktop >= _PyFrame_GetCode(src)->co_nlocalsplus);
*dest = *src;
- for (int i = 1; i < src->stacktop; i++) {
+ assert(src->stackpointer != NULL);
+ int stacktop = (int)(src->stackpointer - src->localsplus);
+ assert(stacktop >= _PyFrame_GetCode(src)->co_nlocalsplus);
+ dest->stackpointer = dest->localsplus + stacktop;
+ for (int i = 1; i < stacktop; i++) {
dest->localsplus[i] = src->localsplus[i];
}
// Don't leave a dangling pointer to the old frame when creating generators
frame->f_builtins = func->func_builtins;
frame->f_globals = func->func_globals;
frame->f_locals = locals;
- frame->stacktop = code->co_nlocalsplus;
+ frame->stackpointer = frame->localsplus + code->co_nlocalsplus;
frame->frame_obj = NULL;
frame->instr_ptr = _PyCode_CODE(code);
frame->return_offset = 0;
return frame->localsplus;
}
-/* Fetches the stack pointer, and sets stacktop to -1.
- Having stacktop <= 0 ensures that invalid
- values are not visible to the cycle GC.
- We choose -1 rather than 0 to assist debugging. */
+/* Fetches the stack pointer, and sets stackpointer to NULL.
+ Having stackpointer == NULL ensures that invalid
+ values are not visible to the cycle GC. */
static inline _PyStackRef*
_PyFrame_GetStackPointer(_PyInterpreterFrame *frame)
{
- _PyStackRef *sp = frame->localsplus + frame->stacktop;
- frame->stacktop = -1;
+ assert(frame->stackpointer != NULL);
+ _PyStackRef *sp = frame->stackpointer;
+ frame->stackpointer = NULL;
return sp;
}
static inline void
_PyFrame_SetStackPointer(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer)
{
- frame->stacktop = (int)(stack_pointer - frame->localsplus);
+ assert(frame->stackpointer == NULL);
+ frame->stackpointer = stack_pointer;
}
/* Determine whether a frame is incomplete.
frame->f_globals = NULL;
#endif
frame->f_locals = NULL;
- frame->stacktop = code->co_nlocalsplus + stackdepth;
+ assert(stackdepth <= code->co_stacksize);
+ frame->stackpointer = frame->localsplus + code->co_nlocalsplus + stackdepth;
frame->frame_obj = NULL;
frame->instr_ptr = _PyCode_CODE(code);
frame->owner = FRAME_OWNED_BY_THREAD;
Py_CLEAR(frame->f_funcobj);
Py_CLEAR(frame->f_locals);
_PyStackRef *locals = _PyFrame_GetLocalsArray(frame);
- for (int i = 0; i < frame->stacktop; i++) {
- PyStackRef_CLEAR(locals[i]);
+ _PyStackRef *sp = frame->stackpointer;
+ while (sp > locals) {
+ sp--;
+ PyStackRef_CLEAR(*sp);
}
}
Py_CLEAR(f->f_back);
/* locals and stack */
_PyStackRef *locals = _PyFrame_GetLocalsArray(f->f_frame);
- assert(f->f_frame->stacktop >= 0);
- for (int i = 0; i < f->f_frame->stacktop; i++) {
- PyStackRef_CLEAR(locals[i]);
+ _PyStackRef *sp = f->f_frame->stackpointer;
+ assert(sp >= locals);
+ while (sp > locals) {
+ sp--;
+ PyStackRef_CLEAR(*sp);
}
- f->f_frame->stacktop = 0;
+ f->f_frame->stackpointer = locals;
Py_CLEAR(f->f_frame->f_locals);
return 0;
}
return 0;
}
- PyObject *value = PyStackRef_AsPyObjectBorrow(frame->localsplus[i]);
- if (frame->stacktop) {
+ PyObject *value = NULL;
+ if (frame->stackpointer == NULL || frame->stackpointer > frame->localsplus + i) {
+ value = PyStackRef_AsPyObjectBorrow(frame->localsplus[i]);
if (kind & CO_FAST_FREE) {
// The cell was set by COPY_FREE_VARS.
assert(value != NULL && PyCell_Check(value));
}
}
}
- else {
- assert(value == NULL);
- }
*pvalue = value;
return 1;
}
Py_VISIT(_PyFrame_GetCode(frame));
/* locals */
_PyStackRef *locals = _PyFrame_GetLocalsArray(frame);
- int i = 0;
+ _PyStackRef *sp = frame->stackpointer;
/* locals and stack */
- for (; i <frame->stacktop; i++) {
- Py_VISIT(PyStackRef_AsPyObjectBorrow(locals[i]));
+ while (sp > locals) {
+ sp--;
+ Py_VISIT(PyStackRef_AsPyObjectBorrow(*sp));
}
return 0;
}
assert(frame->owner != FRAME_OWNED_BY_CSTACK);
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_ssize_t size = ((char*)frame->stackpointer) - (char *)frame;
Py_INCREF(_PyFrame_GetCode(frame));
memcpy((_PyInterpreterFrame *)f->_f_frame_data, frame, size);
frame = (_PyInterpreterFrame *)f->_f_frame_data;
+ frame->stackpointer = (_PyStackRef *)(((char *)frame) + size);
f->f_frame = frame;
frame->owner = FRAME_OWNED_BY_FRAME_OBJECT;
if (_PyFrame_IsIncomplete(frame)) {
void
_PyFrame_ClearLocals(_PyInterpreterFrame *frame)
{
- assert(frame->stacktop >= 0);
- int stacktop = frame->stacktop;
- frame->stacktop = 0;
- for (int i = 0; i < stacktop; i++) {
- PyStackRef_XCLOSE(frame->localsplus[i]);
+ assert(frame->stackpointer != NULL);
+ _PyStackRef *sp = frame->stackpointer;
+ _PyStackRef *locals = frame->localsplus;
+ frame->stackpointer = locals;
+ while (sp > locals) {
+ sp--;
+ PyStackRef_XCLOSE(*sp);
}
Py_CLEAR(frame->f_locals);
}