blob: 97f344b08e8e8c5c6311b50aba126d131041ff0d [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 Georgecc4c1ad2017-01-27 12:34:09 +110041#define TRACE(ip) printf("sp=%d ", (int)(sp - code_state->sp)); mp_bytecode_print2(ip, 1, code_state->const_table);
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)
Damien George101886f2017-02-16 16:48:33 +110066#define DECODE_ULABEL size_t ulab = (ip[0] | (ip[1] << 8)); ip += 2
67#define DECODE_SLABEL size_t slab = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2
Damien Georgec8e9c0d2015-11-02 17:27:18 +000068
69#if MICROPY_PERSISTENT_CODE
70
71#define DECODE_QSTR \
72 qstr qst = ip[0] | ip[1] << 8; \
73 ip += 2;
74#define DECODE_PTR \
75 DECODE_UINT; \
Damien George999cedb2015-11-27 17:01:44 +000076 void *ptr = (void*)(uintptr_t)code_state->const_table[unum]
77#define DECODE_OBJ \
78 DECODE_UINT; \
79 mp_obj_t obj = (mp_obj_t)code_state->const_table[unum]
Damien Georgec8e9c0d2015-11-02 17:27:18 +000080
81#else
82
Damien Georged8675542014-05-25 22:58:04 +010083#define DECODE_QSTR qstr qst = 0; \
Paul Sokolovsky0f96ec82014-02-18 21:21:22 +020084 do { \
85 qst = (qst << 7) + (*ip & 0x7f); \
Damien Georged8675542014-05-25 22:58:04 +010086 } while ((*ip++ & 0x80) != 0)
Damien Georgecd97a432014-12-02 19:25:10 +000087#define DECODE_PTR \
Damien George999cedb2015-11-27 17:01:44 +000088 ip = (byte*)MP_ALIGN(ip, sizeof(void*)); \
89 void *ptr = *(void**)ip; \
90 ip += sizeof(void*)
91#define DECODE_OBJ \
92 ip = (byte*)MP_ALIGN(ip, sizeof(mp_obj_t)); \
93 mp_obj_t obj = *(mp_obj_t*)ip; \
94 ip += sizeof(mp_obj_t)
Damien Georgec8e9c0d2015-11-02 17:27:18 +000095
96#endif
97
Damien George20006db2014-01-18 14:10:48 +000098#define PUSH(val) *++sp = (val)
99#define POP() (*sp--)
Damiendb4c3612013-12-10 17:27:24 +0000100#define TOP() (*sp)
101#define SET_TOP(val) *sp = (val)
Damien429d7192013-10-04 19:53:11 +0100102
Paul Sokolovskyae2c81f2015-04-26 01:20:49 +0300103#if MICROPY_PY_SYS_EXC_INFO
Damien George999cedb2015-11-27 17:01:44 +0000104#define CLEAR_SYS_EXC_INFO() MP_STATE_VM(cur_exception) = NULL;
Paul Sokolovskyae2c81f2015-04-26 01:20:49 +0300105#else
106#define CLEAR_SYS_EXC_INFO()
107#endif
108
Damien George74eb44c2014-12-22 12:49:57 +0000109#define PUSH_EXC_BLOCK(with_or_finally) do { \
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +0200110 DECODE_ULABEL; /* except labels are always forward */ \
111 ++exc_sp; \
Damien Georgecd97a432014-12-02 19:25:10 +0000112 exc_sp->handler = ip + ulab; \
Damien George74eb44c2014-12-22 12:49:57 +0000113 exc_sp->val_sp = MP_TAGPTR_MAKE(sp, ((with_or_finally) << 1) | currently_in_except_block); \
Damien George999cedb2015-11-27 17:01:44 +0000114 exc_sp->prev_exc = NULL; \
Damien Georgecd97a432014-12-02 19:25:10 +0000115 currently_in_except_block = 0; /* in a try block now */ \
116} while (0)
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +0200117
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +0200118#define POP_EXC_BLOCK() \
Damien George74eb44c2014-12-22 12:49:57 +0000119 currently_in_except_block = MP_TAGPTR_TAG0(exc_sp->val_sp); /* restore previous state */ \
Paul Sokolovskyae2c81f2015-04-26 01:20:49 +0300120 exc_sp--; /* pop back to previous exception handler */ \
121 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 +0200122
Damien George20006db2014-01-18 14:10:48 +0000123// fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)
124// sp points to bottom of stack which grows up
Damien Georgec8f78bc2014-02-15 22:55:00 +0000125// returns:
126// MP_VM_RETURN_NORMAL, sp valid, return value in *sp
127// MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
128// MP_VM_RETURN_EXCEPTION, exception in fastn[0]
Damien George581a59a2016-08-27 23:21:00 +1000129mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc) {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200130#define SELECTIVE_EXC_IP (0)
131#if SELECTIVE_EXC_IP
Damien Georgef89d6592014-12-29 00:29:59 +0000132#define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */
Paul Sokolovsky74957502014-12-28 07:17:43 +0200133#define MARK_EXC_IP_GLOBAL()
134#else
135#define MARK_EXC_IP_SELECTIVE()
Damien Georgef89d6592014-12-29 00:29:59 +0000136#define MARK_EXC_IP_GLOBAL() { code_state->ip = ip; } /* stores ip pointing to last opcode */
Paul Sokolovsky74957502014-12-28 07:17:43 +0200137#endif
Damien George58ebde42014-05-21 20:32:59 +0100138#if MICROPY_OPT_COMPUTED_GOTO
Damien George51dfcb42015-01-01 20:27:54 +0000139 #include "py/vmentrytable.h"
AZ Huang9309d992014-04-15 15:57:01 +0800140 #define DISPATCH() do { \
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +0300141 TRACE(ip); \
Paul Sokolovsky74957502014-12-28 07:17:43 +0200142 MARK_EXC_IP_GLOBAL(); \
Damien Georgedb128912014-04-27 18:19:06 +0100143 goto *entry_table[*ip++]; \
Damien George4dea9222015-04-09 15:29:54 +0000144 } while (0)
Damien George124df6f2014-10-25 18:19:55 +0100145 #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
AZ Huang9309d992014-04-15 15:57:01 +0800146 #define ENTRY(op) entry_##op
147 #define ENTRY_DEFAULT entry_default
AZ Huangb1f692e2014-04-14 23:22:44 +0800148#else
AZ Huang9309d992014-04-15 15:57:01 +0800149 #define DISPATCH() break
Damien George124df6f2014-10-25 18:19:55 +0100150 #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
AZ Huang9309d992014-04-15 15:57:01 +0800151 #define ENTRY(op) case op
152 #define ENTRY_DEFAULT default
AZ Huangb1f692e2014-04-14 23:22:44 +0800153#endif
154
Damien George66ae8c92014-04-17 16:50:23 +0100155 // nlr_raise needs to be implemented as a goto, so that the C compiler's flow analyser
156 // sees that it's possible for us to jump from the dispatch loop to the exception
157 // handler. Without this, the code may have a different stack layout in the dispatch
158 // loop and the exception handler, leading to very obscure bugs.
Damien George999cedb2015-11-27 17:01:44 +0000159 #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 +0100160
Paul Sokolovsky20397572015-03-28 01:14:44 +0200161#if MICROPY_STACKLESS
162run_code_state: ;
163#endif
Damien Georgeaabd83e2014-06-07 14:16:08 +0100164 // Pointers which are constant for particular invocation of mp_execute_bytecode()
stijn36cc84a2015-04-09 11:34:08 +0200165 mp_obj_t * /*const*/ fastn = &code_state->state[code_state->n_state - 1];
166 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 +0300167
Damien George66ae8c92014-04-17 16:50:23 +0100168 // variables that are visible to the exception handler (declared volatile)
Damien George74eb44c2014-12-22 12:49:57 +0000169 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 +0300170 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 +0100171
Damien Georgef6c22a02017-02-06 10:50:43 +1100172 #if MICROPY_PY_THREAD_GIL && MICROPY_PY_THREAD_GIL_VM_DIVISOR
173 // This needs to be volatile and outside the VM loop so it persists across handling
174 // of any exceptions. Otherwise it's possible that the VM never gives up the GIL.
175 volatile int gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
176 #endif
177
Damience89a212013-10-15 22:25:17 +0100178 // outer exception handling loop
Damien429d7192013-10-04 19:53:11 +0100179 for (;;) {
Damien George66ae8c92014-04-17 16:50:23 +0100180 nlr_buf_t nlr;
Damien George9e6e9352014-03-26 18:37:06 +0000181outer_dispatch_loop:
Damience89a212013-10-15 22:25:17 +0100182 if (nlr_push(&nlr) == 0) {
Damien George66ae8c92014-04-17 16:50:23 +0100183 // local variables that are not visible to the exception handler
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300184 const byte *ip = code_state->ip;
185 mp_obj_t *sp = code_state->sp;
Damien Georged8675542014-05-25 22:58:04 +0100186 mp_obj_t obj_shared;
Damien George40d84302016-02-15 22:46:21 +0000187 MICROPY_VM_HOOK_INIT
Damien George66ae8c92014-04-17 16:50:23 +0100188
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200189 // If we have exception to inject, now that we finish setting up
190 // execution context, raise it. This works as if RAISE_VARARGS
191 // bytecode was executed.
Paul Sokolovskycf21a4e2014-03-26 17:36:12 +0200192 // Injecting exc into yield from generator is a special case,
193 // handled by MP_BC_YIELD_FROM itself
194 if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
Damien Georged8675542014-05-25 22:58:04 +0100195 mp_obj_t exc = inject_exc;
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200196 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100197 exc = mp_make_raise_obj(exc);
198 RAISE(exc);
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200199 }
Damien George66ae8c92014-04-17 16:50:23 +0100200
Damience89a212013-10-15 22:25:17 +0100201 // loop to execute byte code
202 for (;;) {
Paul Sokolovsky6472dea2014-02-01 00:55:05 +0200203dispatch_loop:
Damien George58ebde42014-05-21 20:32:59 +0100204#if MICROPY_OPT_COMPUTED_GOTO
AZ Huangb1f692e2014-04-14 23:22:44 +0800205 DISPATCH();
206#else
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +0300207 TRACE(ip);
Paul Sokolovsky74957502014-12-28 07:17:43 +0200208 MARK_EXC_IP_GLOBAL();
Damien Georgedb128912014-04-27 18:19:06 +0100209 switch (*ip++) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800210#endif
Damien429d7192013-10-04 19:53:11 +0100211
AZ Huangb1f692e2014-04-14 23:22:44 +0800212 ENTRY(MP_BC_LOAD_CONST_FALSE):
213 PUSH(mp_const_false);
214 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100215
AZ Huangb1f692e2014-04-14 23:22:44 +0800216 ENTRY(MP_BC_LOAD_CONST_NONE):
217 PUSH(mp_const_none);
218 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100219
AZ Huangb1f692e2014-04-14 23:22:44 +0800220 ENTRY(MP_BC_LOAD_CONST_TRUE):
221 PUSH(mp_const_true);
222 DISPATCH();
Damien Georgee9906ac2014-01-04 18:44:46 +0000223
AZ Huangb1f692e2014-04-14 23:22:44 +0800224 ENTRY(MP_BC_LOAD_CONST_SMALL_INT): {
Damien George40f3c022014-07-03 13:25:24 +0100225 mp_int_t num = 0;
AZ Huangb1f692e2014-04-14 23:22:44 +0800226 if ((ip[0] & 0x40) != 0) {
227 // Number is negative
228 num--;
Paul Sokolovsky047cd402014-02-19 15:47:59 +0200229 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800230 do {
231 num = (num << 7) | (*ip & 0x7f);
232 } while ((*ip++ & 0x80) != 0);
233 PUSH(MP_OBJ_NEW_SMALL_INT(num));
234 DISPATCH();
235 }
Damience89a212013-10-15 22:25:17 +0100236
Damien Georged8675542014-05-25 22:58:04 +0100237 ENTRY(MP_BC_LOAD_CONST_STRING): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800238 DECODE_QSTR;
Damien Georgeed570e42015-06-25 13:58:41 +0000239 PUSH(MP_OBJ_NEW_QSTR(qst));
AZ Huangb1f692e2014-04-14 23:22:44 +0800240 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100241 }
Damience89a212013-10-15 22:25:17 +0100242
Damien Georgedab13852015-01-13 15:55:54 +0000243 ENTRY(MP_BC_LOAD_CONST_OBJ): {
Damien George999cedb2015-11-27 17:01:44 +0000244 DECODE_OBJ;
245 PUSH(obj);
Damien Georgedab13852015-01-13 15:55:54 +0000246 DISPATCH();
247 }
248
AZ Huangb1f692e2014-04-14 23:22:44 +0800249 ENTRY(MP_BC_LOAD_NULL):
250 PUSH(MP_OBJ_NULL);
251 DISPATCH();
Damien George523b5752014-03-31 11:59:23 +0100252
Damien Georgecd97a432014-12-02 19:25:10 +0000253 ENTRY(MP_BC_LOAD_FAST_N): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800254 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100255 obj_shared = fastn[-unum];
AZ Huangb1f692e2014-04-14 23:22:44 +0800256 load_check:
Damien Georged8675542014-05-25 22:58:04 +0100257 if (obj_shared == MP_OBJ_NULL) {
258 local_name_error: {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200259 MARK_EXC_IP_SELECTIVE();
Damien Georged8675542014-05-25 22:58:04 +0100260 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment");
261 RAISE(obj);
262 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800263 }
Damien Georged8675542014-05-25 22:58:04 +0100264 PUSH(obj_shared);
AZ Huangb1f692e2014-04-14 23:22:44 +0800265 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000266 }
Damien George2bf7c092014-04-09 15:26:46 +0100267
Damien Georgecd97a432014-12-02 19:25:10 +0000268 ENTRY(MP_BC_LOAD_DEREF): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800269 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100270 obj_shared = mp_obj_cell_get(fastn[-unum]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800271 goto load_check;
Damien Georgecd97a432014-12-02 19:25:10 +0000272 }
Damien9ecbcff2013-12-11 00:41:43 +0000273
Damien George7ee91cf2015-01-06 12:51:39 +0000274 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100275 ENTRY(MP_BC_LOAD_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200276 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800277 DECODE_QSTR;
278 PUSH(mp_load_name(qst));
279 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100280 }
Damien George7ee91cf2015-01-06 12:51:39 +0000281 #else
282 ENTRY(MP_BC_LOAD_NAME): {
283 MARK_EXC_IP_SELECTIVE();
284 DECODE_QSTR;
285 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
286 mp_uint_t x = *ip;
287 if (x < MP_STATE_CTX(dict_locals)->map.alloc && MP_STATE_CTX(dict_locals)->map.table[x].key == key) {
288 PUSH(MP_STATE_CTX(dict_locals)->map.table[x].value);
289 } else {
290 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_locals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
291 if (elem != NULL) {
292 *(byte*)ip = (elem - &MP_STATE_CTX(dict_locals)->map.table[0]) & 0xff;
293 PUSH(elem->value);
294 } else {
295 PUSH(mp_load_name(MP_OBJ_QSTR_VALUE(key)));
296 }
297 }
298 ip++;
299 DISPATCH();
300 }
301 #endif
Damience89a212013-10-15 22:25:17 +0100302
Damien George7ee91cf2015-01-06 12:51:39 +0000303 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100304 ENTRY(MP_BC_LOAD_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200305 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800306 DECODE_QSTR;
307 PUSH(mp_load_global(qst));
308 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100309 }
Damien George7ee91cf2015-01-06 12:51:39 +0000310 #else
311 ENTRY(MP_BC_LOAD_GLOBAL): {
312 MARK_EXC_IP_SELECTIVE();
313 DECODE_QSTR;
314 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
315 mp_uint_t x = *ip;
316 if (x < MP_STATE_CTX(dict_globals)->map.alloc && MP_STATE_CTX(dict_globals)->map.table[x].key == key) {
317 PUSH(MP_STATE_CTX(dict_globals)->map.table[x].value);
318 } else {
319 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_globals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
320 if (elem != NULL) {
321 *(byte*)ip = (elem - &MP_STATE_CTX(dict_globals)->map.table[0]) & 0xff;
322 PUSH(elem->value);
323 } else {
324 PUSH(mp_load_global(MP_OBJ_QSTR_VALUE(key)));
325 }
326 }
327 ip++;
328 DISPATCH();
329 }
330 #endif
Damience89a212013-10-15 22:25:17 +0100331
Damien George7ee91cf2015-01-06 12:51:39 +0000332 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100333 ENTRY(MP_BC_LOAD_ATTR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200334 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800335 DECODE_QSTR;
336 SET_TOP(mp_load_attr(TOP(), qst));
337 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100338 }
Damien George7ee91cf2015-01-06 12:51:39 +0000339 #else
340 ENTRY(MP_BC_LOAD_ATTR): {
341 MARK_EXC_IP_SELECTIVE();
342 DECODE_QSTR;
343 mp_obj_t top = TOP();
Damien Georgeb1bbe962015-04-01 14:10:50 +0000344 if (mp_obj_get_type(top)->attr == mp_obj_instance_attr) {
Damien George999cedb2015-11-27 17:01:44 +0000345 mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
Damien George7ee91cf2015-01-06 12:51:39 +0000346 mp_uint_t x = *ip;
347 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
348 mp_map_elem_t *elem;
349 if (x < self->members.alloc && self->members.table[x].key == key) {
350 elem = &self->members.table[x];
351 } else {
352 elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);
353 if (elem != NULL) {
354 *(byte*)ip = elem - &self->members.table[0];
355 } else {
356 goto load_attr_cache_fail;
357 }
358 }
359 SET_TOP(elem->value);
360 ip++;
361 DISPATCH();
362 }
363 load_attr_cache_fail:
364 SET_TOP(mp_load_attr(top, qst));
365 ip++;
366 DISPATCH();
367 }
368 #endif
Damience89a212013-10-15 22:25:17 +0100369
Damien Georged8675542014-05-25 22:58:04 +0100370 ENTRY(MP_BC_LOAD_METHOD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200371 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800372 DECODE_QSTR;
373 mp_load_method(*sp, qst, sp);
374 sp += 1;
375 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100376 }
Damience89a212013-10-15 22:25:17 +0100377
AZ Huangb1f692e2014-04-14 23:22:44 +0800378 ENTRY(MP_BC_LOAD_BUILD_CLASS):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200379 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800380 PUSH(mp_load_build_class());
381 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100382
Damien Georged8675542014-05-25 22:58:04 +0100383 ENTRY(MP_BC_LOAD_SUBSCR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200384 MARK_EXC_IP_SELECTIVE();
Damien Georged8675542014-05-25 22:58:04 +0100385 mp_obj_t index = POP();
386 SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL));
Damien George729f7b42014-04-17 22:10:53 +0100387 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100388 }
Damien George729f7b42014-04-17 22:10:53 +0100389
Damien Georgecd97a432014-12-02 19:25:10 +0000390 ENTRY(MP_BC_STORE_FAST_N): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800391 DECODE_UINT;
392 fastn[-unum] = POP();
393 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000394 }
Damience89a212013-10-15 22:25:17 +0100395
Damien Georgecd97a432014-12-02 19:25:10 +0000396 ENTRY(MP_BC_STORE_DEREF): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800397 DECODE_UINT;
398 mp_obj_cell_set(fastn[-unum], POP());
399 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000400 }
Damien9ecbcff2013-12-11 00:41:43 +0000401
Damien Georged8675542014-05-25 22:58:04 +0100402 ENTRY(MP_BC_STORE_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200403 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800404 DECODE_QSTR;
405 mp_store_name(qst, POP());
406 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100407 }
Damience89a212013-10-15 22:25:17 +0100408
Damien Georged8675542014-05-25 22:58:04 +0100409 ENTRY(MP_BC_STORE_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200410 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800411 DECODE_QSTR;
412 mp_store_global(qst, POP());
413 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100414 }
Damien6addc892013-11-04 23:04:50 +0000415
Damien George7ee91cf2015-01-06 12:51:39 +0000416 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100417 ENTRY(MP_BC_STORE_ATTR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200418 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800419 DECODE_QSTR;
420 mp_store_attr(sp[0], qst, sp[-1]);
421 sp -= 2;
422 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100423 }
Damien George7ee91cf2015-01-06 12:51:39 +0000424 #else
stijn28fa84b2015-02-14 18:43:54 +0100425 // This caching code works with MICROPY_PY_BUILTINS_PROPERTY and/or
426 // MICROPY_PY_DESCRIPTORS enabled because if the attr exists in
427 // self->members then it can't be a property or have descriptors. A
Damien George7ee91cf2015-01-06 12:51:39 +0000428 // consequence of this is that we can't use MP_MAP_LOOKUP_ADD_IF_NOT_FOUND
429 // in the fast-path below, because that store could override a property.
430 ENTRY(MP_BC_STORE_ATTR): {
431 MARK_EXC_IP_SELECTIVE();
432 DECODE_QSTR;
433 mp_obj_t top = TOP();
Damien Georgeb1bbe962015-04-01 14:10:50 +0000434 if (mp_obj_get_type(top)->attr == mp_obj_instance_attr && sp[-1] != MP_OBJ_NULL) {
Damien George999cedb2015-11-27 17:01:44 +0000435 mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
Damien George7ee91cf2015-01-06 12:51:39 +0000436 mp_uint_t x = *ip;
437 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
438 mp_map_elem_t *elem;
439 if (x < self->members.alloc && self->members.table[x].key == key) {
440 elem = &self->members.table[x];
441 } else {
442 elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);
443 if (elem != NULL) {
444 *(byte*)ip = elem - &self->members.table[0];
445 } else {
446 goto store_attr_cache_fail;
447 }
448 }
449 elem->value = sp[-1];
450 sp -= 2;
451 ip++;
452 DISPATCH();
453 }
454 store_attr_cache_fail:
455 mp_store_attr(sp[0], qst, sp[-1]);
456 sp -= 2;
457 ip++;
458 DISPATCH();
459 }
460 #endif
Damience89a212013-10-15 22:25:17 +0100461
AZ Huangb1f692e2014-04-14 23:22:44 +0800462 ENTRY(MP_BC_STORE_SUBSCR):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200463 MARK_EXC_IP_SELECTIVE();
Damien George729f7b42014-04-17 22:10:53 +0100464 mp_obj_subscr(sp[-1], sp[0], sp[-2]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800465 sp -= 3;
466 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100467
Damien Georgecd97a432014-12-02 19:25:10 +0000468 ENTRY(MP_BC_DELETE_FAST): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200469 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800470 DECODE_UINT;
471 if (fastn[-unum] == MP_OBJ_NULL) {
472 goto local_name_error;
473 }
474 fastn[-unum] = MP_OBJ_NULL;
475 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000476 }
Damien George2bf7c092014-04-09 15:26:46 +0100477
Damien Georgecd97a432014-12-02 19:25:10 +0000478 ENTRY(MP_BC_DELETE_DEREF): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200479 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800480 DECODE_UINT;
481 if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
482 goto local_name_error;
483 }
484 mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);
485 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000486 }
Damien George2bf7c092014-04-09 15:26:46 +0100487
Damien Georged8675542014-05-25 22:58:04 +0100488 ENTRY(MP_BC_DELETE_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200489 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800490 DECODE_QSTR;
491 mp_delete_name(qst);
492 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100493 }
Paul Sokolovskyf9090342014-03-23 21:19:02 +0200494
Damien Georged8675542014-05-25 22:58:04 +0100495 ENTRY(MP_BC_DELETE_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200496 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800497 DECODE_QSTR;
498 mp_delete_global(qst);
499 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100500 }
Damien George1d24ea52014-04-08 21:11:49 +0100501
Damien Georged8675542014-05-25 22:58:04 +0100502 ENTRY(MP_BC_DUP_TOP): {
503 mp_obj_t top = TOP();
504 PUSH(top);
AZ Huangb1f692e2014-04-14 23:22:44 +0800505 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100506 }
Damience89a212013-10-15 22:25:17 +0100507
AZ Huangb1f692e2014-04-14 23:22:44 +0800508 ENTRY(MP_BC_DUP_TOP_TWO):
509 sp += 2;
510 sp[0] = sp[-2];
511 sp[-1] = sp[-3];
512 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100513
AZ Huangb1f692e2014-04-14 23:22:44 +0800514 ENTRY(MP_BC_POP_TOP):
515 sp -= 1;
516 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100517
Damien Georged8675542014-05-25 22:58:04 +0100518 ENTRY(MP_BC_ROT_TWO): {
519 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800520 sp[0] = sp[-1];
Damien Georged8675542014-05-25 22:58:04 +0100521 sp[-1] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800522 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100523 }
Damien4ebb32f2013-11-02 14:33:10 +0000524
Damien Georged8675542014-05-25 22:58:04 +0100525 ENTRY(MP_BC_ROT_THREE): {
526 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800527 sp[0] = sp[-1];
528 sp[-1] = sp[-2];
Damien Georged8675542014-05-25 22:58:04 +0100529 sp[-2] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800530 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100531 }
Damience89a212013-10-15 22:25:17 +0100532
Damien Georgecd97a432014-12-02 19:25:10 +0000533 ENTRY(MP_BC_JUMP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800534 DECODE_SLABEL;
Damien Georgecd97a432014-12-02 19:25:10 +0000535 ip += slab;
Damien George124df6f2014-10-25 18:19:55 +0100536 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000537 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800538
Damien Georgecd97a432014-12-02 19:25:10 +0000539 ENTRY(MP_BC_POP_JUMP_IF_TRUE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800540 DECODE_SLABEL;
541 if (mp_obj_is_true(POP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000542 ip += slab;
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200543 }
Damien George124df6f2014-10-25 18:19:55 +0100544 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000545 }
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200546
Damien Georgecd97a432014-12-02 19:25:10 +0000547 ENTRY(MP_BC_POP_JUMP_IF_FALSE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800548 DECODE_SLABEL;
549 if (!mp_obj_is_true(POP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000550 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800551 }
Damien George124df6f2014-10-25 18:19:55 +0100552 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000553 }
Damien George600ae732014-01-21 23:48:04 +0000554
Damien Georgecd97a432014-12-02 19:25:10 +0000555 ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800556 DECODE_SLABEL;
557 if (mp_obj_is_true(TOP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000558 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800559 } else {
560 sp--;
561 }
Damien George124df6f2014-10-25 18:19:55 +0100562 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000563 }
Damience89a212013-10-15 22:25:17 +0100564
Damien Georgecd97a432014-12-02 19:25:10 +0000565 ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800566 DECODE_SLABEL;
567 if (mp_obj_is_true(TOP())) {
568 sp--;
569 } else {
Damien Georgecd97a432014-12-02 19:25:10 +0000570 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800571 }
Damien George124df6f2014-10-25 18:19:55 +0100572 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000573 }
Damience89a212013-10-15 22:25:17 +0100574
Damien Georged8675542014-05-25 22:58:04 +0100575 ENTRY(MP_BC_SETUP_WITH): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200576 MARK_EXC_IP_SELECTIVE();
Damien George8c1d23a2015-04-24 01:52:28 +0100577 // stack: (..., ctx_mgr)
Damien Georged8675542014-05-25 22:58:04 +0100578 mp_obj_t obj = TOP();
Damien George8c1d23a2015-04-24 01:52:28 +0100579 mp_load_method(obj, MP_QSTR___exit__, sp);
580 mp_load_method(obj, MP_QSTR___enter__, sp + 2);
581 mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 2);
582 sp += 1;
Damien George74eb44c2014-12-22 12:49:57 +0000583 PUSH_EXC_BLOCK(1);
Damien Georged8675542014-05-25 22:58:04 +0100584 PUSH(ret);
Damien George8c1d23a2015-04-24 01:52:28 +0100585 // stack: (..., __exit__, ctx_mgr, as_value)
AZ Huangb1f692e2014-04-14 23:22:44 +0800586 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100587 }
Damience89a212013-10-15 22:25:17 +0100588
AZ Huangb1f692e2014-04-14 23:22:44 +0800589 ENTRY(MP_BC_WITH_CLEANUP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200590 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800591 // Arriving here, there's "exception control block" on top of stack,
Damien George8c1d23a2015-04-24 01:52:28 +0100592 // and __exit__ method (with self) underneath it. Bytecode calls __exit__,
AZ Huangb1f692e2014-04-14 23:22:44 +0800593 // and "deletes" it off stack, shifting "exception control block"
594 // to its place.
Damien Georgef0406852016-09-27 12:37:21 +1000595 // The bytecode emitter ensures that there is enough space on the Python
596 // value stack to hold the __exit__ method plus an additional 4 entries.
AZ Huangb1f692e2014-04-14 23:22:44 +0800597 if (TOP() == mp_const_none) {
Damien George8c1d23a2015-04-24 01:52:28 +0100598 // stack: (..., __exit__, ctx_mgr, None)
599 sp[1] = mp_const_none;
600 sp[2] = mp_const_none;
601 sp -= 2;
602 mp_call_method_n_kw(3, 0, sp);
AZ Huangb1f692e2014-04-14 23:22:44 +0800603 SET_TOP(mp_const_none);
AZ Huangb1f692e2014-04-14 23:22:44 +0800604 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
Damien George5e1d9932015-03-25 22:20:37 +0000605 mp_int_t cause_val = MP_OBJ_SMALL_INT_VALUE(TOP());
606 if (cause_val == UNWIND_RETURN) {
Damien George8c1d23a2015-04-24 01:52:28 +0100607 // stack: (..., __exit__, ctx_mgr, ret_val, UNWIND_RETURN)
608 mp_obj_t ret_val = sp[-1];
609 sp[-1] = mp_const_none;
610 sp[0] = mp_const_none;
611 sp[1] = mp_const_none;
612 mp_call_method_n_kw(3, 0, sp - 3);
613 sp[-3] = ret_val;
614 sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN);
Damien George5e1d9932015-03-25 22:20:37 +0000615 } else {
616 assert(cause_val == UNWIND_JUMP);
Damien George8c1d23a2015-04-24 01:52:28 +0100617 // stack: (..., __exit__, ctx_mgr, dest_ip, num_exc, UNWIND_JUMP)
618 mp_obj_t dest_ip = sp[-2];
619 mp_obj_t num_exc = sp[-1];
620 sp[-2] = mp_const_none;
621 sp[-1] = mp_const_none;
622 sp[0] = mp_const_none;
623 mp_call_method_n_kw(3, 0, sp - 4);
624 sp[-4] = dest_ip;
625 sp[-3] = num_exc;
626 sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP);
AZ Huangb1f692e2014-04-14 23:22:44 +0800627 }
Damien George8c1d23a2015-04-24 01:52:28 +0100628 sp -= 2; // we removed (__exit__, ctx_mgr)
Damien George5e1d9932015-03-25 22:20:37 +0000629 } else {
Damien Georgef0406852016-09-27 12:37:21 +1000630 assert(mp_obj_is_exception_instance(TOP()));
631 // stack: (..., __exit__, ctx_mgr, exc_instance)
632 // Need to pass (exc_type, exc_instance, None) as arguments to __exit__.
633 sp[1] = sp[0];
Damien George71fec072016-09-27 13:21:23 +1000634 sp[0] = MP_OBJ_FROM_PTR(mp_obj_get_type(sp[0]));
Damien Georgef0406852016-09-27 12:37:21 +1000635 sp[2] = mp_const_none;
636 sp -= 2;
637 mp_obj_t ret_value = mp_call_method_n_kw(3, 0, sp);
Damien Georged8675542014-05-25 22:58:04 +0100638 if (mp_obj_is_true(ret_value)) {
Damien George8c1d23a2015-04-24 01:52:28 +0100639 // We need to silence/swallow the exception. This is done
640 // by popping the exception and the __exit__ handler and
641 // replacing it with None, which signals END_FINALLY to just
642 // execute the finally handler normally.
Damien George8c1d23a2015-04-24 01:52:28 +0100643 SET_TOP(mp_const_none);
AZ Huangb1f692e2014-04-14 23:22:44 +0800644 assert(exc_sp >= exc_stack);
AZ Huangb1f692e2014-04-14 23:22:44 +0800645 POP_EXC_BLOCK();
Damien George596f41d2015-02-10 13:21:42 +0000646 } else {
Damien George8c1d23a2015-04-24 01:52:28 +0100647 // We need to re-raise the exception. We pop __exit__ handler
Damien Georgef0406852016-09-27 12:37:21 +1000648 // by copying the exception instance down to the new top-of-stack.
649 sp[0] = sp[3];
AZ Huangb1f692e2014-04-14 23:22:44 +0800650 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800651 }
652 DISPATCH();
653 }
Damienc226dca2013-10-16 16:12:52 +0100654
Damien Georgecd97a432014-12-02 19:25:10 +0000655 ENTRY(MP_BC_UNWIND_JUMP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200656 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800657 DECODE_SLABEL;
Damien George999cedb2015-11-27 17:01:44 +0000658 PUSH((mp_obj_t)(mp_uint_t)(uintptr_t)(ip + slab)); // push destination ip for jump
659 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 +0000660unwind_jump:;
661 mp_uint_t unum = (mp_uint_t)POP(); // get number of exception handlers to unwind
Damien George25c84642014-05-30 15:20:41 +0100662 while ((unum & 0x7f) > 0) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800663 unum -= 1;
664 assert(exc_sp >= exc_stack);
Damien George74eb44c2014-12-22 12:49:57 +0000665 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
Damien George4bf3f2d2015-10-15 17:48:28 +0100666 // Getting here the stack looks like:
667 // (..., X, dest_ip)
668 // where X is pointed to by exc_sp->val_sp and in the case
669 // of a "with" block contains the context manager info.
AZ Huangb1f692e2014-04-14 23:22:44 +0800670 // We're going to run "finally" code as a coroutine
671 // (not calling it recursively). Set up a sentinel
672 // on a stack so it can return back to us when it is
Damien George4bf3f2d2015-10-15 17:48:28 +0100673 // done (when WITH_CLEANUP or END_FINALLY reached).
Damien George999cedb2015-11-27 17:01:44 +0000674 PUSH((mp_obj_t)unum); // push number of exception handlers left to unwind
AZ Huangb1f692e2014-04-14 23:22:44 +0800675 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
676 ip = exc_sp->handler; // get exception handler byte code address
677 exc_sp--; // pop exception handler
678 goto dispatch_loop; // run the exception handler
679 }
Damien George93bb7df2016-02-01 16:07:21 +0000680 POP_EXC_BLOCK();
AZ Huangb1f692e2014-04-14 23:22:44 +0800681 }
Damien George999cedb2015-11-27 17:01:44 +0000682 ip = (const byte*)MP_OBJ_TO_PTR(POP()); // pop destination ip for jump
Damien George25c84642014-05-30 15:20:41 +0100683 if (unum != 0) {
684 sp--;
685 }
Damien George124df6f2014-10-25 18:19:55 +0100686 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000687 }
Damience89a212013-10-15 22:25:17 +0100688
AZ Huangb1f692e2014-04-14 23:22:44 +0800689 // matched against: POP_BLOCK or POP_EXCEPT (anything else?)
690 ENTRY(MP_BC_SETUP_EXCEPT):
Damien Georgecd97a432014-12-02 19:25:10 +0000691 ENTRY(MP_BC_SETUP_FINALLY): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200692 MARK_EXC_IP_SELECTIVE();
Damien Georgef89d6592014-12-29 00:29:59 +0000693 #if SELECTIVE_EXC_IP
694 PUSH_EXC_BLOCK((code_state->ip[-1] == MP_BC_SETUP_FINALLY) ? 1 : 0);
695 #else
696 PUSH_EXC_BLOCK((code_state->ip[0] == MP_BC_SETUP_FINALLY) ? 1 : 0);
697 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800698 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000699 }
Damience89a212013-10-15 22:25:17 +0100700
AZ Huangb1f692e2014-04-14 23:22:44 +0800701 ENTRY(MP_BC_END_FINALLY):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200702 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800703 // if TOS is None, just pops it and continues
Damien Georgef0406852016-09-27 12:37:21 +1000704 // if TOS is an integer, finishes coroutine and returns control to caller
705 // if TOS is an exception, reraises the exception
AZ Huangb1f692e2014-04-14 23:22:44 +0800706 if (TOP() == mp_const_none) {
Damien George20006db2014-01-18 14:10:48 +0000707 sp--;
Damien Georgef0406852016-09-27 12:37:21 +1000708 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800709 // We finished "finally" coroutine and now dispatch back
710 // to our caller, based on TOS value
711 mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());
Damien George5e1d9932015-03-25 22:20:37 +0000712 if (reason == UNWIND_RETURN) {
713 goto unwind_return;
714 } else {
715 assert(reason == UNWIND_JUMP);
716 goto unwind_jump;
AZ Huangb1f692e2014-04-14 23:22:44 +0800717 }
Damien Georgef0406852016-09-27 12:37:21 +1000718 } else {
719 assert(mp_obj_is_exception_instance(TOP()));
720 RAISE(TOP());
AZ Huangb1f692e2014-04-14 23:22:44 +0800721 }
722 DISPATCH();
723
724 ENTRY(MP_BC_GET_ITER):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200725 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800726 SET_TOP(mp_getiter(TOP()));
727 DISPATCH();
728
Damien Georged8675542014-05-25 22:58:04 +0100729 ENTRY(MP_BC_FOR_ITER): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200730 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800731 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgec60a2612014-06-01 12:32:28 +0100732 code_state->sp = sp;
Paul Sokolovskyc48d6f72014-05-11 20:32:39 +0300733 assert(TOP());
Damien Georged8675542014-05-25 22:58:04 +0100734 mp_obj_t value = mp_iternext_allow_raise(TOP());
735 if (value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800736 --sp; // pop the exhausted iterator
Damien Georgecd97a432014-12-02 19:25:10 +0000737 ip += ulab; // jump to after for-block
AZ Huangb1f692e2014-04-14 23:22:44 +0800738 } else {
Damien Georged8675542014-05-25 22:58:04 +0100739 PUSH(value); // push the next iteration value
AZ Huangb1f692e2014-04-14 23:22:44 +0800740 }
741 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100742 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800743
744 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
745 ENTRY(MP_BC_POP_BLOCK):
746 // we are exiting an exception handler, so pop the last one of the exception-stack
747 assert(exc_sp >= exc_stack);
748 POP_EXC_BLOCK();
749 DISPATCH();
750
751 // matched against: SETUP_EXCEPT
752 ENTRY(MP_BC_POP_EXCEPT):
AZ Huangb1f692e2014-04-14 23:22:44 +0800753 assert(exc_sp >= exc_stack);
754 assert(currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +0800755 POP_EXC_BLOCK();
AZ Huangb1f692e2014-04-14 23:22:44 +0800756 DISPATCH();
757
Damien Georgecd97a432014-12-02 19:25:10 +0000758 ENTRY(MP_BC_BUILD_TUPLE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200759 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800760 DECODE_UINT;
761 sp -= unum - 1;
762 SET_TOP(mp_obj_new_tuple(unum, sp));
763 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000764 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800765
Damien Georgecd97a432014-12-02 19:25:10 +0000766 ENTRY(MP_BC_BUILD_LIST): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200767 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800768 DECODE_UINT;
769 sp -= unum - 1;
770 SET_TOP(mp_obj_new_list(unum, sp));
771 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000772 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800773
Damien Georgecd97a432014-12-02 19:25:10 +0000774 ENTRY(MP_BC_BUILD_MAP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200775 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800776 DECODE_UINT;
777 PUSH(mp_obj_new_dict(unum));
778 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000779 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800780
781 ENTRY(MP_BC_STORE_MAP):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200782 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800783 sp -= 2;
784 mp_obj_dict_store(sp[0], sp[2], sp[1]);
785 DISPATCH();
786
Damien George3ebd4d02014-06-01 13:46:47 +0100787#if MICROPY_PY_BUILTINS_SET
Damien Georgecd97a432014-12-02 19:25:10 +0000788 ENTRY(MP_BC_BUILD_SET): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200789 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800790 DECODE_UINT;
791 sp -= unum - 1;
792 SET_TOP(mp_obj_new_set(unum, sp));
793 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000794 }
Damien George3ebd4d02014-06-01 13:46:47 +0100795#endif
Damienc12aa462013-10-16 20:57:49 +0100796
Damien Georgefb510b32014-06-01 13:32:54 +0100797#if MICROPY_PY_BUILTINS_SLICE
Damien Georgecd97a432014-12-02 19:25:10 +0000798 ENTRY(MP_BC_BUILD_SLICE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200799 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800800 DECODE_UINT;
801 if (unum == 2) {
Damien Georged8675542014-05-25 22:58:04 +0100802 mp_obj_t stop = POP();
803 mp_obj_t start = TOP();
804 SET_TOP(mp_obj_new_slice(start, stop, mp_const_none));
AZ Huangb1f692e2014-04-14 23:22:44 +0800805 } else {
Damien Georged8675542014-05-25 22:58:04 +0100806 mp_obj_t step = POP();
807 mp_obj_t stop = POP();
808 mp_obj_t start = TOP();
809 SET_TOP(mp_obj_new_slice(start, stop, step));
AZ Huangb1f692e2014-04-14 23:22:44 +0800810 }
811 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000812 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800813#endif
814
Damien Georgeadaf0d82016-09-19 08:46:01 +1000815 ENTRY(MP_BC_STORE_COMP): {
816 MARK_EXC_IP_SELECTIVE();
817 DECODE_UINT;
818 mp_obj_t obj = sp[-(unum >> 2)];
819 if ((unum & 3) == 0) {
820 mp_obj_list_append(obj, sp[0]);
821 sp--;
822 } else if (!MICROPY_PY_BUILTINS_SET || (unum & 3) == 1) {
823 mp_obj_dict_store(obj, sp[0], sp[-1]);
824 sp -= 2;
825 #if MICROPY_PY_BUILTINS_SET
826 } else {
827 mp_obj_set_store(obj, sp[0]);
828 sp--;
829 #endif
830 }
831 DISPATCH();
832 }
833
Damien Georgecd97a432014-12-02 19:25:10 +0000834 ENTRY(MP_BC_UNPACK_SEQUENCE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200835 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800836 DECODE_UINT;
837 mp_unpack_sequence(sp[0], unum, sp);
838 sp += unum - 1;
839 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000840 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800841
Damien Georgecd97a432014-12-02 19:25:10 +0000842 ENTRY(MP_BC_UNPACK_EX): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200843 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800844 DECODE_UINT;
845 mp_unpack_ex(sp[0], unum, sp);
846 sp += (unum & 0xff) + ((unum >> 8) & 0xff);
847 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000848 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800849
Damien Georgecd97a432014-12-02 19:25:10 +0000850 ENTRY(MP_BC_MAKE_FUNCTION): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800851 DECODE_PTR;
Damien Georgecd97a432014-12-02 19:25:10 +0000852 PUSH(mp_make_function_from_raw_code(ptr, MP_OBJ_NULL, MP_OBJ_NULL));
AZ Huangb1f692e2014-04-14 23:22:44 +0800853 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000854 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800855
Damien Georged8675542014-05-25 22:58:04 +0100856 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800857 DECODE_PTR;
858 // Stack layout: def_tuple def_dict <- TOS
Damien Georged8675542014-05-25 22:58:04 +0100859 mp_obj_t def_dict = POP();
Damien Georgecd97a432014-12-02 19:25:10 +0000860 SET_TOP(mp_make_function_from_raw_code(ptr, TOP(), def_dict));
AZ Huangb1f692e2014-04-14 23:22:44 +0800861 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100862 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800863
Damien George3558f622014-04-20 17:50:40 +0100864 ENTRY(MP_BC_MAKE_CLOSURE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800865 DECODE_PTR;
Damien George101886f2017-02-16 16:48:33 +1100866 size_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100867 // Stack layout: closed_overs <- TOS
868 sp -= n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000869 SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800870 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100871 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800872
Damien George3558f622014-04-20 17:50:40 +0100873 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800874 DECODE_PTR;
Damien George101886f2017-02-16 16:48:33 +1100875 size_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100876 // Stack layout: def_tuple def_dict closed_overs <- TOS
877 sp -= 2 + n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000878 SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800879 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100880 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800881
Damien Georgecd97a432014-12-02 19:25:10 +0000882 ENTRY(MP_BC_CALL_FUNCTION): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200883 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800884 DECODE_UINT;
885 // unum & 0xff == n_positional
886 // (unum >> 8) & 0xff == n_keyword
887 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
Paul Sokolovsky20397572015-03-28 01:14:44 +0200888 #if MICROPY_STACKLESS
889 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
890 code_state->ip = ip;
891 code_state->sp = sp;
892 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
Damien George581a59a2016-08-27 23:21:00 +1000893 mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1);
Paul Sokolovsky332a9092015-03-28 01:14:44 +0200894 if (new_state) {
895 new_state->prev = code_state;
896 code_state = new_state;
897 nlr_pop();
898 goto run_code_state;
899 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200900 #if MICROPY_STACKLESS_STRICT
901 else {
902 deep_recursion_error:
903 mp_exc_recursion_depth();
904 }
905 #endif
Paul Sokolovsky20397572015-03-28 01:14:44 +0200906 }
907 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800908 SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
909 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000910 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800911
Damien Georgecd97a432014-12-02 19:25:10 +0000912 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200913 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800914 DECODE_UINT;
915 // unum & 0xff == n_positional
916 // (unum >> 8) & 0xff == n_keyword
917 // We have folowing stack layout here:
918 // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
919 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200920 #if MICROPY_STACKLESS
921 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
922 code_state->ip = ip;
923 code_state->sp = sp;
924 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
925
Damien George12a5e172015-04-01 23:31:30 +0100926 mp_call_args_t out_args;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200927 mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args);
928
Damien George581a59a2016-08-27 23:21:00 +1000929 mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200930 out_args.n_args, out_args.n_kw, out_args.args);
931 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
932 if (new_state) {
933 new_state->prev = code_state;
934 code_state = new_state;
935 nlr_pop();
936 goto run_code_state;
937 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200938 #if MICROPY_STACKLESS_STRICT
939 else {
940 goto deep_recursion_error;
941 }
942 #endif
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200943 }
944 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800945 SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
946 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000947 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800948
Damien Georgecd97a432014-12-02 19:25:10 +0000949 ENTRY(MP_BC_CALL_METHOD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200950 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800951 DECODE_UINT;
952 // unum & 0xff == n_positional
953 // (unum >> 8) & 0xff == n_keyword
954 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200955 #if MICROPY_STACKLESS
956 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
957 code_state->ip = ip;
958 code_state->sp = sp;
959 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
960
Damien George101886f2017-02-16 16:48:33 +1100961 size_t n_args = unum & 0xff;
962 size_t n_kw = (unum >> 8) & 0xff;
Damien George7a30e872015-12-17 12:32:41 +0000963 int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1;
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200964
Damien George581a59a2016-08-27 23:21:00 +1000965 mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust);
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200966 if (new_state) {
967 new_state->prev = code_state;
968 code_state = new_state;
969 nlr_pop();
970 goto run_code_state;
971 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200972 #if MICROPY_STACKLESS_STRICT
973 else {
974 goto deep_recursion_error;
975 }
976 #endif
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200977 }
978 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800979 SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
980 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000981 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800982
Damien Georgecd97a432014-12-02 19:25:10 +0000983 ENTRY(MP_BC_CALL_METHOD_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200984 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800985 DECODE_UINT;
986 // unum & 0xff == n_positional
987 // (unum >> 8) & 0xff == n_keyword
988 // We have folowing stack layout here:
989 // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
990 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200991 #if MICROPY_STACKLESS
992 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
993 code_state->ip = ip;
994 code_state->sp = sp;
995 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
996
Damien George12a5e172015-04-01 23:31:30 +0100997 mp_call_args_t out_args;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200998 mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args);
999
Damien George581a59a2016-08-27 23:21:00 +10001000 mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001001 out_args.n_args, out_args.n_kw, out_args.args);
1002 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
1003 if (new_state) {
1004 new_state->prev = code_state;
1005 code_state = new_state;
1006 nlr_pop();
1007 goto run_code_state;
1008 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +02001009 #if MICROPY_STACKLESS_STRICT
1010 else {
1011 goto deep_recursion_error;
1012 }
1013 #endif
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001014 }
1015 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001016 SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
1017 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +00001018 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001019
1020 ENTRY(MP_BC_RETURN_VALUE):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001021 MARK_EXC_IP_SELECTIVE();
Damien George80473402015-12-24 12:47:39 +00001022 // These next 3 lines pop a try-finally exception handler, if one
1023 // is there on the exception stack. Without this the finally block
1024 // is executed a second time when the return is executed, because
1025 // the try-finally exception handler is still on the stack.
1026 // TODO Possibly find a better way to handle this case.
1027 if (currently_in_except_block) {
1028 POP_EXC_BLOCK();
1029 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001030unwind_return:
1031 while (exc_sp >= exc_stack) {
Damien George74eb44c2014-12-22 12:49:57 +00001032 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
Damien George4bf3f2d2015-10-15 17:48:28 +01001033 // Getting here the stack looks like:
1034 // (..., X, [iter0, iter1, ...,] ret_val)
1035 // where X is pointed to by exc_sp->val_sp and in the case
1036 // of a "with" block contains the context manager info.
1037 // There may be 0 or more for-iterators between X and the
1038 // return value, and these must be removed before control can
1039 // pass to the finally code. We simply copy the ret_value down
1040 // over these iterators, if they exist. If they don't then the
1041 // following is a null operation.
1042 mp_obj_t *finally_sp = MP_TAGPTR_PTR(exc_sp->val_sp);
1043 finally_sp[1] = sp[0];
1044 sp = &finally_sp[1];
AZ Huangb1f692e2014-04-14 23:22:44 +08001045 // We're going to run "finally" code as a coroutine
1046 // (not calling it recursively). Set up a sentinel
1047 // on a stack so it can return back to us when it is
Damien George4bf3f2d2015-10-15 17:48:28 +01001048 // done (when WITH_CLEANUP or END_FINALLY reached).
AZ Huangb1f692e2014-04-14 23:22:44 +08001049 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
1050 ip = exc_sp->handler;
AZ Huangb1f692e2014-04-14 23:22:44 +08001051 exc_sp--;
1052 goto dispatch_loop;
1053 }
1054 exc_sp--;
1055 }
1056 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001057 code_state->sp = sp;
AZ Huangb1f692e2014-04-14 23:22:44 +08001058 assert(exc_sp == exc_stack - 1);
Damien George40d84302016-02-15 22:46:21 +00001059 MICROPY_VM_HOOK_RETURN
Paul Sokolovsky20397572015-03-28 01:14:44 +02001060 #if MICROPY_STACKLESS
1061 if (code_state->prev != NULL) {
1062 mp_obj_t res = *sp;
1063 mp_globals_set(code_state->old_globals);
1064 code_state = code_state->prev;
1065 *code_state->sp = res;
1066 goto run_code_state;
1067 }
1068 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001069 return MP_VM_RETURN_NORMAL;
1070
Damien Georged8675542014-05-25 22:58:04 +01001071 ENTRY(MP_BC_RAISE_VARARGS): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001072 MARK_EXC_IP_SELECTIVE();
Damien Georgecd97a432014-12-02 19:25:10 +00001073 mp_uint_t unum = *ip++;
Damien Georged8675542014-05-25 22:58:04 +01001074 mp_obj_t obj;
Paul Sokolovsky2ff2ea52015-09-01 10:35:58 +03001075 if (unum == 2) {
1076 mp_warning("exception chaining not supported");
1077 // ignore (pop) "from" argument
1078 sp--;
1079 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001080 if (unum == 0) {
1081 // search for the inner-most previous exception, to reraise it
Damien Georged8675542014-05-25 22:58:04 +01001082 obj = MP_OBJ_NULL;
AZ Huangb1f692e2014-04-14 23:22:44 +08001083 for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
Damien George999cedb2015-11-27 17:01:44 +00001084 if (e->prev_exc != NULL) {
1085 obj = MP_OBJ_FROM_PTR(e->prev_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +08001086 break;
1087 }
1088 }
Damien Georged8675542014-05-25 22:58:04 +01001089 if (obj == MP_OBJ_NULL) {
1090 obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
1091 RAISE(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001092 }
1093 } else {
Damien Georged8675542014-05-25 22:58:04 +01001094 obj = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +08001095 }
Damien Georged8675542014-05-25 22:58:04 +01001096 obj = mp_make_raise_obj(obj);
1097 RAISE(obj);
1098 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001099
1100 ENTRY(MP_BC_YIELD_VALUE):
1101yield:
1102 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001103 code_state->ip = ip;
1104 code_state->sp = sp;
1105 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +08001106 return MP_VM_RETURN_YIELD;
1107
1108 ENTRY(MP_BC_YIELD_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001109 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001110//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
1111#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
Damien George999cedb2015-11-27 17:01:44 +00001112#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 +08001113 mp_vm_return_kind_t ret_kind;
Damien Georged8675542014-05-25 22:58:04 +01001114 mp_obj_t send_value = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +08001115 mp_obj_t t_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +01001116 mp_obj_t ret_value;
AZ Huangb1f692e2014-04-14 23:22:44 +08001117 if (inject_exc != MP_OBJ_NULL) {
1118 t_exc = inject_exc;
1119 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +01001120 ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001121 } else {
Damien Georged8675542014-05-25 22:58:04 +01001122 ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001123 }
1124
1125 if (ret_kind == MP_VM_RETURN_YIELD) {
1126 ip--;
Damien Georged8675542014-05-25 22:58:04 +01001127 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001128 goto yield;
1129 }
1130 if (ret_kind == MP_VM_RETURN_NORMAL) {
1131 // Pop exhausted gen
1132 sp--;
Paul Sokolovskyeff85bb2016-04-28 01:54:23 +03001133 // TODO: When ret_value can be MP_OBJ_NULL here??
1134 if (ret_value == MP_OBJ_NULL || ret_value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +08001135 // Optimize StopIteration
1136 // TODO: get StopIteration's value
1137 PUSH(mp_const_none);
1138 } else {
Damien Georged8675542014-05-25 22:58:04 +01001139 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001140 }
1141
1142 // If we injected GeneratorExit downstream, then even
1143 // if it was swallowed, we re-raise GeneratorExit
1144 GENERATOR_EXIT_IF_NEEDED(t_exc);
1145 DISPATCH();
1146 }
1147 if (ret_kind == MP_VM_RETURN_EXCEPTION) {
1148 // Pop exhausted gen
1149 sp--;
Damien George999cedb2015-11-27 17:01:44 +00001150 if (EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
Damien Georged8675542014-05-25 22:58:04 +01001151 PUSH(mp_obj_exception_get_value(ret_value));
AZ Huangb1f692e2014-04-14 23:22:44 +08001152 // If we injected GeneratorExit downstream, then even
1153 // if it was swallowed, we re-raise GeneratorExit
1154 GENERATOR_EXIT_IF_NEEDED(t_exc);
1155 DISPATCH();
1156 } else {
Damien Georged8675542014-05-25 22:58:04 +01001157 RAISE(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001158 }
1159 }
Damien429d7192013-10-04 19:53:11 +01001160 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001161
Damien Georged8675542014-05-25 22:58:04 +01001162 ENTRY(MP_BC_IMPORT_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001163 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001164 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001165 mp_obj_t obj = POP();
1166 SET_TOP(mp_import_name(qst, obj, TOP()));
AZ Huangb1f692e2014-04-14 23:22:44 +08001167 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001168 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001169
Damien Georged8675542014-05-25 22:58:04 +01001170 ENTRY(MP_BC_IMPORT_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001171 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001172 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001173 mp_obj_t obj = mp_import_from(TOP(), qst);
1174 PUSH(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001175 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001176 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001177
1178 ENTRY(MP_BC_IMPORT_STAR):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001179 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001180 mp_import_all(POP());
1181 DISPATCH();
1182
Damien George8456cc02014-10-25 16:43:46 +01001183#if MICROPY_OPT_COMPUTED_GOTO
1184 ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):
1185 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1186 DISPATCH();
1187
1188 ENTRY(MP_BC_LOAD_FAST_MULTI):
1189 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1190 goto load_check;
1191
1192 ENTRY(MP_BC_STORE_FAST_MULTI):
1193 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1194 DISPATCH();
1195
1196 ENTRY(MP_BC_UNARY_OP_MULTI):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001197 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001198 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1199 DISPATCH();
1200
1201 ENTRY(MP_BC_BINARY_OP_MULTI): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001202 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001203 mp_obj_t rhs = POP();
1204 mp_obj_t lhs = TOP();
1205 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1206 DISPATCH();
1207 }
1208
1209 ENTRY_DEFAULT:
Paul Sokolovsky74957502014-12-28 07:17:43 +02001210 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001211#else
1212 ENTRY_DEFAULT:
1213 if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
1214 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1215 DISPATCH();
1216 } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
1217 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1218 goto load_check;
1219 } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
1220 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1221 DISPATCH();
Damien Georgebdbe8c92015-12-08 12:28:11 +00001222 } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 7) {
Damien George8456cc02014-10-25 16:43:46 +01001223 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1224 DISPATCH();
Damien Georgec5029bc2015-06-13 22:00:10 +01001225 } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) {
Damien George8456cc02014-10-25 16:43:46 +01001226 mp_obj_t rhs = POP();
1227 mp_obj_t lhs = TOP();
1228 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1229 DISPATCH();
1230 } else
1231#endif
1232 {
Damien Georged8675542014-05-25 22:58:04 +01001233 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
AZ Huangb1f692e2014-04-14 23:22:44 +08001234 nlr_pop();
Damien Georged8675542014-05-25 22:58:04 +01001235 fastn[0] = obj;
AZ Huangb1f692e2014-04-14 23:22:44 +08001236 return MP_VM_RETURN_EXCEPTION;
Damien Georged8675542014-05-25 22:58:04 +01001237 }
Damien George66ae8c92014-04-17 16:50:23 +01001238
Damien George58ebde42014-05-21 20:32:59 +01001239#if !MICROPY_OPT_COMPUTED_GOTO
AZ Huang9309d992014-04-15 15:57:01 +08001240 } // switch
AZ Huangb1f692e2014-04-14 23:22:44 +08001241#endif
Damien George124df6f2014-10-25 18:19:55 +01001242
1243pending_exception_check:
Damien George40d84302016-02-15 22:46:21 +00001244 MICROPY_VM_HOOK_LOOP
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001245 if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001246 MARK_EXC_IP_SELECTIVE();
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001247 mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
1248 MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
Damien George124df6f2014-10-25 18:19:55 +01001249 RAISE(obj);
1250 }
Damien George124df6f2014-10-25 18:19:55 +01001251
Damien Georgef6c22a02017-02-06 10:50:43 +11001252 #if MICROPY_PY_THREAD_GIL
1253 #if MICROPY_PY_THREAD_GIL_VM_DIVISOR
1254 if (--gil_divisor == 0) {
1255 gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
1256 #else
1257 {
1258 #endif
1259 MP_THREAD_GIL_EXIT();
1260 MP_THREAD_GIL_ENTER();
1261 }
1262 #endif
Damien George4cec63a2016-05-26 10:42:53 +00001263
Damien George66ae8c92014-04-17 16:50:23 +01001264 } // for loop
Damien429d7192013-10-04 19:53:11 +01001265
Damience89a212013-10-15 22:25:17 +01001266 } else {
Damien George66ae8c92014-04-17 16:50:23 +01001267exception_handler:
Damience89a212013-10-15 22:25:17 +01001268 // exception occurred
Damien429d7192013-10-04 19:53:11 +01001269
Paul Sokolovsky8b85d142015-04-25 03:17:41 +03001270 #if MICROPY_PY_SYS_EXC_INFO
1271 MP_STATE_VM(cur_exception) = nlr.ret_val;
1272 #endif
1273
Damien Georgef89d6592014-12-29 00:29:59 +00001274 #if SELECTIVE_EXC_IP
1275 // with selective ip, we store the ip 1 byte past the opcode, so move ptr back
1276 code_state->ip -= 1;
1277 #endif
1278
Damien George999cedb2015-11-27 17:01:44 +00001279 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 +03001280 if (code_state->ip) {
1281 // check if it's a StopIteration within a for block
1282 if (*code_state->ip == MP_BC_FOR_ITER) {
1283 const byte *ip = code_state->ip + 1;
1284 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
1285 code_state->ip = ip + ulab; // jump to after for-block
1286 code_state->sp -= 1; // pop the exhausted iterator
1287 goto outer_dispatch_loop; // continue with dispatch loop
Paul Sokolovsky6738c1d2015-05-11 02:59:25 +03001288 } else if (*code_state->ip == MP_BC_YIELD_FROM) {
1289 // StopIteration inside yield from call means return a value of
1290 // yield from, so inject exception's value as yield from's result
Damien George999cedb2015-11-27 17:01:44 +00001291 *++code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));
Paul Sokolovsky6738c1d2015-05-11 02:59:25 +03001292 code_state->ip++; // yield from is over, move to next instruction
1293 goto outer_dispatch_loop; // continue with dispatch loop
Paul Sokolovskya7c02c42015-05-10 17:18:10 +03001294 }
1295 }
Damien George9e6e9352014-03-26 18:37:06 +00001296 }
1297
Paul Sokolovsky20397572015-03-28 01:14:44 +02001298#if MICROPY_STACKLESS
1299unwind_loop:
1300#endif
Damien George08335002014-01-18 23:24:36 +00001301 // set file and line number that the exception occurred at
Paul Sokolovsky382e8ee2014-01-30 13:49:18 +02001302 // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
1303 // But consider how to handle nested exceptions.
Damien George6902eed2014-04-04 10:52:59 +00001304 // 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 +00001305 if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
Damien Georgeb534e1b2014-09-04 14:44:01 +01001306 const byte *ip = code_state->code_info;
Damien George101886f2017-02-16 16:48:33 +11001307 size_t code_info_size = mp_decode_uint(&ip);
Damien Georgec8e9c0d2015-11-02 17:27:18 +00001308 #if MICROPY_PERSISTENT_CODE
1309 qstr block_name = ip[0] | (ip[1] << 8);
1310 qstr source_file = ip[2] | (ip[3] << 8);
1311 ip += 4;
1312 #else
Damien Georgeb534e1b2014-09-04 14:44:01 +01001313 qstr block_name = mp_decode_uint(&ip);
1314 qstr source_file = mp_decode_uint(&ip);
Damien Georgec8e9c0d2015-11-02 17:27:18 +00001315 #endif
Damien George3d2daa22016-01-02 22:04:12 +00001316 size_t bc = code_state->ip - code_state->code_info - code_info_size;
1317 size_t source_line = 1;
1318 size_t c;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001319 while ((c = *ip)) {
Damien George101886f2017-02-16 16:48:33 +11001320 size_t b, l;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001321 if ((c & 0x80) == 0) {
1322 // 0b0LLBBBBB encoding
1323 b = c & 0x1f;
1324 l = c >> 5;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001325 ip += 1;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001326 } else {
1327 // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
1328 b = c & 0xf;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001329 l = ((c << 4) & 0x700) | ip[1];
1330 ip += 2;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001331 }
1332 if (bc >= b) {
1333 bc -= b;
1334 source_line += l;
1335 } else {
1336 // found source line corresponding to bytecode offset
1337 break;
Paul Sokolovsky411732e2014-06-02 18:24:34 +03001338 }
Damien George08335002014-01-18 23:24:36 +00001339 }
Damien George999cedb2015-11-27 17:01:44 +00001340 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 +00001341 }
1342
Damien8f9e2ee2013-12-29 16:54:59 +00001343 while (currently_in_except_block) {
1344 // nested exception
1345
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001346 assert(exc_sp >= exc_stack);
Damien8f9e2ee2013-12-29 16:54:59 +00001347
1348 // TODO make a proper message for nested exception
1349 // at the moment we are just raising the very last exception (the one that caused the nested exception)
1350
1351 // move up to previous exception handler
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +02001352 POP_EXC_BLOCK();
Damien8f9e2ee2013-12-29 16:54:59 +00001353 }
1354
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001355 if (exc_sp >= exc_stack) {
Damien8f9e2ee2013-12-29 16:54:59 +00001356 // set flag to indicate that we are now handling an exception
1357 currently_in_except_block = 1;
1358
Damience89a212013-10-15 22:25:17 +01001359 // catch exception and pass to byte code
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001360 code_state->ip = exc_sp->handler;
Damien George66ae8c92014-04-17 16:50:23 +01001361 mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
Damien Georged7592a12014-03-30 00:54:48 +00001362 // save this exception in the stack so it can be used in a reraise, if needed
1363 exc_sp->prev_exc = nlr.ret_val;
Damien Georgef0406852016-09-27 12:37:21 +10001364 // push exception object so it can be handled by bytecode
Damien George999cedb2015-11-27 17:01:44 +00001365 PUSH(MP_OBJ_FROM_PTR(nlr.ret_val));
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001366 code_state->sp = sp;
Damien8f9e2ee2013-12-29 16:54:59 +00001367
Paul Sokolovsky20397572015-03-28 01:14:44 +02001368 #if MICROPY_STACKLESS
1369 } else if (code_state->prev != NULL) {
1370 mp_globals_set(code_state->old_globals);
1371 code_state = code_state->prev;
1372 fastn = &code_state->state[code_state->n_state - 1];
1373 exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
1374 // variables that are visible to the exception handler (declared volatile)
1375 currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
1376 exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
1377 goto unwind_loop;
1378
1379 #endif
Damience89a212013-10-15 22:25:17 +01001380 } else {
Damien Georgec8f78bc2014-02-15 22:55:00 +00001381 // propagate exception to higher level
1382 // TODO what to do about ip and sp? they don't really make sense at this point
Damien George999cedb2015-11-27 17:01:44 +00001383 fastn[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // must put exception here because sp is invalid
Damien Georgec8f78bc2014-02-15 22:55:00 +00001384 return MP_VM_RETURN_EXCEPTION;
Damience89a212013-10-15 22:25:17 +01001385 }
Damien429d7192013-10-04 19:53:11 +01001386 }
1387 }
1388}