Skip to content

Commit 798fcb0

Browse files
committed
gh-144140: Optimize len for string constants in optimizer
1 parent c461aa9 commit 798fcb0

File tree

3 files changed

+58
-7
lines changed

3 files changed

+58
-7
lines changed

Lib/test/test_capi/test_opt.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2269,6 +2269,20 @@ def testfunc(n):
22692269
self.assertNotIn("_GUARD_NOS_INT", uops)
22702270
self.assertNotIn("_GUARD_TOS_INT", uops)
22712271
self.assertIn("_POP_TOP_NOP", uops)
2272+
2273+
def test_call_len_string(self):
2274+
def testfunc(n):
2275+
for _ in range(n):
2276+
_ = len("abc")
2277+
d = ''
2278+
_ = len(d)
2279+
2280+
_, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
2281+
self.assertIsNotNone(ex)
2282+
uops = get_opnames(ex)
2283+
print(uops)
2284+
self.assertNotIn("_CALL_LEN", uops)
2285+
self.assertIn("_SHUFFLE_3_LOAD_CONST_INLINE_BORROW", uops)
22722286

22732287
def test_call_len_known_length_small_int(self):
22742288
# Make sure that len(t) is optimized for a tuple of length 5.

Python/optimizer_bytecodes.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,12 +1394,25 @@ dummy_func(void) {
13941394

13951395
op(_CALL_LEN, (callable, null, arg -- res, a, c)) {
13961396
res = sym_new_type(ctx, &PyLong_Type);
1397-
Py_ssize_t tuple_length = sym_tuple_length(arg);
1398-
if (tuple_length >= 0) {
1399-
PyObject *temp = PyLong_FromSsize_t(tuple_length);
1397+
PyObject *temp = NULL;
1398+
1399+
Py_ssize_t length = sym_tuple_length(arg);
1400+
if (length >= 0) {
1401+
temp = PyLong_FromSsize_t(length);
14001402
if (temp == NULL) {
14011403
goto error;
14021404
}
1405+
}
1406+
else if (sym_is_const(ctx, arg)) {
1407+
PyObject *const_val = sym_get_const(ctx, arg);
1408+
if (const_val != NULL && PyUnicode_CheckExact(const_val)) {
1409+
temp = PyLong_FromSsize_t(PyUnicode_GET_LENGTH(const_val));
1410+
if (temp == NULL) {
1411+
goto error;
1412+
}
1413+
}
1414+
}
1415+
if (temp != NULL) {
14031416
if (_Py_IsImmortal(temp)) {
14041417
REPLACE_OP(this_instr, _SHUFFLE_3_LOAD_CONST_INLINE_BORROW,
14051418
0, (uintptr_t)temp);

Python/optimizer_cases.c.h

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

0 commit comments

Comments
 (0)