blob: 848a77a453a4450af3bf7be7501b2806dc77e478 [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) {
Damien Georgef4df3aa2016-01-09 23:59:52 +0000684 // pop iter and iter_buf
Damien George25c84642014-05-30 15:20:41 +0100685 sp--;
Damien Georgef4df3aa2016-01-09 23:59:52 +0000686 sp -= sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t);
Damien George25c84642014-05-30 15:20:41 +0100687 }
Damien George124df6f2014-10-25 18:19:55 +0100688 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000689 }
Damience89a212013-10-15 22:25:17 +0100690
AZ Huangb1f692e2014-04-14 23:22:44 +0800691 // matched against: POP_BLOCK or POP_EXCEPT (anything else?)
692 ENTRY(MP_BC_SETUP_EXCEPT):
Damien Georgecd97a432014-12-02 19:25:10 +0000693 ENTRY(MP_BC_SETUP_FINALLY): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200694 MARK_EXC_IP_SELECTIVE();
Damien Georgef89d6592014-12-29 00:29:59 +0000695 #if SELECTIVE_EXC_IP
696 PUSH_EXC_BLOCK((code_state->ip[-1] == MP_BC_SETUP_FINALLY) ? 1 : 0);
697 #else
698 PUSH_EXC_BLOCK((code_state->ip[0] == MP_BC_SETUP_FINALLY) ? 1 : 0);
699 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800700 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000701 }
Damience89a212013-10-15 22:25:17 +0100702
AZ Huangb1f692e2014-04-14 23:22:44 +0800703 ENTRY(MP_BC_END_FINALLY):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200704 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800705 // if TOS is None, just pops it and continues
Damien Georgef0406852016-09-27 12:37:21 +1000706 // if TOS is an integer, finishes coroutine and returns control to caller
707 // if TOS is an exception, reraises the exception
AZ Huangb1f692e2014-04-14 23:22:44 +0800708 if (TOP() == mp_const_none) {
Damien George20006db2014-01-18 14:10:48 +0000709 sp--;
Damien Georgef0406852016-09-27 12:37:21 +1000710 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800711 // We finished "finally" coroutine and now dispatch back
712 // to our caller, based on TOS value
713 mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());
Damien George5e1d9932015-03-25 22:20:37 +0000714 if (reason == UNWIND_RETURN) {
715 goto unwind_return;
716 } else {
717 assert(reason == UNWIND_JUMP);
718 goto unwind_jump;
AZ Huangb1f692e2014-04-14 23:22:44 +0800719 }
Damien Georgef0406852016-09-27 12:37:21 +1000720 } else {
721 assert(mp_obj_is_exception_instance(TOP()));
722 RAISE(TOP());
AZ Huangb1f692e2014-04-14 23:22:44 +0800723 }
724 DISPATCH();
725
726 ENTRY(MP_BC_GET_ITER):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200727 MARK_EXC_IP_SELECTIVE();
Damien Georgeae8d8672016-01-09 23:14:54 +0000728 SET_TOP(mp_getiter(TOP(), NULL));
AZ Huangb1f692e2014-04-14 23:22:44 +0800729 DISPATCH();
730
Damien Georgef4df3aa2016-01-09 23:59:52 +0000731 ENTRY(MP_BC_GET_ITER_STACK): {
732 MARK_EXC_IP_SELECTIVE();
733 mp_obj_t obj = TOP();
734 mp_obj_iter_buf_t *iter_buf = (mp_obj_iter_buf_t*)sp;
735 sp += sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t);
736 SET_TOP(mp_getiter(obj, iter_buf));
737 DISPATCH();
738 }
739
Damien Georged8675542014-05-25 22:58:04 +0100740 ENTRY(MP_BC_FOR_ITER): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200741 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800742 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgec60a2612014-06-01 12:32:28 +0100743 code_state->sp = sp;
Paul Sokolovskyc48d6f72014-05-11 20:32:39 +0300744 assert(TOP());
Damien Georged8675542014-05-25 22:58:04 +0100745 mp_obj_t value = mp_iternext_allow_raise(TOP());
746 if (value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800747 --sp; // pop the exhausted iterator
Damien Georgecd97a432014-12-02 19:25:10 +0000748 ip += ulab; // jump to after for-block
AZ Huangb1f692e2014-04-14 23:22:44 +0800749 } else {
Damien Georged8675542014-05-25 22:58:04 +0100750 PUSH(value); // push the next iteration value
AZ Huangb1f692e2014-04-14 23:22:44 +0800751 }
752 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100753 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800754
755 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
756 ENTRY(MP_BC_POP_BLOCK):
757 // we are exiting an exception handler, so pop the last one of the exception-stack
758 assert(exc_sp >= exc_stack);
759 POP_EXC_BLOCK();
760 DISPATCH();
761
762 // matched against: SETUP_EXCEPT
763 ENTRY(MP_BC_POP_EXCEPT):
AZ Huangb1f692e2014-04-14 23:22:44 +0800764 assert(exc_sp >= exc_stack);
765 assert(currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +0800766 POP_EXC_BLOCK();
AZ Huangb1f692e2014-04-14 23:22:44 +0800767 DISPATCH();
768
Damien Georgecd97a432014-12-02 19:25:10 +0000769 ENTRY(MP_BC_BUILD_TUPLE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200770 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800771 DECODE_UINT;
772 sp -= unum - 1;
773 SET_TOP(mp_obj_new_tuple(unum, sp));
774 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000775 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800776
Damien Georgecd97a432014-12-02 19:25:10 +0000777 ENTRY(MP_BC_BUILD_LIST): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200778 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800779 DECODE_UINT;
780 sp -= unum - 1;
781 SET_TOP(mp_obj_new_list(unum, sp));
782 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000783 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800784
Damien Georgecd97a432014-12-02 19:25:10 +0000785 ENTRY(MP_BC_BUILD_MAP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200786 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800787 DECODE_UINT;
788 PUSH(mp_obj_new_dict(unum));
789 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000790 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800791
792 ENTRY(MP_BC_STORE_MAP):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200793 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800794 sp -= 2;
795 mp_obj_dict_store(sp[0], sp[2], sp[1]);
796 DISPATCH();
797
Damien George3ebd4d02014-06-01 13:46:47 +0100798#if MICROPY_PY_BUILTINS_SET
Damien Georgecd97a432014-12-02 19:25:10 +0000799 ENTRY(MP_BC_BUILD_SET): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200800 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800801 DECODE_UINT;
802 sp -= unum - 1;
803 SET_TOP(mp_obj_new_set(unum, sp));
804 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000805 }
Damien George3ebd4d02014-06-01 13:46:47 +0100806#endif
Damienc12aa462013-10-16 20:57:49 +0100807
Damien Georgefb510b32014-06-01 13:32:54 +0100808#if MICROPY_PY_BUILTINS_SLICE
Damien Georgecd97a432014-12-02 19:25:10 +0000809 ENTRY(MP_BC_BUILD_SLICE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200810 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800811 DECODE_UINT;
812 if (unum == 2) {
Damien Georged8675542014-05-25 22:58:04 +0100813 mp_obj_t stop = POP();
814 mp_obj_t start = TOP();
815 SET_TOP(mp_obj_new_slice(start, stop, mp_const_none));
AZ Huangb1f692e2014-04-14 23:22:44 +0800816 } else {
Damien Georged8675542014-05-25 22:58:04 +0100817 mp_obj_t step = POP();
818 mp_obj_t stop = POP();
819 mp_obj_t start = TOP();
820 SET_TOP(mp_obj_new_slice(start, stop, step));
AZ Huangb1f692e2014-04-14 23:22:44 +0800821 }
822 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000823 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800824#endif
825
Damien Georgeadaf0d82016-09-19 08:46:01 +1000826 ENTRY(MP_BC_STORE_COMP): {
827 MARK_EXC_IP_SELECTIVE();
828 DECODE_UINT;
829 mp_obj_t obj = sp[-(unum >> 2)];
830 if ((unum & 3) == 0) {
831 mp_obj_list_append(obj, sp[0]);
832 sp--;
833 } else if (!MICROPY_PY_BUILTINS_SET || (unum & 3) == 1) {
834 mp_obj_dict_store(obj, sp[0], sp[-1]);
835 sp -= 2;
836 #if MICROPY_PY_BUILTINS_SET
837 } else {
838 mp_obj_set_store(obj, sp[0]);
839 sp--;
840 #endif
841 }
842 DISPATCH();
843 }
844
Damien Georgecd97a432014-12-02 19:25:10 +0000845 ENTRY(MP_BC_UNPACK_SEQUENCE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200846 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800847 DECODE_UINT;
848 mp_unpack_sequence(sp[0], unum, sp);
849 sp += unum - 1;
850 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000851 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800852
Damien Georgecd97a432014-12-02 19:25:10 +0000853 ENTRY(MP_BC_UNPACK_EX): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200854 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800855 DECODE_UINT;
856 mp_unpack_ex(sp[0], unum, sp);
857 sp += (unum & 0xff) + ((unum >> 8) & 0xff);
858 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000859 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800860
Damien Georgecd97a432014-12-02 19:25:10 +0000861 ENTRY(MP_BC_MAKE_FUNCTION): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800862 DECODE_PTR;
Damien Georgecd97a432014-12-02 19:25:10 +0000863 PUSH(mp_make_function_from_raw_code(ptr, MP_OBJ_NULL, MP_OBJ_NULL));
AZ Huangb1f692e2014-04-14 23:22:44 +0800864 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000865 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800866
Damien Georged8675542014-05-25 22:58:04 +0100867 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800868 DECODE_PTR;
869 // Stack layout: def_tuple def_dict <- TOS
Damien Georged8675542014-05-25 22:58:04 +0100870 mp_obj_t def_dict = POP();
Damien Georgecd97a432014-12-02 19:25:10 +0000871 SET_TOP(mp_make_function_from_raw_code(ptr, TOP(), def_dict));
AZ Huangb1f692e2014-04-14 23:22:44 +0800872 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100873 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800874
Damien George3558f622014-04-20 17:50:40 +0100875 ENTRY(MP_BC_MAKE_CLOSURE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800876 DECODE_PTR;
Damien George101886f2017-02-16 16:48:33 +1100877 size_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100878 // Stack layout: closed_overs <- TOS
879 sp -= n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000880 SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800881 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100882 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800883
Damien George3558f622014-04-20 17:50:40 +0100884 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800885 DECODE_PTR;
Damien George101886f2017-02-16 16:48:33 +1100886 size_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100887 // Stack layout: def_tuple def_dict closed_overs <- TOS
888 sp -= 2 + n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000889 SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800890 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100891 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800892
Damien Georgecd97a432014-12-02 19:25:10 +0000893 ENTRY(MP_BC_CALL_FUNCTION): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200894 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800895 DECODE_UINT;
896 // unum & 0xff == n_positional
897 // (unum >> 8) & 0xff == n_keyword
898 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
Paul Sokolovsky20397572015-03-28 01:14:44 +0200899 #if MICROPY_STACKLESS
900 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
901 code_state->ip = ip;
902 code_state->sp = sp;
903 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
Damien George581a59a2016-08-27 23:21:00 +1000904 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 +0200905 if (new_state) {
906 new_state->prev = code_state;
907 code_state = new_state;
908 nlr_pop();
909 goto run_code_state;
910 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200911 #if MICROPY_STACKLESS_STRICT
912 else {
913 deep_recursion_error:
914 mp_exc_recursion_depth();
915 }
916 #endif
Paul Sokolovsky20397572015-03-28 01:14:44 +0200917 }
918 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800919 SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
920 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000921 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800922
Damien Georgecd97a432014-12-02 19:25:10 +0000923 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200924 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800925 DECODE_UINT;
926 // unum & 0xff == n_positional
927 // (unum >> 8) & 0xff == n_keyword
928 // We have folowing stack layout here:
929 // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
930 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200931 #if MICROPY_STACKLESS
932 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
933 code_state->ip = ip;
934 code_state->sp = sp;
935 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
936
Damien George12a5e172015-04-01 23:31:30 +0100937 mp_call_args_t out_args;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200938 mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args);
939
Damien George581a59a2016-08-27 23:21:00 +1000940 mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200941 out_args.n_args, out_args.n_kw, out_args.args);
942 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
943 if (new_state) {
944 new_state->prev = code_state;
945 code_state = new_state;
946 nlr_pop();
947 goto run_code_state;
948 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200949 #if MICROPY_STACKLESS_STRICT
950 else {
951 goto deep_recursion_error;
952 }
953 #endif
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200954 }
955 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800956 SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
957 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000958 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800959
Damien Georgecd97a432014-12-02 19:25:10 +0000960 ENTRY(MP_BC_CALL_METHOD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200961 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800962 DECODE_UINT;
963 // unum & 0xff == n_positional
964 // (unum >> 8) & 0xff == n_keyword
965 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200966 #if MICROPY_STACKLESS
967 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
968 code_state->ip = ip;
969 code_state->sp = sp;
970 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
971
Damien George101886f2017-02-16 16:48:33 +1100972 size_t n_args = unum & 0xff;
973 size_t n_kw = (unum >> 8) & 0xff;
Damien George7a30e872015-12-17 12:32:41 +0000974 int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1;
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200975
Damien George581a59a2016-08-27 23:21:00 +1000976 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 +0200977 if (new_state) {
978 new_state->prev = code_state;
979 code_state = new_state;
980 nlr_pop();
981 goto run_code_state;
982 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200983 #if MICROPY_STACKLESS_STRICT
984 else {
985 goto deep_recursion_error;
986 }
987 #endif
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200988 }
989 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800990 SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
991 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000992 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800993
Damien Georgecd97a432014-12-02 19:25:10 +0000994 ENTRY(MP_BC_CALL_METHOD_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200995 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800996 DECODE_UINT;
997 // unum & 0xff == n_positional
998 // (unum >> 8) & 0xff == n_keyword
999 // We have folowing stack layout here:
1000 // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
1001 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001002 #if MICROPY_STACKLESS
1003 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
1004 code_state->ip = ip;
1005 code_state->sp = sp;
1006 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
1007
Damien George12a5e172015-04-01 23:31:30 +01001008 mp_call_args_t out_args;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001009 mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args);
1010
Damien George581a59a2016-08-27 23:21:00 +10001011 mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001012 out_args.n_args, out_args.n_kw, out_args.args);
1013 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
1014 if (new_state) {
1015 new_state->prev = code_state;
1016 code_state = new_state;
1017 nlr_pop();
1018 goto run_code_state;
1019 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +02001020 #if MICROPY_STACKLESS_STRICT
1021 else {
1022 goto deep_recursion_error;
1023 }
1024 #endif
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001025 }
1026 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001027 SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
1028 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +00001029 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001030
1031 ENTRY(MP_BC_RETURN_VALUE):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001032 MARK_EXC_IP_SELECTIVE();
Damien George80473402015-12-24 12:47:39 +00001033 // These next 3 lines pop a try-finally exception handler, if one
1034 // is there on the exception stack. Without this the finally block
1035 // is executed a second time when the return is executed, because
1036 // the try-finally exception handler is still on the stack.
1037 // TODO Possibly find a better way to handle this case.
1038 if (currently_in_except_block) {
1039 POP_EXC_BLOCK();
1040 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001041unwind_return:
1042 while (exc_sp >= exc_stack) {
Damien George74eb44c2014-12-22 12:49:57 +00001043 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
Damien George4bf3f2d2015-10-15 17:48:28 +01001044 // Getting here the stack looks like:
1045 // (..., X, [iter0, iter1, ...,] ret_val)
1046 // where X is pointed to by exc_sp->val_sp and in the case
1047 // of a "with" block contains the context manager info.
1048 // There may be 0 or more for-iterators between X and the
1049 // return value, and these must be removed before control can
1050 // pass to the finally code. We simply copy the ret_value down
1051 // over these iterators, if they exist. If they don't then the
1052 // following is a null operation.
1053 mp_obj_t *finally_sp = MP_TAGPTR_PTR(exc_sp->val_sp);
1054 finally_sp[1] = sp[0];
1055 sp = &finally_sp[1];
AZ Huangb1f692e2014-04-14 23:22:44 +08001056 // We're going to run "finally" code as a coroutine
1057 // (not calling it recursively). Set up a sentinel
1058 // on a stack so it can return back to us when it is
Damien George4bf3f2d2015-10-15 17:48:28 +01001059 // done (when WITH_CLEANUP or END_FINALLY reached).
AZ Huangb1f692e2014-04-14 23:22:44 +08001060 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
1061 ip = exc_sp->handler;
AZ Huangb1f692e2014-04-14 23:22:44 +08001062 exc_sp--;
1063 goto dispatch_loop;
1064 }
1065 exc_sp--;
1066 }
1067 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001068 code_state->sp = sp;
AZ Huangb1f692e2014-04-14 23:22:44 +08001069 assert(exc_sp == exc_stack - 1);
Damien George40d84302016-02-15 22:46:21 +00001070 MICROPY_VM_HOOK_RETURN
Paul Sokolovsky20397572015-03-28 01:14:44 +02001071 #if MICROPY_STACKLESS
1072 if (code_state->prev != NULL) {
1073 mp_obj_t res = *sp;
1074 mp_globals_set(code_state->old_globals);
1075 code_state = code_state->prev;
1076 *code_state->sp = res;
1077 goto run_code_state;
1078 }
1079 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001080 return MP_VM_RETURN_NORMAL;
1081
Damien Georged8675542014-05-25 22:58:04 +01001082 ENTRY(MP_BC_RAISE_VARARGS): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001083 MARK_EXC_IP_SELECTIVE();
Damien Georgecd97a432014-12-02 19:25:10 +00001084 mp_uint_t unum = *ip++;
Damien Georged8675542014-05-25 22:58:04 +01001085 mp_obj_t obj;
Paul Sokolovsky2ff2ea52015-09-01 10:35:58 +03001086 if (unum == 2) {
1087 mp_warning("exception chaining not supported");
1088 // ignore (pop) "from" argument
1089 sp--;
1090 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001091 if (unum == 0) {
1092 // search for the inner-most previous exception, to reraise it
Damien Georged8675542014-05-25 22:58:04 +01001093 obj = MP_OBJ_NULL;
AZ Huangb1f692e2014-04-14 23:22:44 +08001094 for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
Damien George999cedb2015-11-27 17:01:44 +00001095 if (e->prev_exc != NULL) {
1096 obj = MP_OBJ_FROM_PTR(e->prev_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +08001097 break;
1098 }
1099 }
Damien Georged8675542014-05-25 22:58:04 +01001100 if (obj == MP_OBJ_NULL) {
1101 obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
1102 RAISE(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001103 }
1104 } else {
Damien Georged8675542014-05-25 22:58:04 +01001105 obj = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +08001106 }
Damien Georged8675542014-05-25 22:58:04 +01001107 obj = mp_make_raise_obj(obj);
1108 RAISE(obj);
1109 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001110
1111 ENTRY(MP_BC_YIELD_VALUE):
1112yield:
1113 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001114 code_state->ip = ip;
1115 code_state->sp = sp;
1116 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +08001117 return MP_VM_RETURN_YIELD;
1118
1119 ENTRY(MP_BC_YIELD_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001120 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001121//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
1122#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
Damien George999cedb2015-11-27 17:01:44 +00001123#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 +08001124 mp_vm_return_kind_t ret_kind;
Damien Georged8675542014-05-25 22:58:04 +01001125 mp_obj_t send_value = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +08001126 mp_obj_t t_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +01001127 mp_obj_t ret_value;
AZ Huangb1f692e2014-04-14 23:22:44 +08001128 if (inject_exc != MP_OBJ_NULL) {
1129 t_exc = inject_exc;
1130 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +01001131 ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001132 } else {
Damien Georged8675542014-05-25 22:58:04 +01001133 ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001134 }
1135
1136 if (ret_kind == MP_VM_RETURN_YIELD) {
1137 ip--;
Damien Georged8675542014-05-25 22:58:04 +01001138 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001139 goto yield;
1140 }
1141 if (ret_kind == MP_VM_RETURN_NORMAL) {
1142 // Pop exhausted gen
1143 sp--;
Paul Sokolovskyeff85bb2016-04-28 01:54:23 +03001144 // TODO: When ret_value can be MP_OBJ_NULL here??
1145 if (ret_value == MP_OBJ_NULL || ret_value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +08001146 // Optimize StopIteration
1147 // TODO: get StopIteration's value
1148 PUSH(mp_const_none);
1149 } else {
Damien Georged8675542014-05-25 22:58:04 +01001150 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001151 }
1152
1153 // If we injected GeneratorExit downstream, then even
1154 // if it was swallowed, we re-raise GeneratorExit
1155 GENERATOR_EXIT_IF_NEEDED(t_exc);
1156 DISPATCH();
1157 }
1158 if (ret_kind == MP_VM_RETURN_EXCEPTION) {
1159 // Pop exhausted gen
1160 sp--;
Damien George999cedb2015-11-27 17:01:44 +00001161 if (EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
Damien Georged8675542014-05-25 22:58:04 +01001162 PUSH(mp_obj_exception_get_value(ret_value));
AZ Huangb1f692e2014-04-14 23:22:44 +08001163 // If we injected GeneratorExit downstream, then even
1164 // if it was swallowed, we re-raise GeneratorExit
1165 GENERATOR_EXIT_IF_NEEDED(t_exc);
1166 DISPATCH();
1167 } else {
Damien Georged8675542014-05-25 22:58:04 +01001168 RAISE(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001169 }
1170 }
Damien429d7192013-10-04 19:53:11 +01001171 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001172
Damien Georged8675542014-05-25 22:58:04 +01001173 ENTRY(MP_BC_IMPORT_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001174 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001175 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001176 mp_obj_t obj = POP();
1177 SET_TOP(mp_import_name(qst, obj, TOP()));
AZ Huangb1f692e2014-04-14 23:22:44 +08001178 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001179 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001180
Damien Georged8675542014-05-25 22:58:04 +01001181 ENTRY(MP_BC_IMPORT_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001182 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001183 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001184 mp_obj_t obj = mp_import_from(TOP(), qst);
1185 PUSH(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001186 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001187 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001188
1189 ENTRY(MP_BC_IMPORT_STAR):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001190 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001191 mp_import_all(POP());
1192 DISPATCH();
1193
Damien George8456cc02014-10-25 16:43:46 +01001194#if MICROPY_OPT_COMPUTED_GOTO
1195 ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):
1196 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1197 DISPATCH();
1198
1199 ENTRY(MP_BC_LOAD_FAST_MULTI):
1200 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1201 goto load_check;
1202
1203 ENTRY(MP_BC_STORE_FAST_MULTI):
1204 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1205 DISPATCH();
1206
1207 ENTRY(MP_BC_UNARY_OP_MULTI):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001208 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001209 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1210 DISPATCH();
1211
1212 ENTRY(MP_BC_BINARY_OP_MULTI): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001213 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001214 mp_obj_t rhs = POP();
1215 mp_obj_t lhs = TOP();
1216 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1217 DISPATCH();
1218 }
1219
1220 ENTRY_DEFAULT:
Paul Sokolovsky74957502014-12-28 07:17:43 +02001221 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001222#else
1223 ENTRY_DEFAULT:
1224 if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
1225 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1226 DISPATCH();
1227 } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
1228 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1229 goto load_check;
1230 } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
1231 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1232 DISPATCH();
Damien Georgebdbe8c92015-12-08 12:28:11 +00001233 } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 7) {
Damien George8456cc02014-10-25 16:43:46 +01001234 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1235 DISPATCH();
Damien Georgec5029bc2015-06-13 22:00:10 +01001236 } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) {
Damien George8456cc02014-10-25 16:43:46 +01001237 mp_obj_t rhs = POP();
1238 mp_obj_t lhs = TOP();
1239 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1240 DISPATCH();
1241 } else
1242#endif
1243 {
Damien Georged8675542014-05-25 22:58:04 +01001244 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
AZ Huangb1f692e2014-04-14 23:22:44 +08001245 nlr_pop();
Damien Georged8675542014-05-25 22:58:04 +01001246 fastn[0] = obj;
AZ Huangb1f692e2014-04-14 23:22:44 +08001247 return MP_VM_RETURN_EXCEPTION;
Damien Georged8675542014-05-25 22:58:04 +01001248 }
Damien George66ae8c92014-04-17 16:50:23 +01001249
Damien George58ebde42014-05-21 20:32:59 +01001250#if !MICROPY_OPT_COMPUTED_GOTO
AZ Huang9309d992014-04-15 15:57:01 +08001251 } // switch
AZ Huangb1f692e2014-04-14 23:22:44 +08001252#endif
Damien George124df6f2014-10-25 18:19:55 +01001253
1254pending_exception_check:
Damien George40d84302016-02-15 22:46:21 +00001255 MICROPY_VM_HOOK_LOOP
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001256 if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001257 MARK_EXC_IP_SELECTIVE();
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001258 mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
1259 MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
Damien George124df6f2014-10-25 18:19:55 +01001260 RAISE(obj);
1261 }
Damien George124df6f2014-10-25 18:19:55 +01001262
Damien Georgef6c22a02017-02-06 10:50:43 +11001263 #if MICROPY_PY_THREAD_GIL
1264 #if MICROPY_PY_THREAD_GIL_VM_DIVISOR
1265 if (--gil_divisor == 0) {
1266 gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
1267 #else
1268 {
1269 #endif
1270 MP_THREAD_GIL_EXIT();
1271 MP_THREAD_GIL_ENTER();
1272 }
1273 #endif
Damien George4cec63a2016-05-26 10:42:53 +00001274
Damien George66ae8c92014-04-17 16:50:23 +01001275 } // for loop
Damien429d7192013-10-04 19:53:11 +01001276
Damience89a212013-10-15 22:25:17 +01001277 } else {
Damien George66ae8c92014-04-17 16:50:23 +01001278exception_handler:
Damience89a212013-10-15 22:25:17 +01001279 // exception occurred
Damien429d7192013-10-04 19:53:11 +01001280
Paul Sokolovsky8b85d142015-04-25 03:17:41 +03001281 #if MICROPY_PY_SYS_EXC_INFO
1282 MP_STATE_VM(cur_exception) = nlr.ret_val;
1283 #endif
1284
Damien Georgef89d6592014-12-29 00:29:59 +00001285 #if SELECTIVE_EXC_IP
1286 // with selective ip, we store the ip 1 byte past the opcode, so move ptr back
1287 code_state->ip -= 1;
1288 #endif
1289
Damien George999cedb2015-11-27 17:01:44 +00001290 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 +03001291 if (code_state->ip) {
1292 // check if it's a StopIteration within a for block
1293 if (*code_state->ip == MP_BC_FOR_ITER) {
1294 const byte *ip = code_state->ip + 1;
1295 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
1296 code_state->ip = ip + ulab; // jump to after for-block
1297 code_state->sp -= 1; // pop the exhausted iterator
1298 goto outer_dispatch_loop; // continue with dispatch loop
Paul Sokolovsky6738c1d2015-05-11 02:59:25 +03001299 } else if (*code_state->ip == MP_BC_YIELD_FROM) {
1300 // StopIteration inside yield from call means return a value of
1301 // yield from, so inject exception's value as yield from's result
Damien George999cedb2015-11-27 17:01:44 +00001302 *++code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));
Paul Sokolovsky6738c1d2015-05-11 02:59:25 +03001303 code_state->ip++; // yield from is over, move to next instruction
1304 goto outer_dispatch_loop; // continue with dispatch loop
Paul Sokolovskya7c02c42015-05-10 17:18:10 +03001305 }
1306 }
Damien George9e6e9352014-03-26 18:37:06 +00001307 }
1308
Paul Sokolovsky20397572015-03-28 01:14:44 +02001309#if MICROPY_STACKLESS
1310unwind_loop:
1311#endif
Damien George08335002014-01-18 23:24:36 +00001312 // set file and line number that the exception occurred at
Paul Sokolovsky382e8ee2014-01-30 13:49:18 +02001313 // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
1314 // But consider how to handle nested exceptions.
Damien George6902eed2014-04-04 10:52:59 +00001315 // 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 +00001316 if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
Damien Georgeb534e1b2014-09-04 14:44:01 +01001317 const byte *ip = code_state->code_info;
Damien George101886f2017-02-16 16:48:33 +11001318 size_t code_info_size = mp_decode_uint(&ip);
Damien Georgec8e9c0d2015-11-02 17:27:18 +00001319 #if MICROPY_PERSISTENT_CODE
1320 qstr block_name = ip[0] | (ip[1] << 8);
1321 qstr source_file = ip[2] | (ip[3] << 8);
1322 ip += 4;
1323 #else
Damien Georgeb534e1b2014-09-04 14:44:01 +01001324 qstr block_name = mp_decode_uint(&ip);
1325 qstr source_file = mp_decode_uint(&ip);
Damien Georgec8e9c0d2015-11-02 17:27:18 +00001326 #endif
Damien George3d2daa22016-01-02 22:04:12 +00001327 size_t bc = code_state->ip - code_state->code_info - code_info_size;
1328 size_t source_line = 1;
1329 size_t c;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001330 while ((c = *ip)) {
Damien George101886f2017-02-16 16:48:33 +11001331 size_t b, l;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001332 if ((c & 0x80) == 0) {
1333 // 0b0LLBBBBB encoding
1334 b = c & 0x1f;
1335 l = c >> 5;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001336 ip += 1;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001337 } else {
1338 // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
1339 b = c & 0xf;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001340 l = ((c << 4) & 0x700) | ip[1];
1341 ip += 2;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001342 }
1343 if (bc >= b) {
1344 bc -= b;
1345 source_line += l;
1346 } else {
1347 // found source line corresponding to bytecode offset
1348 break;
Paul Sokolovsky411732e2014-06-02 18:24:34 +03001349 }
Damien George08335002014-01-18 23:24:36 +00001350 }
Damien George999cedb2015-11-27 17:01:44 +00001351 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 +00001352 }
1353
Damien8f9e2ee2013-12-29 16:54:59 +00001354 while (currently_in_except_block) {
1355 // nested exception
1356
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001357 assert(exc_sp >= exc_stack);
Damien8f9e2ee2013-12-29 16:54:59 +00001358
1359 // TODO make a proper message for nested exception
1360 // at the moment we are just raising the very last exception (the one that caused the nested exception)
1361
1362 // move up to previous exception handler
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +02001363 POP_EXC_BLOCK();
Damien8f9e2ee2013-12-29 16:54:59 +00001364 }
1365
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001366 if (exc_sp >= exc_stack) {
Damien8f9e2ee2013-12-29 16:54:59 +00001367 // set flag to indicate that we are now handling an exception
1368 currently_in_except_block = 1;
1369
Damience89a212013-10-15 22:25:17 +01001370 // catch exception and pass to byte code
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001371 code_state->ip = exc_sp->handler;
Damien George66ae8c92014-04-17 16:50:23 +01001372 mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
Damien Georged7592a12014-03-30 00:54:48 +00001373 // save this exception in the stack so it can be used in a reraise, if needed
1374 exc_sp->prev_exc = nlr.ret_val;
Damien Georgef0406852016-09-27 12:37:21 +10001375 // push exception object so it can be handled by bytecode
Damien George999cedb2015-11-27 17:01:44 +00001376 PUSH(MP_OBJ_FROM_PTR(nlr.ret_val));
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001377 code_state->sp = sp;
Damien8f9e2ee2013-12-29 16:54:59 +00001378
Paul Sokolovsky20397572015-03-28 01:14:44 +02001379 #if MICROPY_STACKLESS
1380 } else if (code_state->prev != NULL) {
1381 mp_globals_set(code_state->old_globals);
1382 code_state = code_state->prev;
1383 fastn = &code_state->state[code_state->n_state - 1];
1384 exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
1385 // variables that are visible to the exception handler (declared volatile)
1386 currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
1387 exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
1388 goto unwind_loop;
1389
1390 #endif
Damience89a212013-10-15 22:25:17 +01001391 } else {
Damien Georgec8f78bc2014-02-15 22:55:00 +00001392 // propagate exception to higher level
1393 // TODO what to do about ip and sp? they don't really make sense at this point
Damien George999cedb2015-11-27 17:01:44 +00001394 fastn[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // must put exception here because sp is invalid
Damien Georgec8f78bc2014-02-15 22:55:00 +00001395 return MP_VM_RETURN_EXCEPTION;
Damience89a212013-10-15 22:25:17 +01001396 }
Damien429d7192013-10-04 19:53:11 +01001397 }
1398 }
1399}