summaryrefslogtreecommitdiff
path: root/Python/specialize.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/specialize.c')
-rw-r--r--Python/specialize.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/Python/specialize.c b/Python/specialize.c
index 3fa28f4098..9230087a78 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -96,6 +96,7 @@ _Py_GetSpecializationStats(void) {
return NULL;
}
int err = 0;
+ err += add_stat_dict(stats, LOAD_SUPER_ATTR, "load_super_attr");
err += add_stat_dict(stats, LOAD_ATTR, "load_attr");
err += add_stat_dict(stats, LOAD_GLOBAL, "load_global");
err += add_stat_dict(stats, BINARY_SUBSCR, "binary_subscr");
@@ -320,6 +321,14 @@ _PyCode_Quicken(PyCodeObject *code)
#define SPEC_FAIL_LOAD_GLOBAL_NON_DICT 17
#define SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT 18
+/* Super */
+
+#define SPEC_FAIL_SUPER_NOT_LOAD_METHOD 9
+#define SPEC_FAIL_SUPER_BAD_CLASS 10
+#define SPEC_FAIL_SUPER_SHADOWED 11
+#define SPEC_FAIL_SUPER_NOT_METHOD 12
+#define SPEC_FAIL_SUPER_ERROR_OR_NOT_FOUND 13
+
/* Attributes */
#define SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR 9
@@ -505,6 +514,52 @@ specialize_module_load_attr(
/* Attribute specialization */
+void
+_Py_Specialize_LoadSuperAttr(PyObject *global_super, PyObject *class, PyObject *self,
+ _Py_CODEUNIT *instr, PyObject *name, int load_method) {
+ assert(ENABLE_SPECIALIZATION);
+ assert(_PyOpcode_Caches[LOAD_SUPER_ATTR] == INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR);
+ _PySuperAttrCache *cache = (_PySuperAttrCache *)(instr + 1);
+ if (!load_method) {
+ SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_NOT_LOAD_METHOD);
+ goto fail;
+ }
+ if (global_super != (PyObject *)&PySuper_Type) {
+ SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_SHADOWED);
+ goto fail;
+ }
+ if (!PyType_Check(class)) {
+ SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_BAD_CLASS);
+ goto fail;
+ }
+ PyTypeObject *tp = (PyTypeObject *)class;
+ PyObject *res = _PySuper_LookupDescr(tp, self, name);
+ if (res == NULL) {
+ SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_ERROR_OR_NOT_FOUND);
+ PyErr_Clear();
+ goto fail;
+ }
+ if (_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)) {
+ write_u32(cache->class_version, tp->tp_version_tag);
+ write_u32(cache->self_type_version, Py_TYPE(self)->tp_version_tag);
+ write_obj(cache->method, res); // borrowed
+ instr->op.code = LOAD_SUPER_ATTR_METHOD;
+ goto success;
+ }
+ SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_NOT_METHOD);
+
+fail:
+ STAT_INC(LOAD_SUPER_ATTR, failure);
+ assert(!PyErr_Occurred());
+ instr->op.code = LOAD_SUPER_ATTR;
+ cache->counter = adaptive_counter_backoff(cache->counter);
+ return;
+success:
+ STAT_INC(LOAD_SUPER_ATTR, success);
+ assert(!PyErr_Occurred());
+ cache->counter = adaptive_counter_cooldown();
+}
+
typedef enum {
OVERRIDING, /* Is an overriding descriptor, and will remain so. */
METHOD, /* Attribute has Py_TPFLAGS_METHOD_DESCRIPTOR set */