summaryrefslogtreecommitdiffstats
path: root/Python/specialize.c
diff options
context:
space:
mode:
authorBrandt Bucher <brandtbucher@microsoft.com>2022-02-16 16:48:16 (GMT)
committerGitHub <noreply@github.com>2022-02-16 16:48:16 (GMT)
commita9da085015db8cbb81f660158864ac94fe6c67a2 (patch)
treec24578d6baf4b19b1e57598c32797ec9b17aaf99 /Python/specialize.c
parente8a19b092fc0551581e10d6f310dd5feabac7609 (diff)
downloadcpython-a9da085015db8cbb81f660158864ac94fe6c67a2.zip
cpython-a9da085015db8cbb81f660158864ac94fe6c67a2.tar.gz
cpython-a9da085015db8cbb81f660158864ac94fe6c67a2.tar.bz2
bpo-46702: Specialize UNPACK_SEQUENCE (GH-31240)
Diffstat (limited to 'Python/specialize.c')
-rw-r--r--Python/specialize.c94
1 files changed, 57 insertions, 37 deletions
diff --git a/Python/specialize.c b/Python/specialize.c
index 0e1ffad..ab2363c 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -51,6 +51,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. */
@@ -64,6 +65,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
};
Py_ssize_t _Py_QuickenedCount = 0;
@@ -155,6 +157,7 @@ _Py_GetSpecializationStats(void) {
err += add_stat_dict(stats, CALL, "call");
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;
@@ -607,27 +610,10 @@ 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_TUPLE_0 9
-#define SPEC_FAIL_UNPACK_SEQUENCE_TUPLE_1 10
-#define SPEC_FAIL_UNPACK_SEQUENCE_TUPLE_2 11
-#define SPEC_FAIL_UNPACK_SEQUENCE_TUPLE_3 12
-#define SPEC_FAIL_UNPACK_SEQUENCE_TUPLE_4 13
-#define SPEC_FAIL_UNPACK_SEQUENCE_TUPLE_N 14
-
-#define SPEC_FAIL_UNPACK_SEQUENCE_LIST_0 15
-#define SPEC_FAIL_UNPACK_SEQUENCE_LIST_1 16
-#define SPEC_FAIL_UNPACK_SEQUENCE_LIST_2 17
-#define SPEC_FAIL_UNPACK_SEQUENCE_LIST_3 18
-#define SPEC_FAIL_UNPACK_SEQUENCE_LIST_4 19
-#define SPEC_FAIL_UNPACK_SEQUENCE_LIST_N 20
-
-#define SPEC_FAIL_UNPACK_SEQUENCE_OTHER_0 21
-#define SPEC_FAIL_UNPACK_SEQUENCE_OTHER_1 22
-#define SPEC_FAIL_UNPACK_SEQUENCE_OTHER_2 23
-#define SPEC_FAIL_UNPACK_SEQUENCE_OTHER_3 24
-#define SPEC_FAIL_UNPACK_SEQUENCE_OTHER_4 25
-#define SPEC_FAIL_UNPACK_SEQUENCE_OTHER_N 26
+// UNPACK_SEQUENCE
+
+#define SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR 8
+#define SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE 9
static int
@@ -1950,6 +1936,56 @@ success:
}
#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)
+{
+ _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;
+ }
+ 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;
+ }
+ 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, unpack_sequence_fail_kind(seq));
+failure:
+ STAT_INC(UNPACK_SEQUENCE, failure);
+ cache_backoff(adaptive);
+ return;
+success:
+ STAT_INC(UNPACK_SEQUENCE, success);
+ adaptive->counter = initial_counter_value();
+}
+
+#ifdef Py_STATS
int
_PySpecialization_ClassifyIterator(PyObject *iter)
@@ -2002,22 +2038,6 @@ int
}
int
-_PySpecialization_ClassifySequence(PyObject *seq, int n)
-{
- assert(n >= 0);
- if (n > 4) {
- n = 5;
- }
- if (PyTuple_CheckExact(seq)) {
- return SPEC_FAIL_UNPACK_SEQUENCE_TUPLE_0 + n;
- }
- if (PyList_CheckExact(seq)) {
- return SPEC_FAIL_UNPACK_SEQUENCE_LIST_0 + n;
- }
- return SPEC_FAIL_UNPACK_SEQUENCE_OTHER_0 + n;
-}
-
-int
_PySpecialization_ClassifyCallable(PyObject *callable)
{
return call_fail_kind(callable);