LCOV - code coverage report
Current view: top level - py - vm.c (source / functions) Hit Total Coverage
Test: unix_coverage_v1.22.0-325-gd11ca092f.info Lines: 602 602 100.0 %
Date: 2024-04-17 08:48:33 Functions: 1 1 100.0 %
Branches: 193 238 81.1 %

           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                 :    8223300 : 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                 :    8223300 : FRAME_ENTER();
     257                 :            : 
     258                 :            : #if MICROPY_STACKLESS
     259                 :            : run_code_state_from_return: ;
     260                 :            : #endif
     261                 :    8223300 : FRAME_SETUP();
     262                 :            : 
     263                 :            :     // Pointers which are constant for particular invocation of mp_execute_bytecode()
     264                 :    8223300 :     mp_obj_t * /*const*/ fastn;
     265                 :    8223300 :     mp_exc_stack_t * /*const*/ exc_stack;
     266                 :            :     {
     267                 :    8223300 :         size_t n_state = code_state->n_state;
     268                 :    8223300 :         fastn = &code_state->state[n_state - 1];
     269                 :    8223300 :         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                 :    8223300 :     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                 :    8291828 :     for (;;) {
     283                 :    8288565 :         nlr_buf_t nlr;
     284                 :            : outer_dispatch_loop:
     285         [ +  + ]:    8288565 :         if (nlr_push(&nlr) == 0) {
     286                 :            :             // local variables that are not visible to the exception handler
     287                 :    8230982 :             const byte *ip = code_state->ip;
     288                 :    8230982 :             mp_obj_t *sp = code_state->sp;
     289                 :            :             #if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
     290                 :    8230982 :             const qstr_short_t *qstr_table = code_state->fun_bc->context->constants.qstr_table;
     291                 :            :             #endif
     292                 :    8230982 :             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   [ +  +  +  + ]:    8230982 :             if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
     301                 :         85 :                 mp_obj_t exc = inject_exc;
     302                 :         85 :                 inject_exc = MP_OBJ_NULL;
     303                 :         85 :                 exc = mp_make_raise_obj(exc);
     304                 :         85 :                 RAISE(exc);
     305                 :            :             }
     306                 :            : 
     307                 :            :             // loop to execute byte code
     308                 :   20981904 :             for (;;) {
     309                 :    8230897 : dispatch_loop:
     310                 :            :                 #if MICROPY_OPT_COMPUTED_GOTO
     311                 :   20981904 :                 DISPATCH();
     312                 :            :                 #else
     313                 :            :                 TRACE(ip);
     314                 :            :                 MARK_EXC_IP_GLOBAL();
     315                 :            :                 TRACE_TICK(ip, sp, false);
     316                 :            :                 switch (*ip++) {
     317                 :            :                 #endif
     318                 :            : 
     319                 :        648 :                 ENTRY(MP_BC_LOAD_CONST_FALSE):
     320                 :        648 :                     PUSH(mp_const_false);
     321                 :        648 :                     DISPATCH();
     322                 :            : 
     323                 :     905862 :                 ENTRY(MP_BC_LOAD_CONST_NONE):
     324                 :     905862 :                     PUSH(mp_const_none);
     325                 :     905862 :                     DISPATCH();
     326                 :            : 
     327                 :        894 :                 ENTRY(MP_BC_LOAD_CONST_TRUE):
     328                 :        894 :                     PUSH(mp_const_true);
     329                 :        894 :                     DISPATCH();
     330                 :            : 
     331                 :    7732334 :                 ENTRY(MP_BC_LOAD_CONST_SMALL_INT): {
     332                 :    7732334 :                     mp_uint_t num = 0;
     333         [ +  + ]:    7732334 :                     if ((ip[0] & 0x40) != 0) {
     334                 :            :                         // Number is negative
     335                 :        217 :                         num--;
     336                 :            :                     }
     337                 :   15486019 :                     do {
     338                 :   15486019 :                         num = (num << 7) | (*ip & 0x7f);
     339         [ +  + ]:   15486019 :                     } while ((*ip++ & 0x80) != 0);
     340                 :    7732334 :                     PUSH(MP_OBJ_NEW_SMALL_INT(num));
     341                 :    7732334 :                     DISPATCH();
     342                 :            :                 }
     343                 :            : 
     344                 :     205805 :                 ENTRY(MP_BC_LOAD_CONST_STRING): {
     345         [ -  + ]:     205805 :                     DECODE_QSTR;
     346                 :     205805 :                     PUSH(MP_OBJ_NEW_QSTR(qst));
     347                 :     205805 :                     DISPATCH();
     348                 :            :                 }
     349                 :            : 
     350                 :      48401 :                 ENTRY(MP_BC_LOAD_CONST_OBJ): {
     351         [ -  + ]:      48401 :                     DECODE_OBJ;
     352                 :      48401 :                     PUSH(obj);
     353                 :      48401 :                     DISPATCH();
     354                 :            :                 }
     355                 :            : 
     356                 :       1388 :                 ENTRY(MP_BC_LOAD_NULL):
     357                 :       1388 :                     PUSH(MP_OBJ_NULL);
     358                 :       1388 :                     DISPATCH();
     359                 :            : 
     360                 :          2 :                 ENTRY(MP_BC_LOAD_FAST_N): {
     361         [ -  + ]:          2 :                     DECODE_UINT;
     362                 :          2 :                     obj_shared = fastn[-unum];
     363                 :   60991994 :                     load_check:
     364         [ +  + ]:   60991994 :                     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                 :   60991982 :                     PUSH(obj_shared);
     372                 :   60991982 :                     DISPATCH();
     373                 :            :                 }
     374                 :            : 
     375                 :      48592 :                 ENTRY(MP_BC_LOAD_DEREF): {
     376         [ -  + ]:      48592 :                     DECODE_UINT;
     377                 :      48592 :                     obj_shared = mp_obj_cell_get(fastn[-unum]);
     378                 :      48592 :                     goto load_check;
     379                 :            :                 }
     380                 :            : 
     381                 :     693177 :                 ENTRY(MP_BC_LOAD_NAME): {
     382                 :     693177 :                     MARK_EXC_IP_SELECTIVE();
     383         [ -  + ]:     693177 :                     DECODE_QSTR;
     384                 :     693177 :                     PUSH(mp_load_name(qst));
     385                 :     693115 :                     DISPATCH();
     386                 :            :                 }
     387                 :            : 
     388                 :   11928058 :                 ENTRY(MP_BC_LOAD_GLOBAL): {
     389                 :   11928058 :                     MARK_EXC_IP_SELECTIVE();
     390         [ -  + ]:   11928058 :                     DECODE_QSTR;
     391                 :   11928058 :                     PUSH(mp_load_global(qst));
     392                 :   11910061 :                     DISPATCH();
     393                 :            :                 }
     394                 :            : 
     395                 :    2301772 :                 ENTRY(MP_BC_LOAD_ATTR): {
     396                 :    2301772 :                     FRAME_UPDATE();
     397                 :    2301772 :                     MARK_EXC_IP_SELECTIVE();
     398         [ -  + ]:    2301772 :                     DECODE_QSTR;
     399                 :    2301772 :                     mp_obj_t top = TOP();
     400                 :    2301772 :                     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                 :    2301772 :                     mp_map_elem_t *elem = NULL;
     407         [ +  + ]:    2301772 :                     if (mp_obj_is_instance_type(mp_obj_get_type(top))) {
     408                 :    2108752 :                         mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
     409                 :    2108752 :                         elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
     410                 :            :                     }
     411         [ +  + ]:    2108816 :                     if (elem) {
     412                 :    1879788 :                         obj = elem->value;
     413                 :            :                     } else
     414                 :            :                     #endif
     415                 :            :                     {
     416                 :     421964 :                         obj = mp_load_attr(top, qst);
     417                 :            :                     }
     418                 :    2301712 :                     SET_TOP(obj);
     419                 :    2301712 :                     DISPATCH();
     420                 :            :                 }
     421                 :            : 
     422                 :     592649 :                 ENTRY(MP_BC_LOAD_METHOD): {
     423                 :     592649 :                     MARK_EXC_IP_SELECTIVE();
     424         [ -  + ]:     592649 :                     DECODE_QSTR;
     425                 :     592649 :                     mp_load_method(*sp, qst, sp);
     426                 :     592633 :                     sp += 1;
     427                 :     592633 :                     DISPATCH();
     428                 :            :                 }
     429                 :            : 
     430                 :         29 :                 ENTRY(MP_BC_LOAD_SUPER_METHOD): {
     431                 :         29 :                     MARK_EXC_IP_SELECTIVE();
     432         [ -  + ]:         29 :                     DECODE_QSTR;
     433                 :         29 :                     sp -= 1;
     434                 :         29 :                     mp_load_super_method(qst, sp - 1);
     435                 :         29 :                     DISPATCH();
     436                 :            :                 }
     437                 :            : 
     438                 :        806 :                 ENTRY(MP_BC_LOAD_BUILD_CLASS):
     439                 :        806 :                     MARK_EXC_IP_SELECTIVE();
     440                 :        806 :                     PUSH(mp_load_build_class());
     441                 :        806 :                     DISPATCH();
     442                 :            : 
     443                 :   12606360 :                 ENTRY(MP_BC_LOAD_SUBSCR): {
     444                 :   12606360 :                     MARK_EXC_IP_SELECTIVE();
     445                 :   12606360 :                     mp_obj_t index = POP();
     446                 :   12606360 :                     SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL));
     447                 :   12604761 :                     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                 :       1363 :                 ENTRY(MP_BC_STORE_DEREF): {
     457         [ -  + ]:       1363 :                     DECODE_UINT;
     458                 :       1363 :                     mp_obj_cell_set(fastn[-unum], POP());
     459                 :       1363 :                     DISPATCH();
     460                 :            :                 }
     461                 :            : 
     462                 :     325894 :                 ENTRY(MP_BC_STORE_NAME): {
     463                 :     325894 :                     MARK_EXC_IP_SELECTIVE();
     464         [ -  + ]:     325894 :                     DECODE_QSTR;
     465                 :     325894 :                     mp_store_name(qst, POP());
     466                 :     325893 :                     DISPATCH();
     467                 :            :                 }
     468                 :            : 
     469                 :      72671 :                 ENTRY(MP_BC_STORE_GLOBAL): {
     470                 :      72671 :                     MARK_EXC_IP_SELECTIVE();
     471         [ -  + ]:      72671 :                     DECODE_QSTR;
     472                 :      72671 :                     mp_store_global(qst, POP());
     473                 :      72671 :                     DISPATCH();
     474                 :            :                 }
     475                 :            : 
     476                 :     213937 :                 ENTRY(MP_BC_STORE_ATTR): {
     477                 :     213937 :                     FRAME_UPDATE();
     478                 :     213937 :                     MARK_EXC_IP_SELECTIVE();
     479         [ -  + ]:     213937 :                     DECODE_QSTR;
     480                 :     213937 :                     mp_store_attr(sp[0], qst, sp[-1]);
     481                 :     213897 :                     sp -= 2;
     482                 :     213897 :                     DISPATCH();
     483                 :            :                 }
     484                 :            : 
     485                 :    6749898 :                 ENTRY(MP_BC_STORE_SUBSCR):
     486                 :    6749898 :                     MARK_EXC_IP_SELECTIVE();
     487                 :    6749898 :                     mp_obj_subscr(sp[-1], sp[0], sp[-2]);
     488                 :    6750502 :                     sp -= 3;
     489                 :    6750502 :                     DISPATCH();
     490                 :            : 
     491                 :        442 :                 ENTRY(MP_BC_DELETE_FAST): {
     492                 :        442 :                     MARK_EXC_IP_SELECTIVE();
     493         [ -  + ]:        442 :                     DECODE_UINT;
     494         [ +  + ]:        442 :                     if (fastn[-unum] == MP_OBJ_NULL) {
     495                 :          2 :                         goto local_name_error;
     496                 :            :                     }
     497                 :        440 :                     fastn[-unum] = MP_OBJ_NULL;
     498                 :        440 :                     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                 :        257 :                 ENTRY(MP_BC_DELETE_NAME): {
     512                 :        257 :                     MARK_EXC_IP_SELECTIVE();
     513         [ -  + ]:        257 :                     DECODE_QSTR;
     514                 :        257 :                     mp_delete_name(qst);
     515                 :        255 :                     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                 :    9488535 :                 ENTRY(MP_BC_DUP_TOP): {
     526                 :    9488535 :                     mp_obj_t top = TOP();
     527                 :    9488535 :                     PUSH(top);
     528                 :    9488535 :                     DISPATCH();
     529                 :            :                 }
     530                 :            : 
     531                 :    1937580 :                 ENTRY(MP_BC_DUP_TOP_TWO):
     532                 :    1937580 :                     sp += 2;
     533                 :    1937580 :                     sp[0] = sp[-2];
     534                 :    1937580 :                     sp[-1] = sp[-3];
     535                 :    1937580 :                     DISPATCH();
     536                 :            : 
     537                 :    1284713 :                 ENTRY(MP_BC_POP_TOP):
     538                 :    1284713 :                     sp -= 1;
     539                 :    1284713 :                     DISPATCH();
     540                 :            : 
     541                 :    1610402 :                 ENTRY(MP_BC_ROT_TWO): {
     542                 :    1610402 :                     mp_obj_t top = sp[0];
     543                 :    1610402 :                     sp[0] = sp[-1];
     544                 :    1610402 :                     sp[-1] = top;
     545                 :    1610402 :                     DISPATCH();
     546                 :            :                 }
     547                 :            : 
     548                 :     407165 :                 ENTRY(MP_BC_ROT_THREE): {
     549                 :     407165 :                     mp_obj_t top = sp[0];
     550                 :     407165 :                     sp[0] = sp[-1];
     551                 :     407165 :                     sp[-1] = sp[-2];
     552                 :     407165 :                     sp[-2] = top;
     553                 :     407165 :                     DISPATCH();
     554                 :            :                 }
     555                 :            : 
     556                 :     882193 :                 ENTRY(MP_BC_JUMP): {
     557         [ +  + ]:     882193 :                     DECODE_SLABEL;
     558                 :     882193 :                     ip += slab;
     559                 :     882193 :                     DISPATCH_WITH_PEND_EXC_CHECK();
     560                 :            :                 }
     561                 :            : 
     562                 :    6317732 :                 ENTRY(MP_BC_POP_JUMP_IF_TRUE): {
     563         [ +  + ]:    6317732 :                     DECODE_SLABEL;
     564         [ +  + ]:    6317732 :                     if (mp_obj_is_true(POP())) {
     565                 :    5781176 :                         ip += slab;
     566                 :            :                     }
     567                 :    6300926 :                     DISPATCH_WITH_PEND_EXC_CHECK();
     568                 :            :                 }
     569                 :            : 
     570                 :    5633514 :                 ENTRY(MP_BC_POP_JUMP_IF_FALSE): {
     571         [ +  + ]:    5633514 :                     DECODE_SLABEL;
     572         [ +  + ]:    5633514 :                     if (!mp_obj_is_true(POP())) {
     573                 :    3001951 :                         ip += slab;
     574                 :            :                     }
     575                 :    5637447 :                     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                 :        644 :                 ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP): {
     589         [ -  + ]:        644 :                     DECODE_ULABEL;
     590         [ +  + ]:        644 :                     if (mp_obj_is_true(TOP())) {
     591                 :        606 :                         sp--;
     592                 :            :                     } else {
     593                 :         38 :                         ip += ulab;
     594                 :            :                     }
     595                 :        644 :                     DISPATCH_WITH_PEND_EXC_CHECK();
     596                 :            :                 }
     597                 :            : 
     598                 :      34963 :                 ENTRY(MP_BC_SETUP_WITH): {
     599                 :      34963 :                     MARK_EXC_IP_SELECTIVE();
     600                 :            :                     // stack: (..., ctx_mgr)
     601                 :      34963 :                     mp_obj_t obj = TOP();
     602                 :      34963 :                     mp_load_method(obj, MP_QSTR___exit__, sp);
     603                 :      34964 :                     mp_load_method(obj, MP_QSTR___enter__, sp + 2);
     604                 :      34964 :                     mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 2);
     605                 :      34961 :                     sp += 1;
     606         [ +  + ]:      34961 :                     PUSH_EXC_BLOCK(1);
     607                 :      34961 :                     PUSH(ret);
     608                 :            :                     // stack: (..., __exit__, ctx_mgr, as_value)
     609                 :      34961 :                     DISPATCH();
     610                 :            :                 }
     611                 :            : 
     612                 :      34961 :                 ENTRY(MP_BC_WITH_CLEANUP): {
     613                 :      34961 :                     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         [ +  + ]:      34961 :                     if (TOP() == mp_const_none) {
     621                 :            :                         // stack: (..., __exit__, ctx_mgr, None)
     622                 :      34855 :                         sp[1] = mp_const_none;
     623                 :      34855 :                         sp[2] = mp_const_none;
     624                 :      34855 :                         sp -= 2;
     625                 :      34855 :                         mp_call_method_n_kw(3, 0, sp);
     626                 :      34854 :                         SET_TOP(mp_const_none);
     627         [ +  + ]:        106 :                     } 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                 :         78 :                         mp_obj_t data = sp[-1];
     633                 :         78 :                         mp_obj_t cause = sp[0];
     634                 :         78 :                         sp[-1] = mp_const_none;
     635                 :         78 :                         sp[0] = mp_const_none;
     636                 :         78 :                         sp[1] = mp_const_none;
     637                 :         78 :                         mp_call_method_n_kw(3, 0, sp - 3);
     638                 :         78 :                         sp[-3] = data;
     639                 :         78 :                         sp[-2] = cause;
     640                 :         78 :                         sp -= 2; // we removed (__exit__, ctx_mgr)
     641                 :            :                     } else {
     642         [ -  + ]:         28 :                         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                 :         28 :                         sp[1] = sp[0];
     646                 :         28 :                         sp[0] = MP_OBJ_FROM_PTR(mp_obj_get_type(sp[0]));
     647                 :         28 :                         sp[2] = mp_const_none;
     648                 :         28 :                         sp -= 2;
     649                 :         28 :                         mp_obj_t ret_value = mp_call_method_n_kw(3, 0, sp);
     650         [ +  + ]:         28 :                         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                 :          6 :                             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                 :         22 :                             sp[0] = sp[3];
     660                 :            :                         }
     661                 :            :                     }
     662                 :      34960 :                     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                 :     145078 :                 ENTRY(MP_BC_SETUP_EXCEPT):
     709                 :     146114 :                 ENTRY(MP_BC_SETUP_FINALLY): {
     710                 :     146114 :                     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   [ +  +  +  + ]:     146114 :                     PUSH_EXC_BLOCK((code_state->ip[0] == MP_BC_SETUP_FINALLY) ? 1 : 0);
     715                 :            :                     #endif
     716                 :     146114 :                     DISPATCH();
     717                 :            :                 }
     718                 :            : 
     719                 :      35857 :                 ENTRY(MP_BC_END_FINALLY):
     720                 :      35857 :                     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         [ -  + ]:      35857 :                     assert(exc_sp >= exc_stack);
     725                 :      35857 :                     POP_EXC_BLOCK();
     726         [ +  + ]:      35857 :                     if (TOP() == mp_const_none) {
     727                 :      35522 :                         sp--;
     728         [ +  + ]:        335 :                     } 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                 :        229 :                         mp_int_t cause = MP_OBJ_SMALL_INT_VALUE(POP());
     732         [ +  + ]:        229 :                         if (cause < 0) {
     733                 :            :                             // A negative cause indicates unwind return
     734                 :        166 :                             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         [ -  + ]:        106 :                         assert(mp_obj_is_exception_instance(TOP()));
     743                 :        106 :                         RAISE(TOP());
     744                 :            :                     }
     745                 :      35522 :                     DISPATCH();
     746                 :            : 
     747                 :      62831 :                 ENTRY(MP_BC_GET_ITER):
     748                 :      62831 :                     MARK_EXC_IP_SELECTIVE();
     749                 :      62831 :                     SET_TOP(mp_getiter(TOP(), NULL));
     750                 :      62830 :                     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                 :      67496 :                 ENTRY(MP_BC_GET_ITER_STACK): {
     757                 :      67496 :                     MARK_EXC_IP_SELECTIVE();
     758                 :      67496 :                     mp_obj_t obj = TOP();
     759                 :      67496 :                     mp_obj_iter_buf_t *iter_buf = (mp_obj_iter_buf_t*)sp;
     760                 :      67496 :                     sp += MP_OBJ_ITER_BUF_NSLOTS - 1;
     761                 :      67496 :                     obj = mp_getiter(obj, iter_buf);
     762         [ +  + ]:      67492 :                     if (obj != MP_OBJ_FROM_PTR(iter_buf)) {
     763                 :            :                         // Iterator didn't use the stack so indicate that with MP_OBJ_NULL.
     764                 :      65312 :                         *(sp - MP_OBJ_ITER_BUF_NSLOTS + 1) = MP_OBJ_NULL;
     765                 :      65312 :                         *(sp - MP_OBJ_ITER_BUF_NSLOTS + 2) = obj;
     766                 :            :                     }
     767                 :      67492 :                     DISPATCH();
     768                 :            :                 }
     769                 :            : 
     770                 :     114714 :                 ENTRY(MP_BC_FOR_ITER): {
     771                 :     114714 :                     FRAME_UPDATE();
     772                 :     114714 :                     MARK_EXC_IP_SELECTIVE();
     773         [ +  + ]:     114714 :                     DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
     774                 :     114714 :                     code_state->sp = sp;
     775                 :     114714 :                     mp_obj_t obj;
     776         [ +  + ]:     114714 :                     if (*(sp - MP_OBJ_ITER_BUF_NSLOTS + 1) == MP_OBJ_NULL) {
     777                 :      99752 :                         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                 :     114714 :                     mp_obj_t value = mp_iternext_allow_raise(obj);
     782         [ +  + ]:     114510 :                     if (value == MP_OBJ_STOP_ITERATION) {
     783                 :      67365 :                         sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator
     784                 :      67365 :                         ip += ulab; // jump to after for-block
     785                 :            :                     } else {
     786                 :      47145 :                         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                 :     114510 :                     DISPATCH();
     795                 :            :                 }
     796                 :            : 
     797                 :     144761 :                 ENTRY(MP_BC_POP_EXCEPT_JUMP): {
     798         [ -  + ]:     144761 :                     assert(exc_sp >= exc_stack);
     799                 :     144761 :                     POP_EXC_BLOCK();
     800         [ +  + ]:     144761 :                     DECODE_ULABEL;
     801                 :     144761 :                     ip += ulab;
     802                 :     144761 :                     DISPATCH_WITH_PEND_EXC_CHECK();
     803                 :            :                 }
     804                 :            : 
     805                 :      31889 :                 ENTRY(MP_BC_BUILD_TUPLE): {
     806                 :      31889 :                     MARK_EXC_IP_SELECTIVE();
     807         [ -  + ]:      31889 :                     DECODE_UINT;
     808                 :      31889 :                     sp -= unum - 1;
     809                 :      31889 :                     SET_TOP(mp_obj_new_tuple(unum, sp));
     810                 :      31888 :                     DISPATCH();
     811                 :            :                 }
     812                 :            : 
     813                 :     372819 :                 ENTRY(MP_BC_BUILD_LIST): {
     814                 :     372819 :                     MARK_EXC_IP_SELECTIVE();
     815         [ +  + ]:     372821 :                     DECODE_UINT;
     816                 :     372819 :                     sp -= unum - 1;
     817                 :     372819 :                     SET_TOP(mp_obj_new_list(unum, sp));
     818                 :     372840 :                     DISPATCH();
     819                 :            :                 }
     820                 :            : 
     821                 :        638 :                 ENTRY(MP_BC_BUILD_MAP): {
     822                 :        638 :                     MARK_EXC_IP_SELECTIVE();
     823         [ -  + ]:        638 :                     DECODE_UINT;
     824                 :        638 :                     PUSH(mp_obj_new_dict(unum));
     825                 :        636 :                     DISPATCH();
     826                 :            :                 }
     827                 :            : 
     828                 :        925 :                 ENTRY(MP_BC_STORE_MAP):
     829                 :        925 :                     MARK_EXC_IP_SELECTIVE();
     830                 :        925 :                     sp -= 2;
     831                 :        925 :                     mp_obj_dict_store(sp[0], sp[2], sp[1]);
     832                 :        923 :                     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                 :       4556 :                 ENTRY(MP_BC_BUILD_SLICE): {
     846                 :       4556 :                     MARK_EXC_IP_SELECTIVE();
     847                 :       4556 :                     mp_obj_t step = mp_const_none;
     848         [ +  + ]:       4556 :                     if (*ip++ == 3) {
     849                 :            :                         // 3-argument slice includes step
     850                 :        107 :                         step = POP();
     851                 :            :                     }
     852                 :       4556 :                     mp_obj_t stop = POP();
     853                 :       4556 :                     mp_obj_t start = TOP();
     854                 :       4556 :                     SET_TOP(mp_obj_new_slice(start, stop, step));
     855                 :       4554 :                     DISPATCH();
     856                 :            :                 }
     857                 :            :                 #endif
     858                 :            : 
     859                 :      15961 :                 ENTRY(MP_BC_STORE_COMP): {
     860                 :      15961 :                     MARK_EXC_IP_SELECTIVE();
     861         [ -  + ]:      15961 :                     DECODE_UINT;
     862                 :      15961 :                     mp_obj_t obj = sp[-(unum >> 2)];
     863         [ +  + ]:      15961 :                     if ((unum & 3) == 0) {
     864                 :      14529 :                         mp_obj_list_append(obj, sp[0]);
     865                 :      14529 :                         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                 :      15961 :                     DISPATCH();
     876                 :            :                 }
     877                 :            : 
     878                 :      21335 :                 ENTRY(MP_BC_UNPACK_SEQUENCE): {
     879                 :      21335 :                     MARK_EXC_IP_SELECTIVE();
     880         [ -  + ]:      21335 :                     DECODE_UINT;
     881                 :      21335 :                     mp_unpack_sequence(sp[0], unum, sp);
     882                 :      21327 :                     sp += unum - 1;
     883                 :      21327 :                     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                 :       4296 :                 ENTRY(MP_BC_MAKE_FUNCTION): {
     895         [ -  + ]:       4296 :                     DECODE_PTR;
     896                 :       4296 :                     PUSH(mp_make_function_from_proto_fun(ptr, code_state->fun_bc->context, NULL));
     897                 :       4296 :                     DISPATCH();
     898                 :            :                 }
     899                 :            : 
     900                 :        217 :                 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
     901         [ -  + ]:        217 :                     DECODE_PTR;
     902                 :            :                     // Stack layout: def_tuple def_dict <- TOS
     903                 :        217 :                     sp -= 1;
     904                 :        217 :                     SET_TOP(mp_make_function_from_proto_fun(ptr, code_state->fun_bc->context, sp));
     905                 :        217 :                     DISPATCH();
     906                 :            :                 }
     907                 :            : 
     908                 :       2437 :                 ENTRY(MP_BC_MAKE_CLOSURE): {
     909         [ -  + ]:       2437 :                     DECODE_PTR;
     910                 :       2437 :                     size_t n_closed_over = *ip++;
     911                 :            :                     // Stack layout: closed_overs <- TOS
     912                 :       2437 :                     sp -= n_closed_over - 1;
     913                 :       2437 :                     SET_TOP(mp_make_closure_from_proto_fun(ptr, code_state->fun_bc->context, n_closed_over, sp));
     914                 :       2437 :                     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                 :    8386640 :                 ENTRY(MP_BC_CALL_FUNCTION): {
     927                 :    8386640 :                     FRAME_UPDATE();
     928                 :    8386640 :                     MARK_EXC_IP_SELECTIVE();
     929         [ +  + ]:    8429864 :                     DECODE_UINT;
     930                 :            :                     // unum & 0xff == n_positional
     931                 :            :                     // (unum >> 8) & 0xff == n_keyword
     932                 :    8386640 :                     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                 :    8386640 :                     SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
     958                 :    8386516 :                     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                 :     590544 :                 ENTRY(MP_BC_CALL_METHOD): {
    1008                 :     590544 :                     FRAME_UPDATE();
    1009                 :     590544 :                     MARK_EXC_IP_SELECTIVE();
    1010         [ +  + ]:     590850 :                     DECODE_UINT;
    1011                 :            :                     // unum & 0xff == n_positional
    1012                 :            :                     // (unum >> 8) & 0xff == n_keyword
    1013                 :     590544 :                     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                 :     590544 :                     SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
    1043                 :     589669 :                     DISPATCH();
    1044                 :            :                 }
    1045                 :            : 
    1046                 :       2071 :                 ENTRY(MP_BC_CALL_METHOD_VAR_KW): {
    1047                 :       2071 :                     FRAME_UPDATE();
    1048                 :       2071 :                     MARK_EXC_IP_SELECTIVE();
    1049         [ +  + ]:       2102 :                     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                 :       2071 :                     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                 :       2071 :                     SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
    1089                 :       2037 :                     DISPATCH();
    1090                 :            :                 }
    1091                 :            : 
    1092                 :    8028804 :                 ENTRY(MP_BC_RETURN_VALUE):
    1093                 :            :                     MARK_EXC_IP_SELECTIVE();
    1094                 :    8028804 : unwind_return:
    1095                 :            :                     // Search for and execute finally handlers that aren't already active
    1096                 :    8028804 :                     while (exc_sp >= exc_stack) {
    1097         [ +  + ]:        361 :                         if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
    1098         [ +  + ]:        256 :                             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                 :        182 :                                 mp_obj_t *finally_sp = MP_TAGPTR_PTR(exc_sp->val_sp);
    1110                 :        182 :                                 finally_sp[1] = sp[0];
    1111                 :        182 :                                 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                 :        182 :                                 PUSH(MP_OBJ_NEW_SMALL_INT(-1));
    1117                 :        182 :                                 ip = exc_sp->handler;
    1118                 :        182 :                                 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         [ +  + ]:    8028804 :                         POP_EXC_BLOCK();
    1125                 :            :                     }
    1126                 :    8028443 :                     nlr_pop();
    1127                 :    8033070 :                     code_state->sp = sp;
    1128         [ -  + ]:    8033070 :                     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                 :    8175256 :                     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                 :      62442 :                 ENTRY(MP_BC_RAISE_OBJ): {
    1167                 :      62442 :                     MARK_EXC_IP_SELECTIVE();
    1168                 :      62442 :                     mp_obj_t obj = mp_make_raise_obj(TOP());
    1169                 :      62442 :                     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                 :      78800 :                 ENTRY(MP_BC_YIELD_VALUE):
    1183                 :      78800 : yield:
    1184                 :      78800 :                     nlr_pop();
    1185                 :      78800 :                     code_state->ip = ip;
    1186                 :      78800 :                     code_state->sp = sp;
    1187                 :      78800 :                     code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp);
    1188                 :      78800 :                     FRAME_LEAVE();
    1189                 :      78800 :                     return MP_VM_RETURN_YIELD;
    1190                 :            : 
    1191                 :     124980 :                 ENTRY(MP_BC_YIELD_FROM): {
    1192                 :     124980 :                     MARK_EXC_IP_SELECTIVE();
    1193                 :     124980 :                     mp_vm_return_kind_t ret_kind;
    1194                 :     124980 :                     mp_obj_t send_value = POP();
    1195                 :     124980 :                     mp_obj_t t_exc = MP_OBJ_NULL;
    1196                 :     124980 :                     mp_obj_t ret_value;
    1197                 :     124980 :                     code_state->sp = sp; // Save sp because it's needed if mp_resume raises StopIteration
    1198         [ +  + ]:     124980 :                     if (inject_exc != MP_OBJ_NULL) {
    1199                 :        105 :                         t_exc = inject_exc;
    1200                 :        105 :                         inject_exc = MP_OBJ_NULL;
    1201                 :        105 :                         ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
    1202                 :            :                     } else {
    1203                 :     124875 :                         ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
    1204                 :            :                     }
    1205                 :            : 
    1206         [ +  + ]:      62957 :                     if (ret_kind == MP_VM_RETURN_YIELD) {
    1207                 :      62351 :                         ip--;
    1208                 :      62351 :                         PUSH(ret_value);
    1209                 :      62351 :                         goto yield;
    1210         [ +  + ]:        606 :                     } 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                 :        291 :                         SET_TOP(ret_value);
    1214                 :            :                         // If we injected GeneratorExit downstream, then even
    1215                 :            :                         // if it was swallowed, we re-raise GeneratorExit
    1216   [ +  +  +  + ]:        291 :                         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                 :        323 :                             RAISE(raise_t);
    1219                 :            :                         }
    1220                 :        283 :                         DISPATCH();
    1221                 :            :                     } else {
    1222         [ -  + ]:        315 :                         assert(ret_kind == MP_VM_RETURN_EXCEPTION);
    1223         [ -  + ]:        315 :                         assert(!mp_obj_exception_match(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration)));
    1224                 :            :                         // Pop exhausted gen
    1225                 :        315 :                         sp--;
    1226                 :      62666 :                         RAISE(ret_value);
    1227                 :            :                     }
    1228                 :            :                 }
    1229                 :            : 
    1230                 :       1023 :                 ENTRY(MP_BC_IMPORT_NAME): {
    1231                 :       1023 :                     FRAME_UPDATE();
    1232                 :       1023 :                     MARK_EXC_IP_SELECTIVE();
    1233         [ -  + ]:       1023 :                     DECODE_QSTR;
    1234                 :       1023 :                     mp_obj_t obj = POP();
    1235                 :       1023 :                     SET_TOP(mp_import_name(qst, obj, TOP()));
    1236                 :       1005 :                     DISPATCH();
    1237                 :            :                 }
    1238                 :            : 
    1239                 :        387 :                 ENTRY(MP_BC_IMPORT_FROM): {
    1240                 :        387 :                     FRAME_UPDATE();
    1241                 :        387 :                     MARK_EXC_IP_SELECTIVE();
    1242         [ -  + ]:        387 :                     DECODE_QSTR;
    1243                 :        387 :                     mp_obj_t obj = mp_import_from(TOP(), qst);
    1244                 :        383 :                     PUSH(obj);
    1245                 :        383 :                     DISPATCH();
    1246                 :            :                 }
    1247                 :            : 
    1248                 :         45 :                 ENTRY(MP_BC_IMPORT_STAR):
    1249                 :         45 :                     MARK_EXC_IP_SELECTIVE();
    1250                 :         45 :                     mp_import_all(POP());
    1251                 :         45 :                     DISPATCH();
    1252                 :            : 
    1253                 :            :                 #if MICROPY_OPT_COMPUTED_GOTO
    1254                 :   30834111 :                 ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):
    1255                 :   30834111 :                     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                 :   30834111 :                     DISPATCH();
    1257                 :            : 
    1258                 :   60943400 :                 ENTRY(MP_BC_LOAD_FAST_MULTI):
    1259                 :   60943400 :                     obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
    1260                 :   60943400 :                     goto load_check;
    1261                 :            : 
    1262                 :   10427318 :                 ENTRY(MP_BC_STORE_FAST_MULTI):
    1263                 :   10427318 :                     fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
    1264                 :   10427318 :                     DISPATCH();
    1265                 :            : 
    1266                 :     127273 :                 ENTRY(MP_BC_UNARY_OP_MULTI):
    1267                 :     127273 :                     MARK_EXC_IP_SELECTIVE();
    1268                 :     127273 :                     SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
    1269                 :     127253 :                     DISPATCH();
    1270                 :            : 
    1271                 :   51066522 :                 ENTRY(MP_BC_BINARY_OP_MULTI): {
    1272                 :   51066522 :                     MARK_EXC_IP_SELECTIVE();
    1273                 :   51066522 :                     mp_obj_t rhs = POP();
    1274                 :   51066522 :                     mp_obj_t lhs = TOP();
    1275                 :   51066522 :                     SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
    1276                 :   50746261 :                     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                 :   12966407 : 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                 :   12966407 :                 if (
    1326                 :            :                 #if MICROPY_ENABLE_SCHEDULER
    1327                 :            :                 #if MICROPY_PY_THREAD
    1328                 :            :                     // Scheduler + threading: Scheduler and pending exceptions are independent, check both.
    1329   [ +  +  +  # ]:   12966407 :                     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                 :     114712 :                     MARK_EXC_IP_SELECTIVE();
    1344                 :     114712 :                     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                 :      65653 : exception_handler:
    1371                 :            :             // exception occurred
    1372                 :            : 
    1373                 :            :             #if MICROPY_PY_SYS_EXC_INFO
    1374                 :     128649 :             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         [ +  + ]:     128649 :             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         [ +  + ]:     124337 :                 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         [ +  + ]:     124331 :                 } 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                 :      61996 :                     *code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));
    1395                 :      61996 :                     code_state->ip++; // yield from is over, move to next instruction
    1396                 :      61996 :                     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         [ +  + ]:      66647 :             if (nlr.ret_val != &mp_const_GeneratorExit_obj
    1415         [ +  + ]:      66619 :                 && *code_state->ip != MP_BC_END_FINALLY
    1416         [ +  + ]:      66513 :                 && *code_state->ip != MP_BC_RAISE_LAST) {
    1417                 :      66495 :                 const byte *ip = code_state->fun_bc->bytecode;
    1418         [ +  + ]:      68658 :                 MP_BC_PRELUDE_SIG_DECODE(ip);
    1419         [ +  + ]:      66865 :                 MP_BC_PRELUDE_SIZE_DECODE(ip);
    1420                 :      66495 :                 const byte *line_info_top = ip + n_info;
    1421                 :      66495 :                 const byte *bytecode_start = ip + n_info + n_cell;
    1422                 :      66495 :                 size_t bc = code_state->ip - bytecode_start;
    1423                 :      66495 :                 qstr block_name = mp_decode_uint_value(ip);
    1424         [ +  + ]:     196706 :                 for (size_t i = 0; i < 1 + n_pos_args + n_kwonly_args; ++i) {
    1425                 :     130211 :                     ip = mp_decode_uint_skip(ip);
    1426                 :            :                 }
    1427                 :            :                 #if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
    1428                 :      66495 :                 block_name = code_state->fun_bc->context->constants.qstr_table[block_name];
    1429                 :      66495 :                 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                 :      66495 :                 size_t source_line = mp_bytecode_get_source_line(ip, line_info_top, bc);
    1434                 :      66495 :                 mp_obj_exception_add_traceback(MP_OBJ_FROM_PTR(nlr.ret_val), source_file, source_line, block_name);
    1435                 :            :             }
    1436                 :            : 
    1437         [ +  + ]:       3356 :             while (exc_sp >= exc_stack && exc_sp->handler <= code_state->ip) {
    1438                 :            : 
    1439                 :            :                 // nested exception
    1440                 :            : 
    1441         [ -  + ]:         93 :                 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         [ +  + ]:      66740 :                 POP_EXC_BLOCK();
    1448                 :            :             }
    1449                 :            : 
    1450         [ +  + ]:      66647 :             if (exc_sp >= exc_stack) {
    1451                 :            :                 // catch exception and pass to byte code
    1452                 :       3263 :                 code_state->ip = exc_sp->handler;
    1453                 :       3263 :                 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                 :       3263 :                 exc_sp->prev_exc = nlr.ret_val;
    1456                 :            :                 // push exception object so it can be handled by bytecode
    1457                 :       3263 :                 PUSH(MP_OBJ_FROM_PTR(nlr.ret_val));
    1458                 :       3263 :                 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                 :      63384 :                 code_state->state[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // put exception here because sp is invalid
    1484                 :      63384 :                 FRAME_LEAVE();
    1485                 :      63384 :                 return MP_VM_RETURN_EXCEPTION;
    1486                 :            :             }
    1487                 :            :         }
    1488                 :            :     }
    1489                 :            : }

Generated by: LCOV version 1.15-5-g462f71d