/* Common */
+#define SPEC_FAIL_OTHER 0
#define SPEC_FAIL_NO_DICT 1
#define SPEC_FAIL_OVERRIDDEN 2
#define SPEC_FAIL_OUT_OF_VERSIONS 3
/* 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
// 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);
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;
}
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)
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);
}
else {
- SPECIALIZATION_FAIL(BINARY_ADD, SPEC_FAIL_OTHER_TYPE);
+ SPECIALIZATION_FAIL(BINARY_ADD, SPEC_FAIL_OTHER);
}
fail:
STAT_INC(BINARY_ADD, specialization_failure);