blob: 2dcc5378be338438779ececf34c14db8d6881710 [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
2 * This file is part of the Micro Python project, http://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2013, 2014 Damien P. George
Paul Sokolovskyda9f0922014-05-13 08:44:45 +03007 * Copyright (c) 2014 Paul Sokolovsky
Damien George04b91472014-05-03 23:27:38 +01008 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 */
27
Damien429d7192013-10-04 19:53:11 +010028#include <stdio.h>
Paul Sokolovsky55ca0752014-03-30 17:35:53 +030029#include <string.h>
Damien429d7192013-10-04 19:53:11 +010030#include <assert.h>
31
Damien Georgeb4b10fd2015-01-01 23:30:53 +000032#include "py/mpstate.h"
Damien George51dfcb42015-01-01 20:27:54 +000033#include "py/nlr.h"
34#include "py/emitglue.h"
Damien George7ee91cf2015-01-06 12:51:39 +000035#include "py/objtype.h"
Damien George51dfcb42015-01-01 20:27:54 +000036#include "py/runtime.h"
37#include "py/bc0.h"
38#include "py/bc.h"
Damien429d7192013-10-04 19:53:11 +010039
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +030040#if 0
Damien George7764f162014-12-12 17:18:56 +000041#define TRACE(ip) printf("sp=" INT_FMT " ", sp - code_state->sp); mp_bytecode_print2(ip, 1);
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +030042#else
43#define TRACE(ip)
44#endif
Damien Georgee90be0d2014-04-10 16:21:34 +000045
Paul Sokolovsky85193422014-01-31 19:45:15 +020046// Value stack grows up (this makes it incompatible with native C stack, but
47// makes sure that arguments to functions are in natural order arg1..argN
48// (Python semantics mandates left-to-right evaluation order, including for
49// function arguments). Stack pointer is pre-incremented and points at the
50// top element.
51// Exception stack also grows up, top element is also pointed at.
52
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020053// Exception stack unwind reasons (WHY_* in CPython-speak)
Damien Georgecbddb272014-02-01 20:08:18 +000054// TODO perhaps compress this to RETURN=0, JUMP>0, with number of unwinds
55// left to do encoded in the JUMP number
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020056typedef enum {
57 UNWIND_RETURN = 1,
Damien Georgecbddb272014-02-01 20:08:18 +000058 UNWIND_JUMP,
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020059} mp_unwind_reason_t;
60
Damien Georgecd97a432014-12-02 19:25:10 +000061#define DECODE_UINT \
62 mp_uint_t unum = 0; \
Paul Sokolovsky0f96ec82014-02-18 21:21:22 +020063 do { \
64 unum = (unum << 7) + (*ip & 0x7f); \
Damien Georgecd97a432014-12-02 19:25:10 +000065 } while ((*ip++ & 0x80) != 0)
66#define DECODE_ULABEL mp_uint_t ulab = (ip[0] | (ip[1] << 8)); ip += 2
67#define DECODE_SLABEL mp_uint_t slab = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2
Damien Georged8675542014-05-25 22:58:04 +010068#define DECODE_QSTR qstr qst = 0; \
Paul Sokolovsky0f96ec82014-02-18 21:21:22 +020069 do { \
70 qst = (qst << 7) + (*ip & 0x7f); \
Damien Georged8675542014-05-25 22:58:04 +010071 } while ((*ip++ & 0x80) != 0)
Damien Georgecd97a432014-12-02 19:25:10 +000072#define DECODE_PTR \
Damien George40f3c022014-07-03 13:25:24 +010073 ip = (byte*)(((mp_uint_t)ip + sizeof(mp_uint_t) - 1) & (~(sizeof(mp_uint_t) - 1))); /* align ip */ \
Damien Georgecd97a432014-12-02 19:25:10 +000074 void *ptr = (void*)*(mp_uint_t*)ip; \
75 ip += sizeof(mp_uint_t)
Damien George20006db2014-01-18 14:10:48 +000076#define PUSH(val) *++sp = (val)
77#define POP() (*sp--)
Damiendb4c3612013-12-10 17:27:24 +000078#define TOP() (*sp)
79#define SET_TOP(val) *sp = (val)
Damien429d7192013-10-04 19:53:11 +010080
Damien George74eb44c2014-12-22 12:49:57 +000081#define PUSH_EXC_BLOCK(with_or_finally) do { \
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +020082 DECODE_ULABEL; /* except labels are always forward */ \
83 ++exc_sp; \
Damien Georgecd97a432014-12-02 19:25:10 +000084 exc_sp->handler = ip + ulab; \
Damien George74eb44c2014-12-22 12:49:57 +000085 exc_sp->val_sp = MP_TAGPTR_MAKE(sp, ((with_or_finally) << 1) | currently_in_except_block); \
Damien Georged7592a12014-03-30 00:54:48 +000086 exc_sp->prev_exc = MP_OBJ_NULL; \
Damien Georgecd97a432014-12-02 19:25:10 +000087 currently_in_except_block = 0; /* in a try block now */ \
88} while (0)
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +020089
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +020090#define POP_EXC_BLOCK() \
Damien George74eb44c2014-12-22 12:49:57 +000091 currently_in_except_block = MP_TAGPTR_TAG0(exc_sp->val_sp); /* restore previous state */ \
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +020092 exc_sp--; /* pop back to previous exception handler */
93
Damien George20006db2014-01-18 14:10:48 +000094// fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)
95// sp points to bottom of stack which grows up
Damien Georgec8f78bc2014-02-15 22:55:00 +000096// returns:
97// MP_VM_RETURN_NORMAL, sp valid, return value in *sp
98// MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
99// MP_VM_RETURN_EXCEPTION, exception in fastn[0]
Damien Georgeaabd83e2014-06-07 14:16:08 +0100100mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_obj_t inject_exc) {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200101#define SELECTIVE_EXC_IP (0)
102#if SELECTIVE_EXC_IP
Damien Georgef89d6592014-12-29 00:29:59 +0000103#define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */
Paul Sokolovsky74957502014-12-28 07:17:43 +0200104#define MARK_EXC_IP_GLOBAL()
105#else
106#define MARK_EXC_IP_SELECTIVE()
Damien Georgef89d6592014-12-29 00:29:59 +0000107#define MARK_EXC_IP_GLOBAL() { code_state->ip = ip; } /* stores ip pointing to last opcode */
Paul Sokolovsky74957502014-12-28 07:17:43 +0200108#endif
Damien George58ebde42014-05-21 20:32:59 +0100109#if MICROPY_OPT_COMPUTED_GOTO
Damien George51dfcb42015-01-01 20:27:54 +0000110 #include "py/vmentrytable.h"
AZ Huang9309d992014-04-15 15:57:01 +0800111 #define DISPATCH() do { \
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +0300112 TRACE(ip); \
Paul Sokolovsky74957502014-12-28 07:17:43 +0200113 MARK_EXC_IP_GLOBAL(); \
Damien Georgedb128912014-04-27 18:19:06 +0100114 goto *entry_table[*ip++]; \
AZ Huangb1f692e2014-04-14 23:22:44 +0800115 } while(0)
Damien George124df6f2014-10-25 18:19:55 +0100116 #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
AZ Huang9309d992014-04-15 15:57:01 +0800117 #define ENTRY(op) entry_##op
118 #define ENTRY_DEFAULT entry_default
AZ Huangb1f692e2014-04-14 23:22:44 +0800119#else
AZ Huang9309d992014-04-15 15:57:01 +0800120 #define DISPATCH() break
Damien George124df6f2014-10-25 18:19:55 +0100121 #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
AZ Huang9309d992014-04-15 15:57:01 +0800122 #define ENTRY(op) case op
123 #define ENTRY_DEFAULT default
AZ Huangb1f692e2014-04-14 23:22:44 +0800124#endif
125
Damien George66ae8c92014-04-17 16:50:23 +0100126 // nlr_raise needs to be implemented as a goto, so that the C compiler's flow analyser
127 // sees that it's possible for us to jump from the dispatch loop to the exception
128 // handler. Without this, the code may have a different stack layout in the dispatch
129 // loop and the exception handler, leading to very obscure bugs.
130 #define RAISE(o) do { nlr_pop(); nlr.ret_val = o; goto exception_handler; } while(0)
Damien429d7192013-10-04 19:53:11 +0100131
Damien Georgeaabd83e2014-06-07 14:16:08 +0100132 // Pointers which are constant for particular invocation of mp_execute_bytecode()
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300133 mp_obj_t *const fastn = &code_state->state[code_state->n_state - 1];
134 mp_exc_stack_t *const exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
135
Damien George66ae8c92014-04-17 16:50:23 +0100136 // variables that are visible to the exception handler (declared volatile)
Damien George74eb44c2014-12-22 12:49:57 +0000137 volatile bool currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300138 mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
Damienc9f91972013-10-15 23:46:01 +0100139
Damience89a212013-10-15 22:25:17 +0100140 // outer exception handling loop
Damien429d7192013-10-04 19:53:11 +0100141 for (;;) {
Damien George66ae8c92014-04-17 16:50:23 +0100142 nlr_buf_t nlr;
Damien George9e6e9352014-03-26 18:37:06 +0000143outer_dispatch_loop:
Damience89a212013-10-15 22:25:17 +0100144 if (nlr_push(&nlr) == 0) {
Damien George66ae8c92014-04-17 16:50:23 +0100145 // local variables that are not visible to the exception handler
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300146 const byte *ip = code_state->ip;
147 mp_obj_t *sp = code_state->sp;
Damien Georged8675542014-05-25 22:58:04 +0100148 mp_obj_t obj_shared;
Damien George66ae8c92014-04-17 16:50:23 +0100149
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200150 // If we have exception to inject, now that we finish setting up
151 // execution context, raise it. This works as if RAISE_VARARGS
152 // bytecode was executed.
Paul Sokolovskycf21a4e2014-03-26 17:36:12 +0200153 // Injecting exc into yield from generator is a special case,
154 // handled by MP_BC_YIELD_FROM itself
155 if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
Damien Georged8675542014-05-25 22:58:04 +0100156 mp_obj_t exc = inject_exc;
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200157 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100158 exc = mp_make_raise_obj(exc);
159 RAISE(exc);
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200160 }
Damien George66ae8c92014-04-17 16:50:23 +0100161
Damience89a212013-10-15 22:25:17 +0100162 // loop to execute byte code
163 for (;;) {
Paul Sokolovsky6472dea2014-02-01 00:55:05 +0200164dispatch_loop:
Damien George58ebde42014-05-21 20:32:59 +0100165#if MICROPY_OPT_COMPUTED_GOTO
AZ Huangb1f692e2014-04-14 23:22:44 +0800166 DISPATCH();
167#else
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +0300168 TRACE(ip);
Paul Sokolovsky74957502014-12-28 07:17:43 +0200169 MARK_EXC_IP_GLOBAL();
Damien Georgedb128912014-04-27 18:19:06 +0100170 switch (*ip++) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800171#endif
Damien429d7192013-10-04 19:53:11 +0100172
AZ Huangb1f692e2014-04-14 23:22:44 +0800173 ENTRY(MP_BC_LOAD_CONST_FALSE):
174 PUSH(mp_const_false);
175 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100176
AZ Huangb1f692e2014-04-14 23:22:44 +0800177 ENTRY(MP_BC_LOAD_CONST_NONE):
178 PUSH(mp_const_none);
179 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100180
AZ Huangb1f692e2014-04-14 23:22:44 +0800181 ENTRY(MP_BC_LOAD_CONST_TRUE):
182 PUSH(mp_const_true);
183 DISPATCH();
Damien Georgee9906ac2014-01-04 18:44:46 +0000184
AZ Huangb1f692e2014-04-14 23:22:44 +0800185 ENTRY(MP_BC_LOAD_CONST_ELLIPSIS):
186 PUSH((mp_obj_t)&mp_const_ellipsis_obj);
187 DISPATCH();
188
189 ENTRY(MP_BC_LOAD_CONST_SMALL_INT): {
Damien George40f3c022014-07-03 13:25:24 +0100190 mp_int_t num = 0;
AZ Huangb1f692e2014-04-14 23:22:44 +0800191 if ((ip[0] & 0x40) != 0) {
192 // Number is negative
193 num--;
Paul Sokolovsky047cd402014-02-19 15:47:59 +0200194 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800195 do {
196 num = (num << 7) | (*ip & 0x7f);
197 } while ((*ip++ & 0x80) != 0);
198 PUSH(MP_OBJ_NEW_SMALL_INT(num));
199 DISPATCH();
200 }
Damience89a212013-10-15 22:25:17 +0100201
Damien Georged8675542014-05-25 22:58:04 +0100202 ENTRY(MP_BC_LOAD_CONST_INT): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800203 DECODE_QSTR;
Damien George503d6112014-05-28 14:07:21 +0100204 PUSH(mp_load_const_int(qst));
AZ Huangb1f692e2014-04-14 23:22:44 +0800205 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100206 }
Paul Sokolovskya9f5abd2014-01-17 19:51:46 +0200207
Damien Georged8675542014-05-25 22:58:04 +0100208 ENTRY(MP_BC_LOAD_CONST_DEC): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200209 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800210 DECODE_QSTR;
211 PUSH(mp_load_const_dec(qst));
212 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100213 }
Damien7410e442013-11-02 19:47:57 +0000214
Damien Georged8675542014-05-25 22:58:04 +0100215 ENTRY(MP_BC_LOAD_CONST_BYTES): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800216 DECODE_QSTR;
217 PUSH(mp_load_const_bytes(qst));
218 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100219 }
Paul Sokolovskybdf822b2014-01-02 18:46:27 +0200220
Damien Georged8675542014-05-25 22:58:04 +0100221 ENTRY(MP_BC_LOAD_CONST_STRING): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800222 DECODE_QSTR;
223 PUSH(mp_load_const_str(qst));
224 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100225 }
Damience89a212013-10-15 22:25:17 +0100226
Damien Georgedab13852015-01-13 15:55:54 +0000227 ENTRY(MP_BC_LOAD_CONST_OBJ): {
228 DECODE_PTR;
229 PUSH(ptr);
230 DISPATCH();
231 }
232
AZ Huangb1f692e2014-04-14 23:22:44 +0800233 ENTRY(MP_BC_LOAD_NULL):
234 PUSH(MP_OBJ_NULL);
235 DISPATCH();
Damien George523b5752014-03-31 11:59:23 +0100236
Damien Georgecd97a432014-12-02 19:25:10 +0000237 ENTRY(MP_BC_LOAD_FAST_N): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800238 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100239 obj_shared = fastn[-unum];
AZ Huangb1f692e2014-04-14 23:22:44 +0800240 load_check:
Damien Georged8675542014-05-25 22:58:04 +0100241 if (obj_shared == MP_OBJ_NULL) {
242 local_name_error: {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200243 MARK_EXC_IP_SELECTIVE();
Damien Georged8675542014-05-25 22:58:04 +0100244 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment");
245 RAISE(obj);
246 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800247 }
Damien Georged8675542014-05-25 22:58:04 +0100248 PUSH(obj_shared);
AZ Huangb1f692e2014-04-14 23:22:44 +0800249 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000250 }
Damien George2bf7c092014-04-09 15:26:46 +0100251
Damien Georgecd97a432014-12-02 19:25:10 +0000252 ENTRY(MP_BC_LOAD_DEREF): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800253 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100254 obj_shared = mp_obj_cell_get(fastn[-unum]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800255 goto load_check;
Damien Georgecd97a432014-12-02 19:25:10 +0000256 }
Damien9ecbcff2013-12-11 00:41:43 +0000257
Damien George7ee91cf2015-01-06 12:51:39 +0000258 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100259 ENTRY(MP_BC_LOAD_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200260 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800261 DECODE_QSTR;
262 PUSH(mp_load_name(qst));
263 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100264 }
Damien George7ee91cf2015-01-06 12:51:39 +0000265 #else
266 ENTRY(MP_BC_LOAD_NAME): {
267 MARK_EXC_IP_SELECTIVE();
268 DECODE_QSTR;
269 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
270 mp_uint_t x = *ip;
271 if (x < MP_STATE_CTX(dict_locals)->map.alloc && MP_STATE_CTX(dict_locals)->map.table[x].key == key) {
272 PUSH(MP_STATE_CTX(dict_locals)->map.table[x].value);
273 } else {
274 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_locals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
275 if (elem != NULL) {
276 *(byte*)ip = (elem - &MP_STATE_CTX(dict_locals)->map.table[0]) & 0xff;
277 PUSH(elem->value);
278 } else {
279 PUSH(mp_load_name(MP_OBJ_QSTR_VALUE(key)));
280 }
281 }
282 ip++;
283 DISPATCH();
284 }
285 #endif
Damience89a212013-10-15 22:25:17 +0100286
Damien George7ee91cf2015-01-06 12:51:39 +0000287 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100288 ENTRY(MP_BC_LOAD_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200289 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800290 DECODE_QSTR;
291 PUSH(mp_load_global(qst));
292 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100293 }
Damien George7ee91cf2015-01-06 12:51:39 +0000294 #else
295 ENTRY(MP_BC_LOAD_GLOBAL): {
296 MARK_EXC_IP_SELECTIVE();
297 DECODE_QSTR;
298 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
299 mp_uint_t x = *ip;
300 if (x < MP_STATE_CTX(dict_globals)->map.alloc && MP_STATE_CTX(dict_globals)->map.table[x].key == key) {
301 PUSH(MP_STATE_CTX(dict_globals)->map.table[x].value);
302 } else {
303 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_globals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
304 if (elem != NULL) {
305 *(byte*)ip = (elem - &MP_STATE_CTX(dict_globals)->map.table[0]) & 0xff;
306 PUSH(elem->value);
307 } else {
308 PUSH(mp_load_global(MP_OBJ_QSTR_VALUE(key)));
309 }
310 }
311 ip++;
312 DISPATCH();
313 }
314 #endif
Damience89a212013-10-15 22:25:17 +0100315
Damien George7ee91cf2015-01-06 12:51:39 +0000316 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100317 ENTRY(MP_BC_LOAD_ATTR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200318 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800319 DECODE_QSTR;
320 SET_TOP(mp_load_attr(TOP(), qst));
321 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100322 }
Damien George7ee91cf2015-01-06 12:51:39 +0000323 #else
324 ENTRY(MP_BC_LOAD_ATTR): {
325 MARK_EXC_IP_SELECTIVE();
326 DECODE_QSTR;
327 mp_obj_t top = TOP();
328 if (mp_obj_get_type(top)->load_attr == mp_obj_instance_load_attr) {
329 mp_obj_instance_t *self = top;
330 mp_uint_t x = *ip;
331 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
332 mp_map_elem_t *elem;
333 if (x < self->members.alloc && self->members.table[x].key == key) {
334 elem = &self->members.table[x];
335 } else {
336 elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);
337 if (elem != NULL) {
338 *(byte*)ip = elem - &self->members.table[0];
339 } else {
340 goto load_attr_cache_fail;
341 }
342 }
343 SET_TOP(elem->value);
344 ip++;
345 DISPATCH();
346 }
347 load_attr_cache_fail:
348 SET_TOP(mp_load_attr(top, qst));
349 ip++;
350 DISPATCH();
351 }
352 #endif
Damience89a212013-10-15 22:25:17 +0100353
Damien Georged8675542014-05-25 22:58:04 +0100354 ENTRY(MP_BC_LOAD_METHOD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200355 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800356 DECODE_QSTR;
357 mp_load_method(*sp, qst, sp);
358 sp += 1;
359 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100360 }
Damience89a212013-10-15 22:25:17 +0100361
AZ Huangb1f692e2014-04-14 23:22:44 +0800362 ENTRY(MP_BC_LOAD_BUILD_CLASS):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200363 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800364 PUSH(mp_load_build_class());
365 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100366
Damien Georged8675542014-05-25 22:58:04 +0100367 ENTRY(MP_BC_LOAD_SUBSCR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200368 MARK_EXC_IP_SELECTIVE();
Damien Georged8675542014-05-25 22:58:04 +0100369 mp_obj_t index = POP();
370 SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL));
Damien George729f7b42014-04-17 22:10:53 +0100371 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100372 }
Damien George729f7b42014-04-17 22:10:53 +0100373
Damien Georgecd97a432014-12-02 19:25:10 +0000374 ENTRY(MP_BC_STORE_FAST_N): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800375 DECODE_UINT;
376 fastn[-unum] = POP();
377 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000378 }
Damience89a212013-10-15 22:25:17 +0100379
Damien Georgecd97a432014-12-02 19:25:10 +0000380 ENTRY(MP_BC_STORE_DEREF): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800381 DECODE_UINT;
382 mp_obj_cell_set(fastn[-unum], POP());
383 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000384 }
Damien9ecbcff2013-12-11 00:41:43 +0000385
Damien Georged8675542014-05-25 22:58:04 +0100386 ENTRY(MP_BC_STORE_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200387 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800388 DECODE_QSTR;
389 mp_store_name(qst, POP());
390 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100391 }
Damience89a212013-10-15 22:25:17 +0100392
Damien Georged8675542014-05-25 22:58:04 +0100393 ENTRY(MP_BC_STORE_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200394 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800395 DECODE_QSTR;
396 mp_store_global(qst, POP());
397 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100398 }
Damien6addc892013-11-04 23:04:50 +0000399
Damien George7ee91cf2015-01-06 12:51:39 +0000400 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100401 ENTRY(MP_BC_STORE_ATTR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200402 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800403 DECODE_QSTR;
404 mp_store_attr(sp[0], qst, sp[-1]);
405 sp -= 2;
406 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100407 }
Damien George7ee91cf2015-01-06 12:51:39 +0000408 #else
409 // This caching code works with MICROPY_PY_BUILTINS_PROPERTY enabled because
410 // if the attr exists in self->members then it can't be a property. A
411 // consequence of this is that we can't use MP_MAP_LOOKUP_ADD_IF_NOT_FOUND
412 // in the fast-path below, because that store could override a property.
413 ENTRY(MP_BC_STORE_ATTR): {
414 MARK_EXC_IP_SELECTIVE();
415 DECODE_QSTR;
416 mp_obj_t top = TOP();
417 if (mp_obj_get_type(top)->store_attr == mp_obj_instance_store_attr && sp[-1] != MP_OBJ_NULL) {
418 mp_obj_instance_t *self = top;
419 mp_uint_t x = *ip;
420 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
421 mp_map_elem_t *elem;
422 if (x < self->members.alloc && self->members.table[x].key == key) {
423 elem = &self->members.table[x];
424 } else {
425 elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);
426 if (elem != NULL) {
427 *(byte*)ip = elem - &self->members.table[0];
428 } else {
429 goto store_attr_cache_fail;
430 }
431 }
432 elem->value = sp[-1];
433 sp -= 2;
434 ip++;
435 DISPATCH();
436 }
437 store_attr_cache_fail:
438 mp_store_attr(sp[0], qst, sp[-1]);
439 sp -= 2;
440 ip++;
441 DISPATCH();
442 }
443 #endif
Damience89a212013-10-15 22:25:17 +0100444
AZ Huangb1f692e2014-04-14 23:22:44 +0800445 ENTRY(MP_BC_STORE_SUBSCR):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200446 MARK_EXC_IP_SELECTIVE();
Damien George729f7b42014-04-17 22:10:53 +0100447 mp_obj_subscr(sp[-1], sp[0], sp[-2]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800448 sp -= 3;
449 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100450
Damien Georgecd97a432014-12-02 19:25:10 +0000451 ENTRY(MP_BC_DELETE_FAST): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200452 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800453 DECODE_UINT;
454 if (fastn[-unum] == MP_OBJ_NULL) {
455 goto local_name_error;
456 }
457 fastn[-unum] = MP_OBJ_NULL;
458 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000459 }
Damien George2bf7c092014-04-09 15:26:46 +0100460
Damien Georgecd97a432014-12-02 19:25:10 +0000461 ENTRY(MP_BC_DELETE_DEREF): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200462 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800463 DECODE_UINT;
464 if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
465 goto local_name_error;
466 }
467 mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);
468 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000469 }
Damien George2bf7c092014-04-09 15:26:46 +0100470
Damien Georged8675542014-05-25 22:58:04 +0100471 ENTRY(MP_BC_DELETE_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200472 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800473 DECODE_QSTR;
474 mp_delete_name(qst);
475 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100476 }
Paul Sokolovskyf9090342014-03-23 21:19:02 +0200477
Damien Georged8675542014-05-25 22:58:04 +0100478 ENTRY(MP_BC_DELETE_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200479 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800480 DECODE_QSTR;
481 mp_delete_global(qst);
482 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100483 }
Damien George1d24ea52014-04-08 21:11:49 +0100484
Damien Georged8675542014-05-25 22:58:04 +0100485 ENTRY(MP_BC_DUP_TOP): {
486 mp_obj_t top = TOP();
487 PUSH(top);
AZ Huangb1f692e2014-04-14 23:22:44 +0800488 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100489 }
Damience89a212013-10-15 22:25:17 +0100490
AZ Huangb1f692e2014-04-14 23:22:44 +0800491 ENTRY(MP_BC_DUP_TOP_TWO):
492 sp += 2;
493 sp[0] = sp[-2];
494 sp[-1] = sp[-3];
495 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100496
AZ Huangb1f692e2014-04-14 23:22:44 +0800497 ENTRY(MP_BC_POP_TOP):
498 sp -= 1;
499 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100500
Damien Georged8675542014-05-25 22:58:04 +0100501 ENTRY(MP_BC_ROT_TWO): {
502 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800503 sp[0] = sp[-1];
Damien Georged8675542014-05-25 22:58:04 +0100504 sp[-1] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800505 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100506 }
Damien4ebb32f2013-11-02 14:33:10 +0000507
Damien Georged8675542014-05-25 22:58:04 +0100508 ENTRY(MP_BC_ROT_THREE): {
509 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800510 sp[0] = sp[-1];
511 sp[-1] = sp[-2];
Damien Georged8675542014-05-25 22:58:04 +0100512 sp[-2] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800513 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100514 }
Damience89a212013-10-15 22:25:17 +0100515
Damien Georgecd97a432014-12-02 19:25:10 +0000516 ENTRY(MP_BC_JUMP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800517 DECODE_SLABEL;
Damien Georgecd97a432014-12-02 19:25:10 +0000518 ip += slab;
Damien George124df6f2014-10-25 18:19:55 +0100519 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000520 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800521
Damien Georgecd97a432014-12-02 19:25:10 +0000522 ENTRY(MP_BC_POP_JUMP_IF_TRUE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800523 DECODE_SLABEL;
524 if (mp_obj_is_true(POP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000525 ip += slab;
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200526 }
Damien George124df6f2014-10-25 18:19:55 +0100527 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000528 }
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200529
Damien Georgecd97a432014-12-02 19:25:10 +0000530 ENTRY(MP_BC_POP_JUMP_IF_FALSE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800531 DECODE_SLABEL;
532 if (!mp_obj_is_true(POP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000533 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800534 }
Damien George124df6f2014-10-25 18:19:55 +0100535 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000536 }
Damien George600ae732014-01-21 23:48:04 +0000537
Damien Georgecd97a432014-12-02 19:25:10 +0000538 ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800539 DECODE_SLABEL;
540 if (mp_obj_is_true(TOP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000541 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800542 } else {
543 sp--;
544 }
Damien George124df6f2014-10-25 18:19:55 +0100545 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000546 }
Damience89a212013-10-15 22:25:17 +0100547
Damien Georgecd97a432014-12-02 19:25:10 +0000548 ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800549 DECODE_SLABEL;
550 if (mp_obj_is_true(TOP())) {
551 sp--;
552 } else {
Damien Georgecd97a432014-12-02 19:25:10 +0000553 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800554 }
Damien George124df6f2014-10-25 18:19:55 +0100555 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000556 }
Damience89a212013-10-15 22:25:17 +0100557
Damien Georged8675542014-05-25 22:58:04 +0100558 ENTRY(MP_BC_SETUP_WITH): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200559 MARK_EXC_IP_SELECTIVE();
Damien Georged8675542014-05-25 22:58:04 +0100560 mp_obj_t obj = TOP();
561 SET_TOP(mp_load_attr(obj, MP_QSTR___exit__));
562 mp_load_method(obj, MP_QSTR___enter__, sp + 1);
563 mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 1);
Damien George74eb44c2014-12-22 12:49:57 +0000564 PUSH_EXC_BLOCK(1);
Damien Georged8675542014-05-25 22:58:04 +0100565 PUSH(ret);
AZ Huangb1f692e2014-04-14 23:22:44 +0800566 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100567 }
Damience89a212013-10-15 22:25:17 +0100568
AZ Huangb1f692e2014-04-14 23:22:44 +0800569 ENTRY(MP_BC_WITH_CLEANUP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200570 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800571 // Arriving here, there's "exception control block" on top of stack,
572 // and __exit__ bound method underneath it. Bytecode calls __exit__,
573 // and "deletes" it off stack, shifting "exception control block"
574 // to its place.
575 static const mp_obj_t no_exc[] = {mp_const_none, mp_const_none, mp_const_none};
576 if (TOP() == mp_const_none) {
577 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100578 mp_obj_t obj = TOP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800579 SET_TOP(mp_const_none);
Damien Georged8675542014-05-25 22:58:04 +0100580 mp_call_function_n_kw(obj, 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800581 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
582 mp_obj_t cause = POP();
583 switch (MP_OBJ_SMALL_INT_VALUE(cause)) {
584 case UNWIND_RETURN: {
585 mp_obj_t retval = POP();
Damien Georged8675542014-05-25 22:58:04 +0100586 mp_call_function_n_kw(TOP(), 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800587 SET_TOP(retval);
588 PUSH(cause);
589 break;
590 }
591 case UNWIND_JUMP: {
Damien Georged8675542014-05-25 22:58:04 +0100592 mp_call_function_n_kw(sp[-2], 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800593 // Pop __exit__ boundmethod at sp[-2]
594 sp[-2] = sp[-1];
595 sp[-1] = sp[0];
596 SET_TOP(cause);
597 break;
598 }
599 default:
600 assert(0);
601 }
602 } else if (mp_obj_is_exception_type(TOP())) {
603 mp_obj_t args[3] = {sp[0], sp[-1], sp[-2]};
Damien Georged8675542014-05-25 22:58:04 +0100604 mp_obj_t ret_value = mp_call_function_n_kw(sp[-3], 3, 0, args);
AZ Huangb1f692e2014-04-14 23:22:44 +0800605 // Pop __exit__ boundmethod at sp[-3]
Damien Georged8675542014-05-25 22:58:04 +0100606 // TODO: Once semantics is proven, optimize for case when ret_value == True
AZ Huangb1f692e2014-04-14 23:22:44 +0800607 sp[-3] = sp[-2];
608 sp[-2] = sp[-1];
609 sp[-1] = sp[0];
Damien George20006db2014-01-18 14:10:48 +0000610 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100611 if (mp_obj_is_true(ret_value)) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800612 // This is what CPython does
613 //PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_SILENCED));
614 // But what we need to do is - pop exception from value stack...
615 sp -= 3;
616 // ... pop "with" exception handler, and signal END_FINALLY
617 // to just execute finally handler normally (by pushing None
618 // on value stack)
619 assert(exc_sp >= exc_stack);
AZ Huangb1f692e2014-04-14 23:22:44 +0800620 POP_EXC_BLOCK();
621 PUSH(mp_const_none);
622 }
623 } else {
624 assert(0);
625 }
626 DISPATCH();
627 }
Damienc226dca2013-10-16 16:12:52 +0100628
Damien Georgecd97a432014-12-02 19:25:10 +0000629 ENTRY(MP_BC_UNWIND_JUMP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200630 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800631 DECODE_SLABEL;
Damien Georgecd97a432014-12-02 19:25:10 +0000632 PUSH((void*)(ip + slab)); // push destination ip for jump
Damien George40f3c022014-07-03 13:25:24 +0100633 PUSH((void*)(mp_uint_t)(*ip)); // push number of exception handlers to unwind (0x80 bit set if we also need to pop stack)
Damien Georgecd97a432014-12-02 19:25:10 +0000634unwind_jump:;
635 mp_uint_t unum = (mp_uint_t)POP(); // get number of exception handlers to unwind
Damien George25c84642014-05-30 15:20:41 +0100636 while ((unum & 0x7f) > 0) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800637 unum -= 1;
638 assert(exc_sp >= exc_stack);
Damien George74eb44c2014-12-22 12:49:57 +0000639 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800640 // We're going to run "finally" code as a coroutine
641 // (not calling it recursively). Set up a sentinel
642 // on a stack so it can return back to us when it is
643 // done (when END_FINALLY reached).
644 PUSH((void*)unum); // push number of exception handlers left to unwind
645 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
646 ip = exc_sp->handler; // get exception handler byte code address
647 exc_sp--; // pop exception handler
648 goto dispatch_loop; // run the exception handler
649 }
650 exc_sp--;
651 }
652 ip = (const byte*)POP(); // pop destination ip for jump
Damien George25c84642014-05-30 15:20:41 +0100653 if (unum != 0) {
654 sp--;
655 }
Damien George124df6f2014-10-25 18:19:55 +0100656 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000657 }
Damience89a212013-10-15 22:25:17 +0100658
AZ Huangb1f692e2014-04-14 23:22:44 +0800659 // matched against: POP_BLOCK or POP_EXCEPT (anything else?)
660 ENTRY(MP_BC_SETUP_EXCEPT):
Damien Georgecd97a432014-12-02 19:25:10 +0000661 ENTRY(MP_BC_SETUP_FINALLY): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200662 MARK_EXC_IP_SELECTIVE();
Damien Georgef89d6592014-12-29 00:29:59 +0000663 #if SELECTIVE_EXC_IP
664 PUSH_EXC_BLOCK((code_state->ip[-1] == MP_BC_SETUP_FINALLY) ? 1 : 0);
665 #else
666 PUSH_EXC_BLOCK((code_state->ip[0] == MP_BC_SETUP_FINALLY) ? 1 : 0);
667 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800668 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000669 }
Damience89a212013-10-15 22:25:17 +0100670
AZ Huangb1f692e2014-04-14 23:22:44 +0800671 ENTRY(MP_BC_END_FINALLY):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200672 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800673 // not fully implemented
674 // if TOS is an exception, reraises the exception (3 values on TOS)
675 // if TOS is None, just pops it and continues
676 // if TOS is an integer, does something else
677 // else error
678 if (mp_obj_is_exception_type(TOP())) {
Damien George66ae8c92014-04-17 16:50:23 +0100679 RAISE(sp[-1]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800680 }
681 if (TOP() == mp_const_none) {
Damien George20006db2014-01-18 14:10:48 +0000682 sp--;
AZ Huangb1f692e2014-04-14 23:22:44 +0800683 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
684 // We finished "finally" coroutine and now dispatch back
685 // to our caller, based on TOS value
686 mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());
687 switch (reason) {
688 case UNWIND_RETURN:
689 goto unwind_return;
690 case UNWIND_JUMP:
691 goto unwind_jump;
692 }
693 assert(0);
694 } else {
695 assert(0);
696 }
697 DISPATCH();
698
699 ENTRY(MP_BC_GET_ITER):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200700 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800701 SET_TOP(mp_getiter(TOP()));
702 DISPATCH();
703
Damien Georged8675542014-05-25 22:58:04 +0100704 ENTRY(MP_BC_FOR_ITER): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200705 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800706 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgec60a2612014-06-01 12:32:28 +0100707 code_state->sp = sp;
Paul Sokolovskyc48d6f72014-05-11 20:32:39 +0300708 assert(TOP());
Damien Georged8675542014-05-25 22:58:04 +0100709 mp_obj_t value = mp_iternext_allow_raise(TOP());
710 if (value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800711 --sp; // pop the exhausted iterator
Damien Georgecd97a432014-12-02 19:25:10 +0000712 ip += ulab; // jump to after for-block
AZ Huangb1f692e2014-04-14 23:22:44 +0800713 } else {
Damien Georged8675542014-05-25 22:58:04 +0100714 PUSH(value); // push the next iteration value
AZ Huangb1f692e2014-04-14 23:22:44 +0800715 }
716 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100717 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800718
719 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
720 ENTRY(MP_BC_POP_BLOCK):
721 // we are exiting an exception handler, so pop the last one of the exception-stack
722 assert(exc_sp >= exc_stack);
723 POP_EXC_BLOCK();
724 DISPATCH();
725
726 // matched against: SETUP_EXCEPT
727 ENTRY(MP_BC_POP_EXCEPT):
728 // TODO need to work out how blocks work etc
729 // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
730 assert(exc_sp >= exc_stack);
731 assert(currently_in_except_block);
732 //sp = (mp_obj_t*)(*exc_sp--);
733 //exc_sp--; // discard ip
734 POP_EXC_BLOCK();
735 //sp -= 3; // pop 3 exception values
736 DISPATCH();
737
738 ENTRY(MP_BC_NOT):
739 if (TOP() == mp_const_true) {
740 SET_TOP(mp_const_false);
741 } else {
742 SET_TOP(mp_const_true);
743 }
744 DISPATCH();
745
Damien Georgecd97a432014-12-02 19:25:10 +0000746 ENTRY(MP_BC_BUILD_TUPLE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200747 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800748 DECODE_UINT;
749 sp -= unum - 1;
750 SET_TOP(mp_obj_new_tuple(unum, sp));
751 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000752 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800753
Damien Georgecd97a432014-12-02 19:25:10 +0000754 ENTRY(MP_BC_BUILD_LIST): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200755 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800756 DECODE_UINT;
757 sp -= unum - 1;
758 SET_TOP(mp_obj_new_list(unum, sp));
759 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000760 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800761
Damien Georgecd97a432014-12-02 19:25:10 +0000762 ENTRY(MP_BC_LIST_APPEND): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200763 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800764 DECODE_UINT;
765 // I think it's guaranteed by the compiler that sp[unum] is a list
766 mp_obj_list_append(sp[-unum], sp[0]);
767 sp--;
768 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000769 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800770
Damien Georgecd97a432014-12-02 19:25:10 +0000771 ENTRY(MP_BC_BUILD_MAP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200772 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800773 DECODE_UINT;
774 PUSH(mp_obj_new_dict(unum));
775 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000776 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800777
778 ENTRY(MP_BC_STORE_MAP):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200779 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800780 sp -= 2;
781 mp_obj_dict_store(sp[0], sp[2], sp[1]);
782 DISPATCH();
783
Damien Georgecd97a432014-12-02 19:25:10 +0000784 ENTRY(MP_BC_MAP_ADD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200785 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800786 DECODE_UINT;
787 // I think it's guaranteed by the compiler that sp[-unum - 1] is a map
788 mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]);
789 sp -= 2;
790 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000791 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800792
Damien George3ebd4d02014-06-01 13:46:47 +0100793#if MICROPY_PY_BUILTINS_SET
Damien Georgecd97a432014-12-02 19:25:10 +0000794 ENTRY(MP_BC_BUILD_SET): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200795 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800796 DECODE_UINT;
797 sp -= unum - 1;
798 SET_TOP(mp_obj_new_set(unum, sp));
799 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000800 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800801
Damien Georgecd97a432014-12-02 19:25:10 +0000802 ENTRY(MP_BC_SET_ADD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200803 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800804 DECODE_UINT;
805 // I think it's guaranteed by the compiler that sp[-unum] is a set
806 mp_obj_set_store(sp[-unum], sp[0]);
807 sp--;
808 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000809 }
Damien George3ebd4d02014-06-01 13:46:47 +0100810#endif
Damienc12aa462013-10-16 20:57:49 +0100811
Damien Georgefb510b32014-06-01 13:32:54 +0100812#if MICROPY_PY_BUILTINS_SLICE
Damien Georgecd97a432014-12-02 19:25:10 +0000813 ENTRY(MP_BC_BUILD_SLICE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200814 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800815 DECODE_UINT;
816 if (unum == 2) {
Damien Georged8675542014-05-25 22:58:04 +0100817 mp_obj_t stop = POP();
818 mp_obj_t start = TOP();
819 SET_TOP(mp_obj_new_slice(start, stop, mp_const_none));
AZ Huangb1f692e2014-04-14 23:22:44 +0800820 } else {
Damien Georged8675542014-05-25 22:58:04 +0100821 mp_obj_t step = POP();
822 mp_obj_t stop = POP();
823 mp_obj_t start = TOP();
824 SET_TOP(mp_obj_new_slice(start, stop, step));
AZ Huangb1f692e2014-04-14 23:22:44 +0800825 }
826 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000827 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800828#endif
829
Damien Georgecd97a432014-12-02 19:25:10 +0000830 ENTRY(MP_BC_UNPACK_SEQUENCE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200831 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800832 DECODE_UINT;
833 mp_unpack_sequence(sp[0], unum, sp);
834 sp += unum - 1;
835 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000836 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800837
Damien Georgecd97a432014-12-02 19:25:10 +0000838 ENTRY(MP_BC_UNPACK_EX): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200839 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800840 DECODE_UINT;
841 mp_unpack_ex(sp[0], unum, sp);
842 sp += (unum & 0xff) + ((unum >> 8) & 0xff);
843 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000844 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800845
Damien Georgecd97a432014-12-02 19:25:10 +0000846 ENTRY(MP_BC_MAKE_FUNCTION): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800847 DECODE_PTR;
Damien Georgecd97a432014-12-02 19:25:10 +0000848 PUSH(mp_make_function_from_raw_code(ptr, MP_OBJ_NULL, MP_OBJ_NULL));
AZ Huangb1f692e2014-04-14 23:22:44 +0800849 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000850 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800851
Damien Georged8675542014-05-25 22:58:04 +0100852 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800853 DECODE_PTR;
854 // Stack layout: def_tuple def_dict <- TOS
Damien Georged8675542014-05-25 22:58:04 +0100855 mp_obj_t def_dict = POP();
Damien Georgecd97a432014-12-02 19:25:10 +0000856 SET_TOP(mp_make_function_from_raw_code(ptr, TOP(), def_dict));
AZ Huangb1f692e2014-04-14 23:22:44 +0800857 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100858 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800859
Damien George3558f622014-04-20 17:50:40 +0100860 ENTRY(MP_BC_MAKE_CLOSURE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800861 DECODE_PTR;
Damien George40f3c022014-07-03 13:25:24 +0100862 mp_uint_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100863 // Stack layout: closed_overs <- TOS
864 sp -= n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000865 SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800866 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100867 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800868
Damien George3558f622014-04-20 17:50:40 +0100869 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800870 DECODE_PTR;
Damien George40f3c022014-07-03 13:25:24 +0100871 mp_uint_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100872 // Stack layout: def_tuple def_dict closed_overs <- TOS
873 sp -= 2 + n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000874 SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800875 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100876 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800877
Damien Georgecd97a432014-12-02 19:25:10 +0000878 ENTRY(MP_BC_CALL_FUNCTION): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200879 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800880 DECODE_UINT;
881 // unum & 0xff == n_positional
882 // (unum >> 8) & 0xff == n_keyword
883 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
884 SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
885 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000886 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800887
Damien Georgecd97a432014-12-02 19:25:10 +0000888 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200889 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800890 DECODE_UINT;
891 // unum & 0xff == n_positional
892 // (unum >> 8) & 0xff == n_keyword
893 // We have folowing stack layout here:
894 // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
895 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
896 SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
897 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000898 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800899
Damien Georgecd97a432014-12-02 19:25:10 +0000900 ENTRY(MP_BC_CALL_METHOD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200901 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800902 DECODE_UINT;
903 // unum & 0xff == n_positional
904 // (unum >> 8) & 0xff == n_keyword
905 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
906 SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
907 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000908 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800909
Damien Georgecd97a432014-12-02 19:25:10 +0000910 ENTRY(MP_BC_CALL_METHOD_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200911 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800912 DECODE_UINT;
913 // unum & 0xff == n_positional
914 // (unum >> 8) & 0xff == n_keyword
915 // We have folowing stack layout here:
916 // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
917 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
918 SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
919 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000920 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800921
922 ENTRY(MP_BC_RETURN_VALUE):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200923 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800924unwind_return:
925 while (exc_sp >= exc_stack) {
Damien George74eb44c2014-12-22 12:49:57 +0000926 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800927 // We're going to run "finally" code as a coroutine
928 // (not calling it recursively). Set up a sentinel
929 // on a stack so it can return back to us when it is
930 // done (when END_FINALLY reached).
931 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
932 ip = exc_sp->handler;
933 // We don't need to do anything with sp, finally is just
934 // syntactic sugar for sequential execution??
935 // sp =
936 exc_sp--;
937 goto dispatch_loop;
938 }
939 exc_sp--;
940 }
941 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300942 code_state->sp = sp;
AZ Huangb1f692e2014-04-14 23:22:44 +0800943 assert(exc_sp == exc_stack - 1);
944 return MP_VM_RETURN_NORMAL;
945
Damien Georged8675542014-05-25 22:58:04 +0100946 ENTRY(MP_BC_RAISE_VARARGS): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200947 MARK_EXC_IP_SELECTIVE();
Damien Georgecd97a432014-12-02 19:25:10 +0000948 mp_uint_t unum = *ip++;
Damien Georged8675542014-05-25 22:58:04 +0100949 mp_obj_t obj;
AZ Huangb1f692e2014-04-14 23:22:44 +0800950 assert(unum <= 1);
951 if (unum == 0) {
952 // search for the inner-most previous exception, to reraise it
Damien Georged8675542014-05-25 22:58:04 +0100953 obj = MP_OBJ_NULL;
AZ Huangb1f692e2014-04-14 23:22:44 +0800954 for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
955 if (e->prev_exc != MP_OBJ_NULL) {
Damien Georged8675542014-05-25 22:58:04 +0100956 obj = e->prev_exc;
AZ Huangb1f692e2014-04-14 23:22:44 +0800957 break;
958 }
959 }
Damien Georged8675542014-05-25 22:58:04 +0100960 if (obj == MP_OBJ_NULL) {
961 obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
962 RAISE(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +0800963 }
964 } else {
Damien Georged8675542014-05-25 22:58:04 +0100965 obj = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800966 }
Damien Georged8675542014-05-25 22:58:04 +0100967 obj = mp_make_raise_obj(obj);
968 RAISE(obj);
969 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800970
971 ENTRY(MP_BC_YIELD_VALUE):
972yield:
973 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300974 code_state->ip = ip;
975 code_state->sp = sp;
976 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +0800977 return MP_VM_RETURN_YIELD;
978
979 ENTRY(MP_BC_YIELD_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200980 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800981//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
982#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
Damien George66ae8c92014-04-17 16:50:23 +0100983#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { RAISE(t); }
AZ Huangb1f692e2014-04-14 23:22:44 +0800984 mp_vm_return_kind_t ret_kind;
Damien Georged8675542014-05-25 22:58:04 +0100985 mp_obj_t send_value = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800986 mp_obj_t t_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100987 mp_obj_t ret_value;
AZ Huangb1f692e2014-04-14 23:22:44 +0800988 if (inject_exc != MP_OBJ_NULL) {
989 t_exc = inject_exc;
990 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100991 ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800992 } else {
Damien Georged8675542014-05-25 22:58:04 +0100993 ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800994 }
995
996 if (ret_kind == MP_VM_RETURN_YIELD) {
997 ip--;
Damien Georged8675542014-05-25 22:58:04 +0100998 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800999 goto yield;
1000 }
1001 if (ret_kind == MP_VM_RETURN_NORMAL) {
1002 // Pop exhausted gen
1003 sp--;
Damien Georged8675542014-05-25 22:58:04 +01001004 if (ret_value == MP_OBJ_NULL) {
AZ Huangb1f692e2014-04-14 23:22:44 +08001005 // Optimize StopIteration
1006 // TODO: get StopIteration's value
1007 PUSH(mp_const_none);
1008 } else {
Damien Georged8675542014-05-25 22:58:04 +01001009 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001010 }
1011
1012 // If we injected GeneratorExit downstream, then even
1013 // if it was swallowed, we re-raise GeneratorExit
1014 GENERATOR_EXIT_IF_NEEDED(t_exc);
1015 DISPATCH();
1016 }
1017 if (ret_kind == MP_VM_RETURN_EXCEPTION) {
1018 // Pop exhausted gen
1019 sp--;
Damien Georged8675542014-05-25 22:58:04 +01001020 if (EXC_MATCH(ret_value, &mp_type_StopIteration)) {
1021 PUSH(mp_obj_exception_get_value(ret_value));
AZ Huangb1f692e2014-04-14 23:22:44 +08001022 // If we injected GeneratorExit downstream, then even
1023 // if it was swallowed, we re-raise GeneratorExit
1024 GENERATOR_EXIT_IF_NEEDED(t_exc);
1025 DISPATCH();
1026 } else {
Damien Georged8675542014-05-25 22:58:04 +01001027 RAISE(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001028 }
1029 }
Damien429d7192013-10-04 19:53:11 +01001030 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001031
Damien Georged8675542014-05-25 22:58:04 +01001032 ENTRY(MP_BC_IMPORT_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001033 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001034 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001035 mp_obj_t obj = POP();
1036 SET_TOP(mp_import_name(qst, obj, TOP()));
AZ Huangb1f692e2014-04-14 23:22:44 +08001037 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001038 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001039
Damien Georged8675542014-05-25 22:58:04 +01001040 ENTRY(MP_BC_IMPORT_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001041 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001042 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001043 mp_obj_t obj = mp_import_from(TOP(), qst);
1044 PUSH(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001045 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001046 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001047
1048 ENTRY(MP_BC_IMPORT_STAR):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001049 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001050 mp_import_all(POP());
1051 DISPATCH();
1052
Damien George8456cc02014-10-25 16:43:46 +01001053#if MICROPY_OPT_COMPUTED_GOTO
1054 ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):
1055 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1056 DISPATCH();
1057
1058 ENTRY(MP_BC_LOAD_FAST_MULTI):
1059 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1060 goto load_check;
1061
1062 ENTRY(MP_BC_STORE_FAST_MULTI):
1063 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1064 DISPATCH();
1065
1066 ENTRY(MP_BC_UNARY_OP_MULTI):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001067 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001068 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1069 DISPATCH();
1070
1071 ENTRY(MP_BC_BINARY_OP_MULTI): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001072 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001073 mp_obj_t rhs = POP();
1074 mp_obj_t lhs = TOP();
1075 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1076 DISPATCH();
1077 }
1078
1079 ENTRY_DEFAULT:
Paul Sokolovsky74957502014-12-28 07:17:43 +02001080 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001081#else
1082 ENTRY_DEFAULT:
1083 if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
1084 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1085 DISPATCH();
1086 } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
1087 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1088 goto load_check;
1089 } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
1090 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1091 DISPATCH();
1092 } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 5) {
1093 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1094 DISPATCH();
1095 } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 35) {
1096 mp_obj_t rhs = POP();
1097 mp_obj_t lhs = TOP();
1098 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1099 DISPATCH();
1100 } else
1101#endif
1102 {
Damien Georged8675542014-05-25 22:58:04 +01001103 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
AZ Huangb1f692e2014-04-14 23:22:44 +08001104 nlr_pop();
Damien Georged8675542014-05-25 22:58:04 +01001105 fastn[0] = obj;
AZ Huangb1f692e2014-04-14 23:22:44 +08001106 return MP_VM_RETURN_EXCEPTION;
Damien Georged8675542014-05-25 22:58:04 +01001107 }
Damien George66ae8c92014-04-17 16:50:23 +01001108
Damien George58ebde42014-05-21 20:32:59 +01001109#if !MICROPY_OPT_COMPUTED_GOTO
AZ Huang9309d992014-04-15 15:57:01 +08001110 } // switch
AZ Huangb1f692e2014-04-14 23:22:44 +08001111#endif
Damien George124df6f2014-10-25 18:19:55 +01001112
1113pending_exception_check:
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001114 if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001115 MARK_EXC_IP_SELECTIVE();
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001116 mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
1117 MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
Damien George124df6f2014-10-25 18:19:55 +01001118 RAISE(obj);
1119 }
Damien George124df6f2014-10-25 18:19:55 +01001120
Damien George66ae8c92014-04-17 16:50:23 +01001121 } // for loop
Damien429d7192013-10-04 19:53:11 +01001122
Damience89a212013-10-15 22:25:17 +01001123 } else {
Damien George66ae8c92014-04-17 16:50:23 +01001124exception_handler:
Damience89a212013-10-15 22:25:17 +01001125 // exception occurred
Damien429d7192013-10-04 19:53:11 +01001126
Damien Georgef89d6592014-12-29 00:29:59 +00001127 #if SELECTIVE_EXC_IP
1128 // with selective ip, we store the ip 1 byte past the opcode, so move ptr back
1129 code_state->ip -= 1;
1130 #endif
1131
Damien George9e6e9352014-03-26 18:37:06 +00001132 // check if it's a StopIteration within a for block
Damien Georgec60a2612014-06-01 12:32:28 +01001133 if (*code_state->ip == MP_BC_FOR_ITER && mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) {
1134 const byte *ip = code_state->ip + 1;
Damien George9e6e9352014-03-26 18:37:06 +00001135 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgecd97a432014-12-02 19:25:10 +00001136 code_state->ip = ip + ulab; // jump to after for-block
Damien Georgec60a2612014-06-01 12:32:28 +01001137 code_state->sp -= 1; // pop the exhausted iterator
Damien George9e6e9352014-03-26 18:37:06 +00001138 goto outer_dispatch_loop; // continue with dispatch loop
1139 }
1140
Damien George08335002014-01-18 23:24:36 +00001141 // set file and line number that the exception occurred at
Paul Sokolovsky382e8ee2014-01-30 13:49:18 +02001142 // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
1143 // But consider how to handle nested exceptions.
Damien George6902eed2014-04-04 10:52:59 +00001144 // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
1145 if (mp_obj_is_exception_instance(nlr.ret_val) && nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
Damien Georgeb534e1b2014-09-04 14:44:01 +01001146 const byte *ip = code_state->code_info;
1147 mp_uint_t code_info_size = mp_decode_uint(&ip);
1148 qstr block_name = mp_decode_uint(&ip);
1149 qstr source_file = mp_decode_uint(&ip);
1150 mp_uint_t bc = code_state->ip - code_state->code_info - code_info_size;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001151 mp_uint_t source_line = 1;
1152 mp_uint_t c;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001153 while ((c = *ip)) {
Damien Georgeb427d6a2014-08-26 23:35:57 +01001154 mp_uint_t b, l;
1155 if ((c & 0x80) == 0) {
1156 // 0b0LLBBBBB encoding
1157 b = c & 0x1f;
1158 l = c >> 5;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001159 ip += 1;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001160 } else {
1161 // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
1162 b = c & 0xf;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001163 l = ((c << 4) & 0x700) | ip[1];
1164 ip += 2;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001165 }
1166 if (bc >= b) {
1167 bc -= b;
1168 source_line += l;
1169 } else {
1170 // found source line corresponding to bytecode offset
1171 break;
Paul Sokolovsky411732e2014-06-02 18:24:34 +03001172 }
Damien George08335002014-01-18 23:24:36 +00001173 }
Damien George136b1492014-01-19 12:38:49 +00001174 mp_obj_exception_add_traceback(nlr.ret_val, source_file, source_line, block_name);
Damien George08335002014-01-18 23:24:36 +00001175 }
1176
Damien8f9e2ee2013-12-29 16:54:59 +00001177 while (currently_in_except_block) {
1178 // nested exception
1179
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001180 assert(exc_sp >= exc_stack);
Damien8f9e2ee2013-12-29 16:54:59 +00001181
1182 // TODO make a proper message for nested exception
1183 // at the moment we are just raising the very last exception (the one that caused the nested exception)
1184
1185 // move up to previous exception handler
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +02001186 POP_EXC_BLOCK();
Damien8f9e2ee2013-12-29 16:54:59 +00001187 }
1188
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001189 if (exc_sp >= exc_stack) {
Damien8f9e2ee2013-12-29 16:54:59 +00001190 // set flag to indicate that we are now handling an exception
1191 currently_in_except_block = 1;
1192
Damience89a212013-10-15 22:25:17 +01001193 // catch exception and pass to byte code
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001194 code_state->ip = exc_sp->handler;
Damien George66ae8c92014-04-17 16:50:23 +01001195 mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
Damien Georged7592a12014-03-30 00:54:48 +00001196 // save this exception in the stack so it can be used in a reraise, if needed
1197 exc_sp->prev_exc = nlr.ret_val;
Damienc9f91972013-10-15 23:46:01 +01001198 // push(traceback, exc-val, exc-type)
Damiend99b0522013-12-21 18:17:45 +00001199 PUSH(mp_const_none);
Damienc9f91972013-10-15 23:46:01 +01001200 PUSH(nlr.ret_val);
Paul Sokolovsky682f9e62014-03-29 02:52:17 +02001201 PUSH(mp_obj_get_type(nlr.ret_val));
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001202 code_state->sp = sp;
Damien8f9e2ee2013-12-29 16:54:59 +00001203
Damience89a212013-10-15 22:25:17 +01001204 } else {
Damien Georgec8f78bc2014-02-15 22:55:00 +00001205 // propagate exception to higher level
1206 // TODO what to do about ip and sp? they don't really make sense at this point
1207 fastn[0] = nlr.ret_val; // must put exception here because sp is invalid
1208 return MP_VM_RETURN_EXCEPTION;
Damience89a212013-10-15 22:25:17 +01001209 }
Damien429d7192013-10-04 19:53:11 +01001210 }
1211 }
1212}