blob: d67f5fc0056f1926e5b14c5f1dfb473489a250a4 [file] [log] [blame]
Damien429d7192013-10-04 19:53:11 +01001#include <stdio.h>
Paul Sokolovsky55ca0752014-03-30 17:35:53 +03002#include <string.h>
Damien429d7192013-10-04 19:53:11 +01003#include <assert.h>
4
Damience89a212013-10-15 22:25:17 +01005#include "nlr.h"
Damien429d7192013-10-04 19:53:11 +01006#include "misc.h"
Damiend99b0522013-12-21 18:17:45 +00007#include "mpconfig.h"
Damien George55baff42014-01-21 21:40:13 +00008#include "qstr.h"
Damiend99b0522013-12-21 18:17:45 +00009#include "obj.h"
Damien Georgedf8127a2014-04-13 11:04:33 +010010#include "emitglue.h"
Damien429d7192013-10-04 19:53:11 +010011#include "runtime.h"
Damiend99b0522013-12-21 18:17:45 +000012#include "bc0.h"
Damieneb19efb2013-10-10 22:06:54 +010013#include "bc.h"
Paul Sokolovskycf21a4e2014-03-26 17:36:12 +020014#include "objgenerator.h"
Damien429d7192013-10-04 19:53:11 +010015
Damien Georgee90be0d2014-04-10 16:21:34 +000016#define DETECT_VM_STACK_OVERFLOW (0)
17
Paul Sokolovsky85193422014-01-31 19:45:15 +020018// Value stack grows up (this makes it incompatible with native C stack, but
19// makes sure that arguments to functions are in natural order arg1..argN
20// (Python semantics mandates left-to-right evaluation order, including for
21// function arguments). Stack pointer is pre-incremented and points at the
22// top element.
23// Exception stack also grows up, top element is also pointed at.
24
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020025// Exception stack unwind reasons (WHY_* in CPython-speak)
Damien Georgecbddb272014-02-01 20:08:18 +000026// TODO perhaps compress this to RETURN=0, JUMP>0, with number of unwinds
27// left to do encoded in the JUMP number
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020028typedef enum {
29 UNWIND_RETURN = 1,
Damien Georgecbddb272014-02-01 20:08:18 +000030 UNWIND_JUMP,
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020031} mp_unwind_reason_t;
32
Damien Georgedf8127a2014-04-13 11:04:33 +010033#define DECODE_UINT do { \
Paul Sokolovsky0f96ec82014-02-18 21:21:22 +020034 unum = 0; \
35 do { \
36 unum = (unum << 7) + (*ip & 0x7f); \
37 } while ((*ip++ & 0x80) != 0); \
Damien Georgedf8127a2014-04-13 11:04:33 +010038} while (0)
Damien03c9cfb2013-11-05 22:06:08 +000039#define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0)
40#define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0)
Damien Georgedf8127a2014-04-13 11:04:33 +010041#define DECODE_QSTR do { \
Paul Sokolovsky0f96ec82014-02-18 21:21:22 +020042 qst = 0; \
43 do { \
44 qst = (qst << 7) + (*ip & 0x7f); \
45 } while ((*ip++ & 0x80) != 0); \
Damien Georgedf8127a2014-04-13 11:04:33 +010046} while (0)
47#define DECODE_PTR do { \
48 ip = (byte*)(((machine_uint_t)ip + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1))); /* align ip */ \
49 unum = *(machine_uint_t*)ip; \
50 ip += sizeof(machine_uint_t); \
51} while (0)
Damien George20006db2014-01-18 14:10:48 +000052#define PUSH(val) *++sp = (val)
53#define POP() (*sp--)
Damiendb4c3612013-12-10 17:27:24 +000054#define TOP() (*sp)
55#define SET_TOP(val) *sp = (val)
Damien429d7192013-10-04 19:53:11 +010056
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +020057#define PUSH_EXC_BLOCK() \
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +020058 DECODE_ULABEL; /* except labels are always forward */ \
59 ++exc_sp; \
60 exc_sp->opcode = op; \
61 exc_sp->handler = ip + unum; \
62 exc_sp->val_sp = MP_TAGPTR_MAKE(sp, currently_in_except_block); \
Damien Georged7592a12014-03-30 00:54:48 +000063 exc_sp->prev_exc = MP_OBJ_NULL; \
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +020064 currently_in_except_block = 0; /* in a try block now */
65
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +020066#define POP_EXC_BLOCK() \
67 currently_in_except_block = MP_TAGPTR_TAG(exc_sp->val_sp); /* restore previous state */ \
68 exc_sp--; /* pop back to previous exception handler */
69
Damien Georgebee17b02014-03-27 11:07:04 +000070mp_vm_return_kind_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, const mp_obj_t *args2, uint n_args2, mp_obj_t *ret) {
Damien George8dcc0c72014-03-27 10:55:21 +000071 const byte *ip = code;
72
73 // get code info size, and skip line number table
74 machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
75 ip += code_info_size;
76
Damien Georgebee17b02014-03-27 11:07:04 +000077 // bytecode prelude: state size and exception stack size; 16 bit uints
78 machine_uint_t n_state = ip[0] | (ip[1] << 8);
79 machine_uint_t n_exc_stack = ip[2] | (ip[3] << 8);
80 ip += 4;
Damien George8dcc0c72014-03-27 10:55:21 +000081
Damien George20006db2014-01-18 14:10:48 +000082 // allocate state for locals and stack
83 mp_obj_t temp_state[10];
Damiend99b0522013-12-21 18:17:45 +000084 mp_obj_t *state = &temp_state[0];
Damien Georgee90be0d2014-04-10 16:21:34 +000085#if DETECT_VM_STACK_OVERFLOW
Damien Georgea1ef4412014-04-10 16:59:44 +000086 n_state += 1;
87#endif
Damien40fdfe32013-11-05 22:16:22 +000088 if (n_state > 10) {
Damiend99b0522013-12-21 18:17:45 +000089 state = m_new(mp_obj_t, n_state);
Damien40fdfe32013-11-05 22:16:22 +000090 }
Damien George20006db2014-01-18 14:10:48 +000091 mp_obj_t *sp = &state[0] - 1;
92
Damien George8dcc0c72014-03-27 10:55:21 +000093 // allocate state for exceptions
Damien George89f94b52014-03-30 00:57:09 +000094 mp_exc_stack_t exc_state[4];
95 mp_exc_stack_t *exc_stack = &exc_state[0];
Damien George8dcc0c72014-03-27 10:55:21 +000096 if (n_exc_stack > 4) {
Damien George89f94b52014-03-30 00:57:09 +000097 exc_stack = m_new(mp_exc_stack_t, n_exc_stack);
Damien George8dcc0c72014-03-27 10:55:21 +000098 }
Damien George89f94b52014-03-30 00:57:09 +000099 mp_exc_stack_t *exc_sp = &exc_stack[0] - 1;
Damien George8dcc0c72014-03-27 10:55:21 +0000100
Damienbd254452013-10-16 20:39:12 +0100101 // init args
Damien Georgefb083ea2014-02-01 18:29:40 +0000102 for (uint i = 0; i < n_args; i++) {
Damien George20006db2014-01-18 14:10:48 +0000103 state[n_state - 1 - i] = args[i];
Damienbd254452013-10-16 20:39:12 +0100104 }
Damien Georgefb083ea2014-02-01 18:29:40 +0000105 for (uint i = 0; i < n_args2; i++) {
106 state[n_state - 1 - n_args - i] = args2[i];
107 }
Damien George08335002014-01-18 23:24:36 +0000108
Damien Georged99944a2014-04-09 19:53:31 +0100109 // set rest of state to MP_OBJ_NULL
110 for (uint i = 0; i < n_state - n_args - n_args2; i++) {
111 state[i] = MP_OBJ_NULL;
112 }
113
Damien George8dcc0c72014-03-27 10:55:21 +0000114 // bytecode prelude: initialise closed over variables
115 for (uint n_local = *ip++; n_local > 0; n_local--) {
116 uint local_num = *ip++;
Damien Georged99944a2014-04-09 19:53:31 +0100117 state[n_state - 1 - local_num] = mp_obj_new_cell(state[n_state - 1 - local_num]);
Damien George6baf76e2013-12-30 22:32:17 +0000118 }
119
120 // execute the byte code
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200121 mp_vm_return_kind_t vm_return_kind = mp_execute_byte_code_2(code, &ip, &state[n_state - 1], &sp, exc_stack, &exc_sp, MP_OBJ_NULL);
Damien George6baf76e2013-12-30 22:32:17 +0000122
Damien Georgee90be0d2014-04-10 16:21:34 +0000123#if DETECT_VM_STACK_OVERFLOW
Damien Georgea1ef4412014-04-10 16:59:44 +0000124 // We can't check the case when an exception is returned in state[n_state - 1]
125 // and there are no arguments, because in this case our detection slot may have
126 // been overwritten by the returned exception (which is allowed).
127 if (!(vm_return_kind == MP_VM_RETURN_EXCEPTION && n_args == 0 && n_args2 == 0)) {
128 // Just check to see that we have at least 1 null object left in the state.
129 bool overflow = true;
130 for (uint i = 0; i < n_state - n_args - n_args2; i++) {
131 if (state[i] == MP_OBJ_NULL) {
132 overflow = false;
133 break;
134 }
135 }
136 if (overflow) {
137 printf("VM stack overflow state=%p n_state+1=%u\n", state, n_state);
138 assert(0);
139 }
Damien Georgee90be0d2014-04-10 16:21:34 +0000140 }
141#endif
142
Damien Georgec8f78bc2014-02-15 22:55:00 +0000143 switch (vm_return_kind) {
144 case MP_VM_RETURN_NORMAL:
145 *ret = *sp;
146 return MP_VM_RETURN_NORMAL;
147 case MP_VM_RETURN_EXCEPTION:
148 *ret = state[n_state - 1];
149 return MP_VM_RETURN_EXCEPTION;
150 case MP_VM_RETURN_YIELD: // byte-code shouldn't yield
151 default:
152 assert(0);
153 *ret = mp_const_none;
154 return MP_VM_RETURN_NORMAL;
155 }
Damienbd254452013-10-16 20:39:12 +0100156}
157
Damien George20006db2014-01-18 14:10:48 +0000158// fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)
159// sp points to bottom of stack which grows up
Damien Georgec8f78bc2014-02-15 22:55:00 +0000160// returns:
161// MP_VM_RETURN_NORMAL, sp valid, return value in *sp
162// MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
163// MP_VM_RETURN_EXCEPTION, exception in fastn[0]
Paul Sokolovskyc0abc282014-03-22 13:49:31 +0200164mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out,
165 mp_obj_t *fastn, mp_obj_t **sp_in_out,
Damien George89f94b52014-03-30 00:57:09 +0000166 mp_exc_stack_t *exc_stack, mp_exc_stack_t **exc_sp_in_out,
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200167 volatile mp_obj_t inject_exc) {
Damienc9f91972013-10-15 23:46:01 +0100168 // careful: be sure to declare volatile any variables read in the exception handler (written is ok, I think)
169
AZ Huang9309d992014-04-15 15:57:01 +0800170#if MICROPY_USE_COMPUTED_GOTOS
171 #include "entry_table.h"
172 #define DISPATCH() do { \
173 save_ip = ip; \
174 op = *ip++; \
175 goto *entry_table[op]; \
AZ Huangb1f692e2014-04-14 23:22:44 +0800176 } while(0)
AZ Huang9309d992014-04-15 15:57:01 +0800177 #define ENTRY(op) entry_##op
178 #define ENTRY_DEFAULT entry_default
AZ Huangb1f692e2014-04-14 23:22:44 +0800179#else
AZ Huang9309d992014-04-15 15:57:01 +0800180 #define DISPATCH() break
181 #define ENTRY(op) case op
182 #define ENTRY_DEFAULT default
AZ Huangb1f692e2014-04-14 23:22:44 +0800183#endif
184
185 int op = 0;
Damienbd254452013-10-16 20:39:12 +0100186 const byte *ip = *ip_in_out;
Damiend99b0522013-12-21 18:17:45 +0000187 mp_obj_t *sp = *sp_in_out;
Damien429d7192013-10-04 19:53:11 +0100188 machine_uint_t unum;
Damien Georgecbd2f742014-01-19 11:48:48 +0000189 qstr qst;
Damiend99b0522013-12-21 18:17:45 +0000190 mp_obj_t obj1, obj2;
Damience89a212013-10-15 22:25:17 +0100191 nlr_buf_t nlr;
Damien429d7192013-10-04 19:53:11 +0100192
Paul Sokolovsky16734202014-03-22 23:20:07 +0200193 volatile bool currently_in_except_block = MP_TAGPTR_TAG(*exc_sp_in_out); // 0 or 1, to detect nested exceptions
Damien George89f94b52014-03-30 00:57:09 +0000194 mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(*exc_sp_in_out); // stack grows up, exc_sp points to top of stack
Damien George08335002014-01-18 23:24:36 +0000195 const byte *volatile save_ip = ip; // this is so we can access ip in the exception handler without making ip volatile (which means the compiler can't keep it in a register in the main loop)
Damienc9f91972013-10-15 23:46:01 +0100196
Damience89a212013-10-15 22:25:17 +0100197 // outer exception handling loop
Damien429d7192013-10-04 19:53:11 +0100198 for (;;) {
Damien George9e6e9352014-03-26 18:37:06 +0000199outer_dispatch_loop:
Damience89a212013-10-15 22:25:17 +0100200 if (nlr_push(&nlr) == 0) {
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200201 // If we have exception to inject, now that we finish setting up
202 // execution context, raise it. This works as if RAISE_VARARGS
203 // bytecode was executed.
Paul Sokolovskycf21a4e2014-03-26 17:36:12 +0200204 // Injecting exc into yield from generator is a special case,
205 // handled by MP_BC_YIELD_FROM itself
206 if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200207 mp_obj_t t = inject_exc;
208 inject_exc = MP_OBJ_NULL;
Damien Georgeea13f402014-04-05 18:32:08 +0100209 nlr_raise(mp_make_raise_obj(t));
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200210 }
Damience89a212013-10-15 22:25:17 +0100211 // loop to execute byte code
212 for (;;) {
Paul Sokolovsky6472dea2014-02-01 00:55:05 +0200213dispatch_loop:
AZ Huang9309d992014-04-15 15:57:01 +0800214#if MICROPY_USE_COMPUTED_GOTOS
AZ Huangb1f692e2014-04-14 23:22:44 +0800215 DISPATCH();
216#else
Damien George08335002014-01-18 23:24:36 +0000217 save_ip = ip;
AZ Huangb1f692e2014-04-14 23:22:44 +0800218 op = *ip++;
219
Damience89a212013-10-15 22:25:17 +0100220 switch (op) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800221#endif
222 //printf("ip=%p sp=%p op=%u\n", save_ip, sp, op);
Damien429d7192013-10-04 19:53:11 +0100223
AZ Huangb1f692e2014-04-14 23:22:44 +0800224 ENTRY(MP_BC_LOAD_CONST_FALSE):
225 PUSH(mp_const_false);
226 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100227
AZ Huangb1f692e2014-04-14 23:22:44 +0800228 ENTRY(MP_BC_LOAD_CONST_NONE):
229 PUSH(mp_const_none);
230 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100231
AZ Huangb1f692e2014-04-14 23:22:44 +0800232 ENTRY(MP_BC_LOAD_CONST_TRUE):
233 PUSH(mp_const_true);
234 DISPATCH();
Damien Georgee9906ac2014-01-04 18:44:46 +0000235
AZ Huangb1f692e2014-04-14 23:22:44 +0800236 ENTRY(MP_BC_LOAD_CONST_ELLIPSIS):
237 PUSH((mp_obj_t)&mp_const_ellipsis_obj);
238 DISPATCH();
239
240 ENTRY(MP_BC_LOAD_CONST_SMALL_INT): {
241 machine_int_t num = 0;
242 if ((ip[0] & 0x40) != 0) {
243 // Number is negative
244 num--;
Paul Sokolovsky047cd402014-02-19 15:47:59 +0200245 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800246 do {
247 num = (num << 7) | (*ip & 0x7f);
248 } while ((*ip++ & 0x80) != 0);
249 PUSH(MP_OBJ_NEW_SMALL_INT(num));
250 DISPATCH();
251 }
Damience89a212013-10-15 22:25:17 +0100252
AZ Huangb1f692e2014-04-14 23:22:44 +0800253 ENTRY(MP_BC_LOAD_CONST_INT):
254 DECODE_QSTR;
255 PUSH(mp_obj_new_int_from_long_str(qstr_str(qst)));
256 DISPATCH();
Paul Sokolovskya9f5abd2014-01-17 19:51:46 +0200257
AZ Huangb1f692e2014-04-14 23:22:44 +0800258 ENTRY(MP_BC_LOAD_CONST_DEC):
259 DECODE_QSTR;
260 PUSH(mp_load_const_dec(qst));
261 DISPATCH();
Damien7410e442013-11-02 19:47:57 +0000262
AZ Huangb1f692e2014-04-14 23:22:44 +0800263 ENTRY(MP_BC_LOAD_CONST_ID):
264 DECODE_QSTR;
265 PUSH(mp_load_const_str(qst)); // TODO
266 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100267
AZ Huangb1f692e2014-04-14 23:22:44 +0800268 ENTRY(MP_BC_LOAD_CONST_BYTES):
269 DECODE_QSTR;
270 PUSH(mp_load_const_bytes(qst));
271 DISPATCH();
Paul Sokolovskybdf822b2014-01-02 18:46:27 +0200272
AZ Huangb1f692e2014-04-14 23:22:44 +0800273 ENTRY(MP_BC_LOAD_CONST_STRING):
274 DECODE_QSTR;
275 PUSH(mp_load_const_str(qst));
276 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100277
AZ Huangb1f692e2014-04-14 23:22:44 +0800278 ENTRY(MP_BC_LOAD_NULL):
279 PUSH(MP_OBJ_NULL);
280 DISPATCH();
Damien George523b5752014-03-31 11:59:23 +0100281
AZ Huangb1f692e2014-04-14 23:22:44 +0800282 ENTRY(MP_BC_LOAD_FAST_0):
283 obj1 = fastn[0];
284 goto load_check;
Damience89a212013-10-15 22:25:17 +0100285
AZ Huangb1f692e2014-04-14 23:22:44 +0800286 ENTRY(MP_BC_LOAD_FAST_1):
287 obj1 = fastn[-1];
288 goto load_check;
Damience89a212013-10-15 22:25:17 +0100289
AZ Huangb1f692e2014-04-14 23:22:44 +0800290 ENTRY(MP_BC_LOAD_FAST_2):
291 obj1 = fastn[-2];
292 goto load_check;
Damience89a212013-10-15 22:25:17 +0100293
AZ Huangb1f692e2014-04-14 23:22:44 +0800294 ENTRY(MP_BC_LOAD_FAST_N):
295 DECODE_UINT;
296 obj1 = fastn[-unum];
297 load_check:
298 if (obj1 == MP_OBJ_NULL) {
299 local_name_error:
300 nlr_raise(mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment"));
301 }
302 PUSH(obj1);
303 DISPATCH();
Damien George2bf7c092014-04-09 15:26:46 +0100304
AZ Huangb1f692e2014-04-14 23:22:44 +0800305 ENTRY(MP_BC_LOAD_DEREF):
306 DECODE_UINT;
307 obj1 = mp_obj_cell_get(fastn[-unum]);
308 goto load_check;
Damien9ecbcff2013-12-11 00:41:43 +0000309
AZ Huangb1f692e2014-04-14 23:22:44 +0800310 ENTRY(MP_BC_LOAD_NAME):
311 DECODE_QSTR;
312 PUSH(mp_load_name(qst));
313 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100314
AZ Huangb1f692e2014-04-14 23:22:44 +0800315 ENTRY(MP_BC_LOAD_GLOBAL):
316 DECODE_QSTR;
317 PUSH(mp_load_global(qst));
318 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100319
AZ Huangb1f692e2014-04-14 23:22:44 +0800320 ENTRY(MP_BC_LOAD_ATTR):
321 DECODE_QSTR;
322 SET_TOP(mp_load_attr(TOP(), qst));
323 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100324
AZ Huangb1f692e2014-04-14 23:22:44 +0800325 ENTRY(MP_BC_LOAD_METHOD):
326 DECODE_QSTR;
327 mp_load_method(*sp, qst, sp);
328 sp += 1;
329 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100330
AZ Huangb1f692e2014-04-14 23:22:44 +0800331 ENTRY(MP_BC_LOAD_BUILD_CLASS):
332 PUSH(mp_load_build_class());
333 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100334
AZ Huangb1f692e2014-04-14 23:22:44 +0800335 ENTRY(MP_BC_STORE_FAST_0):
336 fastn[0] = POP();
337 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100338
AZ Huangb1f692e2014-04-14 23:22:44 +0800339 ENTRY(MP_BC_STORE_FAST_1):
340 fastn[-1] = POP();
341 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100342
AZ Huangb1f692e2014-04-14 23:22:44 +0800343 ENTRY(MP_BC_STORE_FAST_2):
344 fastn[-2] = POP();
345 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100346
AZ Huangb1f692e2014-04-14 23:22:44 +0800347 ENTRY(MP_BC_STORE_FAST_N):
348 DECODE_UINT;
349 fastn[-unum] = POP();
350 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100351
AZ Huangb1f692e2014-04-14 23:22:44 +0800352 ENTRY(MP_BC_STORE_DEREF):
353 DECODE_UINT;
354 mp_obj_cell_set(fastn[-unum], POP());
355 DISPATCH();
Damien9ecbcff2013-12-11 00:41:43 +0000356
AZ Huangb1f692e2014-04-14 23:22:44 +0800357 ENTRY(MP_BC_STORE_NAME):
358 DECODE_QSTR;
359 mp_store_name(qst, POP());
360 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100361
AZ Huangb1f692e2014-04-14 23:22:44 +0800362 ENTRY(MP_BC_STORE_GLOBAL):
363 DECODE_QSTR;
364 mp_store_global(qst, POP());
365 DISPATCH();
Damien6addc892013-11-04 23:04:50 +0000366
AZ Huangb1f692e2014-04-14 23:22:44 +0800367 ENTRY(MP_BC_STORE_ATTR):
368 DECODE_QSTR;
369 mp_store_attr(sp[0], qst, sp[-1]);
370 sp -= 2;
371 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100372
AZ Huangb1f692e2014-04-14 23:22:44 +0800373 ENTRY(MP_BC_STORE_SUBSCR):
374 mp_store_subscr(sp[-1], sp[0], sp[-2]);
375 sp -= 3;
376 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100377
AZ Huangb1f692e2014-04-14 23:22:44 +0800378 ENTRY(MP_BC_DELETE_FAST):
379 DECODE_UINT;
380 if (fastn[-unum] == MP_OBJ_NULL) {
381 goto local_name_error;
382 }
383 fastn[-unum] = MP_OBJ_NULL;
384 DISPATCH();
Damien George2bf7c092014-04-09 15:26:46 +0100385
AZ Huangb1f692e2014-04-14 23:22:44 +0800386 ENTRY(MP_BC_DELETE_DEREF):
387 DECODE_UINT;
388 if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
389 goto local_name_error;
390 }
391 mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);
392 DISPATCH();
Damien George2bf7c092014-04-09 15:26:46 +0100393
AZ Huangb1f692e2014-04-14 23:22:44 +0800394 ENTRY(MP_BC_DELETE_NAME):
395 DECODE_QSTR;
396 mp_delete_name(qst);
397 DISPATCH();
Paul Sokolovskyf9090342014-03-23 21:19:02 +0200398
AZ Huangb1f692e2014-04-14 23:22:44 +0800399 ENTRY(MP_BC_DELETE_GLOBAL):
400 DECODE_QSTR;
401 mp_delete_global(qst);
402 DISPATCH();
Damien George1d24ea52014-04-08 21:11:49 +0100403
AZ Huangb1f692e2014-04-14 23:22:44 +0800404 ENTRY(MP_BC_DUP_TOP):
405 obj1 = TOP();
406 PUSH(obj1);
407 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100408
AZ Huangb1f692e2014-04-14 23:22:44 +0800409 ENTRY(MP_BC_DUP_TOP_TWO):
410 sp += 2;
411 sp[0] = sp[-2];
412 sp[-1] = sp[-3];
413 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100414
AZ Huangb1f692e2014-04-14 23:22:44 +0800415 ENTRY(MP_BC_POP_TOP):
416 sp -= 1;
417 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100418
AZ Huangb1f692e2014-04-14 23:22:44 +0800419 ENTRY(MP_BC_ROT_TWO):
420 obj1 = sp[0];
421 sp[0] = sp[-1];
422 sp[-1] = obj1;
423 DISPATCH();
Damien4ebb32f2013-11-02 14:33:10 +0000424
AZ Huangb1f692e2014-04-14 23:22:44 +0800425 ENTRY(MP_BC_ROT_THREE):
426 obj1 = sp[0];
427 sp[0] = sp[-1];
428 sp[-1] = sp[-2];
429 sp[-2] = obj1;
430 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100431
AZ Huangb1f692e2014-04-14 23:22:44 +0800432 ENTRY(MP_BC_JUMP):
433 DECODE_SLABEL;
434 ip += unum;
435 DISPATCH();
436
437 ENTRY(MP_BC_POP_JUMP_IF_TRUE):
438 DECODE_SLABEL;
439 if (mp_obj_is_true(POP())) {
Damien03c9cfb2013-11-05 22:06:08 +0000440 ip += unum;
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200441 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800442 DISPATCH();
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200443
AZ Huangb1f692e2014-04-14 23:22:44 +0800444 ENTRY(MP_BC_POP_JUMP_IF_FALSE):
445 DECODE_SLABEL;
446 if (!mp_obj_is_true(POP())) {
447 ip += unum;
448 }
449 DISPATCH();
Damien George600ae732014-01-21 23:48:04 +0000450
AZ Huangb1f692e2014-04-14 23:22:44 +0800451 ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP):
452 DECODE_SLABEL;
453 if (mp_obj_is_true(TOP())) {
454 ip += unum;
455 } else {
456 sp--;
457 }
458 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100459
AZ Huangb1f692e2014-04-14 23:22:44 +0800460 ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP):
461 DECODE_SLABEL;
462 if (mp_obj_is_true(TOP())) {
463 sp--;
464 } else {
465 ip += unum;
466 }
467 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100468
AZ Huangb1f692e2014-04-14 23:22:44 +0800469 /* we are trying to get away without using this opcode
470 ENTRY(MP_BC_SETUP_LOOP):
471 DECODE_UINT;
472 // push_block(MP_BC_SETUP_LOOP, ip + unum, sp)
473 DISPATCH();
474 */
Damience89a212013-10-15 22:25:17 +0100475
AZ Huangb1f692e2014-04-14 23:22:44 +0800476 ENTRY(MP_BC_SETUP_WITH):
477 obj1 = TOP();
478 SET_TOP(mp_load_attr(obj1, MP_QSTR___exit__));
479 mp_load_method(obj1, MP_QSTR___enter__, sp + 1);
480 obj2 = mp_call_method_n_kw(0, 0, sp + 1);
481 PUSH_EXC_BLOCK();
482 PUSH(obj2);
483 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100484
AZ Huangb1f692e2014-04-14 23:22:44 +0800485 ENTRY(MP_BC_WITH_CLEANUP): {
486 // Arriving here, there's "exception control block" on top of stack,
487 // and __exit__ bound method underneath it. Bytecode calls __exit__,
488 // and "deletes" it off stack, shifting "exception control block"
489 // to its place.
490 static const mp_obj_t no_exc[] = {mp_const_none, mp_const_none, mp_const_none};
491 if (TOP() == mp_const_none) {
492 sp--;
Damiendb4c3612013-12-10 17:27:24 +0000493 obj1 = TOP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800494 SET_TOP(mp_const_none);
495 obj2 = mp_call_function_n_kw(obj1, 3, 0, no_exc);
496 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
497 mp_obj_t cause = POP();
498 switch (MP_OBJ_SMALL_INT_VALUE(cause)) {
499 case UNWIND_RETURN: {
500 mp_obj_t retval = POP();
501 obj2 = mp_call_function_n_kw(TOP(), 3, 0, no_exc);
502 SET_TOP(retval);
503 PUSH(cause);
504 break;
505 }
506 case UNWIND_JUMP: {
507 obj2 = mp_call_function_n_kw(sp[-2], 3, 0, no_exc);
508 // Pop __exit__ boundmethod at sp[-2]
509 sp[-2] = sp[-1];
510 sp[-1] = sp[0];
511 SET_TOP(cause);
512 break;
513 }
514 default:
515 assert(0);
516 }
517 } else if (mp_obj_is_exception_type(TOP())) {
518 mp_obj_t args[3] = {sp[0], sp[-1], sp[-2]};
519 obj2 = mp_call_function_n_kw(sp[-3], 3, 0, args);
520 // Pop __exit__ boundmethod at sp[-3]
521 // TODO: Once semantics is proven, optimize for case when obj2 == True
522 sp[-3] = sp[-2];
523 sp[-2] = sp[-1];
524 sp[-1] = sp[0];
Damien George20006db2014-01-18 14:10:48 +0000525 sp--;
AZ Huangb1f692e2014-04-14 23:22:44 +0800526 if (mp_obj_is_true(obj2)) {
527 // This is what CPython does
528 //PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_SILENCED));
529 // But what we need to do is - pop exception from value stack...
530 sp -= 3;
531 // ... pop "with" exception handler, and signal END_FINALLY
532 // to just execute finally handler normally (by pushing None
533 // on value stack)
534 assert(exc_sp >= exc_stack);
535 assert(exc_sp->opcode == MP_BC_SETUP_WITH);
536 POP_EXC_BLOCK();
537 PUSH(mp_const_none);
538 }
539 } else {
540 assert(0);
541 }
542 DISPATCH();
543 }
Damienc226dca2013-10-16 16:12:52 +0100544
AZ Huangb1f692e2014-04-14 23:22:44 +0800545 ENTRY(MP_BC_UNWIND_JUMP):
546 DECODE_SLABEL;
547 PUSH((void*)(ip + unum)); // push destination ip for jump
548 PUSH((void*)(machine_uint_t)(*ip)); // push number of exception handlers to unwind
549unwind_jump:
550 unum = (machine_uint_t)POP(); // get number of exception handlers to unwind
551 while (unum > 0) {
552 unum -= 1;
553 assert(exc_sp >= exc_stack);
554 if (exc_sp->opcode == MP_BC_SETUP_FINALLY || exc_sp->opcode == MP_BC_SETUP_WITH) {
555 // We're going to run "finally" code as a coroutine
556 // (not calling it recursively). Set up a sentinel
557 // on a stack so it can return back to us when it is
558 // done (when END_FINALLY reached).
559 PUSH((void*)unum); // push number of exception handlers left to unwind
560 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
561 ip = exc_sp->handler; // get exception handler byte code address
562 exc_sp--; // pop exception handler
563 goto dispatch_loop; // run the exception handler
564 }
565 exc_sp--;
566 }
567 ip = (const byte*)POP(); // pop destination ip for jump
568 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100569
AZ Huangb1f692e2014-04-14 23:22:44 +0800570 // matched against: POP_BLOCK or POP_EXCEPT (anything else?)
571 ENTRY(MP_BC_SETUP_EXCEPT):
572 ENTRY(MP_BC_SETUP_FINALLY):
573 PUSH_EXC_BLOCK();
574 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100575
AZ Huangb1f692e2014-04-14 23:22:44 +0800576 ENTRY(MP_BC_END_FINALLY):
577 // not fully implemented
578 // if TOS is an exception, reraises the exception (3 values on TOS)
579 // if TOS is None, just pops it and continues
580 // if TOS is an integer, does something else
581 // else error
582 if (mp_obj_is_exception_type(TOP())) {
583 nlr_raise(sp[-1]);
584 }
585 if (TOP() == mp_const_none) {
Damien George20006db2014-01-18 14:10:48 +0000586 sp--;
AZ Huangb1f692e2014-04-14 23:22:44 +0800587 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
588 // We finished "finally" coroutine and now dispatch back
589 // to our caller, based on TOS value
590 mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());
591 switch (reason) {
592 case UNWIND_RETURN:
593 goto unwind_return;
594 case UNWIND_JUMP:
595 goto unwind_jump;
596 }
597 assert(0);
598 } else {
599 assert(0);
600 }
601 DISPATCH();
602
603 ENTRY(MP_BC_GET_ITER):
604 SET_TOP(mp_getiter(TOP()));
605 DISPATCH();
606
607 ENTRY(MP_BC_FOR_ITER):
608 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
609 obj1 = mp_iternext_allow_raise(TOP());
610 if (obj1 == MP_OBJ_NULL) {
611 --sp; // pop the exhausted iterator
612 ip += unum; // jump to after for-block
613 } else {
614 PUSH(obj1); // push the next iteration value
615 }
616 DISPATCH();
617
618 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
619 ENTRY(MP_BC_POP_BLOCK):
620 // we are exiting an exception handler, so pop the last one of the exception-stack
621 assert(exc_sp >= exc_stack);
622 POP_EXC_BLOCK();
623 DISPATCH();
624
625 // matched against: SETUP_EXCEPT
626 ENTRY(MP_BC_POP_EXCEPT):
627 // TODO need to work out how blocks work etc
628 // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
629 assert(exc_sp >= exc_stack);
630 assert(currently_in_except_block);
631 //sp = (mp_obj_t*)(*exc_sp--);
632 //exc_sp--; // discard ip
633 POP_EXC_BLOCK();
634 //sp -= 3; // pop 3 exception values
635 DISPATCH();
636
637 ENTRY(MP_BC_NOT):
638 if (TOP() == mp_const_true) {
639 SET_TOP(mp_const_false);
640 } else {
641 SET_TOP(mp_const_true);
642 }
643 DISPATCH();
644
645 ENTRY(MP_BC_UNARY_OP):
646 unum = *ip++;
647 SET_TOP(mp_unary_op(unum, TOP()));
648 DISPATCH();
649
650 ENTRY(MP_BC_BINARY_OP):
651 unum = *ip++;
652 obj2 = POP();
653 obj1 = TOP();
654 SET_TOP(mp_binary_op(unum, obj1, obj2));
655 DISPATCH();
656
657 ENTRY(MP_BC_BUILD_TUPLE):
658 DECODE_UINT;
659 sp -= unum - 1;
660 SET_TOP(mp_obj_new_tuple(unum, sp));
661 DISPATCH();
662
663 ENTRY(MP_BC_BUILD_LIST):
664 DECODE_UINT;
665 sp -= unum - 1;
666 SET_TOP(mp_obj_new_list(unum, sp));
667 DISPATCH();
668
669 ENTRY(MP_BC_LIST_APPEND):
670 DECODE_UINT;
671 // I think it's guaranteed by the compiler that sp[unum] is a list
672 mp_obj_list_append(sp[-unum], sp[0]);
673 sp--;
674 DISPATCH();
675
676 ENTRY(MP_BC_BUILD_MAP):
677 DECODE_UINT;
678 PUSH(mp_obj_new_dict(unum));
679 DISPATCH();
680
681 ENTRY(MP_BC_STORE_MAP):
682 sp -= 2;
683 mp_obj_dict_store(sp[0], sp[2], sp[1]);
684 DISPATCH();
685
686 ENTRY(MP_BC_MAP_ADD):
687 DECODE_UINT;
688 // I think it's guaranteed by the compiler that sp[-unum - 1] is a map
689 mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]);
690 sp -= 2;
691 DISPATCH();
692
693 ENTRY(MP_BC_BUILD_SET):
694 DECODE_UINT;
695 sp -= unum - 1;
696 SET_TOP(mp_obj_new_set(unum, sp));
697 DISPATCH();
698
699 ENTRY(MP_BC_SET_ADD):
700 DECODE_UINT;
701 // I think it's guaranteed by the compiler that sp[-unum] is a set
702 mp_obj_set_store(sp[-unum], sp[0]);
703 sp--;
704 DISPATCH();
Damienc12aa462013-10-16 20:57:49 +0100705
Paul Sokolovskye606cb62014-01-04 01:34:23 +0200706#if MICROPY_ENABLE_SLICE
AZ Huangb1f692e2014-04-14 23:22:44 +0800707 ENTRY(MP_BC_BUILD_SLICE):
708 DECODE_UINT;
709 if (unum == 2) {
Damien Georgee337f1e2014-03-31 15:18:37 +0100710 obj2 = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800711 obj1 = TOP();
712 SET_TOP(mp_obj_new_slice(obj1, obj2, NULL));
713 } else {
714 obj1 = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "3-argument slice is not supported");
Damience89a212013-10-15 22:25:17 +0100715 nlr_pop();
Damien Georgee753d912014-04-08 16:49:28 +0100716 fastn[0] = obj1;
717 return MP_VM_RETURN_EXCEPTION;
AZ Huangb1f692e2014-04-14 23:22:44 +0800718 }
719 DISPATCH();
720#endif
721
722 ENTRY(MP_BC_UNPACK_SEQUENCE):
723 DECODE_UINT;
724 mp_unpack_sequence(sp[0], unum, sp);
725 sp += unum - 1;
726 DISPATCH();
727
728 ENTRY(MP_BC_UNPACK_EX):
729 DECODE_UINT;
730 mp_unpack_ex(sp[0], unum, sp);
731 sp += (unum & 0xff) + ((unum >> 8) & 0xff);
732 DISPATCH();
733
734 ENTRY(MP_BC_MAKE_FUNCTION):
735 DECODE_PTR;
736 PUSH(mp_make_function_from_raw_code((mp_raw_code_t*)unum, MP_OBJ_NULL, MP_OBJ_NULL));
737 DISPATCH();
738
739 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS):
740 DECODE_PTR;
741 // Stack layout: def_tuple def_dict <- TOS
742 obj1 = POP();
743 SET_TOP(mp_make_function_from_raw_code((mp_raw_code_t*)unum, TOP(), obj1));
744 DISPATCH();
745
746 ENTRY(MP_BC_MAKE_CLOSURE):
747 DECODE_PTR;
748 // Stack layout: closure_tuple <- TOS
749 SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, TOP(), MP_OBJ_NULL, MP_OBJ_NULL));
750 DISPATCH();
751
752 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS):
753 DECODE_PTR;
754 // Stack layout: def_tuple def_dict closure_tuple <- TOS
755 obj1 = POP();
756 obj2 = POP();
757 SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, obj1, TOP(), obj2));
758 DISPATCH();
759
760 ENTRY(MP_BC_CALL_FUNCTION):
761 DECODE_UINT;
762 // unum & 0xff == n_positional
763 // (unum >> 8) & 0xff == n_keyword
764 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
765 SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
766 DISPATCH();
767
768 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW):
769 DECODE_UINT;
770 // unum & 0xff == n_positional
771 // (unum >> 8) & 0xff == n_keyword
772 // We have folowing stack layout here:
773 // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
774 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
775 SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
776 DISPATCH();
777
778 ENTRY(MP_BC_CALL_METHOD):
779 DECODE_UINT;
780 // unum & 0xff == n_positional
781 // (unum >> 8) & 0xff == n_keyword
782 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
783 SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
784 DISPATCH();
785
786 ENTRY(MP_BC_CALL_METHOD_VAR_KW):
787 DECODE_UINT;
788 // unum & 0xff == n_positional
789 // (unum >> 8) & 0xff == n_keyword
790 // We have folowing stack layout here:
791 // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
792 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
793 SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
794 DISPATCH();
795
796 ENTRY(MP_BC_RETURN_VALUE):
797unwind_return:
798 while (exc_sp >= exc_stack) {
799 if (exc_sp->opcode == MP_BC_SETUP_FINALLY || exc_sp->opcode == MP_BC_SETUP_WITH) {
800 // We're going to run "finally" code as a coroutine
801 // (not calling it recursively). Set up a sentinel
802 // on a stack so it can return back to us when it is
803 // done (when END_FINALLY reached).
804 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
805 ip = exc_sp->handler;
806 // We don't need to do anything with sp, finally is just
807 // syntactic sugar for sequential execution??
808 // sp =
809 exc_sp--;
810 goto dispatch_loop;
811 }
812 exc_sp--;
813 }
814 nlr_pop();
815 *sp_in_out = sp;
816 assert(exc_sp == exc_stack - 1);
817 return MP_VM_RETURN_NORMAL;
818
819 ENTRY(MP_BC_RAISE_VARARGS):
820 unum = *ip++;
821 assert(unum <= 1);
822 if (unum == 0) {
823 // search for the inner-most previous exception, to reraise it
824 obj1 = MP_OBJ_NULL;
825 for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
826 if (e->prev_exc != MP_OBJ_NULL) {
827 obj1 = e->prev_exc;
828 break;
829 }
830 }
831 if (obj1 == MP_OBJ_NULL) {
832 nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise"));
833 }
834 } else {
835 obj1 = POP();
836 }
837 nlr_raise(mp_make_raise_obj(obj1));
838
839 ENTRY(MP_BC_YIELD_VALUE):
840yield:
841 nlr_pop();
842 *ip_in_out = ip;
843 *sp_in_out = sp;
844 *exc_sp_in_out = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
845 return MP_VM_RETURN_YIELD;
846
847 ENTRY(MP_BC_YIELD_FROM): {
848//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
849#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
850#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { nlr_raise(t); }
851 mp_vm_return_kind_t ret_kind;
852 obj1 = POP();
853 mp_obj_t t_exc = MP_OBJ_NULL;
854 if (inject_exc != MP_OBJ_NULL) {
855 t_exc = inject_exc;
856 inject_exc = MP_OBJ_NULL;
857 ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &obj2);
858 } else {
859 ret_kind = mp_resume(TOP(), obj1, MP_OBJ_NULL, &obj2);
860 }
861
862 if (ret_kind == MP_VM_RETURN_YIELD) {
863 ip--;
864 PUSH(obj2);
865 goto yield;
866 }
867 if (ret_kind == MP_VM_RETURN_NORMAL) {
868 // Pop exhausted gen
869 sp--;
870 if (obj2 == MP_OBJ_NULL) {
871 // Optimize StopIteration
872 // TODO: get StopIteration's value
873 PUSH(mp_const_none);
874 } else {
875 PUSH(obj2);
876 }
877
878 // If we injected GeneratorExit downstream, then even
879 // if it was swallowed, we re-raise GeneratorExit
880 GENERATOR_EXIT_IF_NEEDED(t_exc);
881 DISPATCH();
882 }
883 if (ret_kind == MP_VM_RETURN_EXCEPTION) {
884 // Pop exhausted gen
885 sp--;
886 if (EXC_MATCH(obj2, &mp_type_StopIteration)) {
887 PUSH(mp_obj_exception_get_value(obj2));
888 // If we injected GeneratorExit downstream, then even
889 // if it was swallowed, we re-raise GeneratorExit
890 GENERATOR_EXIT_IF_NEEDED(t_exc);
891 DISPATCH();
892 } else {
893 nlr_raise(obj2);
894 }
895 }
Damien429d7192013-10-04 19:53:11 +0100896 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800897
898 ENTRY(MP_BC_IMPORT_NAME):
899 DECODE_QSTR;
900 obj1 = POP();
901 SET_TOP(mp_import_name(qst, obj1, TOP()));
902 DISPATCH();
903
904 ENTRY(MP_BC_IMPORT_FROM):
905 DECODE_QSTR;
906 obj1 = mp_import_from(TOP(), qst);
907 PUSH(obj1);
908 DISPATCH();
909
910 ENTRY(MP_BC_IMPORT_STAR):
911 mp_import_all(POP());
912 DISPATCH();
913
914 ENTRY_DEFAULT:
915 printf("code %p, byte code 0x%02x not implemented\n", ip, op);
916 obj1 = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
917 nlr_pop();
918 fastn[0] = obj1;
919 return MP_VM_RETURN_EXCEPTION;
AZ Huang9309d992014-04-15 15:57:01 +0800920#if !MICROPY_USE_COMPUTED_GOTOS
921 } // switch
AZ Huangb1f692e2014-04-14 23:22:44 +0800922#endif
Damience89a212013-10-15 22:25:17 +0100923 }
Damien429d7192013-10-04 19:53:11 +0100924
Damience89a212013-10-15 22:25:17 +0100925 } else {
926 // exception occurred
Damien429d7192013-10-04 19:53:11 +0100927
Damien George9e6e9352014-03-26 18:37:06 +0000928 // check if it's a StopIteration within a for block
929 if (*save_ip == MP_BC_FOR_ITER && mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) {
930 ip = save_ip + 1;
931 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
932 --sp; // pop the exhausted iterator
933 ip += unum; // jump to after for-block
934 goto outer_dispatch_loop; // continue with dispatch loop
935 }
936
Damien George08335002014-01-18 23:24:36 +0000937 // set file and line number that the exception occurred at
Paul Sokolovsky382e8ee2014-01-30 13:49:18 +0200938 // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
939 // But consider how to handle nested exceptions.
Damien George6902eed2014-04-04 10:52:59 +0000940 // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
941 if (mp_obj_is_exception_instance(nlr.ret_val) && nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
Damien George08335002014-01-18 23:24:36 +0000942 machine_uint_t code_info_size = code_info[0] | (code_info[1] << 8) | (code_info[2] << 16) | (code_info[3] << 24);
Damien Georgecbd2f742014-01-19 11:48:48 +0000943 qstr source_file = code_info[4] | (code_info[5] << 8) | (code_info[6] << 16) | (code_info[7] << 24);
944 qstr block_name = code_info[8] | (code_info[9] << 8) | (code_info[10] << 16) | (code_info[11] << 24);
Damien George08335002014-01-18 23:24:36 +0000945 machine_uint_t source_line = 1;
946 machine_uint_t bc = save_ip - code_info - code_info_size;
Damien Georgecbd2f742014-01-19 11:48:48 +0000947 //printf("find %lu %d %d\n", bc, code_info[12], code_info[13]);
Damien George28eb5772014-01-25 11:43:20 +0000948 for (const byte* ci = code_info + 12; *ci && bc >= ((*ci) & 31); ci++) {
949 bc -= *ci & 31;
950 source_line += *ci >> 5;
Damien George08335002014-01-18 23:24:36 +0000951 }
Damien George136b1492014-01-19 12:38:49 +0000952 mp_obj_exception_add_traceback(nlr.ret_val, source_file, source_line, block_name);
Damien George08335002014-01-18 23:24:36 +0000953 }
954
Damien8f9e2ee2013-12-29 16:54:59 +0000955 while (currently_in_except_block) {
956 // nested exception
957
Paul Sokolovskyc0abc282014-03-22 13:49:31 +0200958 assert(exc_sp >= exc_stack);
Damien8f9e2ee2013-12-29 16:54:59 +0000959
960 // TODO make a proper message for nested exception
961 // at the moment we are just raising the very last exception (the one that caused the nested exception)
962
963 // move up to previous exception handler
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +0200964 POP_EXC_BLOCK();
Damien8f9e2ee2013-12-29 16:54:59 +0000965 }
966
Paul Sokolovskyc0abc282014-03-22 13:49:31 +0200967 if (exc_sp >= exc_stack) {
Damien8f9e2ee2013-12-29 16:54:59 +0000968 // set flag to indicate that we are now handling an exception
969 currently_in_except_block = 1;
970
Damience89a212013-10-15 22:25:17 +0100971 // catch exception and pass to byte code
Paul Sokolovsky16734202014-03-22 23:20:07 +0200972 sp = MP_TAGPTR_PTR(exc_sp->val_sp);
Paul Sokolovskyc7a0b142014-01-31 19:40:09 +0200973 ip = exc_sp->handler;
Damien Georged7592a12014-03-30 00:54:48 +0000974 // save this exception in the stack so it can be used in a reraise, if needed
975 exc_sp->prev_exc = nlr.ret_val;
Damienc9f91972013-10-15 23:46:01 +0100976 // push(traceback, exc-val, exc-type)
Damiend99b0522013-12-21 18:17:45 +0000977 PUSH(mp_const_none);
Damienc9f91972013-10-15 23:46:01 +0100978 PUSH(nlr.ret_val);
Paul Sokolovsky682f9e62014-03-29 02:52:17 +0200979 PUSH(mp_obj_get_type(nlr.ret_val));
Damien8f9e2ee2013-12-29 16:54:59 +0000980
Damience89a212013-10-15 22:25:17 +0100981 } else {
Damien Georgec8f78bc2014-02-15 22:55:00 +0000982 // propagate exception to higher level
983 // TODO what to do about ip and sp? they don't really make sense at this point
984 fastn[0] = nlr.ret_val; // must put exception here because sp is invalid
985 return MP_VM_RETURN_EXCEPTION;
Damience89a212013-10-15 22:25:17 +0100986 }
Damien429d7192013-10-04 19:53:11 +0100987 }
988 }
989}