Skip to content

Commit

Permalink
Implement _GROW_TIER2_FRAME without adding tier2_extra_size
Browse files Browse the repository at this point in the history
  • Loading branch information
gvanrossum committed Mar 5, 2024
1 parent b04215f commit e84eeed
Show file tree
Hide file tree
Showing 6 changed files with 15 additions and 42 deletions.
31 changes: 0 additions & 31 deletions Include/internal/pycore_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ typedef struct _PyInterpreterFrame {
_Py_CODEUNIT *instr_ptr; /* Instruction currently executing (or about to begin) */
int stacktop; /* Offset of TOS from localsplus */
uint16_t return_offset; /* Only relevant during a function call */
uint16_t tier2_extra_size; /* How many extra entries is at the end of localsplus for tier 2 inlining */
char owner;
/* Locals and stack */
PyObject *localsplus[1];
Expand Down Expand Up @@ -132,7 +131,6 @@ _PyFrame_Initialize(
frame->instr_ptr = _PyCode_CODE(code);
frame->return_offset = 0;
frame->owner = FRAME_OWNED_BY_THREAD;
frame->tier2_extra_size = 0;

for (int i = null_locals_from; i < code->co_nlocalsplus; i++) {
frame->localsplus[i] = NULL;
Expand Down Expand Up @@ -260,35 +258,6 @@ _PyThreadState_PushFrame(PyThreadState *tstate, size_t size);

void _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame *frame);


/* Converts frame for tier 2.
* Adds stack space at the end of the current frame for Tier 2 execution.
* The frame that is being expanded MUST be the current executing frame, and
* it must be at the top of the datastack.
* */
static inline int
_PyFrame_ConvertToTier2(PyThreadState *tstate, _PyInterpreterFrame *frame,
int localsplus_grow)
{
assert(localsplus_grow > 0);
// Already grown previously
if (frame->tier2_extra_size >= localsplus_grow) {
return 0;
}
if (frame->owner != FRAME_OWNED_BY_THREAD) {
return 1;
}
if (!_PyThreadState_HasStackSpace(tstate, localsplus_grow)) {
return 1;
}
assert(_PyThreadState_HasStackSpace(tstate, localsplus_grow));
assert(tstate->current_frame == frame);
tstate->datastack_top += localsplus_grow;
assert(tstate->datastack_top < tstate->datastack_limit);
frame->tier2_extra_size += localsplus_grow;
return 0;
}

/* Pushes a frame without checking for space.
* Must be guarded by _PyThreadState_HasStackSpace()
* Consumes reference to func. */
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_uop_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Lib/test/test_sys.py
Original file line number Diff line number Diff line change
Expand Up @@ -1550,7 +1550,7 @@ class C(object): pass
def func():
return sys._getframe()
x = func()
check(x, size('3Pi3c7P4ic??2P'))
check(x, size('3Pi3c7P2ic??2P'))
# function
def func(): pass
check(func, size('15Pi'))
Expand All @@ -1567,7 +1567,7 @@ def bar(cls):
check(bar, size('PP'))
# generator
def get_gen(): yield 1
check(get_gen(), size('PP4P4c7P4ic??2P'))
check(get_gen(), size('PP4P4c7P2ic??2P'))
# iterator
check(iter('abc'), size('lP'))
# callable-iterator
Expand Down
5 changes: 4 additions & 1 deletion Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -4175,7 +4175,10 @@ dummy_func(
}

op(_GROW_TIER2_FRAME, (--)) {
DEOPT_IF(_PyFrame_ConvertToTier2(tstate, frame, oparg));
DEOPT_IF(frame->owner != FRAME_OWNED_BY_THREAD);
DEOPT_IF(stack_pointer + oparg > tstate->datastack_limit);
assert(stack_pointer <= tstate->datastack_top);
tstate->datastack_top = stack_pointer + oparg;
}


Expand Down
10 changes: 4 additions & 6 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1675,11 +1675,10 @@ static void
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:
// This doesn't apply to tier 2 frames.
assert(frame->tier2_extra_size == 0 ? (PyObject **)frame + _PyFrame_GetCode(frame)->co_framesize ==
tstate->datastack_top : 1);
// // 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 + _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);
Expand Down Expand Up @@ -1793,7 +1792,6 @@ _PyEvalFramePushAndInit_Ex(PyThreadState *tstate, PyFunctionObject *func,
return NULL;
}


PyObject *
_PyEval_Vector(PyThreadState *tstate, PyFunctionObject *func,
PyObject *locals,
Expand Down
5 changes: 4 additions & 1 deletion Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e84eeed

Please sign in to comment.