diff options
author | Mark Shannon <mark@hotpy.org> | 2024-03-11 09:30:15 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-11 09:30:15 (GMT) |
commit | 4e5df2013fc29ed8bdb71572f1d12ff36e7028d5 (patch) | |
tree | 7e13e821f19e33133bcebf17225808a68a4efda0 | |
parent | 8d7fde655fbb57e393831b9f30ebba80d6da366f (diff) | |
download | cpython-4e5df2013fc29ed8bdb71572f1d12ff36e7028d5.zip cpython-4e5df2013fc29ed8bdb71572f1d12ff36e7028d5.tar.gz cpython-4e5df2013fc29ed8bdb71572f1d12ff36e7028d5.tar.bz2 |
GH-116468: Use constants instead of `oparg` in stack effects when `oparg` is known to be a constant. (GH-116469)
-rw-r--r-- | Include/internal/pycore_opcode_metadata.h | 10 | ||||
-rw-r--r-- | Python/bytecodes.c | 30 | ||||
-rw-r--r-- | Python/executor_cases.c.h | 64 | ||||
-rw-r--r-- | Python/generated_cases.c.h | 74 | ||||
-rw-r--r-- | Python/optimizer_cases.c.h | 28 |
5 files changed, 98 insertions, 108 deletions
diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index efb731f..05ff78d 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -116,7 +116,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) { case CALL_LEN: return 2 + oparg; case CALL_LIST_APPEND: - return 2 + oparg; + return 3; case CALL_METHOD_DESCRIPTOR_FAST: return 2 + oparg; case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: @@ -130,11 +130,11 @@ int _PyOpcode_num_popped(int opcode, int oparg) { case CALL_PY_WITH_DEFAULTS: return 2 + oparg; case CALL_STR_1: - return 2 + oparg; + return 3; case CALL_TUPLE_1: - return 2 + oparg; + return 3; case CALL_TYPE_1: - return 2 + oparg; + return 3; case CHECK_EG_MATCH: return 2; case CHECK_EXC_MATCH: @@ -879,7 +879,7 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { case UNPACK_SEQUENCE_TUPLE: return oparg; case UNPACK_SEQUENCE_TWO_TUPLE: - return oparg; + return 2; case WITH_EXCEPT_START: return 5; case YIELD_VALUE: diff --git a/Python/bytecodes.c b/Python/bytecodes.c index bf9d2a3..03e5f4e 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -129,6 +129,8 @@ dummy_func( PyObject *top; PyObject *type; PyObject *typevars; + PyObject *val0; + PyObject *val1; int values_or_none; switch (opcode) { @@ -1223,13 +1225,13 @@ dummy_func( macro(UNPACK_SEQUENCE) = _SPECIALIZE_UNPACK_SEQUENCE + _UNPACK_SEQUENCE; - inst(UNPACK_SEQUENCE_TWO_TUPLE, (unused/1, seq -- values[oparg])) { + inst(UNPACK_SEQUENCE_TWO_TUPLE, (unused/1, seq -- val1, val0)) { + assert(oparg == 2); DEOPT_IF(!PyTuple_CheckExact(seq)); DEOPT_IF(PyTuple_GET_SIZE(seq) != 2); - assert(oparg == 2); STAT_INC(UNPACK_SEQUENCE, hit); - values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); - values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); + val0 = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); + val1 = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); DECREF_INPUTS(); } @@ -3236,39 +3238,33 @@ dummy_func( DISPATCH_INLINED(new_frame); } - inst(CALL_TYPE_1, (unused/1, unused/2, callable, null, args[oparg] -- res)) { + inst(CALL_TYPE_1, (unused/1, unused/2, callable, null, arg -- res)) { assert(oparg == 1); DEOPT_IF(null != NULL); - PyObject *obj = args[0]; DEOPT_IF(callable != (PyObject *)&PyType_Type); STAT_INC(CALL, hit); - res = Py_NewRef(Py_TYPE(obj)); - Py_DECREF(obj); - Py_DECREF(&PyType_Type); // I.e., callable + res = Py_NewRef(Py_TYPE(arg)); + Py_DECREF(arg); } - inst(CALL_STR_1, (unused/1, unused/2, callable, null, args[oparg] -- res)) { + inst(CALL_STR_1, (unused/1, unused/2, callable, null, arg -- res)) { assert(oparg == 1); DEOPT_IF(null != NULL); DEOPT_IF(callable != (PyObject *)&PyUnicode_Type); STAT_INC(CALL, hit); - PyObject *arg = args[0]; res = PyObject_Str(arg); Py_DECREF(arg); - Py_DECREF(&PyUnicode_Type); // I.e., callable ERROR_IF(res == NULL, error); CHECK_EVAL_BREAKER(); } - inst(CALL_TUPLE_1, (unused/1, unused/2, callable, null, args[oparg] -- res)) { + inst(CALL_TUPLE_1, (unused/1, unused/2, callable, null, arg -- res)) { assert(oparg == 1); DEOPT_IF(null != NULL); DEOPT_IF(callable != (PyObject *)&PyTuple_Type); STAT_INC(CALL, hit); - PyObject *arg = args[0]; res = PySequence_Tuple(arg); Py_DECREF(arg); - Py_DECREF(&PyTuple_Type); // I.e., tuple ERROR_IF(res == NULL, error); CHECK_EVAL_BREAKER(); } @@ -3490,14 +3486,14 @@ dummy_func( } // This is secretly a super-instruction - tier1 inst(CALL_LIST_APPEND, (unused/1, unused/2, callable, self, args[oparg] -- unused)) { + tier1 inst(CALL_LIST_APPEND, (unused/1, unused/2, callable, self, arg -- unused)) { assert(oparg == 1); PyInterpreterState *interp = tstate->interp; DEOPT_IF(callable != interp->callable_cache.list_append); assert(self != NULL); DEOPT_IF(!PyList_Check(self)); STAT_INC(CALL, hit); - if (_PyList_AppendTakeRef((PyListObject *)self, args[0]) < 0) { + if (_PyList_AppendTakeRef((PyListObject *)self, arg) < 0) { goto pop_1_error; // Since arg is DECREF'ed already } Py_DECREF(self); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index ccd8fb3..42e884c 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -1061,18 +1061,20 @@ case _UNPACK_SEQUENCE_TWO_TUPLE: { PyObject *seq; - PyObject **values; + PyObject *val1; + PyObject *val0; oparg = CURRENT_OPARG(); seq = stack_pointer[-1]; - values = &stack_pointer[-1]; + assert(oparg == 2); if (!PyTuple_CheckExact(seq)) goto deoptimize; if (PyTuple_GET_SIZE(seq) != 2) goto deoptimize; - assert(oparg == 2); STAT_INC(UNPACK_SEQUENCE, hit); - values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); - values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); + val0 = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); + val1 = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); Py_DECREF(seq); - stack_pointer += -1 + oparg; + stack_pointer[-1] = val1; + stack_pointer[0] = val0; + stack_pointer += 1; break; } @@ -3057,71 +3059,65 @@ /* _CALL_PY_WITH_DEFAULTS is not a viable micro-op for tier 2 */ case _CALL_TYPE_1: { - PyObject **args; + PyObject *arg; PyObject *null; PyObject *callable; PyObject *res; oparg = CURRENT_OPARG(); - args = &stack_pointer[-oparg]; - null = stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + arg = stack_pointer[-1]; + null = stack_pointer[-2]; + callable = stack_pointer[-3]; assert(oparg == 1); if (null != NULL) goto deoptimize; - PyObject *obj = args[0]; if (callable != (PyObject *)&PyType_Type) goto deoptimize; STAT_INC(CALL, hit); - res = Py_NewRef(Py_TYPE(obj)); - Py_DECREF(obj); - Py_DECREF(&PyType_Type); // I.e., callable - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + res = Py_NewRef(Py_TYPE(arg)); + Py_DECREF(arg); + stack_pointer[-3] = res; + stack_pointer += -2; break; } case _CALL_STR_1: { - PyObject **args; + PyObject *arg; PyObject *null; PyObject *callable; PyObject *res; oparg = CURRENT_OPARG(); - args = &stack_pointer[-oparg]; - null = stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + arg = stack_pointer[-1]; + null = stack_pointer[-2]; + callable = stack_pointer[-3]; assert(oparg == 1); if (null != NULL) goto deoptimize; if (callable != (PyObject *)&PyUnicode_Type) goto deoptimize; STAT_INC(CALL, hit); - PyObject *arg = args[0]; res = PyObject_Str(arg); Py_DECREF(arg); - Py_DECREF(&PyUnicode_Type); // I.e., callable - if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; } - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + if (res == NULL) goto pop_3_error_tier_two; + stack_pointer[-3] = res; + stack_pointer += -2; CHECK_EVAL_BREAKER(); break; } case _CALL_TUPLE_1: { - PyObject **args; + PyObject *arg; PyObject *null; PyObject *callable; PyObject *res; oparg = CURRENT_OPARG(); - args = &stack_pointer[-oparg]; - null = stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + arg = stack_pointer[-1]; + null = stack_pointer[-2]; + callable = stack_pointer[-3]; assert(oparg == 1); if (null != NULL) goto deoptimize; if (callable != (PyObject *)&PyTuple_Type) goto deoptimize; STAT_INC(CALL, hit); - PyObject *arg = args[0]; res = PySequence_Tuple(arg); Py_DECREF(arg); - Py_DECREF(&PyTuple_Type); // I.e., tuple - if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; } - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + if (res == NULL) goto pop_3_error_tier_two; + stack_pointer[-3] = res; + stack_pointer += -2; CHECK_EVAL_BREAKER(); break; } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index f5d125c..53c0211 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1472,21 +1472,21 @@ next_instr += 4; INSTRUCTION_STATS(CALL_LIST_APPEND); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - PyObject **args; + PyObject *arg; PyObject *self; PyObject *callable; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - args = &stack_pointer[-oparg]; - self = stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + arg = stack_pointer[-1]; + self = stack_pointer[-2]; + callable = stack_pointer[-3]; assert(oparg == 1); PyInterpreterState *interp = tstate->interp; DEOPT_IF(callable != interp->callable_cache.list_append, CALL); assert(self != NULL); DEOPT_IF(!PyList_Check(self), CALL); STAT_INC(CALL, hit); - if (_PyList_AppendTakeRef((PyListObject *)self, args[0]) < 0) { + if (_PyList_AppendTakeRef((PyListObject *)self, arg) < 0) { goto pop_1_error; // Since arg is DECREF'ed already } Py_DECREF(self); @@ -1810,26 +1810,24 @@ next_instr += 4; INSTRUCTION_STATS(CALL_STR_1); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - PyObject **args; + PyObject *arg; PyObject *null; PyObject *callable; PyObject *res; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - args = &stack_pointer[-oparg]; - null = stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + arg = stack_pointer[-1]; + null = stack_pointer[-2]; + callable = stack_pointer[-3]; assert(oparg == 1); DEOPT_IF(null != NULL, CALL); DEOPT_IF(callable != (PyObject *)&PyUnicode_Type, CALL); STAT_INC(CALL, hit); - PyObject *arg = args[0]; res = PyObject_Str(arg); Py_DECREF(arg); - Py_DECREF(&PyUnicode_Type); // I.e., callable - if (res == NULL) { stack_pointer += -2 - oparg; goto error; } - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + if (res == NULL) goto pop_3_error; + stack_pointer[-3] = res; + stack_pointer += -2; CHECK_EVAL_BREAKER(); DISPATCH(); } @@ -1839,26 +1837,24 @@ next_instr += 4; INSTRUCTION_STATS(CALL_TUPLE_1); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - PyObject **args; + PyObject *arg; PyObject *null; PyObject *callable; PyObject *res; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - args = &stack_pointer[-oparg]; - null = stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + arg = stack_pointer[-1]; + null = stack_pointer[-2]; + callable = stack_pointer[-3]; assert(oparg == 1); DEOPT_IF(null != NULL, CALL); DEOPT_IF(callable != (PyObject *)&PyTuple_Type, CALL); STAT_INC(CALL, hit); - PyObject *arg = args[0]; res = PySequence_Tuple(arg); Py_DECREF(arg); - Py_DECREF(&PyTuple_Type); // I.e., tuple - if (res == NULL) { stack_pointer += -2 - oparg; goto error; } - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + if (res == NULL) goto pop_3_error; + stack_pointer[-3] = res; + stack_pointer += -2; CHECK_EVAL_BREAKER(); DISPATCH(); } @@ -1868,25 +1864,23 @@ next_instr += 4; INSTRUCTION_STATS(CALL_TYPE_1); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - PyObject **args; + PyObject *arg; PyObject *null; PyObject *callable; PyObject *res; /* Skip 1 cache entry */ /* Skip 2 cache entries */ - args = &stack_pointer[-oparg]; - null = stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + arg = stack_pointer[-1]; + null = stack_pointer[-2]; + callable = stack_pointer[-3]; assert(oparg == 1); DEOPT_IF(null != NULL, CALL); - PyObject *obj = args[0]; DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL); STAT_INC(CALL, hit); - res = Py_NewRef(Py_TYPE(obj)); - Py_DECREF(obj); - Py_DECREF(&PyType_Type); // I.e., callable - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + res = Py_NewRef(Py_TYPE(arg)); + Py_DECREF(arg); + stack_pointer[-3] = res; + stack_pointer += -2; DISPATCH(); } @@ -5910,18 +5904,20 @@ INSTRUCTION_STATS(UNPACK_SEQUENCE_TWO_TUPLE); static_assert(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE == 1, "incorrect cache size"); PyObject *seq; - PyObject **values; + PyObject *val1; + PyObject *val0; /* Skip 1 cache entry */ seq = stack_pointer[-1]; - values = &stack_pointer[-1]; + assert(oparg == 2); DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE); - assert(oparg == 2); STAT_INC(UNPACK_SEQUENCE, hit); - values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); - values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); + val0 = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); + val1 = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); Py_DECREF(seq); - stack_pointer += -1 + oparg; + stack_pointer[-1] = val1; + stack_pointer[0] = val0; + stack_pointer += 1; DISPATCH(); } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index c88b251..fed5730 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -684,13 +684,15 @@ } case _UNPACK_SEQUENCE_TWO_TUPLE: { - _Py_UopsSymbol **values; - values = &stack_pointer[-1]; - for (int _i = oparg; --_i >= 0;) { - values[_i] = sym_new_unknown(ctx); - if (values[_i] == NULL) goto out_of_space; - } - stack_pointer += -1 + oparg; + _Py_UopsSymbol *val1; + _Py_UopsSymbol *val0; + val1 = sym_new_unknown(ctx); + if (val1 == NULL) goto out_of_space; + val0 = sym_new_unknown(ctx); + if (val0 == NULL) goto out_of_space; + stack_pointer[-1] = val1; + stack_pointer[0] = val0; + stack_pointer += 1; break; } @@ -1632,8 +1634,8 @@ _Py_UopsSymbol *res; res = sym_new_unknown(ctx); if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[-3] = res; + stack_pointer += -2; break; } @@ -1641,8 +1643,8 @@ _Py_UopsSymbol *res; res = sym_new_unknown(ctx); if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[-3] = res; + stack_pointer += -2; break; } @@ -1650,8 +1652,8 @@ _Py_UopsSymbol *res; res = sym_new_unknown(ctx); if (res == NULL) goto out_of_space; - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[-3] = res; + stack_pointer += -2; break; } |