Skip to content

Commit 7b89ad8

Browse files
jimmodpgeorge
authored andcommitted
py/vm: Add a fast path for LOAD_ATTR on instance types.
When the LOAD_ATTR opcode is executed there are quite a few different cases that have to be handled, but the common case is accessing a member on an instance type. Typically, built-in types provide methods which is why this is common. Fortunately, for this specific case, if the member is found in the member map then there's no further processing. This optimisation does a relatively cheap check (type is instance) and then forwards directly to the member map lookup, falling back to the regular path if necessary. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
1 parent 910e060 commit 7b89ad8

File tree

4 files changed

+31
-1
lines changed

4 files changed

+31
-1
lines changed

py/mpconfig.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,12 @@
527527
#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0)
528528
#endif
529529

530+
// Optimise the fast path for loading attributes from instance types. Increases
531+
// Thumb2 code size by about 48 bytes.
532+
#ifndef MICROPY_OPT_LOAD_ATTR_FAST_PATH
533+
#define MICROPY_OPT_LOAD_ATTR_FAST_PATH (0)
534+
#endif
535+
530536
// Whether to use fast versions of bitwise operations (and, or, xor) when the
531537
// arguments are both positive. Increases Thumb2 code size by about 250 bytes.
532538
#ifndef MICROPY_OPT_MPZ_BITWISE

py/objtype.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des
579579
assert(mp_obj_is_instance_type(mp_obj_get_type(self_in)));
580580
mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
581581

582+
// Note: This is fast-path'ed in the VM for the MP_BC_LOAD_ATTR operation.
582583
mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
583584
if (elem != NULL) {
584585
// object member, always treated as a value

py/runtime.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,10 @@ void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) {
10811081
dest[0] = MP_OBJ_NULL;
10821082
dest[1] = MP_OBJ_NULL;
10831083

1084+
// Note: the specific case of obj being an instance type is fast-path'ed in the VM
1085+
// for the MP_BC_LOAD_ATTR opcode. Instance types handle type->attr and look up directly
1086+
// in their member's map.
1087+
10841088
// get the type
10851089
const mp_obj_type_t *type = mp_obj_get_type(obj);
10861090

py/vm.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,26 @@ FRAME_SETUP();
414414
FRAME_UPDATE();
415415
MARK_EXC_IP_SELECTIVE();
416416
DECODE_QSTR;
417-
SET_TOP(mp_load_attr(TOP(), qst));
417+
mp_obj_t top = TOP();
418+
mp_obj_t obj;
419+
#if MICROPY_OPT_LOAD_ATTR_FAST_PATH
420+
// For the specific case of an instance type, it implements .attr
421+
// and forwards to its members map. Attribute lookups on instance
422+
// types are extremely common, so avoid all the other checks and
423+
// calls that normally happen first.
424+
mp_map_elem_t *elem = NULL;
425+
if (mp_obj_is_instance_type(mp_obj_get_type(top))) {
426+
mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
427+
elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
428+
}
429+
if (elem) {
430+
obj = elem->value;
431+
} else
432+
#endif
433+
{
434+
obj = mp_load_attr(top, qst);
435+
}
436+
SET_TOP(obj);
418437
DISPATCH();
419438
}
420439
#else

0 commit comments

Comments
 (0)