From 000ae2a9ed61675a0b6f440da4981dacbefede89 Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Wed, 26 Jan 2022 14:11:02 -0800 Subject: [PATCH 1/9] Specialize UNPACK_SEQUENCE --- Include/internal/pycore_code.h | 2 + Include/opcode.h | 13 +++-- Lib/opcode.py | 3 ++ Python/ceval.c | 90 +++++++++++++++++++++++----------- Python/opcode_targets.h | 16 +++--- Python/specialize.c | 34 +++++++++++++ 6 files changed, 116 insertions(+), 42 deletions(-) diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index dfc75300315e29..9bed911fac8967 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -275,6 +275,8 @@ int _Py_Specialize_CallNoKw(PyObject *callable, _Py_CODEUNIT *instr, int nargs, void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache); void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache); +void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, + SpecializedCacheEntry *cache); #ifdef Py_STATS diff --git a/Include/opcode.h b/Include/opcode.h index 985758d8fdbf22..203f36c633b715 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -167,11 +167,14 @@ extern "C" { #define STORE_ATTR_INSTANCE_VALUE 80 #define STORE_ATTR_SLOT 81 #define STORE_ATTR_WITH_HINT 131 -#define LOAD_FAST__LOAD_FAST 140 -#define STORE_FAST__LOAD_FAST 141 -#define LOAD_FAST__LOAD_CONST 143 -#define LOAD_CONST__LOAD_FAST 150 -#define STORE_FAST__STORE_FAST 153 +#define UNPACK_SEQUENCE_ADAPTIVE 140 +#define UNPACK_SEQUENCE_LIST 141 +#define UNPACK_SEQUENCE_TUPLE 143 +#define LOAD_FAST__LOAD_FAST 150 +#define STORE_FAST__LOAD_FAST 153 +#define LOAD_FAST__LOAD_CONST 154 +#define LOAD_CONST__LOAD_FAST 158 +#define STORE_FAST__STORE_FAST 159 #define DO_TRACING 255 #ifdef NEED_OPCODE_JUMP_TABLES static uint32_t _PyOpcode_RelativeJump[8] = { diff --git a/Lib/opcode.py b/Lib/opcode.py index 1bd48eee8549a3..a84602bc41232f 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -279,6 +279,9 @@ def jabs_op(name, op): "STORE_ATTR_INSTANCE_VALUE", "STORE_ATTR_SLOT", "STORE_ATTR_WITH_HINT", + "UNPACK_SEQUENCE_ADAPTIVE", + "UNPACK_SEQUENCE_LIST", + "UNPACK_SEQUENCE_TUPLE", # Super instructions "LOAD_FAST__LOAD_FAST", "STORE_FAST__LOAD_FAST", diff --git a/Python/ceval.c b/Python/ceval.c index 0a6fc4a20660b5..a25350f75790c4 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2837,46 +2837,77 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(UNPACK_SEQUENCE) { PREDICTED(UNPACK_SEQUENCE); - PyObject *seq = POP(), *item, **items; - if (PyTuple_CheckExact(seq) && - PyTuple_GET_SIZE(seq) == oparg) { - items = ((PyTupleObject *)seq)->ob_item; - while (oparg--) { - item = items[oparg]; - Py_INCREF(item); - PUSH(item); - } - } else if (PyList_CheckExact(seq) && - PyList_GET_SIZE(seq) == oparg) { - items = ((PyListObject *)seq)->ob_item; - while (oparg--) { - item = items[oparg]; - Py_INCREF(item); - PUSH(item); - } - } else if (unpack_iterable(tstate, seq, oparg, -1, - stack_pointer + oparg)) { - STACK_GROW(oparg); - } else { - /* unpack_iterable() raised an exception */ + PyObject *seq = TOP(); + PyObject **top = stack_pointer + oparg - 1; + if (!unpack_iterable(tstate, seq, oparg, -1, top)) { + STACK_SHRINK(1); Py_DECREF(seq); goto error; } + stack_pointer = top; Py_DECREF(seq); DISPATCH(); } - TARGET(UNPACK_EX) { - int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); - PyObject *seq = POP(); + TARGET(UNPACK_SEQUENCE_ADAPTIVE) { + assert(cframe.use_tracing == 0); + SpecializedCacheEntry *cache = GET_CACHE(); + if (cache->adaptive.counter == 0) { + PyObject *seq = TOP(); + next_instr--; + _Py_Specialize_UnpackSequence(seq, next_instr, cache); + DISPATCH(); + } + else { + STAT_INC(UNPACK_SEQUENCE, deferred); + cache->adaptive.counter--; + oparg = cache->adaptive.original_oparg; + JUMP_TO_INSTRUCTION(UNPACK_SEQUENCE); + } + } - if (unpack_iterable(tstate, seq, oparg & 0xFF, oparg >> 8, - stack_pointer + totalargs)) { - stack_pointer += totalargs; - } else { + TARGET(UNPACK_SEQUENCE_TUPLE) { + PyObject *seq = TOP(); + int len = GET_CACHE()->adaptive.original_oparg; + DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); + DEOPT_IF(PyTuple_GET_SIZE(seq) != len, UNPACK_SEQUENCE); + STAT_INC(UNPACK_SEQUENCE, hit); + BASIC_STACKADJ(len - 1); + PyObject **stack = &TOP(); + PyObject **items = _PyTuple_ITEMS(seq); + while (len--) { + *stack-- = Py_NewRef(*items++); + } + Py_DECREF(seq); + DISPATCH(); + } + + TARGET(UNPACK_SEQUENCE_LIST) { + PyObject *seq = TOP(); + int len = GET_CACHE()->adaptive.original_oparg; + DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE); + DEOPT_IF(PyList_GET_SIZE(seq) != len, UNPACK_SEQUENCE); + STAT_INC(UNPACK_SEQUENCE, hit); + BASIC_STACKADJ(len - 1); + PyObject **stack = &TOP(); + PyObject **items = _PyList_ITEMS(seq); + while (len--) { + *stack-- = Py_NewRef(*items++); + } + Py_DECREF(seq); + DISPATCH(); + } + + TARGET(UNPACK_EX) { + PyObject *seq = TOP(); + int before = oparg & 0xFF, after = oparg >> 8; + PyObject **top = stack_pointer + before + after; + if (!unpack_iterable(tstate, seq, before, after, top)) { + STACK_SHRINK(1); Py_DECREF(seq); goto error; } + stack_pointer = top; Py_DECREF(seq); DISPATCH(); } @@ -5342,6 +5373,7 @@ MISS_WITH_CACHE(CALL_NO_KW) MISS_WITH_CACHE(BINARY_OP) MISS_WITH_CACHE(COMPARE_OP) MISS_WITH_CACHE(BINARY_SUBSCR) +MISS_WITH_CACHE(UNPACK_SEQUENCE) MISS_WITH_OPARG_COUNTER(STORE_SUBSCR) binary_subscr_dict_error: diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index c19cd0e88468a3..bed12b30c15728 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -139,26 +139,26 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_DEREF, &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, - &&TARGET_LOAD_FAST__LOAD_FAST, - &&TARGET_STORE_FAST__LOAD_FAST, + &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, + &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_CALL_FUNCTION_EX, - &&TARGET_LOAD_FAST__LOAD_CONST, + &&TARGET_UNPACK_SEQUENCE_TUPLE, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, &&TARGET_MAP_ADD, &&TARGET_LOAD_CLASSDEREF, &&TARGET_COPY_FREE_VARS, - &&TARGET_LOAD_CONST__LOAD_FAST, + &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, - &&TARGET_STORE_FAST__STORE_FAST, - &&_unknown_opcode, + &&TARGET_STORE_FAST__LOAD_FAST, + &&TARGET_LOAD_FAST__LOAD_CONST, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_LOAD_CONST__LOAD_FAST, + &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_LOAD_METHOD, &&_unknown_opcode, &&TARGET_LIST_EXTEND, diff --git a/Python/specialize.c b/Python/specialize.c index 44c006245ebfc9..4b58b8f3aebb7c 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -127,6 +127,7 @@ _Py_GetSpecializationStats(void) { err += add_stat_dict(stats, CALL_NO_KW, "call_no_kw"); err += add_stat_dict(stats, BINARY_OP, "binary_op"); err += add_stat_dict(stats, COMPARE_OP, "compare_op"); + err += add_stat_dict(stats, UNPACK_SEQUENCE, "unpack_sequence"); if (err < 0) { Py_DECREF(stats); return NULL; @@ -255,6 +256,7 @@ static uint8_t adaptive_opcodes[256] = { [STORE_ATTR] = STORE_ATTR_ADAPTIVE, [BINARY_OP] = BINARY_OP_ADAPTIVE, [COMPARE_OP] = COMPARE_OP_ADAPTIVE, + [UNPACK_SEQUENCE] = UNPACK_SEQUENCE_ADAPTIVE, }; /* The number of cache entries required for a "family" of instructions. */ @@ -268,6 +270,7 @@ static uint8_t cache_requirements[256] = { [STORE_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */ [BINARY_OP] = 1, // _PyAdaptiveEntry [COMPARE_OP] = 1, /* _PyAdaptiveEntry */ + [UNPACK_SEQUENCE] = 1, // _PyAdaptiveEntry }; /* Return the oparg for the cache_offset and instruction index. @@ -1746,3 +1749,34 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, STAT_INC(COMPARE_OP, success); adaptive->counter = initial_counter_value(); } + +void +_Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, + SpecializedCacheEntry *cache) +{ + _PyAdaptiveEntry *adaptive = &cache->adaptive; + if (PyTuple_CheckExact(seq)) { + if (PyTuple_GET_SIZE(seq) != adaptive->original_oparg) { + SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR); + goto failure; + } + *instr = _Py_MAKECODEUNIT(UNPACK_SEQUENCE_TUPLE, _Py_OPARG(*instr)); + goto success; + } + if (PyList_CheckExact(seq)) { + if (PyList_GET_SIZE(seq) != adaptive->original_oparg) { + SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR); + goto failure; + } + *instr = _Py_MAKECODEUNIT(UNPACK_SEQUENCE_LIST, _Py_OPARG(*instr)); + goto success; + } + SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_OTHER); +failure: + STAT_INC(UNPACK_SEQUENCE, failure); + cache_backoff(adaptive); + return; +success: + STAT_INC(UNPACK_SEQUENCE, success); + adaptive->counter = initial_counter_value(); +} From 5dab3be2a1ec247ed34e2437e3adf1a32764df4e Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Wed, 26 Jan 2022 15:13:04 -0800 Subject: [PATCH 2/9] Simplify things a bit --- Python/ceval.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index a25350f75790c4..1f27d24a7a2837 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2837,14 +2837,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(UNPACK_SEQUENCE) { PREDICTED(UNPACK_SEQUENCE); - PyObject *seq = TOP(); - PyObject **top = stack_pointer + oparg - 1; + PyObject *seq = POP(); + PyObject **top = stack_pointer + oparg; if (!unpack_iterable(tstate, seq, oparg, -1, top)) { - STACK_SHRINK(1); Py_DECREF(seq); goto error; } - stack_pointer = top; + STACK_GROW(oparg); Py_DECREF(seq); DISPATCH(); } @@ -2872,11 +2871,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); DEOPT_IF(PyTuple_GET_SIZE(seq) != len, UNPACK_SEQUENCE); STAT_INC(UNPACK_SEQUENCE, hit); - BASIC_STACKADJ(len - 1); - PyObject **stack = &TOP(); + STACK_SHRINK(1); PyObject **items = _PyTuple_ITEMS(seq); while (len--) { - *stack-- = Py_NewRef(*items++); + PUSH(Py_NewRef(items[len])); } Py_DECREF(seq); DISPATCH(); @@ -2888,26 +2886,24 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE); DEOPT_IF(PyList_GET_SIZE(seq) != len, UNPACK_SEQUENCE); STAT_INC(UNPACK_SEQUENCE, hit); - BASIC_STACKADJ(len - 1); - PyObject **stack = &TOP(); + STACK_SHRINK(1); PyObject **items = _PyList_ITEMS(seq); while (len--) { - *stack-- = Py_NewRef(*items++); + PUSH(Py_NewRef(items[len])); } Py_DECREF(seq); DISPATCH(); } TARGET(UNPACK_EX) { - PyObject *seq = TOP(); - int before = oparg & 0xFF, after = oparg >> 8; - PyObject **top = stack_pointer + before + after; - if (!unpack_iterable(tstate, seq, before, after, top)) { - STACK_SHRINK(1); + int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); + PyObject *seq = POP(); + PyObject **top = stack_pointer + totalargs; + if (!unpack_iterable(tstate, seq, oparg & 0xFF, oparg >> 8, top)) { Py_DECREF(seq); goto error; } - stack_pointer = top; + STACK_GROW(totalargs); Py_DECREF(seq); DISPATCH(); } From 502e53778206c06884b1e75c61238c8eb61172b0 Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Wed, 9 Feb 2022 11:47:41 -0800 Subject: [PATCH 3/9] Add UNPACK_SEQUENCE_TWO_TUPLE --- Include/opcode.h | 11 ++++++----- Lib/opcode.py | 1 + Python/ceval.c | 11 +++++++++++ Python/opcode_targets.h | 8 ++++---- Python/specialize.c | 5 +++++ 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Include/opcode.h b/Include/opcode.h index 203f36c633b715..792651933db0c2 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -170,11 +170,12 @@ extern "C" { #define UNPACK_SEQUENCE_ADAPTIVE 140 #define UNPACK_SEQUENCE_LIST 141 #define UNPACK_SEQUENCE_TUPLE 143 -#define LOAD_FAST__LOAD_FAST 150 -#define STORE_FAST__LOAD_FAST 153 -#define LOAD_FAST__LOAD_CONST 154 -#define LOAD_CONST__LOAD_FAST 158 -#define STORE_FAST__STORE_FAST 159 +#define UNPACK_SEQUENCE_TWO_TUPLE 150 +#define LOAD_FAST__LOAD_FAST 153 +#define STORE_FAST__LOAD_FAST 154 +#define LOAD_FAST__LOAD_CONST 158 +#define LOAD_CONST__LOAD_FAST 159 +#define STORE_FAST__STORE_FAST 161 #define DO_TRACING 255 #ifdef NEED_OPCODE_JUMP_TABLES static uint32_t _PyOpcode_RelativeJump[8] = { diff --git a/Lib/opcode.py b/Lib/opcode.py index a84602bc41232f..af4c513cf57b1e 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -282,6 +282,7 @@ def jabs_op(name, op): "UNPACK_SEQUENCE_ADAPTIVE", "UNPACK_SEQUENCE_LIST", "UNPACK_SEQUENCE_TUPLE", + "UNPACK_SEQUENCE_TWO_TUPLE", # Super instructions "LOAD_FAST__LOAD_FAST", "STORE_FAST__LOAD_FAST", diff --git a/Python/ceval.c b/Python/ceval.c index 1f27d24a7a2837..6b85b49843ea22 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2865,6 +2865,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } } + TARGET(UNPACK_SEQUENCE_TWO_TUPLE) { + PyObject *seq = TOP(); + DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE); + DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE); + STAT_INC(UNPACK_SEQUENCE, hit); + SET_TOP(Py_NewRef(PyTuple_GET_ITEM(seq, 1))); + PUSH(Py_NewRef(PyTuple_GET_ITEM(seq, 0))); + Py_DECREF(seq); + DISPATCH(); + } + TARGET(UNPACK_SEQUENCE_TUPLE) { PyObject *seq = TOP(); int len = GET_CACHE()->adaptive.original_oparg; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index bed12b30c15728..e5fb1627428852 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -149,18 +149,18 @@ static void *opcode_targets[256] = { &&TARGET_MAP_ADD, &&TARGET_LOAD_CLASSDEREF, &&TARGET_COPY_FREE_VARS, - &&TARGET_LOAD_FAST__LOAD_FAST, + &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, + &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_STORE_FAST__LOAD_FAST, - &&TARGET_LOAD_FAST__LOAD_CONST, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, + &&TARGET_LOAD_FAST__LOAD_CONST, &&TARGET_LOAD_CONST__LOAD_FAST, - &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_LOAD_METHOD, - &&_unknown_opcode, + &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, diff --git a/Python/specialize.c b/Python/specialize.c index 4b58b8f3aebb7c..ed466a69e676d2 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -1760,6 +1760,11 @@ _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR); goto failure; } + if (PyTuple_GET_SIZE(seq) == 2) { + *instr = _Py_MAKECODEUNIT(UNPACK_SEQUENCE_TWO_TUPLE, + _Py_OPARG(*instr)); + goto success; + } *instr = _Py_MAKECODEUNIT(UNPACK_SEQUENCE_TUPLE, _Py_OPARG(*instr)); goto success; } From fb1df0f4ffa3fe3f69da05a021705e883fae94fe Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Wed, 9 Feb 2022 16:00:56 -0800 Subject: [PATCH 4/9] Use NOTRACE_DISPATCH --- Python/ceval.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index d719d847b0e9c4..eebb16c383cbaa 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2768,7 +2768,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr SET_TOP(Py_NewRef(PyTuple_GET_ITEM(seq, 1))); PUSH(Py_NewRef(PyTuple_GET_ITEM(seq, 0))); Py_DECREF(seq); - DISPATCH(); + NOTRACE_DISPATCH(); } TARGET(UNPACK_SEQUENCE_TUPLE) { @@ -2783,7 +2783,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr PUSH(Py_NewRef(items[len])); } Py_DECREF(seq); - DISPATCH(); + NOTRACE_DISPATCH(); } TARGET(UNPACK_SEQUENCE_LIST) { @@ -2798,7 +2798,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr PUSH(Py_NewRef(items[len])); } Py_DECREF(seq); - DISPATCH(); + NOTRACE_DISPATCH(); } TARGET(UNPACK_EX) { From 5557efd079e9398cd5165d922fe878a6d2eb8b70 Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Wed, 9 Feb 2022 16:30:06 -0800 Subject: [PATCH 5/9] Clean things up a bit --- Python/specialize.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Python/specialize.c b/Python/specialize.c index ea4249b8d61ddd..09755bbb1fcb3a 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -1904,7 +1904,6 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, adaptive->counter = initial_counter_value(); } - void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache) @@ -1941,7 +1940,6 @@ _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, adaptive->counter = initial_counter_value(); } - int _PySpecialization_ClassifyIterator(PyObject *iter) { From d7c9fe10011af6cc701e7401113defc9799059e5 Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Wed, 9 Feb 2022 16:36:24 -0800 Subject: [PATCH 6/9] blurb add --- .../Core and Builtins/2022-02-09-16-36-11.bpo-46702.LcaEuC.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-02-09-16-36-11.bpo-46702.LcaEuC.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-02-09-16-36-11.bpo-46702.LcaEuC.rst b/Misc/NEWS.d/next/Core and Builtins/2022-02-09-16-36-11.bpo-46702.LcaEuC.rst new file mode 100644 index 00000000000000..8fe758528960f7 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-02-09-16-36-11.bpo-46702.LcaEuC.rst @@ -0,0 +1,2 @@ +Specialize :opcode:`UNPACK_SEQUENCE` for :class:`tuple` and :class:`list` +unpackings. From 477e6ef20450f705b2b9d4fd20cac61bbb8f003e Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Thu, 10 Feb 2022 12:52:10 -0800 Subject: [PATCH 7/9] Fixup --- Python/specialize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/specialize.c b/Python/specialize.c index d585700addc835..8deccbd39d2b51 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -2018,4 +2018,4 @@ _PySpecialization_ClassifyCallable(PyObject *callable) return call_fail_kind(callable); } -#endif \ No newline at end of file +#endif From 7d1944bc1ffa6d7abff5b473607b37f725c6dff4 Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Mon, 14 Feb 2022 14:24:37 -0800 Subject: [PATCH 8/9] Add more stats --- Python/specialize.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Python/specialize.c b/Python/specialize.c index 8e27f5b60b72fd..7c5aab78fed729 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -610,6 +610,11 @@ initial_counter_value(void) { #define SPEC_FAIL_FOR_ITER_DICT_VALUES 22 #define SPEC_FAIL_FOR_ITER_ENUMERATE 23 +// UNPACK_SEQUENCE + +#define SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR 8 +#define SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE 9 + static int specialize_module_load_attr( @@ -1956,7 +1961,17 @@ _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, *instr = _Py_MAKECODEUNIT(UNPACK_SEQUENCE_LIST, _Py_OPARG(*instr)); goto success; } - SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_OTHER); + if (PyIter_Check(seq)) { + SPECIALIZATION_FAIL(UNPACK_SEQUENCE, + SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR); + } + else if (PySequence_Check(seq)) { + SPECIALIZATION_FAIL(UNPACK_SEQUENCE, + SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE); + } + else { + SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_OTHER); + } failure: STAT_INC(UNPACK_SEQUENCE, failure); cache_backoff(adaptive); From c49b2fc04ee65ad839e43f7cc235d2ec3d93135f Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Mon, 14 Feb 2022 14:46:38 -0800 Subject: [PATCH 9/9] Don't classify failures when not collecting stats --- Python/specialize.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Python/specialize.c b/Python/specialize.c index 7c5aab78fed729..ab2363cab9f3eb 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -1935,6 +1935,20 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, adaptive->counter = initial_counter_value(); } +#ifdef Py_STATS +static int +unpack_sequence_fail_kind(PyObject *seq) +{ + if (PySequence_Check(seq)) { + return SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE; + } + if (PyIter_Check(seq)) { + return SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR; + } + return SPEC_FAIL_OTHER; +} +#endif + void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache) @@ -1961,17 +1975,7 @@ _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, *instr = _Py_MAKECODEUNIT(UNPACK_SEQUENCE_LIST, _Py_OPARG(*instr)); goto success; } - if (PyIter_Check(seq)) { - SPECIALIZATION_FAIL(UNPACK_SEQUENCE, - SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR); - } - else if (PySequence_Check(seq)) { - SPECIALIZATION_FAIL(UNPACK_SEQUENCE, - SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE); - } - else { - SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_OTHER); - } + SPECIALIZATION_FAIL(UNPACK_SEQUENCE, unpack_sequence_fail_kind(seq)); failure: STAT_INC(UNPACK_SEQUENCE, failure); cache_backoff(adaptive);