blob: 4ec1ea9066792a02b2364ad850a4c09d1a7b7298 [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 George71a3d6e2017-03-17 14:54:53 +110076 void *ptr = (void*)(uintptr_t)code_state->fun_bc->const_table[unum]
Damien George999cedb2015-11-27 17:01:44 +000077#define DECODE_OBJ \
78 DECODE_UINT; \
Damien George71a3d6e2017-03-17 14:54:53 +110079 mp_obj_t obj = (mp_obj_t)code_state->fun_bc->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()
Damien George5640e6d2017-03-17 16:38:46 +1100165 size_t n_state = mp_decode_uint_value(code_state->fun_bc->bytecode);
Damien George71a3d6e2017-03-17 14:54:53 +1100166 mp_obj_t * /*const*/ fastn = &code_state->state[n_state - 1];
167 mp_exc_stack_t * /*const*/ exc_stack = (mp_exc_stack_t*)(code_state->state + n_state);
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300168
Damien George66ae8c92014-04-17 16:50:23 +0100169 // variables that are visible to the exception handler (declared volatile)
Damien George74eb44c2014-12-22 12:49:57 +0000170 volatile bool currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300171 mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
Damienc9f91972013-10-15 23:46:01 +0100172
Damien Georgef6c22a02017-02-06 10:50:43 +1100173 #if MICROPY_PY_THREAD_GIL && MICROPY_PY_THREAD_GIL_VM_DIVISOR
174 // This needs to be volatile and outside the VM loop so it persists across handling
175 // of any exceptions. Otherwise it's possible that the VM never gives up the GIL.
176 volatile int gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
177 #endif
178
Damience89a212013-10-15 22:25:17 +0100179 // outer exception handling loop
Damien429d7192013-10-04 19:53:11 +0100180 for (;;) {
Damien George66ae8c92014-04-17 16:50:23 +0100181 nlr_buf_t nlr;
Damien George9e6e9352014-03-26 18:37:06 +0000182outer_dispatch_loop:
Damience89a212013-10-15 22:25:17 +0100183 if (nlr_push(&nlr) == 0) {
Damien George66ae8c92014-04-17 16:50:23 +0100184 // local variables that are not visible to the exception handler
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300185 const byte *ip = code_state->ip;
186 mp_obj_t *sp = code_state->sp;
Damien Georged8675542014-05-25 22:58:04 +0100187 mp_obj_t obj_shared;
Damien George40d84302016-02-15 22:46:21 +0000188 MICROPY_VM_HOOK_INIT
Damien George66ae8c92014-04-17 16:50:23 +0100189
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200190 // If we have exception to inject, now that we finish setting up
191 // execution context, raise it. This works as if RAISE_VARARGS
192 // bytecode was executed.
Paul Sokolovskycf21a4e2014-03-26 17:36:12 +0200193 // Injecting exc into yield from generator is a special case,
194 // handled by MP_BC_YIELD_FROM itself
195 if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
Damien Georged8675542014-05-25 22:58:04 +0100196 mp_obj_t exc = inject_exc;
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200197 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100198 exc = mp_make_raise_obj(exc);
199 RAISE(exc);
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200200 }
Damien George66ae8c92014-04-17 16:50:23 +0100201
Damience89a212013-10-15 22:25:17 +0100202 // loop to execute byte code
203 for (;;) {
Paul Sokolovsky6472dea2014-02-01 00:55:05 +0200204dispatch_loop:
Damien George58ebde42014-05-21 20:32:59 +0100205#if MICROPY_OPT_COMPUTED_GOTO
AZ Huangb1f692e2014-04-14 23:22:44 +0800206 DISPATCH();
207#else
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +0300208 TRACE(ip);
Paul Sokolovsky74957502014-12-28 07:17:43 +0200209 MARK_EXC_IP_GLOBAL();
Damien Georgedb128912014-04-27 18:19:06 +0100210 switch (*ip++) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800211#endif
Damien429d7192013-10-04 19:53:11 +0100212
AZ Huangb1f692e2014-04-14 23:22:44 +0800213 ENTRY(MP_BC_LOAD_CONST_FALSE):
214 PUSH(mp_const_false);
215 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100216
AZ Huangb1f692e2014-04-14 23:22:44 +0800217 ENTRY(MP_BC_LOAD_CONST_NONE):
218 PUSH(mp_const_none);
219 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100220
AZ Huangb1f692e2014-04-14 23:22:44 +0800221 ENTRY(MP_BC_LOAD_CONST_TRUE):
222 PUSH(mp_const_true);
223 DISPATCH();
Damien Georgee9906ac2014-01-04 18:44:46 +0000224
AZ Huangb1f692e2014-04-14 23:22:44 +0800225 ENTRY(MP_BC_LOAD_CONST_SMALL_INT): {
Damien George40f3c022014-07-03 13:25:24 +0100226 mp_int_t num = 0;
AZ Huangb1f692e2014-04-14 23:22:44 +0800227 if ((ip[0] & 0x40) != 0) {
228 // Number is negative
229 num--;
Paul Sokolovsky047cd402014-02-19 15:47:59 +0200230 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800231 do {
232 num = (num << 7) | (*ip & 0x7f);
233 } while ((*ip++ & 0x80) != 0);
234 PUSH(MP_OBJ_NEW_SMALL_INT(num));
235 DISPATCH();
236 }
Damience89a212013-10-15 22:25:17 +0100237
Damien Georged8675542014-05-25 22:58:04 +0100238 ENTRY(MP_BC_LOAD_CONST_STRING): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800239 DECODE_QSTR;
Damien Georgeed570e42015-06-25 13:58:41 +0000240 PUSH(MP_OBJ_NEW_QSTR(qst));
AZ Huangb1f692e2014-04-14 23:22:44 +0800241 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100242 }
Damience89a212013-10-15 22:25:17 +0100243
Damien Georgedab13852015-01-13 15:55:54 +0000244 ENTRY(MP_BC_LOAD_CONST_OBJ): {
Damien George999cedb2015-11-27 17:01:44 +0000245 DECODE_OBJ;
246 PUSH(obj);
Damien Georgedab13852015-01-13 15:55:54 +0000247 DISPATCH();
248 }
249
AZ Huangb1f692e2014-04-14 23:22:44 +0800250 ENTRY(MP_BC_LOAD_NULL):
251 PUSH(MP_OBJ_NULL);
252 DISPATCH();
Damien George523b5752014-03-31 11:59:23 +0100253
Damien Georgecd97a432014-12-02 19:25:10 +0000254 ENTRY(MP_BC_LOAD_FAST_N): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800255 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100256 obj_shared = fastn[-unum];
AZ Huangb1f692e2014-04-14 23:22:44 +0800257 load_check:
Damien Georged8675542014-05-25 22:58:04 +0100258 if (obj_shared == MP_OBJ_NULL) {
259 local_name_error: {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200260 MARK_EXC_IP_SELECTIVE();
Damien Georged8675542014-05-25 22:58:04 +0100261 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment");
262 RAISE(obj);
263 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800264 }
Damien Georged8675542014-05-25 22:58:04 +0100265 PUSH(obj_shared);
AZ Huangb1f692e2014-04-14 23:22:44 +0800266 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000267 }
Damien George2bf7c092014-04-09 15:26:46 +0100268
Damien Georgecd97a432014-12-02 19:25:10 +0000269 ENTRY(MP_BC_LOAD_DEREF): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800270 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100271 obj_shared = mp_obj_cell_get(fastn[-unum]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800272 goto load_check;
Damien Georgecd97a432014-12-02 19:25:10 +0000273 }
Damien9ecbcff2013-12-11 00:41:43 +0000274
Damien George7ee91cf2015-01-06 12:51:39 +0000275 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100276 ENTRY(MP_BC_LOAD_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200277 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800278 DECODE_QSTR;
279 PUSH(mp_load_name(qst));
280 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100281 }
Damien George7ee91cf2015-01-06 12:51:39 +0000282 #else
283 ENTRY(MP_BC_LOAD_NAME): {
284 MARK_EXC_IP_SELECTIVE();
285 DECODE_QSTR;
286 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
287 mp_uint_t x = *ip;
288 if (x < MP_STATE_CTX(dict_locals)->map.alloc && MP_STATE_CTX(dict_locals)->map.table[x].key == key) {
289 PUSH(MP_STATE_CTX(dict_locals)->map.table[x].value);
290 } else {
291 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_locals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
292 if (elem != NULL) {
293 *(byte*)ip = (elem - &MP_STATE_CTX(dict_locals)->map.table[0]) & 0xff;
294 PUSH(elem->value);
295 } else {
296 PUSH(mp_load_name(MP_OBJ_QSTR_VALUE(key)));
297 }
298 }
299 ip++;
300 DISPATCH();
301 }
302 #endif
Damience89a212013-10-15 22:25:17 +0100303
Damien George7ee91cf2015-01-06 12:51:39 +0000304 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100305 ENTRY(MP_BC_LOAD_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200306 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800307 DECODE_QSTR;
308 PUSH(mp_load_global(qst));
309 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100310 }
Damien George7ee91cf2015-01-06 12:51:39 +0000311 #else
312 ENTRY(MP_BC_LOAD_GLOBAL): {
313 MARK_EXC_IP_SELECTIVE();
314 DECODE_QSTR;
315 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
316 mp_uint_t x = *ip;
317 if (x < MP_STATE_CTX(dict_globals)->map.alloc && MP_STATE_CTX(dict_globals)->map.table[x].key == key) {
318 PUSH(MP_STATE_CTX(dict_globals)->map.table[x].value);
319 } else {
320 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_globals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
321 if (elem != NULL) {
322 *(byte*)ip = (elem - &MP_STATE_CTX(dict_globals)->map.table[0]) & 0xff;
323 PUSH(elem->value);
324 } else {
325 PUSH(mp_load_global(MP_OBJ_QSTR_VALUE(key)));
326 }
327 }
328 ip++;
329 DISPATCH();
330 }
331 #endif
Damience89a212013-10-15 22:25:17 +0100332
Damien George7ee91cf2015-01-06 12:51:39 +0000333 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100334 ENTRY(MP_BC_LOAD_ATTR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200335 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800336 DECODE_QSTR;
337 SET_TOP(mp_load_attr(TOP(), qst));
338 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100339 }
Damien George7ee91cf2015-01-06 12:51:39 +0000340 #else
341 ENTRY(MP_BC_LOAD_ATTR): {
342 MARK_EXC_IP_SELECTIVE();
343 DECODE_QSTR;
344 mp_obj_t top = TOP();
Damien Georgeb1bbe962015-04-01 14:10:50 +0000345 if (mp_obj_get_type(top)->attr == mp_obj_instance_attr) {
Damien George999cedb2015-11-27 17:01:44 +0000346 mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
Damien George7ee91cf2015-01-06 12:51:39 +0000347 mp_uint_t x = *ip;
348 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
349 mp_map_elem_t *elem;
350 if (x < self->members.alloc && self->members.table[x].key == key) {
351 elem = &self->members.table[x];
352 } else {
353 elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);
354 if (elem != NULL) {
355 *(byte*)ip = elem - &self->members.table[0];
356 } else {
357 goto load_attr_cache_fail;
358 }
359 }
360 SET_TOP(elem->value);
361 ip++;
362 DISPATCH();
363 }
364 load_attr_cache_fail:
365 SET_TOP(mp_load_attr(top, qst));
366 ip++;
367 DISPATCH();
368 }
369 #endif
Damience89a212013-10-15 22:25:17 +0100370
Damien Georged8675542014-05-25 22:58:04 +0100371 ENTRY(MP_BC_LOAD_METHOD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200372 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800373 DECODE_QSTR;
374 mp_load_method(*sp, qst, sp);
375 sp += 1;
376 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100377 }
Damience89a212013-10-15 22:25:17 +0100378
AZ Huangb1f692e2014-04-14 23:22:44 +0800379 ENTRY(MP_BC_LOAD_BUILD_CLASS):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200380 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800381 PUSH(mp_load_build_class());
382 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100383
Damien Georged8675542014-05-25 22:58:04 +0100384 ENTRY(MP_BC_LOAD_SUBSCR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200385 MARK_EXC_IP_SELECTIVE();
Damien Georged8675542014-05-25 22:58:04 +0100386 mp_obj_t index = POP();
387 SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL));
Damien George729f7b42014-04-17 22:10:53 +0100388 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100389 }
Damien George729f7b42014-04-17 22:10:53 +0100390
Damien Georgecd97a432014-12-02 19:25:10 +0000391 ENTRY(MP_BC_STORE_FAST_N): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800392 DECODE_UINT;
393 fastn[-unum] = POP();
394 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000395 }
Damience89a212013-10-15 22:25:17 +0100396
Damien Georgecd97a432014-12-02 19:25:10 +0000397 ENTRY(MP_BC_STORE_DEREF): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800398 DECODE_UINT;
399 mp_obj_cell_set(fastn[-unum], POP());
400 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000401 }
Damien9ecbcff2013-12-11 00:41:43 +0000402
Damien Georged8675542014-05-25 22:58:04 +0100403 ENTRY(MP_BC_STORE_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200404 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800405 DECODE_QSTR;
406 mp_store_name(qst, POP());
407 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100408 }
Damience89a212013-10-15 22:25:17 +0100409
Damien Georged8675542014-05-25 22:58:04 +0100410 ENTRY(MP_BC_STORE_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200411 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800412 DECODE_QSTR;
413 mp_store_global(qst, POP());
414 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100415 }
Damien6addc892013-11-04 23:04:50 +0000416
Damien George7ee91cf2015-01-06 12:51:39 +0000417 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
Damien Georged8675542014-05-25 22:58:04 +0100418 ENTRY(MP_BC_STORE_ATTR): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200419 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800420 DECODE_QSTR;
421 mp_store_attr(sp[0], qst, sp[-1]);
422 sp -= 2;
423 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100424 }
Damien George7ee91cf2015-01-06 12:51:39 +0000425 #else
stijn28fa84b2015-02-14 18:43:54 +0100426 // This caching code works with MICROPY_PY_BUILTINS_PROPERTY and/or
427 // MICROPY_PY_DESCRIPTORS enabled because if the attr exists in
428 // self->members then it can't be a property or have descriptors. A
Damien George7ee91cf2015-01-06 12:51:39 +0000429 // consequence of this is that we can't use MP_MAP_LOOKUP_ADD_IF_NOT_FOUND
430 // in the fast-path below, because that store could override a property.
431 ENTRY(MP_BC_STORE_ATTR): {
432 MARK_EXC_IP_SELECTIVE();
433 DECODE_QSTR;
434 mp_obj_t top = TOP();
Damien Georgeb1bbe962015-04-01 14:10:50 +0000435 if (mp_obj_get_type(top)->attr == mp_obj_instance_attr && sp[-1] != MP_OBJ_NULL) {
Damien George999cedb2015-11-27 17:01:44 +0000436 mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
Damien George7ee91cf2015-01-06 12:51:39 +0000437 mp_uint_t x = *ip;
438 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
439 mp_map_elem_t *elem;
440 if (x < self->members.alloc && self->members.table[x].key == key) {
441 elem = &self->members.table[x];
442 } else {
443 elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);
444 if (elem != NULL) {
445 *(byte*)ip = elem - &self->members.table[0];
446 } else {
447 goto store_attr_cache_fail;
448 }
449 }
450 elem->value = sp[-1];
451 sp -= 2;
452 ip++;
453 DISPATCH();
454 }
455 store_attr_cache_fail:
456 mp_store_attr(sp[0], qst, sp[-1]);
457 sp -= 2;
458 ip++;
459 DISPATCH();
460 }
461 #endif
Damience89a212013-10-15 22:25:17 +0100462
AZ Huangb1f692e2014-04-14 23:22:44 +0800463 ENTRY(MP_BC_STORE_SUBSCR):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200464 MARK_EXC_IP_SELECTIVE();
Damien George729f7b42014-04-17 22:10:53 +0100465 mp_obj_subscr(sp[-1], sp[0], sp[-2]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800466 sp -= 3;
467 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100468
Damien Georgecd97a432014-12-02 19:25:10 +0000469 ENTRY(MP_BC_DELETE_FAST): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200470 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800471 DECODE_UINT;
472 if (fastn[-unum] == MP_OBJ_NULL) {
473 goto local_name_error;
474 }
475 fastn[-unum] = MP_OBJ_NULL;
476 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000477 }
Damien George2bf7c092014-04-09 15:26:46 +0100478
Damien Georgecd97a432014-12-02 19:25:10 +0000479 ENTRY(MP_BC_DELETE_DEREF): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200480 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800481 DECODE_UINT;
482 if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
483 goto local_name_error;
484 }
485 mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);
486 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000487 }
Damien George2bf7c092014-04-09 15:26:46 +0100488
Damien Georged8675542014-05-25 22:58:04 +0100489 ENTRY(MP_BC_DELETE_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200490 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800491 DECODE_QSTR;
492 mp_delete_name(qst);
493 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100494 }
Paul Sokolovskyf9090342014-03-23 21:19:02 +0200495
Damien Georged8675542014-05-25 22:58:04 +0100496 ENTRY(MP_BC_DELETE_GLOBAL): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200497 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800498 DECODE_QSTR;
499 mp_delete_global(qst);
500 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100501 }
Damien George1d24ea52014-04-08 21:11:49 +0100502
Damien Georged8675542014-05-25 22:58:04 +0100503 ENTRY(MP_BC_DUP_TOP): {
504 mp_obj_t top = TOP();
505 PUSH(top);
AZ Huangb1f692e2014-04-14 23:22:44 +0800506 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100507 }
Damience89a212013-10-15 22:25:17 +0100508
AZ Huangb1f692e2014-04-14 23:22:44 +0800509 ENTRY(MP_BC_DUP_TOP_TWO):
510 sp += 2;
511 sp[0] = sp[-2];
512 sp[-1] = sp[-3];
513 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100514
AZ Huangb1f692e2014-04-14 23:22:44 +0800515 ENTRY(MP_BC_POP_TOP):
516 sp -= 1;
517 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100518
Damien Georged8675542014-05-25 22:58:04 +0100519 ENTRY(MP_BC_ROT_TWO): {
520 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800521 sp[0] = sp[-1];
Damien Georged8675542014-05-25 22:58:04 +0100522 sp[-1] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800523 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100524 }
Damien4ebb32f2013-11-02 14:33:10 +0000525
Damien Georged8675542014-05-25 22:58:04 +0100526 ENTRY(MP_BC_ROT_THREE): {
527 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800528 sp[0] = sp[-1];
529 sp[-1] = sp[-2];
Damien Georged8675542014-05-25 22:58:04 +0100530 sp[-2] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800531 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100532 }
Damience89a212013-10-15 22:25:17 +0100533
Damien Georgecd97a432014-12-02 19:25:10 +0000534 ENTRY(MP_BC_JUMP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800535 DECODE_SLABEL;
Damien Georgecd97a432014-12-02 19:25:10 +0000536 ip += slab;
Damien George124df6f2014-10-25 18:19:55 +0100537 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000538 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800539
Damien Georgecd97a432014-12-02 19:25:10 +0000540 ENTRY(MP_BC_POP_JUMP_IF_TRUE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800541 DECODE_SLABEL;
542 if (mp_obj_is_true(POP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000543 ip += slab;
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200544 }
Damien George124df6f2014-10-25 18:19:55 +0100545 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000546 }
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200547
Damien Georgecd97a432014-12-02 19:25:10 +0000548 ENTRY(MP_BC_POP_JUMP_IF_FALSE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800549 DECODE_SLABEL;
550 if (!mp_obj_is_true(POP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000551 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800552 }
Damien George124df6f2014-10-25 18:19:55 +0100553 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000554 }
Damien George600ae732014-01-21 23:48:04 +0000555
Damien Georgecd97a432014-12-02 19:25:10 +0000556 ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800557 DECODE_SLABEL;
558 if (mp_obj_is_true(TOP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000559 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800560 } else {
561 sp--;
562 }
Damien George124df6f2014-10-25 18:19:55 +0100563 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000564 }
Damience89a212013-10-15 22:25:17 +0100565
Damien Georgecd97a432014-12-02 19:25:10 +0000566 ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800567 DECODE_SLABEL;
568 if (mp_obj_is_true(TOP())) {
569 sp--;
570 } else {
Damien Georgecd97a432014-12-02 19:25:10 +0000571 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800572 }
Damien George124df6f2014-10-25 18:19:55 +0100573 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000574 }
Damience89a212013-10-15 22:25:17 +0100575
Damien Georged8675542014-05-25 22:58:04 +0100576 ENTRY(MP_BC_SETUP_WITH): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200577 MARK_EXC_IP_SELECTIVE();
Damien George8c1d23a2015-04-24 01:52:28 +0100578 // stack: (..., ctx_mgr)
Damien Georged8675542014-05-25 22:58:04 +0100579 mp_obj_t obj = TOP();
Damien George8c1d23a2015-04-24 01:52:28 +0100580 mp_load_method(obj, MP_QSTR___exit__, sp);
581 mp_load_method(obj, MP_QSTR___enter__, sp + 2);
582 mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 2);
583 sp += 1;
Damien George74eb44c2014-12-22 12:49:57 +0000584 PUSH_EXC_BLOCK(1);
Damien Georged8675542014-05-25 22:58:04 +0100585 PUSH(ret);
Damien George8c1d23a2015-04-24 01:52:28 +0100586 // stack: (..., __exit__, ctx_mgr, as_value)
AZ Huangb1f692e2014-04-14 23:22:44 +0800587 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100588 }
Damience89a212013-10-15 22:25:17 +0100589
AZ Huangb1f692e2014-04-14 23:22:44 +0800590 ENTRY(MP_BC_WITH_CLEANUP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200591 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800592 // Arriving here, there's "exception control block" on top of stack,
Damien George8c1d23a2015-04-24 01:52:28 +0100593 // and __exit__ method (with self) underneath it. Bytecode calls __exit__,
AZ Huangb1f692e2014-04-14 23:22:44 +0800594 // and "deletes" it off stack, shifting "exception control block"
595 // to its place.
Damien Georgef0406852016-09-27 12:37:21 +1000596 // The bytecode emitter ensures that there is enough space on the Python
597 // value stack to hold the __exit__ method plus an additional 4 entries.
AZ Huangb1f692e2014-04-14 23:22:44 +0800598 if (TOP() == mp_const_none) {
Damien George8c1d23a2015-04-24 01:52:28 +0100599 // stack: (..., __exit__, ctx_mgr, None)
600 sp[1] = mp_const_none;
601 sp[2] = mp_const_none;
602 sp -= 2;
603 mp_call_method_n_kw(3, 0, sp);
AZ Huangb1f692e2014-04-14 23:22:44 +0800604 SET_TOP(mp_const_none);
AZ Huangb1f692e2014-04-14 23:22:44 +0800605 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
Damien George5e1d9932015-03-25 22:20:37 +0000606 mp_int_t cause_val = MP_OBJ_SMALL_INT_VALUE(TOP());
607 if (cause_val == UNWIND_RETURN) {
Damien George8c1d23a2015-04-24 01:52:28 +0100608 // stack: (..., __exit__, ctx_mgr, ret_val, UNWIND_RETURN)
609 mp_obj_t ret_val = sp[-1];
610 sp[-1] = mp_const_none;
611 sp[0] = mp_const_none;
612 sp[1] = mp_const_none;
613 mp_call_method_n_kw(3, 0, sp - 3);
614 sp[-3] = ret_val;
615 sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN);
Damien George5e1d9932015-03-25 22:20:37 +0000616 } else {
617 assert(cause_val == UNWIND_JUMP);
Damien George8c1d23a2015-04-24 01:52:28 +0100618 // stack: (..., __exit__, ctx_mgr, dest_ip, num_exc, UNWIND_JUMP)
619 mp_obj_t dest_ip = sp[-2];
620 mp_obj_t num_exc = sp[-1];
621 sp[-2] = mp_const_none;
622 sp[-1] = mp_const_none;
623 sp[0] = mp_const_none;
624 mp_call_method_n_kw(3, 0, sp - 4);
625 sp[-4] = dest_ip;
626 sp[-3] = num_exc;
627 sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP);
AZ Huangb1f692e2014-04-14 23:22:44 +0800628 }
Damien George8c1d23a2015-04-24 01:52:28 +0100629 sp -= 2; // we removed (__exit__, ctx_mgr)
Damien George5e1d9932015-03-25 22:20:37 +0000630 } else {
Damien Georgef0406852016-09-27 12:37:21 +1000631 assert(mp_obj_is_exception_instance(TOP()));
632 // stack: (..., __exit__, ctx_mgr, exc_instance)
633 // Need to pass (exc_type, exc_instance, None) as arguments to __exit__.
634 sp[1] = sp[0];
Damien George71fec072016-09-27 13:21:23 +1000635 sp[0] = MP_OBJ_FROM_PTR(mp_obj_get_type(sp[0]));
Damien Georgef0406852016-09-27 12:37:21 +1000636 sp[2] = mp_const_none;
637 sp -= 2;
638 mp_obj_t ret_value = mp_call_method_n_kw(3, 0, sp);
Damien Georged8675542014-05-25 22:58:04 +0100639 if (mp_obj_is_true(ret_value)) {
Damien George8c1d23a2015-04-24 01:52:28 +0100640 // We need to silence/swallow the exception. This is done
641 // by popping the exception and the __exit__ handler and
642 // replacing it with None, which signals END_FINALLY to just
643 // execute the finally handler normally.
Damien George8c1d23a2015-04-24 01:52:28 +0100644 SET_TOP(mp_const_none);
AZ Huangb1f692e2014-04-14 23:22:44 +0800645 assert(exc_sp >= exc_stack);
AZ Huangb1f692e2014-04-14 23:22:44 +0800646 POP_EXC_BLOCK();
Damien George596f41d2015-02-10 13:21:42 +0000647 } else {
Damien George8c1d23a2015-04-24 01:52:28 +0100648 // We need to re-raise the exception. We pop __exit__ handler
Damien Georgef0406852016-09-27 12:37:21 +1000649 // by copying the exception instance down to the new top-of-stack.
650 sp[0] = sp[3];
AZ Huangb1f692e2014-04-14 23:22:44 +0800651 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800652 }
653 DISPATCH();
654 }
Damienc226dca2013-10-16 16:12:52 +0100655
Damien Georgecd97a432014-12-02 19:25:10 +0000656 ENTRY(MP_BC_UNWIND_JUMP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200657 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800658 DECODE_SLABEL;
Damien George999cedb2015-11-27 17:01:44 +0000659 PUSH((mp_obj_t)(mp_uint_t)(uintptr_t)(ip + slab)); // push destination ip for jump
660 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 +0000661unwind_jump:;
662 mp_uint_t unum = (mp_uint_t)POP(); // get number of exception handlers to unwind
Damien George25c84642014-05-30 15:20:41 +0100663 while ((unum & 0x7f) > 0) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800664 unum -= 1;
665 assert(exc_sp >= exc_stack);
Damien George74eb44c2014-12-22 12:49:57 +0000666 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
Damien George4bf3f2d2015-10-15 17:48:28 +0100667 // Getting here the stack looks like:
668 // (..., X, dest_ip)
669 // where X is pointed to by exc_sp->val_sp and in the case
670 // of a "with" block contains the context manager info.
AZ Huangb1f692e2014-04-14 23:22:44 +0800671 // We're going to run "finally" code as a coroutine
672 // (not calling it recursively). Set up a sentinel
673 // on a stack so it can return back to us when it is
Damien George4bf3f2d2015-10-15 17:48:28 +0100674 // done (when WITH_CLEANUP or END_FINALLY reached).
Damien George999cedb2015-11-27 17:01:44 +0000675 PUSH((mp_obj_t)unum); // push number of exception handlers left to unwind
AZ Huangb1f692e2014-04-14 23:22:44 +0800676 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
677 ip = exc_sp->handler; // get exception handler byte code address
678 exc_sp--; // pop exception handler
679 goto dispatch_loop; // run the exception handler
680 }
Damien George93bb7df2016-02-01 16:07:21 +0000681 POP_EXC_BLOCK();
AZ Huangb1f692e2014-04-14 23:22:44 +0800682 }
Damien George999cedb2015-11-27 17:01:44 +0000683 ip = (const byte*)MP_OBJ_TO_PTR(POP()); // pop destination ip for jump
Damien George25c84642014-05-30 15:20:41 +0100684 if (unum != 0) {
Damien Georgef4df3aa2016-01-09 23:59:52 +0000685 // pop iter and iter_buf
Damien George25c84642014-05-30 15:20:41 +0100686 sp--;
Damien Georgef4df3aa2016-01-09 23:59:52 +0000687 sp -= sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t);
Damien George25c84642014-05-30 15:20:41 +0100688 }
Damien George124df6f2014-10-25 18:19:55 +0100689 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000690 }
Damience89a212013-10-15 22:25:17 +0100691
AZ Huangb1f692e2014-04-14 23:22:44 +0800692 // matched against: POP_BLOCK or POP_EXCEPT (anything else?)
693 ENTRY(MP_BC_SETUP_EXCEPT):
Damien Georgecd97a432014-12-02 19:25:10 +0000694 ENTRY(MP_BC_SETUP_FINALLY): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200695 MARK_EXC_IP_SELECTIVE();
Damien Georgef89d6592014-12-29 00:29:59 +0000696 #if SELECTIVE_EXC_IP
697 PUSH_EXC_BLOCK((code_state->ip[-1] == MP_BC_SETUP_FINALLY) ? 1 : 0);
698 #else
699 PUSH_EXC_BLOCK((code_state->ip[0] == MP_BC_SETUP_FINALLY) ? 1 : 0);
700 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800701 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000702 }
Damience89a212013-10-15 22:25:17 +0100703
AZ Huangb1f692e2014-04-14 23:22:44 +0800704 ENTRY(MP_BC_END_FINALLY):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200705 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800706 // if TOS is None, just pops it and continues
Damien Georgef0406852016-09-27 12:37:21 +1000707 // if TOS is an integer, finishes coroutine and returns control to caller
708 // if TOS is an exception, reraises the exception
AZ Huangb1f692e2014-04-14 23:22:44 +0800709 if (TOP() == mp_const_none) {
Damien George20006db2014-01-18 14:10:48 +0000710 sp--;
Damien Georgef0406852016-09-27 12:37:21 +1000711 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800712 // We finished "finally" coroutine and now dispatch back
713 // to our caller, based on TOS value
714 mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());
Damien George5e1d9932015-03-25 22:20:37 +0000715 if (reason == UNWIND_RETURN) {
716 goto unwind_return;
717 } else {
718 assert(reason == UNWIND_JUMP);
719 goto unwind_jump;
AZ Huangb1f692e2014-04-14 23:22:44 +0800720 }
Damien Georgef0406852016-09-27 12:37:21 +1000721 } else {
722 assert(mp_obj_is_exception_instance(TOP()));
723 RAISE(TOP());
AZ Huangb1f692e2014-04-14 23:22:44 +0800724 }
725 DISPATCH();
726
727 ENTRY(MP_BC_GET_ITER):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200728 MARK_EXC_IP_SELECTIVE();
Damien Georgeae8d8672016-01-09 23:14:54 +0000729 SET_TOP(mp_getiter(TOP(), NULL));
AZ Huangb1f692e2014-04-14 23:22:44 +0800730 DISPATCH();
731
Damien George088740e2017-01-17 15:27:37 +1100732 // An iterator for a for-loop takes 4 slots on the stack. They are either
733 // used to store the iterator object itself, or the first slot is NULL and
734 // the second slot holds a reference to the iterator object.
Damien Georgef4df3aa2016-01-09 23:59:52 +0000735 ENTRY(MP_BC_GET_ITER_STACK): {
736 MARK_EXC_IP_SELECTIVE();
737 mp_obj_t obj = TOP();
738 mp_obj_iter_buf_t *iter_buf = (mp_obj_iter_buf_t*)sp;
Damien George088740e2017-01-17 15:27:37 +1100739 sp += sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1;
740 obj = mp_getiter(obj, iter_buf);
741 if (obj != MP_OBJ_FROM_PTR(iter_buf)) {
742 // Iterator didn't use the stack so indicate that with MP_OBJ_NULL.
743 sp[-3] = MP_OBJ_NULL;
744 sp[-2] = obj;
745 }
Damien Georgef4df3aa2016-01-09 23:59:52 +0000746 DISPATCH();
747 }
748
Damien Georged8675542014-05-25 22:58:04 +0100749 ENTRY(MP_BC_FOR_ITER): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200750 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800751 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgec60a2612014-06-01 12:32:28 +0100752 code_state->sp = sp;
Damien George088740e2017-01-17 15:27:37 +1100753 mp_obj_t obj;
754 if (sp[-3] == MP_OBJ_NULL) {
755 obj = sp[-2];
756 } else {
757 obj = MP_OBJ_FROM_PTR(&sp[-3]);
758 }
759 mp_obj_t value = mp_iternext_allow_raise(obj);
Damien Georged8675542014-05-25 22:58:04 +0100760 if (value == MP_OBJ_STOP_ITERATION) {
Damien George088740e2017-01-17 15:27:37 +1100761 sp -= 4; // pop the exhausted iterator
Damien Georgecd97a432014-12-02 19:25:10 +0000762 ip += ulab; // jump to after for-block
AZ Huangb1f692e2014-04-14 23:22:44 +0800763 } else {
Damien Georged8675542014-05-25 22:58:04 +0100764 PUSH(value); // push the next iteration value
AZ Huangb1f692e2014-04-14 23:22:44 +0800765 }
766 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100767 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800768
769 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
770 ENTRY(MP_BC_POP_BLOCK):
771 // we are exiting an exception handler, so pop the last one of the exception-stack
772 assert(exc_sp >= exc_stack);
773 POP_EXC_BLOCK();
774 DISPATCH();
775
776 // matched against: SETUP_EXCEPT
777 ENTRY(MP_BC_POP_EXCEPT):
AZ Huangb1f692e2014-04-14 23:22:44 +0800778 assert(exc_sp >= exc_stack);
779 assert(currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +0800780 POP_EXC_BLOCK();
AZ Huangb1f692e2014-04-14 23:22:44 +0800781 DISPATCH();
782
Damien Georgecd97a432014-12-02 19:25:10 +0000783 ENTRY(MP_BC_BUILD_TUPLE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200784 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800785 DECODE_UINT;
786 sp -= unum - 1;
787 SET_TOP(mp_obj_new_tuple(unum, sp));
788 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000789 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800790
Damien Georgecd97a432014-12-02 19:25:10 +0000791 ENTRY(MP_BC_BUILD_LIST): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200792 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800793 DECODE_UINT;
794 sp -= unum - 1;
795 SET_TOP(mp_obj_new_list(unum, sp));
796 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000797 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800798
Damien Georgecd97a432014-12-02 19:25:10 +0000799 ENTRY(MP_BC_BUILD_MAP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200800 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800801 DECODE_UINT;
802 PUSH(mp_obj_new_dict(unum));
803 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000804 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800805
806 ENTRY(MP_BC_STORE_MAP):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200807 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800808 sp -= 2;
809 mp_obj_dict_store(sp[0], sp[2], sp[1]);
810 DISPATCH();
811
Damien George3ebd4d02014-06-01 13:46:47 +0100812#if MICROPY_PY_BUILTINS_SET
Damien Georgecd97a432014-12-02 19:25:10 +0000813 ENTRY(MP_BC_BUILD_SET): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200814 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800815 DECODE_UINT;
816 sp -= unum - 1;
817 SET_TOP(mp_obj_new_set(unum, sp));
818 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000819 }
Damien George3ebd4d02014-06-01 13:46:47 +0100820#endif
Damienc12aa462013-10-16 20:57:49 +0100821
Damien Georgefb510b32014-06-01 13:32:54 +0100822#if MICROPY_PY_BUILTINS_SLICE
Damien Georgecd97a432014-12-02 19:25:10 +0000823 ENTRY(MP_BC_BUILD_SLICE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200824 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800825 DECODE_UINT;
826 if (unum == 2) {
Damien Georged8675542014-05-25 22:58:04 +0100827 mp_obj_t stop = POP();
828 mp_obj_t start = TOP();
829 SET_TOP(mp_obj_new_slice(start, stop, mp_const_none));
AZ Huangb1f692e2014-04-14 23:22:44 +0800830 } else {
Damien Georged8675542014-05-25 22:58:04 +0100831 mp_obj_t step = POP();
832 mp_obj_t stop = POP();
833 mp_obj_t start = TOP();
834 SET_TOP(mp_obj_new_slice(start, stop, step));
AZ Huangb1f692e2014-04-14 23:22:44 +0800835 }
836 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000837 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800838#endif
839
Damien Georgeadaf0d82016-09-19 08:46:01 +1000840 ENTRY(MP_BC_STORE_COMP): {
841 MARK_EXC_IP_SELECTIVE();
842 DECODE_UINT;
843 mp_obj_t obj = sp[-(unum >> 2)];
844 if ((unum & 3) == 0) {
845 mp_obj_list_append(obj, sp[0]);
846 sp--;
847 } else if (!MICROPY_PY_BUILTINS_SET || (unum & 3) == 1) {
848 mp_obj_dict_store(obj, sp[0], sp[-1]);
849 sp -= 2;
850 #if MICROPY_PY_BUILTINS_SET
851 } else {
852 mp_obj_set_store(obj, sp[0]);
853 sp--;
854 #endif
855 }
856 DISPATCH();
857 }
858
Damien Georgecd97a432014-12-02 19:25:10 +0000859 ENTRY(MP_BC_UNPACK_SEQUENCE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200860 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800861 DECODE_UINT;
862 mp_unpack_sequence(sp[0], unum, sp);
863 sp += unum - 1;
864 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000865 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800866
Damien Georgecd97a432014-12-02 19:25:10 +0000867 ENTRY(MP_BC_UNPACK_EX): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200868 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800869 DECODE_UINT;
870 mp_unpack_ex(sp[0], unum, sp);
871 sp += (unum & 0xff) + ((unum >> 8) & 0xff);
872 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000873 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800874
Damien Georgecd97a432014-12-02 19:25:10 +0000875 ENTRY(MP_BC_MAKE_FUNCTION): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800876 DECODE_PTR;
Damien Georgecd97a432014-12-02 19:25:10 +0000877 PUSH(mp_make_function_from_raw_code(ptr, MP_OBJ_NULL, MP_OBJ_NULL));
AZ Huangb1f692e2014-04-14 23:22:44 +0800878 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000879 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800880
Damien Georged8675542014-05-25 22:58:04 +0100881 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800882 DECODE_PTR;
883 // Stack layout: def_tuple def_dict <- TOS
Damien Georged8675542014-05-25 22:58:04 +0100884 mp_obj_t def_dict = POP();
Damien Georgecd97a432014-12-02 19:25:10 +0000885 SET_TOP(mp_make_function_from_raw_code(ptr, TOP(), def_dict));
AZ Huangb1f692e2014-04-14 23:22:44 +0800886 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100887 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800888
Damien George3558f622014-04-20 17:50:40 +0100889 ENTRY(MP_BC_MAKE_CLOSURE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800890 DECODE_PTR;
Damien George101886f2017-02-16 16:48:33 +1100891 size_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100892 // Stack layout: closed_overs <- TOS
893 sp -= n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000894 SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800895 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100896 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800897
Damien George3558f622014-04-20 17:50:40 +0100898 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800899 DECODE_PTR;
Damien George101886f2017-02-16 16:48:33 +1100900 size_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100901 // Stack layout: def_tuple def_dict closed_overs <- TOS
902 sp -= 2 + n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000903 SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800904 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100905 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800906
Damien Georgecd97a432014-12-02 19:25:10 +0000907 ENTRY(MP_BC_CALL_FUNCTION): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200908 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800909 DECODE_UINT;
910 // unum & 0xff == n_positional
911 // (unum >> 8) & 0xff == n_keyword
912 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
Paul Sokolovsky20397572015-03-28 01:14:44 +0200913 #if MICROPY_STACKLESS
914 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
915 code_state->ip = ip;
916 code_state->sp = sp;
917 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
Damien George581a59a2016-08-27 23:21:00 +1000918 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 +0200919 if (new_state) {
920 new_state->prev = code_state;
921 code_state = new_state;
922 nlr_pop();
923 goto run_code_state;
924 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200925 #if MICROPY_STACKLESS_STRICT
926 else {
927 deep_recursion_error:
928 mp_exc_recursion_depth();
929 }
930 #endif
Paul Sokolovsky20397572015-03-28 01:14:44 +0200931 }
932 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800933 SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
934 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000935 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800936
Damien Georgecd97a432014-12-02 19:25:10 +0000937 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200938 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800939 DECODE_UINT;
940 // unum & 0xff == n_positional
941 // (unum >> 8) & 0xff == n_keyword
942 // We have folowing stack layout here:
943 // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
944 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200945 #if MICROPY_STACKLESS
946 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
947 code_state->ip = ip;
948 code_state->sp = sp;
949 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
950
Damien George12a5e172015-04-01 23:31:30 +0100951 mp_call_args_t out_args;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200952 mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args);
953
Damien George581a59a2016-08-27 23:21:00 +1000954 mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200955 out_args.n_args, out_args.n_kw, out_args.args);
956 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
957 if (new_state) {
958 new_state->prev = code_state;
959 code_state = new_state;
960 nlr_pop();
961 goto run_code_state;
962 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200963 #if MICROPY_STACKLESS_STRICT
964 else {
965 goto deep_recursion_error;
966 }
967 #endif
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200968 }
969 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800970 SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
971 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000972 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800973
Damien Georgecd97a432014-12-02 19:25:10 +0000974 ENTRY(MP_BC_CALL_METHOD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200975 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800976 DECODE_UINT;
977 // unum & 0xff == n_positional
978 // (unum >> 8) & 0xff == n_keyword
979 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200980 #if MICROPY_STACKLESS
981 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
982 code_state->ip = ip;
983 code_state->sp = sp;
984 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
985
Damien George101886f2017-02-16 16:48:33 +1100986 size_t n_args = unum & 0xff;
987 size_t n_kw = (unum >> 8) & 0xff;
Damien George7a30e872015-12-17 12:32:41 +0000988 int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1;
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200989
Damien George581a59a2016-08-27 23:21:00 +1000990 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 +0200991 if (new_state) {
992 new_state->prev = code_state;
993 code_state = new_state;
994 nlr_pop();
995 goto run_code_state;
996 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200997 #if MICROPY_STACKLESS_STRICT
998 else {
999 goto deep_recursion_error;
1000 }
1001 #endif
Paul Sokolovsky390e9262015-03-28 01:14:44 +02001002 }
1003 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001004 SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
1005 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +00001006 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001007
Damien Georgecd97a432014-12-02 19:25:10 +00001008 ENTRY(MP_BC_CALL_METHOD_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001009 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001010 DECODE_UINT;
1011 // unum & 0xff == n_positional
1012 // (unum >> 8) & 0xff == n_keyword
1013 // We have folowing stack layout here:
1014 // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
1015 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001016 #if MICROPY_STACKLESS
1017 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
1018 code_state->ip = ip;
1019 code_state->sp = sp;
1020 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
1021
Damien George12a5e172015-04-01 23:31:30 +01001022 mp_call_args_t out_args;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001023 mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args);
1024
Damien George581a59a2016-08-27 23:21:00 +10001025 mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001026 out_args.n_args, out_args.n_kw, out_args.args);
1027 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
1028 if (new_state) {
1029 new_state->prev = code_state;
1030 code_state = new_state;
1031 nlr_pop();
1032 goto run_code_state;
1033 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +02001034 #if MICROPY_STACKLESS_STRICT
1035 else {
1036 goto deep_recursion_error;
1037 }
1038 #endif
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001039 }
1040 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001041 SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
1042 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +00001043 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001044
1045 ENTRY(MP_BC_RETURN_VALUE):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001046 MARK_EXC_IP_SELECTIVE();
Damien George80473402015-12-24 12:47:39 +00001047 // These next 3 lines pop a try-finally exception handler, if one
1048 // is there on the exception stack. Without this the finally block
1049 // is executed a second time when the return is executed, because
1050 // the try-finally exception handler is still on the stack.
1051 // TODO Possibly find a better way to handle this case.
1052 if (currently_in_except_block) {
1053 POP_EXC_BLOCK();
1054 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001055unwind_return:
1056 while (exc_sp >= exc_stack) {
Damien George74eb44c2014-12-22 12:49:57 +00001057 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
Damien George4bf3f2d2015-10-15 17:48:28 +01001058 // Getting here the stack looks like:
1059 // (..., X, [iter0, iter1, ...,] ret_val)
1060 // where X is pointed to by exc_sp->val_sp and in the case
1061 // of a "with" block contains the context manager info.
1062 // There may be 0 or more for-iterators between X and the
1063 // return value, and these must be removed before control can
1064 // pass to the finally code. We simply copy the ret_value down
1065 // over these iterators, if they exist. If they don't then the
1066 // following is a null operation.
1067 mp_obj_t *finally_sp = MP_TAGPTR_PTR(exc_sp->val_sp);
1068 finally_sp[1] = sp[0];
1069 sp = &finally_sp[1];
AZ Huangb1f692e2014-04-14 23:22:44 +08001070 // We're going to run "finally" code as a coroutine
1071 // (not calling it recursively). Set up a sentinel
1072 // on a stack so it can return back to us when it is
Damien George4bf3f2d2015-10-15 17:48:28 +01001073 // done (when WITH_CLEANUP or END_FINALLY reached).
AZ Huangb1f692e2014-04-14 23:22:44 +08001074 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
1075 ip = exc_sp->handler;
AZ Huangb1f692e2014-04-14 23:22:44 +08001076 exc_sp--;
1077 goto dispatch_loop;
1078 }
1079 exc_sp--;
1080 }
1081 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001082 code_state->sp = sp;
AZ Huangb1f692e2014-04-14 23:22:44 +08001083 assert(exc_sp == exc_stack - 1);
Damien George40d84302016-02-15 22:46:21 +00001084 MICROPY_VM_HOOK_RETURN
Paul Sokolovsky20397572015-03-28 01:14:44 +02001085 #if MICROPY_STACKLESS
1086 if (code_state->prev != NULL) {
1087 mp_obj_t res = *sp;
1088 mp_globals_set(code_state->old_globals);
1089 code_state = code_state->prev;
1090 *code_state->sp = res;
1091 goto run_code_state;
1092 }
1093 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001094 return MP_VM_RETURN_NORMAL;
1095
Damien Georged8675542014-05-25 22:58:04 +01001096 ENTRY(MP_BC_RAISE_VARARGS): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001097 MARK_EXC_IP_SELECTIVE();
Damien Georgecd97a432014-12-02 19:25:10 +00001098 mp_uint_t unum = *ip++;
Damien Georged8675542014-05-25 22:58:04 +01001099 mp_obj_t obj;
Paul Sokolovsky2ff2ea52015-09-01 10:35:58 +03001100 if (unum == 2) {
1101 mp_warning("exception chaining not supported");
1102 // ignore (pop) "from" argument
1103 sp--;
1104 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001105 if (unum == 0) {
1106 // search for the inner-most previous exception, to reraise it
Damien Georged8675542014-05-25 22:58:04 +01001107 obj = MP_OBJ_NULL;
AZ Huangb1f692e2014-04-14 23:22:44 +08001108 for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
Damien George999cedb2015-11-27 17:01:44 +00001109 if (e->prev_exc != NULL) {
1110 obj = MP_OBJ_FROM_PTR(e->prev_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +08001111 break;
1112 }
1113 }
Damien Georged8675542014-05-25 22:58:04 +01001114 if (obj == MP_OBJ_NULL) {
1115 obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
1116 RAISE(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001117 }
1118 } else {
Damien Georged8675542014-05-25 22:58:04 +01001119 obj = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +08001120 }
Damien Georged8675542014-05-25 22:58:04 +01001121 obj = mp_make_raise_obj(obj);
1122 RAISE(obj);
1123 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001124
1125 ENTRY(MP_BC_YIELD_VALUE):
1126yield:
1127 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001128 code_state->ip = ip;
1129 code_state->sp = sp;
1130 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +08001131 return MP_VM_RETURN_YIELD;
1132
1133 ENTRY(MP_BC_YIELD_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001134 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001135//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
1136#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
Damien George999cedb2015-11-27 17:01:44 +00001137#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 +08001138 mp_vm_return_kind_t ret_kind;
Damien Georged8675542014-05-25 22:58:04 +01001139 mp_obj_t send_value = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +08001140 mp_obj_t t_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +01001141 mp_obj_t ret_value;
AZ Huangb1f692e2014-04-14 23:22:44 +08001142 if (inject_exc != MP_OBJ_NULL) {
1143 t_exc = inject_exc;
1144 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +01001145 ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001146 } else {
Damien Georged8675542014-05-25 22:58:04 +01001147 ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001148 }
1149
1150 if (ret_kind == MP_VM_RETURN_YIELD) {
1151 ip--;
Damien Georged8675542014-05-25 22:58:04 +01001152 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001153 goto yield;
1154 }
1155 if (ret_kind == MP_VM_RETURN_NORMAL) {
1156 // Pop exhausted gen
1157 sp--;
Paul Sokolovskyeff85bb2016-04-28 01:54:23 +03001158 // TODO: When ret_value can be MP_OBJ_NULL here??
1159 if (ret_value == MP_OBJ_NULL || ret_value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +08001160 // Optimize StopIteration
1161 // TODO: get StopIteration's value
1162 PUSH(mp_const_none);
1163 } else {
Damien Georged8675542014-05-25 22:58:04 +01001164 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001165 }
1166
1167 // If we injected GeneratorExit downstream, then even
1168 // if it was swallowed, we re-raise GeneratorExit
1169 GENERATOR_EXIT_IF_NEEDED(t_exc);
1170 DISPATCH();
1171 }
1172 if (ret_kind == MP_VM_RETURN_EXCEPTION) {
1173 // Pop exhausted gen
1174 sp--;
Damien George999cedb2015-11-27 17:01:44 +00001175 if (EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
Damien Georged8675542014-05-25 22:58:04 +01001176 PUSH(mp_obj_exception_get_value(ret_value));
AZ Huangb1f692e2014-04-14 23:22:44 +08001177 // If we injected GeneratorExit downstream, then even
1178 // if it was swallowed, we re-raise GeneratorExit
1179 GENERATOR_EXIT_IF_NEEDED(t_exc);
1180 DISPATCH();
1181 } else {
Damien Georged8675542014-05-25 22:58:04 +01001182 RAISE(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001183 }
1184 }
Damien429d7192013-10-04 19:53:11 +01001185 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001186
Damien Georged8675542014-05-25 22:58:04 +01001187 ENTRY(MP_BC_IMPORT_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001188 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001189 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001190 mp_obj_t obj = POP();
1191 SET_TOP(mp_import_name(qst, obj, TOP()));
AZ Huangb1f692e2014-04-14 23:22:44 +08001192 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001193 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001194
Damien Georged8675542014-05-25 22:58:04 +01001195 ENTRY(MP_BC_IMPORT_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001196 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001197 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001198 mp_obj_t obj = mp_import_from(TOP(), qst);
1199 PUSH(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001200 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001201 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001202
1203 ENTRY(MP_BC_IMPORT_STAR):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001204 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001205 mp_import_all(POP());
1206 DISPATCH();
1207
Damien George8456cc02014-10-25 16:43:46 +01001208#if MICROPY_OPT_COMPUTED_GOTO
1209 ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):
1210 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1211 DISPATCH();
1212
1213 ENTRY(MP_BC_LOAD_FAST_MULTI):
1214 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1215 goto load_check;
1216
1217 ENTRY(MP_BC_STORE_FAST_MULTI):
1218 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1219 DISPATCH();
1220
1221 ENTRY(MP_BC_UNARY_OP_MULTI):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001222 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001223 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1224 DISPATCH();
1225
1226 ENTRY(MP_BC_BINARY_OP_MULTI): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001227 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001228 mp_obj_t rhs = POP();
1229 mp_obj_t lhs = TOP();
1230 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1231 DISPATCH();
1232 }
1233
1234 ENTRY_DEFAULT:
Paul Sokolovsky74957502014-12-28 07:17:43 +02001235 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001236#else
1237 ENTRY_DEFAULT:
1238 if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
1239 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1240 DISPATCH();
1241 } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
1242 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1243 goto load_check;
1244 } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
1245 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1246 DISPATCH();
Damien Georgebdbe8c92015-12-08 12:28:11 +00001247 } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 7) {
Damien George8456cc02014-10-25 16:43:46 +01001248 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1249 DISPATCH();
Damien Georgec5029bc2015-06-13 22:00:10 +01001250 } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) {
Damien George8456cc02014-10-25 16:43:46 +01001251 mp_obj_t rhs = POP();
1252 mp_obj_t lhs = TOP();
1253 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1254 DISPATCH();
1255 } else
1256#endif
1257 {
Damien Georged8675542014-05-25 22:58:04 +01001258 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
AZ Huangb1f692e2014-04-14 23:22:44 +08001259 nlr_pop();
Damien Georged8675542014-05-25 22:58:04 +01001260 fastn[0] = obj;
AZ Huangb1f692e2014-04-14 23:22:44 +08001261 return MP_VM_RETURN_EXCEPTION;
Damien Georged8675542014-05-25 22:58:04 +01001262 }
Damien George66ae8c92014-04-17 16:50:23 +01001263
Damien George58ebde42014-05-21 20:32:59 +01001264#if !MICROPY_OPT_COMPUTED_GOTO
AZ Huang9309d992014-04-15 15:57:01 +08001265 } // switch
AZ Huangb1f692e2014-04-14 23:22:44 +08001266#endif
Damien George124df6f2014-10-25 18:19:55 +01001267
1268pending_exception_check:
Damien George40d84302016-02-15 22:46:21 +00001269 MICROPY_VM_HOOK_LOOP
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001270 if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001271 MARK_EXC_IP_SELECTIVE();
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001272 mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
1273 MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
Damien George124df6f2014-10-25 18:19:55 +01001274 RAISE(obj);
1275 }
Damien George124df6f2014-10-25 18:19:55 +01001276
Damien Georgef6c22a02017-02-06 10:50:43 +11001277 #if MICROPY_PY_THREAD_GIL
1278 #if MICROPY_PY_THREAD_GIL_VM_DIVISOR
1279 if (--gil_divisor == 0) {
1280 gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
1281 #else
1282 {
1283 #endif
1284 MP_THREAD_GIL_EXIT();
1285 MP_THREAD_GIL_ENTER();
1286 }
1287 #endif
Damien George4cec63a2016-05-26 10:42:53 +00001288
Damien George66ae8c92014-04-17 16:50:23 +01001289 } // for loop
Damien429d7192013-10-04 19:53:11 +01001290
Damience89a212013-10-15 22:25:17 +01001291 } else {
Damien George66ae8c92014-04-17 16:50:23 +01001292exception_handler:
Damience89a212013-10-15 22:25:17 +01001293 // exception occurred
Damien429d7192013-10-04 19:53:11 +01001294
Paul Sokolovsky8b85d142015-04-25 03:17:41 +03001295 #if MICROPY_PY_SYS_EXC_INFO
1296 MP_STATE_VM(cur_exception) = nlr.ret_val;
1297 #endif
1298
Damien Georgef89d6592014-12-29 00:29:59 +00001299 #if SELECTIVE_EXC_IP
1300 // with selective ip, we store the ip 1 byte past the opcode, so move ptr back
1301 code_state->ip -= 1;
1302 #endif
1303
Damien George999cedb2015-11-27 17:01:44 +00001304 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 +03001305 if (code_state->ip) {
1306 // check if it's a StopIteration within a for block
1307 if (*code_state->ip == MP_BC_FOR_ITER) {
1308 const byte *ip = code_state->ip + 1;
1309 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
1310 code_state->ip = ip + ulab; // jump to after for-block
Damien George088740e2017-01-17 15:27:37 +11001311 code_state->sp -= 4; // pop the exhausted iterator
Paul Sokolovskya7c02c42015-05-10 17:18:10 +03001312 goto outer_dispatch_loop; // continue with dispatch loop
Paul Sokolovsky6738c1d2015-05-11 02:59:25 +03001313 } else if (*code_state->ip == MP_BC_YIELD_FROM) {
1314 // StopIteration inside yield from call means return a value of
1315 // yield from, so inject exception's value as yield from's result
Damien George999cedb2015-11-27 17:01:44 +00001316 *++code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));
Paul Sokolovsky6738c1d2015-05-11 02:59:25 +03001317 code_state->ip++; // yield from is over, move to next instruction
1318 goto outer_dispatch_loop; // continue with dispatch loop
Paul Sokolovskya7c02c42015-05-10 17:18:10 +03001319 }
1320 }
Damien George9e6e9352014-03-26 18:37:06 +00001321 }
1322
Paul Sokolovsky20397572015-03-28 01:14:44 +02001323#if MICROPY_STACKLESS
1324unwind_loop:
1325#endif
Damien George08335002014-01-18 23:24:36 +00001326 // set file and line number that the exception occurred at
Paul Sokolovsky382e8ee2014-01-30 13:49:18 +02001327 // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
1328 // But consider how to handle nested exceptions.
Damien George6902eed2014-04-04 10:52:59 +00001329 // 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 +00001330 if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
Damien George71a3d6e2017-03-17 14:54:53 +11001331 const byte *ip = code_state->fun_bc->bytecode;
1332 mp_decode_uint(&ip); // skip n_state
1333 mp_decode_uint(&ip); // skip n_exc_stack
1334 ip++; // skip scope_params
1335 ip++; // skip n_pos_args
1336 ip++; // skip n_kwonly_args
1337 ip++; // skip n_def_pos_args
1338 size_t bc = code_state->ip - ip;
Damien George101886f2017-02-16 16:48:33 +11001339 size_t code_info_size = mp_decode_uint(&ip);
Damien George71a3d6e2017-03-17 14:54:53 +11001340 bc -= code_info_size;
Damien Georgec8e9c0d2015-11-02 17:27:18 +00001341 #if MICROPY_PERSISTENT_CODE
1342 qstr block_name = ip[0] | (ip[1] << 8);
1343 qstr source_file = ip[2] | (ip[3] << 8);
1344 ip += 4;
1345 #else
Damien Georgeb534e1b2014-09-04 14:44:01 +01001346 qstr block_name = mp_decode_uint(&ip);
1347 qstr source_file = mp_decode_uint(&ip);
Damien Georgec8e9c0d2015-11-02 17:27:18 +00001348 #endif
Damien George3d2daa22016-01-02 22:04:12 +00001349 size_t source_line = 1;
1350 size_t c;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001351 while ((c = *ip)) {
Damien George101886f2017-02-16 16:48:33 +11001352 size_t b, l;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001353 if ((c & 0x80) == 0) {
1354 // 0b0LLBBBBB encoding
1355 b = c & 0x1f;
1356 l = c >> 5;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001357 ip += 1;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001358 } else {
1359 // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
1360 b = c & 0xf;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001361 l = ((c << 4) & 0x700) | ip[1];
1362 ip += 2;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001363 }
1364 if (bc >= b) {
1365 bc -= b;
1366 source_line += l;
1367 } else {
1368 // found source line corresponding to bytecode offset
1369 break;
Paul Sokolovsky411732e2014-06-02 18:24:34 +03001370 }
Damien George08335002014-01-18 23:24:36 +00001371 }
Damien George999cedb2015-11-27 17:01:44 +00001372 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 +00001373 }
1374
Damien8f9e2ee2013-12-29 16:54:59 +00001375 while (currently_in_except_block) {
1376 // nested exception
1377
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001378 assert(exc_sp >= exc_stack);
Damien8f9e2ee2013-12-29 16:54:59 +00001379
1380 // TODO make a proper message for nested exception
1381 // at the moment we are just raising the very last exception (the one that caused the nested exception)
1382
1383 // move up to previous exception handler
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +02001384 POP_EXC_BLOCK();
Damien8f9e2ee2013-12-29 16:54:59 +00001385 }
1386
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001387 if (exc_sp >= exc_stack) {
Damien8f9e2ee2013-12-29 16:54:59 +00001388 // set flag to indicate that we are now handling an exception
1389 currently_in_except_block = 1;
1390
Damience89a212013-10-15 22:25:17 +01001391 // catch exception and pass to byte code
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001392 code_state->ip = exc_sp->handler;
Damien George66ae8c92014-04-17 16:50:23 +01001393 mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
Damien Georged7592a12014-03-30 00:54:48 +00001394 // save this exception in the stack so it can be used in a reraise, if needed
1395 exc_sp->prev_exc = nlr.ret_val;
Damien Georgef0406852016-09-27 12:37:21 +10001396 // push exception object so it can be handled by bytecode
Damien George999cedb2015-11-27 17:01:44 +00001397 PUSH(MP_OBJ_FROM_PTR(nlr.ret_val));
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001398 code_state->sp = sp;
Damien8f9e2ee2013-12-29 16:54:59 +00001399
Paul Sokolovsky20397572015-03-28 01:14:44 +02001400 #if MICROPY_STACKLESS
1401 } else if (code_state->prev != NULL) {
1402 mp_globals_set(code_state->old_globals);
1403 code_state = code_state->prev;
Damien George71a3d6e2017-03-17 14:54:53 +11001404 fastn = &code_state->state[n_state - 1];
1405 exc_stack = (mp_exc_stack_t*)(code_state->state + n_state);
Paul Sokolovsky20397572015-03-28 01:14:44 +02001406 // variables that are visible to the exception handler (declared volatile)
1407 currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
1408 exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
1409 goto unwind_loop;
1410
1411 #endif
Damience89a212013-10-15 22:25:17 +01001412 } else {
Damien Georgec8f78bc2014-02-15 22:55:00 +00001413 // propagate exception to higher level
1414 // TODO what to do about ip and sp? they don't really make sense at this point
Damien George999cedb2015-11-27 17:01:44 +00001415 fastn[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // must put exception here because sp is invalid
Damien Georgec8f78bc2014-02-15 22:55:00 +00001416 return MP_VM_RETURN_EXCEPTION;
Damience89a212013-10-15 22:25:17 +01001417 }
Damien429d7192013-10-04 19:53:11 +01001418 }
1419 }
1420}