summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--py/mpconfig.h6
-rw-r--r--py/objtype.c1
-rw-r--r--py/runtime.c4
-rw-r--r--py/vm.c21
4 files changed, 31 insertions, 1 deletions
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 7b98112e1..2fbf1490d 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -527,6 +527,12 @@
#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0)
#endif
+// Optimise the fast path for loading attributes from instance types. Increases
+// Thumb2 code size by about 48 bytes.
+#ifndef MICROPY_OPT_LOAD_ATTR_FAST_PATH
+#define MICROPY_OPT_LOAD_ATTR_FAST_PATH (0)
+#endif
+
// Whether to use fast versions of bitwise operations (and, or, xor) when the
// arguments are both positive. Increases Thumb2 code size by about 250 bytes.
#ifndef MICROPY_OPT_MPZ_BITWISE
diff --git a/py/objtype.c b/py/objtype.c
index 508bab99d..0977a67ce 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -579,6 +579,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des
assert(mp_obj_is_instance_type(mp_obj_get_type(self_in)));
mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
+ // Note: This is fast-path'ed in the VM for the MP_BC_LOAD_ATTR operation.
mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
if (elem != NULL) {
// object member, always treated as a value
diff --git a/py/runtime.c b/py/runtime.c
index 27e5bc13e..2f7cf1fa6 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -1081,6 +1081,10 @@ void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) {
dest[0] = MP_OBJ_NULL;
dest[1] = MP_OBJ_NULL;
+ // Note: the specific case of obj being an instance type is fast-path'ed in the VM
+ // for the MP_BC_LOAD_ATTR opcode. Instance types handle type->attr and look up directly
+ // in their member's map.
+
// get the type
const mp_obj_type_t *type = mp_obj_get_type(obj);
diff --git a/py/vm.c b/py/vm.c
index bbfc9914e..e5a62e441 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -414,7 +414,26 @@ dispatch_loop:
FRAME_UPDATE();
MARK_EXC_IP_SELECTIVE();
DECODE_QSTR;
- SET_TOP(mp_load_attr(TOP(), qst));
+ mp_obj_t top = TOP();
+ mp_obj_t obj;
+ #if MICROPY_OPT_LOAD_ATTR_FAST_PATH
+ // For the specific case of an instance type, it implements .attr
+ // and forwards to its members map. Attribute lookups on instance
+ // types are extremely common, so avoid all the other checks and
+ // calls that normally happen first.
+ mp_map_elem_t *elem = NULL;
+ if (mp_obj_is_instance_type(mp_obj_get_type(top))) {
+ mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
+ elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
+ }
+ if (elem) {
+ obj = elem->value;
+ } else
+ #endif
+ {
+ obj = mp_load_attr(top, qst);
+ }
+ SET_TOP(obj);
DISPATCH();
}
#else