blob: bd5bae115e6abb5936b6d49ac0ad69dc7c362b45 [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 George999cedb2015-11-27 17:01:44 +000041//#define TRACE(ip) printf("sp=" INT_FMT " ", sp - code_state->sp); mp_bytecode_print2(ip, 1);
42#define TRACE(ip) printf("sp=%d ", sp - code_state->sp); mp_bytecode_print2(ip, 1);
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +030043#else
44#define TRACE(ip)
45#endif
Damien Georgee90be0d2014-04-10 16:21:34 +000046
Paul Sokolovsky85193422014-01-31 19:45:15 +020047// Value stack grows up (this makes it incompatible with native C stack, but
48// makes sure that arguments to functions are in natural order arg1..argN
49// (Python semantics mandates left-to-right evaluation order, including for
50// function arguments). Stack pointer is pre-incremented and points at the
51// top element.
52// Exception stack also grows up, top element is also pointed at.
53
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020054// Exception stack unwind reasons (WHY_* in CPython-speak)
Damien Georgecbddb272014-02-01 20:08:18 +000055// TODO perhaps compress this to RETURN=0, JUMP>0, with number of unwinds
56// left to do encoded in the JUMP number
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020057typedef enum {
58 UNWIND_RETURN = 1,
Damien Georgecbddb272014-02-01 20:08:18 +000059 UNWIND_JUMP,
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020060} mp_unwind_reason_t;
61
Damien Georgecd97a432014-12-02 19:25:10 +000062#define DECODE_UINT \
63 mp_uint_t unum = 0; \
Paul Sokolovsky0f96ec82014-02-18 21:21:22 +020064 do { \
65 unum = (unum << 7) + (*ip & 0x7f); \
Damien Georgecd97a432014-12-02 19:25:10 +000066 } while ((*ip++ & 0x80) != 0)
67#define DECODE_ULABEL mp_uint_t ulab = (ip[0] | (ip[1] << 8)); ip += 2
68#define DECODE_SLABEL mp_uint_t slab = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2
Damien Georgec8e9c0d2015-11-02 17:27:18 +000069
70#if MICROPY_PERSISTENT_CODE
71
72#define DECODE_QSTR \
73 qstr qst = ip[0] | ip[1] << 8; \
74 ip += 2;
75#define DECODE_PTR \
76 DECODE_UINT; \
Damien George999cedb2015-11-27 17:01:44 +000077 void *ptr = (void*)(uintptr_t)code_state->const_table[unum]
78#define DECODE_OBJ \
79 DECODE_UINT; \
80 mp_obj_t obj = (mp_obj_t)code_state->const_table[unum]
Damien Georgec8e9c0d2015-11-02 17:27:18 +000081
82#else
83
Damien Georged8675542014-05-25 22:58:04 +010084#define DECODE_QSTR qstr qst = 0; \
Paul Sokolovsky0f96ec82014-02-18 21:21:22 +020085 do { \
86 qst = (qst << 7) + (*ip & 0x7f); \
Damien Georged8675542014-05-25 22:58:04 +010087 } while ((*ip++ & 0x80) != 0)
Damien Georgecd97a432014-12-02 19:25:10 +000088#define DECODE_PTR \
Damien George999cedb2015-11-27 17:01:44 +000089 ip = (byte*)MP_ALIGN(ip, sizeof(void*)); \
90 void *ptr = *(void**)ip; \
91 ip += sizeof(void*)
92#define DECODE_OBJ \
93 ip = (byte*)MP_ALIGN(ip, sizeof(mp_obj_t)); \
94 mp_obj_t obj = *(mp_obj_t*)ip; \
95 ip += sizeof(mp_obj_t)
Damien Georgec8e9c0d2015-11-02 17:27:18 +000096
97#endif
98
Damien George20006db2014-01-18 14:10:48 +000099#define PUSH(val) *++sp = (val)
100#define POP() (*sp--)
Damiendb4c3612013-12-10 17:27:24 +0000101#define TOP() (*sp)
102#define SET_TOP(val) *sp = (val)
Damien429d7192013-10-04 19:53:11 +0100103
Paul Sokolovskyae2c81f2015-04-26 01:20:49 +0300104#if MICROPY_PY_SYS_EXC_INFO
Damien George999cedb2015-11-27 17:01:44 +0000105#define CLEAR_SYS_EXC_INFO() MP_STATE_VM(cur_exception) = NULL;
Paul Sokolovskyae2c81f2015-04-26 01:20:49 +0300106#else
107#define CLEAR_SYS_EXC_INFO()
108#endif
109
Damien George74eb44c2014-12-22 12:49:57 +0000110#define PUSH_EXC_BLOCK(with_or_finally) do { \
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +0200111 DECODE_ULABEL; /* except labels are always forward */ \
112 ++exc_sp; \
Damien Georgecd97a432014-12-02 19:25:10 +0000113 exc_sp->handler = ip + ulab; \
Damien George74eb44c2014-12-22 12:49:57 +0000114 exc_sp->val_sp = MP_TAGPTR_MAKE(sp, ((with_or_finally) << 1) | currently_in_except_block); \
Damien George999cedb2015-11-27 17:01:44 +0000115 exc_sp->prev_exc = NULL; \
Damien Georgecd97a432014-12-02 19:25:10 +0000116 currently_in_except_block = 0; /* in a try block now */ \
117} while (0)
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +0200118
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +0200119#define POP_EXC_BLOCK() \
Damien George74eb44c2014-12-22 12:49:57 +0000120 currently_in_except_block = MP_TAGPTR_TAG0(exc_sp->val_sp); /* restore previous state */ \
Paul Sokolovskyae2c81f2015-04-26 01:20:49 +0300121 exc_sp--; /* pop back to previous exception handler */ \
122 CLEAR_SYS_EXC_INFO() /* just clear sys.exc_info(), not compliant, but it shouldn't be used in 1st place */
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +0200123
Damien George20006db2014-01-18 14:10:48 +0000124// fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)
125// sp points to bottom of stack which grows up
Damien Georgec8f78bc2014-02-15 22:55:00 +0000126// returns:
127// MP_VM_RETURN_NORMAL, sp valid, return value in *sp
128// MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
129// MP_VM_RETURN_EXCEPTION, exception in fastn[0]
Damien Georgeaabd83e2014-06-07 14:16:08 +0100130mp_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 +0200131#define SELECTIVE_EXC_IP (0)
132#if SELECTIVE_EXC_IP
Damien Georgef89d6592014-12-29 00:29:59 +0000133#define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */
Paul Sokolovsky74957502014-12-28 07:17:43 +0200134#define MARK_EXC_IP_GLOBAL()
135#else
136#define MARK_EXC_IP_SELECTIVE()
Damien Georgef89d6592014-12-29 00:29:59 +0000137#define MARK_EXC_IP_GLOBAL() { code_state->ip = ip; } /* stores ip pointing to last opcode */
Paul Sokolovsky74957502014-12-28 07:17:43 +0200138#endif
Damien George58ebde42014-05-21 20:32:59 +0100139#if MICROPY_OPT_COMPUTED_GOTO
Damien George51dfcb42015-01-01 20:27:54 +0000140 #include "py/vmentrytable.h"
AZ Huang9309d992014-04-15 15:57:01 +0800141 #define DISPATCH() do { \
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +0300142 TRACE(ip); \
Paul Sokolovsky74957502014-12-28 07:17:43 +0200143 MARK_EXC_IP_GLOBAL(); \
Damien Georgedb128912014-04-27 18:19:06 +0100144 goto *entry_table[*ip++]; \
Damien George4dea9222015-04-09 15:29:54 +0000145 } while (0)
Damien George124df6f2014-10-25 18:19:55 +0100146 #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
AZ Huang9309d992014-04-15 15:57:01 +0800147 #define ENTRY(op) entry_##op
148 #define ENTRY_DEFAULT entry_default
AZ Huangb1f692e2014-04-14 23:22:44 +0800149#else
AZ Huang9309d992014-04-15 15:57:01 +0800150 #define DISPATCH() break
Damien George124df6f2014-10-25 18:19:55 +0100151 #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
AZ Huang9309d992014-04-15 15:57:01 +0800152 #define ENTRY(op) case op
153 #define ENTRY_DEFAULT default
AZ Huangb1f692e2014-04-14 23:22:44 +0800154#endif
155
Damien George66ae8c92014-04-17 16:50:23 +0100156 // nlr_raise needs to be implemented as a goto, so that the C compiler's flow analyser
157 // sees that it's possible for us to jump from the dispatch loop to the exception
158 // handler. Without this, the code may have a different stack layout in the dispatch
159 // loop and the exception handler, leading to very obscure bugs.
Damien George999cedb2015-11-27 17:01:44 +0000160 #define RAISE(o) do { nlr_pop(); nlr.ret_val = MP_OBJ_TO_PTR(o); goto exception_handler; } while (0)
Damien429d7192013-10-04 19:53:11 +0100161
Paul Sokolovsky20397572015-03-28 01:14:44 +0200162#if MICROPY_STACKLESS
163run_code_state: ;
164#endif
Damien Georgeaabd83e2014-06-07 14:16:08 +0100165 // Pointers which are constant for particular invocation of mp_execute_bytecode()
stijn36cc84a2015-04-09 11:34:08 +0200166 mp_obj_t * /*const*/ fastn = &code_state->state[code_state->n_state - 1];
167 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 +0300168
Damien George66ae8c92014-04-17 16:50:23 +0100169 // variables that are visible to the exception handler (declared volatile)
Damien George74eb44c2014-12-22 12:49:57 +0000170 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 +0300171 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 +0100172
Damience89a212013-10-15 22:25:17 +0100173 // outer exception handling loop
Damien429d7192013-10-04 19:53:11 +0100174 for (;;) {
Damien George66ae8c92014-04-17 16:50:23 +0100175 nlr_buf_t nlr;
Damien George9e6e9352014-03-26 18:37:06 +0000176outer_dispatch_loop:
Damience89a212013-10-15 22:25:17 +0100177 if (nlr_push(&nlr) == 0) {
Damien George66ae8c92014-04-17 16:50:23 +0100178 // local variables that are not visible to the exception handler
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300179 const byte *ip = code_state->ip;
180 mp_obj_t *sp = code_state->sp;
Damien Georged8675542014-05-25 22:58:04 +0100181 mp_obj_t obj_shared;
Damien George40d84302016-02-15 22:46:21 +0000182 MICROPY_VM_HOOK_INIT
Damien George66ae8c92014-04-17 16:50:23 +0100183
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200184 // If we have exception to inject, now that we finish setting up
185 // execution context, raise it. This works as if RAISE_VARARGS
186 // bytecode was executed.
Paul Sokolovskycf21a4e2014-03-26 17:36:12 +0200187 // Injecting exc into yield from generator is a special case,
188 // handled by MP_BC_YIELD_FROM itself
189 if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
Damien Georged8675542014-05-25 22:58:04 +0100190 mp_obj_t exc = inject_exc;
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200191 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100192 exc = mp_make_raise_obj(exc);
193 RAISE(exc);
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200194 }
Damien George66ae8c92014-04-17 16:50:23 +0100195
Damience89a212013-10-15 22:25:17 +0100196 // loop to execute byte code
197 for (;;) {
Paul Sokolovsky6472dea2014-02-01 00:55:05 +0200198dispatch_loop:
Damien George58ebde42014-05-21 20:32:59 +0100199#if MICROPY_OPT_COMPUTED_GOTO
AZ Huangb1f692e2014-04-14 23:22:44 +0800200 DISPATCH();
201#else
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +0300202 TRACE(ip);
Paul Sokolovsky74957502014-12-28 07:17:43 +0200203 MARK_EXC_IP_GLOBAL();
Damien Georgedb128912014-04-27 18:19:06 +0100204 switch (*ip++) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800205#endif
Damien429d7192013-10-04 19:53:11 +0100206
AZ Huangb1f692e2014-04-14 23:22:44 +0800207 ENTRY(MP_BC_LOAD_CONST_FALSE):
208 PUSH(mp_const_false);
209 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100210
AZ Huangb1f692e2014-04-14 23:22:44 +0800211 ENTRY(MP_BC_LOAD_CONST_NONE):
212 PUSH(mp_const_none);
213 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100214
AZ Huangb1f692e2014-04-14 23:22:44 +0800215 ENTRY(MP_BC_LOAD_CONST_TRUE):
216 PUSH(mp_const_true);
217 DISPATCH();
Damien Georgee9906ac2014-01-04 18:44:46 +0000218
AZ Huangb1f692e2014-04-14 23:22:44 +0800219 ENTRY(MP_BC_LOAD_CONST_SMALL_INT): {
Damien George40f3c022014-07-03 13:25:24 +0100220 mp_int_t num = 0;
AZ Huangb1f692e2014-04-14 23:22:44 +0800221 if ((ip[0] & 0x40) != 0) {
222 // Number is negative
223 num--;
Paul Sokolovsky047cd402014-02-19 15:47:59 +0200224 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800225 do {
226 num = (num << 7) | (*ip & 0x7f);
227 } while ((*ip++ & 0x80) != 0);
228 PUSH(MP_OBJ_NEW_SMALL_INT(num));
229 DISPATCH();
230 }
Damience89a212013-10-15 22:25:17 +0100231
Damien Georged8675542014-05-25 22:58:04 +0100232 ENTRY(MP_BC_LOAD_CONST_STRING): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800233 DECODE_QSTR;
Damien Georgeed570e42015-06-25 13:58:41 +0000234 PUSH(MP_OBJ_NEW_QSTR(qst));
AZ Huangb1f692e2014-04-14 23:22:44 +0800235 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100236 }
Damience89a212013-10-15 22:25:17 +0100237
Damien Georgedab13852015-01-13 15:55:54 +0000238 ENTRY(MP_BC_LOAD_CONST_OBJ): {
Damien George999cedb2015-11-27 17:01:44 +0000239 DECODE_OBJ;
240 PUSH(obj);
Damien Georgedab13852015-01-13 15:55:54 +0000241 DISPATCH();
242 }
243
AZ Huangb1f692e2014-04-14 23:22:44 +0800244 ENTRY(MP_BC_LOAD_NULL):
245 PUSH(MP_OBJ_NULL);
246 DISPATCH();
Damien George523b5752014-03-31 11:59:23 +0100247
Damien Georgecd97a432014-12-02 19:25:10 +0000248 ENTRY(MP_BC_LOAD_FAST_N): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800249 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100250 obj_shared = fastn[-unum];
AZ Huangb1f692e2014-04-14 23:22:44 +0800251 load_check:
Damien Georged8675542014-05-25 22:58:04 +0100252 if (obj_shared == MP_OBJ_NULL) {
253 local_name_error: {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200254 MARK_EXC_IP_SELECTIVE();
Damien Georged8675542014-05-25 22:58:04 +0100255 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment");
256 RAISE(obj);
257 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800258 }
Damien Georged8675542014-05-25 22:58:04 +0100259 PUSH(obj_shared);
AZ Huangb1f692e2014-04-14 23:22:44 +0800260 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000261 }
Damien George2bf7c092014-04-09 15:26:46 +0100262
Damien Georgecd97a432014-12-02 19:25:10 +0000263 ENTRY(MP_BC_LOAD_DEREF): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800264 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100265 obj_shared = mp_obj_cell_get(fastn[-unum]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800266 goto load_check;
Damien Georgecd97a432014-12-02 19:25:10 +0000267 }
Damien9ecbcff2013-12-11 00:41:43 +0000268
Damien George7ee91cf2015-01-06 12:51:39 +0000269 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100270 ENTRY(MP_BC_LOAD_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200271 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800272 DECODE_QSTR;
273 PUSH(mp_load_name(qst));
274 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100275 }
Damien George7ee91cf2015-01-06 12:51:39 +0000276 #else
277 ENTRY(MP_BC_LOAD_NAME): {
278 MARK_EXC_IP_SELECTIVE();
279 DECODE_QSTR;
280 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
281 mp_uint_t x = *ip;
282 if (x < MP_STATE_CTX(dict_locals)->map.alloc && MP_STATE_CTX(dict_locals)->map.table[x].key == key) {
283 PUSH(MP_STATE_CTX(dict_locals)->map.table[x].value);
284 } else {
285 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_locals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
286 if (elem != NULL) {
287 *(byte*)ip = (elem - &MP_STATE_CTX(dict_locals)->map.table[0]) & 0xff;
288 PUSH(elem->value);
289 } else {
290 PUSH(mp_load_name(MP_OBJ_QSTR_VALUE(key)));
291 }
292 }
293 ip++;
294 DISPATCH();
295 }
296 #endif
Damience89a212013-10-15 22:25:17 +0100297
Damien George7ee91cf2015-01-06 12:51:39 +0000298 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100299 ENTRY(MP_BC_LOAD_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200300 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800301 DECODE_QSTR;
302 PUSH(mp_load_global(qst));
303 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100304 }
Damien George7ee91cf2015-01-06 12:51:39 +0000305 #else
306 ENTRY(MP_BC_LOAD_GLOBAL): {
307 MARK_EXC_IP_SELECTIVE();
308 DECODE_QSTR;
309 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
310 mp_uint_t x = *ip;
311 if (x < MP_STATE_CTX(dict_globals)->map.alloc && MP_STATE_CTX(dict_globals)->map.table[x].key == key) {
312 PUSH(MP_STATE_CTX(dict_globals)->map.table[x].value);
313 } else {
314 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_globals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
315 if (elem != NULL) {
316 *(byte*)ip = (elem - &MP_STATE_CTX(dict_globals)->map.table[0]) & 0xff;
317 PUSH(elem->value);
318 } else {
319 PUSH(mp_load_global(MP_OBJ_QSTR_VALUE(key)));
320 }
321 }
322 ip++;
323 DISPATCH();
324 }
325 #endif
Damience89a212013-10-15 22:25:17 +0100326
Damien George7ee91cf2015-01-06 12:51:39 +0000327 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100328 ENTRY(MP_BC_LOAD_ATTR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200329 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800330 DECODE_QSTR;
331 SET_TOP(mp_load_attr(TOP(), qst));
332 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100333 }
Damien George7ee91cf2015-01-06 12:51:39 +0000334 #else
335 ENTRY(MP_BC_LOAD_ATTR): {
336 MARK_EXC_IP_SELECTIVE();
337 DECODE_QSTR;
338 mp_obj_t top = TOP();
Damien Georgeb1bbe962015-04-01 14:10:50 +0000339 if (mp_obj_get_type(top)->attr == mp_obj_instance_attr) {
Damien George999cedb2015-11-27 17:01:44 +0000340 mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
Damien George7ee91cf2015-01-06 12:51:39 +0000341 mp_uint_t x = *ip;
342 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
343 mp_map_elem_t *elem;
344 if (x < self->members.alloc && self->members.table[x].key == key) {
345 elem = &self->members.table[x];
346 } else {
347 elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);
348 if (elem != NULL) {
349 *(byte*)ip = elem - &self->members.table[0];
350 } else {
351 goto load_attr_cache_fail;
352 }
353 }
354 SET_TOP(elem->value);
355 ip++;
356 DISPATCH();
357 }
358 load_attr_cache_fail:
359 SET_TOP(mp_load_attr(top, qst));
360 ip++;
361 DISPATCH();
362 }
363 #endif
Damience89a212013-10-15 22:25:17 +0100364
Damien Georged8675542014-05-25 22:58:04 +0100365 ENTRY(MP_BC_LOAD_METHOD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200366 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800367 DECODE_QSTR;
368 mp_load_method(*sp, qst, sp);
369 sp += 1;
370 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100371 }
Damience89a212013-10-15 22:25:17 +0100372
AZ Huangb1f692e2014-04-14 23:22:44 +0800373 ENTRY(MP_BC_LOAD_BUILD_CLASS):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200374 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800375 PUSH(mp_load_build_class());
376 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100377
Damien Georged8675542014-05-25 22:58:04 +0100378 ENTRY(MP_BC_LOAD_SUBSCR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200379 MARK_EXC_IP_SELECTIVE();
Damien Georged8675542014-05-25 22:58:04 +0100380 mp_obj_t index = POP();
381 SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL));
Damien George729f7b42014-04-17 22:10:53 +0100382 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100383 }
Damien George729f7b42014-04-17 22:10:53 +0100384
Damien Georgecd97a432014-12-02 19:25:10 +0000385 ENTRY(MP_BC_STORE_FAST_N): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800386 DECODE_UINT;
387 fastn[-unum] = POP();
388 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000389 }
Damience89a212013-10-15 22:25:17 +0100390
Damien Georgecd97a432014-12-02 19:25:10 +0000391 ENTRY(MP_BC_STORE_DEREF): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800392 DECODE_UINT;
393 mp_obj_cell_set(fastn[-unum], POP());
394 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000395 }
Damien9ecbcff2013-12-11 00:41:43 +0000396
Damien Georged8675542014-05-25 22:58:04 +0100397 ENTRY(MP_BC_STORE_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200398 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800399 DECODE_QSTR;
400 mp_store_name(qst, POP());
401 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100402 }
Damience89a212013-10-15 22:25:17 +0100403
Damien Georged8675542014-05-25 22:58:04 +0100404 ENTRY(MP_BC_STORE_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200405 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800406 DECODE_QSTR;
407 mp_store_global(qst, POP());
408 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100409 }
Damien6addc892013-11-04 23:04:50 +0000410
Damien George7ee91cf2015-01-06 12:51:39 +0000411 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100412 ENTRY(MP_BC_STORE_ATTR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200413 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800414 DECODE_QSTR;
415 mp_store_attr(sp[0], qst, sp[-1]);
416 sp -= 2;
417 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100418 }
Damien George7ee91cf2015-01-06 12:51:39 +0000419 #else
stijn28fa84b2015-02-14 18:43:54 +0100420 // This caching code works with MICROPY_PY_BUILTINS_PROPERTY and/or
421 // MICROPY_PY_DESCRIPTORS enabled because if the attr exists in
422 // self->members then it can't be a property or have descriptors. A
Damien George7ee91cf2015-01-06 12:51:39 +0000423 // consequence of this is that we can't use MP_MAP_LOOKUP_ADD_IF_NOT_FOUND
424 // in the fast-path below, because that store could override a property.
425 ENTRY(MP_BC_STORE_ATTR): {
426 MARK_EXC_IP_SELECTIVE();
427 DECODE_QSTR;
428 mp_obj_t top = TOP();
Damien Georgeb1bbe962015-04-01 14:10:50 +0000429 if (mp_obj_get_type(top)->attr == mp_obj_instance_attr && sp[-1] != MP_OBJ_NULL) {
Damien George999cedb2015-11-27 17:01:44 +0000430 mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
Damien George7ee91cf2015-01-06 12:51:39 +0000431 mp_uint_t x = *ip;
432 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
433 mp_map_elem_t *elem;
434 if (x < self->members.alloc && self->members.table[x].key == key) {
435 elem = &self->members.table[x];
436 } else {
437 elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);
438 if (elem != NULL) {
439 *(byte*)ip = elem - &self->members.table[0];
440 } else {
441 goto store_attr_cache_fail;
442 }
443 }
444 elem->value = sp[-1];
445 sp -= 2;
446 ip++;
447 DISPATCH();
448 }
449 store_attr_cache_fail:
450 mp_store_attr(sp[0], qst, sp[-1]);
451 sp -= 2;
452 ip++;
453 DISPATCH();
454 }
455 #endif
Damience89a212013-10-15 22:25:17 +0100456
AZ Huangb1f692e2014-04-14 23:22:44 +0800457 ENTRY(MP_BC_STORE_SUBSCR):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200458 MARK_EXC_IP_SELECTIVE();
Damien George729f7b42014-04-17 22:10:53 +0100459 mp_obj_subscr(sp[-1], sp[0], sp[-2]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800460 sp -= 3;
461 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100462
Damien Georgecd97a432014-12-02 19:25:10 +0000463 ENTRY(MP_BC_DELETE_FAST): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200464 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800465 DECODE_UINT;
466 if (fastn[-unum] == MP_OBJ_NULL) {
467 goto local_name_error;
468 }
469 fastn[-unum] = MP_OBJ_NULL;
470 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000471 }
Damien George2bf7c092014-04-09 15:26:46 +0100472
Damien Georgecd97a432014-12-02 19:25:10 +0000473 ENTRY(MP_BC_DELETE_DEREF): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200474 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800475 DECODE_UINT;
476 if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
477 goto local_name_error;
478 }
479 mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);
480 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000481 }
Damien George2bf7c092014-04-09 15:26:46 +0100482
Damien Georged8675542014-05-25 22:58:04 +0100483 ENTRY(MP_BC_DELETE_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200484 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800485 DECODE_QSTR;
486 mp_delete_name(qst);
487 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100488 }
Paul Sokolovskyf9090342014-03-23 21:19:02 +0200489
Damien Georged8675542014-05-25 22:58:04 +0100490 ENTRY(MP_BC_DELETE_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200491 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800492 DECODE_QSTR;
493 mp_delete_global(qst);
494 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100495 }
Damien George1d24ea52014-04-08 21:11:49 +0100496
Damien Georged8675542014-05-25 22:58:04 +0100497 ENTRY(MP_BC_DUP_TOP): {
498 mp_obj_t top = TOP();
499 PUSH(top);
AZ Huangb1f692e2014-04-14 23:22:44 +0800500 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100501 }
Damience89a212013-10-15 22:25:17 +0100502
AZ Huangb1f692e2014-04-14 23:22:44 +0800503 ENTRY(MP_BC_DUP_TOP_TWO):
504 sp += 2;
505 sp[0] = sp[-2];
506 sp[-1] = sp[-3];
507 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100508
AZ Huangb1f692e2014-04-14 23:22:44 +0800509 ENTRY(MP_BC_POP_TOP):
510 sp -= 1;
511 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100512
Damien Georged8675542014-05-25 22:58:04 +0100513 ENTRY(MP_BC_ROT_TWO): {
514 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800515 sp[0] = sp[-1];
Damien Georged8675542014-05-25 22:58:04 +0100516 sp[-1] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800517 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100518 }
Damien4ebb32f2013-11-02 14:33:10 +0000519
Damien Georged8675542014-05-25 22:58:04 +0100520 ENTRY(MP_BC_ROT_THREE): {
521 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800522 sp[0] = sp[-1];
523 sp[-1] = sp[-2];
Damien Georged8675542014-05-25 22:58:04 +0100524 sp[-2] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800525 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100526 }
Damience89a212013-10-15 22:25:17 +0100527
Damien Georgecd97a432014-12-02 19:25:10 +0000528 ENTRY(MP_BC_JUMP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800529 DECODE_SLABEL;
Damien Georgecd97a432014-12-02 19:25:10 +0000530 ip += slab;
Damien George124df6f2014-10-25 18:19:55 +0100531 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000532 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800533
Damien Georgecd97a432014-12-02 19:25:10 +0000534 ENTRY(MP_BC_POP_JUMP_IF_TRUE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800535 DECODE_SLABEL;
536 if (mp_obj_is_true(POP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000537 ip += slab;
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200538 }
Damien George124df6f2014-10-25 18:19:55 +0100539 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000540 }
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200541
Damien Georgecd97a432014-12-02 19:25:10 +0000542 ENTRY(MP_BC_POP_JUMP_IF_FALSE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800543 DECODE_SLABEL;
544 if (!mp_obj_is_true(POP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000545 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800546 }
Damien George124df6f2014-10-25 18:19:55 +0100547 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000548 }
Damien George600ae732014-01-21 23:48:04 +0000549
Damien Georgecd97a432014-12-02 19:25:10 +0000550 ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800551 DECODE_SLABEL;
552 if (mp_obj_is_true(TOP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000553 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800554 } else {
555 sp--;
556 }
Damien George124df6f2014-10-25 18:19:55 +0100557 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000558 }
Damience89a212013-10-15 22:25:17 +0100559
Damien Georgecd97a432014-12-02 19:25:10 +0000560 ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800561 DECODE_SLABEL;
562 if (mp_obj_is_true(TOP())) {
563 sp--;
564 } else {
Damien Georgecd97a432014-12-02 19:25:10 +0000565 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800566 }
Damien George124df6f2014-10-25 18:19:55 +0100567 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000568 }
Damience89a212013-10-15 22:25:17 +0100569
Damien Georged8675542014-05-25 22:58:04 +0100570 ENTRY(MP_BC_SETUP_WITH): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200571 MARK_EXC_IP_SELECTIVE();
Damien George8c1d23a2015-04-24 01:52:28 +0100572 // stack: (..., ctx_mgr)
Damien Georged8675542014-05-25 22:58:04 +0100573 mp_obj_t obj = TOP();
Damien George8c1d23a2015-04-24 01:52:28 +0100574 mp_load_method(obj, MP_QSTR___exit__, sp);
575 mp_load_method(obj, MP_QSTR___enter__, sp + 2);
576 mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 2);
577 sp += 1;
Damien George74eb44c2014-12-22 12:49:57 +0000578 PUSH_EXC_BLOCK(1);
Damien Georged8675542014-05-25 22:58:04 +0100579 PUSH(ret);
Damien George8c1d23a2015-04-24 01:52:28 +0100580 // stack: (..., __exit__, ctx_mgr, as_value)
AZ Huangb1f692e2014-04-14 23:22:44 +0800581 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100582 }
Damience89a212013-10-15 22:25:17 +0100583
AZ Huangb1f692e2014-04-14 23:22:44 +0800584 ENTRY(MP_BC_WITH_CLEANUP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200585 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800586 // Arriving here, there's "exception control block" on top of stack,
Damien George8c1d23a2015-04-24 01:52:28 +0100587 // and __exit__ method (with self) underneath it. Bytecode calls __exit__,
AZ Huangb1f692e2014-04-14 23:22:44 +0800588 // and "deletes" it off stack, shifting "exception control block"
589 // to its place.
AZ Huangb1f692e2014-04-14 23:22:44 +0800590 if (TOP() == mp_const_none) {
Damien George8c1d23a2015-04-24 01:52:28 +0100591 // stack: (..., __exit__, ctx_mgr, None)
592 sp[1] = mp_const_none;
593 sp[2] = mp_const_none;
594 sp -= 2;
595 mp_call_method_n_kw(3, 0, sp);
AZ Huangb1f692e2014-04-14 23:22:44 +0800596 SET_TOP(mp_const_none);
AZ Huangb1f692e2014-04-14 23:22:44 +0800597 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
Damien George5e1d9932015-03-25 22:20:37 +0000598 mp_int_t cause_val = MP_OBJ_SMALL_INT_VALUE(TOP());
599 if (cause_val == UNWIND_RETURN) {
Damien George8c1d23a2015-04-24 01:52:28 +0100600 // stack: (..., __exit__, ctx_mgr, ret_val, UNWIND_RETURN)
601 mp_obj_t ret_val = sp[-1];
602 sp[-1] = mp_const_none;
603 sp[0] = mp_const_none;
604 sp[1] = mp_const_none;
605 mp_call_method_n_kw(3, 0, sp - 3);
606 sp[-3] = ret_val;
607 sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN);
Damien George5e1d9932015-03-25 22:20:37 +0000608 } else {
609 assert(cause_val == UNWIND_JUMP);
Damien George8c1d23a2015-04-24 01:52:28 +0100610 // stack: (..., __exit__, ctx_mgr, dest_ip, num_exc, UNWIND_JUMP)
611 mp_obj_t dest_ip = sp[-2];
612 mp_obj_t num_exc = sp[-1];
613 sp[-2] = mp_const_none;
614 sp[-1] = mp_const_none;
615 sp[0] = mp_const_none;
616 mp_call_method_n_kw(3, 0, sp - 4);
617 sp[-4] = dest_ip;
618 sp[-3] = num_exc;
619 sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP);
AZ Huangb1f692e2014-04-14 23:22:44 +0800620 }
Damien George8c1d23a2015-04-24 01:52:28 +0100621 sp -= 2; // we removed (__exit__, ctx_mgr)
Damien George5e1d9932015-03-25 22:20:37 +0000622 } else {
623 assert(mp_obj_is_exception_type(TOP()));
Damien George8c1d23a2015-04-24 01:52:28 +0100624 // stack: (..., __exit__, ctx_mgr, traceback, exc_val, exc_type)
Damien George596f41d2015-02-10 13:21:42 +0000625 // Need to pass (sp[0], sp[-1], sp[-2]) as arguments so must reverse the
626 // order of these on the value stack (don't want to create a temporary
627 // array because it increases stack footprint of the VM).
628 mp_obj_t obj = sp[-2];
629 sp[-2] = sp[0];
630 sp[0] = obj;
Damien George8c1d23a2015-04-24 01:52:28 +0100631 mp_obj_t ret_value = mp_call_method_n_kw(3, 0, sp - 4);
Damien Georged8675542014-05-25 22:58:04 +0100632 if (mp_obj_is_true(ret_value)) {
Damien George8c1d23a2015-04-24 01:52:28 +0100633 // We need to silence/swallow the exception. This is done
634 // by popping the exception and the __exit__ handler and
635 // replacing it with None, which signals END_FINALLY to just
636 // execute the finally handler normally.
Damien George596f41d2015-02-10 13:21:42 +0000637 sp -= 4;
Damien George8c1d23a2015-04-24 01:52:28 +0100638 SET_TOP(mp_const_none);
AZ Huangb1f692e2014-04-14 23:22:44 +0800639 assert(exc_sp >= exc_stack);
AZ Huangb1f692e2014-04-14 23:22:44 +0800640 POP_EXC_BLOCK();
Damien George596f41d2015-02-10 13:21:42 +0000641 } else {
Damien George8c1d23a2015-04-24 01:52:28 +0100642 // We need to re-raise the exception. We pop __exit__ handler
643 // and copy the 3 exception values down (remembering that they
644 // are reversed due to above code).
645 sp[-4] = sp[0];
646 sp[-3] = sp[-1];
647 sp -= 2;
AZ Huangb1f692e2014-04-14 23:22:44 +0800648 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800649 }
650 DISPATCH();
651 }
Damienc226dca2013-10-16 16:12:52 +0100652
Damien Georgecd97a432014-12-02 19:25:10 +0000653 ENTRY(MP_BC_UNWIND_JUMP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200654 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800655 DECODE_SLABEL;
Damien George999cedb2015-11-27 17:01:44 +0000656 PUSH((mp_obj_t)(mp_uint_t)(uintptr_t)(ip + slab)); // push destination ip for jump
657 PUSH((mp_obj_t)(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 +0000658unwind_jump:;
659 mp_uint_t unum = (mp_uint_t)POP(); // get number of exception handlers to unwind
Damien George25c84642014-05-30 15:20:41 +0100660 while ((unum & 0x7f) > 0) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800661 unum -= 1;
662 assert(exc_sp >= exc_stack);
Damien George74eb44c2014-12-22 12:49:57 +0000663 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
Damien George4bf3f2d2015-10-15 17:48:28 +0100664 // Getting here the stack looks like:
665 // (..., X, dest_ip)
666 // where X is pointed to by exc_sp->val_sp and in the case
667 // of a "with" block contains the context manager info.
AZ Huangb1f692e2014-04-14 23:22:44 +0800668 // We're going to run "finally" code as a coroutine
669 // (not calling it recursively). Set up a sentinel
670 // on a stack so it can return back to us when it is
Damien George4bf3f2d2015-10-15 17:48:28 +0100671 // done (when WITH_CLEANUP or END_FINALLY reached).
Damien George999cedb2015-11-27 17:01:44 +0000672 PUSH((mp_obj_t)unum); // push number of exception handlers left to unwind
AZ Huangb1f692e2014-04-14 23:22:44 +0800673 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
674 ip = exc_sp->handler; // get exception handler byte code address
675 exc_sp--; // pop exception handler
676 goto dispatch_loop; // run the exception handler
677 }
Damien George93bb7df2016-02-01 16:07:21 +0000678 POP_EXC_BLOCK();
AZ Huangb1f692e2014-04-14 23:22:44 +0800679 }
Damien George999cedb2015-11-27 17:01:44 +0000680 ip = (const byte*)MP_OBJ_TO_PTR(POP()); // pop destination ip for jump
Damien George25c84642014-05-30 15:20:41 +0100681 if (unum != 0) {
682 sp--;
683 }
Damien George124df6f2014-10-25 18:19:55 +0100684 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000685 }
Damience89a212013-10-15 22:25:17 +0100686
AZ Huangb1f692e2014-04-14 23:22:44 +0800687 // matched against: POP_BLOCK or POP_EXCEPT (anything else?)
688 ENTRY(MP_BC_SETUP_EXCEPT):
Damien Georgecd97a432014-12-02 19:25:10 +0000689 ENTRY(MP_BC_SETUP_FINALLY): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200690 MARK_EXC_IP_SELECTIVE();
Damien Georgef89d6592014-12-29 00:29:59 +0000691 #if SELECTIVE_EXC_IP
692 PUSH_EXC_BLOCK((code_state->ip[-1] == MP_BC_SETUP_FINALLY) ? 1 : 0);
693 #else
694 PUSH_EXC_BLOCK((code_state->ip[0] == MP_BC_SETUP_FINALLY) ? 1 : 0);
695 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800696 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000697 }
Damience89a212013-10-15 22:25:17 +0100698
AZ Huangb1f692e2014-04-14 23:22:44 +0800699 ENTRY(MP_BC_END_FINALLY):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200700 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800701 // not fully implemented
702 // if TOS is an exception, reraises the exception (3 values on TOS)
703 // if TOS is None, just pops it and continues
704 // if TOS is an integer, does something else
705 // else error
706 if (mp_obj_is_exception_type(TOP())) {
Damien George66ae8c92014-04-17 16:50:23 +0100707 RAISE(sp[-1]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800708 }
709 if (TOP() == mp_const_none) {
Damien George20006db2014-01-18 14:10:48 +0000710 sp--;
Damien George5e1d9932015-03-25 22:20:37 +0000711 } else {
712 assert(MP_OBJ_IS_SMALL_INT(TOP()));
AZ Huangb1f692e2014-04-14 23:22:44 +0800713 // We finished "finally" coroutine and now dispatch back
714 // to our caller, based on TOS value
715 mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());
Damien George5e1d9932015-03-25 22:20:37 +0000716 if (reason == UNWIND_RETURN) {
717 goto unwind_return;
718 } else {
719 assert(reason == UNWIND_JUMP);
720 goto unwind_jump;
AZ Huangb1f692e2014-04-14 23:22:44 +0800721 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800722 }
723 DISPATCH();
724
725 ENTRY(MP_BC_GET_ITER):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200726 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800727 SET_TOP(mp_getiter(TOP()));
728 DISPATCH();
729
Damien Georged8675542014-05-25 22:58:04 +0100730 ENTRY(MP_BC_FOR_ITER): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200731 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800732 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgec60a2612014-06-01 12:32:28 +0100733 code_state->sp = sp;
Paul Sokolovskyc48d6f72014-05-11 20:32:39 +0300734 assert(TOP());
Damien Georged8675542014-05-25 22:58:04 +0100735 mp_obj_t value = mp_iternext_allow_raise(TOP());
736 if (value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800737 --sp; // pop the exhausted iterator
Damien Georgecd97a432014-12-02 19:25:10 +0000738 ip += ulab; // jump to after for-block
AZ Huangb1f692e2014-04-14 23:22:44 +0800739 } else {
Damien Georged8675542014-05-25 22:58:04 +0100740 PUSH(value); // push the next iteration value
AZ Huangb1f692e2014-04-14 23:22:44 +0800741 }
742 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100743 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800744
745 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
746 ENTRY(MP_BC_POP_BLOCK):
747 // we are exiting an exception handler, so pop the last one of the exception-stack
748 assert(exc_sp >= exc_stack);
749 POP_EXC_BLOCK();
750 DISPATCH();
751
752 // matched against: SETUP_EXCEPT
753 ENTRY(MP_BC_POP_EXCEPT):
754 // TODO need to work out how blocks work etc
755 // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
756 assert(exc_sp >= exc_stack);
757 assert(currently_in_except_block);
758 //sp = (mp_obj_t*)(*exc_sp--);
759 //exc_sp--; // discard ip
760 POP_EXC_BLOCK();
761 //sp -= 3; // pop 3 exception values
762 DISPATCH();
763
Damien Georgecd97a432014-12-02 19:25:10 +0000764 ENTRY(MP_BC_BUILD_TUPLE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200765 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800766 DECODE_UINT;
767 sp -= unum - 1;
768 SET_TOP(mp_obj_new_tuple(unum, sp));
769 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000770 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800771
Damien Georgecd97a432014-12-02 19:25:10 +0000772 ENTRY(MP_BC_BUILD_LIST): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200773 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800774 DECODE_UINT;
775 sp -= unum - 1;
776 SET_TOP(mp_obj_new_list(unum, sp));
777 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000778 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800779
Damien Georgecd97a432014-12-02 19:25:10 +0000780 ENTRY(MP_BC_LIST_APPEND): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200781 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800782 DECODE_UINT;
783 // I think it's guaranteed by the compiler that sp[unum] is a list
784 mp_obj_list_append(sp[-unum], sp[0]);
785 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_BUILD_MAP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200790 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800791 DECODE_UINT;
792 PUSH(mp_obj_new_dict(unum));
793 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000794 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800795
796 ENTRY(MP_BC_STORE_MAP):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200797 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800798 sp -= 2;
799 mp_obj_dict_store(sp[0], sp[2], sp[1]);
800 DISPATCH();
801
Damien Georgecd97a432014-12-02 19:25:10 +0000802 ENTRY(MP_BC_MAP_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 - 1] is a map
806 mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]);
807 sp -= 2;
808 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000809 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800810
Damien George3ebd4d02014-06-01 13:46:47 +0100811#if MICROPY_PY_BUILTINS_SET
Damien Georgecd97a432014-12-02 19:25:10 +0000812 ENTRY(MP_BC_BUILD_SET): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200813 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800814 DECODE_UINT;
815 sp -= unum - 1;
816 SET_TOP(mp_obj_new_set(unum, sp));
817 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000818 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800819
Damien Georgecd97a432014-12-02 19:25:10 +0000820 ENTRY(MP_BC_SET_ADD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200821 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800822 DECODE_UINT;
823 // I think it's guaranteed by the compiler that sp[-unum] is a set
824 mp_obj_set_store(sp[-unum], sp[0]);
825 sp--;
826 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000827 }
Damien George3ebd4d02014-06-01 13:46:47 +0100828#endif
Damienc12aa462013-10-16 20:57:49 +0100829
Damien Georgefb510b32014-06-01 13:32:54 +0100830#if MICROPY_PY_BUILTINS_SLICE
Damien Georgecd97a432014-12-02 19:25:10 +0000831 ENTRY(MP_BC_BUILD_SLICE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200832 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800833 DECODE_UINT;
834 if (unum == 2) {
Damien Georged8675542014-05-25 22:58:04 +0100835 mp_obj_t stop = POP();
836 mp_obj_t start = TOP();
837 SET_TOP(mp_obj_new_slice(start, stop, mp_const_none));
AZ Huangb1f692e2014-04-14 23:22:44 +0800838 } else {
Damien Georged8675542014-05-25 22:58:04 +0100839 mp_obj_t step = POP();
840 mp_obj_t stop = POP();
841 mp_obj_t start = TOP();
842 SET_TOP(mp_obj_new_slice(start, stop, step));
AZ Huangb1f692e2014-04-14 23:22:44 +0800843 }
844 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000845 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800846#endif
847
Damien Georgecd97a432014-12-02 19:25:10 +0000848 ENTRY(MP_BC_UNPACK_SEQUENCE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200849 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800850 DECODE_UINT;
851 mp_unpack_sequence(sp[0], unum, sp);
852 sp += unum - 1;
853 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000854 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800855
Damien Georgecd97a432014-12-02 19:25:10 +0000856 ENTRY(MP_BC_UNPACK_EX): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200857 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800858 DECODE_UINT;
859 mp_unpack_ex(sp[0], unum, sp);
860 sp += (unum & 0xff) + ((unum >> 8) & 0xff);
861 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000862 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800863
Damien Georgecd97a432014-12-02 19:25:10 +0000864 ENTRY(MP_BC_MAKE_FUNCTION): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800865 DECODE_PTR;
Damien Georgecd97a432014-12-02 19:25:10 +0000866 PUSH(mp_make_function_from_raw_code(ptr, MP_OBJ_NULL, MP_OBJ_NULL));
AZ Huangb1f692e2014-04-14 23:22:44 +0800867 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000868 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800869
Damien Georged8675542014-05-25 22:58:04 +0100870 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800871 DECODE_PTR;
872 // Stack layout: def_tuple def_dict <- TOS
Damien Georged8675542014-05-25 22:58:04 +0100873 mp_obj_t def_dict = POP();
Damien Georgecd97a432014-12-02 19:25:10 +0000874 SET_TOP(mp_make_function_from_raw_code(ptr, TOP(), def_dict));
AZ Huangb1f692e2014-04-14 23:22:44 +0800875 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100876 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800877
Damien George3558f622014-04-20 17:50:40 +0100878 ENTRY(MP_BC_MAKE_CLOSURE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800879 DECODE_PTR;
Damien George40f3c022014-07-03 13:25:24 +0100880 mp_uint_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100881 // Stack layout: closed_overs <- TOS
882 sp -= n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000883 SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800884 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100885 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800886
Damien George3558f622014-04-20 17:50:40 +0100887 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800888 DECODE_PTR;
Damien George40f3c022014-07-03 13:25:24 +0100889 mp_uint_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100890 // Stack layout: def_tuple def_dict closed_overs <- TOS
891 sp -= 2 + n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000892 SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800893 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100894 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800895
Damien Georgecd97a432014-12-02 19:25:10 +0000896 ENTRY(MP_BC_CALL_FUNCTION): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200897 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800898 DECODE_UINT;
899 // unum & 0xff == n_positional
900 // (unum >> 8) & 0xff == n_keyword
901 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
Paul Sokolovsky20397572015-03-28 01:14:44 +0200902 #if MICROPY_STACKLESS
903 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
904 code_state->ip = ip;
905 code_state->sp = sp;
906 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
907 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 +0200908 if (new_state) {
909 new_state->prev = code_state;
910 code_state = new_state;
911 nlr_pop();
912 goto run_code_state;
913 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200914 #if MICROPY_STACKLESS_STRICT
915 else {
916 deep_recursion_error:
917 mp_exc_recursion_depth();
918 }
919 #endif
Paul Sokolovsky20397572015-03-28 01:14:44 +0200920 }
921 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800922 SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
923 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000924 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800925
Damien Georgecd97a432014-12-02 19:25:10 +0000926 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200927 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800928 DECODE_UINT;
929 // unum & 0xff == n_positional
930 // (unum >> 8) & 0xff == n_keyword
931 // We have folowing stack layout here:
932 // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
933 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200934 #if MICROPY_STACKLESS
935 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
936 code_state->ip = ip;
937 code_state->sp = sp;
938 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
939
Damien George12a5e172015-04-01 23:31:30 +0100940 mp_call_args_t out_args;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200941 mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args);
942
943 mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
944 out_args.n_args, out_args.n_kw, out_args.args);
945 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
946 if (new_state) {
947 new_state->prev = code_state;
948 code_state = new_state;
949 nlr_pop();
950 goto run_code_state;
951 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200952 #if MICROPY_STACKLESS_STRICT
953 else {
954 goto deep_recursion_error;
955 }
956 #endif
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200957 }
958 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800959 SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
960 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000961 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800962
Damien Georgecd97a432014-12-02 19:25:10 +0000963 ENTRY(MP_BC_CALL_METHOD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200964 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800965 DECODE_UINT;
966 // unum & 0xff == n_positional
967 // (unum >> 8) & 0xff == n_keyword
968 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200969 #if MICROPY_STACKLESS
970 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
971 code_state->ip = ip;
972 code_state->sp = sp;
973 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
974
975 mp_uint_t n_args = unum & 0xff;
976 mp_uint_t n_kw = (unum >> 8) & 0xff;
Damien George7a30e872015-12-17 12:32:41 +0000977 int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1;
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200978
979 mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust);
980 if (new_state) {
981 new_state->prev = code_state;
982 code_state = new_state;
983 nlr_pop();
984 goto run_code_state;
985 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200986 #if MICROPY_STACKLESS_STRICT
987 else {
988 goto deep_recursion_error;
989 }
990 #endif
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200991 }
992 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800993 SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
994 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000995 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800996
Damien Georgecd97a432014-12-02 19:25:10 +0000997 ENTRY(MP_BC_CALL_METHOD_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200998 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800999 DECODE_UINT;
1000 // unum & 0xff == n_positional
1001 // (unum >> 8) & 0xff == n_keyword
1002 // We have folowing stack layout here:
1003 // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
1004 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001005 #if MICROPY_STACKLESS
1006 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
1007 code_state->ip = ip;
1008 code_state->sp = sp;
1009 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
1010
Damien George12a5e172015-04-01 23:31:30 +01001011 mp_call_args_t out_args;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001012 mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args);
1013
1014 mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
1015 out_args.n_args, out_args.n_kw, out_args.args);
1016 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
1017 if (new_state) {
1018 new_state->prev = code_state;
1019 code_state = new_state;
1020 nlr_pop();
1021 goto run_code_state;
1022 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +02001023 #if MICROPY_STACKLESS_STRICT
1024 else {
1025 goto deep_recursion_error;
1026 }
1027 #endif
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001028 }
1029 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001030 SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
1031 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +00001032 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001033
1034 ENTRY(MP_BC_RETURN_VALUE):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001035 MARK_EXC_IP_SELECTIVE();
Damien George80473402015-12-24 12:47:39 +00001036 // These next 3 lines pop a try-finally exception handler, if one
1037 // is there on the exception stack. Without this the finally block
1038 // is executed a second time when the return is executed, because
1039 // the try-finally exception handler is still on the stack.
1040 // TODO Possibly find a better way to handle this case.
1041 if (currently_in_except_block) {
1042 POP_EXC_BLOCK();
1043 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001044unwind_return:
1045 while (exc_sp >= exc_stack) {
Damien George74eb44c2014-12-22 12:49:57 +00001046 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
Damien George4bf3f2d2015-10-15 17:48:28 +01001047 // Getting here the stack looks like:
1048 // (..., X, [iter0, iter1, ...,] ret_val)
1049 // where X is pointed to by exc_sp->val_sp and in the case
1050 // of a "with" block contains the context manager info.
1051 // There may be 0 or more for-iterators between X and the
1052 // return value, and these must be removed before control can
1053 // pass to the finally code. We simply copy the ret_value down
1054 // over these iterators, if they exist. If they don't then the
1055 // following is a null operation.
1056 mp_obj_t *finally_sp = MP_TAGPTR_PTR(exc_sp->val_sp);
1057 finally_sp[1] = sp[0];
1058 sp = &finally_sp[1];
AZ Huangb1f692e2014-04-14 23:22:44 +08001059 // We're going to run "finally" code as a coroutine
1060 // (not calling it recursively). Set up a sentinel
1061 // on a stack so it can return back to us when it is
Damien George4bf3f2d2015-10-15 17:48:28 +01001062 // done (when WITH_CLEANUP or END_FINALLY reached).
AZ Huangb1f692e2014-04-14 23:22:44 +08001063 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
1064 ip = exc_sp->handler;
AZ Huangb1f692e2014-04-14 23:22:44 +08001065 exc_sp--;
1066 goto dispatch_loop;
1067 }
1068 exc_sp--;
1069 }
1070 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001071 code_state->sp = sp;
AZ Huangb1f692e2014-04-14 23:22:44 +08001072 assert(exc_sp == exc_stack - 1);
Damien George40d84302016-02-15 22:46:21 +00001073 MICROPY_VM_HOOK_RETURN
Paul Sokolovsky20397572015-03-28 01:14:44 +02001074 #if MICROPY_STACKLESS
1075 if (code_state->prev != NULL) {
1076 mp_obj_t res = *sp;
1077 mp_globals_set(code_state->old_globals);
1078 code_state = code_state->prev;
1079 *code_state->sp = res;
1080 goto run_code_state;
1081 }
1082 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001083 return MP_VM_RETURN_NORMAL;
1084
Damien Georged8675542014-05-25 22:58:04 +01001085 ENTRY(MP_BC_RAISE_VARARGS): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001086 MARK_EXC_IP_SELECTIVE();
Damien Georgecd97a432014-12-02 19:25:10 +00001087 mp_uint_t unum = *ip++;
Damien Georged8675542014-05-25 22:58:04 +01001088 mp_obj_t obj;
Paul Sokolovsky2ff2ea52015-09-01 10:35:58 +03001089 if (unum == 2) {
1090 mp_warning("exception chaining not supported");
1091 // ignore (pop) "from" argument
1092 sp--;
1093 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001094 if (unum == 0) {
1095 // search for the inner-most previous exception, to reraise it
Damien Georged8675542014-05-25 22:58:04 +01001096 obj = MP_OBJ_NULL;
AZ Huangb1f692e2014-04-14 23:22:44 +08001097 for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
Damien George999cedb2015-11-27 17:01:44 +00001098 if (e->prev_exc != NULL) {
1099 obj = MP_OBJ_FROM_PTR(e->prev_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +08001100 break;
1101 }
1102 }
Damien Georged8675542014-05-25 22:58:04 +01001103 if (obj == MP_OBJ_NULL) {
1104 obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
1105 RAISE(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001106 }
1107 } else {
Damien Georged8675542014-05-25 22:58:04 +01001108 obj = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +08001109 }
Damien Georged8675542014-05-25 22:58:04 +01001110 obj = mp_make_raise_obj(obj);
1111 RAISE(obj);
1112 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001113
1114 ENTRY(MP_BC_YIELD_VALUE):
1115yield:
1116 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001117 code_state->ip = ip;
1118 code_state->sp = sp;
1119 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +08001120 return MP_VM_RETURN_YIELD;
1121
1122 ENTRY(MP_BC_YIELD_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001123 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001124//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
1125#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
Damien George999cedb2015-11-27 17:01:44 +00001126#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { RAISE(t); }
AZ Huangb1f692e2014-04-14 23:22:44 +08001127 mp_vm_return_kind_t ret_kind;
Damien Georged8675542014-05-25 22:58:04 +01001128 mp_obj_t send_value = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +08001129 mp_obj_t t_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +01001130 mp_obj_t ret_value;
AZ Huangb1f692e2014-04-14 23:22:44 +08001131 if (inject_exc != MP_OBJ_NULL) {
1132 t_exc = inject_exc;
1133 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +01001134 ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001135 } else {
Damien Georged8675542014-05-25 22:58:04 +01001136 ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001137 }
1138
1139 if (ret_kind == MP_VM_RETURN_YIELD) {
1140 ip--;
Damien Georged8675542014-05-25 22:58:04 +01001141 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001142 goto yield;
1143 }
1144 if (ret_kind == MP_VM_RETURN_NORMAL) {
1145 // Pop exhausted gen
1146 sp--;
Paul Sokolovskyeff85bb2016-04-28 01:54:23 +03001147 // TODO: When ret_value can be MP_OBJ_NULL here??
1148 if (ret_value == MP_OBJ_NULL || ret_value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +08001149 // Optimize StopIteration
1150 // TODO: get StopIteration's value
1151 PUSH(mp_const_none);
1152 } else {
Damien Georged8675542014-05-25 22:58:04 +01001153 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001154 }
1155
1156 // If we injected GeneratorExit downstream, then even
1157 // if it was swallowed, we re-raise GeneratorExit
1158 GENERATOR_EXIT_IF_NEEDED(t_exc);
1159 DISPATCH();
1160 }
1161 if (ret_kind == MP_VM_RETURN_EXCEPTION) {
1162 // Pop exhausted gen
1163 sp--;
Damien George999cedb2015-11-27 17:01:44 +00001164 if (EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
Damien Georged8675542014-05-25 22:58:04 +01001165 PUSH(mp_obj_exception_get_value(ret_value));
AZ Huangb1f692e2014-04-14 23:22:44 +08001166 // If we injected GeneratorExit downstream, then even
1167 // if it was swallowed, we re-raise GeneratorExit
1168 GENERATOR_EXIT_IF_NEEDED(t_exc);
1169 DISPATCH();
1170 } else {
Damien Georged8675542014-05-25 22:58:04 +01001171 RAISE(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001172 }
1173 }
Damien429d7192013-10-04 19:53:11 +01001174 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001175
Damien Georged8675542014-05-25 22:58:04 +01001176 ENTRY(MP_BC_IMPORT_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001177 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001178 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001179 mp_obj_t obj = POP();
1180 SET_TOP(mp_import_name(qst, obj, TOP()));
AZ Huangb1f692e2014-04-14 23:22:44 +08001181 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001182 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001183
Damien Georged8675542014-05-25 22:58:04 +01001184 ENTRY(MP_BC_IMPORT_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001185 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001186 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001187 mp_obj_t obj = mp_import_from(TOP(), qst);
1188 PUSH(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001189 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001190 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001191
1192 ENTRY(MP_BC_IMPORT_STAR):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001193 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001194 mp_import_all(POP());
1195 DISPATCH();
1196
Damien George8456cc02014-10-25 16:43:46 +01001197#if MICROPY_OPT_COMPUTED_GOTO
1198 ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):
1199 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1200 DISPATCH();
1201
1202 ENTRY(MP_BC_LOAD_FAST_MULTI):
1203 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1204 goto load_check;
1205
1206 ENTRY(MP_BC_STORE_FAST_MULTI):
1207 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1208 DISPATCH();
1209
1210 ENTRY(MP_BC_UNARY_OP_MULTI):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001211 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001212 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1213 DISPATCH();
1214
1215 ENTRY(MP_BC_BINARY_OP_MULTI): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001216 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001217 mp_obj_t rhs = POP();
1218 mp_obj_t lhs = TOP();
1219 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1220 DISPATCH();
1221 }
1222
1223 ENTRY_DEFAULT:
Paul Sokolovsky74957502014-12-28 07:17:43 +02001224 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001225#else
1226 ENTRY_DEFAULT:
1227 if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
1228 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1229 DISPATCH();
1230 } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
1231 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1232 goto load_check;
1233 } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
1234 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1235 DISPATCH();
Damien Georgebdbe8c92015-12-08 12:28:11 +00001236 } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 7) {
Damien George8456cc02014-10-25 16:43:46 +01001237 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1238 DISPATCH();
Damien Georgec5029bc2015-06-13 22:00:10 +01001239 } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) {
Damien George8456cc02014-10-25 16:43:46 +01001240 mp_obj_t rhs = POP();
1241 mp_obj_t lhs = TOP();
1242 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1243 DISPATCH();
1244 } else
1245#endif
1246 {
Damien Georged8675542014-05-25 22:58:04 +01001247 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
AZ Huangb1f692e2014-04-14 23:22:44 +08001248 nlr_pop();
Damien Georged8675542014-05-25 22:58:04 +01001249 fastn[0] = obj;
AZ Huangb1f692e2014-04-14 23:22:44 +08001250 return MP_VM_RETURN_EXCEPTION;
Damien Georged8675542014-05-25 22:58:04 +01001251 }
Damien George66ae8c92014-04-17 16:50:23 +01001252
Damien George58ebde42014-05-21 20:32:59 +01001253#if !MICROPY_OPT_COMPUTED_GOTO
AZ Huang9309d992014-04-15 15:57:01 +08001254 } // switch
AZ Huangb1f692e2014-04-14 23:22:44 +08001255#endif
Damien George124df6f2014-10-25 18:19:55 +01001256
1257pending_exception_check:
Damien George40d84302016-02-15 22:46:21 +00001258 MICROPY_VM_HOOK_LOOP
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001259 if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001260 MARK_EXC_IP_SELECTIVE();
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001261 mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
1262 MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
Damien George124df6f2014-10-25 18:19:55 +01001263 RAISE(obj);
1264 }
Damien George124df6f2014-10-25 18:19:55 +01001265
Damien George66ae8c92014-04-17 16:50:23 +01001266 } // for loop
Damien429d7192013-10-04 19:53:11 +01001267
Damience89a212013-10-15 22:25:17 +01001268 } else {
Damien George66ae8c92014-04-17 16:50:23 +01001269exception_handler:
Damience89a212013-10-15 22:25:17 +01001270 // exception occurred
Damien429d7192013-10-04 19:53:11 +01001271
Paul Sokolovsky8b85d142015-04-25 03:17:41 +03001272 #if MICROPY_PY_SYS_EXC_INFO
1273 MP_STATE_VM(cur_exception) = nlr.ret_val;
1274 #endif
1275
Damien Georgef89d6592014-12-29 00:29:59 +00001276 #if SELECTIVE_EXC_IP
1277 // with selective ip, we store the ip 1 byte past the opcode, so move ptr back
1278 code_state->ip -= 1;
1279 #endif
1280
Damien George999cedb2015-11-27 17:01:44 +00001281 if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
Paul Sokolovskya7c02c42015-05-10 17:18:10 +03001282 if (code_state->ip) {
1283 // check if it's a StopIteration within a for block
1284 if (*code_state->ip == MP_BC_FOR_ITER) {
1285 const byte *ip = code_state->ip + 1;
1286 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
1287 code_state->ip = ip + ulab; // jump to after for-block
1288 code_state->sp -= 1; // pop the exhausted iterator
1289 goto outer_dispatch_loop; // continue with dispatch loop
Paul Sokolovsky6738c1d2015-05-11 02:59:25 +03001290 } else if (*code_state->ip == MP_BC_YIELD_FROM) {
1291 // StopIteration inside yield from call means return a value of
1292 // yield from, so inject exception's value as yield from's result
Damien George999cedb2015-11-27 17:01:44 +00001293 *++code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));
Paul Sokolovsky6738c1d2015-05-11 02:59:25 +03001294 code_state->ip++; // yield from is over, move to next instruction
1295 goto outer_dispatch_loop; // continue with dispatch loop
Paul Sokolovskya7c02c42015-05-10 17:18:10 +03001296 }
1297 }
Damien George9e6e9352014-03-26 18:37:06 +00001298 }
1299
Paul Sokolovsky20397572015-03-28 01:14:44 +02001300#if MICROPY_STACKLESS
1301unwind_loop:
1302#endif
Damien George08335002014-01-18 23:24:36 +00001303 // set file and line number that the exception occurred at
Paul Sokolovsky382e8ee2014-01-30 13:49:18 +02001304 // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
1305 // But consider how to handle nested exceptions.
Damien George6902eed2014-04-04 10:52:59 +00001306 // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
Damien George999cedb2015-11-27 17:01:44 +00001307 if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
Damien Georgeb534e1b2014-09-04 14:44:01 +01001308 const byte *ip = code_state->code_info;
1309 mp_uint_t code_info_size = mp_decode_uint(&ip);
Damien Georgec8e9c0d2015-11-02 17:27:18 +00001310 #if MICROPY_PERSISTENT_CODE
1311 qstr block_name = ip[0] | (ip[1] << 8);
1312 qstr source_file = ip[2] | (ip[3] << 8);
1313 ip += 4;
1314 #else
Damien Georgeb534e1b2014-09-04 14:44:01 +01001315 qstr block_name = mp_decode_uint(&ip);
1316 qstr source_file = mp_decode_uint(&ip);
Damien Georgec8e9c0d2015-11-02 17:27:18 +00001317 #endif
Damien George3d2daa22016-01-02 22:04:12 +00001318 size_t bc = code_state->ip - code_state->code_info - code_info_size;
1319 size_t source_line = 1;
1320 size_t c;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001321 while ((c = *ip)) {
Damien Georgeb427d6a2014-08-26 23:35:57 +01001322 mp_uint_t b, l;
1323 if ((c & 0x80) == 0) {
1324 // 0b0LLBBBBB encoding
1325 b = c & 0x1f;
1326 l = c >> 5;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001327 ip += 1;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001328 } else {
1329 // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
1330 b = c & 0xf;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001331 l = ((c << 4) & 0x700) | ip[1];
1332 ip += 2;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001333 }
1334 if (bc >= b) {
1335 bc -= b;
1336 source_line += l;
1337 } else {
1338 // found source line corresponding to bytecode offset
1339 break;
Paul Sokolovsky411732e2014-06-02 18:24:34 +03001340 }
Damien George08335002014-01-18 23:24:36 +00001341 }
Damien George999cedb2015-11-27 17:01:44 +00001342 mp_obj_exception_add_traceback(MP_OBJ_FROM_PTR(nlr.ret_val), source_file, source_line, block_name);
Damien George08335002014-01-18 23:24:36 +00001343 }
1344
Damien8f9e2ee2013-12-29 16:54:59 +00001345 while (currently_in_except_block) {
1346 // nested exception
1347
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001348 assert(exc_sp >= exc_stack);
Damien8f9e2ee2013-12-29 16:54:59 +00001349
1350 // TODO make a proper message for nested exception
1351 // at the moment we are just raising the very last exception (the one that caused the nested exception)
1352
1353 // move up to previous exception handler
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +02001354 POP_EXC_BLOCK();
Damien8f9e2ee2013-12-29 16:54:59 +00001355 }
1356
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001357 if (exc_sp >= exc_stack) {
Damien8f9e2ee2013-12-29 16:54:59 +00001358 // set flag to indicate that we are now handling an exception
1359 currently_in_except_block = 1;
1360
Damience89a212013-10-15 22:25:17 +01001361 // catch exception and pass to byte code
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001362 code_state->ip = exc_sp->handler;
Damien George66ae8c92014-04-17 16:50:23 +01001363 mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
Damien Georged7592a12014-03-30 00:54:48 +00001364 // save this exception in the stack so it can be used in a reraise, if needed
1365 exc_sp->prev_exc = nlr.ret_val;
Damienc9f91972013-10-15 23:46:01 +01001366 // push(traceback, exc-val, exc-type)
Damiend99b0522013-12-21 18:17:45 +00001367 PUSH(mp_const_none);
Damien George999cedb2015-11-27 17:01:44 +00001368 PUSH(MP_OBJ_FROM_PTR(nlr.ret_val));
1369 PUSH(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type));
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001370 code_state->sp = sp;
Damien8f9e2ee2013-12-29 16:54:59 +00001371
Paul Sokolovsky20397572015-03-28 01:14:44 +02001372 #if MICROPY_STACKLESS
1373 } else if (code_state->prev != NULL) {
1374 mp_globals_set(code_state->old_globals);
1375 code_state = code_state->prev;
1376 fastn = &code_state->state[code_state->n_state - 1];
1377 exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
1378 // variables that are visible to the exception handler (declared volatile)
1379 currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
1380 exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
1381 goto unwind_loop;
1382
1383 #endif
Damience89a212013-10-15 22:25:17 +01001384 } else {
Damien Georgec8f78bc2014-02-15 22:55:00 +00001385 // propagate exception to higher level
1386 // TODO what to do about ip and sp? they don't really make sense at this point
Damien George999cedb2015-11-27 17:01:44 +00001387 fastn[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // must put exception here because sp is invalid
Damien Georgec8f78bc2014-02-15 22:55:00 +00001388 return MP_VM_RETURN_EXCEPTION;
Damience89a212013-10-15 22:25:17 +01001389 }
Damien429d7192013-10-04 19:53:11 +01001390 }
1391 }
1392}