[CALL_KW_BOUND_METHOD] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION_KW, 2, 1 }, { _EXPAND_METHOD_KW, OPARG_SIMPLE, 3 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } },
[CALL_KW_NON_PY] = { .nuops = 3, .uops = { { _CHECK_IS_NOT_PY_CALLABLE_KW, OPARG_SIMPLE, 3 }, { _CALL_KW_NON_PY, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } },
[CALL_KW_PY] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION_KW, 2, 1 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } },
- [CALL_LEN] = { .nuops = 3, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_LEN, OPARG_SIMPLE, 3 }, { _CALL_LEN, OPARG_SIMPLE, 3 } } },
+ [CALL_LEN] = { .nuops = 5, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_LEN, OPARG_SIMPLE, 3 }, { _CALL_LEN, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 } } },
[CALL_LIST_APPEND] = { .nuops = 4, .uops = { { _GUARD_CALLABLE_LIST_APPEND, OPARG_SIMPLE, 3 }, { _GUARD_NOS_NOT_NULL, OPARG_SIMPLE, 3 }, { _GUARD_NOS_LIST, OPARG_SIMPLE, 3 }, { _CALL_LIST_APPEND, OPARG_SIMPLE, 3 } } },
[CALL_METHOD_DESCRIPTOR_FAST] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_FAST, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } },
[CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } },
#define _CALL_INTRINSIC_2_r21 624
#define _CALL_ISINSTANCE_r31 625
#define _CALL_KW_NON_PY_r11 626
-#define _CALL_LEN_r31 627
+#define _CALL_LEN_r33 627
#define _CALL_LIST_APPEND_r30 628
#define _CALL_METHOD_DESCRIPTOR_FAST_r01 629
#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 630
{ -1, -1, -1 },
{ -1, -1, -1 },
{ -1, -1, -1 },
- { 1, 0, _CALL_LEN_r31 },
+ { 3, 0, _CALL_LEN_r33 },
},
},
[_GUARD_CALLABLE_ISINSTANCE] = {
[_GUARD_CALLABLE_LEN_r13] = _GUARD_CALLABLE_LEN,
[_GUARD_CALLABLE_LEN_r23] = _GUARD_CALLABLE_LEN,
[_GUARD_CALLABLE_LEN_r33] = _GUARD_CALLABLE_LEN,
- [_CALL_LEN_r31] = _CALL_LEN,
+ [_CALL_LEN_r33] = _CALL_LEN,
[_GUARD_CALLABLE_ISINSTANCE_r03] = _GUARD_CALLABLE_ISINSTANCE,
[_GUARD_CALLABLE_ISINSTANCE_r13] = _GUARD_CALLABLE_ISINSTANCE,
[_GUARD_CALLABLE_ISINSTANCE_r23] = _GUARD_CALLABLE_ISINSTANCE,
[_CALL_KW_NON_PY] = "_CALL_KW_NON_PY",
[_CALL_KW_NON_PY_r11] = "_CALL_KW_NON_PY_r11",
[_CALL_LEN] = "_CALL_LEN",
- [_CALL_LEN_r31] = "_CALL_LEN_r31",
+ [_CALL_LEN_r33] = "_CALL_LEN_r33",
[_CALL_LIST_APPEND] = "_CALL_LIST_APPEND",
[_CALL_LIST_APPEND_r30] = "_CALL_LIST_APPEND_r30",
[_CALL_METHOD_DESCRIPTOR_FAST] = "_CALL_METHOD_DESCRIPTOR_FAST",
self.assertIn("_CALL_LEN", uops)
self.assertNotIn("_GUARD_NOS_INT", uops)
self.assertNotIn("_GUARD_TOS_INT", uops)
+ self.assertIn("_POP_TOP_NOP", uops)
def test_call_len_known_length_small_int(self):
# Make sure that len(t) is optimized for a tuple of length 5.
unused/2 +
_GUARD_NOS_NULL +
_GUARD_CALLABLE_LEN +
- _CALL_LEN;
+ _CALL_LEN +
+ POP_TOP +
+ POP_TOP;
op(_GUARD_CALLABLE_LEN, (callable, unused, unused -- callable, unused, unused)){
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
DEOPT_IF(callable_o != interp->callable_cache.len);
}
- op(_CALL_LEN, (callable, null, arg -- res)) {
+ op(_CALL_LEN, (callable, null, arg -- res, a, c)) {
/* len(o) */
- (void)null;
STAT_INC(CALL, hit);
PyObject *arg_o = PyStackRef_AsPyObjectBorrow(arg);
Py_ssize_t len_i = PyObject_Length(arg_o);
if (res_o == NULL) {
ERROR_NO_POP();
}
- PyStackRef_CLOSE(arg);
- DEAD(null);
- PyStackRef_CLOSE(callable);
+ a = arg;
+ c = callable;
+ INPUTS_DEAD();
res = PyStackRef_FromPyObjectSteal(res_o);
}
break;
}
- case _CALL_LEN_r31: {
+ case _CALL_LEN_r33: {
CHECK_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_WITH_CACHE());
_PyStackRef arg;
- _PyStackRef null;
_PyStackRef callable;
_PyStackRef res;
+ _PyStackRef a;
+ _PyStackRef c;
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
_PyStackRef _stack_item_2 = _tos_cache2;
arg = _stack_item_2;
- null = _stack_item_1;
callable = _stack_item_0;
- (void)null;
STAT_INC(CALL, hit);
PyObject *arg_o = PyStackRef_AsPyObjectBorrow(arg);
stack_pointer[0] = callable;
- stack_pointer[1] = null;
+ stack_pointer[1] = _stack_item_1;
stack_pointer[2] = arg;
stack_pointer += 3;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
SET_CURRENT_CACHED_VALUES(0);
JUMP_TO_ERROR();
}
- stack_pointer += -1;
- ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
- _PyFrame_SetStackPointer(frame, stack_pointer);
- PyStackRef_CLOSE(arg);
- stack_pointer = _PyFrame_GetStackPointer(frame);
- stack_pointer += -2;
- ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
- _PyFrame_SetStackPointer(frame, stack_pointer);
- PyStackRef_CLOSE(callable);
- stack_pointer = _PyFrame_GetStackPointer(frame);
+ a = arg;
+ c = callable;
res = PyStackRef_FromPyObjectSteal(res_o);
+ _tos_cache2 = c;
+ _tos_cache1 = a;
_tos_cache0 = res;
- _tos_cache1 = PyStackRef_ZERO_BITS;
- _tos_cache2 = PyStackRef_ZERO_BITS;
- SET_CURRENT_CACHED_VALUES(1);
+ SET_CURRENT_CACHED_VALUES(3);
+ stack_pointer += -3;
+ ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
assert(WITHIN_STACK_BOUNDS_WITH_CACHE());
break;
}
_PyStackRef callable;
_PyStackRef arg;
_PyStackRef res;
+ _PyStackRef a;
+ _PyStackRef c;
+ _PyStackRef value;
/* Skip 1 cache entry */
/* Skip 2 cache entries */
// _GUARD_NOS_NULL
// _CALL_LEN
{
arg = stack_pointer[-1];
- (void)null;
STAT_INC(CALL, hit);
PyObject *arg_o = PyStackRef_AsPyObjectBorrow(arg);
_PyFrame_SetStackPointer(frame, stack_pointer);
if (res_o == NULL) {
JUMP_TO_LABEL(error);
}
+ a = arg;
+ c = callable;
+ res = PyStackRef_FromPyObjectSteal(res_o);
+ }
+ // _POP_TOP
+ {
+ value = c;
+ stack_pointer[-3] = res;
+ stack_pointer[-2] = a;
stack_pointer += -1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
_PyFrame_SetStackPointer(frame, stack_pointer);
- PyStackRef_CLOSE(arg);
+ PyStackRef_XCLOSE(value);
stack_pointer = _PyFrame_GetStackPointer(frame);
- stack_pointer += -2;
+ }
+ // _POP_TOP
+ {
+ value = a;
+ stack_pointer += -1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
_PyFrame_SetStackPointer(frame, stack_pointer);
- PyStackRef_CLOSE(callable);
+ PyStackRef_XCLOSE(value);
stack_pointer = _PyFrame_GetStackPointer(frame);
- res = PyStackRef_FromPyObjectSteal(res_o);
}
- stack_pointer[0] = res;
- stack_pointer += 1;
- ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
DISPATCH();
}
sym_set_const(callable, (PyObject *)&PyUnicode_Type);
}
- op(_CALL_LEN, (callable, null, arg -- res)) {
+ 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) {
res = sym_new_const(ctx, temp);
Py_DECREF(temp);
}
+ a = arg;
+ c = callable;
}
op(_GET_LEN, (obj -- obj, len)) {
case _CALL_LEN: {
JitOptRef arg;
+ JitOptRef callable;
JitOptRef res;
+ JitOptRef a;
+ JitOptRef c;
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) {
Py_DECREF(temp);
stack_pointer += 2;
}
- CHECK_STACK_BOUNDS(-2);
+ a = arg;
+ c = callable;
stack_pointer[-3] = res;
- stack_pointer += -2;
- ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
+ stack_pointer[-2] = a;
+ stack_pointer[-1] = c;
break;
}