1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2013-2019 Damien P. George
7  * Copyright (c) 2014-2015 Paul Sokolovsky
8  *
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 
28 #include <stdio.h>
29 #include <string.h>
30 #include <assert.h>
31 
32 #include "py/emitglue.h"
33 #include "py/objtype.h"
34 #include "py/runtime.h"
35 #include "py/bc0.h"
36 #include "py/bc.h"
37 #include "py/profile.h"
38 
39 // *FORMAT-OFF*
40 
41 #if 0
42 #if MICROPY_PY_THREAD
43 #define TRACE_PREFIX mp_printf(&mp_plat_print, "ts=%p sp=%d ", mp_thread_get_state(), (int)(sp - &code_state->state[0] + 1))
44 #else
45 #define TRACE_PREFIX mp_printf(&mp_plat_print, "sp=%d ", (int)(sp - &code_state->state[0] + 1))
46 #endif
47 #define TRACE(ip) TRACE_PREFIX; mp_bytecode_print2(&mp_plat_print, ip, 1, code_state->fun_bc->const_table);
48 #else
49 #define TRACE(ip)
50 #endif
51 
52 // Value stack grows up (this makes it incompatible with native C stack, but
53 // makes sure that arguments to functions are in natural order arg1..argN
54 // (Python semantics mandates left-to-right evaluation order, including for
55 // function arguments). Stack pointer is pre-incremented and points at the
56 // top element.
57 // Exception stack also grows up, top element is also pointed at.
58 
59 #define DECODE_UINT \
60     mp_uint_t unum = 0; \
61     do { \
62         unum = (unum << 7) + (*ip & 0x7f); \
63     } while ((*ip++ & 0x80) != 0)
64 #define DECODE_ULABEL size_t ulab = (ip[0] | (ip[1] << 8)); ip += 2
65 #define DECODE_SLABEL size_t slab = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2
66 
67 #if MICROPY_PERSISTENT_CODE
68 
69 #define DECODE_QSTR \
70     qstr qst = ip[0] | ip[1] << 8; \
71     ip += 2;
72 #define DECODE_PTR \
73     DECODE_UINT; \
74     void *ptr = (void*)(uintptr_t)code_state->fun_bc->const_table[unum]
75 #define DECODE_OBJ \
76     DECODE_UINT; \
77     mp_obj_t obj = (mp_obj_t)code_state->fun_bc->const_table[unum]
78 
79 #else
80 
81 #define DECODE_QSTR qstr qst = 0; \
82     do { \
83         qst = (qst << 7) + (*ip & 0x7f); \
84     } while ((*ip++ & 0x80) != 0)
85 #define DECODE_PTR \
86     ip = (byte*)MP_ALIGN(ip, sizeof(void*)); \
87     void *ptr = *(void**)ip; \
88     ip += sizeof(void*)
89 #define DECODE_OBJ \
90     ip = (byte*)MP_ALIGN(ip, sizeof(mp_obj_t)); \
91     mp_obj_t obj = *(mp_obj_t*)ip; \
92     ip += sizeof(mp_obj_t)
93 
94 #endif
95 
96 #define PUSH(val) *++sp = (val)
97 #define POP() (*sp--)
98 #define TOP() (*sp)
99 #define SET_TOP(val) *sp = (val)
100 
101 #if MICROPY_PY_SYS_EXC_INFO
102 #define CLEAR_SYS_EXC_INFO() MP_STATE_VM(cur_exception) = NULL;
103 #else
104 #define CLEAR_SYS_EXC_INFO()
105 #endif
106 
107 #define PUSH_EXC_BLOCK(with_or_finally) do { \
108     DECODE_ULABEL; /* except labels are always forward */ \
109     ++exc_sp; \
110     exc_sp->handler = ip + ulab; \
111     exc_sp->val_sp = MP_TAGPTR_MAKE(sp, ((with_or_finally) << 1)); \
112     exc_sp->prev_exc = NULL; \
113 } while (0)
114 
115 #define POP_EXC_BLOCK() \
116     exc_sp--; /* pop back to previous exception handler */ \
117     CLEAR_SYS_EXC_INFO() /* just clear sys.exc_info(), not compliant, but it shouldn't be used in 1st place */
118 
119 #define CANCEL_ACTIVE_FINALLY(sp) do { \
120     if (mp_obj_is_small_int(sp[-1])) { \
121         /* Stack: (..., prev_dest_ip, prev_cause, dest_ip) */ \
122         /* Cancel the unwind through the previous finally, replace with current one */ \
123         sp[-2] = sp[0]; \
124         sp -= 2; \
125     } else { \
126         assert(sp[-1] == mp_const_none || mp_obj_is_exception_instance(sp[-1])); \
127         /* Stack: (..., None/exception, dest_ip) */ \
128         /* Silence the finally's exception value (may be None or an exception) */ \
129         sp[-1] = sp[0]; \
130         --sp; \
131     } \
132 } while (0)
133 
134 #if MICROPY_PY_SYS_SETTRACE
135 
136 #define FRAME_SETUP() do { \
137     assert(code_state != code_state->prev_state); \
138     MP_STATE_THREAD(current_code_state) = code_state; \
139     assert(code_state != code_state->prev_state); \
140 } while(0)
141 
142 #define FRAME_ENTER() do { \
143     assert(code_state != code_state->prev_state); \
144     code_state->prev_state = MP_STATE_THREAD(current_code_state); \
145     assert(code_state != code_state->prev_state); \
146     if (!mp_prof_is_executing) { \
147         mp_prof_frame_enter(code_state); \
148     } \
149 } while(0)
150 
151 #define FRAME_LEAVE() do { \
152     assert(code_state != code_state->prev_state); \
153     MP_STATE_THREAD(current_code_state) = code_state->prev_state; \
154     assert(code_state != code_state->prev_state); \
155 } while(0)
156 
157 #define FRAME_UPDATE() do { \
158     assert(MP_STATE_THREAD(current_code_state) == code_state); \
159     if (!mp_prof_is_executing) { \
160         code_state->frame = MP_OBJ_TO_PTR(mp_prof_frame_update(code_state)); \
161     } \
162 } while(0)
163 
164 #define TRACE_TICK(current_ip, current_sp, is_exception) do { \
165     assert(code_state != code_state->prev_state); \
166     assert(MP_STATE_THREAD(current_code_state) == code_state); \
167     if (!mp_prof_is_executing && code_state->frame && MP_STATE_THREAD(prof_trace_callback)) { \
168         MP_PROF_INSTR_DEBUG_PRINT(code_state->ip); \
169     } \
170     if (!mp_prof_is_executing && code_state->frame && code_state->frame->callback) { \
171         mp_prof_instr_tick(code_state, is_exception); \
172     } \
173 } while(0)
174 
175 #else // MICROPY_PY_SYS_SETTRACE
176 #define FRAME_SETUP()
177 #define FRAME_ENTER()
178 #define FRAME_LEAVE()
179 #define FRAME_UPDATE()
180 #define TRACE_TICK(current_ip, current_sp, is_exception)
181 #endif // MICROPY_PY_SYS_SETTRACE
182 
183 #if MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
mp_map_cached_lookup(mp_map_t * map,qstr qst,uint8_t * idx_cache)184 static inline mp_map_elem_t *mp_map_cached_lookup(mp_map_t *map, qstr qst, uint8_t *idx_cache) {
185     size_t idx = *idx_cache;
186     mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
187     mp_map_elem_t *elem = NULL;
188     if (idx < map->alloc && map->table[idx].key == key) {
189         elem = &map->table[idx];
190     } else {
191         elem = mp_map_lookup(map, key, MP_MAP_LOOKUP);
192         if (elem != NULL) {
193             *idx_cache = (elem - &map->table[0]) & 0xff;
194         }
195     }
196     return elem;
197 }
198 #endif
199 
200 // fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)
201 // sp points to bottom of stack which grows up
202 // returns:
203 //  MP_VM_RETURN_NORMAL, sp valid, return value in *sp
204 //  MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
205 //  MP_VM_RETURN_EXCEPTION, exception in state[0]
mp_execute_bytecode(mp_code_state_t * code_state,volatile mp_obj_t inject_exc)206 mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc) {
207 #define SELECTIVE_EXC_IP (0)
208 #if SELECTIVE_EXC_IP
209 #define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */
210 #define MARK_EXC_IP_GLOBAL()
211 #else
212 #define MARK_EXC_IP_SELECTIVE()
213 #define MARK_EXC_IP_GLOBAL() { code_state->ip = ip; } /* stores ip pointing to last opcode */
214 #endif
215 #if MICROPY_OPT_COMPUTED_GOTO
216     #include "py/vmentrytable.h"
217     #define DISPATCH() do { \
218         TRACE(ip); \
219         MARK_EXC_IP_GLOBAL(); \
220         TRACE_TICK(ip, sp, false); \
221         goto *entry_table[*ip++]; \
222     } while (0)
223     #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
224     #define ENTRY(op) entry_##op
225     #define ENTRY_DEFAULT entry_default
226 #else
227     #define DISPATCH() goto dispatch_loop
228     #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
229     #define ENTRY(op) case op
230     #define ENTRY_DEFAULT default
231 #endif
232 
233     // nlr_raise needs to be implemented as a goto, so that the C compiler's flow analyser
234     // sees that it's possible for us to jump from the dispatch loop to the exception
235     // handler.  Without this, the code may have a different stack layout in the dispatch
236     // loop and the exception handler, leading to very obscure bugs.
237     #define RAISE(o) do { nlr_pop(); nlr.ret_val = MP_OBJ_TO_PTR(o); goto exception_handler; } while (0)
238 
239 #if MICROPY_STACKLESS
240 run_code_state: ;
241 #endif
242 FRAME_ENTER();
243 
244 #if MICROPY_STACKLESS
245 run_code_state_from_return: ;
246 #endif
247 FRAME_SETUP();
248 
249     // Pointers which are constant for particular invocation of mp_execute_bytecode()
250     mp_obj_t * /*const*/ fastn;
251     mp_exc_stack_t * /*const*/ exc_stack;
252     {
253         size_t n_state = code_state->n_state;
254         fastn = &code_state->state[n_state - 1];
255         exc_stack = (mp_exc_stack_t*)(code_state->state + n_state);
256     }
257 
258     // variables that are visible to the exception handler (declared volatile)
259     mp_exc_stack_t *volatile exc_sp = MP_CODE_STATE_EXC_SP_IDX_TO_PTR(exc_stack, code_state->exc_sp_idx); // stack grows up, exc_sp points to top of stack
260 
261     #if MICROPY_PY_THREAD_GIL && MICROPY_PY_THREAD_GIL_VM_DIVISOR
262     // This needs to be volatile and outside the VM loop so it persists across handling
263     // of any exceptions.  Otherwise it's possible that the VM never gives up the GIL.
264     volatile int gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
265     #endif
266 
267     // outer exception handling loop
268     for (;;) {
269         nlr_buf_t nlr;
270 outer_dispatch_loop:
271         if (nlr_push(&nlr) == 0) {
272             // local variables that are not visible to the exception handler
273             const byte *ip = code_state->ip;
274             mp_obj_t *sp = code_state->sp;
275             mp_obj_t obj_shared;
276             MICROPY_VM_HOOK_INIT
277 
278             // If we have exception to inject, now that we finish setting up
279             // execution context, raise it. This works as if MP_BC_RAISE_OBJ
280             // bytecode was executed.
281             // Injecting exc into yield from generator is a special case,
282             // handled by MP_BC_YIELD_FROM itself
283             if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
284                 mp_obj_t exc = inject_exc;
285                 inject_exc = MP_OBJ_NULL;
286                 exc = mp_make_raise_obj(exc);
287                 RAISE(exc);
288             }
289 
290             // loop to execute byte code
291             for (;;) {
292 dispatch_loop:
293 #if MICROPY_OPT_COMPUTED_GOTO
294                 DISPATCH();
295 #else
296                 TRACE(ip);
297                 MARK_EXC_IP_GLOBAL();
298                 TRACE_TICK(ip, sp, false);
299                 switch (*ip++) {
300 #endif
301 
302                 ENTRY(MP_BC_LOAD_CONST_FALSE):
303                     PUSH(mp_const_false);
304                     DISPATCH();
305 
306                 ENTRY(MP_BC_LOAD_CONST_NONE):
307                     PUSH(mp_const_none);
308                     DISPATCH();
309 
310                 ENTRY(MP_BC_LOAD_CONST_TRUE):
311                     PUSH(mp_const_true);
312                     DISPATCH();
313 
314                 ENTRY(MP_BC_LOAD_CONST_SMALL_INT): {
315                     mp_uint_t num = 0;
316                     if ((ip[0] & 0x40) != 0) {
317                         // Number is negative
318                         num--;
319                     }
320                     do {
321                         num = (num << 7) | (*ip & 0x7f);
322                     } while ((*ip++ & 0x80) != 0);
323                     PUSH(MP_OBJ_NEW_SMALL_INT(num));
324                     DISPATCH();
325                 }
326 
327                 ENTRY(MP_BC_LOAD_CONST_STRING): {
328                     DECODE_QSTR;
329                     PUSH(MP_OBJ_NEW_QSTR(qst));
330                     DISPATCH();
331                 }
332 
333                 ENTRY(MP_BC_LOAD_CONST_OBJ): {
334                     DECODE_OBJ;
335                     PUSH(obj);
336                     DISPATCH();
337                 }
338 
339                 ENTRY(MP_BC_LOAD_NULL):
340                     PUSH(MP_OBJ_NULL);
341                     DISPATCH();
342 
343                 ENTRY(MP_BC_LOAD_FAST_N): {
344                     DECODE_UINT;
345                     obj_shared = fastn[-unum];
346                     load_check:
347                     if (obj_shared == MP_OBJ_NULL) {
348                         local_name_error: {
349                             MARK_EXC_IP_SELECTIVE();
350                             mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, MP_ERROR_TEXT("local variable referenced before assignment"));
351                             RAISE(obj);
352                         }
353                     }
354                     PUSH(obj_shared);
355                     DISPATCH();
356                 }
357 
358                 ENTRY(MP_BC_LOAD_DEREF): {
359                     DECODE_UINT;
360                     obj_shared = mp_obj_cell_get(fastn[-unum]);
361                     goto load_check;
362                 }
363 
364                 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
365                 ENTRY(MP_BC_LOAD_NAME): {
366                     MARK_EXC_IP_SELECTIVE();
367                     DECODE_QSTR;
368                     PUSH(mp_load_name(qst));
369                     DISPATCH();
370                 }
371                 #else
372                 ENTRY(MP_BC_LOAD_NAME): {
373                     MARK_EXC_IP_SELECTIVE();
374                     DECODE_QSTR;
375                     mp_map_elem_t *elem = mp_map_cached_lookup(&mp_locals_get()->map, qst, (uint8_t*)ip);
376                     mp_obj_t obj;
377                     if (elem != NULL) {
378                         obj = elem->value;
379                     } else {
380                         obj = mp_load_name(qst);
381                     }
382                     PUSH(obj);
383                     ip++;
384                     DISPATCH();
385                 }
386                 #endif
387 
388                 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
389                 ENTRY(MP_BC_LOAD_GLOBAL): {
390                     MARK_EXC_IP_SELECTIVE();
391                     DECODE_QSTR;
392                     PUSH(mp_load_global(qst));
393                     DISPATCH();
394                 }
395                 #else
396                 ENTRY(MP_BC_LOAD_GLOBAL): {
397                     MARK_EXC_IP_SELECTIVE();
398                     DECODE_QSTR;
399                     mp_map_elem_t *elem = mp_map_cached_lookup(&mp_globals_get()->map, qst, (uint8_t*)ip);
400                     mp_obj_t obj;
401                     if (elem != NULL) {
402                         obj = elem->value;
403                     } else {
404                         obj = mp_load_global(qst);
405                     }
406                     PUSH(obj);
407                     ip++;
408                     DISPATCH();
409                 }
410                 #endif
411 
412                 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
413                 ENTRY(MP_BC_LOAD_ATTR): {
414                     FRAME_UPDATE();
415                     MARK_EXC_IP_SELECTIVE();
416                     DECODE_QSTR;
417                     SET_TOP(mp_load_attr(TOP(), qst));
418                     DISPATCH();
419                 }
420                 #else
421                 ENTRY(MP_BC_LOAD_ATTR): {
422                     FRAME_UPDATE();
423                     MARK_EXC_IP_SELECTIVE();
424                     DECODE_QSTR;
425                     mp_obj_t top = TOP();
426                     mp_map_elem_t *elem = NULL;
427                     if (mp_obj_is_instance_type(mp_obj_get_type(top))) {
428                         mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
429                         elem = mp_map_cached_lookup(&self->members, qst, (uint8_t*)ip);
430                     }
431                     mp_obj_t obj;
432                     if (elem != NULL) {
433                         obj = elem->value;
434                     } else {
435                         obj = mp_load_attr(top, qst);
436                     }
437                     SET_TOP(obj);
438                     ip++;
439                     DISPATCH();
440                 }
441                 #endif
442 
443                 ENTRY(MP_BC_LOAD_METHOD): {
444                     MARK_EXC_IP_SELECTIVE();
445                     DECODE_QSTR;
446                     mp_load_method(*sp, qst, sp);
447                     sp += 1;
448                     DISPATCH();
449                 }
450 
451                 ENTRY(MP_BC_LOAD_SUPER_METHOD): {
452                     MARK_EXC_IP_SELECTIVE();
453                     DECODE_QSTR;
454                     sp -= 1;
455                     mp_load_super_method(qst, sp - 1);
456                     DISPATCH();
457                 }
458 
459                 ENTRY(MP_BC_LOAD_BUILD_CLASS):
460                     MARK_EXC_IP_SELECTIVE();
461                     PUSH(mp_load_build_class());
462                     DISPATCH();
463 
464                 ENTRY(MP_BC_LOAD_SUBSCR): {
465                     MARK_EXC_IP_SELECTIVE();
466                     mp_obj_t index = POP();
467                     SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL));
468                     DISPATCH();
469                 }
470 
471                 ENTRY(MP_BC_STORE_FAST_N): {
472                     DECODE_UINT;
473                     fastn[-unum] = POP();
474                     DISPATCH();
475                 }
476 
477                 ENTRY(MP_BC_STORE_DEREF): {
478                     DECODE_UINT;
479                     mp_obj_cell_set(fastn[-unum], POP());
480                     DISPATCH();
481                 }
482 
483                 ENTRY(MP_BC_STORE_NAME): {
484                     MARK_EXC_IP_SELECTIVE();
485                     DECODE_QSTR;
486                     mp_store_name(qst, POP());
487                     DISPATCH();
488                 }
489 
490                 ENTRY(MP_BC_STORE_GLOBAL): {
491                     MARK_EXC_IP_SELECTIVE();
492                     DECODE_QSTR;
493                     mp_store_global(qst, POP());
494                     DISPATCH();
495                 }
496 
497                 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
498                 ENTRY(MP_BC_STORE_ATTR): {
499                     FRAME_UPDATE();
500                     MARK_EXC_IP_SELECTIVE();
501                     DECODE_QSTR;
502                     mp_store_attr(sp[0], qst, sp[-1]);
503                     sp -= 2;
504                     DISPATCH();
505                 }
506                 #else
507                 // This caching code works with MICROPY_PY_BUILTINS_PROPERTY and/or
508                 // MICROPY_PY_DESCRIPTORS enabled because if the attr exists in
509                 // self->members then it can't be a property or have descriptors.  A
510                 // consequence of this is that we can't use MP_MAP_LOOKUP_ADD_IF_NOT_FOUND
511                 // in the fast-path below, because that store could override a property.
512                 ENTRY(MP_BC_STORE_ATTR): {
513                     FRAME_UPDATE();
514                     MARK_EXC_IP_SELECTIVE();
515                     DECODE_QSTR;
516                     mp_map_elem_t *elem = NULL;
517                     mp_obj_t top = TOP();
518                     if (mp_obj_is_instance_type(mp_obj_get_type(top)) && sp[-1] != MP_OBJ_NULL) {
519                         mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
520                         elem = mp_map_cached_lookup(&self->members, qst, (uint8_t*)ip);
521                     }
522                     if (elem != NULL) {
523                         elem->value = sp[-1];
524                     } else {
525                         mp_store_attr(sp[0], qst, sp[-1]);
526                     }
527                     sp -= 2;
528                     ip++;
529                     DISPATCH();
530                 }
531                 #endif
532 
533                 ENTRY(MP_BC_STORE_SUBSCR):
534                     MARK_EXC_IP_SELECTIVE();
535                     mp_obj_subscr(sp[-1], sp[0], sp[-2]);
536                     sp -= 3;
537                     DISPATCH();
538 
539                 ENTRY(MP_BC_DELETE_FAST): {
540                     MARK_EXC_IP_SELECTIVE();
541                     DECODE_UINT;
542                     if (fastn[-unum] == MP_OBJ_NULL) {
543                         goto local_name_error;
544                     }
545                     fastn[-unum] = MP_OBJ_NULL;
546                     DISPATCH();
547                 }
548 
549                 ENTRY(MP_BC_DELETE_DEREF): {
550                     MARK_EXC_IP_SELECTIVE();
551                     DECODE_UINT;
552                     if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
553                         goto local_name_error;
554                     }
555                     mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);
556                     DISPATCH();
557                 }
558 
559                 ENTRY(MP_BC_DELETE_NAME): {
560                     MARK_EXC_IP_SELECTIVE();
561                     DECODE_QSTR;
562                     mp_delete_name(qst);
563                     DISPATCH();
564                 }
565 
566                 ENTRY(MP_BC_DELETE_GLOBAL): {
567                     MARK_EXC_IP_SELECTIVE();
568                     DECODE_QSTR;
569                     mp_delete_global(qst);
570                     DISPATCH();
571                 }
572 
573                 ENTRY(MP_BC_DUP_TOP): {
574                     mp_obj_t top = TOP();
575                     PUSH(top);
576                     DISPATCH();
577                 }
578 
579                 ENTRY(MP_BC_DUP_TOP_TWO):
580                     sp += 2;
581                     sp[0] = sp[-2];
582                     sp[-1] = sp[-3];
583                     DISPATCH();
584 
585                 ENTRY(MP_BC_POP_TOP):
586                     sp -= 1;
587                     DISPATCH();
588 
589                 ENTRY(MP_BC_ROT_TWO): {
590                     mp_obj_t top = sp[0];
591                     sp[0] = sp[-1];
592                     sp[-1] = top;
593                     DISPATCH();
594                 }
595 
596                 ENTRY(MP_BC_ROT_THREE): {
597                     mp_obj_t top = sp[0];
598                     sp[0] = sp[-1];
599                     sp[-1] = sp[-2];
600                     sp[-2] = top;
601                     DISPATCH();
602                 }
603 
604                 ENTRY(MP_BC_JUMP): {
605                     DECODE_SLABEL;
606                     ip += slab;
607                     DISPATCH_WITH_PEND_EXC_CHECK();
608                 }
609 
610                 ENTRY(MP_BC_POP_JUMP_IF_TRUE): {
611                     DECODE_SLABEL;
612                     if (mp_obj_is_true(POP())) {
613                         ip += slab;
614                     }
615                     DISPATCH_WITH_PEND_EXC_CHECK();
616                 }
617 
618                 ENTRY(MP_BC_POP_JUMP_IF_FALSE): {
619                     DECODE_SLABEL;
620                     if (!mp_obj_is_true(POP())) {
621                         ip += slab;
622                     }
623                     DISPATCH_WITH_PEND_EXC_CHECK();
624                 }
625 
626                 ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP): {
627                     DECODE_SLABEL;
628                     if (mp_obj_is_true(TOP())) {
629                         ip += slab;
630                     } else {
631                         sp--;
632                     }
633                     DISPATCH_WITH_PEND_EXC_CHECK();
634                 }
635 
636                 ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP): {
637                     DECODE_SLABEL;
638                     if (mp_obj_is_true(TOP())) {
639                         sp--;
640                     } else {
641                         ip += slab;
642                     }
643                     DISPATCH_WITH_PEND_EXC_CHECK();
644                 }
645 
646                 ENTRY(MP_BC_SETUP_WITH): {
647                     MARK_EXC_IP_SELECTIVE();
648                     // stack: (..., ctx_mgr)
649                     mp_obj_t obj = TOP();
650                     mp_load_method(obj, MP_QSTR___exit__, sp);
651                     mp_load_method(obj, MP_QSTR___enter__, sp + 2);
652                     mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 2);
653                     sp += 1;
654                     PUSH_EXC_BLOCK(1);
655                     PUSH(ret);
656                     // stack: (..., __exit__, ctx_mgr, as_value)
657                     DISPATCH();
658                 }
659 
660                 ENTRY(MP_BC_WITH_CLEANUP): {
661                     MARK_EXC_IP_SELECTIVE();
662                     // Arriving here, there's "exception control block" on top of stack,
663                     // and __exit__ method (with self) underneath it. Bytecode calls __exit__,
664                     // and "deletes" it off stack, shifting "exception control block"
665                     // to its place.
666                     // The bytecode emitter ensures that there is enough space on the Python
667                     // value stack to hold the __exit__ method plus an additional 4 entries.
668                     if (TOP() == mp_const_none) {
669                         // stack: (..., __exit__, ctx_mgr, None)
670                         sp[1] = mp_const_none;
671                         sp[2] = mp_const_none;
672                         sp -= 2;
673                         mp_call_method_n_kw(3, 0, sp);
674                         SET_TOP(mp_const_none);
675                     } else if (mp_obj_is_small_int(TOP())) {
676                         // Getting here there are two distinct cases:
677                         //  - unwind return, stack: (..., __exit__, ctx_mgr, ret_val, SMALL_INT(-1))
678                         //  - unwind jump, stack:   (..., __exit__, ctx_mgr, dest_ip, SMALL_INT(num_exc))
679                         // For both cases we do exactly the same thing.
680                         mp_obj_t data = sp[-1];
681                         mp_obj_t cause = sp[0];
682                         sp[-1] = mp_const_none;
683                         sp[0] = mp_const_none;
684                         sp[1] = mp_const_none;
685                         mp_call_method_n_kw(3, 0, sp - 3);
686                         sp[-3] = data;
687                         sp[-2] = cause;
688                         sp -= 2; // we removed (__exit__, ctx_mgr)
689                     } else {
690                         assert(mp_obj_is_exception_instance(TOP()));
691                         // stack: (..., __exit__, ctx_mgr, exc_instance)
692                         // Need to pass (exc_type, exc_instance, None) as arguments to __exit__.
693                         sp[1] = sp[0];
694                         sp[0] = MP_OBJ_FROM_PTR(mp_obj_get_type(sp[0]));
695                         sp[2] = mp_const_none;
696                         sp -= 2;
697                         mp_obj_t ret_value = mp_call_method_n_kw(3, 0, sp);
698                         if (mp_obj_is_true(ret_value)) {
699                             // We need to silence/swallow the exception.  This is done
700                             // by popping the exception and the __exit__ handler and
701                             // replacing it with None, which signals END_FINALLY to just
702                             // execute the finally handler normally.
703                             SET_TOP(mp_const_none);
704                         } else {
705                             // We need to re-raise the exception.  We pop __exit__ handler
706                             // by copying the exception instance down to the new top-of-stack.
707                             sp[0] = sp[3];
708                         }
709                     }
710                     DISPATCH();
711                 }
712 
713                 ENTRY(MP_BC_UNWIND_JUMP): {
714                     MARK_EXC_IP_SELECTIVE();
715                     DECODE_SLABEL;
716                     PUSH((mp_obj_t)(mp_uint_t)(uintptr_t)(ip + slab)); // push destination ip for jump
717                     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)
718 unwind_jump:;
719                     mp_uint_t unum = (mp_uint_t)POP(); // get number of exception handlers to unwind
720                     while ((unum & 0x7f) > 0) {
721                         unum -= 1;
722                         assert(exc_sp >= exc_stack);
723 
724                         if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
725                             if (exc_sp->handler > ip) {
726                                 // Found a finally handler that isn't active; run it.
727                                 // Getting here the stack looks like:
728                                 //     (..., X, dest_ip)
729                                 // where X is pointed to by exc_sp->val_sp and in the case
730                                 // of a "with" block contains the context manager info.
731                                 assert(&sp[-1] == MP_TAGPTR_PTR(exc_sp->val_sp));
732                                 // We're going to run "finally" code as a coroutine
733                                 // (not calling it recursively). Set up a sentinel
734                                 // on the stack so it can return back to us when it is
735                                 // done (when WITH_CLEANUP or END_FINALLY reached).
736                                 // The sentinel is the number of exception handlers left to
737                                 // unwind, which is a non-negative integer.
738                                 PUSH(MP_OBJ_NEW_SMALL_INT(unum));
739                                 ip = exc_sp->handler;
740                                 goto dispatch_loop;
741                             } else {
742                                 // Found a finally handler that is already active; cancel it.
743                                 CANCEL_ACTIVE_FINALLY(sp);
744                             }
745                         }
746                         POP_EXC_BLOCK();
747                     }
748                     ip = (const byte*)MP_OBJ_TO_PTR(POP()); // pop destination ip for jump
749                     if (unum != 0) {
750                         // pop the exhausted iterator
751                         sp -= MP_OBJ_ITER_BUF_NSLOTS;
752                     }
753                     DISPATCH_WITH_PEND_EXC_CHECK();
754                 }
755 
756                 ENTRY(MP_BC_SETUP_EXCEPT):
757                 ENTRY(MP_BC_SETUP_FINALLY): {
758                     MARK_EXC_IP_SELECTIVE();
759                     #if SELECTIVE_EXC_IP
760                     PUSH_EXC_BLOCK((code_state->ip[-1] == MP_BC_SETUP_FINALLY) ? 1 : 0);
761                     #else
762                     PUSH_EXC_BLOCK((code_state->ip[0] == MP_BC_SETUP_FINALLY) ? 1 : 0);
763                     #endif
764                     DISPATCH();
765                 }
766 
767                 ENTRY(MP_BC_END_FINALLY):
768                     MARK_EXC_IP_SELECTIVE();
769                     // if TOS is None, just pops it and continues
770                     // if TOS is an integer, finishes coroutine and returns control to caller
771                     // if TOS is an exception, reraises the exception
772                     assert(exc_sp >= exc_stack);
773                     POP_EXC_BLOCK();
774                     if (TOP() == mp_const_none) {
775                         sp--;
776                     } else if (mp_obj_is_small_int(TOP())) {
777                         // We finished "finally" coroutine and now dispatch back
778                         // to our caller, based on TOS value
779                         mp_int_t cause = MP_OBJ_SMALL_INT_VALUE(POP());
780                         if (cause < 0) {
781                             // A negative cause indicates unwind return
782                             goto unwind_return;
783                         } else {
784                             // Otherwise it's an unwind jump and we must push as a raw
785                             // number the number of exception handlers to unwind
786                             PUSH((mp_obj_t)cause);
787                             goto unwind_jump;
788                         }
789                     } else {
790                         assert(mp_obj_is_exception_instance(TOP()));
791                         RAISE(TOP());
792                     }
793                     DISPATCH();
794 
795                 ENTRY(MP_BC_GET_ITER):
796                     MARK_EXC_IP_SELECTIVE();
797                     SET_TOP(mp_getiter(TOP(), NULL));
798                     DISPATCH();
799 
800                 // An iterator for a for-loop takes MP_OBJ_ITER_BUF_NSLOTS slots on
801                 // the Python value stack.  These slots are either used to store the
802                 // iterator object itself, or the first slot is MP_OBJ_NULL and
803                 // the second slot holds a reference to the iterator object.
804                 ENTRY(MP_BC_GET_ITER_STACK): {
805                     MARK_EXC_IP_SELECTIVE();
806                     mp_obj_t obj = TOP();
807                     mp_obj_iter_buf_t *iter_buf = (mp_obj_iter_buf_t*)sp;
808                     sp += MP_OBJ_ITER_BUF_NSLOTS - 1;
809                     obj = mp_getiter(obj, iter_buf);
810                     if (obj != MP_OBJ_FROM_PTR(iter_buf)) {
811                         // Iterator didn't use the stack so indicate that with MP_OBJ_NULL.
812                         sp[-MP_OBJ_ITER_BUF_NSLOTS + 1] = MP_OBJ_NULL;
813                         sp[-MP_OBJ_ITER_BUF_NSLOTS + 2] = obj;
814                     }
815                     DISPATCH();
816                 }
817 
818                 ENTRY(MP_BC_FOR_ITER): {
819                     FRAME_UPDATE();
820                     MARK_EXC_IP_SELECTIVE();
821                     DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
822                     code_state->sp = sp;
823                     mp_obj_t obj;
824                     if (sp[-MP_OBJ_ITER_BUF_NSLOTS + 1] == MP_OBJ_NULL) {
825                         obj = sp[-MP_OBJ_ITER_BUF_NSLOTS + 2];
826                     } else {
827                         obj = MP_OBJ_FROM_PTR(&sp[-MP_OBJ_ITER_BUF_NSLOTS + 1]);
828                     }
829                     mp_obj_t value = mp_iternext_allow_raise(obj);
830                     if (value == MP_OBJ_STOP_ITERATION) {
831                         sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator
832                         ip += ulab; // jump to after for-block
833                     } else {
834                         PUSH(value); // push the next iteration value
835                         #if MICROPY_PY_SYS_SETTRACE
836                         // LINE event should trigger for every iteration so invalidate last trigger
837                         if (code_state->frame) {
838                             code_state->frame->lineno = 0;
839                         }
840                         #endif
841                     }
842                     DISPATCH();
843                 }
844 
845                 ENTRY(MP_BC_POP_EXCEPT_JUMP): {
846                     assert(exc_sp >= exc_stack);
847                     POP_EXC_BLOCK();
848                     DECODE_ULABEL;
849                     ip += ulab;
850                     DISPATCH_WITH_PEND_EXC_CHECK();
851                 }
852 
853                 ENTRY(MP_BC_BUILD_TUPLE): {
854                     MARK_EXC_IP_SELECTIVE();
855                     DECODE_UINT;
856                     sp -= unum - 1;
857                     SET_TOP(mp_obj_new_tuple(unum, sp));
858                     DISPATCH();
859                 }
860 
861                 ENTRY(MP_BC_BUILD_LIST): {
862                     MARK_EXC_IP_SELECTIVE();
863                     DECODE_UINT;
864                     sp -= unum - 1;
865                     SET_TOP(mp_obj_new_list(unum, sp));
866                     DISPATCH();
867                 }
868 
869                 ENTRY(MP_BC_BUILD_MAP): {
870                     MARK_EXC_IP_SELECTIVE();
871                     DECODE_UINT;
872                     PUSH(mp_obj_new_dict(unum));
873                     DISPATCH();
874                 }
875 
876                 ENTRY(MP_BC_STORE_MAP):
877                     MARK_EXC_IP_SELECTIVE();
878                     sp -= 2;
879                     mp_obj_dict_store(sp[0], sp[2], sp[1]);
880                     DISPATCH();
881 
882 #if MICROPY_PY_BUILTINS_SET
883                 ENTRY(MP_BC_BUILD_SET): {
884                     MARK_EXC_IP_SELECTIVE();
885                     DECODE_UINT;
886                     sp -= unum - 1;
887                     SET_TOP(mp_obj_new_set(unum, sp));
888                     DISPATCH();
889                 }
890 #endif
891 
892 #if MICROPY_PY_BUILTINS_SLICE
893                 ENTRY(MP_BC_BUILD_SLICE): {
894                     MARK_EXC_IP_SELECTIVE();
895                     mp_obj_t step = mp_const_none;
896                     if (*ip++ == 3) {
897                         // 3-argument slice includes step
898                         step = POP();
899                     }
900                     mp_obj_t stop = POP();
901                     mp_obj_t start = TOP();
902                     SET_TOP(mp_obj_new_slice(start, stop, step));
903                     DISPATCH();
904                 }
905 #endif
906 
907                 ENTRY(MP_BC_STORE_COMP): {
908                     MARK_EXC_IP_SELECTIVE();
909                     DECODE_UINT;
910                     mp_obj_t obj = sp[-(unum >> 2)];
911                     if ((unum & 3) == 0) {
912                         mp_obj_list_append(obj, sp[0]);
913                         sp--;
914                     } else if (!MICROPY_PY_BUILTINS_SET || (unum & 3) == 1) {
915                         mp_obj_dict_store(obj, sp[0], sp[-1]);
916                         sp -= 2;
917                     #if MICROPY_PY_BUILTINS_SET
918                     } else {
919                         mp_obj_set_store(obj, sp[0]);
920                         sp--;
921                     #endif
922                     }
923                     DISPATCH();
924                 }
925 
926                 ENTRY(MP_BC_UNPACK_SEQUENCE): {
927                     MARK_EXC_IP_SELECTIVE();
928                     DECODE_UINT;
929                     mp_unpack_sequence(sp[0], unum, sp);
930                     sp += unum - 1;
931                     DISPATCH();
932                 }
933 
934                 ENTRY(MP_BC_UNPACK_EX): {
935                     MARK_EXC_IP_SELECTIVE();
936                     DECODE_UINT;
937                     mp_unpack_ex(sp[0], unum, sp);
938                     sp += (unum & 0xff) + ((unum >> 8) & 0xff);
939                     DISPATCH();
940                 }
941 
942                 ENTRY(MP_BC_MAKE_FUNCTION): {
943                     DECODE_PTR;
944                     PUSH(mp_make_function_from_raw_code(ptr, MP_OBJ_NULL, MP_OBJ_NULL));
945                     DISPATCH();
946                 }
947 
948                 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
949                     DECODE_PTR;
950                     // Stack layout: def_tuple def_dict <- TOS
951                     mp_obj_t def_dict = POP();
952                     SET_TOP(mp_make_function_from_raw_code(ptr, TOP(), def_dict));
953                     DISPATCH();
954                 }
955 
956                 ENTRY(MP_BC_MAKE_CLOSURE): {
957                     DECODE_PTR;
958                     size_t n_closed_over = *ip++;
959                     // Stack layout: closed_overs <- TOS
960                     sp -= n_closed_over - 1;
961                     SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp));
962                     DISPATCH();
963                 }
964 
965                 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
966                     DECODE_PTR;
967                     size_t n_closed_over = *ip++;
968                     // Stack layout: def_tuple def_dict closed_overs <- TOS
969                     sp -= 2 + n_closed_over - 1;
970                     SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp));
971                     DISPATCH();
972                 }
973 
974                 ENTRY(MP_BC_CALL_FUNCTION): {
975                     FRAME_UPDATE();
976                     MARK_EXC_IP_SELECTIVE();
977                     DECODE_UINT;
978                     // unum & 0xff == n_positional
979                     // (unum >> 8) & 0xff == n_keyword
980                     sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
981                     #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_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp);
986                         mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1);
987                         #if !MICROPY_ENABLE_PYSTACK
988                         if (new_state == NULL) {
989                             // Couldn't allocate codestate on heap: in the strict case raise
990                             // an exception, otherwise just fall through to stack allocation.
991                             #if MICROPY_STACKLESS_STRICT
992                         deep_recursion_error:
993                             mp_raise_recursion_depth();
994                             #endif
995                         } else
996                         #endif
997                         {
998                             new_state->prev = code_state;
999                             code_state = new_state;
1000                             nlr_pop();
1001                             goto run_code_state;
1002                         }
1003                     }
1004                     #endif
1005                     SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
1006                     DISPATCH();
1007                 }
1008 
1009                 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): {
1010                     FRAME_UPDATE();
1011                     MARK_EXC_IP_SELECTIVE();
1012                     DECODE_UINT;
1013                     // unum & 0xff == n_positional
1014                     // (unum >> 8) & 0xff == n_keyword
1015                     // We have following stack layout here:
1016                     // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
1017                     sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
1018                     #if MICROPY_STACKLESS
1019                     if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
1020                         code_state->ip = ip;
1021                         code_state->sp = sp;
1022                         code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp);
1023 
1024                         mp_call_args_t out_args;
1025                         mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args);
1026 
1027                         mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
1028                             out_args.n_args, out_args.n_kw, out_args.args);
1029                         #if !MICROPY_ENABLE_PYSTACK
1030                         // Freeing args at this point does not follow a LIFO order so only do it if
1031                         // pystack is not enabled.  For pystack, they are freed when code_state is.
1032                         mp_nonlocal_free(out_args.args, out_args.n_alloc * sizeof(mp_obj_t));
1033                         #endif
1034                         #if !MICROPY_ENABLE_PYSTACK
1035                         if (new_state == NULL) {
1036                             // Couldn't allocate codestate on heap: in the strict case raise
1037                             // an exception, otherwise just fall through to stack allocation.
1038                             #if MICROPY_STACKLESS_STRICT
1039                             goto deep_recursion_error;
1040                             #endif
1041                         } else
1042                         #endif
1043                         {
1044                             new_state->prev = code_state;
1045                             code_state = new_state;
1046                             nlr_pop();
1047                             goto run_code_state;
1048                         }
1049                     }
1050                     #endif
1051                     SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
1052                     DISPATCH();
1053                 }
1054 
1055                 ENTRY(MP_BC_CALL_METHOD): {
1056                     FRAME_UPDATE();
1057                     MARK_EXC_IP_SELECTIVE();
1058                     DECODE_UINT;
1059                     // unum & 0xff == n_positional
1060                     // (unum >> 8) & 0xff == n_keyword
1061                     sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
1062                     #if MICROPY_STACKLESS
1063                     if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
1064                         code_state->ip = ip;
1065                         code_state->sp = sp;
1066                         code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp);
1067 
1068                         size_t n_args = unum & 0xff;
1069                         size_t n_kw = (unum >> 8) & 0xff;
1070                         int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1;
1071 
1072                         mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust);
1073                         #if !MICROPY_ENABLE_PYSTACK
1074                         if (new_state == NULL) {
1075                             // Couldn't allocate codestate on heap: in the strict case raise
1076                             // an exception, otherwise just fall through to stack allocation.
1077                             #if MICROPY_STACKLESS_STRICT
1078                             goto deep_recursion_error;
1079                             #endif
1080                         } else
1081                         #endif
1082                         {
1083                             new_state->prev = code_state;
1084                             code_state = new_state;
1085                             nlr_pop();
1086                             goto run_code_state;
1087                         }
1088                     }
1089                     #endif
1090                     SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
1091                     DISPATCH();
1092                 }
1093 
1094                 ENTRY(MP_BC_CALL_METHOD_VAR_KW): {
1095                     FRAME_UPDATE();
1096                     MARK_EXC_IP_SELECTIVE();
1097                     DECODE_UINT;
1098                     // unum & 0xff == n_positional
1099                     // (unum >> 8) & 0xff == n_keyword
1100                     // We have following stack layout here:
1101                     // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
1102                     sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
1103                     #if MICROPY_STACKLESS
1104                     if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
1105                         code_state->ip = ip;
1106                         code_state->sp = sp;
1107                         code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp);
1108 
1109                         mp_call_args_t out_args;
1110                         mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args);
1111 
1112                         mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
1113                             out_args.n_args, out_args.n_kw, out_args.args);
1114                         #if !MICROPY_ENABLE_PYSTACK
1115                         // Freeing args at this point does not follow a LIFO order so only do it if
1116                         // pystack is not enabled.  For pystack, they are freed when code_state is.
1117                         mp_nonlocal_free(out_args.args, out_args.n_alloc * sizeof(mp_obj_t));
1118                         #endif
1119                         #if !MICROPY_ENABLE_PYSTACK
1120                         if (new_state == NULL) {
1121                             // Couldn't allocate codestate on heap: in the strict case raise
1122                             // an exception, otherwise just fall through to stack allocation.
1123                             #if MICROPY_STACKLESS_STRICT
1124                             goto deep_recursion_error;
1125                             #endif
1126                         } else
1127                         #endif
1128                         {
1129                             new_state->prev = code_state;
1130                             code_state = new_state;
1131                             nlr_pop();
1132                             goto run_code_state;
1133                         }
1134                     }
1135                     #endif
1136                     SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
1137                     DISPATCH();
1138                 }
1139 
1140                 ENTRY(MP_BC_RETURN_VALUE):
1141                     MARK_EXC_IP_SELECTIVE();
1142 unwind_return:
1143                     // Search for and execute finally handlers that aren't already active
1144                     while (exc_sp >= exc_stack) {
1145                         if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
1146                             if (exc_sp->handler > ip) {
1147                                 // Found a finally handler that isn't active; run it.
1148                                 // Getting here the stack looks like:
1149                                 //     (..., X, [iter0, iter1, ...,] ret_val)
1150                                 // where X is pointed to by exc_sp->val_sp and in the case
1151                                 // of a "with" block contains the context manager info.
1152                                 // There may be 0 or more for-iterators between X and the
1153                                 // return value, and these must be removed before control can
1154                                 // pass to the finally code.  We simply copy the ret_value down
1155                                 // over these iterators, if they exist.  If they don't then the
1156                                 // following is a null operation.
1157                                 mp_obj_t *finally_sp = MP_TAGPTR_PTR(exc_sp->val_sp);
1158                                 finally_sp[1] = sp[0];
1159                                 sp = &finally_sp[1];
1160                                 // We're going to run "finally" code as a coroutine
1161                                 // (not calling it recursively). Set up a sentinel
1162                                 // on a stack so it can return back to us when it is
1163                                 // done (when WITH_CLEANUP or END_FINALLY reached).
1164                                 PUSH(MP_OBJ_NEW_SMALL_INT(-1));
1165                                 ip = exc_sp->handler;
1166                                 goto dispatch_loop;
1167                             } else {
1168                                 // Found a finally handler that is already active; cancel it.
1169                                 CANCEL_ACTIVE_FINALLY(sp);
1170                             }
1171                         }
1172                         POP_EXC_BLOCK();
1173                     }
1174                     nlr_pop();
1175                     code_state->sp = sp;
1176                     assert(exc_sp == exc_stack - 1);
1177                     MICROPY_VM_HOOK_RETURN
1178                     #if MICROPY_STACKLESS
1179                     if (code_state->prev != NULL) {
1180                         mp_obj_t res = *sp;
1181                         mp_globals_set(code_state->old_globals);
1182                         mp_code_state_t *new_code_state = code_state->prev;
1183                         #if MICROPY_ENABLE_PYSTACK
1184                         // Free code_state, and args allocated by mp_call_prepare_args_n_kw_var
1185                         // (The latter is implicitly freed when using pystack due to its LIFO nature.)
1186                         // The sizeof in the following statement does not include the size of the variable
1187                         // part of the struct.  This arg is anyway not used if pystack is enabled.
1188                         mp_nonlocal_free(code_state, sizeof(mp_code_state_t));
1189                         #endif
1190                         code_state = new_code_state;
1191                         *code_state->sp = res;
1192                         goto run_code_state_from_return;
1193                     }
1194                     #endif
1195                     FRAME_LEAVE();
1196                     return MP_VM_RETURN_NORMAL;
1197 
1198                 ENTRY(MP_BC_RAISE_LAST): {
1199                     MARK_EXC_IP_SELECTIVE();
1200                     // search for the inner-most previous exception, to reraise it
1201                     mp_obj_t obj = MP_OBJ_NULL;
1202                     for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; --e) {
1203                         if (e->prev_exc != NULL) {
1204                             obj = MP_OBJ_FROM_PTR(e->prev_exc);
1205                             break;
1206                         }
1207                     }
1208                     if (obj == MP_OBJ_NULL) {
1209                         obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("no active exception to reraise"));
1210                     }
1211                     RAISE(obj);
1212                 }
1213 
1214                 ENTRY(MP_BC_RAISE_OBJ): {
1215                     MARK_EXC_IP_SELECTIVE();
1216                     mp_obj_t obj = mp_make_raise_obj(TOP());
1217                     RAISE(obj);
1218                 }
1219 
1220                 ENTRY(MP_BC_RAISE_FROM): {
1221                     MARK_EXC_IP_SELECTIVE();
1222                     mp_warning(NULL, "exception chaining not supported");
1223                     sp--; // ignore (pop) "from" argument
1224                     mp_obj_t obj = mp_make_raise_obj(TOP());
1225                     RAISE(obj);
1226                 }
1227 
1228                 ENTRY(MP_BC_YIELD_VALUE):
1229 yield:
1230                     nlr_pop();
1231                     code_state->ip = ip;
1232                     code_state->sp = sp;
1233                     code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp);
1234                     FRAME_LEAVE();
1235                     return MP_VM_RETURN_YIELD;
1236 
1237                 ENTRY(MP_BC_YIELD_FROM): {
1238                     MARK_EXC_IP_SELECTIVE();
1239 //#define EXC_MATCH(exc, type) mp_obj_is_type(exc, type)
1240 #define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
1241 #define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { mp_obj_t raise_t = mp_make_raise_obj(t); RAISE(raise_t); }
1242                     mp_vm_return_kind_t ret_kind;
1243                     mp_obj_t send_value = POP();
1244                     mp_obj_t t_exc = MP_OBJ_NULL;
1245                     mp_obj_t ret_value;
1246                     code_state->sp = sp; // Save sp because it's needed if mp_resume raises StopIteration
1247                     if (inject_exc != MP_OBJ_NULL) {
1248                         t_exc = inject_exc;
1249                         inject_exc = MP_OBJ_NULL;
1250                         ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
1251                     } else {
1252                         ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
1253                     }
1254 
1255                     if (ret_kind == MP_VM_RETURN_YIELD) {
1256                         ip--;
1257                         PUSH(ret_value);
1258                         goto yield;
1259                     } else if (ret_kind == MP_VM_RETURN_NORMAL) {
1260                         // The generator has finished, and returned a value via StopIteration
1261                         // Replace exhausted generator with the returned value
1262                         SET_TOP(ret_value);
1263                         // If we injected GeneratorExit downstream, then even
1264                         // if it was swallowed, we re-raise GeneratorExit
1265                         GENERATOR_EXIT_IF_NEEDED(t_exc);
1266                         DISPATCH();
1267                     } else {
1268                         assert(ret_kind == MP_VM_RETURN_EXCEPTION);
1269                         assert(!EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration)));
1270                         // Pop exhausted gen
1271                         sp--;
1272                         RAISE(ret_value);
1273                     }
1274                 }
1275 
1276                 ENTRY(MP_BC_IMPORT_NAME): {
1277                     FRAME_UPDATE();
1278                     MARK_EXC_IP_SELECTIVE();
1279                     DECODE_QSTR;
1280                     mp_obj_t obj = POP();
1281                     SET_TOP(mp_import_name(qst, obj, TOP()));
1282                     DISPATCH();
1283                 }
1284 
1285                 ENTRY(MP_BC_IMPORT_FROM): {
1286                     FRAME_UPDATE();
1287                     MARK_EXC_IP_SELECTIVE();
1288                     DECODE_QSTR;
1289                     mp_obj_t obj = mp_import_from(TOP(), qst);
1290                     PUSH(obj);
1291                     DISPATCH();
1292                 }
1293 
1294                 ENTRY(MP_BC_IMPORT_STAR):
1295                     MARK_EXC_IP_SELECTIVE();
1296                     mp_import_all(POP());
1297                     DISPATCH();
1298 
1299 #if MICROPY_OPT_COMPUTED_GOTO
1300                 ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):
1301                     PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS));
1302                     DISPATCH();
1303 
1304                 ENTRY(MP_BC_LOAD_FAST_MULTI):
1305                     obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1306                     goto load_check;
1307 
1308                 ENTRY(MP_BC_STORE_FAST_MULTI):
1309                     fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1310                     DISPATCH();
1311 
1312                 ENTRY(MP_BC_UNARY_OP_MULTI):
1313                     MARK_EXC_IP_SELECTIVE();
1314                     SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1315                     DISPATCH();
1316 
1317                 ENTRY(MP_BC_BINARY_OP_MULTI): {
1318                     MARK_EXC_IP_SELECTIVE();
1319                     mp_obj_t rhs = POP();
1320                     mp_obj_t lhs = TOP();
1321                     SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1322                     DISPATCH();
1323                 }
1324 
1325                 ENTRY_DEFAULT:
1326                     MARK_EXC_IP_SELECTIVE();
1327 #else
1328                 ENTRY_DEFAULT:
1329                     if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + MP_BC_LOAD_CONST_SMALL_INT_MULTI_NUM) {
1330                         PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - MP_BC_LOAD_CONST_SMALL_INT_MULTI_EXCESS));
1331                         DISPATCH();
1332                     } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + MP_BC_LOAD_FAST_MULTI_NUM) {
1333                         obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1334                         goto load_check;
1335                     } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + MP_BC_STORE_FAST_MULTI_NUM) {
1336                         fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1337                         DISPATCH();
1338                     } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + MP_BC_UNARY_OP_MULTI_NUM) {
1339                         SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
1340                         DISPATCH();
1341                     } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + MP_BC_BINARY_OP_MULTI_NUM) {
1342                         mp_obj_t rhs = POP();
1343                         mp_obj_t lhs = TOP();
1344                         SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1345                         DISPATCH();
1346                     } else
1347 #endif
1348                 {
1349 
1350                     mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, MP_ERROR_TEXT("opcode"));
1351                     nlr_pop();
1352                     code_state->state[0] = obj;
1353                     FRAME_LEAVE();
1354                     return MP_VM_RETURN_EXCEPTION;
1355                 }
1356 
1357 #if !MICROPY_OPT_COMPUTED_GOTO
1358                 } // switch
1359 #endif
1360 
1361 pending_exception_check:
1362                 MICROPY_VM_HOOK_LOOP
1363 
1364                 #if MICROPY_ENABLE_SCHEDULER
1365                 // This is an inlined variant of mp_handle_pending
1366                 if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) {
1367                     mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
1368                     // Re-check state is still pending now that we're in the atomic section.
1369                     if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) {
1370                         MARK_EXC_IP_SELECTIVE();
1371                         mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception);
1372                         if (obj != MP_OBJ_NULL) {
1373                             MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL;
1374                             if (!mp_sched_num_pending()) {
1375                                 MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
1376                             }
1377                             MICROPY_END_ATOMIC_SECTION(atomic_state);
1378                             RAISE(obj);
1379                         }
1380                         mp_handle_pending_tail(atomic_state);
1381                     } else {
1382                         MICROPY_END_ATOMIC_SECTION(atomic_state);
1383                     }
1384                 }
1385                 #else
1386                 // This is an inlined variant of mp_handle_pending
1387                 if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) {
1388                     MARK_EXC_IP_SELECTIVE();
1389                     mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception);
1390                     MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL;
1391                     RAISE(obj);
1392                 }
1393                 #endif
1394 
1395                 #if MICROPY_PY_THREAD_GIL
1396                 #if MICROPY_PY_THREAD_GIL_VM_DIVISOR
1397                 if (--gil_divisor == 0)
1398                 #endif
1399                 {
1400                     #if MICROPY_PY_THREAD_GIL_VM_DIVISOR
1401                     gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
1402                     #endif
1403                     #if MICROPY_ENABLE_SCHEDULER
1404                     // can only switch threads if the scheduler is unlocked
1405                     if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE)
1406                     #endif
1407                     {
1408                     MP_THREAD_GIL_EXIT();
1409                     MP_THREAD_GIL_ENTER();
1410                     }
1411                 }
1412                 #endif
1413 
1414             } // for loop
1415 
1416         } else {
1417 exception_handler:
1418             // exception occurred
1419 
1420             #if MICROPY_PY_SYS_EXC_INFO
1421             MP_STATE_VM(cur_exception) = nlr.ret_val;
1422             #endif
1423 
1424             #if SELECTIVE_EXC_IP
1425             // with selective ip, we store the ip 1 byte past the opcode, so move ptr back
1426             code_state->ip -= 1;
1427             #endif
1428 
1429             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))) {
1430                 if (code_state->ip) {
1431                     // check if it's a StopIteration within a for block
1432                     if (*code_state->ip == MP_BC_FOR_ITER) {
1433                         const byte *ip = code_state->ip + 1;
1434                         DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
1435                         code_state->ip = ip + ulab; // jump to after for-block
1436                         code_state->sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator
1437                         goto outer_dispatch_loop; // continue with dispatch loop
1438                     } else if (*code_state->ip == MP_BC_YIELD_FROM) {
1439                         // StopIteration inside yield from call means return a value of
1440                         // yield from, so inject exception's value as yield from's result
1441                         // (Instead of stack pop then push we just replace exhausted gen with value)
1442                         *code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));
1443                         code_state->ip++; // yield from is over, move to next instruction
1444                         goto outer_dispatch_loop; // continue with dispatch loop
1445                     }
1446                 }
1447             }
1448 
1449             #if MICROPY_PY_SYS_SETTRACE
1450             // Exceptions are traced here
1451             if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_Exception))) {
1452                 TRACE_TICK(code_state->ip, code_state->sp, true /* yes, it's an exception */);
1453             }
1454             #endif
1455 
1456 #if MICROPY_STACKLESS
1457 unwind_loop:
1458 #endif
1459             // Set traceback info (file and line number) where the exception occurred, but not for:
1460             // - constant GeneratorExit object, because it's const
1461             // - exceptions re-raised by END_FINALLY
1462             // - exceptions re-raised explicitly by "raise"
1463             if (nlr.ret_val != &mp_const_GeneratorExit_obj
1464                 && *code_state->ip != MP_BC_END_FINALLY
1465                 && *code_state->ip != MP_BC_RAISE_LAST) {
1466                 const byte *ip = code_state->fun_bc->bytecode;
1467                 MP_BC_PRELUDE_SIG_DECODE(ip);
1468                 MP_BC_PRELUDE_SIZE_DECODE(ip);
1469                 const byte *bytecode_start = ip + n_info + n_cell;
1470                 #if !MICROPY_PERSISTENT_CODE
1471                 // so bytecode is aligned
1472                 bytecode_start = MP_ALIGN(bytecode_start, sizeof(mp_uint_t));
1473                 #endif
1474                 size_t bc = code_state->ip - bytecode_start;
1475                 #if MICROPY_PERSISTENT_CODE
1476                 qstr block_name = ip[0] | (ip[1] << 8);
1477                 qstr source_file = ip[2] | (ip[3] << 8);
1478                 ip += 4;
1479                 #else
1480                 qstr block_name = mp_decode_uint_value(ip);
1481                 ip = mp_decode_uint_skip(ip);
1482                 qstr source_file = mp_decode_uint_value(ip);
1483                 ip = mp_decode_uint_skip(ip);
1484                 #endif
1485                 size_t source_line = mp_bytecode_get_source_line(ip, bc);
1486                 mp_obj_exception_add_traceback(MP_OBJ_FROM_PTR(nlr.ret_val), source_file, source_line, block_name);
1487             }
1488 
1489             while (exc_sp >= exc_stack && exc_sp->handler <= code_state->ip) {
1490 
1491                 // nested exception
1492 
1493                 assert(exc_sp >= exc_stack);
1494 
1495                 // TODO make a proper message for nested exception
1496                 // at the moment we are just raising the very last exception (the one that caused the nested exception)
1497 
1498                 // move up to previous exception handler
1499                 POP_EXC_BLOCK();
1500             }
1501 
1502             if (exc_sp >= exc_stack) {
1503                 // catch exception and pass to byte code
1504                 code_state->ip = exc_sp->handler;
1505                 mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
1506                 // save this exception in the stack so it can be used in a reraise, if needed
1507                 exc_sp->prev_exc = nlr.ret_val;
1508                 // push exception object so it can be handled by bytecode
1509                 PUSH(MP_OBJ_FROM_PTR(nlr.ret_val));
1510                 code_state->sp = sp;
1511 
1512             #if MICROPY_STACKLESS
1513             } else if (code_state->prev != NULL) {
1514                 mp_globals_set(code_state->old_globals);
1515                 mp_code_state_t *new_code_state = code_state->prev;
1516                 #if MICROPY_ENABLE_PYSTACK
1517                 // Free code_state, and args allocated by mp_call_prepare_args_n_kw_var
1518                 // (The latter is implicitly freed when using pystack due to its LIFO nature.)
1519                 // The sizeof in the following statement does not include the size of the variable
1520                 // part of the struct.  This arg is anyway not used if pystack is enabled.
1521                 mp_nonlocal_free(code_state, sizeof(mp_code_state_t));
1522                 #endif
1523                 code_state = new_code_state;
1524                 size_t n_state = code_state->n_state;
1525                 fastn = &code_state->state[n_state - 1];
1526                 exc_stack = (mp_exc_stack_t*)(code_state->state + n_state);
1527                 // variables that are visible to the exception handler (declared volatile)
1528                 exc_sp = MP_CODE_STATE_EXC_SP_IDX_TO_PTR(exc_stack, code_state->exc_sp_idx); // stack grows up, exc_sp points to top of stack
1529                 goto unwind_loop;
1530 
1531             #endif
1532             } else {
1533                 // propagate exception to higher level
1534                 // Note: ip and sp don't have usable values at this point
1535                 code_state->state[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // put exception here because sp is invalid
1536                 FRAME_LEAVE();
1537                 return MP_VM_RETURN_EXCEPTION;
1538             }
1539         }
1540     }
1541 }
1542