summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/bc.h13
-rw-r--r--py/vm.c18
2 files changed, 14 insertions, 17 deletions
diff --git a/py/bc.h b/py/bc.h
index 058eaba401..476942fb96 100644
--- a/py/bc.h
+++ b/py/bc.h
@@ -28,12 +28,10 @@
typedef struct _mp_exc_stack {
const byte *handler;
// bit 0 is saved currently_in_except_block value
+ // bit 1 is whether the opcode was SETUP_WITH or SETUP_FINALLY
mp_obj_t *val_sp;
// Saved exception, valid if currently_in_except_block bit is 1
mp_obj_t prev_exc;
- // We might only have 2 interesting cases here: SETUP_EXCEPT & SETUP_FINALLY,
- // consider storing it in bit 1 of val_sp. TODO: SETUP_WITH?
- byte opcode;
} mp_exc_stack_t;
typedef struct _mp_code_state {
@@ -56,7 +54,8 @@ void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t
void mp_bytecode_print(const void *descr, mp_uint_t n_total_args, const byte *code, mp_uint_t len);
void mp_bytecode_print2(const byte *code, mp_uint_t len);
-// Helper macros to access pointer with least significant bit holding a flag
-#define MP_TAGPTR_PTR(x) ((void*)((mp_uint_t)(x) & ~((mp_uint_t)1)))
-#define MP_TAGPTR_TAG(x) ((mp_uint_t)(x) & 1)
-#define MP_TAGPTR_MAKE(ptr, tag) ((void*)((mp_uint_t)(ptr) | tag))
+// Helper macros to access pointer with least significant bits holding flags
+#define MP_TAGPTR_PTR(x) ((void*)((mp_uint_t)(x) & ~((mp_uint_t)3)))
+#define MP_TAGPTR_TAG0(x) ((mp_uint_t)(x) & 1)
+#define MP_TAGPTR_TAG1(x) ((mp_uint_t)(x) & 2)
+#define MP_TAGPTR_MAKE(ptr, tag) ((void*)((mp_uint_t)(ptr) | (tag)))
diff --git a/py/vm.c b/py/vm.c
index fd9bbf0543..e7583ce076 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -81,18 +81,17 @@ typedef enum {
#define TOP() (*sp)
#define SET_TOP(val) *sp = (val)
-#define PUSH_EXC_BLOCK() do { \
+#define PUSH_EXC_BLOCK(with_or_finally) do { \
DECODE_ULABEL; /* except labels are always forward */ \
++exc_sp; \
- exc_sp->opcode = *code_state->ip; \
exc_sp->handler = ip + ulab; \
- exc_sp->val_sp = MP_TAGPTR_MAKE(sp, currently_in_except_block); \
+ exc_sp->val_sp = MP_TAGPTR_MAKE(sp, ((with_or_finally) << 1) | currently_in_except_block); \
exc_sp->prev_exc = MP_OBJ_NULL; \
currently_in_except_block = 0; /* in a try block now */ \
} while (0)
#define POP_EXC_BLOCK() \
- currently_in_except_block = MP_TAGPTR_TAG(exc_sp->val_sp); /* restore previous state */ \
+ currently_in_except_block = MP_TAGPTR_TAG0(exc_sp->val_sp); /* restore previous state */ \
exc_sp--; /* pop back to previous exception handler */
// fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)
@@ -130,7 +129,7 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
mp_exc_stack_t *const exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
// variables that are visible to the exception handler (declared volatile)
- volatile bool currently_in_except_block = MP_TAGPTR_TAG(code_state->exc_sp); // 0 or 1, to detect nested exceptions
+ volatile bool currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
// outer exception handling loop
@@ -422,7 +421,7 @@ dispatch_loop:
SET_TOP(mp_load_attr(obj, MP_QSTR___exit__));
mp_load_method(obj, MP_QSTR___enter__, sp + 1);
mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 1);
- PUSH_EXC_BLOCK();
+ PUSH_EXC_BLOCK(1);
PUSH(ret);
DISPATCH();
}
@@ -477,7 +476,6 @@ dispatch_loop:
// to just execute finally handler normally (by pushing None
// on value stack)
assert(exc_sp >= exc_stack);
- assert(exc_sp->opcode == MP_BC_SETUP_WITH);
POP_EXC_BLOCK();
PUSH(mp_const_none);
}
@@ -496,7 +494,7 @@ unwind_jump:;
while ((unum & 0x7f) > 0) {
unum -= 1;
assert(exc_sp >= exc_stack);
- if (exc_sp->opcode == MP_BC_SETUP_FINALLY || exc_sp->opcode == MP_BC_SETUP_WITH) {
+ if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
// We're going to run "finally" code as a coroutine
// (not calling it recursively). Set up a sentinel
// on a stack so it can return back to us when it is
@@ -519,7 +517,7 @@ unwind_jump:;
// matched against: POP_BLOCK or POP_EXCEPT (anything else?)
ENTRY(MP_BC_SETUP_EXCEPT):
ENTRY(MP_BC_SETUP_FINALLY): {
- PUSH_EXC_BLOCK();
+ PUSH_EXC_BLOCK((*code_state->ip == MP_BC_SETUP_FINALLY) ? 1 : 0);
DISPATCH();
}
@@ -759,7 +757,7 @@ unwind_jump:;
ENTRY(MP_BC_RETURN_VALUE):
unwind_return:
while (exc_sp >= exc_stack) {
- if (exc_sp->opcode == MP_BC_SETUP_FINALLY || exc_sp->opcode == MP_BC_SETUP_WITH) {
+ if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
// We're going to run "finally" code as a coroutine
// (not calling it recursively). Set up a sentinel
// on a stack so it can return back to us when it is