mirror of
https://github.com/python/cpython.git
synced 2026-01-26 21:03:34 +00:00
gh-134584: Eliminate redundant refcounting from `_CALL_LEN` (gh-136104)
This commit is contained in:
parent
c433986005
commit
a27538540e
2
Include/internal/pycore_opcode_metadata.h
generated
2
Include/internal/pycore_opcode_metadata.h
generated
@ -1366,7 +1366,7 @@ _PyOpcode_macro_expansion[256] = {
|
||||
[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 } } },
|
||||
|
||||
2
Include/internal/pycore_uop_ids.h
generated
2
Include/internal/pycore_uop_ids.h
generated
@ -431,7 +431,7 @@ extern "C" {
|
||||
#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
|
||||
|
||||
6
Include/internal/pycore_uop_metadata.h
generated
6
Include/internal/pycore_uop_metadata.h
generated
@ -2624,7 +2624,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = {
|
||||
{ -1, -1, -1 },
|
||||
{ -1, -1, -1 },
|
||||
{ -1, -1, -1 },
|
||||
{ 1, 0, _CALL_LEN_r31 },
|
||||
{ 3, 0, _CALL_LEN_r33 },
|
||||
},
|
||||
},
|
||||
[_GUARD_CALLABLE_ISINSTANCE] = {
|
||||
@ -3751,7 +3751,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = {
|
||||
[_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,
|
||||
@ -4042,7 +4042,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = {
|
||||
[_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",
|
||||
|
||||
@ -2066,6 +2066,7 @@ class TestUopsOptimization(unittest.TestCase):
|
||||
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.
|
||||
|
||||
@ -4280,7 +4280,9 @@ dummy_func(
|
||||
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);
|
||||
@ -4288,9 +4290,8 @@ dummy_func(
|
||||
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);
|
||||
@ -4302,9 +4303,9 @@ dummy_func(
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
29
Python/executor_cases.c.h
generated
29
Python/executor_cases.c.h
generated
@ -13370,24 +13370,23 @@
|
||||
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__);
|
||||
@ -13404,21 +13403,15 @@
|
||||
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;
|
||||
}
|
||||
|
||||
27
Python/generated_cases.c.h
generated
27
Python/generated_cases.c.h
generated
@ -3144,6 +3144,9 @@
|
||||
_PyStackRef callable;
|
||||
_PyStackRef arg;
|
||||
_PyStackRef res;
|
||||
_PyStackRef a;
|
||||
_PyStackRef c;
|
||||
_PyStackRef value;
|
||||
/* Skip 1 cache entry */
|
||||
/* Skip 2 cache entries */
|
||||
// _GUARD_NOS_NULL
|
||||
@ -3169,7 +3172,6 @@
|
||||
// _CALL_LEN
|
||||
{
|
||||
arg = stack_pointer[-1];
|
||||
(void)null;
|
||||
STAT_INC(CALL, hit);
|
||||
PyObject *arg_o = PyStackRef_AsPyObjectBorrow(arg);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
@ -3183,21 +3185,30 @@
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@ -1202,7 +1202,7 @@ dummy_func(void) {
|
||||
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) {
|
||||
@ -1217,6 +1217,8 @@ dummy_func(void) {
|
||||
res = sym_new_const(ctx, temp);
|
||||
Py_DECREF(temp);
|
||||
}
|
||||
a = arg;
|
||||
c = callable;
|
||||
}
|
||||
|
||||
op(_GET_LEN, (obj -- obj, len)) {
|
||||
|
||||
11
Python/optimizer_cases.c.h
generated
11
Python/optimizer_cases.c.h
generated
@ -3002,8 +3002,12 @@
|
||||
|
||||
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) {
|
||||
@ -3023,10 +3027,11 @@
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user