Skip to content

Commit 1fb8e0e

Browse files
gh-134584: Eliminate redundant refcounting from _CALL{_BUILTIN_O, _METHOD_DESCRIPTOR_O} (GH-143330)
Co-authored-by: Ken Jin <kenjin4096@gmail.com>
1 parent 422ca07 commit 1fb8e0e

File tree

9 files changed

+177
-76
lines changed

9 files changed

+177
-76
lines changed

Include/internal/pycore_opcode_metadata.h

Lines changed: 2 additions & 2 deletions
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: 4 additions & 4 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: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2201,7 +2201,8 @@ def test_call_builtin_o(self):
22012201
def testfunc(n):
22022202
x = 0
22032203
for _ in range(n):
2204-
y = abs(1)
2204+
my_abs = abs
2205+
y = my_abs(1)
22052206
x += y
22062207
return x
22072208

@@ -2210,7 +2211,26 @@ def testfunc(n):
22102211
self.assertIsNotNone(ex)
22112212
uops = get_opnames(ex)
22122213
self.assertIn("_CALL_BUILTIN_O", uops)
2213-
self.assertIn("_POP_TOP", uops)
2214+
self.assertNotIn("_POP_TOP", uops)
2215+
self.assertIn("_POP_TOP_NOP", uops)
2216+
2217+
def test_call_method_descriptor_o(self):
2218+
def testfunc(n):
2219+
x = 0
2220+
for _ in range(n):
2221+
y = (1, 2, 3)
2222+
z = y.count(2)
2223+
x += z
2224+
return x
2225+
2226+
res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
2227+
self.assertEqual(res, TIER2_THRESHOLD)
2228+
self.assertIsNotNone(ex)
2229+
uops = get_opnames(ex)
2230+
pop_tops = [opname for opname in iter_opnames(ex) if opname == "_POP_TOP"]
2231+
self.assertIn("_CALL_METHOD_DESCRIPTOR_O", uops)
2232+
self.assertIn("_POP_TOP_NOP", uops)
2233+
self.assertLessEqual(len(pop_tops), 1)
22142234

22152235
def test_get_len_with_const_tuple(self):
22162236
def testfunc(n):

Python/bytecodes.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4170,7 +4170,7 @@ dummy_func(
41704170
_CALL_BUILTIN_CLASS +
41714171
_CHECK_PERIODIC_AT_END;
41724172

4173-
op(_CALL_BUILTIN_O, (callable, self_or_null, args[oparg] -- res, a, c)) {
4173+
op(_CALL_BUILTIN_O, (callable, self_or_null, args[oparg] -- res, c, s)) {
41744174
/* Builtin METH_O functions */
41754175
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
41764176

@@ -4193,8 +4193,8 @@ dummy_func(
41934193
if (res_o == NULL) {
41944194
ERROR_NO_POP();
41954195
}
4196-
a = arg;
41974196
c = callable;
4197+
s = args[0];
41984198
INPUTS_DEAD();
41994199
res = PyStackRef_FromPyObjectSteal(res_o);
42004200
}
@@ -4362,7 +4362,7 @@ dummy_func(
43624362
none = PyStackRef_None;
43634363
}
43644364

4365-
op(_CALL_METHOD_DESCRIPTOR_O, (callable, self_or_null, args[oparg] -- res)) {
4365+
op(_CALL_METHOD_DESCRIPTOR_O, (callable, self_or_null, args[oparg] -- res, c, s, a)) {
43664366
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
43674367

43684368
int total_args = oparg;
@@ -4390,15 +4390,23 @@ dummy_func(
43904390
PyStackRef_AsPyObjectBorrow(arg_stackref));
43914391
_Py_LeaveRecursiveCallTstate(tstate);
43924392
assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
4393-
DECREF_INPUTS();
4394-
ERROR_IF(res_o == NULL);
4393+
if (res_o == NULL) {
4394+
ERROR_NO_POP();
4395+
}
4396+
c = callable;
4397+
s = arguments[0];
4398+
a = arguments[1];
4399+
INPUTS_DEAD();
43954400
res = PyStackRef_FromPyObjectSteal(res_o);
43964401
}
43974402

43984403
macro(CALL_METHOD_DESCRIPTOR_O) =
43994404
unused/1 +
44004405
unused/2 +
44014406
_CALL_METHOD_DESCRIPTOR_O +
4407+
POP_TOP +
4408+
POP_TOP +
4409+
POP_TOP +
44024410
_CHECK_PERIODIC_AT_END;
44034411

44044412
op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- res)) {

Python/executor_cases.c.h

Lines changed: 18 additions & 27 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: 42 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)