self.assertNotIn("_GUARD_TOS_INT", uops)
self.assertIn("_POP_TOP_NOP", uops)
+ def test_call_len_string(self):
+ def testfunc(n):
+ for _ in range(n):
+ _ = len("abc")
+ d = ''
+ _ = len(d)
+ _ = len(b"def")
+ _ = len(b"")
+
+ _, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
+ self.assertIsNotNone(ex)
+ uops = get_opnames(ex)
+ self.assertNotIn("_CALL_LEN", uops)
+ self.assertEqual(count_ops(ex, "_SHUFFLE_3_LOAD_CONST_INLINE_BORROW"), 4)
+
def test_call_len_known_length_small_int(self):
# Make sure that len(t) is optimized for a tuple of length 5.
# See https://github.com/python/cpython/issues/139393.
op(_CALL_LEN, (callable, null, arg -- res, a, c)) {
res = sym_new_type(ctx, &PyLong_Type);
- Py_ssize_t tuple_length = sym_tuple_length(arg);
- if (tuple_length >= 0) {
- PyObject *temp = PyLong_FromSsize_t(tuple_length);
+ Py_ssize_t length = sym_tuple_length(arg);
+
+ // Not a tuple, check if it's a const string
+ if (length < 0 && sym_is_const(ctx, arg)) {
+ PyObject *const_val = sym_get_const(ctx, arg);
+ if (const_val != NULL) {
+ if (PyUnicode_CheckExact(const_val)) {
+ length = PyUnicode_GET_LENGTH(const_val);
+ }
+ else if (PyBytes_CheckExact(const_val)) {
+ length = PyBytes_GET_SIZE(const_val);
+ }
+ }
+ }
+
+ if (length >= 0) {
+ PyObject *temp = PyLong_FromSsize_t(length);
if (temp == NULL) {
goto error;
}
if (_Py_IsImmortal(temp)) {
- ADD_OP(_SHUFFLE_3_LOAD_CONST_INLINE_BORROW,
- 0, (uintptr_t)temp);
+ ADD_OP(_SHUFFLE_3_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)temp);
}
res = sym_new_const(ctx, temp);
Py_DECREF(temp);
arg = stack_pointer[-1];
callable = stack_pointer[-3];
res = sym_new_type(ctx, &PyLong_Type);
- Py_ssize_t tuple_length = sym_tuple_length(arg);
- if (tuple_length >= 0) {
- PyObject *temp = PyLong_FromSsize_t(tuple_length);
+ Py_ssize_t length = sym_tuple_length(arg);
+ if (length < 0 && sym_is_const(ctx, arg)) {
+ PyObject *const_val = sym_get_const(ctx, arg);
+ if (const_val != NULL) {
+ if (PyUnicode_CheckExact(const_val)) {
+ length = PyUnicode_GET_LENGTH(const_val);
+ }
+ else if (PyBytes_CheckExact(const_val)) {
+ CHECK_STACK_BOUNDS(-2);
+ stack_pointer[-3] = res;
+ stack_pointer += -2;
+ ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
+ length = PyBytes_GET_SIZE(const_val);
+ stack_pointer += 2;
+ }
+ }
+ }
+ if (length >= 0) {
+ PyObject *temp = PyLong_FromSsize_t(length);
if (temp == NULL) {
goto error;
}
if (_Py_IsImmortal(temp)) {
- ADD_OP(_SHUFFLE_3_LOAD_CONST_INLINE_BORROW,
- 0, (uintptr_t)temp);
+ ADD_OP(_SHUFFLE_3_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)temp);
}
res = sym_new_const(ctx, temp);
CHECK_STACK_BOUNDS(-2);