summaryrefslogtreecommitdiffstatshomepage
path: root/py/vm.c
diff options
context:
space:
mode:
authorPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-12-28 07:17:43 +0200
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-12-28 07:37:04 +0200
commit749575097f1b5c738cd43dce6ef0960eee8af7a3 (patch)
tree36739e1ead5a89a9960682f67158607d2eb2c552 /py/vm.c
parent1570eaf0e3004127f0ac18f909ead29d6a48c87b (diff)
downloadmicropython-749575097f1b5c738cd43dce6ef0960eee8af7a3.tar.gz
micropython-749575097f1b5c738cd43dce6ef0960eee8af7a3.zip
vm: Record exception ip only for instructions where exceptions may happen.
Mirroring ip to a volatile memory variable for each opcode is an expensive operation. For quite a lot of often executed opcodes like stack manipulation or jumps, exceptions cannot actually happen. So, record ip only for opcode where that's possible.
Diffstat (limited to 'py/vm.c')
-rw-r--r--py/vm.c60
1 files changed, 58 insertions, 2 deletions
diff --git a/py/vm.c b/py/vm.c
index e7583ce076..ae66ed1fff 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -101,11 +101,19 @@ typedef enum {
// MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
// MP_VM_RETURN_EXCEPTION, exception in fastn[0]
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_obj_t inject_exc) {
+#define SELECTIVE_EXC_IP (0)
+#if SELECTIVE_EXC_IP
+#define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip - 1; }
+#define MARK_EXC_IP_GLOBAL()
+#else
+#define MARK_EXC_IP_SELECTIVE()
+#define MARK_EXC_IP_GLOBAL() { code_state->ip = ip; }
+#endif
#if MICROPY_OPT_COMPUTED_GOTO
#include "vmentrytable.h"
#define DISPATCH() do { \
TRACE(ip); \
- code_state->ip = ip; \
+ MARK_EXC_IP_GLOBAL(); \
goto *entry_table[*ip++]; \
} while(0)
#define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
@@ -161,7 +169,7 @@ dispatch_loop:
DISPATCH();
#else
TRACE(ip);
- code_state->ip = ip;
+ MARK_EXC_IP_GLOBAL();
switch (*ip++) {
#endif
@@ -201,6 +209,7 @@ dispatch_loop:
}
ENTRY(MP_BC_LOAD_CONST_DEC): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_QSTR;
PUSH(mp_load_const_dec(qst));
DISPATCH();
@@ -228,6 +237,7 @@ dispatch_loop:
load_check:
if (obj_shared == MP_OBJ_NULL) {
local_name_error: {
+ MARK_EXC_IP_SELECTIVE();
mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment");
RAISE(obj);
}
@@ -243,24 +253,28 @@ dispatch_loop:
}
ENTRY(MP_BC_LOAD_NAME): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_QSTR;
PUSH(mp_load_name(qst));
DISPATCH();
}
ENTRY(MP_BC_LOAD_GLOBAL): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_QSTR;
PUSH(mp_load_global(qst));
DISPATCH();
}
ENTRY(MP_BC_LOAD_ATTR): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_QSTR;
SET_TOP(mp_load_attr(TOP(), qst));
DISPATCH();
}
ENTRY(MP_BC_LOAD_METHOD): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_QSTR;
mp_load_method(*sp, qst, sp);
sp += 1;
@@ -268,10 +282,12 @@ dispatch_loop:
}
ENTRY(MP_BC_LOAD_BUILD_CLASS):
+ MARK_EXC_IP_SELECTIVE();
PUSH(mp_load_build_class());
DISPATCH();
ENTRY(MP_BC_LOAD_SUBSCR): {
+ MARK_EXC_IP_SELECTIVE();
mp_obj_t index = POP();
SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL));
DISPATCH();
@@ -290,18 +306,21 @@ dispatch_loop:
}
ENTRY(MP_BC_STORE_NAME): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_QSTR;
mp_store_name(qst, POP());
DISPATCH();
}
ENTRY(MP_BC_STORE_GLOBAL): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_QSTR;
mp_store_global(qst, POP());
DISPATCH();
}
ENTRY(MP_BC_STORE_ATTR): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_QSTR;
mp_store_attr(sp[0], qst, sp[-1]);
sp -= 2;
@@ -309,11 +328,13 @@ dispatch_loop:
}
ENTRY(MP_BC_STORE_SUBSCR):
+ MARK_EXC_IP_SELECTIVE();
mp_obj_subscr(sp[-1], sp[0], sp[-2]);
sp -= 3;
DISPATCH();
ENTRY(MP_BC_DELETE_FAST): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
if (fastn[-unum] == MP_OBJ_NULL) {
goto local_name_error;
@@ -323,6 +344,7 @@ dispatch_loop:
}
ENTRY(MP_BC_DELETE_DEREF): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
goto local_name_error;
@@ -332,12 +354,14 @@ dispatch_loop:
}
ENTRY(MP_BC_DELETE_NAME): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_QSTR;
mp_delete_name(qst);
DISPATCH();
}
ENTRY(MP_BC_DELETE_GLOBAL): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_QSTR;
mp_delete_global(qst);
DISPATCH();
@@ -417,6 +441,7 @@ dispatch_loop:
}
ENTRY(MP_BC_SETUP_WITH): {
+ MARK_EXC_IP_SELECTIVE();
mp_obj_t obj = TOP();
SET_TOP(mp_load_attr(obj, MP_QSTR___exit__));
mp_load_method(obj, MP_QSTR___enter__, sp + 1);
@@ -427,6 +452,7 @@ dispatch_loop:
}
ENTRY(MP_BC_WITH_CLEANUP): {
+ MARK_EXC_IP_SELECTIVE();
// Arriving here, there's "exception control block" on top of stack,
// and __exit__ bound method underneath it. Bytecode calls __exit__,
// and "deletes" it off stack, shifting "exception control block"
@@ -486,6 +512,7 @@ dispatch_loop:
}
ENTRY(MP_BC_UNWIND_JUMP): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_SLABEL;
PUSH((void*)(ip + slab)); // push destination ip for jump
PUSH((void*)(mp_uint_t)(*ip)); // push number of exception handlers to unwind (0x80 bit set if we also need to pop stack)
@@ -517,11 +544,13 @@ unwind_jump:;
// matched against: POP_BLOCK or POP_EXCEPT (anything else?)
ENTRY(MP_BC_SETUP_EXCEPT):
ENTRY(MP_BC_SETUP_FINALLY): {
+ MARK_EXC_IP_SELECTIVE();
PUSH_EXC_BLOCK((*code_state->ip == MP_BC_SETUP_FINALLY) ? 1 : 0);
DISPATCH();
}
ENTRY(MP_BC_END_FINALLY):
+ MARK_EXC_IP_SELECTIVE();
// not fully implemented
// if TOS is an exception, reraises the exception (3 values on TOS)
// if TOS is None, just pops it and continues
@@ -549,10 +578,12 @@ unwind_jump:;
DISPATCH();
ENTRY(MP_BC_GET_ITER):
+ MARK_EXC_IP_SELECTIVE();
SET_TOP(mp_getiter(TOP()));
DISPATCH();
ENTRY(MP_BC_FOR_ITER): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
code_state->sp = sp;
assert(TOP());
@@ -594,6 +625,7 @@ unwind_jump:;
DISPATCH();
ENTRY(MP_BC_BUILD_TUPLE): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
sp -= unum - 1;
SET_TOP(mp_obj_new_tuple(unum, sp));
@@ -601,6 +633,7 @@ unwind_jump:;
}
ENTRY(MP_BC_BUILD_LIST): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
sp -= unum - 1;
SET_TOP(mp_obj_new_list(unum, sp));
@@ -608,6 +641,7 @@ unwind_jump:;
}
ENTRY(MP_BC_LIST_APPEND): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
// I think it's guaranteed by the compiler that sp[unum] is a list
mp_obj_list_append(sp[-unum], sp[0]);
@@ -616,17 +650,20 @@ unwind_jump:;
}
ENTRY(MP_BC_BUILD_MAP): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
PUSH(mp_obj_new_dict(unum));
DISPATCH();
}
ENTRY(MP_BC_STORE_MAP):
+ MARK_EXC_IP_SELECTIVE();
sp -= 2;
mp_obj_dict_store(sp[0], sp[2], sp[1]);
DISPATCH();
ENTRY(MP_BC_MAP_ADD): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
// I think it's guaranteed by the compiler that sp[-unum - 1] is a map
mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]);
@@ -636,6 +673,7 @@ unwind_jump:;
#if MICROPY_PY_BUILTINS_SET
ENTRY(MP_BC_BUILD_SET): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
sp -= unum - 1;
SET_TOP(mp_obj_new_set(unum, sp));
@@ -643,6 +681,7 @@ unwind_jump:;
}
ENTRY(MP_BC_SET_ADD): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
// I think it's guaranteed by the compiler that sp[-unum] is a set
mp_obj_set_store(sp[-unum], sp[0]);
@@ -653,6 +692,7 @@ unwind_jump:;
#if MICROPY_PY_BUILTINS_SLICE
ENTRY(MP_BC_BUILD_SLICE): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
if (unum == 2) {
mp_obj_t stop = POP();
@@ -669,6 +709,7 @@ unwind_jump:;
#endif
ENTRY(MP_BC_UNPACK_SEQUENCE): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
mp_unpack_sequence(sp[0], unum, sp);
sp += unum - 1;
@@ -676,6 +717,7 @@ unwind_jump:;
}
ENTRY(MP_BC_UNPACK_EX): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
mp_unpack_ex(sp[0], unum, sp);
sp += (unum & 0xff) + ((unum >> 8) & 0xff);
@@ -715,6 +757,7 @@ unwind_jump:;
}
ENTRY(MP_BC_CALL_FUNCTION): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
// unum & 0xff == n_positional
// (unum >> 8) & 0xff == n_keyword
@@ -724,6 +767,7 @@ unwind_jump:;
}
ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
// unum & 0xff == n_positional
// (unum >> 8) & 0xff == n_keyword
@@ -735,6 +779,7 @@ unwind_jump:;
}
ENTRY(MP_BC_CALL_METHOD): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
// unum & 0xff == n_positional
// (unum >> 8) & 0xff == n_keyword
@@ -744,6 +789,7 @@ unwind_jump:;
}
ENTRY(MP_BC_CALL_METHOD_VAR_KW): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_UINT;
// unum & 0xff == n_positional
// (unum >> 8) & 0xff == n_keyword
@@ -755,6 +801,7 @@ unwind_jump:;
}
ENTRY(MP_BC_RETURN_VALUE):
+ MARK_EXC_IP_SELECTIVE();
unwind_return:
while (exc_sp >= exc_stack) {
if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
@@ -778,6 +825,7 @@ unwind_return:
return MP_VM_RETURN_NORMAL;
ENTRY(MP_BC_RAISE_VARARGS): {
+ MARK_EXC_IP_SELECTIVE();
mp_uint_t unum = *ip++;
mp_obj_t obj;
assert(unum <= 1);
@@ -810,6 +858,7 @@ yield:
return MP_VM_RETURN_YIELD;
ENTRY(MP_BC_YIELD_FROM): {
+ MARK_EXC_IP_SELECTIVE();
//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { RAISE(t); }
@@ -862,6 +911,7 @@ yield:
}
ENTRY(MP_BC_IMPORT_NAME): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_QSTR;
mp_obj_t obj = POP();
SET_TOP(mp_import_name(qst, obj, TOP()));
@@ -869,6 +919,7 @@ yield:
}
ENTRY(MP_BC_IMPORT_FROM): {
+ MARK_EXC_IP_SELECTIVE();
DECODE_QSTR;
mp_obj_t obj = mp_import_from(TOP(), qst);
PUSH(obj);
@@ -876,6 +927,7 @@ yield:
}
ENTRY(MP_BC_IMPORT_STAR):
+ MARK_EXC_IP_SELECTIVE();
mp_import_all(POP());
DISPATCH();
@@ -893,10 +945,12 @@ yield:
DISPATCH();
ENTRY(MP_BC_UNARY_OP_MULTI):
+ MARK_EXC_IP_SELECTIVE();
SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
DISPATCH();
ENTRY(MP_BC_BINARY_OP_MULTI): {
+ MARK_EXC_IP_SELECTIVE();
mp_obj_t rhs = POP();
mp_obj_t lhs = TOP();
SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
@@ -904,6 +958,7 @@ yield:
}
ENTRY_DEFAULT:
+ MARK_EXC_IP_SELECTIVE();
#else
ENTRY_DEFAULT:
if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
@@ -938,6 +993,7 @@ yield:
pending_exception_check:
if (mp_pending_exception != MP_OBJ_NULL) {
+ MARK_EXC_IP_SELECTIVE();
mp_obj_t obj = mp_pending_exception;
mp_pending_exception = MP_OBJ_NULL;
RAISE(obj);