Numworks Epsilon  1.4.1
Graphing Calculator Operating System
vm.c
Go to the documentation of this file.
1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2013, 2014 Damien P. George
7  * Copyright (c) 2014 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 
38 #if 0
39 #define TRACE(ip) printf("sp=%d ", (int)(sp - &code_state->state[0] + 1)); mp_bytecode_print2(ip, 1, code_state->fun_bc->const_table);
40 #else
41 #define TRACE(ip)
42 #endif
43 
44 // Value stack grows up (this makes it incompatible with native C stack, but
45 // makes sure that arguments to functions are in natural order arg1..argN
46 // (Python semantics mandates left-to-right evaluation order, including for
47 // function arguments). Stack pointer is pre-incremented and points at the
48 // top element.
49 // Exception stack also grows up, top element is also pointed at.
50 
51 // Exception stack unwind reasons (WHY_* in CPython-speak)
52 // TODO perhaps compress this to RETURN=0, JUMP>0, with number of unwinds
53 // left to do encoded in the JUMP number
54 typedef enum {
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) | currently_in_except_block); \
112  exc_sp->prev_exc = NULL; \
113  currently_in_except_block = 0; /* in a try block now */ \
114 } while (0)
115 
116 #define POP_EXC_BLOCK() \
117  currently_in_except_block = MP_TAGPTR_TAG0(exc_sp->val_sp); /* restore previous state */ \
118  exc_sp--; /* pop back to previous exception handler */ \
119  CLEAR_SYS_EXC_INFO() /* just clear sys.exc_info(), not compliant, but it shouldn't be used in 1st place */
120 
121 // fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)
122 // sp points to bottom of stack which grows up
123 // returns:
124 // MP_VM_RETURN_NORMAL, sp valid, return value in *sp
125 // MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
126 // MP_VM_RETURN_EXCEPTION, exception in fastn[0]
128 #define SELECTIVE_EXC_IP (0)
129 #if SELECTIVE_EXC_IP
130 #define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */
131 #define MARK_EXC_IP_GLOBAL()
132 #else
133 #define MARK_EXC_IP_SELECTIVE()
134 #define MARK_EXC_IP_GLOBAL() { code_state->ip = ip; } /* stores ip pointing to last opcode */
135 #endif
136 #if MICROPY_OPT_COMPUTED_GOTO
137  #include "py/vmentrytable.h"
138  #define DISPATCH() do { \
139  TRACE(ip); \
140  MARK_EXC_IP_GLOBAL(); \
141  goto *entry_table[*ip++]; \
142  } while (0)
143  #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
144  #define ENTRY(op) entry_##op
145  #define ENTRY_DEFAULT entry_default
146 #else
147  #define DISPATCH() break
148  #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
149  #define ENTRY(op) case op
150  #define ENTRY_DEFAULT default
151 #endif
152 
153  // nlr_raise needs to be implemented as a goto, so that the C compiler's flow analyser
154  // sees that it's possible for us to jump from the dispatch loop to the exception
155  // handler. Without this, the code may have a different stack layout in the dispatch
156  // loop and the exception handler, leading to very obscure bugs.
157  #define RAISE(o) do { nlr_pop(); nlr.ret_val = MP_OBJ_TO_PTR(o); goto exception_handler; } while (0)
158 
159 #if MICROPY_STACKLESS
160 run_code_state: ;
161 #endif
162  // Pointers which are constant for particular invocation of mp_execute_bytecode()
163  mp_obj_t * /*const*/ fastn;
164  mp_exc_stack_t * /*const*/ exc_stack;
165  {
166  size_t n_state = mp_decode_uint_value(code_state->fun_bc->bytecode);
167  fastn = &code_state->state[n_state - 1];
168  exc_stack = (mp_exc_stack_t*)(code_state->state + n_state);
169  }
170 
171  // variables that are visible to the exception handler (declared volatile)
172  volatile bool currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
173  mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
174 
175  #if MICROPY_PY_THREAD_GIL && MICROPY_PY_THREAD_GIL_VM_DIVISOR
176  // This needs to be volatile and outside the VM loop so it persists across handling
177  // of any exceptions. Otherwise it's possible that the VM never gives up the GIL.
178  volatile int gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
179  #endif
180 
181  // outer exception handling loop
182  for (;;) {
183  nlr_buf_t nlr;
184 outer_dispatch_loop:
185  if (nlr_push(&nlr) == 0) {
186  // local variables that are not visible to the exception handler
187  const byte *ip = code_state->ip;
188  mp_obj_t *sp = code_state->sp;
189  mp_obj_t obj_shared;
191 
192  // If we have exception to inject, now that we finish setting up
193  // execution context, raise it. This works as if RAISE_VARARGS
194  // bytecode was executed.
195  // Injecting exc into yield from generator is a special case,
196  // handled by MP_BC_YIELD_FROM itself
197  if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
198  mp_obj_t exc = inject_exc;
199  inject_exc = MP_OBJ_NULL;
200  exc = mp_make_raise_obj(exc);
201  RAISE(exc);
202  }
203 
204  // loop to execute byte code
205  for (;;) {
206 dispatch_loop:
207 #if MICROPY_OPT_COMPUTED_GOTO
208  DISPATCH();
209 #else
210  TRACE(ip);
212  switch (*ip++) {
213 #endif
214 
217  DISPATCH();
218 
221  DISPATCH();
222 
225  DISPATCH();
226 
228  mp_int_t num = 0;
229  if ((ip[0] & 0x40) != 0) {
230  // Number is negative
231  num--;
232  }
233  do {
234  num = (num << 7) | (*ip & 0x7f);
235  } while ((*ip++ & 0x80) != 0);
237  DISPATCH();
238  }
239 
241  DECODE_QSTR;
242  PUSH(MP_OBJ_NEW_QSTR(qst));
243  DISPATCH();
244  }
245 
247  DECODE_OBJ;
248  PUSH(obj);
249  DISPATCH();
250  }
251 
253  PUSH(MP_OBJ_NULL);
254  DISPATCH();
255 
257  DECODE_UINT;
258  obj_shared = fastn[-unum];
259  load_check:
260  if (obj_shared == MP_OBJ_NULL) {
261  local_name_error: {
263  mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment");
264  RAISE(obj);
265  }
266  }
267  PUSH(obj_shared);
268  DISPATCH();
269  }
270 
272  DECODE_UINT;
273  obj_shared = mp_obj_cell_get(fastn[-unum]);
274  goto load_check;
275  }
276 
277  #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
280  DECODE_QSTR;
281  PUSH(mp_load_name(qst));
282  DISPATCH();
283  }
284  #else
287  DECODE_QSTR;
288  mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
289  mp_uint_t x = *ip;
290  if (x < mp_locals_get()->map.alloc && mp_locals_get()->map.table[x].key == key) {
291  PUSH(mp_locals_get()->map.table[x].value);
292  } else {
293  mp_map_elem_t *elem = mp_map_lookup(&mp_locals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
294  if (elem != NULL) {
295  *(byte*)ip = (elem - &mp_locals_get()->map.table[0]) & 0xff;
296  PUSH(elem->value);
297  } else {
299  }
300  }
301  ip++;
302  DISPATCH();
303  }
304  #endif
305 
306  #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
309  DECODE_QSTR;
310  PUSH(mp_load_global(qst));
311  DISPATCH();
312  }
313  #else
316  DECODE_QSTR;
317  mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
318  mp_uint_t x = *ip;
319  if (x < mp_globals_get()->map.alloc && mp_globals_get()->map.table[x].key == key) {
320  PUSH(mp_globals_get()->map.table[x].value);
321  } else {
322  mp_map_elem_t *elem = mp_map_lookup(&mp_globals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
323  if (elem != NULL) {
324  *(byte*)ip = (elem - &mp_globals_get()->map.table[0]) & 0xff;
325  PUSH(elem->value);
326  } else {
328  }
329  }
330  ip++;
331  DISPATCH();
332  }
333  #endif
334 
335  #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
338  DECODE_QSTR;
339  SET_TOP(mp_load_attr(TOP(), qst));
340  DISPATCH();
341  }
342  #else
345  DECODE_QSTR;
346  mp_obj_t top = TOP();
348  mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
349  mp_uint_t x = *ip;
350  mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
351  mp_map_elem_t *elem;
352  if (x < self->members.alloc && self->members.table[x].key == key) {
353  elem = &self->members.table[x];
354  } else {
355  elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);
356  if (elem != NULL) {
357  *(byte*)ip = elem - &self->members.table[0];
358  } else {
359  goto load_attr_cache_fail;
360  }
361  }
362  SET_TOP(elem->value);
363  ip++;
364  DISPATCH();
365  }
366  load_attr_cache_fail:
367  SET_TOP(mp_load_attr(top, qst));
368  ip++;
369  DISPATCH();
370  }
371  #endif
372 
375  DECODE_QSTR;
376  mp_load_method(*sp, qst, sp);
377  sp += 1;
378  DISPATCH();
379  }
380 
383  DECODE_QSTR;
384  sp -= 1;
385  mp_load_super_method(qst, sp - 1);
386  DISPATCH();
387  }
388 
392  DISPATCH();
393 
396  mp_obj_t index = POP();
398  DISPATCH();
399  }
400 
402  DECODE_UINT;
403  fastn[-unum] = POP();
404  DISPATCH();
405  }
406 
408  DECODE_UINT;
409  mp_obj_cell_set(fastn[-unum], POP());
410  DISPATCH();
411  }
412 
415  DECODE_QSTR;
416  mp_store_name(qst, POP());
417  DISPATCH();
418  }
419 
422  DECODE_QSTR;
423  mp_store_global(qst, POP());
424  DISPATCH();
425  }
426 
427  #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
430  DECODE_QSTR;
431  mp_store_attr(sp[0], qst, sp[-1]);
432  sp -= 2;
433  DISPATCH();
434  }
435  #else
436  // This caching code works with MICROPY_PY_BUILTINS_PROPERTY and/or
437  // MICROPY_PY_DESCRIPTORS enabled because if the attr exists in
438  // self->members then it can't be a property or have descriptors. A
439  // consequence of this is that we can't use MP_MAP_LOOKUP_ADD_IF_NOT_FOUND
440  // in the fast-path below, because that store could override a property.
443  DECODE_QSTR;
444  mp_obj_t top = TOP();
445  if (mp_obj_get_type(top)->attr == mp_obj_instance_attr && sp[-1] != MP_OBJ_NULL) {
446  mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
447  mp_uint_t x = *ip;
448  mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
449  mp_map_elem_t *elem;
450  if (x < self->members.alloc && self->members.table[x].key == key) {
451  elem = &self->members.table[x];
452  } else {
453  elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);
454  if (elem != NULL) {
455  *(byte*)ip = elem - &self->members.table[0];
456  } else {
457  goto store_attr_cache_fail;
458  }
459  }
460  elem->value = sp[-1];
461  sp -= 2;
462  ip++;
463  DISPATCH();
464  }
465  store_attr_cache_fail:
466  mp_store_attr(sp[0], qst, sp[-1]);
467  sp -= 2;
468  ip++;
469  DISPATCH();
470  }
471  #endif
472 
475  mp_obj_subscr(sp[-1], sp[0], sp[-2]);
476  sp -= 3;
477  DISPATCH();
478 
481  DECODE_UINT;
482  if (fastn[-unum] == MP_OBJ_NULL) {
483  goto local_name_error;
484  }
485  fastn[-unum] = MP_OBJ_NULL;
486  DISPATCH();
487  }
488 
491  DECODE_UINT;
492  if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
493  goto local_name_error;
494  }
495  mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);
496  DISPATCH();
497  }
498 
501  DECODE_QSTR;
502  mp_delete_name(qst);
503  DISPATCH();
504  }
505 
508  DECODE_QSTR;
509  mp_delete_global(qst);
510  DISPATCH();
511  }
512 
513  ENTRY(MP_BC_DUP_TOP): {
514  mp_obj_t top = TOP();
515  PUSH(top);
516  DISPATCH();
517  }
518 
520  sp += 2;
521  sp[0] = sp[-2];
522  sp[-1] = sp[-3];
523  DISPATCH();
524 
526  sp -= 1;
527  DISPATCH();
528 
529  ENTRY(MP_BC_ROT_TWO): {
530  mp_obj_t top = sp[0];
531  sp[0] = sp[-1];
532  sp[-1] = top;
533  DISPATCH();
534  }
535 
537  mp_obj_t top = sp[0];
538  sp[0] = sp[-1];
539  sp[-1] = sp[-2];
540  sp[-2] = top;
541  DISPATCH();
542  }
543 
544  ENTRY(MP_BC_JUMP): {
546  ip += slab;
548  }
549 
552  if (mp_obj_is_true(POP())) {
553  ip += slab;
554  }
556  }
557 
560  if (!mp_obj_is_true(POP())) {
561  ip += slab;
562  }
564  }
565 
568  if (mp_obj_is_true(TOP())) {
569  ip += slab;
570  } else {
571  sp--;
572  }
574  }
575 
578  if (mp_obj_is_true(TOP())) {
579  sp--;
580  } else {
581  ip += slab;
582  }
584  }
585 
588  // stack: (..., ctx_mgr)
589  mp_obj_t obj = TOP();
590  mp_load_method(obj, MP_QSTR___exit__, sp);
591  mp_load_method(obj, MP_QSTR___enter__, sp + 2);
592  mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 2);
593  sp += 1;
594  PUSH_EXC_BLOCK(1);
595  PUSH(ret);
596  // stack: (..., __exit__, ctx_mgr, as_value)
597  DISPATCH();
598  }
599 
602  // Arriving here, there's "exception control block" on top of stack,
603  // and __exit__ method (with self) underneath it. Bytecode calls __exit__,
604  // and "deletes" it off stack, shifting "exception control block"
605  // to its place.
606  // The bytecode emitter ensures that there is enough space on the Python
607  // value stack to hold the __exit__ method plus an additional 4 entries.
608  if (TOP() == mp_const_none) {
609  // stack: (..., __exit__, ctx_mgr, None)
610  sp[1] = mp_const_none;
611  sp[2] = mp_const_none;
612  sp -= 2;
613  mp_call_method_n_kw(3, 0, sp);
615  } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
616  mp_int_t cause_val = MP_OBJ_SMALL_INT_VALUE(TOP());
617  if (cause_val == UNWIND_RETURN) {
618  // stack: (..., __exit__, ctx_mgr, ret_val, UNWIND_RETURN)
619  mp_obj_t ret_val = sp[-1];
620  sp[-1] = mp_const_none;
621  sp[0] = mp_const_none;
622  sp[1] = mp_const_none;
623  mp_call_method_n_kw(3, 0, sp - 3);
624  sp[-3] = ret_val;
626  } else {
627  assert(cause_val == UNWIND_JUMP);
628  // stack: (..., __exit__, ctx_mgr, dest_ip, num_exc, UNWIND_JUMP)
629  mp_obj_t dest_ip = sp[-2];
630  mp_obj_t num_exc = sp[-1];
631  sp[-2] = mp_const_none;
632  sp[-1] = mp_const_none;
633  sp[0] = mp_const_none;
634  mp_call_method_n_kw(3, 0, sp - 4);
635  sp[-4] = dest_ip;
636  sp[-3] = num_exc;
638  }
639  sp -= 2; // we removed (__exit__, ctx_mgr)
640  } else {
642  // stack: (..., __exit__, ctx_mgr, exc_instance)
643  // Need to pass (exc_type, exc_instance, None) as arguments to __exit__.
644  sp[1] = sp[0];
645  sp[0] = MP_OBJ_FROM_PTR(mp_obj_get_type(sp[0]));
646  sp[2] = mp_const_none;
647  sp -= 2;
648  mp_obj_t ret_value = mp_call_method_n_kw(3, 0, sp);
649  if (mp_obj_is_true(ret_value)) {
650  // We need to silence/swallow the exception. This is done
651  // by popping the exception and the __exit__ handler and
652  // replacing it with None, which signals END_FINALLY to just
653  // execute the finally handler normally.
655  assert(exc_sp >= exc_stack);
656  POP_EXC_BLOCK();
657  } else {
658  // We need to re-raise the exception. We pop __exit__ handler
659  // by copying the exception instance down to the new top-of-stack.
660  sp[0] = sp[3];
661  }
662  }
663  DISPATCH();
664  }
665 
669  PUSH((mp_obj_t)(mp_uint_t)(uintptr_t)(ip + slab)); // push destination ip for jump
670  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)
671 unwind_jump:;
672  mp_uint_t unum = (mp_uint_t)POP(); // get number of exception handlers to unwind
673  while ((unum & 0x7f) > 0) {
674  unum -= 1;
675  assert(exc_sp >= exc_stack);
676  if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
677  // Getting here the stack looks like:
678  // (..., X, dest_ip)
679  // where X is pointed to by exc_sp->val_sp and in the case
680  // of a "with" block contains the context manager info.
681  // We're going to run "finally" code as a coroutine
682  // (not calling it recursively). Set up a sentinel
683  // on a stack so it can return back to us when it is
684  // done (when WITH_CLEANUP or END_FINALLY reached).
685  PUSH((mp_obj_t)unum); // push number of exception handlers left to unwind
686  PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
687  ip = exc_sp->handler; // get exception handler byte code address
688  exc_sp--; // pop exception handler
689  goto dispatch_loop; // run the exception handler
690  }
691  POP_EXC_BLOCK();
692  }
693  ip = (const byte*)MP_OBJ_TO_PTR(POP()); // pop destination ip for jump
694  if (unum != 0) {
695  // pop the exhausted iterator
697  }
699  }
700 
701  // matched against: POP_BLOCK or POP_EXCEPT (anything else?)
705  #if SELECTIVE_EXC_IP
706  PUSH_EXC_BLOCK((code_state->ip[-1] == MP_BC_SETUP_FINALLY) ? 1 : 0);
707  #else
708  PUSH_EXC_BLOCK((code_state->ip[0] == MP_BC_SETUP_FINALLY) ? 1 : 0);
709  #endif
710  DISPATCH();
711  }
712 
715  // if TOS is None, just pops it and continues
716  // if TOS is an integer, finishes coroutine and returns control to caller
717  // if TOS is an exception, reraises the exception
718  if (TOP() == mp_const_none) {
719  sp--;
720  } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
721  // We finished "finally" coroutine and now dispatch back
722  // to our caller, based on TOS value
724  if (reason == UNWIND_RETURN) {
725  goto unwind_return;
726  } else {
727  assert(reason == UNWIND_JUMP);
728  goto unwind_jump;
729  }
730  } else {
732  RAISE(TOP());
733  }
734  DISPATCH();
735 
738  SET_TOP(mp_getiter(TOP(), NULL));
739  DISPATCH();
740 
741  // An iterator for a for-loop takes MP_OBJ_ITER_BUF_NSLOTS slots on
742  // the Python value stack. These slots are either used to store the
743  // iterator object itself, or the first slot is MP_OBJ_NULL and
744  // the second slot holds a reference to the iterator object.
747  mp_obj_t obj = TOP();
748  mp_obj_iter_buf_t *iter_buf = (mp_obj_iter_buf_t*)sp;
749  sp += MP_OBJ_ITER_BUF_NSLOTS - 1;
750  obj = mp_getiter(obj, iter_buf);
751  if (obj != MP_OBJ_FROM_PTR(iter_buf)) {
752  // Iterator didn't use the stack so indicate that with MP_OBJ_NULL.
754  sp[-MP_OBJ_ITER_BUF_NSLOTS + 2] = obj;
755  }
756  DISPATCH();
757  }
758 
761  DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
762  code_state->sp = sp;
763  mp_obj_t obj;
764  if (sp[-MP_OBJ_ITER_BUF_NSLOTS + 1] == MP_OBJ_NULL) {
765  obj = sp[-MP_OBJ_ITER_BUF_NSLOTS + 2];
766  } else {
767  obj = MP_OBJ_FROM_PTR(&sp[-MP_OBJ_ITER_BUF_NSLOTS + 1]);
768  }
769  mp_obj_t value = mp_iternext_allow_raise(obj);
770  if (value == MP_OBJ_STOP_ITERATION) {
771  sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator
772  ip += ulab; // jump to after for-block
773  } else {
774  PUSH(value); // push the next iteration value
775  }
776  DISPATCH();
777  }
778 
779  // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
781  // we are exiting an exception handler, so pop the last one of the exception-stack
782  assert(exc_sp >= exc_stack);
783  POP_EXC_BLOCK();
784  DISPATCH();
785 
786  // matched against: SETUP_EXCEPT
788  assert(exc_sp >= exc_stack);
789  assert(currently_in_except_block);
790  POP_EXC_BLOCK();
791  DISPATCH();
792 
795  DECODE_UINT;
796  sp -= unum - 1;
797  SET_TOP(mp_obj_new_tuple(unum, sp));
798  DISPATCH();
799  }
800 
803  DECODE_UINT;
804  sp -= unum - 1;
805  SET_TOP(mp_obj_new_list(unum, sp));
806  DISPATCH();
807  }
808 
811  DECODE_UINT;
812  PUSH(mp_obj_new_dict(unum));
813  DISPATCH();
814  }
815 
818  sp -= 2;
819  mp_obj_dict_store(sp[0], sp[2], sp[1]);
820  DISPATCH();
821 
822 #if MICROPY_PY_BUILTINS_SET
825  DECODE_UINT;
826  sp -= unum - 1;
827  SET_TOP(mp_obj_new_set(unum, sp));
828  DISPATCH();
829  }
830 #endif
831 
832 #if MICROPY_PY_BUILTINS_SLICE
835  DECODE_UINT;
836  if (unum == 2) {
837  mp_obj_t stop = POP();
838  mp_obj_t start = TOP();
840  } else {
841  mp_obj_t step = POP();
842  mp_obj_t stop = POP();
843  mp_obj_t start = TOP();
844  SET_TOP(mp_obj_new_slice(start, stop, step));
845  }
846  DISPATCH();
847  }
848 #endif
849 
852  DECODE_UINT;
853  mp_obj_t obj = sp[-(unum >> 2)];
854  if ((unum & 3) == 0) {
855  mp_obj_list_append(obj, sp[0]);
856  sp--;
857  } else if (!MICROPY_PY_BUILTINS_SET || (unum & 3) == 1) {
858  mp_obj_dict_store(obj, sp[0], sp[-1]);
859  sp -= 2;
860  #if MICROPY_PY_BUILTINS_SET
861  } else {
862  mp_obj_set_store(obj, sp[0]);
863  sp--;
864  #endif
865  }
866  DISPATCH();
867  }
868 
871  DECODE_UINT;
872  mp_unpack_sequence(sp[0], unum, sp);
873  sp += unum - 1;
874  DISPATCH();
875  }
876 
879  DECODE_UINT;
880  mp_unpack_ex(sp[0], unum, sp);
881  sp += (unum & 0xff) + ((unum >> 8) & 0xff);
882  DISPATCH();
883  }
884 
886  DECODE_PTR;
888  DISPATCH();
889  }
890 
892  DECODE_PTR;
893  // Stack layout: def_tuple def_dict <- TOS
894  mp_obj_t def_dict = POP();
895  SET_TOP(mp_make_function_from_raw_code(ptr, TOP(), def_dict));
896  DISPATCH();
897  }
898 
900  DECODE_PTR;
901  size_t n_closed_over = *ip++;
902  // Stack layout: closed_overs <- TOS
903  sp -= n_closed_over - 1;
904  SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp));
905  DISPATCH();
906  }
907 
909  DECODE_PTR;
910  size_t n_closed_over = *ip++;
911  // Stack layout: def_tuple def_dict closed_overs <- TOS
912  sp -= 2 + n_closed_over - 1;
913  SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp));
914  DISPATCH();
915  }
916 
919  DECODE_UINT;
920  // unum & 0xff == n_positional
921  // (unum >> 8) & 0xff == n_keyword
922  sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
923  #if MICROPY_STACKLESS
924  if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
925  code_state->ip = ip;
926  code_state->sp = sp;
927  code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
928  mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1);
929  if (new_state) {
930  new_state->prev = code_state;
931  code_state = new_state;
932  nlr_pop();
933  goto run_code_state;
934  }
935  #if MICROPY_STACKLESS_STRICT
936  else {
937  deep_recursion_error:
939  }
940  #endif
941  }
942  #endif
943  SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
944  DISPATCH();
945  }
946 
949  DECODE_UINT;
950  // unum & 0xff == n_positional
951  // (unum >> 8) & 0xff == n_keyword
952  // We have following stack layout here:
953  // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
954  sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
955  #if MICROPY_STACKLESS
956  if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
957  code_state->ip = ip;
958  code_state->sp = sp;
959  code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
960 
961  mp_call_args_t out_args;
962  mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args);
963 
965  out_args.n_args, out_args.n_kw, out_args.args);
966  m_del(mp_obj_t, out_args.args, out_args.n_alloc);
967  if (new_state) {
968  new_state->prev = code_state;
969  code_state = new_state;
970  nlr_pop();
971  goto run_code_state;
972  }
973  #if MICROPY_STACKLESS_STRICT
974  else {
975  goto deep_recursion_error;
976  }
977  #endif
978  }
979  #endif
980  SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
981  DISPATCH();
982  }
983 
986  DECODE_UINT;
987  // unum & 0xff == n_positional
988  // (unum >> 8) & 0xff == n_keyword
989  sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
990  #if MICROPY_STACKLESS
991  if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
992  code_state->ip = ip;
993  code_state->sp = sp;
994  code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
995 
996  size_t n_args = unum & 0xff;
997  size_t n_kw = (unum >> 8) & 0xff;
998  int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1;
999 
1000  mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust);
1001  if (new_state) {
1002  new_state->prev = code_state;
1003  code_state = new_state;
1004  nlr_pop();
1005  goto run_code_state;
1006  }
1007  #if MICROPY_STACKLESS_STRICT
1008  else {
1009  goto deep_recursion_error;
1010  }
1011  #endif
1012  }
1013  #endif
1014  SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
1015  DISPATCH();
1016  }
1017 
1020  DECODE_UINT;
1021  // unum & 0xff == n_positional
1022  // (unum >> 8) & 0xff == n_keyword
1023  // We have following stack layout here:
1024  // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
1025  sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
1026  #if MICROPY_STACKLESS
1027  if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
1028  code_state->ip = ip;
1029  code_state->sp = sp;
1030  code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
1031 
1032  mp_call_args_t out_args;
1033  mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args);
1034 
1035  mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
1036  out_args.n_args, out_args.n_kw, out_args.args);
1037  m_del(mp_obj_t, out_args.args, out_args.n_alloc);
1038  if (new_state) {
1039  new_state->prev = code_state;
1040  code_state = new_state;
1041  nlr_pop();
1042  goto run_code_state;
1043  }
1044  #if MICROPY_STACKLESS_STRICT
1045  else {
1046  goto deep_recursion_error;
1047  }
1048  #endif
1049  }
1050  #endif
1051  SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
1052  DISPATCH();
1053  }
1054 
1057  // These next 3 lines pop a try-finally exception handler, if one
1058  // is there on the exception stack. Without this the finally block
1059  // is executed a second time when the return is executed, because
1060  // the try-finally exception handler is still on the stack.
1061  // TODO Possibly find a better way to handle this case.
1062  if (currently_in_except_block) {
1063  POP_EXC_BLOCK();
1064  }
1065 unwind_return:
1066  while (exc_sp >= exc_stack) {
1067  if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
1068  // Getting here the stack looks like:
1069  // (..., X, [iter0, iter1, ...,] ret_val)
1070  // where X is pointed to by exc_sp->val_sp and in the case
1071  // of a "with" block contains the context manager info.
1072  // There may be 0 or more for-iterators between X and the
1073  // return value, and these must be removed before control can
1074  // pass to the finally code. We simply copy the ret_value down
1075  // over these iterators, if they exist. If they don't then the
1076  // following is a null operation.
1077  mp_obj_t *finally_sp = MP_TAGPTR_PTR(exc_sp->val_sp);
1078  finally_sp[1] = sp[0];
1079  sp = &finally_sp[1];
1080  // We're going to run "finally" code as a coroutine
1081  // (not calling it recursively). Set up a sentinel
1082  // on a stack so it can return back to us when it is
1083  // done (when WITH_CLEANUP or END_FINALLY reached).
1085  ip = exc_sp->handler;
1086  exc_sp--;
1087  goto dispatch_loop;
1088  }
1089  exc_sp--;
1090  }
1091  nlr_pop();
1092  code_state->sp = sp;
1093  assert(exc_sp == exc_stack - 1);
1095  #if MICROPY_STACKLESS
1096  if (code_state->prev != NULL) {
1097  mp_obj_t res = *sp;
1098  mp_globals_set(code_state->old_globals);
1099  code_state = code_state->prev;
1100  *code_state->sp = res;
1101  goto run_code_state;
1102  }
1103  #endif
1104  return MP_VM_RETURN_NORMAL;
1105 
1108  mp_uint_t unum = *ip++;
1109  mp_obj_t obj;
1110  if (unum == 2) {
1111  mp_warning("exception chaining not supported");
1112  // ignore (pop) "from" argument
1113  sp--;
1114  }
1115  if (unum == 0) {
1116  // search for the inner-most previous exception, to reraise it
1117  obj = MP_OBJ_NULL;
1118  for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
1119  if (e->prev_exc != NULL) {
1120  obj = MP_OBJ_FROM_PTR(e->prev_exc);
1121  break;
1122  }
1123  }
1124  if (obj == MP_OBJ_NULL) {
1125  obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "no active exception to reraise");
1126  RAISE(obj);
1127  }
1128  } else {
1129  obj = POP();
1130  }
1131  obj = mp_make_raise_obj(obj);
1132  RAISE(obj);
1133  }
1134 
1136 yield:
1137  nlr_pop();
1138  code_state->ip = ip;
1139  code_state->sp = sp;
1140  code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
1141  return MP_VM_RETURN_YIELD;
1142 
1145 //#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
1146 #define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
1147 #define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { RAISE(t); }
1148  mp_vm_return_kind_t ret_kind;
1149  mp_obj_t send_value = POP();
1150  mp_obj_t t_exc = MP_OBJ_NULL;
1151  mp_obj_t ret_value;
1152  if (inject_exc != MP_OBJ_NULL) {
1153  t_exc = inject_exc;
1154  inject_exc = MP_OBJ_NULL;
1155  ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
1156  } else {
1157  ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
1158  }
1159 
1160  if (ret_kind == MP_VM_RETURN_YIELD) {
1161  ip--;
1162  PUSH(ret_value);
1163  goto yield;
1164  } else if (ret_kind == MP_VM_RETURN_NORMAL) {
1165  // Pop exhausted gen
1166  sp--;
1167  // TODO: When ret_value can be MP_OBJ_NULL here??
1168  if (ret_value == MP_OBJ_NULL || ret_value == MP_OBJ_STOP_ITERATION) {
1169  // Optimize StopIteration
1170  // TODO: get StopIteration's value
1172  } else {
1173  PUSH(ret_value);
1174  }
1175 
1176  // If we injected GeneratorExit downstream, then even
1177  // if it was swallowed, we re-raise GeneratorExit
1178  GENERATOR_EXIT_IF_NEEDED(t_exc);
1179  DISPATCH();
1180  } else {
1181  assert(ret_kind == MP_VM_RETURN_EXCEPTION);
1182  // Pop exhausted gen
1183  sp--;
1184  if (EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
1185  PUSH(mp_obj_exception_get_value(ret_value));
1186  // If we injected GeneratorExit downstream, then even
1187  // if it was swallowed, we re-raise GeneratorExit
1188  GENERATOR_EXIT_IF_NEEDED(t_exc);
1189  DISPATCH();
1190  } else {
1191  RAISE(ret_value);
1192  }
1193  }
1194  }
1195 
1198  DECODE_QSTR;
1199  mp_obj_t obj = POP();
1200  SET_TOP(mp_import_name(qst, obj, TOP()));
1201  DISPATCH();
1202  }
1203 
1206  DECODE_QSTR;
1207  mp_obj_t obj = mp_import_from(TOP(), qst);
1208  PUSH(obj);
1209  DISPATCH();
1210  }
1211 
1214  mp_import_all(POP());
1215  DISPATCH();
1216 
1217 #if MICROPY_OPT_COMPUTED_GOTO
1220  DISPATCH();
1221 
1223  obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1224  goto load_check;
1225 
1227  fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1228  DISPATCH();
1229 
1233  DISPATCH();
1234 
1237  mp_obj_t rhs = POP();
1238  mp_obj_t lhs = TOP();
1239  SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1240  DISPATCH();
1241  }
1242 
1243  ENTRY_DEFAULT:
1245 #else
1246  ENTRY_DEFAULT:
1247  if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
1249  DISPATCH();
1250  } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
1251  obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
1252  goto load_check;
1253  } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
1254  fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
1255  DISPATCH();
1256  } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 7) {
1258  DISPATCH();
1259  } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) {
1260  mp_obj_t rhs = POP();
1261  mp_obj_t lhs = TOP();
1262  SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
1263  DISPATCH();
1264  } else
1265 #endif
1266  {
1267  mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
1268  nlr_pop();
1269  fastn[0] = obj;
1270  return MP_VM_RETURN_EXCEPTION;
1271  }
1272 
1273 #if !MICROPY_OPT_COMPUTED_GOTO
1274  } // switch
1275 #endif
1276 
1277 pending_exception_check:
1279 
1280  #if MICROPY_ENABLE_SCHEDULER
1281  // This is an inlined variant of mp_handle_pending
1282  if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) {
1284  mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
1285  mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
1286  if (obj != MP_OBJ_NULL) {
1287  MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
1288  if (!mp_sched_num_pending()) {
1289  MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
1290  }
1291  MICROPY_END_ATOMIC_SECTION(atomic_state);
1292  RAISE(obj);
1293  }
1294  mp_handle_pending_tail(atomic_state);
1295  }
1296  #else
1297  // This is an inlined variant of mp_handle_pending
1298  if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
1300  mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
1301  MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
1302  RAISE(obj);
1303  }
1304  #endif
1305 
1306  #if MICROPY_PY_THREAD_GIL
1307  #if MICROPY_PY_THREAD_GIL_VM_DIVISOR
1308  if (--gil_divisor == 0) {
1309  gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
1310  #else
1311  {
1312  #endif
1313  #if MICROPY_ENABLE_SCHEDULER
1314  // can only switch threads if the scheduler is unlocked
1315  if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE)
1316  #endif
1317  {
1320  }
1321  }
1322  #endif
1323 
1324  } // for loop
1325 
1326  } else {
1327 exception_handler:
1328  // exception occurred
1329 
1330  #if MICROPY_PY_SYS_EXC_INFO
1331  MP_STATE_VM(cur_exception) = nlr.ret_val;
1332  #endif
1333 
1334  #if SELECTIVE_EXC_IP
1335  // with selective ip, we store the ip 1 byte past the opcode, so move ptr back
1336  code_state->ip -= 1;
1337  #endif
1338 
1340  if (code_state->ip) {
1341  // check if it's a StopIteration within a for block
1342  if (*code_state->ip == MP_BC_FOR_ITER) {
1343  const byte *ip = code_state->ip + 1;
1344  DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
1345  code_state->ip = ip + ulab; // jump to after for-block
1346  code_state->sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator
1347  goto outer_dispatch_loop; // continue with dispatch loop
1348  } else if (*code_state->ip == MP_BC_YIELD_FROM) {
1349  // StopIteration inside yield from call means return a value of
1350  // yield from, so inject exception's value as yield from's result
1351  *++code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));
1352  code_state->ip++; // yield from is over, move to next instruction
1353  goto outer_dispatch_loop; // continue with dispatch loop
1354  }
1355  }
1356  }
1357 
1358 #if MICROPY_STACKLESS
1359 unwind_loop:
1360 #endif
1361  // set file and line number that the exception occurred at
1362  // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
1363  // But consider how to handle nested exceptions.
1364  // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
1366  const byte *ip = code_state->fun_bc->bytecode;
1367  ip = mp_decode_uint_skip(ip); // skip n_state
1368  ip = mp_decode_uint_skip(ip); // skip n_exc_stack
1369  ip++; // skip scope_params
1370  ip++; // skip n_pos_args
1371  ip++; // skip n_kwonly_args
1372  ip++; // skip n_def_pos_args
1373  size_t bc = code_state->ip - ip;
1374  size_t code_info_size = mp_decode_uint_value(ip);
1375  ip = mp_decode_uint_skip(ip); // skip code_info_size
1376  bc -= code_info_size;
1377  #if MICROPY_PERSISTENT_CODE
1378  qstr block_name = ip[0] | (ip[1] << 8);
1379  qstr source_file = ip[2] | (ip[3] << 8);
1380  ip += 4;
1381  #else
1382  qstr block_name = mp_decode_uint_value(ip);
1383  ip = mp_decode_uint_skip(ip);
1384  qstr source_file = mp_decode_uint_value(ip);
1385  ip = mp_decode_uint_skip(ip);
1386  #endif
1387  size_t source_line = 1;
1388  size_t c;
1389  while ((c = *ip)) {
1390  size_t b, l;
1391  if ((c & 0x80) == 0) {
1392  // 0b0LLBBBBB encoding
1393  b = c & 0x1f;
1394  l = c >> 5;
1395  ip += 1;
1396  } else {
1397  // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
1398  b = c & 0xf;
1399  l = ((c << 4) & 0x700) | ip[1];
1400  ip += 2;
1401  }
1402  if (bc >= b) {
1403  bc -= b;
1404  source_line += l;
1405  } else {
1406  // found source line corresponding to bytecode offset
1407  break;
1408  }
1409  }
1410  mp_obj_exception_add_traceback(MP_OBJ_FROM_PTR(nlr.ret_val), source_file, source_line, block_name);
1411  }
1412 
1413  while (currently_in_except_block) {
1414  // nested exception
1415 
1416  assert(exc_sp >= exc_stack);
1417 
1418  // TODO make a proper message for nested exception
1419  // at the moment we are just raising the very last exception (the one that caused the nested exception)
1420 
1421  // move up to previous exception handler
1422  POP_EXC_BLOCK();
1423  }
1424 
1425  if (exc_sp >= exc_stack) {
1426  // set flag to indicate that we are now handling an exception
1427  currently_in_except_block = 1;
1428 
1429  // catch exception and pass to byte code
1430  code_state->ip = exc_sp->handler;
1431  mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
1432  // save this exception in the stack so it can be used in a reraise, if needed
1433  exc_sp->prev_exc = nlr.ret_val;
1434  // push exception object so it can be handled by bytecode
1436  code_state->sp = sp;
1437 
1438  #if MICROPY_STACKLESS
1439  } else if (code_state->prev != NULL) {
1440  mp_globals_set(code_state->old_globals);
1441  code_state = code_state->prev;
1442  size_t n_state = mp_decode_uint_value(code_state->fun_bc->bytecode);
1443  fastn = &code_state->state[n_state - 1];
1444  exc_stack = (mp_exc_stack_t*)(code_state->state + n_state);
1445  // variables that are visible to the exception handler (declared volatile)
1446  currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
1447  exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
1448  goto unwind_loop;
1449 
1450  #endif
1451  } else {
1452  // propagate exception to higher level
1453  // TODO what to do about ip and sp? they don't really make sense at this point
1454  fastn[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // must put exception here because sp is invalid
1455  return MP_VM_RETURN_EXCEPTION;
1456  }
1457  }
1458  }
1459 }
#define MP_BC_CALL_FUNCTION_VAR_KW
Definition: bc0.h:105
#define MP_BC_LOAD_CONST_FALSE
Definition: bc0.h:32
#define MP_BC_BUILD_SET
Definition: bc0.h:89
#define MP_BC_BUILD_MAP
Definition: bc0.h:87
#define MP_BC_BUILD_TUPLE
Definition: bc0.h:85
const mp_obj_type_t mp_type_fun_bc
Definition: objfun.c:331
#define MP_BC_LOAD_NAME
Definition: bc0.h:42
Definition: vm.c:56
const struct _mp_obj_exception_t mp_const_MemoryError_obj
Definition: objexcept.c:47
#define MP_BC_STORE_NAME
Definition: bc0.h:52
mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg)
Definition: runtime.c:216
intptr_t mp_int_t
Definition: mpconfigport.h:73
mp_obj_dict_t * old_globals
Definition: bc.h:82
#define MARK_EXC_IP_SELECTIVE()
uintptr_t mp_uint_t
Definition: mpconfigport.h:74
bool mp_obj_is_exception_instance(mp_obj_t self_in)
Definition: objexcept.c:451
#define MP_BC_STORE_COMP
Definition: bc0.h:91
const byte * ip
Definition: bc.h:78
#define MP_BC_LOAD_DEREF
Definition: bc0.h:41
mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step)
#define MP_BC_RAISE_VARARGS
Definition: bc0.h:96
mp_obj_t state[0]
Definition: bc.h:87
mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items)
Definition: objtuple.c:235
#define MP_BC_GET_ITER_STACK
Definition: bc0.h:83
#define DECODE_QSTR
Definition: vm.c:81
#define MP_BC_LOAD_NULL
Definition: bc0.h:38
#define assert(e)
Definition: assert.h:9
#define mp_const_none
Definition: obj.h:614
#define MP_BC_UNARY_OP_MULTI
Definition: bc0.h:116
#define MP_BC_IMPORT_FROM
Definition: bc0.h:110
#define MP_BC_LOAD_SUPER_METHOD
Definition: bc0.h:46
#define MP_BC_STORE_ATTR
Definition: bc0.h:54
#define DECODE_UINT
Definition: vm.c:59
mp_obj_t mp_import_from(mp_obj_t module, qstr name)
Definition: runtime.c:1336
#define DECODE_OBJ
Definition: vm.c:89
STATIC const uint8_t attr[]
Definition: unicode.c:51
#define MP_BC_BINARY_OP_MULTI
Definition: bc0.h:117
#define m_del(type, ptr, num)
Definition: misc.h:77
#define nlr_push(buf)
Definition: nlr.h:73
#define MP_BC_LOAD_CONST_SMALL_INT_MULTI
Definition: bc0.h:113
void mp_load_super_method(qstr attr, mp_obj_t *dest)
Definition: objtype.c:1133
void mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items)
Definition: runtime.c:827
mp_exc_stack_t * exc_sp
Definition: bc.h:81
#define MP_OBJ_QSTR_VALUE(o)
Definition: obj.h:91
const mp_obj_type_t mp_type_StopIteration
void mp_delete_global(qstr qst)
Definition: runtime.c:210
#define MP_BC_DUP_TOP_TWO
Definition: bc0.h:63
#define MP_BC_LOAD_CONST_NONE
Definition: bc0.h:33
#define EXC_MATCH(exc, type)
#define MP_OBJ_SENTINEL
Definition: obj.h:75
mp_obj_type_t * mp_obj_get_type(mp_const_obj_t o_in)
Definition: obj.c:40
const mp_obj_type_t mp_type_NotImplementedError
unsigned int uintptr_t
Definition: stdint.h:14
#define MP_BC_LOAD_BUILD_CLASS
Definition: bc0.h:47
#define MP_OBJ_FROM_PTR(p)
Definition: obj.h:233
mp_obj_fun_bc_t * fun_bc
Definition: bc.h:77
#define MP_BC_IMPORT_NAME
Definition: bc0.h:109
#define POP()
Definition: vm.c:97
#define MP_OBJ_NEW_QSTR(qst)
Definition: obj.h:92
mp_obj_t mp_load_attr(mp_obj_t base, qstr attr)
Definition: runtime.c:930
#define MP_BC_MAKE_FUNCTION_DEFARGS
Definition: bc0.h:101
#define MP_BC_POP_EXCEPT
Definition: bc0.h:81
#define MP_BC_STORE_MAP
Definition: bc0.h:88
#define MP_BC_MAKE_CLOSURE_DEFARGS
Definition: bc0.h:103
#define mp_const_true
Definition: obj.h:616
#define MP_BC_LOAD_CONST_TRUE
Definition: bc0.h:34
#define MP_BC_DELETE_DEREF
Definition: bc0.h:58
mp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items)
Definition: objlist.c:470
mp_obj_base_t * prev_exc
Definition: bc.h:69
#define MICROPY_VM_HOOK_INIT
Definition: mpconfig.h:421
#define MP_STATE_VM(x)
Definition: mpstate.h:241
#define MP_BC_CALL_METHOD_VAR_KW
Definition: bc0.h:107
#define MP_BC_CALL_FUNCTION
Definition: bc0.h:104
#define MP_BC_POP_TOP
Definition: bc0.h:64
mp_obj_t mp_load_global(qstr qst)
Definition: runtime.c:153
#define MP_BC_POP_JUMP_IF_FALSE
Definition: bc0.h:70
#define MP_BC_BUILD_SLICE
Definition: bc0.h:90
#define MP_OBJ_SMALL_INT_VALUE(o)
Definition: obj.h:86
#define MP_SCHED_IDLE
Definition: mpstate.h:54
#define MP_BC_DELETE_NAME
Definition: bc0.h:59
#define MP_BC_JUMP_IF_TRUE_OR_POP
Definition: bc0.h:71
#define MP_BC_LOAD_GLOBAL
Definition: bc0.h:43
#define MP_BC_MAKE_CLOSURE
Definition: bc0.h:102
mp_obj_t mp_obj_new_dict(size_t n_args)
Definition: objdict.c:584
const mp_obj_type_t mp_type_NameError
bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo)
Definition: objtype.c:1143
void mp_store_name(qstr qst, mp_obj_t obj)
Definition: runtime.c:194
NORETURN void mp_exc_recursion_depth(void)
void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest)
Definition: runtime.c:1076
mp_map_elem_t * mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind)
Definition: map.c:138
#define MICROPY_PY_BUILTINS_SET
Definition: mpconfigport.h:41
#define MP_BC_DELETE_GLOBAL
Definition: bc0.h:60
#define MP_BC_UNPACK_SEQUENCE
Definition: bc0.h:92
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg)
Definition: objlist.c:234
mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg)
Definition: objexcept.c:343
mp_obj_t mp_load_name(qstr qst)
Definition: runtime.c:140
#define MP_BC_STORE_GLOBAL
Definition: bc0.h:53
mp_vm_return_kind_t
Definition: runtime.h:31
c(generic_all_nodes)
#define MP_OBJ_NEW_SMALL_INT(small_int)
Definition: obj.h:87
#define MICROPY_BEGIN_ATOMIC_SECTION()
Definition: mpconfig.h:1169
void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item)
#define GENERATOR_EXIT_IF_NEEDED(t)
#define TRACE(ip)
Definition: vm.c:41
#define MP_TAGPTR_TAG0(x)
Definition: bc.h:106
#define MICROPY_PY_THREAD_GIL_VM_DIVISOR
Definition: mpconfig.h:1041
#define MP_OBJ_ITER_BUF_NSLOTS
Definition: obj.h:428
#define MP_BC_DELETE_FAST
Definition: bc0.h:57
#define MP_BC_ROT_TWO
Definition: bc0.h:65
const byte * handler
Definition: bc.h:64
#define NULL
Definition: stddef.h:4
#define MP_OBJ_NULL
Definition: obj.h:73
#define MP_BC_LOAD_ATTR
Definition: bc0.h:44
#define MP_BC_LOAD_SUBSCR
Definition: bc0.h:48
#define MICROPY_VM_HOOK_LOOP
Definition: mpconfigport.h:61
#define DECODE_ULABEL
Definition: vm.c:64
#define MP_TAGPTR_PTR(x)
Definition: bc.h:105
size_t qstr
Definition: qstr.h:48
mp_obj_t mp_make_closure_from_raw_code(const mp_raw_code_t *rc, mp_uint_t n_closed_over, const mp_obj_t *args)
Definition: emitglue.c:157
mp_uint_t mp_decode_uint_value(const byte *ptr)
Definition: bc.c:61
mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args)
Definition: emitglue.c:116
mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs)
Definition: runtime.c:277
#define MP_BC_UNWIND_JUMP
Definition: bc0.h:82
mp_obj_t value
Definition: obj.h:343
mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items)
#define MP_BC_LOAD_CONST_OBJ
Definition: bc0.h:37
#define DISPATCH_WITH_PEND_EXC_CHECK()
#define MP_BC_CALL_METHOD
Definition: bc0.h:106
mp_obj_t mp_load_build_class(void)
Definition: runtime.c:180
#define MARK_EXC_IP_GLOBAL()
#define PUSH(val)
Definition: vm.c:96
#define MP_BC_JUMP
Definition: bc0.h:68
#define MP_BC_JUMP_IF_FALSE_OR_POP
Definition: bc0.h:72
mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in)
Definition: runtime.c:1162
mp_obj_t * val_sp
Definition: bc.h:67
mp_obj_t * sp
Definition: bc.h:79
#define MP_BC_FOR_ITER
Definition: bc0.h:79
#define MP_TAGPTR_TAG1(x)
Definition: bc.h:107
const byte * bytecode
Definition: objfun.h:34
mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args)
Definition: runtime.c:816
#define MICROPY_VM_HOOK_RETURN
Definition: mpconfig.h:431
#define MP_BC_POP_BLOCK
Definition: bc0.h:80
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qstr block)
Definition: objexcept.c:485
#define SET_TOP(val)
Definition: vm.c:99
#define MP_BC_GET_ITER
Definition: bc0.h:78
#define nlr_pop()
Definition: nlr.h:74
#define MP_BC_WITH_CLEANUP
Definition: bc0.h:74
#define MP_BC_SETUP_WITH
Definition: bc0.h:73
mp_obj_t fun
Definition: runtime.h:113
unsigned char byte
Definition: misc.h:37
void * ret_val
Definition: nlr.h:42
#define DECODE_PTR
Definition: vm.c:85
#define PUSH_EXC_BLOCK(with_or_finally)
Definition: vm.c:107
#define MP_BC_ROT_THREE
Definition: bc0.h:66
#define DECODE_SLABEL
Definition: vm.c:65
#define MP_BC_UNPACK_EX
Definition: bc0.h:93
#define MP_BC_SETUP_EXCEPT
Definition: bc0.h:75
#define MP_BC_LOAD_METHOD
Definition: bc0.h:45
void start()
Definition: rt0.cpp:31
#define MP_BC_LOAD_CONST_SMALL_INT
Definition: bc0.h:35
mp_code_state_t * mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args)
mp_obj_t mp_call_method_n_kw(size_t n_args, size_t n_kw, const mp_obj_t *args)
Definition: runtime.c:639
#define MP_BC_LOAD_FAST_MULTI
Definition: bc0.h:114
void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj)
Definition: objcell.c:39
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value)
Definition: objdict.c:595
#define MP_BC_STORE_FAST_MULTI
Definition: bc0.h:115
#define mp_warning(...)
Definition: runtime.h:177
#define MP_BC_DUP_TOP
Definition: bc0.h:62
mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in)
Definition: objexcept.c:183
STATIC void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args, mp_call_args_t *out_args)
Definition: runtime.c:649
mp_obj_t mp_make_raise_obj(mp_obj_t o)
Definition: runtime.c:1304
#define MP_OBJ_TO_PTR(o)
Definition: obj.h:228
Definition: nlr.h:39
#define MP_BC_MAKE_FUNCTION
Definition: bc0.h:100
size_t n_kw
Definition: runtime.h:114
#define MP_BC_END_FINALLY
Definition: bc0.h:77
#define MP_THREAD_GIL_EXIT()
Definition: mpthread.h:58
void mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items)
Definition: runtime.c:874
#define MP_BC_STORE_FAST_N
Definition: bc0.h:50
mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level)
Definition: runtime.c:1321
mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf)
Definition: runtime.c:1120
void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value)
Definition: runtime.c:1100
#define MICROPY_END_ATOMIC_SECTION(state)
Definition: mpconfig.h:1172
mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val)
Definition: runtime.c:1221
#define MP_BC_STORE_SUBSCR
Definition: bc0.h:55
#define DISPATCH()
#define ENTRY(op)
#define MP_OBJ_STOP_ITERATION
Definition: obj.h:74
#define MP_BC_SETUP_FINALLY
Definition: bc0.h:76
#define TOP()
Definition: vm.c:98
void mp_handle_pending_tail(mp_uint_t atomic_state)
const byte * mp_decode_uint_skip(const byte *ptr)
Definition: bc.c:67
#define MP_SCHED_PENDING
Definition: mpstate.h:56
#define ENTRY_DEFAULT
#define MP_THREAD_GIL_ENTER()
Definition: mpthread.h:57
uint64_t mp_obj_t
Definition: obj.h:39
#define MP_BC_LOAD_CONST_STRING
Definition: bc0.h:36
mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, size_t n_args, size_t n_kw, const mp_obj_t *args)
Definition: runtime.c:615
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc)
Definition: vm.c:127
#define MP_BC_RETURN_VALUE
Definition: bc0.h:95
#define MP_BC_BUILD_LIST
Definition: bc0.h:86
size_t n_args
Definition: runtime.h:114
#define MP_BC_POP_JUMP_IF_TRUE
Definition: bc0.h:69
mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value)
Definition: obj.c:467
#define MP_BC_STORE_DEREF
Definition: bc0.h:51
#define MP_TAGPTR_MAKE(ptr, tag)
Definition: bc.h:108
void mp_delete_name(qstr qst)
Definition: runtime.c:199
void mp_store_global(qstr qst, mp_obj_t obj)
Definition: runtime.c:205
#define MP_BC_IMPORT_STAR
Definition: bc0.h:111
size_t n_alloc
Definition: runtime.h:114
#define MP_BC_YIELD_VALUE
Definition: bc0.h:97
void mp_import_all(mp_obj_t module)
Definition: runtime.c:1380
bool mp_obj_is_true(mp_obj_t arg)
Definition: obj.c:108
#define POP_EXC_BLOCK()
Definition: vm.c:116
mp_obj_t mp_obj_cell_get(mp_obj_t self_in)
Definition: objcell.c:34
#define MP_BC_YIELD_FROM
Definition: bc0.h:98
#define RAISE(o)
mp_unwind_reason_t
Definition: vm.c:54
#define mp_const_false
Definition: obj.h:615
void mp_obj_instance_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest)
Definition: objtype.c:739
const mp_obj_type_t mp_type_RuntimeError
#define MP_BC_LOAD_FAST_N
Definition: bc0.h:40
const struct _mp_obj_exception_t mp_const_GeneratorExit_obj
Definition: objexcept.c:97
mp_obj_t * args
Definition: runtime.h:115