1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) SatoshiLabs
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  */
26 
27 #include "py/profile.h"
28 #include "py/bc0.h"
29 #include "py/gc.h"
30 
31 #if MICROPY_PY_SYS_SETTRACE
32 
33 #define prof_trace_cb MP_STATE_THREAD(prof_trace_callback)
34 
mp_prof_bytecode_lineno(const mp_raw_code_t * rc,size_t bc)35 STATIC uint mp_prof_bytecode_lineno(const mp_raw_code_t *rc, size_t bc) {
36     const mp_bytecode_prelude_t *prelude = &rc->prelude;
37     return mp_bytecode_get_source_line(prelude->line_info, bc);
38 }
39 
mp_prof_extract_prelude(const byte * bytecode,mp_bytecode_prelude_t * prelude)40 void mp_prof_extract_prelude(const byte *bytecode, mp_bytecode_prelude_t *prelude) {
41     const byte *ip = bytecode;
42 
43     MP_BC_PRELUDE_SIG_DECODE(ip);
44     prelude->n_state = n_state;
45     prelude->n_exc_stack = n_exc_stack;
46     prelude->scope_flags = scope_flags;
47     prelude->n_pos_args = n_pos_args;
48     prelude->n_kwonly_args = n_kwonly_args;
49     prelude->n_def_pos_args = n_def_pos_args;
50 
51     MP_BC_PRELUDE_SIZE_DECODE(ip);
52 
53     prelude->line_info = ip + 4;
54     prelude->opcodes = ip + n_info + n_cell;
55 
56     qstr block_name = ip[0] | (ip[1] << 8);
57     qstr source_file = ip[2] | (ip[3] << 8);
58     prelude->qstr_block_name = block_name;
59     prelude->qstr_source_file = source_file;
60 }
61 
62 /******************************************************************************/
63 // code object
64 
code_print(const mp_print_t * print,mp_obj_t o_in,mp_print_kind_t kind)65 STATIC void code_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
66     (void)kind;
67     mp_obj_code_t *o = MP_OBJ_TO_PTR(o_in);
68     const mp_raw_code_t *rc = o->rc;
69     const mp_bytecode_prelude_t *prelude = &rc->prelude;
70     mp_printf(print,
71         "<code object %q at 0x%p, file \"%q\", line %d>",
72         prelude->qstr_block_name,
73         o,
74         prelude->qstr_source_file,
75         rc->line_of_definition
76         );
77 }
78 
code_consts(const mp_raw_code_t * rc)79 STATIC mp_obj_tuple_t *code_consts(const mp_raw_code_t *rc) {
80     const mp_bytecode_prelude_t *prelude = &rc->prelude;
81     int start = prelude->n_pos_args + prelude->n_kwonly_args + rc->n_obj;
82     int stop = prelude->n_pos_args + prelude->n_kwonly_args + rc->n_obj + rc->n_raw_code;
83     mp_obj_tuple_t *consts = MP_OBJ_TO_PTR(mp_obj_new_tuple(stop - start + 1, NULL));
84 
85     size_t const_no = 0;
86     for (int i = start; i < stop; ++i) {
87         mp_obj_t code = mp_obj_new_code((const mp_raw_code_t *)MP_OBJ_TO_PTR(rc->const_table[i]));
88         if (code == MP_OBJ_NULL) {
89             m_malloc_fail(sizeof(mp_obj_code_t));
90         }
91         consts->items[const_no++] = code;
92     }
93     consts->items[const_no++] = mp_const_none;
94 
95     return consts;
96 }
97 
raw_code_lnotab(const mp_raw_code_t * rc)98 STATIC mp_obj_t raw_code_lnotab(const mp_raw_code_t *rc) {
99     // const mp_bytecode_prelude_t *prelude = &rc->prelude;
100     uint start = 0;
101     uint stop = rc->fun_data_len - start;
102 
103     uint last_lineno = mp_prof_bytecode_lineno(rc, start);
104     uint lasti = 0;
105 
106     const uint buffer_chunk_size = (stop - start) >> 2; // heuristic magic
107     uint buffer_size = buffer_chunk_size;
108     byte *buffer = m_new(byte, buffer_size);
109     uint buffer_index = 0;
110 
111     for (uint i = start; i < stop; ++i) {
112         uint lineno = mp_prof_bytecode_lineno(rc, i);
113         size_t line_diff = lineno - last_lineno;
114         if (line_diff > 0) {
115             uint instr_diff = (i - start) - lasti;
116 
117             assert(instr_diff < 256);
118             assert(line_diff < 256);
119 
120             if (buffer_index + 2 > buffer_size) {
121                 buffer = m_renew(byte, buffer, buffer_size, buffer_size + buffer_chunk_size);
122                 buffer_size = buffer_size + buffer_chunk_size;
123             }
124             last_lineno = lineno;
125             lasti = i - start;
126             buffer[buffer_index++] = instr_diff;
127             buffer[buffer_index++] = line_diff;
128         }
129     }
130 
131     mp_obj_t o = mp_obj_new_bytes(buffer, buffer_index);
132     m_del(byte, buffer, buffer_size);
133     return o;
134 }
135 
code_attr(mp_obj_t self_in,qstr attr,mp_obj_t * dest)136 STATIC void code_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
137     if (dest[0] != MP_OBJ_NULL) {
138         // not load attribute
139         return;
140     }
141     mp_obj_code_t *o = MP_OBJ_TO_PTR(self_in);
142     const mp_raw_code_t *rc = o->rc;
143     const mp_bytecode_prelude_t *prelude = &rc->prelude;
144     switch (attr) {
145         case MP_QSTR_co_code:
146             dest[0] = mp_obj_new_bytes(
147                 (void *)prelude->opcodes,
148                 rc->fun_data_len - (prelude->opcodes - (const byte *)rc->fun_data)
149                 );
150             break;
151         case MP_QSTR_co_consts:
152             dest[0] = MP_OBJ_FROM_PTR(code_consts(rc));
153             break;
154         case MP_QSTR_co_filename:
155             dest[0] = MP_OBJ_NEW_QSTR(prelude->qstr_source_file);
156             break;
157         case MP_QSTR_co_firstlineno:
158             dest[0] = MP_OBJ_NEW_SMALL_INT(mp_prof_bytecode_lineno(rc, 0));
159             break;
160         case MP_QSTR_co_name:
161             dest[0] = MP_OBJ_NEW_QSTR(prelude->qstr_block_name);
162             break;
163         case MP_QSTR_co_names:
164             dest[0] = MP_OBJ_FROM_PTR(o->dict_locals);
165             break;
166         case MP_QSTR_co_lnotab:
167             if (!o->lnotab) {
168                 o->lnotab = raw_code_lnotab(rc);
169             }
170             dest[0] = o->lnotab;
171             break;
172     }
173 }
174 
175 const mp_obj_type_t mp_type_settrace_codeobj = {
176     { &mp_type_type },
177     .name = MP_QSTR_code,
178     .print = code_print,
179     .unary_op = mp_generic_unary_op,
180     .attr = code_attr,
181 };
182 
mp_obj_new_code(const mp_raw_code_t * rc)183 mp_obj_t mp_obj_new_code(const mp_raw_code_t *rc) {
184     mp_obj_code_t *o = m_new_obj_maybe(mp_obj_code_t);
185     if (o == NULL) {
186         return MP_OBJ_NULL;
187     }
188     o->base.type = &mp_type_settrace_codeobj;
189     o->rc = rc;
190     o->dict_locals = mp_locals_get(); // this is a wrong! how to do this properly?
191     o->lnotab = MP_OBJ_NULL;
192     return MP_OBJ_FROM_PTR(o);
193 }
194 
195 /******************************************************************************/
196 // frame object
197 
frame_print(const mp_print_t * print,mp_obj_t o_in,mp_print_kind_t kind)198 STATIC void frame_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
199     (void)kind;
200     mp_obj_frame_t *frame = MP_OBJ_TO_PTR(o_in);
201     mp_obj_code_t *code = frame->code;
202     const mp_raw_code_t *rc = code->rc;
203     const mp_bytecode_prelude_t *prelude = &rc->prelude;
204     mp_printf(print,
205         "<frame at 0x%p, file '%q', line %d, code %q>",
206         frame,
207         prelude->qstr_source_file,
208         frame->lineno,
209         prelude->qstr_block_name
210         );
211 }
212 
frame_attr(mp_obj_t self_in,qstr attr,mp_obj_t * dest)213 STATIC void frame_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
214     if (dest[0] != MP_OBJ_NULL) {
215         // not load attribute
216         return;
217     }
218 
219     mp_obj_frame_t *o = MP_OBJ_TO_PTR(self_in);
220 
221     switch (attr) {
222         case MP_QSTR_f_back:
223             dest[0] = mp_const_none;
224             if (o->code_state->prev_state) {
225                 dest[0] = MP_OBJ_FROM_PTR(o->code_state->prev_state->frame);
226             }
227             break;
228         case MP_QSTR_f_code:
229             dest[0] = MP_OBJ_FROM_PTR(o->code);
230             break;
231         case MP_QSTR_f_globals:
232             dest[0] = MP_OBJ_FROM_PTR(o->code_state->fun_bc->globals);
233             break;
234         case MP_QSTR_f_lasti:
235             dest[0] = MP_OBJ_NEW_SMALL_INT(o->lasti);
236             break;
237         case MP_QSTR_f_lineno:
238             dest[0] = MP_OBJ_NEW_SMALL_INT(o->lineno);
239             break;
240     }
241 }
242 
243 const mp_obj_type_t mp_type_frame = {
244     { &mp_type_type },
245     .name = MP_QSTR_frame,
246     .print = frame_print,
247     .unary_op = mp_generic_unary_op,
248     .attr = frame_attr,
249 };
250 
mp_obj_new_frame(const mp_code_state_t * code_state)251 mp_obj_t mp_obj_new_frame(const mp_code_state_t *code_state) {
252     if (gc_is_locked()) {
253         return MP_OBJ_NULL;
254     }
255 
256     mp_obj_frame_t *o = m_new_obj_maybe(mp_obj_frame_t);
257     if (o == NULL) {
258         return MP_OBJ_NULL;
259     }
260 
261     mp_obj_code_t *code = o->code = MP_OBJ_TO_PTR(mp_obj_new_code(code_state->fun_bc->rc));
262     if (code == NULL) {
263         return MP_OBJ_NULL;
264     }
265 
266     const mp_raw_code_t *rc = code->rc;
267     const mp_bytecode_prelude_t *prelude = &rc->prelude;
268     o->code_state = code_state;
269     o->base.type = &mp_type_frame;
270     o->back = NULL;
271     o->code = code;
272     o->lasti = code_state->ip - prelude->opcodes;
273     o->lineno = mp_prof_bytecode_lineno(rc, o->lasti);
274     o->trace_opcodes = false;
275     o->callback = MP_OBJ_NULL;
276 
277     return MP_OBJ_FROM_PTR(o);
278 }
279 
280 
281 /******************************************************************************/
282 // Trace logic
283 
284 typedef struct {
285     struct _mp_obj_frame_t *frame;
286     mp_obj_t event;
287     mp_obj_t arg;
288 } prof_callback_args_t;
289 
mp_prof_callback_invoke(mp_obj_t callback,prof_callback_args_t * args)290 STATIC mp_obj_t mp_prof_callback_invoke(mp_obj_t callback, prof_callback_args_t *args) {
291     assert(mp_obj_is_callable(callback));
292 
293     mp_prof_is_executing = true;
294 
295     mp_obj_t a[3] = {MP_OBJ_FROM_PTR(args->frame), args->event, args->arg};
296     mp_obj_t top = mp_call_function_n_kw(callback, 3, 0, a);
297 
298     mp_prof_is_executing = false;
299 
300     if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) {
301         mp_handle_pending(true);
302     }
303     return top;
304 }
305 
mp_prof_settrace(mp_obj_t callback)306 mp_obj_t mp_prof_settrace(mp_obj_t callback) {
307     if (mp_obj_is_callable(callback)) {
308         prof_trace_cb = callback;
309     } else {
310         prof_trace_cb = MP_OBJ_NULL;
311     }
312     return mp_const_none;
313 }
314 
mp_prof_frame_enter(mp_code_state_t * code_state)315 mp_obj_t mp_prof_frame_enter(mp_code_state_t *code_state) {
316     assert(!mp_prof_is_executing);
317 
318     mp_obj_frame_t *frame = MP_OBJ_TO_PTR(mp_obj_new_frame(code_state));
319     if (frame == NULL) {
320         // Couldn't allocate a frame object
321         return MP_OBJ_NULL;
322     }
323 
324     if (code_state->prev_state && code_state->frame == NULL) {
325         // We are entering not-yet-traced frame
326         // which means it's a CALL event (not a GENERATOR)
327         // so set the function definition line.
328         const mp_raw_code_t *rc = code_state->fun_bc->rc;
329         frame->lineno = rc->line_of_definition;
330         if (!rc->line_of_definition) {
331             frame->lineno = mp_prof_bytecode_lineno(rc, 0);
332         }
333     }
334     code_state->frame = frame;
335 
336     if (!prof_trace_cb) {
337         return MP_OBJ_NULL;
338     }
339 
340     mp_obj_t top;
341     prof_callback_args_t _args, *args = &_args;
342     args->frame = code_state->frame;
343 
344     // SETTRACE event CALL
345     args->event = MP_OBJ_NEW_QSTR(MP_QSTR_call);
346     args->arg = mp_const_none;
347     top = mp_prof_callback_invoke(prof_trace_cb, args);
348 
349     code_state->frame->callback = mp_obj_is_callable(top) ? top : MP_OBJ_NULL;
350 
351     // Invalidate the last executed line number so the LINE trace can trigger after this CALL.
352     frame->lineno = 0;
353 
354     return top;
355 }
356 
mp_prof_frame_update(const mp_code_state_t * code_state)357 mp_obj_t mp_prof_frame_update(const mp_code_state_t *code_state) {
358     mp_obj_frame_t *frame = code_state->frame;
359     if (frame == NULL) {
360         // Frame was not allocated (eg because there was no memory available)
361         return MP_OBJ_NULL;
362     }
363 
364     mp_obj_frame_t *o = frame;
365     mp_obj_code_t *code = o->code;
366     const mp_raw_code_t *rc = code->rc;
367     const mp_bytecode_prelude_t *prelude = &rc->prelude;
368 
369     assert(o->code_state == code_state);
370 
371     o->lasti = code_state->ip - prelude->opcodes;
372     o->lineno = mp_prof_bytecode_lineno(rc, o->lasti);
373 
374     return MP_OBJ_FROM_PTR(o);
375 }
376 
mp_prof_instr_tick(mp_code_state_t * code_state,bool is_exception)377 mp_obj_t mp_prof_instr_tick(mp_code_state_t *code_state, bool is_exception) {
378     // Detect execution recursion
379     assert(!mp_prof_is_executing);
380     assert(code_state->frame);
381     assert(mp_obj_get_type(code_state->frame) == &mp_type_frame);
382 
383     // Detect data recursion
384     assert(code_state != code_state->prev_state);
385 
386     mp_obj_t top = mp_const_none;
387     mp_obj_t callback = code_state->frame->callback;
388 
389     prof_callback_args_t _args, *args = &_args;
390     args->frame = code_state->frame;
391     args->event = mp_const_none;
392     args->arg = mp_const_none;
393 
394     // Call event's are handled inside mp_prof_frame_enter
395 
396     // SETTRACE event EXCEPTION
397     if (is_exception) {
398         args->event = MP_OBJ_NEW_QSTR(MP_QSTR_exception);
399         top = mp_prof_callback_invoke(callback, args);
400         return top;
401     }
402 
403     // SETTRACE event LINE
404     const mp_raw_code_t *rc = code_state->fun_bc->rc;
405     const mp_bytecode_prelude_t *prelude = &rc->prelude;
406     size_t prev_line_no = args->frame->lineno;
407     size_t current_line_no = mp_prof_bytecode_lineno(rc, code_state->ip - prelude->opcodes);
408     if (prev_line_no != current_line_no) {
409         args->frame->lineno = current_line_no;
410         args->event = MP_OBJ_NEW_QSTR(MP_QSTR_line);
411         top = mp_prof_callback_invoke(callback, args);
412     }
413 
414     // SETTRACE event RETURN
415     const byte *ip = code_state->ip;
416     if (*ip == MP_BC_RETURN_VALUE || *ip == MP_BC_YIELD_VALUE) {
417         args->event = MP_OBJ_NEW_QSTR(MP_QSTR_return);
418         top = mp_prof_callback_invoke(callback, args);
419         if (code_state->prev_state && *ip == MP_BC_RETURN_VALUE) {
420             code_state->frame->callback = MP_OBJ_NULL;
421         }
422     }
423 
424     // SETTRACE event OPCODE
425     // TODO: frame.f_trace_opcodes=True
426     if (false) {
427         args->event = MP_OBJ_NEW_QSTR(MP_QSTR_opcode);
428     }
429 
430     return top;
431 }
432 
433 /******************************************************************************/
434 // DEBUG
435 
436 // This section is for debugging the settrace feature itself, and is not intended
437 // to be included in production/release builds.  The code structure for this block
438 // was taken from py/showbc.c and should not be used as a reference.  To enable
439 // this debug feature enable MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE in py/profile.h.
440 #if MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE
441 
442 #include "runtime0.h"
443 
444 #define DECODE_UINT { \
445         unum = 0; \
446         do { \
447             unum = (unum << 7) + (*ip & 0x7f); \
448         } while ((*ip++ & 0x80) != 0); \
449 }
450 #define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0)
451 #define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0)
452 
453 #define DECODE_QSTR \
454     qst = ip[0] | ip[1] << 8; \
455     ip += 2;
456 #define DECODE_PTR \
457     DECODE_UINT; \
458     ptr = (const byte *)const_table[unum]
459 #define DECODE_OBJ \
460     DECODE_UINT; \
461     obj = (mp_obj_t)const_table[unum]
462 
463 typedef struct _mp_dis_instruction_t {
464     mp_uint_t qstr_opname;
465     mp_uint_t arg;
466     mp_obj_t argobj;
467     mp_obj_t argobjex_cache;
468 } mp_dis_instruction_t;
469 
mp_prof_opcode_decode(const byte * ip,const mp_uint_t * const_table,mp_dis_instruction_t * instruction)470 STATIC const byte *mp_prof_opcode_decode(const byte *ip, const mp_uint_t *const_table, mp_dis_instruction_t *instruction) {
471     mp_uint_t unum;
472     const byte *ptr;
473     mp_obj_t obj;
474     qstr qst;
475 
476     instruction->qstr_opname = MP_QSTR_;
477     instruction->arg = 0;
478     instruction->argobj = mp_const_none;
479     instruction->argobjex_cache = mp_const_none;
480 
481     switch (*ip++) {
482         case MP_BC_LOAD_CONST_FALSE:
483             instruction->qstr_opname = MP_QSTR_LOAD_CONST_FALSE;
484             break;
485 
486         case MP_BC_LOAD_CONST_NONE:
487             instruction->qstr_opname = MP_QSTR_LOAD_CONST_NONE;
488             break;
489 
490         case MP_BC_LOAD_CONST_TRUE:
491             instruction->qstr_opname = MP_QSTR_LOAD_CONST_TRUE;
492             break;
493 
494         case MP_BC_LOAD_CONST_SMALL_INT: {
495             mp_int_t num = 0;
496             if ((ip[0] & 0x40) != 0) {
497                 // Number is negative
498                 num--;
499             }
500             do {
501                 num = (num << 7) | (*ip & 0x7f);
502             } while ((*ip++ & 0x80) != 0);
503             instruction->qstr_opname = MP_QSTR_LOAD_CONST_SMALL_INT;
504             instruction->arg = num;
505             break;
506         }
507 
508         case MP_BC_LOAD_CONST_STRING:
509             DECODE_QSTR;
510             instruction->qstr_opname = MP_QSTR_LOAD_CONST_STRING;
511             instruction->arg = qst;
512             instruction->argobj = MP_OBJ_NEW_QSTR(qst);
513             break;
514 
515         case MP_BC_LOAD_CONST_OBJ:
516             DECODE_OBJ;
517             instruction->qstr_opname = MP_QSTR_LOAD_CONST_OBJ;
518             instruction->arg = unum;
519             instruction->argobj = obj;
520             break;
521 
522         case MP_BC_LOAD_NULL:
523             instruction->qstr_opname = MP_QSTR_LOAD_NULL;
524             break;
525 
526         case MP_BC_LOAD_FAST_N:
527             DECODE_UINT;
528             instruction->qstr_opname = MP_QSTR_LOAD_FAST_N;
529             instruction->arg = unum;
530             break;
531 
532         case MP_BC_LOAD_DEREF:
533             DECODE_UINT;
534             instruction->qstr_opname = MP_QSTR_LOAD_DEREF;
535             instruction->arg = unum;
536             break;
537 
538         case MP_BC_LOAD_NAME:
539             DECODE_QSTR;
540             instruction->qstr_opname = MP_QSTR_LOAD_NAME;
541             instruction->arg = qst;
542             instruction->argobj = MP_OBJ_NEW_QSTR(qst);
543             if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
544                 instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(*ip++);
545             }
546             break;
547 
548         case MP_BC_LOAD_GLOBAL:
549             DECODE_QSTR;
550             instruction->qstr_opname = MP_QSTR_LOAD_GLOBAL;
551             instruction->arg = qst;
552             instruction->argobj = MP_OBJ_NEW_QSTR(qst);
553             if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
554                 instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(*ip++);
555             }
556             break;
557 
558         case MP_BC_LOAD_ATTR:
559             DECODE_QSTR;
560             instruction->qstr_opname = MP_QSTR_LOAD_ATTR;
561             instruction->arg = qst;
562             instruction->argobj = MP_OBJ_NEW_QSTR(qst);
563             if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
564                 instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(*ip++);
565             }
566             break;
567 
568         case MP_BC_LOAD_METHOD:
569             DECODE_QSTR;
570             instruction->qstr_opname = MP_QSTR_LOAD_METHOD;
571             instruction->arg = qst;
572             instruction->argobj = MP_OBJ_NEW_QSTR(qst);
573             break;
574 
575         case MP_BC_LOAD_SUPER_METHOD:
576             DECODE_QSTR;
577             instruction->qstr_opname = MP_QSTR_LOAD_SUPER_METHOD;
578             instruction->arg = qst;
579             instruction->argobj = MP_OBJ_NEW_QSTR(qst);
580             break;
581 
582         case MP_BC_LOAD_BUILD_CLASS:
583             instruction->qstr_opname = MP_QSTR_LOAD_BUILD_CLASS;
584             break;
585 
586         case MP_BC_LOAD_SUBSCR:
587             instruction->qstr_opname = MP_QSTR_LOAD_SUBSCR;
588             break;
589 
590         case MP_BC_STORE_FAST_N:
591             DECODE_UINT;
592             instruction->qstr_opname = MP_QSTR_STORE_FAST_N;
593             instruction->arg = unum;
594             break;
595 
596         case MP_BC_STORE_DEREF:
597             DECODE_UINT;
598             instruction->qstr_opname = MP_QSTR_STORE_DEREF;
599             instruction->arg = unum;
600             break;
601 
602         case MP_BC_STORE_NAME:
603             DECODE_QSTR;
604             instruction->qstr_opname = MP_QSTR_STORE_NAME;
605             instruction->arg = qst;
606             instruction->argobj = MP_OBJ_NEW_QSTR(qst);
607             break;
608 
609         case MP_BC_STORE_GLOBAL:
610             DECODE_QSTR;
611             instruction->qstr_opname = MP_QSTR_STORE_GLOBAL;
612             instruction->arg = qst;
613             instruction->argobj = MP_OBJ_NEW_QSTR(qst);
614             break;
615 
616         case MP_BC_STORE_ATTR:
617             DECODE_QSTR;
618             instruction->qstr_opname = MP_QSTR_STORE_ATTR;
619             instruction->arg = qst;
620             instruction->argobj = MP_OBJ_NEW_QSTR(qst);
621             if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
622                 instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(*ip++);
623             }
624             break;
625 
626         case MP_BC_STORE_SUBSCR:
627             instruction->qstr_opname = MP_QSTR_STORE_SUBSCR;
628             break;
629 
630         case MP_BC_DELETE_FAST:
631             DECODE_UINT;
632             instruction->qstr_opname = MP_QSTR_DELETE_FAST;
633             instruction->arg = unum;
634             break;
635 
636         case MP_BC_DELETE_DEREF:
637             DECODE_UINT;
638             instruction->qstr_opname = MP_QSTR_DELETE_DEREF;
639             instruction->arg = unum;
640             break;
641 
642         case MP_BC_DELETE_NAME:
643             DECODE_QSTR;
644             instruction->qstr_opname = MP_QSTR_DELETE_NAME;
645             instruction->arg = qst;
646             instruction->argobj = MP_OBJ_NEW_QSTR(qst);
647             break;
648 
649         case MP_BC_DELETE_GLOBAL:
650             DECODE_QSTR;
651             instruction->qstr_opname = MP_QSTR_DELETE_GLOBAL;
652             instruction->arg = qst;
653             instruction->argobj = MP_OBJ_NEW_QSTR(qst);
654             break;
655 
656         case MP_BC_DUP_TOP:
657             instruction->qstr_opname = MP_QSTR_DUP_TOP;
658             break;
659 
660         case MP_BC_DUP_TOP_TWO:
661             instruction->qstr_opname = MP_QSTR_DUP_TOP_TWO;
662             break;
663 
664         case MP_BC_POP_TOP:
665             instruction->qstr_opname = MP_QSTR_POP_TOP;
666             break;
667 
668         case MP_BC_ROT_TWO:
669             instruction->qstr_opname = MP_QSTR_ROT_TWO;
670             break;
671 
672         case MP_BC_ROT_THREE:
673             instruction->qstr_opname = MP_QSTR_ROT_THREE;
674             break;
675 
676         case MP_BC_JUMP:
677             DECODE_SLABEL;
678             instruction->qstr_opname = MP_QSTR_JUMP;
679             instruction->arg = unum;
680             break;
681 
682         case MP_BC_POP_JUMP_IF_TRUE:
683             DECODE_SLABEL;
684             instruction->qstr_opname = MP_QSTR_POP_JUMP_IF_TRUE;
685             instruction->arg = unum;
686             break;
687 
688         case MP_BC_POP_JUMP_IF_FALSE:
689             DECODE_SLABEL;
690             instruction->qstr_opname = MP_QSTR_POP_JUMP_IF_FALSE;
691             instruction->arg = unum;
692             break;
693 
694         case MP_BC_JUMP_IF_TRUE_OR_POP:
695             DECODE_SLABEL;
696             instruction->qstr_opname = MP_QSTR_JUMP_IF_TRUE_OR_POP;
697             instruction->arg = unum;
698             break;
699 
700         case MP_BC_JUMP_IF_FALSE_OR_POP:
701             DECODE_SLABEL;
702             instruction->qstr_opname = MP_QSTR_JUMP_IF_FALSE_OR_POP;
703             instruction->arg = unum;
704             break;
705 
706         case MP_BC_SETUP_WITH:
707             DECODE_ULABEL; // loop-like labels are always forward
708             instruction->qstr_opname = MP_QSTR_SETUP_WITH;
709             instruction->arg = unum;
710             break;
711 
712         case MP_BC_WITH_CLEANUP:
713             instruction->qstr_opname = MP_QSTR_WITH_CLEANUP;
714             break;
715 
716         case MP_BC_UNWIND_JUMP:
717             DECODE_SLABEL;
718             instruction->qstr_opname = MP_QSTR_UNWIND_JUMP;
719             instruction->arg = unum;
720             break;
721 
722         case MP_BC_SETUP_EXCEPT:
723             DECODE_ULABEL; // except labels are always forward
724             instruction->qstr_opname = MP_QSTR_SETUP_EXCEPT;
725             instruction->arg = unum;
726             break;
727 
728         case MP_BC_SETUP_FINALLY:
729             DECODE_ULABEL; // except labels are always forward
730             instruction->qstr_opname = MP_QSTR_SETUP_FINALLY;
731             instruction->arg = unum;
732             break;
733 
734         case MP_BC_END_FINALLY:
735             // if TOS is an exception, reraises the exception (3 values on TOS)
736             // if TOS is an integer, does something else
737             // if TOS is None, just pops it and continues
738             // else error
739             instruction->qstr_opname = MP_QSTR_END_FINALLY;
740             break;
741 
742         case MP_BC_GET_ITER:
743             instruction->qstr_opname = MP_QSTR_GET_ITER;
744             break;
745 
746         case MP_BC_GET_ITER_STACK:
747             instruction->qstr_opname = MP_QSTR_GET_ITER_STACK;
748             break;
749 
750         case MP_BC_FOR_ITER:
751             DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
752             instruction->qstr_opname = MP_QSTR_FOR_ITER;
753             instruction->arg = unum;
754             break;
755 
756         case MP_BC_BUILD_TUPLE:
757             DECODE_UINT;
758             instruction->qstr_opname = MP_QSTR_BUILD_TUPLE;
759             instruction->arg = unum;
760             break;
761 
762         case MP_BC_BUILD_LIST:
763             DECODE_UINT;
764             instruction->qstr_opname = MP_QSTR_BUILD_LIST;
765             instruction->arg = unum;
766             break;
767 
768         case MP_BC_BUILD_MAP:
769             DECODE_UINT;
770             instruction->qstr_opname = MP_QSTR_BUILD_MAP;
771             instruction->arg = unum;
772             break;
773 
774         case MP_BC_STORE_MAP:
775             instruction->qstr_opname = MP_QSTR_STORE_MAP;
776             break;
777 
778         case MP_BC_BUILD_SET:
779             DECODE_UINT;
780             instruction->qstr_opname = MP_QSTR_BUILD_SET;
781             instruction->arg = unum;
782             break;
783 
784         #if MICROPY_PY_BUILTINS_SLICE
785         case MP_BC_BUILD_SLICE:
786             DECODE_UINT;
787             instruction->qstr_opname = MP_QSTR_BUILD_SLICE;
788             instruction->arg = unum;
789             break;
790         #endif
791 
792         case MP_BC_STORE_COMP:
793             DECODE_UINT;
794             instruction->qstr_opname = MP_QSTR_STORE_COMP;
795             instruction->arg = unum;
796             break;
797 
798         case MP_BC_UNPACK_SEQUENCE:
799             DECODE_UINT;
800             instruction->qstr_opname = MP_QSTR_UNPACK_SEQUENCE;
801             instruction->arg = unum;
802             break;
803 
804         case MP_BC_UNPACK_EX:
805             DECODE_UINT;
806             instruction->qstr_opname = MP_QSTR_UNPACK_EX;
807             instruction->arg = unum;
808             break;
809 
810         case MP_BC_MAKE_FUNCTION:
811             DECODE_PTR;
812             instruction->qstr_opname = MP_QSTR_MAKE_FUNCTION;
813             instruction->arg = unum;
814             instruction->argobj = mp_obj_new_int_from_ull((uint64_t)ptr);
815             break;
816 
817         case MP_BC_MAKE_FUNCTION_DEFARGS:
818             DECODE_PTR;
819             instruction->qstr_opname = MP_QSTR_MAKE_FUNCTION_DEFARGS;
820             instruction->arg = unum;
821             instruction->argobj = mp_obj_new_int_from_ull((uint64_t)ptr);
822             break;
823 
824         case MP_BC_MAKE_CLOSURE: {
825             DECODE_PTR;
826             mp_uint_t n_closed_over = *ip++;
827             instruction->qstr_opname = MP_QSTR_MAKE_CLOSURE;
828             instruction->arg = unum;
829             instruction->argobj = mp_obj_new_int_from_ull((uint64_t)ptr);
830             instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(n_closed_over);
831             break;
832         }
833 
834         case MP_BC_MAKE_CLOSURE_DEFARGS: {
835             DECODE_PTR;
836             mp_uint_t n_closed_over = *ip++;
837             instruction->qstr_opname = MP_QSTR_MAKE_CLOSURE_DEFARGS;
838             instruction->arg = unum;
839             instruction->argobj = mp_obj_new_int_from_ull((uint64_t)ptr);
840             instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(n_closed_over);
841             break;
842         }
843 
844         case MP_BC_CALL_FUNCTION:
845             DECODE_UINT;
846             instruction->qstr_opname = MP_QSTR_CALL_FUNCTION;
847             instruction->arg = unum & 0xff;
848             instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff);
849             break;
850 
851         case MP_BC_CALL_FUNCTION_VAR_KW:
852             DECODE_UINT;
853             instruction->qstr_opname = MP_QSTR_CALL_FUNCTION_VAR_KW;
854             instruction->arg = unum & 0xff;
855             instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff);
856             break;
857 
858         case MP_BC_CALL_METHOD:
859             DECODE_UINT;
860             instruction->qstr_opname = MP_QSTR_CALL_METHOD;
861             instruction->arg = unum & 0xff;
862             instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff);
863             break;
864 
865         case MP_BC_CALL_METHOD_VAR_KW:
866             DECODE_UINT;
867             instruction->qstr_opname = MP_QSTR_CALL_METHOD_VAR_KW;
868             instruction->arg = unum & 0xff;
869             instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff);
870             break;
871 
872         case MP_BC_RETURN_VALUE:
873             instruction->qstr_opname = MP_QSTR_RETURN_VALUE;
874             break;
875 
876         case MP_BC_RAISE_LAST:
877             instruction->qstr_opname = MP_QSTR_RAISE_LAST;
878             break;
879 
880         case MP_BC_RAISE_OBJ:
881             instruction->qstr_opname = MP_QSTR_RAISE_OBJ;
882             break;
883 
884         case MP_BC_RAISE_FROM:
885             instruction->qstr_opname = MP_QSTR_RAISE_FROM;
886             break;
887 
888         case MP_BC_YIELD_VALUE:
889             instruction->qstr_opname = MP_QSTR_YIELD_VALUE;
890             break;
891 
892         case MP_BC_YIELD_FROM:
893             instruction->qstr_opname = MP_QSTR_YIELD_FROM;
894             break;
895 
896         case MP_BC_IMPORT_NAME:
897             DECODE_QSTR;
898             instruction->qstr_opname = MP_QSTR_IMPORT_NAME;
899             instruction->arg = qst;
900             instruction->argobj = MP_OBJ_NEW_QSTR(qst);
901             break;
902 
903         case MP_BC_IMPORT_FROM:
904             DECODE_QSTR;
905             instruction->qstr_opname = MP_QSTR_IMPORT_FROM;
906             instruction->arg = qst;
907             instruction->argobj = MP_OBJ_NEW_QSTR(qst);
908             break;
909 
910         case MP_BC_IMPORT_STAR:
911             instruction->qstr_opname = MP_QSTR_IMPORT_STAR;
912             break;
913 
914         default:
915             if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
916                 instruction->qstr_opname = MP_QSTR_LOAD_CONST_SMALL_INT;
917                 instruction->arg = (mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16;
918             } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
919                 instruction->qstr_opname = MP_QSTR_LOAD_FAST;
920                 instruction->arg = (mp_uint_t)ip[-1] - MP_BC_LOAD_FAST_MULTI;
921             } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
922                 instruction->qstr_opname = MP_QSTR_STORE_FAST;
923                 instruction->arg = (mp_uint_t)ip[-1] - MP_BC_STORE_FAST_MULTI;
924             } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NUM_BYTECODE) {
925                 instruction->qstr_opname = MP_QSTR_UNARY_OP;
926                 instruction->arg = (mp_uint_t)ip[-1] - MP_BC_UNARY_OP_MULTI;
927             } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + MP_BINARY_OP_NUM_BYTECODE) {
928                 mp_uint_t op = ip[-1] - MP_BC_BINARY_OP_MULTI;
929                 instruction->qstr_opname = MP_QSTR_BINARY_OP;
930                 instruction->arg = op;
931             } else {
932                 mp_printf(&mp_plat_print, "code %p, opcode 0x%02x not implemented\n", ip - 1, ip[-1]);
933                 assert(0);
934                 return ip;
935             }
936             break;
937     }
938 
939     return ip;
940 }
941 
mp_prof_print_instr(const byte * ip,mp_code_state_t * code_state)942 void mp_prof_print_instr(const byte *ip, mp_code_state_t *code_state) {
943     mp_dis_instruction_t _instruction, *instruction = &_instruction;
944     mp_prof_opcode_decode(ip, code_state->fun_bc->rc->const_table, instruction);
945     const mp_raw_code_t *rc = code_state->fun_bc->rc;
946     const mp_bytecode_prelude_t *prelude = &rc->prelude;
947 
948     mp_uint_t offset = ip - prelude->opcodes;
949     mp_printf(&mp_plat_print, "instr");
950 
951     /* long path */ if (1) {
952         mp_printf(&mp_plat_print,
953             "@0x%p:%q:%q+0x%04x:%d",
954             ip,
955             prelude->qstr_source_file,
956             prelude->qstr_block_name,
957             offset,
958             mp_prof_bytecode_lineno(rc, offset)
959             );
960     }
961 
962     /* bytecode */ if (0) {
963         mp_printf(&mp_plat_print, " %02x %02x %02x %02x", ip[0], ip[1], ip[2], ip[3]);
964     }
965 
966     mp_printf(&mp_plat_print, " 0x%02x %q [%d]", *ip, instruction->qstr_opname, instruction->arg);
967 
968     if (instruction->argobj != mp_const_none) {
969         mp_printf(&mp_plat_print, " $");
970         mp_obj_print_helper(&mp_plat_print, instruction->argobj, PRINT_REPR);
971     }
972     if (instruction->argobjex_cache != mp_const_none) {
973         mp_printf(&mp_plat_print, " #");
974         mp_obj_print_helper(&mp_plat_print, instruction->argobjex_cache, PRINT_REPR);
975     }
976 
977     mp_printf(&mp_plat_print, "\n");
978 }
979 
980 #endif // MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE
981 
982 #endif // MICROPY_PY_SYS_SETTRACE
983