blob: 8ce635ca87374a6a93c309c0bf32a49e2deee41e [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 Georgea0973b02017-03-27 10:52:04 +110041#define TRACE(ip) printf("sp=%d ", (int)(sp - &code_state->state[0] + 1)); mp_bytecode_print2(ip, 1, code_state->fun_bc->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;
Damien George707f16b2017-03-24 18:41:11 +1100288 if (x < mp_locals_get()->map.alloc && mp_locals_get()->map.table[x].key == key) {
289 PUSH(mp_locals_get()->map.table[x].value);
Damien George7ee91cf2015-01-06 12:51:39 +0000290 } else {
Damien George707f16b2017-03-24 18:41:11 +1100291 mp_map_elem_t *elem = mp_map_lookup(&mp_locals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
Damien George7ee91cf2015-01-06 12:51:39 +0000292 if (elem != NULL) {
Damien George707f16b2017-03-24 18:41:11 +1100293 *(byte*)ip = (elem - &mp_locals_get()->map.table[0]) & 0xff;
Damien George7ee91cf2015-01-06 12:51:39 +0000294 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;
Damien George707f16b2017-03-24 18:41:11 +1100317 if (x < mp_globals_get()->map.alloc && mp_globals_get()->map.table[x].key == key) {
318 PUSH(mp_globals_get()->map.table[x].value);
Damien George7ee91cf2015-01-06 12:51:39 +0000319 } else {
Damien George707f16b2017-03-24 18:41:11 +1100320 mp_map_elem_t *elem = mp_map_lookup(&mp_globals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
Damien George7ee91cf2015-01-06 12:51:39 +0000321 if (elem != NULL) {
Damien George707f16b2017-03-24 18:41:11 +1100322 *(byte*)ip = (elem - &mp_globals_get()->map.table[0]) & 0xff;
Damien George7ee91cf2015-01-06 12:51:39 +0000323 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 George60656ea2017-03-23 16:36:08 +1100687 sp -= MP_OBJ_ITER_BUF_NSLOTS;
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 George60656ea2017-03-23 16:36:08 +1100732 // An iterator for a for-loop takes MP_OBJ_ITER_BUF_NSLOTS slots on
733 // the Python value stack. These slots are either used to store the
734 // iterator object itself, or the first slot is MP_OBJ_NULL and
Damien George088740e2017-01-17 15:27:37 +1100735 // the second slot holds a reference to the iterator object.
Damien Georgef4df3aa2016-01-09 23:59:52 +0000736 ENTRY(MP_BC_GET_ITER_STACK): {
737 MARK_EXC_IP_SELECTIVE();
738 mp_obj_t obj = TOP();
739 mp_obj_iter_buf_t *iter_buf = (mp_obj_iter_buf_t*)sp;
Damien George60656ea2017-03-23 16:36:08 +1100740 sp += MP_OBJ_ITER_BUF_NSLOTS - 1;
Damien George088740e2017-01-17 15:27:37 +1100741 obj = mp_getiter(obj, iter_buf);
742 if (obj != MP_OBJ_FROM_PTR(iter_buf)) {
743 // Iterator didn't use the stack so indicate that with MP_OBJ_NULL.
Damien George60656ea2017-03-23 16:36:08 +1100744 sp[-MP_OBJ_ITER_BUF_NSLOTS + 1] = MP_OBJ_NULL;
745 sp[-MP_OBJ_ITER_BUF_NSLOTS + 2] = obj;
Damien George088740e2017-01-17 15:27:37 +1100746 }
Damien Georgef4df3aa2016-01-09 23:59:52 +0000747 DISPATCH();
748 }
749
Damien Georged8675542014-05-25 22:58:04 +0100750 ENTRY(MP_BC_FOR_ITER): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200751 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800752 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgec60a2612014-06-01 12:32:28 +0100753 code_state->sp = sp;
Damien George088740e2017-01-17 15:27:37 +1100754 mp_obj_t obj;
Damien George60656ea2017-03-23 16:36:08 +1100755 if (sp[-MP_OBJ_ITER_BUF_NSLOTS + 1] == MP_OBJ_NULL) {
756 obj = sp[-MP_OBJ_ITER_BUF_NSLOTS + 2];
Damien George088740e2017-01-17 15:27:37 +1100757 } else {
Damien George60656ea2017-03-23 16:36:08 +1100758 obj = MP_OBJ_FROM_PTR(&sp[-MP_OBJ_ITER_BUF_NSLOTS + 1]);
Damien George088740e2017-01-17 15:27:37 +1100759 }
760 mp_obj_t value = mp_iternext_allow_raise(obj);
Damien Georged8675542014-05-25 22:58:04 +0100761 if (value == MP_OBJ_STOP_ITERATION) {
Damien George60656ea2017-03-23 16:36:08 +1100762 sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator
Damien Georgecd97a432014-12-02 19:25:10 +0000763 ip += ulab; // jump to after for-block
AZ Huangb1f692e2014-04-14 23:22:44 +0800764 } else {
Damien Georged8675542014-05-25 22:58:04 +0100765 PUSH(value); // push the next iteration value
AZ Huangb1f692e2014-04-14 23:22:44 +0800766 }
767 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100768 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800769
770 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
771 ENTRY(MP_BC_POP_BLOCK):
772 // we are exiting an exception handler, so pop the last one of the exception-stack
773 assert(exc_sp >= exc_stack);
774 POP_EXC_BLOCK();
775 DISPATCH();
776
777 // matched against: SETUP_EXCEPT
778 ENTRY(MP_BC_POP_EXCEPT):
AZ Huangb1f692e2014-04-14 23:22:44 +0800779 assert(exc_sp >= exc_stack);
780 assert(currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +0800781 POP_EXC_BLOCK();
AZ Huangb1f692e2014-04-14 23:22:44 +0800782 DISPATCH();
783
Damien Georgecd97a432014-12-02 19:25:10 +0000784 ENTRY(MP_BC_BUILD_TUPLE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200785 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800786 DECODE_UINT;
787 sp -= unum - 1;
788 SET_TOP(mp_obj_new_tuple(unum, sp));
789 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000790 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800791
Damien Georgecd97a432014-12-02 19:25:10 +0000792 ENTRY(MP_BC_BUILD_LIST): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200793 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800794 DECODE_UINT;
795 sp -= unum - 1;
796 SET_TOP(mp_obj_new_list(unum, sp));
797 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000798 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800799
Damien Georgecd97a432014-12-02 19:25:10 +0000800 ENTRY(MP_BC_BUILD_MAP): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200801 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800802 DECODE_UINT;
803 PUSH(mp_obj_new_dict(unum));
804 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000805 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800806
807 ENTRY(MP_BC_STORE_MAP):
Paul Sokolovsky74957502014-12-28 07:17:43 +0200808 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800809 sp -= 2;
810 mp_obj_dict_store(sp[0], sp[2], sp[1]);
811 DISPATCH();
812
Damien George3ebd4d02014-06-01 13:46:47 +0100813#if MICROPY_PY_BUILTINS_SET
Damien Georgecd97a432014-12-02 19:25:10 +0000814 ENTRY(MP_BC_BUILD_SET): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200815 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800816 DECODE_UINT;
817 sp -= unum - 1;
818 SET_TOP(mp_obj_new_set(unum, sp));
819 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000820 }
Damien George3ebd4d02014-06-01 13:46:47 +0100821#endif
Damienc12aa462013-10-16 20:57:49 +0100822
Damien Georgefb510b32014-06-01 13:32:54 +0100823#if MICROPY_PY_BUILTINS_SLICE
Damien Georgecd97a432014-12-02 19:25:10 +0000824 ENTRY(MP_BC_BUILD_SLICE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200825 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800826 DECODE_UINT;
827 if (unum == 2) {
Damien Georged8675542014-05-25 22:58:04 +0100828 mp_obj_t stop = POP();
829 mp_obj_t start = TOP();
830 SET_TOP(mp_obj_new_slice(start, stop, mp_const_none));
AZ Huangb1f692e2014-04-14 23:22:44 +0800831 } else {
Damien Georged8675542014-05-25 22:58:04 +0100832 mp_obj_t step = POP();
833 mp_obj_t stop = POP();
834 mp_obj_t start = TOP();
835 SET_TOP(mp_obj_new_slice(start, stop, step));
AZ Huangb1f692e2014-04-14 23:22:44 +0800836 }
837 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000838 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800839#endif
840
Damien Georgeadaf0d82016-09-19 08:46:01 +1000841 ENTRY(MP_BC_STORE_COMP): {
842 MARK_EXC_IP_SELECTIVE();
843 DECODE_UINT;
844 mp_obj_t obj = sp[-(unum >> 2)];
845 if ((unum & 3) == 0) {
846 mp_obj_list_append(obj, sp[0]);
847 sp--;
848 } else if (!MICROPY_PY_BUILTINS_SET || (unum & 3) == 1) {
849 mp_obj_dict_store(obj, sp[0], sp[-1]);
850 sp -= 2;
851 #if MICROPY_PY_BUILTINS_SET
852 } else {
853 mp_obj_set_store(obj, sp[0]);
854 sp--;
855 #endif
856 }
857 DISPATCH();
858 }
859
Damien Georgecd97a432014-12-02 19:25:10 +0000860 ENTRY(MP_BC_UNPACK_SEQUENCE): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200861 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800862 DECODE_UINT;
863 mp_unpack_sequence(sp[0], unum, sp);
864 sp += unum - 1;
865 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000866 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800867
Damien Georgecd97a432014-12-02 19:25:10 +0000868 ENTRY(MP_BC_UNPACK_EX): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200869 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800870 DECODE_UINT;
871 mp_unpack_ex(sp[0], unum, sp);
872 sp += (unum & 0xff) + ((unum >> 8) & 0xff);
873 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000874 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800875
Damien Georgecd97a432014-12-02 19:25:10 +0000876 ENTRY(MP_BC_MAKE_FUNCTION): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800877 DECODE_PTR;
Damien Georgecd97a432014-12-02 19:25:10 +0000878 PUSH(mp_make_function_from_raw_code(ptr, MP_OBJ_NULL, MP_OBJ_NULL));
AZ Huangb1f692e2014-04-14 23:22:44 +0800879 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000880 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800881
Damien Georged8675542014-05-25 22:58:04 +0100882 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800883 DECODE_PTR;
884 // Stack layout: def_tuple def_dict <- TOS
Damien Georged8675542014-05-25 22:58:04 +0100885 mp_obj_t def_dict = POP();
Damien Georgecd97a432014-12-02 19:25:10 +0000886 SET_TOP(mp_make_function_from_raw_code(ptr, TOP(), def_dict));
AZ Huangb1f692e2014-04-14 23:22:44 +0800887 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100888 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800889
Damien George3558f622014-04-20 17:50:40 +0100890 ENTRY(MP_BC_MAKE_CLOSURE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800891 DECODE_PTR;
Damien George101886f2017-02-16 16:48:33 +1100892 size_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100893 // Stack layout: closed_overs <- TOS
894 sp -= n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000895 SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800896 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100897 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800898
Damien George3558f622014-04-20 17:50:40 +0100899 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800900 DECODE_PTR;
Damien George101886f2017-02-16 16:48:33 +1100901 size_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100902 // Stack layout: def_tuple def_dict closed_overs <- TOS
903 sp -= 2 + n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000904 SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800905 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100906 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800907
Damien Georgecd97a432014-12-02 19:25:10 +0000908 ENTRY(MP_BC_CALL_FUNCTION): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200909 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800910 DECODE_UINT;
911 // unum & 0xff == n_positional
912 // (unum >> 8) & 0xff == n_keyword
913 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
Paul Sokolovsky20397572015-03-28 01:14:44 +0200914 #if MICROPY_STACKLESS
915 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
916 code_state->ip = ip;
917 code_state->sp = sp;
918 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
Damien George581a59a2016-08-27 23:21:00 +1000919 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 +0200920 if (new_state) {
921 new_state->prev = code_state;
922 code_state = new_state;
923 nlr_pop();
924 goto run_code_state;
925 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200926 #if MICROPY_STACKLESS_STRICT
927 else {
928 deep_recursion_error:
929 mp_exc_recursion_depth();
930 }
931 #endif
Paul Sokolovsky20397572015-03-28 01:14:44 +0200932 }
933 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800934 SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
935 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000936 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800937
Damien Georgecd97a432014-12-02 19:25:10 +0000938 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200939 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800940 DECODE_UINT;
941 // unum & 0xff == n_positional
942 // (unum >> 8) & 0xff == n_keyword
943 // We have folowing stack layout here:
944 // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
945 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200946 #if MICROPY_STACKLESS
947 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
948 code_state->ip = ip;
949 code_state->sp = sp;
950 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
951
Damien George12a5e172015-04-01 23:31:30 +0100952 mp_call_args_t out_args;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200953 mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args);
954
Damien George581a59a2016-08-27 23:21:00 +1000955 mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200956 out_args.n_args, out_args.n_kw, out_args.args);
957 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
958 if (new_state) {
959 new_state->prev = code_state;
960 code_state = new_state;
961 nlr_pop();
962 goto run_code_state;
963 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200964 #if MICROPY_STACKLESS_STRICT
965 else {
966 goto deep_recursion_error;
967 }
968 #endif
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +0200969 }
970 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +0800971 SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
972 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000973 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800974
Damien Georgecd97a432014-12-02 19:25:10 +0000975 ENTRY(MP_BC_CALL_METHOD): {
Paul Sokolovsky74957502014-12-28 07:17:43 +0200976 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +0800977 DECODE_UINT;
978 // unum & 0xff == n_positional
979 // (unum >> 8) & 0xff == n_keyword
980 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200981 #if MICROPY_STACKLESS
982 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
983 code_state->ip = ip;
984 code_state->sp = sp;
985 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
986
Damien George101886f2017-02-16 16:48:33 +1100987 size_t n_args = unum & 0xff;
988 size_t n_kw = (unum >> 8) & 0xff;
Damien George7a30e872015-12-17 12:32:41 +0000989 int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1;
Paul Sokolovsky390e9262015-03-28 01:14:44 +0200990
Damien George581a59a2016-08-27 23:21:00 +1000991 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 +0200992 if (new_state) {
993 new_state->prev = code_state;
994 code_state = new_state;
995 nlr_pop();
996 goto run_code_state;
997 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +0200998 #if MICROPY_STACKLESS_STRICT
999 else {
1000 goto deep_recursion_error;
1001 }
1002 #endif
Paul Sokolovsky390e9262015-03-28 01:14:44 +02001003 }
1004 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001005 SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
1006 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +00001007 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001008
Damien Georgecd97a432014-12-02 19:25:10 +00001009 ENTRY(MP_BC_CALL_METHOD_VAR_KW): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001010 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001011 DECODE_UINT;
1012 // unum & 0xff == n_positional
1013 // (unum >> 8) & 0xff == n_keyword
1014 // We have folowing stack layout here:
1015 // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
1016 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001017 #if MICROPY_STACKLESS
1018 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
1019 code_state->ip = ip;
1020 code_state->sp = sp;
1021 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
1022
Damien George12a5e172015-04-01 23:31:30 +01001023 mp_call_args_t out_args;
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001024 mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args);
1025
Damien George581a59a2016-08-27 23:21:00 +10001026 mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001027 out_args.n_args, out_args.n_kw, out_args.args);
1028 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
1029 if (new_state) {
1030 new_state->prev = code_state;
1031 code_state = new_state;
1032 nlr_pop();
1033 goto run_code_state;
1034 }
Paul Sokolovsky7f1c9812015-03-28 01:14:45 +02001035 #if MICROPY_STACKLESS_STRICT
1036 else {
1037 goto deep_recursion_error;
1038 }
1039 #endif
Paul Sokolovskyf0a8f212015-03-28 01:14:45 +02001040 }
1041 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001042 SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
1043 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +00001044 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001045
1046 ENTRY(MP_BC_RETURN_VALUE):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001047 MARK_EXC_IP_SELECTIVE();
Damien George80473402015-12-24 12:47:39 +00001048 // These next 3 lines pop a try-finally exception handler, if one
1049 // is there on the exception stack. Without this the finally block
1050 // is executed a second time when the return is executed, because
1051 // the try-finally exception handler is still on the stack.
1052 // TODO Possibly find a better way to handle this case.
1053 if (currently_in_except_block) {
1054 POP_EXC_BLOCK();
1055 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001056unwind_return:
1057 while (exc_sp >= exc_stack) {
Damien George74eb44c2014-12-22 12:49:57 +00001058 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
Damien George4bf3f2d2015-10-15 17:48:28 +01001059 // Getting here the stack looks like:
1060 // (..., X, [iter0, iter1, ...,] ret_val)
1061 // where X is pointed to by exc_sp->val_sp and in the case
1062 // of a "with" block contains the context manager info.
1063 // There may be 0 or more for-iterators between X and the
1064 // return value, and these must be removed before control can
1065 // pass to the finally code. We simply copy the ret_value down
1066 // over these iterators, if they exist. If they don't then the
1067 // following is a null operation.
1068 mp_obj_t *finally_sp = MP_TAGPTR_PTR(exc_sp->val_sp);
1069 finally_sp[1] = sp[0];
1070 sp = &finally_sp[1];
AZ Huangb1f692e2014-04-14 23:22:44 +08001071 // We're going to run "finally" code as a coroutine
1072 // (not calling it recursively). Set up a sentinel
1073 // on a stack so it can return back to us when it is
Damien George4bf3f2d2015-10-15 17:48:28 +01001074 // done (when WITH_CLEANUP or END_FINALLY reached).
AZ Huangb1f692e2014-04-14 23:22:44 +08001075 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
1076 ip = exc_sp->handler;
AZ Huangb1f692e2014-04-14 23:22:44 +08001077 exc_sp--;
1078 goto dispatch_loop;
1079 }
1080 exc_sp--;
1081 }
1082 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001083 code_state->sp = sp;
AZ Huangb1f692e2014-04-14 23:22:44 +08001084 assert(exc_sp == exc_stack - 1);
Damien George40d84302016-02-15 22:46:21 +00001085 MICROPY_VM_HOOK_RETURN
Paul Sokolovsky20397572015-03-28 01:14:44 +02001086 #if MICROPY_STACKLESS
1087 if (code_state->prev != NULL) {
1088 mp_obj_t res = *sp;
1089 mp_globals_set(code_state->old_globals);
1090 code_state = code_state->prev;
1091 *code_state->sp = res;
1092 goto run_code_state;
1093 }
1094 #endif
AZ Huangb1f692e2014-04-14 23:22:44 +08001095 return MP_VM_RETURN_NORMAL;
1096
Damien Georged8675542014-05-25 22:58:04 +01001097 ENTRY(MP_BC_RAISE_VARARGS): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001098 MARK_EXC_IP_SELECTIVE();
Damien Georgecd97a432014-12-02 19:25:10 +00001099 mp_uint_t unum = *ip++;
Damien Georged8675542014-05-25 22:58:04 +01001100 mp_obj_t obj;
Paul Sokolovsky2ff2ea52015-09-01 10:35:58 +03001101 if (unum == 2) {
1102 mp_warning("exception chaining not supported");
1103 // ignore (pop) "from" argument
1104 sp--;
1105 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001106 if (unum == 0) {
1107 // search for the inner-most previous exception, to reraise it
Damien Georged8675542014-05-25 22:58:04 +01001108 obj = MP_OBJ_NULL;
AZ Huangb1f692e2014-04-14 23:22:44 +08001109 for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
Damien George999cedb2015-11-27 17:01:44 +00001110 if (e->prev_exc != NULL) {
1111 obj = MP_OBJ_FROM_PTR(e->prev_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +08001112 break;
1113 }
1114 }
Damien Georged8675542014-05-25 22:58:04 +01001115 if (obj == MP_OBJ_NULL) {
1116 obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
1117 RAISE(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001118 }
1119 } else {
Damien Georged8675542014-05-25 22:58:04 +01001120 obj = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +08001121 }
Damien Georged8675542014-05-25 22:58:04 +01001122 obj = mp_make_raise_obj(obj);
1123 RAISE(obj);
1124 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001125
1126 ENTRY(MP_BC_YIELD_VALUE):
1127yield:
1128 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001129 code_state->ip = ip;
1130 code_state->sp = sp;
1131 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +08001132 return MP_VM_RETURN_YIELD;
1133
1134 ENTRY(MP_BC_YIELD_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001135 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001136//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
1137#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
Damien George999cedb2015-11-27 17:01:44 +00001138#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 +08001139 mp_vm_return_kind_t ret_kind;
Damien Georged8675542014-05-25 22:58:04 +01001140 mp_obj_t send_value = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +08001141 mp_obj_t t_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +01001142 mp_obj_t ret_value;
AZ Huangb1f692e2014-04-14 23:22:44 +08001143 if (inject_exc != MP_OBJ_NULL) {
1144 t_exc = inject_exc;
1145 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +01001146 ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001147 } else {
Damien Georged8675542014-05-25 22:58:04 +01001148 ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001149 }
1150
1151 if (ret_kind == MP_VM_RETURN_YIELD) {
1152 ip--;
Damien Georged8675542014-05-25 22:58:04 +01001153 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001154 goto yield;
1155 }
1156 if (ret_kind == MP_VM_RETURN_NORMAL) {
1157 // Pop exhausted gen
1158 sp--;
Paul Sokolovskyeff85bb2016-04-28 01:54:23 +03001159 // TODO: When ret_value can be MP_OBJ_NULL here??
1160 if (ret_value == MP_OBJ_NULL || ret_value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +08001161 // Optimize StopIteration
1162 // TODO: get StopIteration's value
1163 PUSH(mp_const_none);
1164 } else {
Damien Georged8675542014-05-25 22:58:04 +01001165 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001166 }
1167
1168 // If we injected GeneratorExit downstream, then even
1169 // if it was swallowed, we re-raise GeneratorExit
1170 GENERATOR_EXIT_IF_NEEDED(t_exc);
1171 DISPATCH();
1172 }
1173 if (ret_kind == MP_VM_RETURN_EXCEPTION) {
1174 // Pop exhausted gen
1175 sp--;
Damien George999cedb2015-11-27 17:01:44 +00001176 if (EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
Damien Georged8675542014-05-25 22:58:04 +01001177 PUSH(mp_obj_exception_get_value(ret_value));
AZ Huangb1f692e2014-04-14 23:22:44 +08001178 // If we injected GeneratorExit downstream, then even
1179 // if it was swallowed, we re-raise GeneratorExit
1180 GENERATOR_EXIT_IF_NEEDED(t_exc);
1181 DISPATCH();
1182 } else {
Damien Georged8675542014-05-25 22:58:04 +01001183 RAISE(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +08001184 }
1185 }
Damien429d7192013-10-04 19:53:11 +01001186 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001187
Damien Georged8675542014-05-25 22:58:04 +01001188 ENTRY(MP_BC_IMPORT_NAME): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001189 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001190 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001191 mp_obj_t obj = POP();
1192 SET_TOP(mp_import_name(qst, obj, TOP()));
AZ Huangb1f692e2014-04-14 23:22:44 +08001193 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001194 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001195
Damien Georged8675542014-05-25 22:58:04 +01001196 ENTRY(MP_BC_IMPORT_FROM): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001197 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001198 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001199 mp_obj_t obj = mp_import_from(TOP(), qst);
1200 PUSH(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001201 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001202 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001203
1204 ENTRY(MP_BC_IMPORT_STAR):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001205 MARK_EXC_IP_SELECTIVE();
AZ Huangb1f692e2014-04-14 23:22:44 +08001206 mp_import_all(POP());
1207 DISPATCH();
1208
Damien George8456cc02014-10-25 16:43:46 +01001209#if MICROPY_OPT_COMPUTED_GOTO
1210 ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):
1211 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1212 DISPATCH();
1213
1214 ENTRY(MP_BC_LOAD_FAST_MULTI):
1215 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1216 goto load_check;
1217
1218 ENTRY(MP_BC_STORE_FAST_MULTI):
1219 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1220 DISPATCH();
1221
1222 ENTRY(MP_BC_UNARY_OP_MULTI):
Paul Sokolovsky74957502014-12-28 07:17:43 +02001223 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001224 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1225 DISPATCH();
1226
1227 ENTRY(MP_BC_BINARY_OP_MULTI): {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001228 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001229 mp_obj_t rhs = POP();
1230 mp_obj_t lhs = TOP();
1231 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1232 DISPATCH();
1233 }
1234
1235 ENTRY_DEFAULT:
Paul Sokolovsky74957502014-12-28 07:17:43 +02001236 MARK_EXC_IP_SELECTIVE();
Damien George8456cc02014-10-25 16:43:46 +01001237#else
1238 ENTRY_DEFAULT:
1239 if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
1240 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
1241 DISPATCH();
1242 } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
1243 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1244 goto load_check;
1245 } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
1246 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1247 DISPATCH();
Damien Georgebdbe8c92015-12-08 12:28:11 +00001248 } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 7) {
Damien George8456cc02014-10-25 16:43:46 +01001249 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1250 DISPATCH();
Damien Georgec5029bc2015-06-13 22:00:10 +01001251 } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) {
Damien George8456cc02014-10-25 16:43:46 +01001252 mp_obj_t rhs = POP();
1253 mp_obj_t lhs = TOP();
1254 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1255 DISPATCH();
1256 } else
1257#endif
1258 {
Damien Georged8675542014-05-25 22:58:04 +01001259 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
AZ Huangb1f692e2014-04-14 23:22:44 +08001260 nlr_pop();
Damien Georged8675542014-05-25 22:58:04 +01001261 fastn[0] = obj;
AZ Huangb1f692e2014-04-14 23:22:44 +08001262 return MP_VM_RETURN_EXCEPTION;
Damien Georged8675542014-05-25 22:58:04 +01001263 }
Damien George66ae8c92014-04-17 16:50:23 +01001264
Damien George58ebde42014-05-21 20:32:59 +01001265#if !MICROPY_OPT_COMPUTED_GOTO
AZ Huang9309d992014-04-15 15:57:01 +08001266 } // switch
AZ Huangb1f692e2014-04-14 23:22:44 +08001267#endif
Damien George124df6f2014-10-25 18:19:55 +01001268
1269pending_exception_check:
Damien George40d84302016-02-15 22:46:21 +00001270 MICROPY_VM_HOOK_LOOP
Damien George6e74d242017-02-16 18:05:06 +11001271
1272 #if MICROPY_ENABLE_SCHEDULER
1273 // This is an inlined variant of mp_handle_pending
1274 if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) {
1275 MARK_EXC_IP_SELECTIVE();
1276 mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
1277 mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
1278 if (obj != MP_OBJ_NULL) {
1279 MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
1280 if (!mp_sched_num_pending()) {
1281 MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
1282 }
1283 MICROPY_END_ATOMIC_SECTION(atomic_state);
1284 RAISE(obj);
1285 }
1286 mp_handle_pending_tail(atomic_state);
1287 }
1288 #else
1289 // This is an inlined variant of mp_handle_pending
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001290 if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
Paul Sokolovsky74957502014-12-28 07:17:43 +02001291 MARK_EXC_IP_SELECTIVE();
Damien Georgeb4b10fd2015-01-01 23:30:53 +00001292 mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
1293 MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
Damien George124df6f2014-10-25 18:19:55 +01001294 RAISE(obj);
1295 }
Damien George6e74d242017-02-16 18:05:06 +11001296 #endif
Damien George124df6f2014-10-25 18:19:55 +01001297
Damien Georgef6c22a02017-02-06 10:50:43 +11001298 #if MICROPY_PY_THREAD_GIL
1299 #if MICROPY_PY_THREAD_GIL_VM_DIVISOR
1300 if (--gil_divisor == 0) {
1301 gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
1302 #else
1303 {
1304 #endif
Damien George1a5c8d12017-03-20 18:42:27 +11001305 #if MICROPY_ENABLE_SCHEDULER
1306 // can only switch threads if the scheduler is unlocked
1307 if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE)
1308 #endif
1309 {
Damien Georgef6c22a02017-02-06 10:50:43 +11001310 MP_THREAD_GIL_EXIT();
1311 MP_THREAD_GIL_ENTER();
Damien George1a5c8d12017-03-20 18:42:27 +11001312 }
Damien Georgef6c22a02017-02-06 10:50:43 +11001313 }
1314 #endif
Damien George4cec63a2016-05-26 10:42:53 +00001315
Damien George66ae8c92014-04-17 16:50:23 +01001316 } // for loop
Damien429d7192013-10-04 19:53:11 +01001317
Damience89a212013-10-15 22:25:17 +01001318 } else {
Damien George66ae8c92014-04-17 16:50:23 +01001319exception_handler:
Damience89a212013-10-15 22:25:17 +01001320 // exception occurred
Damien429d7192013-10-04 19:53:11 +01001321
Paul Sokolovsky8b85d142015-04-25 03:17:41 +03001322 #if MICROPY_PY_SYS_EXC_INFO
1323 MP_STATE_VM(cur_exception) = nlr.ret_val;
1324 #endif
1325
Damien Georgef89d6592014-12-29 00:29:59 +00001326 #if SELECTIVE_EXC_IP
1327 // with selective ip, we store the ip 1 byte past the opcode, so move ptr back
1328 code_state->ip -= 1;
1329 #endif
1330
Damien George999cedb2015-11-27 17:01:44 +00001331 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 +03001332 if (code_state->ip) {
1333 // check if it's a StopIteration within a for block
1334 if (*code_state->ip == MP_BC_FOR_ITER) {
1335 const byte *ip = code_state->ip + 1;
1336 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
1337 code_state->ip = ip + ulab; // jump to after for-block
Damien George60656ea2017-03-23 16:36:08 +11001338 code_state->sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator
Paul Sokolovskya7c02c42015-05-10 17:18:10 +03001339 goto outer_dispatch_loop; // continue with dispatch loop
Paul Sokolovsky6738c1d2015-05-11 02:59:25 +03001340 } else if (*code_state->ip == MP_BC_YIELD_FROM) {
1341 // StopIteration inside yield from call means return a value of
1342 // yield from, so inject exception's value as yield from's result
Damien George999cedb2015-11-27 17:01:44 +00001343 *++code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));
Paul Sokolovsky6738c1d2015-05-11 02:59:25 +03001344 code_state->ip++; // yield from is over, move to next instruction
1345 goto outer_dispatch_loop; // continue with dispatch loop
Paul Sokolovskya7c02c42015-05-10 17:18:10 +03001346 }
1347 }
Damien George9e6e9352014-03-26 18:37:06 +00001348 }
1349
Paul Sokolovsky20397572015-03-28 01:14:44 +02001350#if MICROPY_STACKLESS
1351unwind_loop:
1352#endif
Damien George08335002014-01-18 23:24:36 +00001353 // set file and line number that the exception occurred at
Paul Sokolovsky382e8ee2014-01-30 13:49:18 +02001354 // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
1355 // But consider how to handle nested exceptions.
Damien George6902eed2014-04-04 10:52:59 +00001356 // 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 +00001357 if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
Damien George71a3d6e2017-03-17 14:54:53 +11001358 const byte *ip = code_state->fun_bc->bytecode;
1359 mp_decode_uint(&ip); // skip n_state
1360 mp_decode_uint(&ip); // skip n_exc_stack
1361 ip++; // skip scope_params
1362 ip++; // skip n_pos_args
1363 ip++; // skip n_kwonly_args
1364 ip++; // skip n_def_pos_args
1365 size_t bc = code_state->ip - ip;
Damien George101886f2017-02-16 16:48:33 +11001366 size_t code_info_size = mp_decode_uint(&ip);
Damien George71a3d6e2017-03-17 14:54:53 +11001367 bc -= code_info_size;
Damien Georgec8e9c0d2015-11-02 17:27:18 +00001368 #if MICROPY_PERSISTENT_CODE
1369 qstr block_name = ip[0] | (ip[1] << 8);
1370 qstr source_file = ip[2] | (ip[3] << 8);
1371 ip += 4;
1372 #else
Damien Georgeb534e1b2014-09-04 14:44:01 +01001373 qstr block_name = mp_decode_uint(&ip);
1374 qstr source_file = mp_decode_uint(&ip);
Damien Georgec8e9c0d2015-11-02 17:27:18 +00001375 #endif
Damien George3d2daa22016-01-02 22:04:12 +00001376 size_t source_line = 1;
1377 size_t c;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001378 while ((c = *ip)) {
Damien George101886f2017-02-16 16:48:33 +11001379 size_t b, l;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001380 if ((c & 0x80) == 0) {
1381 // 0b0LLBBBBB encoding
1382 b = c & 0x1f;
1383 l = c >> 5;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001384 ip += 1;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001385 } else {
1386 // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
1387 b = c & 0xf;
Damien Georgeb534e1b2014-09-04 14:44:01 +01001388 l = ((c << 4) & 0x700) | ip[1];
1389 ip += 2;
Damien Georgeb427d6a2014-08-26 23:35:57 +01001390 }
1391 if (bc >= b) {
1392 bc -= b;
1393 source_line += l;
1394 } else {
1395 // found source line corresponding to bytecode offset
1396 break;
Paul Sokolovsky411732e2014-06-02 18:24:34 +03001397 }
Damien George08335002014-01-18 23:24:36 +00001398 }
Damien George999cedb2015-11-27 17:01:44 +00001399 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 +00001400 }
1401
Damien8f9e2ee2013-12-29 16:54:59 +00001402 while (currently_in_except_block) {
1403 // nested exception
1404
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001405 assert(exc_sp >= exc_stack);
Damien8f9e2ee2013-12-29 16:54:59 +00001406
1407 // TODO make a proper message for nested exception
1408 // at the moment we are just raising the very last exception (the one that caused the nested exception)
1409
1410 // move up to previous exception handler
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +02001411 POP_EXC_BLOCK();
Damien8f9e2ee2013-12-29 16:54:59 +00001412 }
1413
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001414 if (exc_sp >= exc_stack) {
Damien8f9e2ee2013-12-29 16:54:59 +00001415 // set flag to indicate that we are now handling an exception
1416 currently_in_except_block = 1;
1417
Damience89a212013-10-15 22:25:17 +01001418 // catch exception and pass to byte code
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001419 code_state->ip = exc_sp->handler;
Damien George66ae8c92014-04-17 16:50:23 +01001420 mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
Damien Georged7592a12014-03-30 00:54:48 +00001421 // save this exception in the stack so it can be used in a reraise, if needed
1422 exc_sp->prev_exc = nlr.ret_val;
Damien Georgef0406852016-09-27 12:37:21 +10001423 // push exception object so it can be handled by bytecode
Damien George999cedb2015-11-27 17:01:44 +00001424 PUSH(MP_OBJ_FROM_PTR(nlr.ret_val));
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001425 code_state->sp = sp;
Damien8f9e2ee2013-12-29 16:54:59 +00001426
Paul Sokolovsky20397572015-03-28 01:14:44 +02001427 #if MICROPY_STACKLESS
1428 } else if (code_state->prev != NULL) {
1429 mp_globals_set(code_state->old_globals);
1430 code_state = code_state->prev;
Damien George71a3d6e2017-03-17 14:54:53 +11001431 fastn = &code_state->state[n_state - 1];
1432 exc_stack = (mp_exc_stack_t*)(code_state->state + n_state);
Paul Sokolovsky20397572015-03-28 01:14:44 +02001433 // variables that are visible to the exception handler (declared volatile)
1434 currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
1435 exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
1436 goto unwind_loop;
1437
1438 #endif
Damience89a212013-10-15 22:25:17 +01001439 } else {
Damien Georgec8f78bc2014-02-15 22:55:00 +00001440 // propagate exception to higher level
1441 // TODO what to do about ip and sp? they don't really make sense at this point
Damien George999cedb2015-11-27 17:01:44 +00001442 fastn[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // must put exception here because sp is invalid
Damien Georgec8f78bc2014-02-15 22:55:00 +00001443 return MP_VM_RETURN_EXCEPTION;
Damience89a212013-10-15 22:25:17 +01001444 }
Damien429d7192013-10-04 19:53:11 +01001445 }
1446 }
1447}