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 |
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] |
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_int_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 | // Pop exhausted gen |
1261 | sp--; |
1262 | if (ret_value == MP_OBJ_STOP_ITERATION) { |
1263 | // Optimize StopIteration |
1264 | // TODO: get StopIteration's value |
1265 | PUSH(mp_const_none); |
1266 | } else { |
1267 | PUSH(ret_value); |
1268 | } |
1269 | |
1270 | // If we injected GeneratorExit downstream, then even |
1271 | // if it was swallowed, we re-raise GeneratorExit |
1272 | GENERATOR_EXIT_IF_NEEDED(t_exc); |
1273 | DISPATCH(); |
1274 | } else { |
1275 | assert(ret_kind == MP_VM_RETURN_EXCEPTION); |
1276 | assert(!EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))); |
1277 | // Pop exhausted gen |
1278 | sp--; |
1279 | RAISE(ret_value); |
1280 | } |
1281 | } |
1282 | |
1283 | ENTRY(MP_BC_IMPORT_NAME): { |
1284 | FRAME_UPDATE(); |
1285 | MARK_EXC_IP_SELECTIVE(); |
1286 | DECODE_QSTR; |
1287 | mp_obj_t obj = POP(); |
1288 | SET_TOP(mp_import_name(qst, obj, TOP())); |
1289 | DISPATCH(); |
1290 | } |
1291 | |
1292 | ENTRY(MP_BC_IMPORT_FROM): { |
1293 | FRAME_UPDATE(); |
1294 | MARK_EXC_IP_SELECTIVE(); |
1295 | DECODE_QSTR; |
1296 | mp_obj_t obj = mp_import_from(TOP(), qst); |
1297 | PUSH(obj); |
1298 | DISPATCH(); |
1299 | } |
1300 | |
1301 | ENTRY(MP_BC_IMPORT_STAR): |
1302 | MARK_EXC_IP_SELECTIVE(); |
1303 | mp_import_all(POP()); |
1304 | DISPATCH(); |
1305 | |
1306 | #if MICROPY_OPT_COMPUTED_GOTO |
1307 | ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI): |
1308 | 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)); |
1309 | DISPATCH(); |
1310 | |
1311 | ENTRY(MP_BC_LOAD_FAST_MULTI): |
1312 | obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]]; |
1313 | goto load_check; |
1314 | |
1315 | ENTRY(MP_BC_STORE_FAST_MULTI): |
1316 | fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP(); |
1317 | DISPATCH(); |
1318 | |
1319 | ENTRY(MP_BC_UNARY_OP_MULTI): |
1320 | MARK_EXC_IP_SELECTIVE(); |
1321 | SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP())); |
1322 | DISPATCH(); |
1323 | |
1324 | ENTRY(MP_BC_BINARY_OP_MULTI): { |
1325 | MARK_EXC_IP_SELECTIVE(); |
1326 | mp_obj_t rhs = POP(); |
1327 | mp_obj_t lhs = TOP(); |
1328 | SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs)); |
1329 | DISPATCH(); |
1330 | } |
1331 | |
1332 | ENTRY_DEFAULT: |
1333 | MARK_EXC_IP_SELECTIVE(); |
1334 | #else |
1335 | ENTRY_DEFAULT: |
1336 | if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + MP_BC_LOAD_CONST_SMALL_INT_MULTI_NUM) { |
1337 | 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)); |
1338 | DISPATCH(); |
1339 | } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + MP_BC_LOAD_FAST_MULTI_NUM) { |
1340 | obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]]; |
1341 | goto load_check; |
1342 | } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + MP_BC_STORE_FAST_MULTI_NUM) { |
1343 | fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP(); |
1344 | DISPATCH(); |
1345 | } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + MP_BC_UNARY_OP_MULTI_NUM) { |
1346 | SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP())); |
1347 | DISPATCH(); |
1348 | } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + MP_BC_BINARY_OP_MULTI_NUM) { |
1349 | mp_obj_t rhs = POP(); |
1350 | mp_obj_t lhs = TOP(); |
1351 | SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs)); |
1352 | DISPATCH(); |
1353 | } else |
1354 | #endif |
1355 | { |
1356 | |
1357 | mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, MP_ERROR_TEXT("opcode" )); |
1358 | nlr_pop(); |
1359 | code_state->state[0] = obj; |
1360 | FRAME_LEAVE(); |
1361 | return MP_VM_RETURN_EXCEPTION; |
1362 | } |
1363 | |
1364 | #if !MICROPY_OPT_COMPUTED_GOTO |
1365 | } // switch |
1366 | #endif |
1367 | |
1368 | pending_exception_check: |
1369 | MICROPY_VM_HOOK_LOOP |
1370 | |
1371 | #if MICROPY_ENABLE_SCHEDULER |
1372 | // This is an inlined variant of mp_handle_pending |
1373 | if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { |
1374 | mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); |
1375 | // Re-check state is still pending now that we're in the atomic section. |
1376 | if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { |
1377 | MARK_EXC_IP_SELECTIVE(); |
1378 | mp_obj_t obj = MP_STATE_VM(mp_pending_exception); |
1379 | if (obj != MP_OBJ_NULL) { |
1380 | MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; |
1381 | if (!mp_sched_num_pending()) { |
1382 | MP_STATE_VM(sched_state) = MP_SCHED_IDLE; |
1383 | } |
1384 | MICROPY_END_ATOMIC_SECTION(atomic_state); |
1385 | RAISE(obj); |
1386 | } |
1387 | mp_handle_pending_tail(atomic_state); |
1388 | } else { |
1389 | MICROPY_END_ATOMIC_SECTION(atomic_state); |
1390 | } |
1391 | } |
1392 | #else |
1393 | // This is an inlined variant of mp_handle_pending |
1394 | if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { |
1395 | MARK_EXC_IP_SELECTIVE(); |
1396 | mp_obj_t obj = MP_STATE_VM(mp_pending_exception); |
1397 | MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; |
1398 | RAISE(obj); |
1399 | } |
1400 | #endif |
1401 | |
1402 | #if MICROPY_PY_THREAD_GIL |
1403 | #if MICROPY_PY_THREAD_GIL_VM_DIVISOR |
1404 | if (--gil_divisor == 0) |
1405 | #endif |
1406 | { |
1407 | #if MICROPY_PY_THREAD_GIL_VM_DIVISOR |
1408 | gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR; |
1409 | #endif |
1410 | #if MICROPY_ENABLE_SCHEDULER |
1411 | // can only switch threads if the scheduler is unlocked |
1412 | if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) |
1413 | #endif |
1414 | { |
1415 | MP_THREAD_GIL_EXIT(); |
1416 | MP_THREAD_GIL_ENTER(); |
1417 | } |
1418 | } |
1419 | #endif |
1420 | |
1421 | } // for loop |
1422 | |
1423 | } else { |
1424 | exception_handler: |
1425 | // exception occurred |
1426 | |
1427 | #if MICROPY_PY_SYS_EXC_INFO |
1428 | MP_STATE_VM(cur_exception) = nlr.ret_val; |
1429 | #endif |
1430 | |
1431 | #if SELECTIVE_EXC_IP |
1432 | // with selective ip, we store the ip 1 byte past the opcode, so move ptr back |
1433 | code_state->ip -= 1; |
1434 | #endif |
1435 | |
1436 | 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))) { |
1437 | if (code_state->ip) { |
1438 | // check if it's a StopIteration within a for block |
1439 | if (*code_state->ip == MP_BC_FOR_ITER) { |
1440 | const byte *ip = code_state->ip + 1; |
1441 | DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward |
1442 | code_state->ip = ip + ulab; // jump to after for-block |
1443 | code_state->sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator |
1444 | goto outer_dispatch_loop; // continue with dispatch loop |
1445 | } else if (*code_state->ip == MP_BC_YIELD_FROM) { |
1446 | // StopIteration inside yield from call means return a value of |
1447 | // yield from, so inject exception's value as yield from's result |
1448 | // (Instead of stack pop then push we just replace exhausted gen with value) |
1449 | *code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); |
1450 | code_state->ip++; // yield from is over, move to next instruction |
1451 | goto outer_dispatch_loop; // continue with dispatch loop |
1452 | } |
1453 | } |
1454 | } |
1455 | |
1456 | #if MICROPY_PY_SYS_SETTRACE |
1457 | // Exceptions are traced here |
1458 | 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))) { |
1459 | TRACE_TICK(code_state->ip, code_state->sp, true /* yes, it's an exception */); |
1460 | } |
1461 | #endif |
1462 | |
1463 | #if MICROPY_STACKLESS |
1464 | unwind_loop: |
1465 | #endif |
1466 | // Set traceback info (file and line number) where the exception occurred, but not for: |
1467 | // - constant GeneratorExit object, because it's const |
1468 | // - exceptions re-raised by END_FINALLY |
1469 | // - exceptions re-raised explicitly by "raise" |
1470 | if (nlr.ret_val != &mp_const_GeneratorExit_obj |
1471 | && *code_state->ip != MP_BC_END_FINALLY |
1472 | && *code_state->ip != MP_BC_RAISE_LAST) { |
1473 | const byte *ip = code_state->fun_bc->bytecode; |
1474 | MP_BC_PRELUDE_SIG_DECODE(ip); |
1475 | MP_BC_PRELUDE_SIZE_DECODE(ip); |
1476 | const byte *bytecode_start = ip + n_info + n_cell; |
1477 | #if !MICROPY_PERSISTENT_CODE |
1478 | // so bytecode is aligned |
1479 | bytecode_start = MP_ALIGN(bytecode_start, sizeof(mp_uint_t)); |
1480 | #endif |
1481 | size_t bc = code_state->ip - bytecode_start; |
1482 | #if MICROPY_PERSISTENT_CODE |
1483 | qstr block_name = ip[0] | (ip[1] << 8); |
1484 | qstr source_file = ip[2] | (ip[3] << 8); |
1485 | ip += 4; |
1486 | #else |
1487 | qstr block_name = mp_decode_uint_value(ip); |
1488 | ip = mp_decode_uint_skip(ip); |
1489 | qstr source_file = mp_decode_uint_value(ip); |
1490 | ip = mp_decode_uint_skip(ip); |
1491 | #endif |
1492 | size_t source_line = mp_bytecode_get_source_line(ip, bc); |
1493 | mp_obj_exception_add_traceback(MP_OBJ_FROM_PTR(nlr.ret_val), source_file, source_line, block_name); |
1494 | } |
1495 | |
1496 | while (exc_sp >= exc_stack && exc_sp->handler <= code_state->ip) { |
1497 | |
1498 | // nested exception |
1499 | |
1500 | assert(exc_sp >= exc_stack); |
1501 | |
1502 | // TODO make a proper message for nested exception |
1503 | // at the moment we are just raising the very last exception (the one that caused the nested exception) |
1504 | |
1505 | // move up to previous exception handler |
1506 | POP_EXC_BLOCK(); |
1507 | } |
1508 | |
1509 | if (exc_sp >= exc_stack) { |
1510 | // catch exception and pass to byte code |
1511 | code_state->ip = exc_sp->handler; |
1512 | mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp); |
1513 | // save this exception in the stack so it can be used in a reraise, if needed |
1514 | exc_sp->prev_exc = nlr.ret_val; |
1515 | // push exception object so it can be handled by bytecode |
1516 | PUSH(MP_OBJ_FROM_PTR(nlr.ret_val)); |
1517 | code_state->sp = sp; |
1518 | |
1519 | #if MICROPY_STACKLESS |
1520 | } else if (code_state->prev != NULL) { |
1521 | mp_globals_set(code_state->old_globals); |
1522 | mp_code_state_t *new_code_state = code_state->prev; |
1523 | #if MICROPY_ENABLE_PYSTACK |
1524 | // Free code_state, and args allocated by mp_call_prepare_args_n_kw_var |
1525 | // (The latter is implicitly freed when using pystack due to its LIFO nature.) |
1526 | // The sizeof in the following statement does not include the size of the variable |
1527 | // part of the struct. This arg is anyway not used if pystack is enabled. |
1528 | mp_nonlocal_free(code_state, sizeof(mp_code_state_t)); |
1529 | #endif |
1530 | code_state = new_code_state; |
1531 | size_t n_state = code_state->n_state; |
1532 | fastn = &code_state->state[n_state - 1]; |
1533 | exc_stack = (mp_exc_stack_t*)(code_state->state + n_state); |
1534 | // variables that are visible to the exception handler (declared volatile) |
1535 | 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 |
1536 | goto unwind_loop; |
1537 | |
1538 | #endif |
1539 | } else { |
1540 | // propagate exception to higher level |
1541 | // Note: ip and sp don't have usable values at this point |
1542 | code_state->state[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // put exception here because sp is invalid |
1543 | FRAME_LEAVE(); |
1544 | return MP_VM_RETURN_EXCEPTION; |
1545 | } |
1546 | } |
1547 | } |
1548 | } |
1549 | |