[Python-checkins] Refine specialization stats (GH-27992)

markshannon webhook-mailer at python.org
Fri Aug 27 07:01:26 EDT 2021


https://github.com/python/cpython/commit/ee9c0527ae4b3868ab6162bb6f423645bf182022
commit: ee9c0527ae4b3868ab6162bb6f423645bf182022
branch: main
author: Mark Shannon <mark at hotpy.org>
committer: markshannon <mark at hotpy.org>
date: 2021-08-27T12:01:22+01:00
summary:

Refine specialization stats (GH-27992)

files:
M Python/specialize.c

diff --git a/Python/specialize.c b/Python/specialize.c
index b321368148f023..6c76fa6b05fbbe 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -405,6 +405,7 @@ _Py_Quicken(PyCodeObject *code) {
 
 /* Common */
 
+#define SPEC_FAIL_OTHER 0
 #define SPEC_FAIL_NO_DICT 1
 #define SPEC_FAIL_OVERRIDDEN 2
 #define SPEC_FAIL_OUT_OF_VERSIONS 3
@@ -427,24 +428,28 @@ _Py_Quicken(PyCodeObject *code) {
 
 /* Methods */
 
-#define SPEC_FAIL_NEGATIVE_DICTOFFSET 14
 #define SPEC_FAIL_IS_ATTR 15
 #define SPEC_FAIL_DICT_SUBCLASS 16
 #define SPEC_FAIL_BUILTIN_CLASS_METHOD 17
 #define SPEC_FAIL_CLASS_METHOD_OBJ 18
-#define SPEC_FAIL_NOT_METHOD 19
+#define SPEC_FAIL_OBJECT_SLOT 19
 
 /* Binary subscr */
 
-#define SPEC_FAIL_LIST_NON_INT_SUBSCRIPT 8
-#define SPEC_FAIL_TUPLE_NON_INT_SUBSCRIPT 9
-#define SPEC_FAIL_NOT_TUPLE_LIST_OR_DICT 10
+#define SPEC_FAIL_ARRAY_INT 8
+#define SPEC_FAIL_ARRAY_SLICE 9
+#define SPEC_FAIL_LIST_SLICE 10
+#define SPEC_FAIL_TUPLE_SLICE 11
+#define SPEC_FAIL_STRING_INT 12
+#define SPEC_FAIL_STRING_SLICE 13
+#define SPEC_FAIL_BUFFER_INT 15
+#define SPEC_FAIL_BUFFER_SLICE 16
+#define SPEC_FAIL_SEQUENCE_INT 17
 
 /* Binary add */
 
 #define SPEC_FAIL_NON_FUNCTION_SCOPE 11
 #define SPEC_FAIL_DIFFERENT_TYPES 12
-#define SPEC_FAIL_OTHER_TYPE 13
 
 
 static int
@@ -870,7 +875,7 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name,
     // Technically this is fine for bound method calls, but it's uncommon and
     // slightly slower at runtime to get dict.
     if (owner_cls->tp_dictoffset < 0) {
-        SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_NEGATIVE_DICTOFFSET);
+        SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_OUT_OF_RANGE);
         goto fail;
     }
     PyObject **owner_dictptr = _PyObject_GetDictPtr(owner);
@@ -896,16 +901,43 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name,
 
     assert(descr != NULL || kind == ABSENT || kind == GETSET_OVERRIDDEN);
     switch (kind) {
+        case OVERRIDING:
+            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OVERRIDING_DESCRIPTOR);
+            goto fail;
         case METHOD:
             break;
+        case PROPERTY:
+            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_PROPERTY);
+            goto fail;
+        case OBJECT_SLOT:
+            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OBJECT_SLOT);
+            goto fail;
+        case OTHER_SLOT:
+            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_NON_OBJECT_SLOT);
+            goto fail;
+        case DUNDER_CLASS:
+            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
+            goto fail;
+        case MUTABLE:
+            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_MUTABLE_CLASS);
+            goto fail;
+        case GETSET_OVERRIDDEN:
+            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OVERRIDDEN);
+            goto fail;
         case BUILTIN_CLASSMETHOD:
             SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_BUILTIN_CLASS_METHOD);
             goto fail;
         case PYTHON_CLASSMETHOD:
             SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_CLASS_METHOD_OBJ);
             goto fail;
-        default:
-            SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_NOT_METHOD);
+        case NON_OVERRIDING:
+            SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_NON_OVERRIDING_DESCRIPTOR);
+            goto fail;
+        case NON_DESCRIPTOR:
+            SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_NOT_DESCRIPTOR);
+            goto fail;
+        case ABSENT:
+            SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_EXPECTED_ERROR);
             goto fail;
     }
 
@@ -1046,6 +1078,45 @@ _Py_Specialize_LoadGlobal(
     return 0;
 }
 
+#if COLLECT_SPECIALIZATION_STATS_DETAILED
+static int
+binary_subscr_faiL_kind(PyTypeObject *container_type, PyObject *sub)
+{
+    if (container_type == &PyUnicode_Type) {
+        if (PyLong_CheckExact(sub)) {
+            return SPEC_FAIL_STRING_INT;
+        }
+        if (PySlice_Check(sub)) {
+            return SPEC_FAIL_STRING_SLICE;
+        }
+        return SPEC_FAIL_OTHER;
+    }
+    else if (strcmp(container_type->tp_name, "array.array") == 0) {
+        if (PyLong_CheckExact(sub)) {
+            return SPEC_FAIL_ARRAY_INT;
+        }
+        if (PySlice_Check(sub)) {
+            return SPEC_FAIL_ARRAY_SLICE;
+        }
+        return SPEC_FAIL_OTHER;
+    }
+    else if (container_type->tp_as_buffer) {
+        if (PyLong_CheckExact(sub)) {
+            return SPEC_FAIL_BUFFER_INT;
+        }
+        if (PySlice_Check(sub)) {
+            return SPEC_FAIL_BUFFER_SLICE;
+        }
+        return SPEC_FAIL_OTHER;
+    }
+    else if (container_type->tp_as_sequence) {
+        if (PyLong_CheckExact(sub) && container_type->tp_as_sequence->sq_item) {
+            return SPEC_FAIL_SEQUENCE_INT;
+        }
+    }
+    return SPEC_FAIL_OTHER;
+}
+#endif
 int
 _Py_Specialize_BinarySubscr(
      PyObject *container, PyObject *sub, _Py_CODEUNIT *instr)
@@ -1055,25 +1126,26 @@ _Py_Specialize_BinarySubscr(
         if (PyLong_CheckExact(sub)) {
             *instr = _Py_MAKECODEUNIT(BINARY_SUBSCR_LIST_INT, saturating_start());
             goto success;
-        } else {
-            SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_LIST_NON_INT_SUBSCRIPT);
-            goto fail;
         }
+        SPECIALIZATION_FAIL(BINARY_SUBSCR,
+            PySlice_Check(sub) ? SPEC_FAIL_LIST_SLICE : SPEC_FAIL_OTHER);
+        goto fail;
     }
     if (container_type == &PyTuple_Type) {
         if (PyLong_CheckExact(sub)) {
             *instr = _Py_MAKECODEUNIT(BINARY_SUBSCR_TUPLE_INT, saturating_start());
             goto success;
-        } else {
-            SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_TUPLE_NON_INT_SUBSCRIPT);
-            goto fail;
         }
+        SPECIALIZATION_FAIL(BINARY_SUBSCR,
+            PySlice_Check(sub) ? SPEC_FAIL_TUPLE_SLICE : SPEC_FAIL_OTHER);
+        goto fail;
     }
     if (container_type == &PyDict_Type) {
         *instr = _Py_MAKECODEUNIT(BINARY_SUBSCR_DICT, saturating_start());
         goto success;
     }
-    SPECIALIZATION_FAIL(BINARY_SUBSCR,SPEC_FAIL_NOT_TUPLE_LIST_OR_DICT);
+    SPECIALIZATION_FAIL(BINARY_SUBSCR,
+                        binary_subscr_faiL_kind(container_type, sub));
     goto fail;
 fail:
     STAT_INC(BINARY_SUBSCR, specialization_failure);
@@ -1114,7 +1186,7 @@ _Py_Specialize_BinaryAdd(PyObject *left, PyObject *right, _Py_CODEUNIT *instr)
 
     }
     else {
-        SPECIALIZATION_FAIL(BINARY_ADD, SPEC_FAIL_OTHER_TYPE);
+        SPECIALIZATION_FAIL(BINARY_ADD, SPEC_FAIL_OTHER);
     }
 fail:
     STAT_INC(BINARY_ADD, specialization_failure);



More information about the Python-checkins mailing list