Skip to content

Commit 5fbc47a

Browse files
Add tests
1 parent 0ca5cd1 commit 5fbc47a

3 files changed

Lines changed: 52 additions & 0 deletions

File tree

Lib/test/test_capi/test_opt.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,9 +1515,33 @@ def test_jit_error_pops(self):
15151515
with self.assertRaises(TypeError):
15161516
{item for item in items}
15171517

1518+
def test_global_guard_hoisted_if_possible(self):
1519+
def testfunc(n):
1520+
for i in range(n):
1521+
# Only works on functions promoted to constants
1522+
# The inner global promoted guard should be hoisted out.
1523+
global_foo(i)
1524+
1525+
opt = _testinternalcapi.new_uop_optimizer()
1526+
with temporary_optimizer(opt):
1527+
testfunc(20)
1528+
1529+
ex = get_first_executor(testfunc)
1530+
self.assertIsNotNone(ex)
1531+
uops = get_opnames(ex)
1532+
opnames = list(iter_opnames(ex))
1533+
self.assertIn("_PUSH_FRAME", uops)
1534+
# Hoisted version
1535+
self.assertIn("_CHECK_FUNCTION_STACK", uops)
1536+
# Only 1 outer guard
1537+
self.assertLessEqual(opnames.count("_CHECK_FUNCTION"), 1)
15181538

15191539
def global_identity(x):
15201540
return x
15211541

1542+
def global_foo(x):
1543+
return global_identity(x)
1544+
1545+
15221546
if __name__ == "__main__":
15231547
unittest.main()

Python/optimizer_bytecodes.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,21 @@ dummy_func(void) {
594594
// with partial evaluation later on.
595595
(void)func_version;
596596
if (ctx->frame->frame_creation_inst != NULL) {
597+
// Already hoisted. Slot can't be used again.
598+
if ((ctx->frame->frame_creation_inst - 1)->opcode == _CHECK_FUNCTION_STACK) {
599+
break;
600+
}
597601
assert((ctx->frame->frame_creation_inst - 1)->opcode == _NOP);
602+
bool has_interfering_inst = false;
603+
for (_PyUOpInstruction *start = ctx->frame->frame_creation_inst + 1; start < this_instr; start++) {
604+
if (_PyUop_Flags[start->opcode] & HAS_ESCAPES_FLAG) {
605+
has_interfering_inst = true;
606+
break;
607+
}
608+
}
609+
if (has_interfering_inst) {
610+
break;
611+
}
598612
*(ctx->frame->frame_creation_inst - 1) = *this_instr;
599613
(ctx->frame->frame_creation_inst - 1)->opcode = _CHECK_FUNCTION_STACK;
600614
(ctx->frame->frame_creation_inst - 1)->oparg = ctx->frame->frame_creation_inst->oparg;

Python/optimizer_cases.c.h

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)