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