8000 GH-131798: Narrow the return type of _GET_LEN to int (GH-133345) · python/cpython@e1c0c45 · GitHub
[go: up one dir, main page]

Skip to content

Commit e1c0c45

Browse files
authored
GH-131798: Narrow the return type of _GET_LEN to int (GH-133345)
1 parent e4fbfb1 commit e1c0c45

File tree

4 files changed

+87
-1
lines changed

4 files changed

+87
-1
lines changed

Lib/test/test_capi/test_opt.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1925,6 +1925,50 @@ def testfunc(n):
19251925
self.assertNotIn("_GUARD_NOS_INT", uops)
19261926
self.assertNotIn("_GUARD_TOS_INT", uops)
19271927

1928+
def test_get_len_with_const_tuple(self):
1929+
def testfunc(n):
1930+
x = 0.0
1931+
for _ in range(n):
1932+
match (1, 2, 3, 4):
1933+
case [_, _, _, _]:
1934+
x += 1.0
1935+
return x
1936+
res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
1937+
self.assertEqual(int(res), TIER2_THRESHOLD)
1938+
uops = get_opnames(ex)
1939+
self.assertNotIn("_GUARD_NOS_INT", uops)
1940+
self.assertNotIn("_GET_LEN", uops)
1941+
self.assertIn("_LOAD_CONST_INLINE_BORROW", uops)
1942+
1943+
def test_get_len_with_non_const_tuple(self):
1944+
def testfunc(n):
1945+
x = 0.0
1946+
for _ in range(n):
1947+
match object(), object():
1948+
case [_, _]:
1949+
x += 1.0
1950+
return x
1951+
res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
1952+
self.assertEqual(int(res), TIER2_THRESHOLD)
1953+
uops = get_opnames(ex)
1954+
self.assertNotIn("_GUARD_NOS_INT", uops)
1955+
self.assertNotIn("_GET_LEN", uops)
1956+
self.assertIn("_LOAD_CONST_INLINE_BORROW", uops)
1957+
1958+
def test_get_len_with_non_tuple(self):
1959+
def testfunc(n):
1960+
x = 0.0
1961+
for _ in range(n):
1962+
match [1, 2, 3, 4]:
1963+
case [_, _, _, _]:
1964+
x += 1.0
1965+
return x
1966+
res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
1967+
self.assertEqual(int(res), TIER2_THRESHOLD)
1968+
uops = get_opnames(ex)
1969+
self.assertNotIn("_GUARD_NOS_INT", uops)
1970+
self.assertIn("_GET_LEN", uops)
1971+
19281972
def test_binary_op_subscr_tuple_int(self):
19291973
def testfunc(n):
19301974
x = 0
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Allow the JIT to remove int guards after ``_GET_LEN`` by setting the return
2+
type to int.

Python/optimizer_bytecodes.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,25 @@ dummy_func(void) {
11161116
res = sym_new_type(ctx, &PyLong_Type);
11171117
}
11181118

1119+
op(_GET_LEN, (obj -- obj, len)) {
1120+
int tuple_length = sym_tuple_length(obj);
1121+
if (tuple_length == -1) {
1122+
len = sym_new_type(ctx, &PyLong_Type);
1123+
}
1124+
else {
1125+
assert(tuple_length >= 0);
1126+
PyObject *temp = PyLong_FromLong(tuple_length);
1127+
if (temp == NULL) {
1128+
goto error;
1129+
}
1130+
if (_Py_IsImmortal(temp)) {
1131+
REPLACE_OP(this_instr, _LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)temp);
1132+
}
1133+
len = sym_new_const(ctx, temp);
1134+
Py_DECREF(temp);
1135+
}
1136+
}
1137+
11191138
op(_GUARD_CALLABLE_LEN, (callable, unused, unused -- callable, unused, unused)) {
11201139
PyObject *len = _PyInterpreterState_GET()->callable_cache.len;
11211140
if (sym_get_const(ctx, callable) == len) {

Python/optimizer_cases.c.h

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

0 commit comments

Comments
 (0)
0