Skip to content

Commit 7c1d63f

Browse files
optimize it as well
1 parent db7d8e6 commit 7c1d63f

File tree

5 files changed

+30
-0
lines changed

5 files changed

+30
-0
lines changed

Include/internal/pycore_optimizer_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ typedef struct _Py_UOpsAbstractFrame {
147147
int stack_len;
148148
int locals_len;
149149
bool caller; // We have made a call from this frame during the trace
150+
bool is_recursion_checked;
150151
JitOptRef callable;
151152
PyFunctionObject *func;
152153
PyCodeObject *code;

Lib/test/test_capi/test_opt.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2813,6 +2813,23 @@ def testfunc(n):
28132813
self.assertNotIn("_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", uops)
28142814
self.assertNotIn("_GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS", uops)
28152815

2816+
def test_check_recursion_limit_deduplicated(self):
2817+
def testfunc(n):
2818+
x = 0
2819+
for _ in range(n):
2820+
y = "hello"
2821+
a = y.upper()
2822+
b = y.lower()
2823+
x += len(a)
2824+
x += len(b)
2825+
return x
2826+
res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
2827+
self.assertEqual(res, TIER2_THRESHOLD * 10)
2828+
self.assertIsNotNone(ex)
2829+
uops = get_opnames(ex)
2830+
self.assertIn("_CALL_METHOD_DESCRIPTOR_NOARGS_INLINE", uops)
2831+
self.assertEqual(count_ops(ex, "_CHECK_RECURSION_LIMIT"), 1)
2832+
28162833
def test_call_intrinsic_1(self):
28172834
def testfunc(n):
28182835
x = 0

Python/optimizer_bytecodes.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,6 +1394,13 @@ dummy_func(void) {
13941394
}
13951395
}
13961396

1397+
op(_CHECK_RECURSION_LIMIT, ( -- )) {
1398+
if (ctx->frame->is_recursion_checked) {
1399+
ADD_OP(_NOP, 0, 0);
1400+
}
1401+
ctx->frame->is_recursion_checked = true;
1402+
}
1403+
13971404
op(_CALL_METHOD_DESCRIPTOR_NOARGS, (callable, self_or_null, args[oparg] -- res)) {
13981405
PyObject *callable_o = sym_get_const(ctx, callable);
13991406
if (callable_o && Py_IS_TYPE(callable_o, &PyMethodDescr_Type)

Python/optimizer_cases.c.h

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

Python/optimizer_symbols.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,6 +1514,7 @@ _Py_uop_frame_new(
15141514
frame->globals_watched = false;
15151515
frame->func = NULL;
15161516
frame->caller = false;
1517+
frame->is_recursion_checked = false;
15171518
if (ctx->locals.used > ctx->locals.end || ctx->stack.used > ctx->stack.end) {
15181519
ctx->done = true;
15191520
ctx->out_of_space = true;

0 commit comments

Comments
 (0)