blob: 7a906cd8048d776cde10a256ae4ad573848ea4c1 [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 George088740e2017-01-17 15:27:37 +1100731 // An iterator for a for-loop takes 4 slots on the stack. They are either
732 // used to store the iterator object itself, or the first slot is NULL and
733 // the second slot holds a reference to the iterator object.
Damien Georgef4df3aa2016-01-09 23:59:52 +0000734 ENTRY(MP_BC_GET_ITER_STACK): {
735 MARK_EXC_IP_SELECTIVE();
736 mp_obj_t obj = TOP();
737 mp_obj_iter_buf_t *iter_buf = (mp_obj_iter_buf_t*)sp;
Damien George088740e2017-01-17 15:27:37 +1100738 sp += sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1;
739 obj = mp_getiter(obj, iter_buf);
740 if (obj != MP_OBJ_FROM_PTR(iter_buf)) {
741 // Iterator didn't use the stack so indicate that with MP_OBJ_NULL.
742 sp[-3] = MP_OBJ_NULL;
743 sp[-2] = obj;
744 }
Damien Georgef4df3aa2016-01-09 23:59:52 +0000745 DISPATCH();
746 }
747
Damien Georged8675542014-05-25 22:58:04 +0100748 ENTRY(MP_BC_FOR_ITER): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200749 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800750 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgec60a2612014-06-01 12:32:28 +0100751 code_state->sp = sp;
Damien George088740e2017-01-17 15:27:37 +1100752 mp_obj_t obj;
753 if (sp[-3] == MP_OBJ_NULL) {
754 obj = sp[-2];
755 } else {
756 obj = MP_OBJ_FROM_PTR(&sp[-3]);
757 }
758 mp_obj_t value = mp_iternext_allow_raise(obj);
Damien Georged8675542014-05-25 22:58:04 +0100759 if (value == MP_OBJ_STOP_ITERATION) {
Damien George088740e2017-01-17 15:27:37 +1100760 sp -= 4; // pop the exhausted iterator
Damien Georgecd97a432014-12-02 19:25:10 +0000761 ip += ulab; // jump to after for-block
AZ Huangb1f692e2014-04-14 23:22:44 +0800762 } else {
Damien Georged8675542014-05-25 22:58:04 +0100763 PUSH(value); // push the next iteration value
AZ Huangb1f692e2014-04-14 23:22:44 +0800764 }
765 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100766 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800767
768 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
769 ENTRY(MP_BC_POP_BLOCK):
770 // we are exiting an exception handler, so pop the last one of the exception-stack
771 assert(exc_sp >= exc_stack);
772 POP_EXC_BLOCK();
773 DISPATCH();
774
775 // matched against: SETUP_EXCEPT
776 ENTRY(MP_BC_POP_EXCEPT):
AZ Huangb1f692e2014-04-14 23:22:44 +0800777 assert(exc_sp >= exc_stack);
778 assert(currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +0800779 POP_EXC_BLOCK();
AZ Huangb1f692e2014-04-14 23:22:44 +0800780 DISPATCH();
781
Damien Georgecd97a432014-12-02 19:25:10 +0000782 ENTRY(MP_BC_BUILD_TUPLE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200783 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800784 DECODE_UINT;
785 sp -= unum - 1;
786 SET_TOP(mp_obj_new_tuple(unum, sp));
787 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000788 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800789
Damien Georgecd97a432014-12-02 19:25:10 +0000790 ENTRY(MP_BC_BUILD_LIST): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200791 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800792 DECODE_UINT;
793 sp -= unum - 1;
794 SET_TOP(mp_obj_new_list(unum, sp));
795 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000796 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800797
Damien Georgecd97a432014-12-02 19:25:10 +0000798 ENTRY(MP_BC_BUILD_MAP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200799 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800800 DECODE_UINT;
801 PUSH(mp_obj_new_dict(unum));
802 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000803 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800804
805 ENTRY(MP_BC_STORE_MAP):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200806 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800807 sp -= 2;
808 mp_obj_dict_store(sp[0], sp[2], sp[1]);
809 DISPATCH();
810
Damien George3ebd4d02014-06-01 13:46:47 +0100811#if MICROPY_PY_BUILTINS_SET
Damien Georgecd97a432014-12-02 19:25:10 +0000812 ENTRY(MP_BC_BUILD_SET): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200813 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800814 DECODE_UINT;
815 sp -= unum - 1;
816 SET_TOP(mp_obj_new_set(unum, sp));
817 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000818 }
Damien George3ebd4d02014-06-01 13:46:47 +0100819#endif
Damienc12aa462013-10-16 20:57:49 +0100820
Damien Georgefb510b32014-06-01 13:32:54 +0100821#if MICROPY_PY_BUILTINS_SLICE
Damien Georgecd97a432014-12-02 19:25:10 +0000822 ENTRY(MP_BC_BUILD_SLICE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200823 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800824 DECODE_UINT;
825 if (unum == 2) {
Damien Georged8675542014-05-25 22:58:04 +0100826 mp_obj_t stop = POP();
827 mp_obj_t start = TOP();
828 SET_TOP(mp_obj_new_slice(start, stop, mp_const_none));
AZ Huangb1f692e2014-04-14 23:22:44 +0800829 } else {
Damien Georged8675542014-05-25 22:58:04 +0100830 mp_obj_t step = POP();
831 mp_obj_t stop = POP();
832 mp_obj_t start = TOP();
833 SET_TOP(mp_obj_new_slice(start, stop, step));
AZ Huangb1f692e2014-04-14 23:22:44 +0800834 }
835 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000836 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800837#endif
838
Damien Georgeadaf0d82016-09-19 08:46:01 +1000839 ENTRY(MP_BC_STORE_COMP): {
840 MARK_EXC_IP_SELECTIVE();
841 DECODE_UINT;
842 mp_obj_t obj = sp[-(unum >> 2)];
843 if ((unum & 3) == 0) {
844 mp_obj_list_append(obj, sp[0]);
845 sp--;
846 } else if (!MICROPY_PY_BUILTINS_SET || (unum & 3) == 1) {
847 mp_obj_dict_store(obj, sp[0], sp[-1]);
848 sp -= 2;
849 #if MICROPY_PY_BUILTINS_SET
850 } else {
851 mp_obj_set_store(obj, sp[0]);
852 sp--;
853 #endif
854 }
855 DISPATCH();
856 }
857
Damien Georgecd97a432014-12-02 19:25:10 +0000858 ENTRY(MP_BC_UNPACK_SEQUENCE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200859 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800860 DECODE_UINT;
861 mp_unpack_sequence(sp[0], unum, sp);
862 sp += unum - 1;
863 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000864 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800865
Damien Georgecd97a432014-12-02 19:25:10 +0000866 ENTRY(MP_BC_UNPACK_EX): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200867 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800868 DECODE_UINT;
869 mp_unpack_ex(sp[0], unum, sp);
870 sp += (unum & 0xff) + ((unum >> 8) & 0xff);
871 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000872 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800873
Damien Georgecd97a432014-12-02 19:25:10 +0000874 ENTRY(MP_BC_MAKE_FUNCTION): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800875 DECODE_PTR;
Damien Georgecd97a432014-12-02 19:25:10 +0000876 PUSH(mp_make_function_from_raw_code(ptr, MP_OBJ_NULL, MP_OBJ_NULL));
AZ Huangb1f692e2014-04-14 23:22:44 +0800877 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000878 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800879
Damien Georged8675542014-05-25 22:58:04 +0100880 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800881 DECODE_PTR;
882 // Stack layout: def_tuple def_dict <- TOS
Damien Georged8675542014-05-25 22:58:04 +0100883 mp_obj_t def_dict = POP();
Damien Georgecd97a432014-12-02 19:25:10 +0000884 SET_TOP(mp_make_function_from_raw_code(ptr, TOP(), def_dict));
AZ Huangb1f692e2014-04-14 23:22:44 +0800885 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100886 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800887
Damien George3558f622014-04-20 17:50:40 +0100888 ENTRY(MP_BC_MAKE_CLOSURE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800889 DECODE_PTR;
Damien George101886f2017-02-16 16:48:33 +1100890 size_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100891 // Stack layout: closed_overs <- TOS
892 sp -= n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000893 SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800894 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100895 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800896
Damien George3558f622014-04-20 17:50:40 +0100897 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800898 DECODE_PTR;
Damien George101886f2017-02-16 16:48:33 +1100899 size_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100900 // Stack layout: def_tuple def_dict closed_overs <- TOS
901 sp -= 2 + n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000902 SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800903 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100904 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800905
Damien Georgecd97a432014-12-02 19:25:10 +0000906 ENTRY(MP_BC_CALL_FUNCTION): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200907 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800908 DECODE_UINT;
909 // unum & 0xff == n_positional
910 // (unum >> 8) & 0xff == n_keyword
911 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
Paul Sokolovsky20397572015-03-28 01:14:44 +0200912 #if MICROPY_STACKLESS
913 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
914 code_state->ip = ip;
915 code_state->sp = sp;
916 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
Damien George581a59a2016-08-27 23:21:00 +1000917 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 +0200918 if (new_state) {
919 new_state->prev = code_state;
920 code_state = new_state;
921 nlr_pop();
922 goto run_code_state;
923 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200924 #if MICROPY_STACKLESS_STRICT
925 else {
926 deep_recursion_error:
927 mp_exc_recursion_depth();
928 }
929 #endif
Paul Sokolovsky20397572015-03-28 01:14:44 +0200930 }
931 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800932 SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
933 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000934 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800935
Damien Georgecd97a432014-12-02 19:25:10 +0000936 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200937 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800938 DECODE_UINT;
939 // unum & 0xff == n_positional
940 // (unum >> 8) & 0xff == n_keyword
941 // We have folowing stack layout here:
942 // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
943 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200944 #if MICROPY_STACKLESS
945 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
946 code_state->ip = ip;
947 code_state->sp = sp;
948 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
949
Damien George12a5e172015-04-01 23:31:30 +0100950 mp_call_args_t out_args;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200951 mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args);
952
Damien George581a59a2016-08-27 23:21:00 +1000953 mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200954 out_args.n_args, out_args.n_kw, out_args.args);
955 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
956 if (new_state) {
957 new_state->prev = code_state;
958 code_state = new_state;
959 nlr_pop();
960 goto run_code_state;
961 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200962 #if MICROPY_STACKLESS_STRICT
963 else {
964 goto deep_recursion_error;
965 }
966 #endif
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200967 }
968 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800969 SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
970 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000971 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800972
Damien Georgecd97a432014-12-02 19:25:10 +0000973 ENTRY(MP_BC_CALL_METHOD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200974 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800975 DECODE_UINT;
976 // unum & 0xff == n_positional
977 // (unum >> 8) & 0xff == n_keyword
978 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200979 #if MICROPY_STACKLESS
980 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
981 code_state->ip = ip;
982 code_state->sp = sp;
983 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
984
Damien George101886f2017-02-16 16:48:33 +1100985 size_t n_args = unum & 0xff;
986 size_t n_kw = (unum >> 8) & 0xff;
Damien George7a30e872015-12-17 12:32:41 +0000987 int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1;
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200988
Damien George581a59a2016-08-27 23:21:00 +1000989 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 +0200990 if (new_state) {
991 new_state->prev = code_state;
992 code_state = new_state;
993 nlr_pop();
994 goto run_code_state;
995 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200996 #if MICROPY_STACKLESS_STRICT
997 else {
998 goto deep_recursion_error;
999 }
1000 #endif
Paul Sokolovsky390e9262015-03-28 01:14:44 +02001001 }
1002 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001003 SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
1004 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +00001005 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001006
Damien Georgecd97a432014-12-02 19:25:10 +00001007 ENTRY(MP_BC_CALL_METHOD_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001008 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001009 DECODE_UINT;
1010 // unum & 0xff == n_positional
1011 // (unum >> 8) & 0xff == n_keyword
1012 // We have folowing stack layout here:
1013 // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
1014 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001015 #if MICROPY_STACKLESS
1016 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
1017 code_state->ip = ip;
1018 code_state->sp = sp;
1019 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
1020
Damien George12a5e172015-04-01 23:31:30 +01001021 mp_call_args_t out_args;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001022 mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args);
1023
Damien George581a59a2016-08-27 23:21:00 +10001024 mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001025 out_args.n_args, out_args.n_kw, out_args.args);
1026 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
1027 if (new_state) {
1028 new_state->prev = code_state;
1029 code_state = new_state;
1030 nlr_pop();
1031 goto run_code_state;
1032 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +02001033 #if MICROPY_STACKLESS_STRICT
1034 else {
1035 goto deep_recursion_error;
1036 }
1037 #endif
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001038 }
1039 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001040 SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
1041 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +00001042 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001043
1044 ENTRY(MP_BC_RETURN_VALUE):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001045 MARK_EXC_IP_SELECTIVE();
Damien George80473402015-12-24 12:47:39 +00001046 // These next 3 lines pop a try-finally exception handler, if one
1047 // is there on the exception stack. Without this the finally block
1048 // is executed a second time when the return is executed, because
1049 // the try-finally exception handler is still on the stack.
1050 // TODO Possibly find a better way to handle this case.
1051 if (currently_in_except_block) {
1052 POP_EXC_BLOCK();
1053 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001054unwind_return:
1055 while (exc_sp >= exc_stack) {
Damien George74eb44c2014-12-22 12:49:57 +00001056 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
Damien George4bf3f2d2015-10-15 17:48:28 +01001057 // Getting here the stack looks like:
1058 // (..., X, [iter0, iter1, ...,] ret_val)
1059 // where X is pointed to by exc_sp->val_sp and in the case
1060 // of a "with" block contains the context manager info.
1061 // There may be 0 or more for-iterators between X and the
1062 // return value, and these must be removed before control can
1063 // pass to the finally code. We simply copy the ret_value down
1064 // over these iterators, if they exist. If they don't then the
1065 // following is a null operation.
1066 mp_obj_t *finally_sp = MP_TAGPTR_PTR(exc_sp->val_sp);
1067 finally_sp[1] = sp[0];
1068 sp = &finally_sp[1];
AZ Huangb1f692e2014-04-14 23:22:44 +08001069 // We're going to run "finally" code as a coroutine
1070 // (not calling it recursively). Set up a sentinel
1071 // on a stack so it can return back to us when it is
Damien George4bf3f2d2015-10-15 17:48:28 +01001072 // done (when WITH_CLEANUP or END_FINALLY reached).
AZ Huangb1f692e2014-04-14 23:22:44 +08001073 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
1074 ip = exc_sp->handler;
AZ Huangb1f692e2014-04-14 23:22:44 +08001075 exc_sp--;
1076 goto dispatch_loop;
1077 }
1078 exc_sp--;
1079 }
1080 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001081 code_state->sp = sp;
AZ Huangb1f692e2014-04-14 23:22:44 +08001082 assert(exc_sp == exc_stack - 1);
Damien George40d84302016-02-15 22:46:21 +00001083 MICROPY_VM_HOOK_RETURN
Paul Sokolovsky20397572015-03-28 01:14:44 +02001084 #if MICROPY_STACKLESS
1085 if (code_state->prev != NULL) {
1086 mp_obj_t res = *sp;
1087 mp_globals_set(code_state->old_globals);
1088 code_state = code_state->prev;
1089 *code_state->sp = res;
1090 goto run_code_state;
1091 }
1092 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001093 return MP_VM_RETURN_NORMAL;
1094
Damien Georged8675542014-05-25 22:58:04 +01001095 ENTRY(MP_BC_RAISE_VARARGS): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001096 MARK_EXC_IP_SELECTIVE();
Damien Georgecd97a432014-12-02 19:25:10 +00001097 mp_uint_t unum = *ip++;
Damien Georged8675542014-05-25 22:58:04 +01001098 mp_obj_t obj;
Paul Sokolovsky2ff2ea52015-09-01 10:35:58 +03001099 if (unum == 2) {
1100 mp_warning("exception chaining not supported");
1101 // ignore (pop) "from" argument
1102 sp--;
1103 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001104 if (unum == 0) {
1105 // search for the inner-most previous exception, to reraise it
Damien Georged8675542014-05-25 22:58:04 +01001106 obj = MP_OBJ_NULL;
AZ Huangb1f692e2014-04-14 23:22:44 +08001107 for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
Damien George999cedb2015-11-27 17:01:44 +00001108 if (e->prev_exc != NULL) {
1109 obj = MP_OBJ_FROM_PTR(e->prev_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +08001110 break;
1111 }
1112 }
Damien Georged8675542014-05-25 22:58:04 +01001113 if (obj == MP_OBJ_NULL) {
1114 obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
1115 RAISE(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001116 }
1117 } else {
Damien Georged8675542014-05-25 22:58:04 +01001118 obj = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +08001119 }
Damien Georged8675542014-05-25 22:58:04 +01001120 obj = mp_make_raise_obj(obj);
1121 RAISE(obj);
1122 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001123
1124 ENTRY(MP_BC_YIELD_VALUE):
1125yield:
1126 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001127 code_state->ip = ip;
1128 code_state->sp = sp;
1129 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +08001130 return MP_VM_RETURN_YIELD;
1131
1132 ENTRY(MP_BC_YIELD_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001133 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001134//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
1135#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
Damien George999cedb2015-11-27 17:01:44 +00001136#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 +08001137 mp_vm_return_kind_t ret_kind;
Damien Georged8675542014-05-25 22:58:04 +01001138 mp_obj_t send_value = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +08001139 mp_obj_t t_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +01001140 mp_obj_t ret_value;
AZ Huangb1f692e2014-04-14 23:22:44 +08001141 if (inject_exc != MP_OBJ_NULL) {
1142 t_exc = inject_exc;
1143 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +01001144 ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001145 } else {
Damien Georged8675542014-05-25 22:58:04 +01001146 ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001147 }
1148
1149 if (ret_kind == MP_VM_RETURN_YIELD) {
1150 ip--;
Damien Georged8675542014-05-25 22:58:04 +01001151 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001152 goto yield;
1153 }
1154 if (ret_kind == MP_VM_RETURN_NORMAL) {
1155 // Pop exhausted gen
1156 sp--;
Paul Sokolovskyeff85bb2016-04-28 01:54:23 +03001157 // TODO: When ret_value can be MP_OBJ_NULL here??
1158 if (ret_value == MP_OBJ_NULL || ret_value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +08001159 // Optimize StopIteration
1160 // TODO: get StopIteration's value
1161 PUSH(mp_const_none);
1162 } else {
Damien Georged8675542014-05-25 22:58:04 +01001163 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001164 }
1165
1166 // If we injected GeneratorExit downstream, then even
1167 // if it was swallowed, we re-raise GeneratorExit
1168 GENERATOR_EXIT_IF_NEEDED(t_exc);
1169 DISPATCH();
1170 }
1171 if (ret_kind == MP_VM_RETURN_EXCEPTION) {
1172 // Pop exhausted gen
1173 sp--;
Damien George999cedb2015-11-27 17:01:44 +00001174 if (EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
Damien Georged8675542014-05-25 22:58:04 +01001175 PUSH(mp_obj_exception_get_value(ret_value));
AZ Huangb1f692e2014-04-14 23:22:44 +08001176 // If we injected GeneratorExit downstream, then even
1177 // if it was swallowed, we re-raise GeneratorExit
1178 GENERATOR_EXIT_IF_NEEDED(t_exc);
1179 DISPATCH();
1180 } else {
Damien Georged8675542014-05-25 22:58:04 +01001181 RAISE(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001182 }
1183 }
Damien429d7192013-10-04 19:53:11 +01001184 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001185
Damien Georged8675542014-05-25 22:58:04 +01001186 ENTRY(MP_BC_IMPORT_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001187 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001188 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001189 mp_obj_t obj = POP();
1190 SET_TOP(mp_import_name(qst, obj, TOP()));
AZ Huangb1f692e2014-04-14 23:22:44 +08001191 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001192 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001193
Damien Georged8675542014-05-25 22:58:04 +01001194 ENTRY(MP_BC_IMPORT_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001195 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001196 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001197 mp_obj_t obj = mp_import_from(TOP(), qst);
1198 PUSH(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001199 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001200 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001201
1202 ENTRY(MP_BC_IMPORT_STAR):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001203 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001204 mp_import_all(POP());
1205 DISPATCH();
1206
Damien George8456cc02014-10-25 16:43:46 +01001207#if MICROPY_OPT_COMPUTED_GOTO
1208 ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):
1209 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1210 DISPATCH();
1211
1212 ENTRY(MP_BC_LOAD_FAST_MULTI):
1213 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1214 goto load_check;
1215
1216 ENTRY(MP_BC_STORE_FAST_MULTI):
1217 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1218 DISPATCH();
1219
1220 ENTRY(MP_BC_UNARY_OP_MULTI):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001221 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001222 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1223 DISPATCH();
1224
1225 ENTRY(MP_BC_BINARY_OP_MULTI): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001226 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001227 mp_obj_t rhs = POP();
1228 mp_obj_t lhs = TOP();
1229 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1230 DISPATCH();
1231 }
1232
1233 ENTRY_DEFAULT:
Paul Sokolovsky74957502014-12-28 07:17:43 +02001234 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001235#else
1236 ENTRY_DEFAULT:
1237 if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
1238 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1239 DISPATCH();
1240 } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
1241 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1242 goto load_check;
1243 } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
1244 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1245 DISPATCH();
Damien Georgebdbe8c92015-12-08 12:28:11 +00001246 } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 7) {
Damien George8456cc02014-10-25 16:43:46 +01001247 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1248 DISPATCH();
Damien Georgec5029bc2015-06-13 22:00:10 +01001249 } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) {
Damien George8456cc02014-10-25 16:43:46 +01001250 mp_obj_t rhs = POP();
1251 mp_obj_t lhs = TOP();
1252 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1253 DISPATCH();
1254 } else
1255#endif
1256 {
Damien Georged8675542014-05-25 22:58:04 +01001257 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
AZ Huangb1f692e2014-04-14 23:22:44 +08001258 nlr_pop();
Damien Georged8675542014-05-25 22:58:04 +01001259 fastn[0] = obj;
AZ Huangb1f692e2014-04-14 23:22:44 +08001260 return MP_VM_RETURN_EXCEPTION;
Damien Georged8675542014-05-25 22:58:04 +01001261 }
Damien George66ae8c92014-04-17 16:50:23 +01001262
Damien George58ebde42014-05-21 20:32:59 +01001263#if !MICROPY_OPT_COMPUTED_GOTO
AZ Huang9309d992014-04-15 15:57:01 +08001264 } // switch
AZ Huangb1f692e2014-04-14 23:22:44 +08001265#endif
Damien George124df6f2014-10-25 18:19:55 +01001266
1267pending_exception_check:
Damien George40d84302016-02-15 22:46:21 +00001268 MICROPY_VM_HOOK_LOOP
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001269 if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001270 MARK_EXC_IP_SELECTIVE();
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001271 mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
1272 MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
Damien George124df6f2014-10-25 18:19:55 +01001273 RAISE(obj);
1274 }
Damien George124df6f2014-10-25 18:19:55 +01001275
Damien Georgef6c22a02017-02-06 10:50:43 +11001276 #if MICROPY_PY_THREAD_GIL
1277 #if MICROPY_PY_THREAD_GIL_VM_DIVISOR
1278 if (--gil_divisor == 0) {
1279 gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
1280 #else
1281 {
1282 #endif
1283 MP_THREAD_GIL_EXIT();
1284 MP_THREAD_GIL_ENTER();
1285 }
1286 #endif
Damien George4cec63a2016-05-26 10:42:53 +00001287
Damien George66ae8c92014-04-17 16:50:23 +01001288 } // for loop
Damien429d7192013-10-04 19:53:11 +01001289
Damience89a212013-10-15 22:25:17 +01001290 } else {
Damien George66ae8c92014-04-17 16:50:23 +01001291exception_handler:
Damience89a212013-10-15 22:25:17 +01001292 // exception occurred
Damien429d7192013-10-04 19:53:11 +01001293
Paul Sokolovsky8b85d142015-04-25 03:17:41 +03001294 #if MICROPY_PY_SYS_EXC_INFO
1295 MP_STATE_VM(cur_exception) = nlr.ret_val;
1296 #endif
1297
Damien Georgef89d6592014-12-29 00:29:59 +00001298 #if SELECTIVE_EXC_IP
1299 // with selective ip, we store the ip 1 byte past the opcode, so move ptr back
1300 code_state->ip -= 1;
1301 #endif
1302
Damien George999cedb2015-11-27 17:01:44 +00001303 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 +03001304 if (code_state->ip) {
1305 // check if it's a StopIteration within a for block
1306 if (*code_state->ip == MP_BC_FOR_ITER) {
1307 const byte *ip = code_state->ip + 1;
1308 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
1309 code_state->ip = ip + ulab; // jump to after for-block
Damien George088740e2017-01-17 15:27:37 +11001310 code_state->sp -= 4; // pop the exhausted iterator
Paul Sokolovskya7c02c42015-05-10 17:18:10 +03001311 goto outer_dispatch_loop; // continue with dispatch loop
Paul Sokolovsky6738c1d2015-05-11 02:59:25 +03001312 } else if (*code_state->ip == MP_BC_YIELD_FROM) {
1313 // StopIteration inside yield from call means return a value of
1314 // yield from, so inject exception's value as yield from's result
Damien George999cedb2015-11-27 17:01:44 +00001315 *++code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));
Paul Sokolovsky6738c1d2015-05-11 02:59:25 +03001316 code_state->ip++; // yield from is over, move to next instruction
1317 goto outer_dispatch_loop; // continue with dispatch loop
Paul Sokolovskya7c02c42015-05-10 17:18:10 +03001318 }
1319 }
Damien George9e6e9352014-03-26 18:37:06 +00001320 }
1321
Paul Sokolovsky20397572015-03-28 01:14:44 +02001322#if MICROPY_STACKLESS
1323unwind_loop:
1324#endif
Damien George08335002014-01-18 23:24:36 +00001325 // set file and line number that the exception occurred at
Paul Sokolovsky382e8ee2014-01-30 13:49:18 +02001326 // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
1327 // But consider how to handle nested exceptions.
Damien George6902eed2014-04-04 10:52:59 +00001328 // 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 +00001329 if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
Damien Georgeb534e1b2014-09-04 14:44:01 +01001330 const byte *ip = code_state->code_info;
Damien George101886f2017-02-16 16:48:33 +11001331 size_t code_info_size = mp_decode_uint(&ip);
Damien Georgec8e9c0d2015-11-02 17:27:18 +00001332 #if MICROPY_PERSISTENT_CODE
1333 qstr block_name = ip[0] | (ip[1] << 8);
1334 qstr source_file = ip[2] | (ip[3] << 8);
1335 ip += 4;
1336 #else
Damien Georgeb534e1b2014-09-04 14:44:01 +01001337 qstr block_name = mp_decode_uint(&ip);
1338 qstr source_file = mp_decode_uint(&ip);
Damien Georgec8e9c0d2015-11-02 17:27:18 +00001339 #endif
Damien George3d2daa22016-01-02 22:04:12 +00001340 size_t bc = code_state->ip - code_state->code_info - code_info_size;
1341 size_t source_line = 1;
1342 size_t c;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001343 while ((c = *ip)) {
Damien George101886f2017-02-16 16:48:33 +11001344 size_t b, l;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001345 if ((c & 0x80) == 0) {
1346 // 0b0LLBBBBB encoding
1347 b = c & 0x1f;
1348 l = c >> 5;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001349 ip += 1;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001350 } else {
1351 // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
1352 b = c & 0xf;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001353 l = ((c << 4) & 0x700) | ip[1];
1354 ip += 2;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001355 }
1356 if (bc >= b) {
1357 bc -= b;
1358 source_line += l;
1359 } else {
1360 // found source line corresponding to bytecode offset
1361 break;
Paul Sokolovsky411732e2014-06-02 18:24:34 +03001362 }
Damien George08335002014-01-18 23:24:36 +00001363 }
Damien George999cedb2015-11-27 17:01:44 +00001364 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 +00001365 }
1366
Damien8f9e2ee2013-12-29 16:54:59 +00001367 while (currently_in_except_block) {
1368 // nested exception
1369
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001370 assert(exc_sp >= exc_stack);
Damien8f9e2ee2013-12-29 16:54:59 +00001371
1372 // TODO make a proper message for nested exception
1373 // at the moment we are just raising the very last exception (the one that caused the nested exception)
1374
1375 // move up to previous exception handler
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +02001376 POP_EXC_BLOCK();
Damien8f9e2ee2013-12-29 16:54:59 +00001377 }
1378
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001379 if (exc_sp >= exc_stack) {
Damien8f9e2ee2013-12-29 16:54:59 +00001380 // set flag to indicate that we are now handling an exception
1381 currently_in_except_block = 1;
1382
Damience89a212013-10-15 22:25:17 +01001383 // catch exception and pass to byte code
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001384 code_state->ip = exc_sp->handler;
Damien George66ae8c92014-04-17 16:50:23 +01001385 mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
Damien Georged7592a12014-03-30 00:54:48 +00001386 // save this exception in the stack so it can be used in a reraise, if needed
1387 exc_sp->prev_exc = nlr.ret_val;
Damien Georgef0406852016-09-27 12:37:21 +10001388 // push exception object so it can be handled by bytecode
Damien George999cedb2015-11-27 17:01:44 +00001389 PUSH(MP_OBJ_FROM_PTR(nlr.ret_val));
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001390 code_state->sp = sp;
Damien8f9e2ee2013-12-29 16:54:59 +00001391
Paul Sokolovsky20397572015-03-28 01:14:44 +02001392 #if MICROPY_STACKLESS
1393 } else if (code_state->prev != NULL) {
1394 mp_globals_set(code_state->old_globals);
1395 code_state = code_state->prev;
1396 fastn = &code_state->state[code_state->n_state - 1];
1397 exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
1398 // variables that are visible to the exception handler (declared volatile)
1399 currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
1400 exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
1401 goto unwind_loop;
1402
1403 #endif
Damience89a212013-10-15 22:25:17 +01001404 } else {
Damien Georgec8f78bc2014-02-15 22:55:00 +00001405 // propagate exception to higher level
1406 // TODO what to do about ip and sp? they don't really make sense at this point
Damien George999cedb2015-11-27 17:01:44 +00001407 fastn[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // must put exception here because sp is invalid
Damien Georgec8f78bc2014-02-15 22:55:00 +00001408 return MP_VM_RETURN_EXCEPTION;
Damience89a212013-10-15 22:25:17 +01001409 }
Damien429d7192013-10-04 19:53:11 +01001410 }
1411 }
1412}