Skip to content

Commit a78f43b

Browse files
authored
gh-134584: Eliminate redundant refcounting from _CALL_TUPLE_1 (GH-135860)
1 parent 44d3dc6 commit a78f43b

File tree

11 files changed

+71
-41
lines changed

11 files changed

+71
-41
lines changed

Include/internal/pycore_opcode_metadata.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_ids.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

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

Lib/test/test_capi/test_opt.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1925,6 +1925,21 @@ def testfunc(n):
19251925
uops = get_opnames(ex)
19261926
self.assertNotIn("_GUARD_IS_NOT_NONE_POP", uops)
19271927

1928+
def test_call_tuple_1_pop_top(self):
1929+
def testfunc(n):
1930+
x = 0
1931+
for _ in range(n):
1932+
t = tuple(())
1933+
x += len(t) == 0
1934+
return x
1935+
1936+
res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
1937+
self.assertEqual(res, TIER2_THRESHOLD)
1938+
self.assertIsNotNone(ex)
1939+
uops = get_opnames(ex)
1940+
self.assertIn("_CALL_TUPLE_1", uops)
1941+
self.assertIn("_POP_TOP_NOP", uops)
1942+
19281943
def test_call_str_1(self):
19291944
def testfunc(n):
19301945
x = 0
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Eliminate redundant refcounting from ``_CALL_TUPLE_1``. Patch by Noam Cohen

Python/bytecodes.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4068,17 +4068,14 @@ dummy_func(
40684068
DEOPT_IF(callable_o != (PyObject *)&PyTuple_Type);
40694069
}
40704070

4071-
op(_CALL_TUPLE_1, (callable, null, arg -- res)) {
4071+
op(_CALL_TUPLE_1, (callable, null, arg -- res, a)) {
40724072
PyObject *arg_o = PyStackRef_AsPyObjectBorrow(arg);
40734073

40744074
assert(oparg == 1);
40754075
STAT_INC(CALL, hit);
40764076
PyObject *res_o = PySequence_Tuple(arg_o);
4077-
DEAD(null);
4078-
DEAD(callable);
4079-
(void)callable; // Silence compiler warnings about unused variables
4080-
(void)null;
4081-
PyStackRef_CLOSE(arg);
4077+
a = arg;
4078+
INPUTS_DEAD();
40824079
ERROR_IF(res_o == NULL);
40834080
res = PyStackRef_FromPyObjectSteal(res_o);
40844081
}
@@ -4089,6 +4086,7 @@ dummy_func(
40894086
_GUARD_NOS_NULL +
40904087
_GUARD_CALLABLE_TUPLE_1 +
40914088
_CALL_TUPLE_1 +
4089+
POP_TOP +
40924090
_CHECK_PERIODIC_AT_END;
40934091

40944092
op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
@@ -5455,6 +5453,12 @@ dummy_func(
54555453
}
54565454
}
54575455

5456+
label(pop_3_error) {
5457+
stack_pointer -= 3;
5458+
assert(WITHIN_STACK_BOUNDS());
5459+
goto error;
5460+
}
5461+
54585462
label(pop_2_error) {
54595463
stack_pointer -= 2;
54605464
assert(WITHIN_STACK_BOUNDS());

Python/executor_cases.c.h

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

Python/generated_cases.c.h

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

Python/opcode_targets.h

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

Python/optimizer_bytecodes.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,7 @@ dummy_func(void) {
10971097
}
10981098
}
10991099

1100-
op(_CALL_TUPLE_1, (callable, null, arg -- res)) {
1100+
op(_CALL_TUPLE_1, (callable, null, arg -- res, a)) {
11011101
if (sym_matches_type(arg, &PyTuple_Type)) {
11021102
// e.g. tuple((1, 2)) or tuple(foo) where foo is known to be a tuple
11031103
// Note: we must strip the reference information because it goes
@@ -1107,6 +1107,7 @@ dummy_func(void) {
11071107
else {
11081108
res = sym_new_type(ctx, &PyTuple_Type);
11091109
}
1110+
a = arg;
11101111
}
11111112

11121113
op(_GUARD_TOS_LIST, (tos -- tos)) {

0 commit comments

Comments
 (0)