blob: 291e707c1f7ff634067e40421e7672d83065f070 [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
Paul Sokolovsky20397572015-03-28 01:14:44 +0200132#if MICROPY_STACKLESS
133run_code_state: ;
134#endif
Damien Georgeaabd83e2014-06-07 14:16:08 +0100135 // Pointers which are constant for particular invocation of mp_execute_bytecode()
Paul Sokolovsky20397572015-03-28 01:14:44 +0200136 mp_obj_t */*const*/ fastn = &code_state->state[code_state->n_state - 1];
137 mp_exc_stack_t */*const*/ exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300138
Damien George66ae8c92014-04-17 16:50:23 +0100139 // variables that are visible to the exception handler (declared volatile)
Damien George74eb44c2014-12-22 12:49:57 +0000140 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 +0300141 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 +0100142
Damience89a212013-10-15 22:25:17 +0100143 // outer exception handling loop
Damien429d7192013-10-04 19:53:11 +0100144 for (;;) {
Damien George66ae8c92014-04-17 16:50:23 +0100145 nlr_buf_t nlr;
Damien George9e6e9352014-03-26 18:37:06 +0000146outer_dispatch_loop:
Damience89a212013-10-15 22:25:17 +0100147 if (nlr_push(&nlr) == 0) {
Damien George66ae8c92014-04-17 16:50:23 +0100148 // local variables that are not visible to the exception handler
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300149 const byte *ip = code_state->ip;
150 mp_obj_t *sp = code_state->sp;
Damien Georged8675542014-05-25 22:58:04 +0100151 mp_obj_t obj_shared;
Damien George66ae8c92014-04-17 16:50:23 +0100152
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200153 // If we have exception to inject, now that we finish setting up
154 // execution context, raise it. This works as if RAISE_VARARGS
155 // bytecode was executed.
Paul Sokolovskycf21a4e2014-03-26 17:36:12 +0200156 // Injecting exc into yield from generator is a special case,
157 // handled by MP_BC_YIELD_FROM itself
158 if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
Damien Georged8675542014-05-25 22:58:04 +0100159 mp_obj_t exc = inject_exc;
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200160 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100161 exc = mp_make_raise_obj(exc);
162 RAISE(exc);
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200163 }
Damien George66ae8c92014-04-17 16:50:23 +0100164
Damience89a212013-10-15 22:25:17 +0100165 // loop to execute byte code
166 for (;;) {
Paul Sokolovsky6472dea2014-02-01 00:55:05 +0200167dispatch_loop:
Damien George58ebde42014-05-21 20:32:59 +0100168#if MICROPY_OPT_COMPUTED_GOTO
AZ Huangb1f692e2014-04-14 23:22:44 +0800169 DISPATCH();
170#else
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +0300171 TRACE(ip);
Paul Sokolovsky74957502014-12-28 07:17:43 +0200172 MARK_EXC_IP_GLOBAL();
Damien Georgedb128912014-04-27 18:19:06 +0100173 switch (*ip++) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800174#endif
Damien429d7192013-10-04 19:53:11 +0100175
AZ Huangb1f692e2014-04-14 23:22:44 +0800176 ENTRY(MP_BC_LOAD_CONST_FALSE):
177 PUSH(mp_const_false);
178 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100179
AZ Huangb1f692e2014-04-14 23:22:44 +0800180 ENTRY(MP_BC_LOAD_CONST_NONE):
181 PUSH(mp_const_none);
182 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100183
AZ Huangb1f692e2014-04-14 23:22:44 +0800184 ENTRY(MP_BC_LOAD_CONST_TRUE):
185 PUSH(mp_const_true);
186 DISPATCH();
Damien Georgee9906ac2014-01-04 18:44:46 +0000187
AZ Huangb1f692e2014-04-14 23:22:44 +0800188 ENTRY(MP_BC_LOAD_CONST_ELLIPSIS):
189 PUSH((mp_obj_t)&mp_const_ellipsis_obj);
190 DISPATCH();
191
192 ENTRY(MP_BC_LOAD_CONST_SMALL_INT): {
Damien George40f3c022014-07-03 13:25:24 +0100193 mp_int_t num = 0;
AZ Huangb1f692e2014-04-14 23:22:44 +0800194 if ((ip[0] & 0x40) != 0) {
195 // Number is negative
196 num--;
Paul Sokolovsky047cd402014-02-19 15:47:59 +0200197 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800198 do {
199 num = (num << 7) | (*ip & 0x7f);
200 } while ((*ip++ & 0x80) != 0);
201 PUSH(MP_OBJ_NEW_SMALL_INT(num));
202 DISPATCH();
203 }
Damience89a212013-10-15 22:25:17 +0100204
Damien Georged8675542014-05-25 22:58:04 +0100205 ENTRY(MP_BC_LOAD_CONST_BYTES): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800206 DECODE_QSTR;
207 PUSH(mp_load_const_bytes(qst));
208 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100209 }
Paul Sokolovskybdf822b2014-01-02 18:46:27 +0200210
Damien Georged8675542014-05-25 22:58:04 +0100211 ENTRY(MP_BC_LOAD_CONST_STRING): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800212 DECODE_QSTR;
213 PUSH(mp_load_const_str(qst));
214 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100215 }
Damience89a212013-10-15 22:25:17 +0100216
Damien Georgedab13852015-01-13 15:55:54 +0000217 ENTRY(MP_BC_LOAD_CONST_OBJ): {
218 DECODE_PTR;
219 PUSH(ptr);
220 DISPATCH();
221 }
222
AZ Huangb1f692e2014-04-14 23:22:44 +0800223 ENTRY(MP_BC_LOAD_NULL):
224 PUSH(MP_OBJ_NULL);
225 DISPATCH();
Damien George523b5752014-03-31 11:59:23 +0100226
Damien Georgecd97a432014-12-02 19:25:10 +0000227 ENTRY(MP_BC_LOAD_FAST_N): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800228 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100229 obj_shared = fastn[-unum];
AZ Huangb1f692e2014-04-14 23:22:44 +0800230 load_check:
Damien Georged8675542014-05-25 22:58:04 +0100231 if (obj_shared == MP_OBJ_NULL) {
232 local_name_error: {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200233 MARK_EXC_IP_SELECTIVE();
Damien Georged8675542014-05-25 22:58:04 +0100234 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment");
235 RAISE(obj);
236 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800237 }
Damien Georged8675542014-05-25 22:58:04 +0100238 PUSH(obj_shared);
AZ Huangb1f692e2014-04-14 23:22:44 +0800239 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000240 }
Damien George2bf7c092014-04-09 15:26:46 +0100241
Damien Georgecd97a432014-12-02 19:25:10 +0000242 ENTRY(MP_BC_LOAD_DEREF): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800243 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100244 obj_shared = mp_obj_cell_get(fastn[-unum]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800245 goto load_check;
Damien Georgecd97a432014-12-02 19:25:10 +0000246 }
Damien9ecbcff2013-12-11 00:41:43 +0000247
Damien George7ee91cf2015-01-06 12:51:39 +0000248 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100249 ENTRY(MP_BC_LOAD_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200250 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800251 DECODE_QSTR;
252 PUSH(mp_load_name(qst));
253 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100254 }
Damien George7ee91cf2015-01-06 12:51:39 +0000255 #else
256 ENTRY(MP_BC_LOAD_NAME): {
257 MARK_EXC_IP_SELECTIVE();
258 DECODE_QSTR;
259 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
260 mp_uint_t x = *ip;
261 if (x < MP_STATE_CTX(dict_locals)->map.alloc && MP_STATE_CTX(dict_locals)->map.table[x].key == key) {
262 PUSH(MP_STATE_CTX(dict_locals)->map.table[x].value);
263 } else {
264 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_locals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
265 if (elem != NULL) {
266 *(byte*)ip = (elem - &MP_STATE_CTX(dict_locals)->map.table[0]) & 0xff;
267 PUSH(elem->value);
268 } else {
269 PUSH(mp_load_name(MP_OBJ_QSTR_VALUE(key)));
270 }
271 }
272 ip++;
273 DISPATCH();
274 }
275 #endif
Damience89a212013-10-15 22:25:17 +0100276
Damien George7ee91cf2015-01-06 12:51:39 +0000277 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100278 ENTRY(MP_BC_LOAD_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200279 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800280 DECODE_QSTR;
281 PUSH(mp_load_global(qst));
282 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100283 }
Damien George7ee91cf2015-01-06 12:51:39 +0000284 #else
285 ENTRY(MP_BC_LOAD_GLOBAL): {
286 MARK_EXC_IP_SELECTIVE();
287 DECODE_QSTR;
288 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
289 mp_uint_t x = *ip;
290 if (x < MP_STATE_CTX(dict_globals)->map.alloc && MP_STATE_CTX(dict_globals)->map.table[x].key == key) {
291 PUSH(MP_STATE_CTX(dict_globals)->map.table[x].value);
292 } else {
293 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_globals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
294 if (elem != NULL) {
295 *(byte*)ip = (elem - &MP_STATE_CTX(dict_globals)->map.table[0]) & 0xff;
296 PUSH(elem->value);
297 } else {
298 PUSH(mp_load_global(MP_OBJ_QSTR_VALUE(key)));
299 }
300 }
301 ip++;
302 DISPATCH();
303 }
304 #endif
Damience89a212013-10-15 22:25:17 +0100305
Damien George7ee91cf2015-01-06 12:51:39 +0000306 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100307 ENTRY(MP_BC_LOAD_ATTR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200308 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800309 DECODE_QSTR;
310 SET_TOP(mp_load_attr(TOP(), qst));
311 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100312 }
Damien George7ee91cf2015-01-06 12:51:39 +0000313 #else
314 ENTRY(MP_BC_LOAD_ATTR): {
315 MARK_EXC_IP_SELECTIVE();
316 DECODE_QSTR;
317 mp_obj_t top = TOP();
318 if (mp_obj_get_type(top)->load_attr == mp_obj_instance_load_attr) {
319 mp_obj_instance_t *self = top;
320 mp_uint_t x = *ip;
321 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
322 mp_map_elem_t *elem;
323 if (x < self->members.alloc && self->members.table[x].key == key) {
324 elem = &self->members.table[x];
325 } else {
326 elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);
327 if (elem != NULL) {
328 *(byte*)ip = elem - &self->members.table[0];
329 } else {
330 goto load_attr_cache_fail;
331 }
332 }
333 SET_TOP(elem->value);
334 ip++;
335 DISPATCH();
336 }
337 load_attr_cache_fail:
338 SET_TOP(mp_load_attr(top, qst));
339 ip++;
340 DISPATCH();
341 }
342 #endif
Damience89a212013-10-15 22:25:17 +0100343
Damien Georged8675542014-05-25 22:58:04 +0100344 ENTRY(MP_BC_LOAD_METHOD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200345 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800346 DECODE_QSTR;
347 mp_load_method(*sp, qst, sp);
348 sp += 1;
349 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100350 }
Damience89a212013-10-15 22:25:17 +0100351
AZ Huangb1f692e2014-04-14 23:22:44 +0800352 ENTRY(MP_BC_LOAD_BUILD_CLASS):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200353 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800354 PUSH(mp_load_build_class());
355 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100356
Damien Georged8675542014-05-25 22:58:04 +0100357 ENTRY(MP_BC_LOAD_SUBSCR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200358 MARK_EXC_IP_SELECTIVE();
Damien Georged8675542014-05-25 22:58:04 +0100359 mp_obj_t index = POP();
360 SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL));
Damien George729f7b42014-04-17 22:10:53 +0100361 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100362 }
Damien George729f7b42014-04-17 22:10:53 +0100363
Damien Georgecd97a432014-12-02 19:25:10 +0000364 ENTRY(MP_BC_STORE_FAST_N): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800365 DECODE_UINT;
366 fastn[-unum] = POP();
367 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000368 }
Damience89a212013-10-15 22:25:17 +0100369
Damien Georgecd97a432014-12-02 19:25:10 +0000370 ENTRY(MP_BC_STORE_DEREF): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800371 DECODE_UINT;
372 mp_obj_cell_set(fastn[-unum], POP());
373 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000374 }
Damien9ecbcff2013-12-11 00:41:43 +0000375
Damien Georged8675542014-05-25 22:58:04 +0100376 ENTRY(MP_BC_STORE_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200377 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800378 DECODE_QSTR;
379 mp_store_name(qst, POP());
380 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100381 }
Damience89a212013-10-15 22:25:17 +0100382
Damien Georged8675542014-05-25 22:58:04 +0100383 ENTRY(MP_BC_STORE_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200384 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800385 DECODE_QSTR;
386 mp_store_global(qst, POP());
387 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100388 }
Damien6addc892013-11-04 23:04:50 +0000389
Damien George7ee91cf2015-01-06 12:51:39 +0000390 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100391 ENTRY(MP_BC_STORE_ATTR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200392 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800393 DECODE_QSTR;
394 mp_store_attr(sp[0], qst, sp[-1]);
395 sp -= 2;
396 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100397 }
Damien George7ee91cf2015-01-06 12:51:39 +0000398 #else
stijn28fa84b2015-02-14 18:43:54 +0100399 // This caching code works with MICROPY_PY_BUILTINS_PROPERTY and/or
400 // MICROPY_PY_DESCRIPTORS enabled because if the attr exists in
401 // self->members then it can't be a property or have descriptors. A
Damien George7ee91cf2015-01-06 12:51:39 +0000402 // consequence of this is that we can't use MP_MAP_LOOKUP_ADD_IF_NOT_FOUND
403 // in the fast-path below, because that store could override a property.
404 ENTRY(MP_BC_STORE_ATTR): {
405 MARK_EXC_IP_SELECTIVE();
406 DECODE_QSTR;
407 mp_obj_t top = TOP();
408 if (mp_obj_get_type(top)->store_attr == mp_obj_instance_store_attr && sp[-1] != MP_OBJ_NULL) {
409 mp_obj_instance_t *self = top;
410 mp_uint_t x = *ip;
411 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
412 mp_map_elem_t *elem;
413 if (x < self->members.alloc && self->members.table[x].key == key) {
414 elem = &self->members.table[x];
415 } else {
416 elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);
417 if (elem != NULL) {
418 *(byte*)ip = elem - &self->members.table[0];
419 } else {
420 goto store_attr_cache_fail;
421 }
422 }
423 elem->value = sp[-1];
424 sp -= 2;
425 ip++;
426 DISPATCH();
427 }
428 store_attr_cache_fail:
429 mp_store_attr(sp[0], qst, sp[-1]);
430 sp -= 2;
431 ip++;
432 DISPATCH();
433 }
434 #endif
Damience89a212013-10-15 22:25:17 +0100435
AZ Huangb1f692e2014-04-14 23:22:44 +0800436 ENTRY(MP_BC_STORE_SUBSCR):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200437 MARK_EXC_IP_SELECTIVE();
Damien George729f7b42014-04-17 22:10:53 +0100438 mp_obj_subscr(sp[-1], sp[0], sp[-2]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800439 sp -= 3;
440 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100441
Damien Georgecd97a432014-12-02 19:25:10 +0000442 ENTRY(MP_BC_DELETE_FAST): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200443 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800444 DECODE_UINT;
445 if (fastn[-unum] == MP_OBJ_NULL) {
446 goto local_name_error;
447 }
448 fastn[-unum] = MP_OBJ_NULL;
449 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000450 }
Damien George2bf7c092014-04-09 15:26:46 +0100451
Damien Georgecd97a432014-12-02 19:25:10 +0000452 ENTRY(MP_BC_DELETE_DEREF): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200453 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800454 DECODE_UINT;
455 if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
456 goto local_name_error;
457 }
458 mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);
459 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000460 }
Damien George2bf7c092014-04-09 15:26:46 +0100461
Damien Georged8675542014-05-25 22:58:04 +0100462 ENTRY(MP_BC_DELETE_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200463 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800464 DECODE_QSTR;
465 mp_delete_name(qst);
466 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100467 }
Paul Sokolovskyf9090342014-03-23 21:19:02 +0200468
Damien Georged8675542014-05-25 22:58:04 +0100469 ENTRY(MP_BC_DELETE_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200470 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800471 DECODE_QSTR;
472 mp_delete_global(qst);
473 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100474 }
Damien George1d24ea52014-04-08 21:11:49 +0100475
Damien Georged8675542014-05-25 22:58:04 +0100476 ENTRY(MP_BC_DUP_TOP): {
477 mp_obj_t top = TOP();
478 PUSH(top);
AZ Huangb1f692e2014-04-14 23:22:44 +0800479 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100480 }
Damience89a212013-10-15 22:25:17 +0100481
AZ Huangb1f692e2014-04-14 23:22:44 +0800482 ENTRY(MP_BC_DUP_TOP_TWO):
483 sp += 2;
484 sp[0] = sp[-2];
485 sp[-1] = sp[-3];
486 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100487
AZ Huangb1f692e2014-04-14 23:22:44 +0800488 ENTRY(MP_BC_POP_TOP):
489 sp -= 1;
490 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100491
Damien Georged8675542014-05-25 22:58:04 +0100492 ENTRY(MP_BC_ROT_TWO): {
493 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800494 sp[0] = sp[-1];
Damien Georged8675542014-05-25 22:58:04 +0100495 sp[-1] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800496 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100497 }
Damien4ebb32f2013-11-02 14:33:10 +0000498
Damien Georged8675542014-05-25 22:58:04 +0100499 ENTRY(MP_BC_ROT_THREE): {
500 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800501 sp[0] = sp[-1];
502 sp[-1] = sp[-2];
Damien Georged8675542014-05-25 22:58:04 +0100503 sp[-2] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800504 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100505 }
Damience89a212013-10-15 22:25:17 +0100506
Damien Georgecd97a432014-12-02 19:25:10 +0000507 ENTRY(MP_BC_JUMP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800508 DECODE_SLABEL;
Damien Georgecd97a432014-12-02 19:25:10 +0000509 ip += slab;
Damien George124df6f2014-10-25 18:19:55 +0100510 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000511 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800512
Damien Georgecd97a432014-12-02 19:25:10 +0000513 ENTRY(MP_BC_POP_JUMP_IF_TRUE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800514 DECODE_SLABEL;
515 if (mp_obj_is_true(POP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000516 ip += slab;
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200517 }
Damien George124df6f2014-10-25 18:19:55 +0100518 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000519 }
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200520
Damien Georgecd97a432014-12-02 19:25:10 +0000521 ENTRY(MP_BC_POP_JUMP_IF_FALSE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800522 DECODE_SLABEL;
523 if (!mp_obj_is_true(POP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000524 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800525 }
Damien George124df6f2014-10-25 18:19:55 +0100526 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000527 }
Damien George600ae732014-01-21 23:48:04 +0000528
Damien Georgecd97a432014-12-02 19:25:10 +0000529 ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800530 DECODE_SLABEL;
531 if (mp_obj_is_true(TOP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000532 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800533 } else {
534 sp--;
535 }
Damien George124df6f2014-10-25 18:19:55 +0100536 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000537 }
Damience89a212013-10-15 22:25:17 +0100538
Damien Georgecd97a432014-12-02 19:25:10 +0000539 ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800540 DECODE_SLABEL;
541 if (mp_obj_is_true(TOP())) {
542 sp--;
543 } else {
Damien Georgecd97a432014-12-02 19:25:10 +0000544 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800545 }
Damien George124df6f2014-10-25 18:19:55 +0100546 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000547 }
Damience89a212013-10-15 22:25:17 +0100548
Damien Georged8675542014-05-25 22:58:04 +0100549 ENTRY(MP_BC_SETUP_WITH): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200550 MARK_EXC_IP_SELECTIVE();
Damien Georged8675542014-05-25 22:58:04 +0100551 mp_obj_t obj = TOP();
552 SET_TOP(mp_load_attr(obj, MP_QSTR___exit__));
553 mp_load_method(obj, MP_QSTR___enter__, sp + 1);
554 mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 1);
Damien George74eb44c2014-12-22 12:49:57 +0000555 PUSH_EXC_BLOCK(1);
Damien Georged8675542014-05-25 22:58:04 +0100556 PUSH(ret);
AZ Huangb1f692e2014-04-14 23:22:44 +0800557 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100558 }
Damience89a212013-10-15 22:25:17 +0100559
AZ Huangb1f692e2014-04-14 23:22:44 +0800560 ENTRY(MP_BC_WITH_CLEANUP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200561 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800562 // Arriving here, there's "exception control block" on top of stack,
563 // and __exit__ bound method underneath it. Bytecode calls __exit__,
564 // and "deletes" it off stack, shifting "exception control block"
565 // to its place.
566 static const mp_obj_t no_exc[] = {mp_const_none, mp_const_none, mp_const_none};
567 if (TOP() == mp_const_none) {
568 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100569 mp_obj_t obj = TOP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800570 SET_TOP(mp_const_none);
Damien Georged8675542014-05-25 22:58:04 +0100571 mp_call_function_n_kw(obj, 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800572 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
Damien George5e1d9932015-03-25 22:20:37 +0000573 mp_int_t cause_val = MP_OBJ_SMALL_INT_VALUE(TOP());
574 if (cause_val == UNWIND_RETURN) {
575 mp_call_function_n_kw(sp[-2], 3, 0, no_exc);
576 } else {
577 assert(cause_val == UNWIND_JUMP);
578 mp_call_function_n_kw(sp[-3], 3, 0, no_exc);
579 // Pop __exit__ boundmethod at sp[-3]
580 sp[-3] = sp[-2];
AZ Huangb1f692e2014-04-14 23:22:44 +0800581 }
Damien George12d6d772015-02-26 17:54:50 +0000582 sp[-2] = sp[-1]; // copy retval down
583 sp[-1] = sp[0]; // copy cause down
584 sp--; // discard top value (was cause)
Damien George5e1d9932015-03-25 22:20:37 +0000585 } else {
586 assert(mp_obj_is_exception_type(TOP()));
Damien George596f41d2015-02-10 13:21:42 +0000587 // Need to pass (sp[0], sp[-1], sp[-2]) as arguments so must reverse the
588 // order of these on the value stack (don't want to create a temporary
589 // array because it increases stack footprint of the VM).
590 mp_obj_t obj = sp[-2];
591 sp[-2] = sp[0];
592 sp[0] = obj;
593 mp_obj_t ret_value = mp_call_function_n_kw(sp[-3], 3, 0, &sp[-2]);
Damien Georged8675542014-05-25 22:58:04 +0100594 if (mp_obj_is_true(ret_value)) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800595 // This is what CPython does
596 //PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_SILENCED));
597 // But what we need to do is - pop exception from value stack...
Damien George596f41d2015-02-10 13:21:42 +0000598 sp -= 4;
AZ Huangb1f692e2014-04-14 23:22:44 +0800599 // ... pop "with" exception handler, and signal END_FINALLY
600 // to just execute finally handler normally (by pushing None
601 // on value stack)
602 assert(exc_sp >= exc_stack);
AZ Huangb1f692e2014-04-14 23:22:44 +0800603 POP_EXC_BLOCK();
604 PUSH(mp_const_none);
Damien George596f41d2015-02-10 13:21:42 +0000605 } else {
606 // Pop __exit__ boundmethod at sp[-3], remembering that top 3 values
607 // are reversed.
608 sp[-3] = sp[0];
609 obj = sp[-2];
610 sp[-2] = sp[-1];
611 sp[-1] = obj;
612 sp--;
AZ Huangb1f692e2014-04-14 23:22:44 +0800613 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800614 }
615 DISPATCH();
616 }
Damienc226dca2013-10-16 16:12:52 +0100617
Damien Georgecd97a432014-12-02 19:25:10 +0000618 ENTRY(MP_BC_UNWIND_JUMP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200619 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800620 DECODE_SLABEL;
Damien Georgecd97a432014-12-02 19:25:10 +0000621 PUSH((void*)(ip + slab)); // push destination ip for jump
Damien George40f3c022014-07-03 13:25:24 +0100622 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 +0000623unwind_jump:;
624 mp_uint_t unum = (mp_uint_t)POP(); // get number of exception handlers to unwind
Damien George25c84642014-05-30 15:20:41 +0100625 while ((unum & 0x7f) > 0) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800626 unum -= 1;
627 assert(exc_sp >= exc_stack);
Damien George74eb44c2014-12-22 12:49:57 +0000628 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800629 // We're going to run "finally" code as a coroutine
630 // (not calling it recursively). Set up a sentinel
631 // on a stack so it can return back to us when it is
632 // done (when END_FINALLY reached).
633 PUSH((void*)unum); // push number of exception handlers left to unwind
634 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
635 ip = exc_sp->handler; // get exception handler byte code address
636 exc_sp--; // pop exception handler
637 goto dispatch_loop; // run the exception handler
638 }
639 exc_sp--;
640 }
641 ip = (const byte*)POP(); // pop destination ip for jump
Damien George25c84642014-05-30 15:20:41 +0100642 if (unum != 0) {
643 sp--;
644 }
Damien George124df6f2014-10-25 18:19:55 +0100645 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000646 }
Damience89a212013-10-15 22:25:17 +0100647
AZ Huangb1f692e2014-04-14 23:22:44 +0800648 // matched against: POP_BLOCK or POP_EXCEPT (anything else?)
649 ENTRY(MP_BC_SETUP_EXCEPT):
Damien Georgecd97a432014-12-02 19:25:10 +0000650 ENTRY(MP_BC_SETUP_FINALLY): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200651 MARK_EXC_IP_SELECTIVE();
Damien Georgef89d6592014-12-29 00:29:59 +0000652 #if SELECTIVE_EXC_IP
653 PUSH_EXC_BLOCK((code_state->ip[-1] == MP_BC_SETUP_FINALLY) ? 1 : 0);
654 #else
655 PUSH_EXC_BLOCK((code_state->ip[0] == MP_BC_SETUP_FINALLY) ? 1 : 0);
656 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800657 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000658 }
Damience89a212013-10-15 22:25:17 +0100659
AZ Huangb1f692e2014-04-14 23:22:44 +0800660 ENTRY(MP_BC_END_FINALLY):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200661 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800662 // not fully implemented
663 // if TOS is an exception, reraises the exception (3 values on TOS)
664 // if TOS is None, just pops it and continues
665 // if TOS is an integer, does something else
666 // else error
667 if (mp_obj_is_exception_type(TOP())) {
Damien George66ae8c92014-04-17 16:50:23 +0100668 RAISE(sp[-1]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800669 }
670 if (TOP() == mp_const_none) {
Damien George20006db2014-01-18 14:10:48 +0000671 sp--;
Damien George5e1d9932015-03-25 22:20:37 +0000672 } else {
673 assert(MP_OBJ_IS_SMALL_INT(TOP()));
AZ Huangb1f692e2014-04-14 23:22:44 +0800674 // We finished "finally" coroutine and now dispatch back
675 // to our caller, based on TOS value
676 mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());
Damien George5e1d9932015-03-25 22:20:37 +0000677 if (reason == UNWIND_RETURN) {
678 goto unwind_return;
679 } else {
680 assert(reason == UNWIND_JUMP);
681 goto unwind_jump;
AZ Huangb1f692e2014-04-14 23:22:44 +0800682 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800683 }
684 DISPATCH();
685
686 ENTRY(MP_BC_GET_ITER):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200687 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800688 SET_TOP(mp_getiter(TOP()));
689 DISPATCH();
690
Damien Georged8675542014-05-25 22:58:04 +0100691 ENTRY(MP_BC_FOR_ITER): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200692 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800693 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgec60a2612014-06-01 12:32:28 +0100694 code_state->sp = sp;
Paul Sokolovskyc48d6f72014-05-11 20:32:39 +0300695 assert(TOP());
Damien Georged8675542014-05-25 22:58:04 +0100696 mp_obj_t value = mp_iternext_allow_raise(TOP());
697 if (value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800698 --sp; // pop the exhausted iterator
Damien Georgecd97a432014-12-02 19:25:10 +0000699 ip += ulab; // jump to after for-block
AZ Huangb1f692e2014-04-14 23:22:44 +0800700 } else {
Damien Georged8675542014-05-25 22:58:04 +0100701 PUSH(value); // push the next iteration value
AZ Huangb1f692e2014-04-14 23:22:44 +0800702 }
703 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100704 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800705
706 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
707 ENTRY(MP_BC_POP_BLOCK):
708 // we are exiting an exception handler, so pop the last one of the exception-stack
709 assert(exc_sp >= exc_stack);
710 POP_EXC_BLOCK();
711 DISPATCH();
712
713 // matched against: SETUP_EXCEPT
714 ENTRY(MP_BC_POP_EXCEPT):
715 // TODO need to work out how blocks work etc
716 // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
717 assert(exc_sp >= exc_stack);
718 assert(currently_in_except_block);
719 //sp = (mp_obj_t*)(*exc_sp--);
720 //exc_sp--; // discard ip
721 POP_EXC_BLOCK();
722 //sp -= 3; // pop 3 exception values
723 DISPATCH();
724
725 ENTRY(MP_BC_NOT):
726 if (TOP() == mp_const_true) {
727 SET_TOP(mp_const_false);
728 } else {
729 SET_TOP(mp_const_true);
730 }
731 DISPATCH();
732
Damien Georgecd97a432014-12-02 19:25:10 +0000733 ENTRY(MP_BC_BUILD_TUPLE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200734 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800735 DECODE_UINT;
736 sp -= unum - 1;
737 SET_TOP(mp_obj_new_tuple(unum, sp));
738 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000739 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800740
Damien Georgecd97a432014-12-02 19:25:10 +0000741 ENTRY(MP_BC_BUILD_LIST): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200742 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800743 DECODE_UINT;
744 sp -= unum - 1;
745 SET_TOP(mp_obj_new_list(unum, sp));
746 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000747 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800748
Damien Georgecd97a432014-12-02 19:25:10 +0000749 ENTRY(MP_BC_LIST_APPEND): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200750 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800751 DECODE_UINT;
752 // I think it's guaranteed by the compiler that sp[unum] is a list
753 mp_obj_list_append(sp[-unum], sp[0]);
754 sp--;
755 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000756 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800757
Damien Georgecd97a432014-12-02 19:25:10 +0000758 ENTRY(MP_BC_BUILD_MAP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200759 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800760 DECODE_UINT;
761 PUSH(mp_obj_new_dict(unum));
762 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000763 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800764
765 ENTRY(MP_BC_STORE_MAP):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200766 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800767 sp -= 2;
768 mp_obj_dict_store(sp[0], sp[2], sp[1]);
769 DISPATCH();
770
Damien Georgecd97a432014-12-02 19:25:10 +0000771 ENTRY(MP_BC_MAP_ADD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200772 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800773 DECODE_UINT;
774 // I think it's guaranteed by the compiler that sp[-unum - 1] is a map
775 mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]);
776 sp -= 2;
777 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000778 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800779
Damien George3ebd4d02014-06-01 13:46:47 +0100780#if MICROPY_PY_BUILTINS_SET
Damien Georgecd97a432014-12-02 19:25:10 +0000781 ENTRY(MP_BC_BUILD_SET): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200782 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800783 DECODE_UINT;
784 sp -= unum - 1;
785 SET_TOP(mp_obj_new_set(unum, sp));
786 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000787 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800788
Damien Georgecd97a432014-12-02 19:25:10 +0000789 ENTRY(MP_BC_SET_ADD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200790 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800791 DECODE_UINT;
792 // I think it's guaranteed by the compiler that sp[-unum] is a set
793 mp_obj_set_store(sp[-unum], sp[0]);
794 sp--;
795 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000796 }
Damien George3ebd4d02014-06-01 13:46:47 +0100797#endif
Damienc12aa462013-10-16 20:57:49 +0100798
Damien Georgefb510b32014-06-01 13:32:54 +0100799#if MICROPY_PY_BUILTINS_SLICE
Damien Georgecd97a432014-12-02 19:25:10 +0000800 ENTRY(MP_BC_BUILD_SLICE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200801 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800802 DECODE_UINT;
803 if (unum == 2) {
Damien Georged8675542014-05-25 22:58:04 +0100804 mp_obj_t stop = POP();
805 mp_obj_t start = TOP();
806 SET_TOP(mp_obj_new_slice(start, stop, mp_const_none));
AZ Huangb1f692e2014-04-14 23:22:44 +0800807 } else {
Damien Georged8675542014-05-25 22:58:04 +0100808 mp_obj_t step = POP();
809 mp_obj_t stop = POP();
810 mp_obj_t start = TOP();
811 SET_TOP(mp_obj_new_slice(start, stop, step));
AZ Huangb1f692e2014-04-14 23:22:44 +0800812 }
813 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000814 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800815#endif
816
Damien Georgecd97a432014-12-02 19:25:10 +0000817 ENTRY(MP_BC_UNPACK_SEQUENCE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200818 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800819 DECODE_UINT;
820 mp_unpack_sequence(sp[0], unum, sp);
821 sp += unum - 1;
822 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000823 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800824
Damien Georgecd97a432014-12-02 19:25:10 +0000825 ENTRY(MP_BC_UNPACK_EX): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200826 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800827 DECODE_UINT;
828 mp_unpack_ex(sp[0], unum, sp);
829 sp += (unum & 0xff) + ((unum >> 8) & 0xff);
830 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000831 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800832
Damien Georgecd97a432014-12-02 19:25:10 +0000833 ENTRY(MP_BC_MAKE_FUNCTION): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800834 DECODE_PTR;
Damien Georgecd97a432014-12-02 19:25:10 +0000835 PUSH(mp_make_function_from_raw_code(ptr, MP_OBJ_NULL, MP_OBJ_NULL));
AZ Huangb1f692e2014-04-14 23:22:44 +0800836 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000837 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800838
Damien Georged8675542014-05-25 22:58:04 +0100839 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800840 DECODE_PTR;
841 // Stack layout: def_tuple def_dict <- TOS
Damien Georged8675542014-05-25 22:58:04 +0100842 mp_obj_t def_dict = POP();
Damien Georgecd97a432014-12-02 19:25:10 +0000843 SET_TOP(mp_make_function_from_raw_code(ptr, TOP(), def_dict));
AZ Huangb1f692e2014-04-14 23:22:44 +0800844 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100845 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800846
Damien George3558f622014-04-20 17:50:40 +0100847 ENTRY(MP_BC_MAKE_CLOSURE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800848 DECODE_PTR;
Damien George40f3c022014-07-03 13:25:24 +0100849 mp_uint_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100850 // Stack layout: closed_overs <- TOS
851 sp -= n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000852 SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800853 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100854 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800855
Damien George3558f622014-04-20 17:50:40 +0100856 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800857 DECODE_PTR;
Damien George40f3c022014-07-03 13:25:24 +0100858 mp_uint_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100859 // Stack layout: def_tuple def_dict closed_overs <- TOS
860 sp -= 2 + n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000861 SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800862 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100863 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800864
Damien Georgecd97a432014-12-02 19:25:10 +0000865 ENTRY(MP_BC_CALL_FUNCTION): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200866 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800867 DECODE_UINT;
868 // unum & 0xff == n_positional
869 // (unum >> 8) & 0xff == n_keyword
870 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
Paul Sokolovsky20397572015-03-28 01:14:44 +0200871 #if MICROPY_STACKLESS
872 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
873 code_state->ip = ip;
874 code_state->sp = sp;
875 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
876 mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1);
Paul Sokolovsky332a9092015-03-28 01:14:44 +0200877 if (new_state) {
878 new_state->prev = code_state;
879 code_state = new_state;
880 nlr_pop();
881 goto run_code_state;
882 }
Paul Sokolovsky20397572015-03-28 01:14:44 +0200883 }
884 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800885 SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
886 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000887 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800888
Damien Georgecd97a432014-12-02 19:25:10 +0000889 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200890 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800891 DECODE_UINT;
892 // unum & 0xff == n_positional
893 // (unum >> 8) & 0xff == n_keyword
894 // We have folowing stack layout here:
895 // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
896 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200897 #if MICROPY_STACKLESS
898 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
899 code_state->ip = ip;
900 code_state->sp = sp;
901 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
902
903 call_args_t out_args;
904 mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args);
905
906 mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
907 out_args.n_args, out_args.n_kw, out_args.args);
908 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
909 if (new_state) {
910 new_state->prev = code_state;
911 code_state = new_state;
912 nlr_pop();
913 goto run_code_state;
914 }
915 }
916 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800917 SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
918 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000919 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800920
Damien Georgecd97a432014-12-02 19:25:10 +0000921 ENTRY(MP_BC_CALL_METHOD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200922 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800923 DECODE_UINT;
924 // unum & 0xff == n_positional
925 // (unum >> 8) & 0xff == n_keyword
926 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200927 #if MICROPY_STACKLESS
928 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
929 code_state->ip = ip;
930 code_state->sp = sp;
931 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
932
933 mp_uint_t n_args = unum & 0xff;
934 mp_uint_t n_kw = (unum >> 8) & 0xff;
935 int adjust = (sp[1] == NULL) ? 0 : 1;
936
937 mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust);
938 if (new_state) {
939 new_state->prev = code_state;
940 code_state = new_state;
941 nlr_pop();
942 goto run_code_state;
943 }
944 }
945 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800946 SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
947 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000948 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800949
Damien Georgecd97a432014-12-02 19:25:10 +0000950 ENTRY(MP_BC_CALL_METHOD_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200951 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800952 DECODE_UINT;
953 // unum & 0xff == n_positional
954 // (unum >> 8) & 0xff == n_keyword
955 // We have folowing stack layout here:
956 // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
957 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200958 #if MICROPY_STACKLESS
959 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
960 code_state->ip = ip;
961 code_state->sp = sp;
962 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
963
964 call_args_t out_args;
965 mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args);
966
967 mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
968 out_args.n_args, out_args.n_kw, out_args.args);
969 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
970 if (new_state) {
971 new_state->prev = code_state;
972 code_state = new_state;
973 nlr_pop();
974 goto run_code_state;
975 }
976 }
977 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800978 SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
979 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000980 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800981
982 ENTRY(MP_BC_RETURN_VALUE):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200983 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800984unwind_return:
985 while (exc_sp >= exc_stack) {
Damien George74eb44c2014-12-22 12:49:57 +0000986 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800987 // We're going to run "finally" code as a coroutine
988 // (not calling it recursively). Set up a sentinel
989 // on a stack so it can return back to us when it is
990 // done (when END_FINALLY reached).
991 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
992 ip = exc_sp->handler;
993 // We don't need to do anything with sp, finally is just
994 // syntactic sugar for sequential execution??
995 // sp =
996 exc_sp--;
997 goto dispatch_loop;
998 }
999 exc_sp--;
1000 }
1001 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001002 code_state->sp = sp;
AZ Huangb1f692e2014-04-14 23:22:44 +08001003 assert(exc_sp == exc_stack - 1);
Paul Sokolovsky20397572015-03-28 01:14:44 +02001004 #if MICROPY_STACKLESS
1005 if (code_state->prev != NULL) {
1006 mp_obj_t res = *sp;
1007 mp_globals_set(code_state->old_globals);
1008 code_state = code_state->prev;
1009 *code_state->sp = res;
1010 goto run_code_state;
1011 }
1012 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001013 return MP_VM_RETURN_NORMAL;
1014
Damien Georged8675542014-05-25 22:58:04 +01001015 ENTRY(MP_BC_RAISE_VARARGS): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001016 MARK_EXC_IP_SELECTIVE();
Damien Georgecd97a432014-12-02 19:25:10 +00001017 mp_uint_t unum = *ip++;
Damien Georged8675542014-05-25 22:58:04 +01001018 mp_obj_t obj;
AZ Huangb1f692e2014-04-14 23:22:44 +08001019 assert(unum <= 1);
1020 if (unum == 0) {
1021 // search for the inner-most previous exception, to reraise it
Damien Georged8675542014-05-25 22:58:04 +01001022 obj = MP_OBJ_NULL;
AZ Huangb1f692e2014-04-14 23:22:44 +08001023 for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
1024 if (e->prev_exc != MP_OBJ_NULL) {
Damien Georged8675542014-05-25 22:58:04 +01001025 obj = e->prev_exc;
AZ Huangb1f692e2014-04-14 23:22:44 +08001026 break;
1027 }
1028 }
Damien Georged8675542014-05-25 22:58:04 +01001029 if (obj == MP_OBJ_NULL) {
1030 obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
1031 RAISE(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001032 }
1033 } else {
Damien Georged8675542014-05-25 22:58:04 +01001034 obj = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +08001035 }
Damien Georged8675542014-05-25 22:58:04 +01001036 obj = mp_make_raise_obj(obj);
1037 RAISE(obj);
1038 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001039
1040 ENTRY(MP_BC_YIELD_VALUE):
1041yield:
1042 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001043 code_state->ip = ip;
1044 code_state->sp = sp;
1045 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +08001046 return MP_VM_RETURN_YIELD;
1047
1048 ENTRY(MP_BC_YIELD_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001049 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001050//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
1051#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
Damien George66ae8c92014-04-17 16:50:23 +01001052#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 +08001053 mp_vm_return_kind_t ret_kind;
Damien Georged8675542014-05-25 22:58:04 +01001054 mp_obj_t send_value = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +08001055 mp_obj_t t_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +01001056 mp_obj_t ret_value;
AZ Huangb1f692e2014-04-14 23:22:44 +08001057 if (inject_exc != MP_OBJ_NULL) {
1058 t_exc = inject_exc;
1059 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +01001060 ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001061 } else {
Damien Georged8675542014-05-25 22:58:04 +01001062 ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001063 }
1064
1065 if (ret_kind == MP_VM_RETURN_YIELD) {
1066 ip--;
Damien Georged8675542014-05-25 22:58:04 +01001067 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001068 goto yield;
1069 }
1070 if (ret_kind == MP_VM_RETURN_NORMAL) {
1071 // Pop exhausted gen
1072 sp--;
Damien Georged8675542014-05-25 22:58:04 +01001073 if (ret_value == MP_OBJ_NULL) {
AZ Huangb1f692e2014-04-14 23:22:44 +08001074 // Optimize StopIteration
1075 // TODO: get StopIteration's value
1076 PUSH(mp_const_none);
1077 } else {
Damien Georged8675542014-05-25 22:58:04 +01001078 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001079 }
1080
1081 // If we injected GeneratorExit downstream, then even
1082 // if it was swallowed, we re-raise GeneratorExit
1083 GENERATOR_EXIT_IF_NEEDED(t_exc);
1084 DISPATCH();
1085 }
1086 if (ret_kind == MP_VM_RETURN_EXCEPTION) {
1087 // Pop exhausted gen
1088 sp--;
Damien Georged8675542014-05-25 22:58:04 +01001089 if (EXC_MATCH(ret_value, &mp_type_StopIteration)) {
1090 PUSH(mp_obj_exception_get_value(ret_value));
AZ Huangb1f692e2014-04-14 23:22:44 +08001091 // If we injected GeneratorExit downstream, then even
1092 // if it was swallowed, we re-raise GeneratorExit
1093 GENERATOR_EXIT_IF_NEEDED(t_exc);
1094 DISPATCH();
1095 } else {
Damien Georged8675542014-05-25 22:58:04 +01001096 RAISE(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001097 }
1098 }
Damien429d7192013-10-04 19:53:11 +01001099 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001100
Damien Georged8675542014-05-25 22:58:04 +01001101 ENTRY(MP_BC_IMPORT_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001102 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001103 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001104 mp_obj_t obj = POP();
1105 SET_TOP(mp_import_name(qst, obj, TOP()));
AZ Huangb1f692e2014-04-14 23:22:44 +08001106 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001107 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001108
Damien Georged8675542014-05-25 22:58:04 +01001109 ENTRY(MP_BC_IMPORT_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001110 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001111 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001112 mp_obj_t obj = mp_import_from(TOP(), qst);
1113 PUSH(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001114 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001115 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001116
1117 ENTRY(MP_BC_IMPORT_STAR):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001118 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001119 mp_import_all(POP());
1120 DISPATCH();
1121
Damien George8456cc02014-10-25 16:43:46 +01001122#if MICROPY_OPT_COMPUTED_GOTO
1123 ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):
1124 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1125 DISPATCH();
1126
1127 ENTRY(MP_BC_LOAD_FAST_MULTI):
1128 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1129 goto load_check;
1130
1131 ENTRY(MP_BC_STORE_FAST_MULTI):
1132 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1133 DISPATCH();
1134
1135 ENTRY(MP_BC_UNARY_OP_MULTI):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001136 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001137 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1138 DISPATCH();
1139
1140 ENTRY(MP_BC_BINARY_OP_MULTI): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001141 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001142 mp_obj_t rhs = POP();
1143 mp_obj_t lhs = TOP();
1144 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1145 DISPATCH();
1146 }
1147
1148 ENTRY_DEFAULT:
Paul Sokolovsky74957502014-12-28 07:17:43 +02001149 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001150#else
1151 ENTRY_DEFAULT:
1152 if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
1153 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1154 DISPATCH();
1155 } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
1156 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1157 goto load_check;
1158 } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
1159 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1160 DISPATCH();
1161 } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 5) {
1162 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1163 DISPATCH();
1164 } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 35) {
1165 mp_obj_t rhs = POP();
1166 mp_obj_t lhs = TOP();
1167 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1168 DISPATCH();
1169 } else
1170#endif
1171 {
Damien Georged8675542014-05-25 22:58:04 +01001172 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
AZ Huangb1f692e2014-04-14 23:22:44 +08001173 nlr_pop();
Damien Georged8675542014-05-25 22:58:04 +01001174 fastn[0] = obj;
AZ Huangb1f692e2014-04-14 23:22:44 +08001175 return MP_VM_RETURN_EXCEPTION;
Damien Georged8675542014-05-25 22:58:04 +01001176 }
Damien George66ae8c92014-04-17 16:50:23 +01001177
Damien George58ebde42014-05-21 20:32:59 +01001178#if !MICROPY_OPT_COMPUTED_GOTO
AZ Huang9309d992014-04-15 15:57:01 +08001179 } // switch
AZ Huangb1f692e2014-04-14 23:22:44 +08001180#endif
Damien George124df6f2014-10-25 18:19:55 +01001181
1182pending_exception_check:
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001183 if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001184 MARK_EXC_IP_SELECTIVE();
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001185 mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
1186 MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
Damien George124df6f2014-10-25 18:19:55 +01001187 RAISE(obj);
1188 }
Damien George124df6f2014-10-25 18:19:55 +01001189
Damien George66ae8c92014-04-17 16:50:23 +01001190 } // for loop
Damien429d7192013-10-04 19:53:11 +01001191
Damience89a212013-10-15 22:25:17 +01001192 } else {
Damien George66ae8c92014-04-17 16:50:23 +01001193exception_handler:
Damience89a212013-10-15 22:25:17 +01001194 // exception occurred
Damien429d7192013-10-04 19:53:11 +01001195
Damien Georgef89d6592014-12-29 00:29:59 +00001196 #if SELECTIVE_EXC_IP
1197 // with selective ip, we store the ip 1 byte past the opcode, so move ptr back
1198 code_state->ip -= 1;
1199 #endif
1200
Damien George9e6e9352014-03-26 18:37:06 +00001201 // check if it's a StopIteration within a for block
Damien Georgec60a2612014-06-01 12:32:28 +01001202 if (*code_state->ip == MP_BC_FOR_ITER && mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) {
1203 const byte *ip = code_state->ip + 1;
Damien George9e6e9352014-03-26 18:37:06 +00001204 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgecd97a432014-12-02 19:25:10 +00001205 code_state->ip = ip + ulab; // jump to after for-block
Damien Georgec60a2612014-06-01 12:32:28 +01001206 code_state->sp -= 1; // pop the exhausted iterator
Damien George9e6e9352014-03-26 18:37:06 +00001207 goto outer_dispatch_loop; // continue with dispatch loop
1208 }
1209
Paul Sokolovsky20397572015-03-28 01:14:44 +02001210#if MICROPY_STACKLESS
1211unwind_loop:
1212#endif
Damien George08335002014-01-18 23:24:36 +00001213 // set file and line number that the exception occurred at
Paul Sokolovsky382e8ee2014-01-30 13:49:18 +02001214 // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
1215 // But consider how to handle nested exceptions.
Damien George6902eed2014-04-04 10:52:59 +00001216 // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
1217 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 +01001218 const byte *ip = code_state->code_info;
1219 mp_uint_t code_info_size = mp_decode_uint(&ip);
1220 qstr block_name = mp_decode_uint(&ip);
1221 qstr source_file = mp_decode_uint(&ip);
1222 mp_uint_t bc = code_state->ip - code_state->code_info - code_info_size;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001223 mp_uint_t source_line = 1;
1224 mp_uint_t c;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001225 while ((c = *ip)) {
Damien Georgeb427d6a2014-08-26 23:35:57 +01001226 mp_uint_t b, l;
1227 if ((c & 0x80) == 0) {
1228 // 0b0LLBBBBB encoding
1229 b = c & 0x1f;
1230 l = c >> 5;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001231 ip += 1;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001232 } else {
1233 // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
1234 b = c & 0xf;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001235 l = ((c << 4) & 0x700) | ip[1];
1236 ip += 2;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001237 }
1238 if (bc >= b) {
1239 bc -= b;
1240 source_line += l;
1241 } else {
1242 // found source line corresponding to bytecode offset
1243 break;
Paul Sokolovsky411732e2014-06-02 18:24:34 +03001244 }
Damien George08335002014-01-18 23:24:36 +00001245 }
Damien George136b1492014-01-19 12:38:49 +00001246 mp_obj_exception_add_traceback(nlr.ret_val, source_file, source_line, block_name);
Damien George08335002014-01-18 23:24:36 +00001247 }
1248
Damien8f9e2ee2013-12-29 16:54:59 +00001249 while (currently_in_except_block) {
1250 // nested exception
1251
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001252 assert(exc_sp >= exc_stack);
Damien8f9e2ee2013-12-29 16:54:59 +00001253
1254 // TODO make a proper message for nested exception
1255 // at the moment we are just raising the very last exception (the one that caused the nested exception)
1256
1257 // move up to previous exception handler
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +02001258 POP_EXC_BLOCK();
Damien8f9e2ee2013-12-29 16:54:59 +00001259 }
1260
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001261 if (exc_sp >= exc_stack) {
Damien8f9e2ee2013-12-29 16:54:59 +00001262 // set flag to indicate that we are now handling an exception
1263 currently_in_except_block = 1;
1264
Damience89a212013-10-15 22:25:17 +01001265 // catch exception and pass to byte code
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001266 code_state->ip = exc_sp->handler;
Damien George66ae8c92014-04-17 16:50:23 +01001267 mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
Damien Georged7592a12014-03-30 00:54:48 +00001268 // save this exception in the stack so it can be used in a reraise, if needed
1269 exc_sp->prev_exc = nlr.ret_val;
Damienc9f91972013-10-15 23:46:01 +01001270 // push(traceback, exc-val, exc-type)
Damiend99b0522013-12-21 18:17:45 +00001271 PUSH(mp_const_none);
Damienc9f91972013-10-15 23:46:01 +01001272 PUSH(nlr.ret_val);
Paul Sokolovsky682f9e62014-03-29 02:52:17 +02001273 PUSH(mp_obj_get_type(nlr.ret_val));
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001274 code_state->sp = sp;
Damien8f9e2ee2013-12-29 16:54:59 +00001275
Paul Sokolovsky20397572015-03-28 01:14:44 +02001276 #if MICROPY_STACKLESS
1277 } else if (code_state->prev != NULL) {
1278 mp_globals_set(code_state->old_globals);
1279 code_state = code_state->prev;
1280 fastn = &code_state->state[code_state->n_state - 1];
1281 exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
1282 // variables that are visible to the exception handler (declared volatile)
1283 currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
1284 exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
1285 goto unwind_loop;
1286
1287 #endif
Damience89a212013-10-15 22:25:17 +01001288 } else {
Damien Georgec8f78bc2014-02-15 22:55:00 +00001289 // propagate exception to higher level
1290 // TODO what to do about ip and sp? they don't really make sense at this point
1291 fastn[0] = nlr.ret_val; // must put exception here because sp is invalid
1292 return MP_VM_RETURN_EXCEPTION;
Damience89a212013-10-15 22:25:17 +01001293 }
Damien429d7192013-10-04 19:53:11 +01001294 }
1295 }
1296}