blob: cfb390bae728ade1c2037f68206288b5ca45932d [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>
Paul Sokolovskyb16523a2014-05-31 03:41:08 +030031#include <alloca.h>
Damien429d7192013-10-04 19:53:11 +010032
Paul Sokolovskyf54bcbf2014-05-02 17:47:01 +030033#include "mpconfig.h"
Damience89a212013-10-15 22:25:17 +010034#include "nlr.h"
Damien429d7192013-10-04 19:53:11 +010035#include "misc.h"
Damien George55baff42014-01-21 21:40:13 +000036#include "qstr.h"
Damiend99b0522013-12-21 18:17:45 +000037#include "obj.h"
Damien Georgedf8127a2014-04-13 11:04:33 +010038#include "emitglue.h"
Damien429d7192013-10-04 19:53:11 +010039#include "runtime.h"
Damiend99b0522013-12-21 18:17:45 +000040#include "bc0.h"
Damieneb19efb2013-10-10 22:06:54 +010041#include "bc.h"
Paul Sokolovskycf21a4e2014-03-26 17:36:12 +020042#include "objgenerator.h"
Damien429d7192013-10-04 19:53:11 +010043
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +030044// With these macros you can tune the maximum number of function state bytes
Damien Georged5e84822014-04-24 13:52:06 +010045// that will be allocated on the stack. Any function that needs more
46// than this will use the heap.
Damien George1b87d102014-06-01 12:06:17 +010047#define VM_MAX_STATE_ON_STACK (10 * sizeof(machine_uint_t))
Damien Georged5e84822014-04-24 13:52:06 +010048
Damien Georgee90be0d2014-04-10 16:21:34 +000049#define DETECT_VM_STACK_OVERFLOW (0)
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +030050#if 0
Damien George3417bc22014-05-10 10:36:38 +010051#define TRACE(ip) mp_bytecode_print2(ip, 1);
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +030052#else
53#define TRACE(ip)
54#endif
Damien Georgee90be0d2014-04-10 16:21:34 +000055
Paul Sokolovsky85193422014-01-31 19:45:15 +020056// Value stack grows up (this makes it incompatible with native C stack, but
57// makes sure that arguments to functions are in natural order arg1..argN
58// (Python semantics mandates left-to-right evaluation order, including for
59// function arguments). Stack pointer is pre-incremented and points at the
60// top element.
61// Exception stack also grows up, top element is also pointed at.
62
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020063// Exception stack unwind reasons (WHY_* in CPython-speak)
Damien Georgecbddb272014-02-01 20:08:18 +000064// TODO perhaps compress this to RETURN=0, JUMP>0, with number of unwinds
65// left to do encoded in the JUMP number
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020066typedef enum {
67 UNWIND_RETURN = 1,
Damien Georgecbddb272014-02-01 20:08:18 +000068 UNWIND_JUMP,
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020069} mp_unwind_reason_t;
70
Damien Georgedf8127a2014-04-13 11:04:33 +010071#define DECODE_UINT do { \
Paul Sokolovsky0f96ec82014-02-18 21:21:22 +020072 unum = 0; \
73 do { \
74 unum = (unum << 7) + (*ip & 0x7f); \
75 } while ((*ip++ & 0x80) != 0); \
Damien Georgedf8127a2014-04-13 11:04:33 +010076} while (0)
Damien03c9cfb2013-11-05 22:06:08 +000077#define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0)
78#define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0)
Damien Georged8675542014-05-25 22:58:04 +010079#define DECODE_QSTR qstr qst = 0; \
Paul Sokolovsky0f96ec82014-02-18 21:21:22 +020080 do { \
81 qst = (qst << 7) + (*ip & 0x7f); \
Damien Georged8675542014-05-25 22:58:04 +010082 } while ((*ip++ & 0x80) != 0)
Damien Georgedf8127a2014-04-13 11:04:33 +010083#define DECODE_PTR do { \
84 ip = (byte*)(((machine_uint_t)ip + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1))); /* align ip */ \
85 unum = *(machine_uint_t*)ip; \
86 ip += sizeof(machine_uint_t); \
87} while (0)
Damien George20006db2014-01-18 14:10:48 +000088#define PUSH(val) *++sp = (val)
89#define POP() (*sp--)
Damiendb4c3612013-12-10 17:27:24 +000090#define TOP() (*sp)
91#define SET_TOP(val) *sp = (val)
Damien429d7192013-10-04 19:53:11 +010092
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +020093#define PUSH_EXC_BLOCK() \
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +020094 DECODE_ULABEL; /* except labels are always forward */ \
95 ++exc_sp; \
Damien Georgec60a2612014-06-01 12:32:28 +010096 exc_sp->opcode = *code_state->ip; \
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +020097 exc_sp->handler = ip + unum; \
98 exc_sp->val_sp = MP_TAGPTR_MAKE(sp, currently_in_except_block); \
Damien Georged7592a12014-03-30 00:54:48 +000099 exc_sp->prev_exc = MP_OBJ_NULL; \
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +0200100 currently_in_except_block = 0; /* in a try block now */
101
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +0200102#define POP_EXC_BLOCK() \
103 currently_in_except_block = MP_TAGPTR_TAG(exc_sp->val_sp); /* restore previous state */ \
104 exc_sp--; /* pop back to previous exception handler */
105
Paul Sokolovsky1f07b7e2014-05-31 03:36:37 +0300106mp_vm_return_kind_t mp_execute_bytecode(const byte *code, const mp_obj_t *args, uint n_args,
107 const mp_obj_t *args2, uint n_args2, mp_obj_t *ret) {
Damien George8dcc0c72014-03-27 10:55:21 +0000108 const byte *ip = code;
109
110 // get code info size, and skip line number table
111 machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
112 ip += code_info_size;
113
Damien Georgebee17b02014-03-27 11:07:04 +0000114 // bytecode prelude: state size and exception stack size; 16 bit uints
115 machine_uint_t n_state = ip[0] | (ip[1] << 8);
116 machine_uint_t n_exc_stack = ip[2] | (ip[3] << 8);
117 ip += 4;
Damien George8dcc0c72014-03-27 10:55:21 +0000118
Damien George20006db2014-01-18 14:10:48 +0000119 // allocate state for locals and stack
Damien Georgee90be0d2014-04-10 16:21:34 +0000120#if DETECT_VM_STACK_OVERFLOW
Damien Georgea1ef4412014-04-10 16:59:44 +0000121 n_state += 1;
122#endif
Damien George20006db2014-01-18 14:10:48 +0000123
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300124 int state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);
125 mp_code_state *code_state;
126 if (state_size > VM_MAX_STATE_ON_STACK) {
127 code_state = m_new_obj_var(mp_code_state, byte, state_size);
Paul Sokolovskyb16523a2014-05-31 03:41:08 +0300128 } else {
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300129 code_state = alloca(sizeof(mp_code_state) + state_size);
Damien George8dcc0c72014-03-27 10:55:21 +0000130 }
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300131
132 code_state->code_info = code;
133 code_state->sp = &code_state->state[0] - 1;
134 code_state->exc_sp = (mp_exc_stack_t*)(code_state->state + n_state) - 1;
135 code_state->n_state = n_state;
Damien George8dcc0c72014-03-27 10:55:21 +0000136
Damienbd254452013-10-16 20:39:12 +0100137 // init args
Damien Georgefb083ea2014-02-01 18:29:40 +0000138 for (uint i = 0; i < n_args; i++) {
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300139 code_state->state[n_state - 1 - i] = args[i];
Damienbd254452013-10-16 20:39:12 +0100140 }
Damien Georgefb083ea2014-02-01 18:29:40 +0000141 for (uint i = 0; i < n_args2; i++) {
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300142 code_state->state[n_state - 1 - n_args - i] = args2[i];
Damien Georgefb083ea2014-02-01 18:29:40 +0000143 }
Damien George08335002014-01-18 23:24:36 +0000144
Damien Georged99944a2014-04-09 19:53:31 +0100145 // set rest of state to MP_OBJ_NULL
146 for (uint i = 0; i < n_state - n_args - n_args2; i++) {
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300147 code_state->state[i] = MP_OBJ_NULL;
Damien Georged99944a2014-04-09 19:53:31 +0100148 }
149
Damien George8dcc0c72014-03-27 10:55:21 +0000150 // bytecode prelude: initialise closed over variables
151 for (uint n_local = *ip++; n_local > 0; n_local--) {
152 uint local_num = *ip++;
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300153 code_state->state[n_state - 1 - local_num] = mp_obj_new_cell(code_state->state[n_state - 1 - local_num]);
Damien George6baf76e2013-12-30 22:32:17 +0000154 }
155
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300156 code_state->ip = ip;
157
Damien George6baf76e2013-12-30 22:32:17 +0000158 // execute the byte code
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300159 mp_vm_return_kind_t vm_return_kind = mp_execute_bytecode2(code_state, MP_OBJ_NULL);
Damien George6baf76e2013-12-30 22:32:17 +0000160
Damien Georgee90be0d2014-04-10 16:21:34 +0000161#if DETECT_VM_STACK_OVERFLOW
Paul Sokolovskyff8da0b2014-05-31 18:14:54 +0300162 if (vm_return_kind == MP_VM_RETURN_NORMAL) {
Damien George1b87d102014-06-01 12:06:17 +0100163 if (code_state->sp < code_state->state) {
164 printf("VM stack underflow: " INT_FMT "\n", code_state->sp - code_state->state);
Paul Sokolovskyff8da0b2014-05-31 18:14:54 +0300165 assert(0);
166 }
167 }
Damien Georgea1ef4412014-04-10 16:59:44 +0000168 // We can't check the case when an exception is returned in state[n_state - 1]
169 // and there are no arguments, because in this case our detection slot may have
170 // been overwritten by the returned exception (which is allowed).
171 if (!(vm_return_kind == MP_VM_RETURN_EXCEPTION && n_args == 0 && n_args2 == 0)) {
172 // Just check to see that we have at least 1 null object left in the state.
173 bool overflow = true;
174 for (uint i = 0; i < n_state - n_args - n_args2; i++) {
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300175 if (code_state->state[i] == MP_OBJ_NULL) {
Damien Georgea1ef4412014-04-10 16:59:44 +0000176 overflow = false;
177 break;
178 }
179 }
180 if (overflow) {
Damien George1b87d102014-06-01 12:06:17 +0100181 printf("VM stack overflow state=%p n_state+1=" UINT_FMT "\n", code_state->state, n_state);
Damien Georgea1ef4412014-04-10 16:59:44 +0000182 assert(0);
183 }
Damien Georgee90be0d2014-04-10 16:21:34 +0000184 }
185#endif
186
Damien Georgec0dc7c32014-04-24 15:42:05 +0100187 mp_vm_return_kind_t ret_kind;
188 switch (vm_return_kind) {
189 case MP_VM_RETURN_NORMAL:
190 // return value is in *sp
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300191 *ret = *code_state->sp;
Damien Georgec0dc7c32014-04-24 15:42:05 +0100192 ret_kind = MP_VM_RETURN_NORMAL;
193 break;
194
195 case MP_VM_RETURN_EXCEPTION:
196 // return value is in state[n_state - 1]
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300197 *ret = code_state->state[n_state - 1];
Damien Georgec0dc7c32014-04-24 15:42:05 +0100198 ret_kind = MP_VM_RETURN_EXCEPTION;
199 break;
200
201 case MP_VM_RETURN_YIELD: // byte-code shouldn't yield
202 default:
203 assert(0);
204 *ret = mp_const_none;
205 ret_kind = MP_VM_RETURN_NORMAL;
Damien George1b87d102014-06-01 12:06:17 +0100206 break;
Damien Georgec0dc7c32014-04-24 15:42:05 +0100207 }
Damien Georged5e84822014-04-24 13:52:06 +0100208
209 // free the state if it was allocated on the heap
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300210 if (state_size > VM_MAX_STATE_ON_STACK) {
211 m_del_var(mp_code_state, byte, state_size, code_state);
Damien Georged5e84822014-04-24 13:52:06 +0100212 }
Damien Georgec0dc7c32014-04-24 15:42:05 +0100213 return ret_kind;
Damienbd254452013-10-16 20:39:12 +0100214}
215
Damien George20006db2014-01-18 14:10:48 +0000216// fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)
217// sp points to bottom of stack which grows up
Damien Georgec8f78bc2014-02-15 22:55:00 +0000218// returns:
219// MP_VM_RETURN_NORMAL, sp valid, return value in *sp
220// MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
221// MP_VM_RETURN_EXCEPTION, exception in fastn[0]
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300222mp_vm_return_kind_t mp_execute_bytecode2(mp_code_state *code_state, volatile mp_obj_t inject_exc) {
Damien George58ebde42014-05-21 20:32:59 +0100223#if MICROPY_OPT_COMPUTED_GOTO
AZ Huang9413ca02014-04-15 21:29:08 +0800224 #include "vmentrytable.h"
AZ Huang9309d992014-04-15 15:57:01 +0800225 #define DISPATCH() do { \
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +0300226 TRACE(ip); \
Damien Georgec60a2612014-06-01 12:32:28 +0100227 code_state->ip = ip; \
Damien Georgedb128912014-04-27 18:19:06 +0100228 goto *entry_table[*ip++]; \
AZ Huangb1f692e2014-04-14 23:22:44 +0800229 } while(0)
AZ Huang9309d992014-04-15 15:57:01 +0800230 #define ENTRY(op) entry_##op
231 #define ENTRY_DEFAULT entry_default
AZ Huangb1f692e2014-04-14 23:22:44 +0800232#else
AZ Huang9309d992014-04-15 15:57:01 +0800233 #define DISPATCH() break
234 #define ENTRY(op) case op
235 #define ENTRY_DEFAULT default
AZ Huangb1f692e2014-04-14 23:22:44 +0800236#endif
237
Damien George66ae8c92014-04-17 16:50:23 +0100238 // nlr_raise needs to be implemented as a goto, so that the C compiler's flow analyser
239 // sees that it's possible for us to jump from the dispatch loop to the exception
240 // handler. Without this, the code may have a different stack layout in the dispatch
241 // loop and the exception handler, leading to very obscure bugs.
242 #define RAISE(o) do { nlr_pop(); nlr.ret_val = o; goto exception_handler; } while(0)
Damien429d7192013-10-04 19:53:11 +0100243
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300244 // Pointers which are constant for particular invocation of mp_execute_bytecode2()
245 mp_obj_t *const fastn = &code_state->state[code_state->n_state - 1];
246 mp_exc_stack_t *const exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
247
Damien George66ae8c92014-04-17 16:50:23 +0100248 // variables that are visible to the exception handler (declared volatile)
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300249 volatile bool currently_in_except_block = MP_TAGPTR_TAG(code_state->exc_sp); // 0 or 1, to detect nested exceptions
250 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 +0100251
Damience89a212013-10-15 22:25:17 +0100252 // outer exception handling loop
Damien429d7192013-10-04 19:53:11 +0100253 for (;;) {
Damien George66ae8c92014-04-17 16:50:23 +0100254 nlr_buf_t nlr;
Damien George9e6e9352014-03-26 18:37:06 +0000255outer_dispatch_loop:
Damience89a212013-10-15 22:25:17 +0100256 if (nlr_push(&nlr) == 0) {
Damien George66ae8c92014-04-17 16:50:23 +0100257 // local variables that are not visible to the exception handler
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300258 const byte *ip = code_state->ip;
259 mp_obj_t *sp = code_state->sp;
Damien George66ae8c92014-04-17 16:50:23 +0100260 machine_uint_t unum;
Damien Georged8675542014-05-25 22:58:04 +0100261 mp_obj_t obj_shared;
Damien George66ae8c92014-04-17 16:50:23 +0100262
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200263 // If we have exception to inject, now that we finish setting up
264 // execution context, raise it. This works as if RAISE_VARARGS
265 // bytecode was executed.
Paul Sokolovskycf21a4e2014-03-26 17:36:12 +0200266 // Injecting exc into yield from generator is a special case,
267 // handled by MP_BC_YIELD_FROM itself
268 if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
Damien Georged8675542014-05-25 22:58:04 +0100269 mp_obj_t exc = inject_exc;
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200270 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100271 exc = mp_make_raise_obj(exc);
272 RAISE(exc);
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200273 }
Damien George66ae8c92014-04-17 16:50:23 +0100274
Damience89a212013-10-15 22:25:17 +0100275 // loop to execute byte code
276 for (;;) {
Paul Sokolovsky6472dea2014-02-01 00:55:05 +0200277dispatch_loop:
Damien George58ebde42014-05-21 20:32:59 +0100278#if MICROPY_OPT_COMPUTED_GOTO
AZ Huangb1f692e2014-04-14 23:22:44 +0800279 DISPATCH();
280#else
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +0300281 TRACE(ip);
Damien Georgec60a2612014-06-01 12:32:28 +0100282 code_state->ip = ip;
Damien Georgedb128912014-04-27 18:19:06 +0100283 switch (*ip++) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800284#endif
Damien429d7192013-10-04 19:53:11 +0100285
AZ Huangb1f692e2014-04-14 23:22:44 +0800286 ENTRY(MP_BC_LOAD_CONST_FALSE):
287 PUSH(mp_const_false);
288 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100289
AZ Huangb1f692e2014-04-14 23:22:44 +0800290 ENTRY(MP_BC_LOAD_CONST_NONE):
291 PUSH(mp_const_none);
292 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100293
AZ Huangb1f692e2014-04-14 23:22:44 +0800294 ENTRY(MP_BC_LOAD_CONST_TRUE):
295 PUSH(mp_const_true);
296 DISPATCH();
Damien Georgee9906ac2014-01-04 18:44:46 +0000297
AZ Huangb1f692e2014-04-14 23:22:44 +0800298 ENTRY(MP_BC_LOAD_CONST_ELLIPSIS):
299 PUSH((mp_obj_t)&mp_const_ellipsis_obj);
300 DISPATCH();
301
302 ENTRY(MP_BC_LOAD_CONST_SMALL_INT): {
303 machine_int_t num = 0;
304 if ((ip[0] & 0x40) != 0) {
305 // Number is negative
306 num--;
Paul Sokolovsky047cd402014-02-19 15:47:59 +0200307 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800308 do {
309 num = (num << 7) | (*ip & 0x7f);
310 } while ((*ip++ & 0x80) != 0);
311 PUSH(MP_OBJ_NEW_SMALL_INT(num));
312 DISPATCH();
313 }
Damience89a212013-10-15 22:25:17 +0100314
Damien Georged8675542014-05-25 22:58:04 +0100315 ENTRY(MP_BC_LOAD_CONST_INT): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800316 DECODE_QSTR;
Damien George503d6112014-05-28 14:07:21 +0100317 PUSH(mp_load_const_int(qst));
AZ Huangb1f692e2014-04-14 23:22:44 +0800318 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100319 }
Paul Sokolovskya9f5abd2014-01-17 19:51:46 +0200320
Damien Georged8675542014-05-25 22:58:04 +0100321 ENTRY(MP_BC_LOAD_CONST_DEC): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800322 DECODE_QSTR;
323 PUSH(mp_load_const_dec(qst));
324 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100325 }
Damien7410e442013-11-02 19:47:57 +0000326
Damien Georged8675542014-05-25 22:58:04 +0100327 ENTRY(MP_BC_LOAD_CONST_BYTES): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800328 DECODE_QSTR;
329 PUSH(mp_load_const_bytes(qst));
330 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100331 }
Paul Sokolovskybdf822b2014-01-02 18:46:27 +0200332
Damien Georged8675542014-05-25 22:58:04 +0100333 ENTRY(MP_BC_LOAD_CONST_STRING): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800334 DECODE_QSTR;
335 PUSH(mp_load_const_str(qst));
336 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100337 }
Damience89a212013-10-15 22:25:17 +0100338
AZ Huangb1f692e2014-04-14 23:22:44 +0800339 ENTRY(MP_BC_LOAD_NULL):
340 PUSH(MP_OBJ_NULL);
341 DISPATCH();
Damien George523b5752014-03-31 11:59:23 +0100342
AZ Huangb1f692e2014-04-14 23:22:44 +0800343 ENTRY(MP_BC_LOAD_FAST_0):
Damien Georged8675542014-05-25 22:58:04 +0100344 obj_shared = fastn[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800345 goto load_check;
Damience89a212013-10-15 22:25:17 +0100346
AZ Huangb1f692e2014-04-14 23:22:44 +0800347 ENTRY(MP_BC_LOAD_FAST_1):
Damien Georged8675542014-05-25 22:58:04 +0100348 obj_shared = fastn[-1];
AZ Huangb1f692e2014-04-14 23:22:44 +0800349 goto load_check;
Damience89a212013-10-15 22:25:17 +0100350
AZ Huangb1f692e2014-04-14 23:22:44 +0800351 ENTRY(MP_BC_LOAD_FAST_2):
Damien Georged8675542014-05-25 22:58:04 +0100352 obj_shared = fastn[-2];
AZ Huangb1f692e2014-04-14 23:22:44 +0800353 goto load_check;
Damience89a212013-10-15 22:25:17 +0100354
AZ Huangb1f692e2014-04-14 23:22:44 +0800355 ENTRY(MP_BC_LOAD_FAST_N):
356 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100357 obj_shared = fastn[-unum];
AZ Huangb1f692e2014-04-14 23:22:44 +0800358 load_check:
Damien Georged8675542014-05-25 22:58:04 +0100359 if (obj_shared == MP_OBJ_NULL) {
360 local_name_error: {
361 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment");
362 RAISE(obj);
363 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800364 }
Damien Georged8675542014-05-25 22:58:04 +0100365 PUSH(obj_shared);
AZ Huangb1f692e2014-04-14 23:22:44 +0800366 DISPATCH();
Damien George2bf7c092014-04-09 15:26:46 +0100367
AZ Huangb1f692e2014-04-14 23:22:44 +0800368 ENTRY(MP_BC_LOAD_DEREF):
369 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100370 obj_shared = mp_obj_cell_get(fastn[-unum]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800371 goto load_check;
Damien9ecbcff2013-12-11 00:41:43 +0000372
Damien Georged8675542014-05-25 22:58:04 +0100373 ENTRY(MP_BC_LOAD_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800374 DECODE_QSTR;
375 PUSH(mp_load_name(qst));
376 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100377 }
Damience89a212013-10-15 22:25:17 +0100378
Damien Georged8675542014-05-25 22:58:04 +0100379 ENTRY(MP_BC_LOAD_GLOBAL): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800380 DECODE_QSTR;
381 PUSH(mp_load_global(qst));
382 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100383 }
Damience89a212013-10-15 22:25:17 +0100384
Damien Georged8675542014-05-25 22:58:04 +0100385 ENTRY(MP_BC_LOAD_ATTR): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800386 DECODE_QSTR;
387 SET_TOP(mp_load_attr(TOP(), qst));
388 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100389 }
Damience89a212013-10-15 22:25:17 +0100390
Damien Georged8675542014-05-25 22:58:04 +0100391 ENTRY(MP_BC_LOAD_METHOD): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800392 DECODE_QSTR;
393 mp_load_method(*sp, qst, sp);
394 sp += 1;
395 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100396 }
Damience89a212013-10-15 22:25:17 +0100397
AZ Huangb1f692e2014-04-14 23:22:44 +0800398 ENTRY(MP_BC_LOAD_BUILD_CLASS):
399 PUSH(mp_load_build_class());
400 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100401
Damien Georged8675542014-05-25 22:58:04 +0100402 ENTRY(MP_BC_LOAD_SUBSCR): {
403 mp_obj_t index = POP();
404 SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL));
Damien George729f7b42014-04-17 22:10:53 +0100405 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100406 }
Damien George729f7b42014-04-17 22:10:53 +0100407
AZ Huangb1f692e2014-04-14 23:22:44 +0800408 ENTRY(MP_BC_STORE_FAST_0):
409 fastn[0] = POP();
410 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100411
AZ Huangb1f692e2014-04-14 23:22:44 +0800412 ENTRY(MP_BC_STORE_FAST_1):
413 fastn[-1] = POP();
414 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100415
AZ Huangb1f692e2014-04-14 23:22:44 +0800416 ENTRY(MP_BC_STORE_FAST_2):
417 fastn[-2] = POP();
418 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100419
AZ Huangb1f692e2014-04-14 23:22:44 +0800420 ENTRY(MP_BC_STORE_FAST_N):
421 DECODE_UINT;
422 fastn[-unum] = POP();
423 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100424
AZ Huangb1f692e2014-04-14 23:22:44 +0800425 ENTRY(MP_BC_STORE_DEREF):
426 DECODE_UINT;
427 mp_obj_cell_set(fastn[-unum], POP());
428 DISPATCH();
Damien9ecbcff2013-12-11 00:41:43 +0000429
Damien Georged8675542014-05-25 22:58:04 +0100430 ENTRY(MP_BC_STORE_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800431 DECODE_QSTR;
432 mp_store_name(qst, POP());
433 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100434 }
Damience89a212013-10-15 22:25:17 +0100435
Damien Georged8675542014-05-25 22:58:04 +0100436 ENTRY(MP_BC_STORE_GLOBAL): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800437 DECODE_QSTR;
438 mp_store_global(qst, POP());
439 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100440 }
Damien6addc892013-11-04 23:04:50 +0000441
Damien Georged8675542014-05-25 22:58:04 +0100442 ENTRY(MP_BC_STORE_ATTR): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800443 DECODE_QSTR;
444 mp_store_attr(sp[0], qst, sp[-1]);
445 sp -= 2;
446 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100447 }
Damience89a212013-10-15 22:25:17 +0100448
AZ Huangb1f692e2014-04-14 23:22:44 +0800449 ENTRY(MP_BC_STORE_SUBSCR):
Damien George729f7b42014-04-17 22:10:53 +0100450 mp_obj_subscr(sp[-1], sp[0], sp[-2]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800451 sp -= 3;
452 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100453
AZ Huangb1f692e2014-04-14 23:22:44 +0800454 ENTRY(MP_BC_DELETE_FAST):
455 DECODE_UINT;
456 if (fastn[-unum] == MP_OBJ_NULL) {
457 goto local_name_error;
458 }
459 fastn[-unum] = MP_OBJ_NULL;
460 DISPATCH();
Damien George2bf7c092014-04-09 15:26:46 +0100461
AZ Huangb1f692e2014-04-14 23:22:44 +0800462 ENTRY(MP_BC_DELETE_DEREF):
463 DECODE_UINT;
464 if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
465 goto local_name_error;
466 }
467 mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);
468 DISPATCH();
Damien George2bf7c092014-04-09 15:26:46 +0100469
Damien Georged8675542014-05-25 22:58:04 +0100470 ENTRY(MP_BC_DELETE_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800471 DECODE_QSTR;
472 mp_delete_name(qst);
473 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100474 }
Paul Sokolovskyf9090342014-03-23 21:19:02 +0200475
Damien Georged8675542014-05-25 22:58:04 +0100476 ENTRY(MP_BC_DELETE_GLOBAL): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800477 DECODE_QSTR;
478 mp_delete_global(qst);
479 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100480 }
Damien George1d24ea52014-04-08 21:11:49 +0100481
Damien Georged8675542014-05-25 22:58:04 +0100482 ENTRY(MP_BC_DUP_TOP): {
483 mp_obj_t top = TOP();
484 PUSH(top);
AZ Huangb1f692e2014-04-14 23:22:44 +0800485 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100486 }
Damience89a212013-10-15 22:25:17 +0100487
AZ Huangb1f692e2014-04-14 23:22:44 +0800488 ENTRY(MP_BC_DUP_TOP_TWO):
489 sp += 2;
490 sp[0] = sp[-2];
491 sp[-1] = sp[-3];
492 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100493
AZ Huangb1f692e2014-04-14 23:22:44 +0800494 ENTRY(MP_BC_POP_TOP):
495 sp -= 1;
496 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100497
Damien Georged8675542014-05-25 22:58:04 +0100498 ENTRY(MP_BC_ROT_TWO): {
499 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800500 sp[0] = sp[-1];
Damien Georged8675542014-05-25 22:58:04 +0100501 sp[-1] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800502 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100503 }
Damien4ebb32f2013-11-02 14:33:10 +0000504
Damien Georged8675542014-05-25 22:58:04 +0100505 ENTRY(MP_BC_ROT_THREE): {
506 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800507 sp[0] = sp[-1];
508 sp[-1] = sp[-2];
Damien Georged8675542014-05-25 22:58:04 +0100509 sp[-2] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800510 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100511 }
Damience89a212013-10-15 22:25:17 +0100512
AZ Huangb1f692e2014-04-14 23:22:44 +0800513 ENTRY(MP_BC_JUMP):
514 DECODE_SLABEL;
515 ip += unum;
516 DISPATCH();
517
518 ENTRY(MP_BC_POP_JUMP_IF_TRUE):
519 DECODE_SLABEL;
520 if (mp_obj_is_true(POP())) {
Damien03c9cfb2013-11-05 22:06:08 +0000521 ip += unum;
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200522 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800523 DISPATCH();
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200524
AZ Huangb1f692e2014-04-14 23:22:44 +0800525 ENTRY(MP_BC_POP_JUMP_IF_FALSE):
526 DECODE_SLABEL;
527 if (!mp_obj_is_true(POP())) {
528 ip += unum;
529 }
530 DISPATCH();
Damien George600ae732014-01-21 23:48:04 +0000531
AZ Huangb1f692e2014-04-14 23:22:44 +0800532 ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP):
533 DECODE_SLABEL;
534 if (mp_obj_is_true(TOP())) {
535 ip += unum;
536 } else {
537 sp--;
538 }
539 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100540
AZ Huangb1f692e2014-04-14 23:22:44 +0800541 ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP):
542 DECODE_SLABEL;
543 if (mp_obj_is_true(TOP())) {
544 sp--;
545 } else {
546 ip += unum;
547 }
548 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100549
Damien Georged8675542014-05-25 22:58:04 +0100550 ENTRY(MP_BC_SETUP_WITH): {
551 mp_obj_t obj = TOP();
552 SET_TOP(mp_load_attr(obj, MP_QSTR___exit__));
553 mp_load_method(obj, MP_QSTR___enter__, sp + 1);
554 mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 1);
AZ Huangb1f692e2014-04-14 23:22:44 +0800555 PUSH_EXC_BLOCK();
Damien Georged8675542014-05-25 22:58:04 +0100556 PUSH(ret);
AZ Huangb1f692e2014-04-14 23:22:44 +0800557 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100558 }
Damience89a212013-10-15 22:25:17 +0100559
AZ Huangb1f692e2014-04-14 23:22:44 +0800560 ENTRY(MP_BC_WITH_CLEANUP): {
561 // Arriving here, there's "exception control block" on top of stack,
562 // and __exit__ bound method underneath it. Bytecode calls __exit__,
563 // and "deletes" it off stack, shifting "exception control block"
564 // to its place.
565 static const mp_obj_t no_exc[] = {mp_const_none, mp_const_none, mp_const_none};
566 if (TOP() == mp_const_none) {
567 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100568 mp_obj_t obj = TOP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800569 SET_TOP(mp_const_none);
Damien Georged8675542014-05-25 22:58:04 +0100570 mp_call_function_n_kw(obj, 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800571 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
572 mp_obj_t cause = POP();
573 switch (MP_OBJ_SMALL_INT_VALUE(cause)) {
574 case UNWIND_RETURN: {
575 mp_obj_t retval = POP();
Damien Georged8675542014-05-25 22:58:04 +0100576 mp_call_function_n_kw(TOP(), 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800577 SET_TOP(retval);
578 PUSH(cause);
579 break;
580 }
581 case UNWIND_JUMP: {
Damien Georged8675542014-05-25 22:58:04 +0100582 mp_call_function_n_kw(sp[-2], 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800583 // Pop __exit__ boundmethod at sp[-2]
584 sp[-2] = sp[-1];
585 sp[-1] = sp[0];
586 SET_TOP(cause);
587 break;
588 }
589 default:
590 assert(0);
591 }
592 } else if (mp_obj_is_exception_type(TOP())) {
593 mp_obj_t args[3] = {sp[0], sp[-1], sp[-2]};
Damien Georged8675542014-05-25 22:58:04 +0100594 mp_obj_t ret_value = mp_call_function_n_kw(sp[-3], 3, 0, args);
AZ Huangb1f692e2014-04-14 23:22:44 +0800595 // Pop __exit__ boundmethod at sp[-3]
Damien Georged8675542014-05-25 22:58:04 +0100596 // TODO: Once semantics is proven, optimize for case when ret_value == True
AZ Huangb1f692e2014-04-14 23:22:44 +0800597 sp[-3] = sp[-2];
598 sp[-2] = sp[-1];
599 sp[-1] = sp[0];
Damien George20006db2014-01-18 14:10:48 +0000600 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100601 if (mp_obj_is_true(ret_value)) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800602 // This is what CPython does
603 //PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_SILENCED));
604 // But what we need to do is - pop exception from value stack...
605 sp -= 3;
606 // ... pop "with" exception handler, and signal END_FINALLY
607 // to just execute finally handler normally (by pushing None
608 // on value stack)
609 assert(exc_sp >= exc_stack);
610 assert(exc_sp->opcode == MP_BC_SETUP_WITH);
611 POP_EXC_BLOCK();
612 PUSH(mp_const_none);
613 }
614 } else {
615 assert(0);
616 }
617 DISPATCH();
618 }
Damienc226dca2013-10-16 16:12:52 +0100619
AZ Huangb1f692e2014-04-14 23:22:44 +0800620 ENTRY(MP_BC_UNWIND_JUMP):
621 DECODE_SLABEL;
622 PUSH((void*)(ip + unum)); // push destination ip for jump
Damien George25c84642014-05-30 15:20:41 +0100623 PUSH((void*)(machine_uint_t)(*ip)); // push number of exception handlers to unwind (0x80 bit set if we also need to pop stack)
AZ Huangb1f692e2014-04-14 23:22:44 +0800624unwind_jump:
625 unum = (machine_uint_t)POP(); // get number of exception handlers to unwind
Damien George25c84642014-05-30 15:20:41 +0100626 while ((unum & 0x7f) > 0) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800627 unum -= 1;
628 assert(exc_sp >= exc_stack);
629 if (exc_sp->opcode == MP_BC_SETUP_FINALLY || exc_sp->opcode == MP_BC_SETUP_WITH) {
630 // We're going to run "finally" code as a coroutine
631 // (not calling it recursively). Set up a sentinel
632 // on a stack so it can return back to us when it is
633 // done (when END_FINALLY reached).
634 PUSH((void*)unum); // push number of exception handlers left to unwind
635 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
636 ip = exc_sp->handler; // get exception handler byte code address
637 exc_sp--; // pop exception handler
638 goto dispatch_loop; // run the exception handler
639 }
640 exc_sp--;
641 }
642 ip = (const byte*)POP(); // pop destination ip for jump
Damien George25c84642014-05-30 15:20:41 +0100643 if (unum != 0) {
644 sp--;
645 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800646 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100647
AZ Huangb1f692e2014-04-14 23:22:44 +0800648 // matched against: POP_BLOCK or POP_EXCEPT (anything else?)
649 ENTRY(MP_BC_SETUP_EXCEPT):
650 ENTRY(MP_BC_SETUP_FINALLY):
651 PUSH_EXC_BLOCK();
652 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100653
AZ Huangb1f692e2014-04-14 23:22:44 +0800654 ENTRY(MP_BC_END_FINALLY):
655 // not fully implemented
656 // if TOS is an exception, reraises the exception (3 values on TOS)
657 // if TOS is None, just pops it and continues
658 // if TOS is an integer, does something else
659 // else error
660 if (mp_obj_is_exception_type(TOP())) {
Damien George66ae8c92014-04-17 16:50:23 +0100661 RAISE(sp[-1]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800662 }
663 if (TOP() == mp_const_none) {
Damien George20006db2014-01-18 14:10:48 +0000664 sp--;
AZ Huangb1f692e2014-04-14 23:22:44 +0800665 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
666 // We finished "finally" coroutine and now dispatch back
667 // to our caller, based on TOS value
668 mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());
669 switch (reason) {
670 case UNWIND_RETURN:
671 goto unwind_return;
672 case UNWIND_JUMP:
673 goto unwind_jump;
674 }
675 assert(0);
676 } else {
677 assert(0);
678 }
679 DISPATCH();
680
681 ENTRY(MP_BC_GET_ITER):
682 SET_TOP(mp_getiter(TOP()));
683 DISPATCH();
684
Damien Georged8675542014-05-25 22:58:04 +0100685 ENTRY(MP_BC_FOR_ITER): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800686 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgec60a2612014-06-01 12:32:28 +0100687 code_state->sp = sp;
Paul Sokolovskyc48d6f72014-05-11 20:32:39 +0300688 assert(TOP());
Damien Georged8675542014-05-25 22:58:04 +0100689 mp_obj_t value = mp_iternext_allow_raise(TOP());
690 if (value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800691 --sp; // pop the exhausted iterator
692 ip += unum; // jump to after for-block
693 } else {
Damien Georged8675542014-05-25 22:58:04 +0100694 PUSH(value); // push the next iteration value
AZ Huangb1f692e2014-04-14 23:22:44 +0800695 }
696 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100697 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800698
699 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
700 ENTRY(MP_BC_POP_BLOCK):
701 // we are exiting an exception handler, so pop the last one of the exception-stack
702 assert(exc_sp >= exc_stack);
703 POP_EXC_BLOCK();
704 DISPATCH();
705
706 // matched against: SETUP_EXCEPT
707 ENTRY(MP_BC_POP_EXCEPT):
708 // TODO need to work out how blocks work etc
709 // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
710 assert(exc_sp >= exc_stack);
711 assert(currently_in_except_block);
712 //sp = (mp_obj_t*)(*exc_sp--);
713 //exc_sp--; // discard ip
714 POP_EXC_BLOCK();
715 //sp -= 3; // pop 3 exception values
716 DISPATCH();
717
718 ENTRY(MP_BC_NOT):
719 if (TOP() == mp_const_true) {
720 SET_TOP(mp_const_false);
721 } else {
722 SET_TOP(mp_const_true);
723 }
724 DISPATCH();
725
726 ENTRY(MP_BC_UNARY_OP):
727 unum = *ip++;
728 SET_TOP(mp_unary_op(unum, TOP()));
729 DISPATCH();
730
Damien Georged8675542014-05-25 22:58:04 +0100731 ENTRY(MP_BC_BINARY_OP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800732 unum = *ip++;
Damien Georged8675542014-05-25 22:58:04 +0100733 mp_obj_t rhs = POP();
734 mp_obj_t lhs = TOP();
735 SET_TOP(mp_binary_op(unum, lhs, rhs));
AZ Huangb1f692e2014-04-14 23:22:44 +0800736 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100737 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800738
739 ENTRY(MP_BC_BUILD_TUPLE):
740 DECODE_UINT;
741 sp -= unum - 1;
742 SET_TOP(mp_obj_new_tuple(unum, sp));
743 DISPATCH();
744
745 ENTRY(MP_BC_BUILD_LIST):
746 DECODE_UINT;
747 sp -= unum - 1;
748 SET_TOP(mp_obj_new_list(unum, sp));
749 DISPATCH();
750
751 ENTRY(MP_BC_LIST_APPEND):
752 DECODE_UINT;
753 // I think it's guaranteed by the compiler that sp[unum] is a list
754 mp_obj_list_append(sp[-unum], sp[0]);
755 sp--;
756 DISPATCH();
757
758 ENTRY(MP_BC_BUILD_MAP):
759 DECODE_UINT;
760 PUSH(mp_obj_new_dict(unum));
761 DISPATCH();
762
763 ENTRY(MP_BC_STORE_MAP):
764 sp -= 2;
765 mp_obj_dict_store(sp[0], sp[2], sp[1]);
766 DISPATCH();
767
768 ENTRY(MP_BC_MAP_ADD):
769 DECODE_UINT;
770 // I think it's guaranteed by the compiler that sp[-unum - 1] is a map
771 mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]);
772 sp -= 2;
773 DISPATCH();
774
Damien George3ebd4d02014-06-01 13:46:47 +0100775#if MICROPY_PY_BUILTINS_SET
AZ Huangb1f692e2014-04-14 23:22:44 +0800776 ENTRY(MP_BC_BUILD_SET):
777 DECODE_UINT;
778 sp -= unum - 1;
779 SET_TOP(mp_obj_new_set(unum, sp));
780 DISPATCH();
781
782 ENTRY(MP_BC_SET_ADD):
783 DECODE_UINT;
784 // I think it's guaranteed by the compiler that sp[-unum] is a set
785 mp_obj_set_store(sp[-unum], sp[0]);
786 sp--;
787 DISPATCH();
Damien George3ebd4d02014-06-01 13:46:47 +0100788#endif
Damienc12aa462013-10-16 20:57:49 +0100789
Damien Georgefb510b32014-06-01 13:32:54 +0100790#if MICROPY_PY_BUILTINS_SLICE
AZ Huangb1f692e2014-04-14 23:22:44 +0800791 ENTRY(MP_BC_BUILD_SLICE):
792 DECODE_UINT;
793 if (unum == 2) {
Damien Georged8675542014-05-25 22:58:04 +0100794 mp_obj_t stop = POP();
795 mp_obj_t start = TOP();
796 SET_TOP(mp_obj_new_slice(start, stop, mp_const_none));
AZ Huangb1f692e2014-04-14 23:22:44 +0800797 } else {
Damien Georged8675542014-05-25 22:58:04 +0100798 mp_obj_t step = POP();
799 mp_obj_t stop = POP();
800 mp_obj_t start = TOP();
801 SET_TOP(mp_obj_new_slice(start, stop, step));
AZ Huangb1f692e2014-04-14 23:22:44 +0800802 }
803 DISPATCH();
804#endif
805
806 ENTRY(MP_BC_UNPACK_SEQUENCE):
807 DECODE_UINT;
808 mp_unpack_sequence(sp[0], unum, sp);
809 sp += unum - 1;
810 DISPATCH();
811
812 ENTRY(MP_BC_UNPACK_EX):
813 DECODE_UINT;
814 mp_unpack_ex(sp[0], unum, sp);
815 sp += (unum & 0xff) + ((unum >> 8) & 0xff);
816 DISPATCH();
817
818 ENTRY(MP_BC_MAKE_FUNCTION):
819 DECODE_PTR;
820 PUSH(mp_make_function_from_raw_code((mp_raw_code_t*)unum, MP_OBJ_NULL, MP_OBJ_NULL));
821 DISPATCH();
822
Damien Georged8675542014-05-25 22:58:04 +0100823 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800824 DECODE_PTR;
825 // Stack layout: def_tuple def_dict <- TOS
Damien Georged8675542014-05-25 22:58:04 +0100826 mp_obj_t def_dict = POP();
827 SET_TOP(mp_make_function_from_raw_code((mp_raw_code_t*)unum, TOP(), def_dict));
AZ Huangb1f692e2014-04-14 23:22:44 +0800828 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100829 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800830
Damien George3558f622014-04-20 17:50:40 +0100831 ENTRY(MP_BC_MAKE_CLOSURE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800832 DECODE_PTR;
Damien George3558f622014-04-20 17:50:40 +0100833 machine_uint_t n_closed_over = *ip++;
834 // Stack layout: closed_overs <- TOS
835 sp -= n_closed_over - 1;
836 SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800837 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100838 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800839
Damien George3558f622014-04-20 17:50:40 +0100840 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800841 DECODE_PTR;
Damien George3558f622014-04-20 17:50:40 +0100842 machine_uint_t n_closed_over = *ip++;
843 // Stack layout: def_tuple def_dict closed_overs <- TOS
844 sp -= 2 + n_closed_over - 1;
845 SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, 0x100 | n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800846 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100847 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800848
849 ENTRY(MP_BC_CALL_FUNCTION):
850 DECODE_UINT;
851 // unum & 0xff == n_positional
852 // (unum >> 8) & 0xff == n_keyword
853 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
854 SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
855 DISPATCH();
856
857 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW):
858 DECODE_UINT;
859 // unum & 0xff == n_positional
860 // (unum >> 8) & 0xff == n_keyword
861 // We have folowing stack layout here:
862 // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
863 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
864 SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
865 DISPATCH();
866
867 ENTRY(MP_BC_CALL_METHOD):
868 DECODE_UINT;
869 // unum & 0xff == n_positional
870 // (unum >> 8) & 0xff == n_keyword
871 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
872 SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
873 DISPATCH();
874
875 ENTRY(MP_BC_CALL_METHOD_VAR_KW):
876 DECODE_UINT;
877 // unum & 0xff == n_positional
878 // (unum >> 8) & 0xff == n_keyword
879 // We have folowing stack layout here:
880 // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
881 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
882 SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
883 DISPATCH();
884
885 ENTRY(MP_BC_RETURN_VALUE):
886unwind_return:
887 while (exc_sp >= exc_stack) {
888 if (exc_sp->opcode == MP_BC_SETUP_FINALLY || exc_sp->opcode == MP_BC_SETUP_WITH) {
889 // We're going to run "finally" code as a coroutine
890 // (not calling it recursively). Set up a sentinel
891 // on a stack so it can return back to us when it is
892 // done (when END_FINALLY reached).
893 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
894 ip = exc_sp->handler;
895 // We don't need to do anything with sp, finally is just
896 // syntactic sugar for sequential execution??
897 // sp =
898 exc_sp--;
899 goto dispatch_loop;
900 }
901 exc_sp--;
902 }
903 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300904 code_state->sp = sp;
AZ Huangb1f692e2014-04-14 23:22:44 +0800905 assert(exc_sp == exc_stack - 1);
906 return MP_VM_RETURN_NORMAL;
907
Damien Georged8675542014-05-25 22:58:04 +0100908 ENTRY(MP_BC_RAISE_VARARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800909 unum = *ip++;
Damien Georged8675542014-05-25 22:58:04 +0100910 mp_obj_t obj;
AZ Huangb1f692e2014-04-14 23:22:44 +0800911 assert(unum <= 1);
912 if (unum == 0) {
913 // search for the inner-most previous exception, to reraise it
Damien Georged8675542014-05-25 22:58:04 +0100914 obj = MP_OBJ_NULL;
AZ Huangb1f692e2014-04-14 23:22:44 +0800915 for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
916 if (e->prev_exc != MP_OBJ_NULL) {
Damien Georged8675542014-05-25 22:58:04 +0100917 obj = e->prev_exc;
AZ Huangb1f692e2014-04-14 23:22:44 +0800918 break;
919 }
920 }
Damien Georged8675542014-05-25 22:58:04 +0100921 if (obj == MP_OBJ_NULL) {
922 obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
923 RAISE(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +0800924 }
925 } else {
Damien Georged8675542014-05-25 22:58:04 +0100926 obj = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800927 }
Damien Georged8675542014-05-25 22:58:04 +0100928 obj = mp_make_raise_obj(obj);
929 RAISE(obj);
930 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800931
932 ENTRY(MP_BC_YIELD_VALUE):
933yield:
934 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300935 code_state->ip = ip;
936 code_state->sp = sp;
937 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +0800938 return MP_VM_RETURN_YIELD;
939
940 ENTRY(MP_BC_YIELD_FROM): {
941//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
942#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
Damien George66ae8c92014-04-17 16:50:23 +0100943#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { RAISE(t); }
AZ Huangb1f692e2014-04-14 23:22:44 +0800944 mp_vm_return_kind_t ret_kind;
Damien Georged8675542014-05-25 22:58:04 +0100945 mp_obj_t send_value = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800946 mp_obj_t t_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100947 mp_obj_t ret_value;
AZ Huangb1f692e2014-04-14 23:22:44 +0800948 if (inject_exc != MP_OBJ_NULL) {
949 t_exc = inject_exc;
950 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100951 ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800952 } else {
Damien Georged8675542014-05-25 22:58:04 +0100953 ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800954 }
955
956 if (ret_kind == MP_VM_RETURN_YIELD) {
957 ip--;
Damien Georged8675542014-05-25 22:58:04 +0100958 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800959 goto yield;
960 }
961 if (ret_kind == MP_VM_RETURN_NORMAL) {
962 // Pop exhausted gen
963 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100964 if (ret_value == MP_OBJ_NULL) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800965 // Optimize StopIteration
966 // TODO: get StopIteration's value
967 PUSH(mp_const_none);
968 } else {
Damien Georged8675542014-05-25 22:58:04 +0100969 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800970 }
971
972 // If we injected GeneratorExit downstream, then even
973 // if it was swallowed, we re-raise GeneratorExit
974 GENERATOR_EXIT_IF_NEEDED(t_exc);
975 DISPATCH();
976 }
977 if (ret_kind == MP_VM_RETURN_EXCEPTION) {
978 // Pop exhausted gen
979 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100980 if (EXC_MATCH(ret_value, &mp_type_StopIteration)) {
981 PUSH(mp_obj_exception_get_value(ret_value));
AZ Huangb1f692e2014-04-14 23:22:44 +0800982 // If we injected GeneratorExit downstream, then even
983 // if it was swallowed, we re-raise GeneratorExit
984 GENERATOR_EXIT_IF_NEEDED(t_exc);
985 DISPATCH();
986 } else {
Damien Georged8675542014-05-25 22:58:04 +0100987 RAISE(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800988 }
989 }
Damien429d7192013-10-04 19:53:11 +0100990 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800991
Damien Georged8675542014-05-25 22:58:04 +0100992 ENTRY(MP_BC_IMPORT_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800993 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +0100994 mp_obj_t obj = POP();
995 SET_TOP(mp_import_name(qst, obj, TOP()));
AZ Huangb1f692e2014-04-14 23:22:44 +0800996 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100997 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800998
Damien Georged8675542014-05-25 22:58:04 +0100999 ENTRY(MP_BC_IMPORT_FROM): {
AZ Huangb1f692e2014-04-14 23:22:44 +08001000 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +01001001 mp_obj_t obj = mp_import_from(TOP(), qst);
1002 PUSH(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +08001003 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +01001004 }
AZ Huangb1f692e2014-04-14 23:22:44 +08001005
1006 ENTRY(MP_BC_IMPORT_STAR):
1007 mp_import_all(POP());
1008 DISPATCH();
1009
Damien Georged8675542014-05-25 22:58:04 +01001010 ENTRY_DEFAULT: {
1011 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
AZ Huangb1f692e2014-04-14 23:22:44 +08001012 nlr_pop();
Damien Georged8675542014-05-25 22:58:04 +01001013 fastn[0] = obj;
AZ Huangb1f692e2014-04-14 23:22:44 +08001014 return MP_VM_RETURN_EXCEPTION;
Damien Georged8675542014-05-25 22:58:04 +01001015 }
Damien George66ae8c92014-04-17 16:50:23 +01001016
Damien George58ebde42014-05-21 20:32:59 +01001017#if !MICROPY_OPT_COMPUTED_GOTO
AZ Huang9309d992014-04-15 15:57:01 +08001018 } // switch
AZ Huangb1f692e2014-04-14 23:22:44 +08001019#endif
Damien George66ae8c92014-04-17 16:50:23 +01001020 } // for loop
Damien429d7192013-10-04 19:53:11 +01001021
Damience89a212013-10-15 22:25:17 +01001022 } else {
Damien George66ae8c92014-04-17 16:50:23 +01001023exception_handler:
Damience89a212013-10-15 22:25:17 +01001024 // exception occurred
Damien429d7192013-10-04 19:53:11 +01001025
Damien George9e6e9352014-03-26 18:37:06 +00001026 // check if it's a StopIteration within a for block
Damien Georgec60a2612014-06-01 12:32:28 +01001027 if (*code_state->ip == MP_BC_FOR_ITER && mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) {
1028 const byte *ip = code_state->ip + 1;
Damien George66ae8c92014-04-17 16:50:23 +01001029 machine_uint_t unum;
Damien George9e6e9352014-03-26 18:37:06 +00001030 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001031 code_state->ip = ip + unum; // jump to after for-block
Damien Georgec60a2612014-06-01 12:32:28 +01001032 code_state->sp -= 1; // pop the exhausted iterator
Damien George9e6e9352014-03-26 18:37:06 +00001033 goto outer_dispatch_loop; // continue with dispatch loop
1034 }
1035
Damien George08335002014-01-18 23:24:36 +00001036 // set file and line number that the exception occurred at
Paul Sokolovsky382e8ee2014-01-30 13:49:18 +02001037 // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
1038 // But consider how to handle nested exceptions.
Damien George6902eed2014-04-04 10:52:59 +00001039 // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
1040 if (mp_obj_is_exception_instance(nlr.ret_val) && nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001041 const byte *code_info = code_state->code_info;
Damien George08335002014-01-18 23:24:36 +00001042 machine_uint_t code_info_size = code_info[0] | (code_info[1] << 8) | (code_info[2] << 16) | (code_info[3] << 24);
Damien Georgecbd2f742014-01-19 11:48:48 +00001043 qstr source_file = code_info[4] | (code_info[5] << 8) | (code_info[6] << 16) | (code_info[7] << 24);
1044 qstr block_name = code_info[8] | (code_info[9] << 8) | (code_info[10] << 16) | (code_info[11] << 24);
Damien George08335002014-01-18 23:24:36 +00001045 machine_uint_t source_line = 1;
Damien Georgec60a2612014-06-01 12:32:28 +01001046 machine_uint_t bc = code_state->ip - code_info - code_info_size;
Damien Georgecbd2f742014-01-19 11:48:48 +00001047 //printf("find %lu %d %d\n", bc, code_info[12], code_info[13]);
Damien George28eb5772014-01-25 11:43:20 +00001048 for (const byte* ci = code_info + 12; *ci && bc >= ((*ci) & 31); ci++) {
1049 bc -= *ci & 31;
1050 source_line += *ci >> 5;
Damien George08335002014-01-18 23:24:36 +00001051 }
Damien George136b1492014-01-19 12:38:49 +00001052 mp_obj_exception_add_traceback(nlr.ret_val, source_file, source_line, block_name);
Damien George08335002014-01-18 23:24:36 +00001053 }
1054
Damien8f9e2ee2013-12-29 16:54:59 +00001055 while (currently_in_except_block) {
1056 // nested exception
1057
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001058 assert(exc_sp >= exc_stack);
Damien8f9e2ee2013-12-29 16:54:59 +00001059
1060 // TODO make a proper message for nested exception
1061 // at the moment we are just raising the very last exception (the one that caused the nested exception)
1062
1063 // move up to previous exception handler
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +02001064 POP_EXC_BLOCK();
Damien8f9e2ee2013-12-29 16:54:59 +00001065 }
1066
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001067 if (exc_sp >= exc_stack) {
Damien8f9e2ee2013-12-29 16:54:59 +00001068 // set flag to indicate that we are now handling an exception
1069 currently_in_except_block = 1;
1070
Damience89a212013-10-15 22:25:17 +01001071 // catch exception and pass to byte code
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001072 code_state->ip = exc_sp->handler;
Damien George66ae8c92014-04-17 16:50:23 +01001073 mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
Damien Georged7592a12014-03-30 00:54:48 +00001074 // save this exception in the stack so it can be used in a reraise, if needed
1075 exc_sp->prev_exc = nlr.ret_val;
Damienc9f91972013-10-15 23:46:01 +01001076 // push(traceback, exc-val, exc-type)
Damiend99b0522013-12-21 18:17:45 +00001077 PUSH(mp_const_none);
Damienc9f91972013-10-15 23:46:01 +01001078 PUSH(nlr.ret_val);
Paul Sokolovsky682f9e62014-03-29 02:52:17 +02001079 PUSH(mp_obj_get_type(nlr.ret_val));
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001080 code_state->sp = sp;
Damien8f9e2ee2013-12-29 16:54:59 +00001081
Damience89a212013-10-15 22:25:17 +01001082 } else {
Damien Georgec8f78bc2014-02-15 22:55:00 +00001083 // propagate exception to higher level
1084 // TODO what to do about ip and sp? they don't really make sense at this point
1085 fastn[0] = nlr.ret_val; // must put exception here because sp is invalid
1086 return MP_VM_RETURN_EXCEPTION;
Damience89a212013-10-15 22:25:17 +01001087 }
Damien429d7192013-10-04 19:53:11 +01001088 }
1089 }
1090}