Skip to content

Commit ce02765

Browse files
Fix: mark interpreter frames as tier 2 or not (python#34)
* fix: mark interpreter frames as tier 2 or not * Test: Added tests for python#33 --------- Co-authored-by: Ken Jin <[email protected]>
1 parent 33988cf commit ce02765

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

Include/internal/pycore_frame.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,14 @@ typedef struct _PyInterpreterFrame {
6262
int stacktop; /* Offset of TOS from localsplus */
6363
uint16_t yield_offset;
6464
char owner;
65+
bool is_tier2;
6566
/* Locals and stack and unboxed bit mask */
6667
PyObject *localsplus[1];
6768
} _PyInterpreterFrame;
6869

6970
static inline int
7071
_PyInterpreterFrame_LASTI(_PyInterpreterFrame *f) {
71-
if (f->f_code->_tier2_info != NULL) {
72+
if (f->is_tier2 && f->f_code->_tier2_info != NULL) {
7273
return ((int)((f)->prev_instr - f->f_code->_tier2_info->_bb_space->u_code));
7374
}
7475
return ((int)((f)->prev_instr - _PyCode_CODE((f)->f_code)));
@@ -130,9 +131,11 @@ _PyFrame_Initialize(
130131
frame->stacktop = code->co_nlocalsplus;
131132
frame->frame_obj = NULL;
132133
if (code->_tier2_info != NULL) {
134+
frame->is_tier2 = true;
133135
frame->prev_instr = code->_tier2_info->_entry_bb->tier2_start - 1;
134136
}
135137
else {
138+
frame->is_tier2 = false;
136139
frame->prev_instr = _PyCode_CODE(code) - 1;
137140
}
138141
frame->yield_offset = 0;

Python/frame.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@ _PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg)
1717
Py_VISIT(frame->f_code);
1818
/* locals */
1919
PyObject **locals = _PyFrame_GetLocalsArray(frame);
20+
char *unboxed_bitmask = _PyFrame_GetUnboxedBitMask(frame);
2021
int i = 0;
2122
/* locals and stack */
2223
for (; i <frame->stacktop; i++) {
23-
Py_VISIT(locals[i]);
24+
if (!unboxed_bitmask[i]) {
25+
Py_VISIT(locals[i]);
26+
}
2427
}
2528
return 0;
2629
}

Python/tier2.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2486,6 +2486,7 @@ _Py_CODEUNIT *
24862486
_PyCode_Tier2Warmup(_PyInterpreterFrame *frame, _Py_CODEUNIT *next_instr)
24872487
{
24882488
PyCodeObject *code = frame->f_code;
2489+
frame->is_tier2 = false;
24892490
if (code->_tier2_warmup != 0) {
24902491
code->_tier2_warmup++;
24912492
if (code->_tier2_warmup >= 0) {
@@ -2494,6 +2495,11 @@ _PyCode_Tier2Warmup(_PyInterpreterFrame *frame, _Py_CODEUNIT *next_instr)
24942495
// just fall back to the tier 1 interpreter.
24952496
_Py_CODEUNIT *next = _PyCode_Tier2Initialize(frame, next_instr);
24962497
if (next != NULL) {
2498+
assert(!frame->is_tier2);
2499+
frame->is_tier2 = true;
2500+
_Py_CODEUNIT *curr = (next_instr - 1);
2501+
assert(curr->op.code == RESUME || curr->op.code == RESUME_QUICK);
2502+
curr->op.code = RESUME_QUICK;
24972503
return next;
24982504
}
24992505
}

tier2_test.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ def f(a):
519519
######################################################################
520520
# Tests for: Tier 2 recursive functions block generation #
521521
######################################################################
522-
with TestInfo("tier 2 BB_TEST_POP_IF_FALSE flag setting"):
522+
with TestInfo("tier 2 recursive functions block generation"):
523523
# See https://github.com/pylbbv/pylbbv/issues/23 for more information.
524524
def f(x):
525525
# Force specialisation
@@ -535,4 +535,19 @@ def f(x):
535535

536536
# As long as it doesn't crash, everything's good.
537537

538+
######################################################################
539+
# Tests for: Tier 2 specialisation in inner call #
540+
######################################################################
541+
with TestInfo("tier 2 specialisation in inner call"):
542+
# See https://github.com/pylbbv/pylbbv/issues/33 for more information.
543+
def f(x):
544+
if x == 0: return 0
545+
if x%2: return f(x-1)
546+
return f(x-1)
547+
548+
for i in range(15): f(3)
549+
f(3)
550+
551+
# As long as it doesn't crash, everything's good.
552+
538553
print("Tests completed ^-^")

0 commit comments

Comments
 (0)