diff --git a/py/mpconfig.h b/py/mpconfig.h index 0c46bf3e5a..cd9380aa6e 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -351,6 +351,22 @@ /*****************************************************************************/ /* Python internal features */ +// Hook for the VM at the start of the opcode loop (can contain variable +// definitions usable by the other hook functions) +#ifndef MICROPY_VM_HOOK_INIT +#define MICROPY_VM_HOOK_INIT +#endif + +// Hook for the VM during the opcode loop (but only after jump opcodes) +#ifndef MICROPY_VM_HOOK_LOOP +#define MICROPY_VM_HOOK_LOOP +#endif + +// Hook for the VM just before return opcode is finished being interpreted +#ifndef MICROPY_VM_HOOK_RETURN +#define MICROPY_VM_HOOK_RETURN +#endif + // Whether to include the garbage collector #ifndef MICROPY_ENABLE_GC #define MICROPY_ENABLE_GC (0) diff --git a/py/vm.c b/py/vm.c index 141315ea8e..b8d38f78e4 100644 --- a/py/vm.c +++ b/py/vm.c @@ -179,6 +179,7 @@ outer_dispatch_loop: const byte *ip = code_state->ip; mp_obj_t *sp = code_state->sp; mp_obj_t obj_shared; + MICROPY_VM_HOOK_INIT // If we have exception to inject, now that we finish setting up // execution context, raise it. This works as if RAISE_VARARGS @@ -1069,6 +1070,7 @@ unwind_return: nlr_pop(); code_state->sp = sp; assert(exc_sp == exc_stack - 1); + MICROPY_VM_HOOK_RETURN #if MICROPY_STACKLESS if (code_state->prev != NULL) { mp_obj_t res = *sp; @@ -1252,6 +1254,7 @@ yield: #endif pending_exception_check: + MICROPY_VM_HOOK_LOOP if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { MARK_EXC_IP_SELECTIVE(); mp_obj_t obj = MP_STATE_VM(mp_pending_exception);