Skip to content

Commit 5d7f302

Browse files
committed
Eliminate redundant refcounting from BINARY_SLICE
1 parent e682141 commit 5d7f302

10 files changed

Lines changed: 158 additions & 69 deletions

File tree

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: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2098,6 +2098,23 @@ def testfunc(n):
20982098
self.assertIn("_BINARY_OP_SUBSCR_DICT", uops)
20992099
self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2)
21002100

2101+
def test_binary_slice(self):
2102+
def testfunc(n):
2103+
x = 0
2104+
s = "hello world"
2105+
a, b = 1, 4
2106+
for _ in range(n):
2107+
v = s[a:b]
2108+
x += len(v)
2109+
return x
2110+
2111+
res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
2112+
self.assertEqual(res, TIER2_THRESHOLD * 3)
2113+
self.assertIsNotNone(ex)
2114+
uops = get_opnames(ex)
2115+
self.assertIn("_BINARY_SLICE", uops)
2116+
self.assertGreaterEqual(count_ops(ex, "_POP_TOP"), 3)
2117+
21012118
def test_contains_op(self):
21022119
def testfunc(n):
21032120
x = 0

Modules/_testinternalcapi/test_cases.c.h

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

Python/bytecodes.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -862,25 +862,29 @@ dummy_func(
862862
#endif /* ENABLE_SPECIALIZATION */
863863
}
864864

865-
op(_BINARY_SLICE, (container, start, stop -- res)) {
866-
PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start),
867-
PyStackRef_AsPyObjectSteal(stop));
865+
op(_BINARY_SLICE, (container, start, stop -- res, c, sta, sto)) {
866+
PyObject *slice = PySlice_New(PyStackRef_AsPyObjectBorrow(start),
867+
PyStackRef_AsPyObjectBorrow(stop),
868+
NULL);
868869
PyObject *res_o;
869-
// Can't use ERROR_IF() here, because we haven't
870-
// DECREF'ed container yet, and we still own slice.
871870
if (slice == NULL) {
872871
res_o = NULL;
873872
}
874873
else {
875874
res_o = PyObject_GetItem(PyStackRef_AsPyObjectBorrow(container), slice);
876875
Py_DECREF(slice);
877876
}
878-
PyStackRef_CLOSE(container);
879-
ERROR_IF(res_o == NULL);
877+
if (res_o == NULL) {
878+
ERROR_NO_POP();
879+
}
880880
res = PyStackRef_FromPyObjectSteal(res_o);
881+
c = container;
882+
sta = start;
883+
sto = stop;
884+
INPUTS_DEAD();
881885
}
882886

883-
macro(BINARY_SLICE) = _SPECIALIZE_BINARY_SLICE + _BINARY_SLICE;
887+
macro(BINARY_SLICE) = _SPECIALIZE_BINARY_SLICE + _BINARY_SLICE + POP_TOP + POP_TOP + POP_TOP;
884888

885889
specializing op(_SPECIALIZE_STORE_SLICE, (v, container, start, stop -- v, container, start, stop)) {
886890
// Placeholder until we implement STORE_SLICE specialization

Python/executor_cases.c.h

Lines changed: 27 additions & 21 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: 38 additions & 15 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: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1491,7 +1491,7 @@ dummy_func(void) {
14911491
sym_set_const(callable, list_append);
14921492
}
14931493

1494-
op(_BINARY_SLICE, (container, start, stop -- res)) {
1494+
op(_BINARY_SLICE, (container, start, stop -- res, c, sta, sto)) {
14951495
// Slicing a string/list/tuple always returns the same type.
14961496
PyTypeObject *type = sym_get_type(container);
14971497
if (type == &PyUnicode_Type ||
@@ -1503,6 +1503,9 @@ dummy_func(void) {
15031503
else {
15041504
res = sym_new_not_null(ctx);
15051505
}
1506+
c = container;
1507+
sta = start;
1508+
sto = stop;
15061509
}
15071510

15081511
op(_GUARD_GLOBALS_VERSION, (version/1 --)) {

0 commit comments

Comments
 (0)