profile.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  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. #include "py/profile.h"
  27. #include "py/bc0.h"
  28. #include "py/gc.h"
  29. #include "py/objfun.h"
  30. #if MICROPY_PY_SYS_SETTRACE
  31. #if !MICROPY_PERSISTENT_CODE_SAVE
  32. // The settrace feature requires that we maintain additional metadata on the raw
  33. // code object which is normally only done when writing .mpy files.
  34. #error "MICROPY_PY_SYS_SETTRACE requires MICROPY_PERSISTENT_CODE_SAVE to be enabled"
  35. #endif
  36. #define prof_trace_cb MP_STATE_THREAD(prof_trace_callback)
  37. #define QSTR_MAP(context, idx) (context->constants.qstr_table[idx])
  38. static uint mp_prof_bytecode_lineno(const mp_raw_code_t *rc, size_t bc) {
  39. const mp_bytecode_prelude_t *prelude = &rc->prelude;
  40. return mp_bytecode_get_source_line(prelude->line_info, prelude->line_info_top, bc);
  41. }
  42. void mp_prof_extract_prelude(const byte *bytecode, mp_bytecode_prelude_t *prelude) {
  43. const byte *ip = bytecode;
  44. MP_BC_PRELUDE_SIG_DECODE(ip);
  45. prelude->n_state = n_state;
  46. prelude->n_exc_stack = n_exc_stack;
  47. prelude->scope_flags = scope_flags;
  48. prelude->n_pos_args = n_pos_args;
  49. prelude->n_kwonly_args = n_kwonly_args;
  50. prelude->n_def_pos_args = n_def_pos_args;
  51. MP_BC_PRELUDE_SIZE_DECODE(ip);
  52. prelude->line_info_top = ip + n_info;
  53. prelude->opcodes = ip + n_info + n_cell;
  54. prelude->qstr_block_name_idx = mp_decode_uint_value(ip);
  55. for (size_t i = 0; i < 1 + n_pos_args + n_kwonly_args; ++i) {
  56. ip = mp_decode_uint_skip(ip);
  57. }
  58. prelude->line_info = ip;
  59. }
  60. /******************************************************************************/
  61. // code object
  62. static void code_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
  63. (void)kind;
  64. mp_obj_code_t *o = MP_OBJ_TO_PTR(o_in);
  65. const mp_raw_code_t *rc = o->rc;
  66. const mp_bytecode_prelude_t *prelude = &rc->prelude;
  67. mp_printf(print,
  68. "<code object %q at 0x%p, file \"%q\", line %d>",
  69. QSTR_MAP(o->context, prelude->qstr_block_name_idx),
  70. o,
  71. QSTR_MAP(o->context, 0),
  72. rc->line_of_definition
  73. );
  74. }
  75. static mp_obj_tuple_t *code_consts(const mp_module_context_t *context, const mp_raw_code_t *rc) {
  76. mp_obj_tuple_t *consts = MP_OBJ_TO_PTR(mp_obj_new_tuple(rc->n_children + 1, NULL));
  77. size_t const_no = 0;
  78. for (size_t i = 0; i < rc->n_children; ++i) {
  79. mp_obj_t code = mp_obj_new_code(context, rc->children[i]);
  80. if (code == MP_OBJ_NULL) {
  81. m_malloc_fail(sizeof(mp_obj_code_t));
  82. }
  83. consts->items[const_no++] = code;
  84. }
  85. consts->items[const_no++] = mp_const_none;
  86. return consts;
  87. }
  88. static mp_obj_t raw_code_lnotab(const mp_raw_code_t *rc) {
  89. // const mp_bytecode_prelude_t *prelude = &rc->prelude;
  90. uint start = 0;
  91. uint stop = rc->fun_data_len - start;
  92. uint last_lineno = mp_prof_bytecode_lineno(rc, start);
  93. uint lasti = 0;
  94. const uint buffer_chunk_size = (stop - start) >> 2; // heuristic magic
  95. uint buffer_size = buffer_chunk_size;
  96. byte *buffer = m_new(byte, buffer_size);
  97. uint buffer_index = 0;
  98. for (uint i = start; i < stop; ++i) {
  99. uint lineno = mp_prof_bytecode_lineno(rc, i);
  100. size_t line_diff = lineno - last_lineno;
  101. if (line_diff > 0) {
  102. uint instr_diff = (i - start) - lasti;
  103. assert(instr_diff < 256);
  104. assert(line_diff < 256);
  105. if (buffer_index + 2 > buffer_size) {
  106. buffer = m_renew(byte, buffer, buffer_size, buffer_size + buffer_chunk_size);
  107. buffer_size = buffer_size + buffer_chunk_size;
  108. }
  109. last_lineno = lineno;
  110. lasti = i - start;
  111. buffer[buffer_index++] = instr_diff;
  112. buffer[buffer_index++] = line_diff;
  113. }
  114. }
  115. mp_obj_t o = mp_obj_new_bytes(buffer, buffer_index);
  116. m_del(byte, buffer, buffer_size);
  117. return o;
  118. }
  119. static void code_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
  120. if (dest[0] != MP_OBJ_NULL) {
  121. // not load attribute
  122. return;
  123. }
  124. mp_obj_code_t *o = MP_OBJ_TO_PTR(self_in);
  125. const mp_raw_code_t *rc = o->rc;
  126. const mp_bytecode_prelude_t *prelude = &rc->prelude;
  127. switch (attr) {
  128. case MP_QSTR_co_code:
  129. dest[0] = mp_obj_new_bytes(
  130. (void *)prelude->opcodes,
  131. rc->fun_data_len - (prelude->opcodes - (const byte *)rc->fun_data)
  132. );
  133. break;
  134. case MP_QSTR_co_consts:
  135. dest[0] = MP_OBJ_FROM_PTR(code_consts(o->context, rc));
  136. break;
  137. case MP_QSTR_co_filename:
  138. dest[0] = MP_OBJ_NEW_QSTR(QSTR_MAP(o->context, 0));
  139. break;
  140. case MP_QSTR_co_firstlineno:
  141. dest[0] = MP_OBJ_NEW_SMALL_INT(mp_prof_bytecode_lineno(rc, 0));
  142. break;
  143. case MP_QSTR_co_name:
  144. dest[0] = MP_OBJ_NEW_QSTR(QSTR_MAP(o->context, prelude->qstr_block_name_idx));
  145. break;
  146. case MP_QSTR_co_names:
  147. dest[0] = MP_OBJ_FROM_PTR(o->dict_locals);
  148. break;
  149. case MP_QSTR_co_lnotab:
  150. if (!o->lnotab) {
  151. o->lnotab = raw_code_lnotab(rc);
  152. }
  153. dest[0] = o->lnotab;
  154. break;
  155. }
  156. }
  157. MP_DEFINE_CONST_OBJ_TYPE(
  158. mp_type_settrace_codeobj,
  159. MP_QSTR_code,
  160. MP_TYPE_FLAG_NONE,
  161. print, code_print,
  162. attr, code_attr
  163. );
  164. mp_obj_t mp_obj_new_code(const mp_module_context_t *context, const mp_raw_code_t *rc) {
  165. mp_obj_code_t *o = m_new_obj_maybe(mp_obj_code_t);
  166. if (o == NULL) {
  167. return MP_OBJ_NULL;
  168. }
  169. o->base.type = &mp_type_settrace_codeobj;
  170. o->context = context;
  171. o->rc = rc;
  172. o->dict_locals = mp_locals_get(); // this is a wrong! how to do this properly?
  173. o->lnotab = MP_OBJ_NULL;
  174. return MP_OBJ_FROM_PTR(o);
  175. }
  176. /******************************************************************************/
  177. // frame object
  178. static void frame_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
  179. (void)kind;
  180. mp_obj_frame_t *frame = MP_OBJ_TO_PTR(o_in);
  181. mp_obj_code_t *code = frame->code;
  182. const mp_raw_code_t *rc = code->rc;
  183. const mp_bytecode_prelude_t *prelude = &rc->prelude;
  184. mp_printf(print,
  185. "<frame at 0x%p, file '%q', line %d, code %q>",
  186. frame,
  187. QSTR_MAP(code->context, 0),
  188. frame->lineno,
  189. QSTR_MAP(code->context, prelude->qstr_block_name_idx)
  190. );
  191. }
  192. static void frame_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
  193. if (dest[0] != MP_OBJ_NULL) {
  194. // not load attribute
  195. return;
  196. }
  197. mp_obj_frame_t *o = MP_OBJ_TO_PTR(self_in);
  198. switch (attr) {
  199. case MP_QSTR_f_back:
  200. dest[0] = mp_const_none;
  201. if (o->code_state->prev_state) {
  202. dest[0] = MP_OBJ_FROM_PTR(o->code_state->prev_state->frame);
  203. }
  204. break;
  205. case MP_QSTR_f_code:
  206. dest[0] = MP_OBJ_FROM_PTR(o->code);
  207. break;
  208. case MP_QSTR_f_globals:
  209. dest[0] = MP_OBJ_FROM_PTR(o->code_state->fun_bc->context->module.globals);
  210. break;
  211. case MP_QSTR_f_lasti:
  212. dest[0] = MP_OBJ_NEW_SMALL_INT(o->lasti);
  213. break;
  214. case MP_QSTR_f_lineno:
  215. dest[0] = MP_OBJ_NEW_SMALL_INT(o->lineno);
  216. break;
  217. }
  218. }
  219. MP_DEFINE_CONST_OBJ_TYPE(
  220. mp_type_frame,
  221. MP_QSTR_frame,
  222. MP_TYPE_FLAG_NONE,
  223. print, frame_print,
  224. attr, frame_attr
  225. );
  226. mp_obj_t mp_obj_new_frame(const mp_code_state_t *code_state) {
  227. if (gc_is_locked()) {
  228. return MP_OBJ_NULL;
  229. }
  230. mp_obj_frame_t *o = m_new_obj_maybe(mp_obj_frame_t);
  231. if (o == NULL) {
  232. return MP_OBJ_NULL;
  233. }
  234. mp_obj_code_t *code = o->code = MP_OBJ_TO_PTR(mp_obj_new_code(code_state->fun_bc->context, code_state->fun_bc->rc));
  235. if (code == NULL) {
  236. return MP_OBJ_NULL;
  237. }
  238. const mp_raw_code_t *rc = code->rc;
  239. const mp_bytecode_prelude_t *prelude = &rc->prelude;
  240. o->code_state = code_state;
  241. o->base.type = &mp_type_frame;
  242. o->back = NULL;
  243. o->code = code;
  244. o->lasti = code_state->ip - prelude->opcodes;
  245. o->lineno = mp_prof_bytecode_lineno(rc, o->lasti);
  246. o->trace_opcodes = false;
  247. o->callback = MP_OBJ_NULL;
  248. return MP_OBJ_FROM_PTR(o);
  249. }
  250. /******************************************************************************/
  251. // Trace logic
  252. typedef struct {
  253. struct _mp_obj_frame_t *frame;
  254. mp_obj_t event;
  255. mp_obj_t arg;
  256. } prof_callback_args_t;
  257. static mp_obj_t mp_prof_callback_invoke(mp_obj_t callback, prof_callback_args_t *args) {
  258. assert(mp_obj_is_callable(callback));
  259. mp_prof_is_executing = true;
  260. mp_obj_t a[3] = {MP_OBJ_FROM_PTR(args->frame), args->event, args->arg};
  261. mp_obj_t top = mp_call_function_n_kw(callback, 3, 0, a);
  262. mp_prof_is_executing = false;
  263. if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) {
  264. mp_handle_pending(true);
  265. }
  266. return top;
  267. }
  268. mp_obj_t mp_prof_settrace(mp_obj_t callback) {
  269. if (mp_obj_is_callable(callback)) {
  270. prof_trace_cb = callback;
  271. } else {
  272. prof_trace_cb = MP_OBJ_NULL;
  273. }
  274. return mp_const_none;
  275. }
  276. mp_obj_t mp_prof_frame_enter(mp_code_state_t *code_state) {
  277. assert(!mp_prof_is_executing);
  278. mp_obj_frame_t *frame = MP_OBJ_TO_PTR(mp_obj_new_frame(code_state));
  279. if (frame == NULL) {
  280. // Couldn't allocate a frame object
  281. return MP_OBJ_NULL;
  282. }
  283. if (code_state->prev_state && code_state->frame == NULL) {
  284. // We are entering not-yet-traced frame
  285. // which means it's a CALL event (not a GENERATOR)
  286. // so set the function definition line.
  287. const mp_raw_code_t *rc = code_state->fun_bc->rc;
  288. frame->lineno = rc->line_of_definition;
  289. if (!rc->line_of_definition) {
  290. frame->lineno = mp_prof_bytecode_lineno(rc, 0);
  291. }
  292. }
  293. code_state->frame = frame;
  294. if (!prof_trace_cb) {
  295. return MP_OBJ_NULL;
  296. }
  297. mp_obj_t top;
  298. prof_callback_args_t _args, *args = &_args;
  299. args->frame = code_state->frame;
  300. // SETTRACE event CALL
  301. args->event = MP_OBJ_NEW_QSTR(MP_QSTR_call);
  302. args->arg = mp_const_none;
  303. top = mp_prof_callback_invoke(prof_trace_cb, args);
  304. code_state->frame->callback = mp_obj_is_callable(top) ? top : MP_OBJ_NULL;
  305. // Invalidate the last executed line number so the LINE trace can trigger after this CALL.
  306. frame->lineno = 0;
  307. return top;
  308. }
  309. mp_obj_t mp_prof_frame_update(const mp_code_state_t *code_state) {
  310. mp_obj_frame_t *frame = code_state->frame;
  311. if (frame == NULL) {
  312. // Frame was not allocated (eg because there was no memory available)
  313. return MP_OBJ_NULL;
  314. }
  315. mp_obj_frame_t *o = frame;
  316. mp_obj_code_t *code = o->code;
  317. const mp_raw_code_t *rc = code->rc;
  318. const mp_bytecode_prelude_t *prelude = &rc->prelude;
  319. assert(o->code_state == code_state);
  320. o->lasti = code_state->ip - prelude->opcodes;
  321. o->lineno = mp_prof_bytecode_lineno(rc, o->lasti);
  322. return MP_OBJ_FROM_PTR(o);
  323. }
  324. mp_obj_t mp_prof_instr_tick(mp_code_state_t *code_state, bool is_exception) {
  325. // Detect execution recursion
  326. assert(!mp_prof_is_executing);
  327. assert(code_state->frame);
  328. assert(mp_obj_get_type(code_state->frame) == &mp_type_frame);
  329. // Detect data recursion
  330. assert(code_state != code_state->prev_state);
  331. mp_obj_t top = mp_const_none;
  332. mp_obj_t callback = code_state->frame->callback;
  333. prof_callback_args_t _args, *args = &_args;
  334. args->frame = code_state->frame;
  335. args->event = mp_const_none;
  336. args->arg = mp_const_none;
  337. // Call event's are handled inside mp_prof_frame_enter
  338. // SETTRACE event EXCEPTION
  339. if (is_exception) {
  340. args->event = MP_OBJ_NEW_QSTR(MP_QSTR_exception);
  341. top = mp_prof_callback_invoke(callback, args);
  342. return top;
  343. }
  344. // SETTRACE event LINE
  345. const mp_raw_code_t *rc = code_state->fun_bc->rc;
  346. const mp_bytecode_prelude_t *prelude = &rc->prelude;
  347. size_t prev_line_no = args->frame->lineno;
  348. size_t current_line_no = mp_prof_bytecode_lineno(rc, code_state->ip - prelude->opcodes);
  349. if (prev_line_no != current_line_no) {
  350. args->frame->lineno = current_line_no;
  351. args->event = MP_OBJ_NEW_QSTR(MP_QSTR_line);
  352. top = mp_prof_callback_invoke(callback, args);
  353. }
  354. // SETTRACE event RETURN
  355. const byte *ip = code_state->ip;
  356. if (*ip == MP_BC_RETURN_VALUE || *ip == MP_BC_YIELD_VALUE) {
  357. args->event = MP_OBJ_NEW_QSTR(MP_QSTR_return);
  358. top = mp_prof_callback_invoke(callback, args);
  359. if (code_state->prev_state && *ip == MP_BC_RETURN_VALUE) {
  360. code_state->frame->callback = MP_OBJ_NULL;
  361. }
  362. }
  363. // SETTRACE event OPCODE
  364. // TODO: frame.f_trace_opcodes=True
  365. if (false) {
  366. args->event = MP_OBJ_NEW_QSTR(MP_QSTR_opcode);
  367. }
  368. return top;
  369. }
  370. /******************************************************************************/
  371. // DEBUG
  372. // This section is for debugging the settrace feature itself, and is not intended
  373. // to be included in production/release builds. The code structure for this block
  374. // was taken from py/showbc.c and should not be used as a reference. To enable
  375. // this debug feature enable MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE in py/profile.h.
  376. #if MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE
  377. #include "runtime0.h"
  378. #define DECODE_UINT { \
  379. unum = 0; \
  380. do { \
  381. unum = (unum << 7) + (*ip & 0x7f); \
  382. } while ((*ip++ & 0x80) != 0); \
  383. }
  384. #define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0)
  385. #define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0)
  386. #define DECODE_QSTR \
  387. qst = ip[0] | ip[1] << 8; \
  388. ip += 2;
  389. #define DECODE_PTR \
  390. DECODE_UINT; \
  391. ptr = (const byte *)const_table[unum]
  392. #define DECODE_OBJ \
  393. DECODE_UINT; \
  394. obj = (mp_obj_t)const_table[unum]
  395. typedef struct _mp_dis_instruction_t {
  396. mp_uint_t qstr_opname;
  397. mp_uint_t arg;
  398. mp_obj_t argobj;
  399. mp_obj_t argobjex_cache;
  400. } mp_dis_instruction_t;
  401. static const byte *mp_prof_opcode_decode(const byte *ip, const mp_uint_t *const_table, mp_dis_instruction_t *instruction) {
  402. mp_uint_t unum;
  403. const byte *ptr;
  404. mp_obj_t obj;
  405. qstr qst;
  406. instruction->qstr_opname = MP_QSTR_;
  407. instruction->arg = 0;
  408. instruction->argobj = mp_const_none;
  409. instruction->argobjex_cache = mp_const_none;
  410. switch (*ip++) {
  411. case MP_BC_LOAD_CONST_FALSE:
  412. instruction->qstr_opname = MP_QSTR_LOAD_CONST_FALSE;
  413. break;
  414. case MP_BC_LOAD_CONST_NONE:
  415. instruction->qstr_opname = MP_QSTR_LOAD_CONST_NONE;
  416. break;
  417. case MP_BC_LOAD_CONST_TRUE:
  418. instruction->qstr_opname = MP_QSTR_LOAD_CONST_TRUE;
  419. break;
  420. case MP_BC_LOAD_CONST_SMALL_INT: {
  421. mp_int_t num = 0;
  422. if ((ip[0] & 0x40) != 0) {
  423. // Number is negative
  424. num--;
  425. }
  426. do {
  427. num = (num << 7) | (*ip & 0x7f);
  428. } while ((*ip++ & 0x80) != 0);
  429. instruction->qstr_opname = MP_QSTR_LOAD_CONST_SMALL_INT;
  430. instruction->arg = num;
  431. break;
  432. }
  433. case MP_BC_LOAD_CONST_STRING:
  434. DECODE_QSTR;
  435. instruction->qstr_opname = MP_QSTR_LOAD_CONST_STRING;
  436. instruction->arg = qst;
  437. instruction->argobj = MP_OBJ_NEW_QSTR(qst);
  438. break;
  439. case MP_BC_LOAD_CONST_OBJ:
  440. DECODE_OBJ;
  441. instruction->qstr_opname = MP_QSTR_LOAD_CONST_OBJ;
  442. instruction->arg = unum;
  443. instruction->argobj = obj;
  444. break;
  445. case MP_BC_LOAD_NULL:
  446. instruction->qstr_opname = MP_QSTR_LOAD_NULL;
  447. break;
  448. case MP_BC_LOAD_FAST_N:
  449. DECODE_UINT;
  450. instruction->qstr_opname = MP_QSTR_LOAD_FAST_N;
  451. instruction->arg = unum;
  452. break;
  453. case MP_BC_LOAD_DEREF:
  454. DECODE_UINT;
  455. instruction->qstr_opname = MP_QSTR_LOAD_DEREF;
  456. instruction->arg = unum;
  457. break;
  458. case MP_BC_LOAD_NAME:
  459. DECODE_QSTR;
  460. instruction->qstr_opname = MP_QSTR_LOAD_NAME;
  461. instruction->arg = qst;
  462. instruction->argobj = MP_OBJ_NEW_QSTR(qst);
  463. break;
  464. case MP_BC_LOAD_GLOBAL:
  465. DECODE_QSTR;
  466. instruction->qstr_opname = MP_QSTR_LOAD_GLOBAL;
  467. instruction->arg = qst;
  468. instruction->argobj = MP_OBJ_NEW_QSTR(qst);
  469. break;
  470. case MP_BC_LOAD_ATTR:
  471. DECODE_QSTR;
  472. instruction->qstr_opname = MP_QSTR_LOAD_ATTR;
  473. instruction->arg = qst;
  474. instruction->argobj = MP_OBJ_NEW_QSTR(qst);
  475. break;
  476. case MP_BC_LOAD_METHOD:
  477. DECODE_QSTR;
  478. instruction->qstr_opname = MP_QSTR_LOAD_METHOD;
  479. instruction->arg = qst;
  480. instruction->argobj = MP_OBJ_NEW_QSTR(qst);
  481. break;
  482. case MP_BC_LOAD_SUPER_METHOD:
  483. DECODE_QSTR;
  484. instruction->qstr_opname = MP_QSTR_LOAD_SUPER_METHOD;
  485. instruction->arg = qst;
  486. instruction->argobj = MP_OBJ_NEW_QSTR(qst);
  487. break;
  488. case MP_BC_LOAD_BUILD_CLASS:
  489. instruction->qstr_opname = MP_QSTR_LOAD_BUILD_CLASS;
  490. break;
  491. case MP_BC_LOAD_SUBSCR:
  492. instruction->qstr_opname = MP_QSTR_LOAD_SUBSCR;
  493. break;
  494. case MP_BC_STORE_FAST_N:
  495. DECODE_UINT;
  496. instruction->qstr_opname = MP_QSTR_STORE_FAST_N;
  497. instruction->arg = unum;
  498. break;
  499. case MP_BC_STORE_DEREF:
  500. DECODE_UINT;
  501. instruction->qstr_opname = MP_QSTR_STORE_DEREF;
  502. instruction->arg = unum;
  503. break;
  504. case MP_BC_STORE_NAME:
  505. DECODE_QSTR;
  506. instruction->qstr_opname = MP_QSTR_STORE_NAME;
  507. instruction->arg = qst;
  508. instruction->argobj = MP_OBJ_NEW_QSTR(qst);
  509. break;
  510. case MP_BC_STORE_GLOBAL:
  511. DECODE_QSTR;
  512. instruction->qstr_opname = MP_QSTR_STORE_GLOBAL;
  513. instruction->arg = qst;
  514. instruction->argobj = MP_OBJ_NEW_QSTR(qst);
  515. break;
  516. case MP_BC_STORE_ATTR:
  517. DECODE_QSTR;
  518. instruction->qstr_opname = MP_QSTR_STORE_ATTR;
  519. instruction->arg = qst;
  520. instruction->argobj = MP_OBJ_NEW_QSTR(qst);
  521. break;
  522. case MP_BC_STORE_SUBSCR:
  523. instruction->qstr_opname = MP_QSTR_STORE_SUBSCR;
  524. break;
  525. case MP_BC_DELETE_FAST:
  526. DECODE_UINT;
  527. instruction->qstr_opname = MP_QSTR_DELETE_FAST;
  528. instruction->arg = unum;
  529. break;
  530. case MP_BC_DELETE_DEREF:
  531. DECODE_UINT;
  532. instruction->qstr_opname = MP_QSTR_DELETE_DEREF;
  533. instruction->arg = unum;
  534. break;
  535. case MP_BC_DELETE_NAME:
  536. DECODE_QSTR;
  537. instruction->qstr_opname = MP_QSTR_DELETE_NAME;
  538. instruction->arg = qst;
  539. instruction->argobj = MP_OBJ_NEW_QSTR(qst);
  540. break;
  541. case MP_BC_DELETE_GLOBAL:
  542. DECODE_QSTR;
  543. instruction->qstr_opname = MP_QSTR_DELETE_GLOBAL;
  544. instruction->arg = qst;
  545. instruction->argobj = MP_OBJ_NEW_QSTR(qst);
  546. break;
  547. case MP_BC_DUP_TOP:
  548. instruction->qstr_opname = MP_QSTR_DUP_TOP;
  549. break;
  550. case MP_BC_DUP_TOP_TWO:
  551. instruction->qstr_opname = MP_QSTR_DUP_TOP_TWO;
  552. break;
  553. case MP_BC_POP_TOP:
  554. instruction->qstr_opname = MP_QSTR_POP_TOP;
  555. break;
  556. case MP_BC_ROT_TWO:
  557. instruction->qstr_opname = MP_QSTR_ROT_TWO;
  558. break;
  559. case MP_BC_ROT_THREE:
  560. instruction->qstr_opname = MP_QSTR_ROT_THREE;
  561. break;
  562. case MP_BC_JUMP:
  563. DECODE_SLABEL;
  564. instruction->qstr_opname = MP_QSTR_JUMP;
  565. instruction->arg = unum;
  566. break;
  567. case MP_BC_POP_JUMP_IF_TRUE:
  568. DECODE_SLABEL;
  569. instruction->qstr_opname = MP_QSTR_POP_JUMP_IF_TRUE;
  570. instruction->arg = unum;
  571. break;
  572. case MP_BC_POP_JUMP_IF_FALSE:
  573. DECODE_SLABEL;
  574. instruction->qstr_opname = MP_QSTR_POP_JUMP_IF_FALSE;
  575. instruction->arg = unum;
  576. break;
  577. case MP_BC_JUMP_IF_TRUE_OR_POP:
  578. DECODE_SLABEL;
  579. instruction->qstr_opname = MP_QSTR_JUMP_IF_TRUE_OR_POP;
  580. instruction->arg = unum;
  581. break;
  582. case MP_BC_JUMP_IF_FALSE_OR_POP:
  583. DECODE_SLABEL;
  584. instruction->qstr_opname = MP_QSTR_JUMP_IF_FALSE_OR_POP;
  585. instruction->arg = unum;
  586. break;
  587. case MP_BC_SETUP_WITH:
  588. DECODE_ULABEL; // loop-like labels are always forward
  589. instruction->qstr_opname = MP_QSTR_SETUP_WITH;
  590. instruction->arg = unum;
  591. break;
  592. case MP_BC_WITH_CLEANUP:
  593. instruction->qstr_opname = MP_QSTR_WITH_CLEANUP;
  594. break;
  595. case MP_BC_UNWIND_JUMP:
  596. DECODE_SLABEL;
  597. instruction->qstr_opname = MP_QSTR_UNWIND_JUMP;
  598. instruction->arg = unum;
  599. break;
  600. case MP_BC_SETUP_EXCEPT:
  601. DECODE_ULABEL; // except labels are always forward
  602. instruction->qstr_opname = MP_QSTR_SETUP_EXCEPT;
  603. instruction->arg = unum;
  604. break;
  605. case MP_BC_SETUP_FINALLY:
  606. DECODE_ULABEL; // except labels are always forward
  607. instruction->qstr_opname = MP_QSTR_SETUP_FINALLY;
  608. instruction->arg = unum;
  609. break;
  610. case MP_BC_END_FINALLY:
  611. // if TOS is an exception, reraises the exception (3 values on TOS)
  612. // if TOS is an integer, does something else
  613. // if TOS is None, just pops it and continues
  614. // else error
  615. instruction->qstr_opname = MP_QSTR_END_FINALLY;
  616. break;
  617. case MP_BC_GET_ITER:
  618. instruction->qstr_opname = MP_QSTR_GET_ITER;
  619. break;
  620. case MP_BC_GET_ITER_STACK:
  621. instruction->qstr_opname = MP_QSTR_GET_ITER_STACK;
  622. break;
  623. case MP_BC_FOR_ITER:
  624. DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
  625. instruction->qstr_opname = MP_QSTR_FOR_ITER;
  626. instruction->arg = unum;
  627. break;
  628. case MP_BC_BUILD_TUPLE:
  629. DECODE_UINT;
  630. instruction->qstr_opname = MP_QSTR_BUILD_TUPLE;
  631. instruction->arg = unum;
  632. break;
  633. case MP_BC_BUILD_LIST:
  634. DECODE_UINT;
  635. instruction->qstr_opname = MP_QSTR_BUILD_LIST;
  636. instruction->arg = unum;
  637. break;
  638. case MP_BC_BUILD_MAP:
  639. DECODE_UINT;
  640. instruction->qstr_opname = MP_QSTR_BUILD_MAP;
  641. instruction->arg = unum;
  642. break;
  643. case MP_BC_STORE_MAP:
  644. instruction->qstr_opname = MP_QSTR_STORE_MAP;
  645. break;
  646. case MP_BC_BUILD_SET:
  647. DECODE_UINT;
  648. instruction->qstr_opname = MP_QSTR_BUILD_SET;
  649. instruction->arg = unum;
  650. break;
  651. #if MICROPY_PY_BUILTINS_SLICE
  652. case MP_BC_BUILD_SLICE:
  653. DECODE_UINT;
  654. instruction->qstr_opname = MP_QSTR_BUILD_SLICE;
  655. instruction->arg = unum;
  656. break;
  657. #endif
  658. case MP_BC_STORE_COMP:
  659. DECODE_UINT;
  660. instruction->qstr_opname = MP_QSTR_STORE_COMP;
  661. instruction->arg = unum;
  662. break;
  663. case MP_BC_UNPACK_SEQUENCE:
  664. DECODE_UINT;
  665. instruction->qstr_opname = MP_QSTR_UNPACK_SEQUENCE;
  666. instruction->arg = unum;
  667. break;
  668. case MP_BC_UNPACK_EX:
  669. DECODE_UINT;
  670. instruction->qstr_opname = MP_QSTR_UNPACK_EX;
  671. instruction->arg = unum;
  672. break;
  673. case MP_BC_MAKE_FUNCTION:
  674. DECODE_PTR;
  675. instruction->qstr_opname = MP_QSTR_MAKE_FUNCTION;
  676. instruction->arg = unum;
  677. instruction->argobj = mp_obj_new_int_from_ull((uint64_t)ptr);
  678. break;
  679. case MP_BC_MAKE_FUNCTION_DEFARGS:
  680. DECODE_PTR;
  681. instruction->qstr_opname = MP_QSTR_MAKE_FUNCTION_DEFARGS;
  682. instruction->arg = unum;
  683. instruction->argobj = mp_obj_new_int_from_ull((uint64_t)ptr);
  684. break;
  685. case MP_BC_MAKE_CLOSURE: {
  686. DECODE_PTR;
  687. mp_uint_t n_closed_over = *ip++;
  688. instruction->qstr_opname = MP_QSTR_MAKE_CLOSURE;
  689. instruction->arg = unum;
  690. instruction->argobj = mp_obj_new_int_from_ull((uint64_t)ptr);
  691. instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(n_closed_over);
  692. break;
  693. }
  694. case MP_BC_MAKE_CLOSURE_DEFARGS: {
  695. DECODE_PTR;
  696. mp_uint_t n_closed_over = *ip++;
  697. instruction->qstr_opname = MP_QSTR_MAKE_CLOSURE_DEFARGS;
  698. instruction->arg = unum;
  699. instruction->argobj = mp_obj_new_int_from_ull((uint64_t)ptr);
  700. instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(n_closed_over);
  701. break;
  702. }
  703. case MP_BC_CALL_FUNCTION:
  704. DECODE_UINT;
  705. instruction->qstr_opname = MP_QSTR_CALL_FUNCTION;
  706. instruction->arg = unum & 0xff;
  707. instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff);
  708. break;
  709. case MP_BC_CALL_FUNCTION_VAR_KW:
  710. DECODE_UINT;
  711. instruction->qstr_opname = MP_QSTR_CALL_FUNCTION_VAR_KW;
  712. instruction->arg = unum & 0xff;
  713. instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff);
  714. break;
  715. case MP_BC_CALL_METHOD:
  716. DECODE_UINT;
  717. instruction->qstr_opname = MP_QSTR_CALL_METHOD;
  718. instruction->arg = unum & 0xff;
  719. instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff);
  720. break;
  721. case MP_BC_CALL_METHOD_VAR_KW:
  722. DECODE_UINT;
  723. instruction->qstr_opname = MP_QSTR_CALL_METHOD_VAR_KW;
  724. instruction->arg = unum & 0xff;
  725. instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff);
  726. break;
  727. case MP_BC_RETURN_VALUE:
  728. instruction->qstr_opname = MP_QSTR_RETURN_VALUE;
  729. break;
  730. case MP_BC_RAISE_LAST:
  731. instruction->qstr_opname = MP_QSTR_RAISE_LAST;
  732. break;
  733. case MP_BC_RAISE_OBJ:
  734. instruction->qstr_opname = MP_QSTR_RAISE_OBJ;
  735. break;
  736. case MP_BC_RAISE_FROM:
  737. instruction->qstr_opname = MP_QSTR_RAISE_FROM;
  738. break;
  739. case MP_BC_YIELD_VALUE:
  740. instruction->qstr_opname = MP_QSTR_YIELD_VALUE;
  741. break;
  742. case MP_BC_YIELD_FROM:
  743. instruction->qstr_opname = MP_QSTR_YIELD_FROM;
  744. break;
  745. case MP_BC_IMPORT_NAME:
  746. DECODE_QSTR;
  747. instruction->qstr_opname = MP_QSTR_IMPORT_NAME;
  748. instruction->arg = qst;
  749. instruction->argobj = MP_OBJ_NEW_QSTR(qst);
  750. break;
  751. case MP_BC_IMPORT_FROM:
  752. DECODE_QSTR;
  753. instruction->qstr_opname = MP_QSTR_IMPORT_FROM;
  754. instruction->arg = qst;
  755. instruction->argobj = MP_OBJ_NEW_QSTR(qst);
  756. break;
  757. case MP_BC_IMPORT_STAR:
  758. instruction->qstr_opname = MP_QSTR_IMPORT_STAR;
  759. break;
  760. default:
  761. if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
  762. instruction->qstr_opname = MP_QSTR_LOAD_CONST_SMALL_INT;
  763. instruction->arg = (mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16;
  764. } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
  765. instruction->qstr_opname = MP_QSTR_LOAD_FAST;
  766. instruction->arg = (mp_uint_t)ip[-1] - MP_BC_LOAD_FAST_MULTI;
  767. } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
  768. instruction->qstr_opname = MP_QSTR_STORE_FAST;
  769. instruction->arg = (mp_uint_t)ip[-1] - MP_BC_STORE_FAST_MULTI;
  770. } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NUM_BYTECODE) {
  771. instruction->qstr_opname = MP_QSTR_UNARY_OP;
  772. instruction->arg = (mp_uint_t)ip[-1] - MP_BC_UNARY_OP_MULTI;
  773. } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + MP_BINARY_OP_NUM_BYTECODE) {
  774. mp_uint_t op = ip[-1] - MP_BC_BINARY_OP_MULTI;
  775. instruction->qstr_opname = MP_QSTR_BINARY_OP;
  776. instruction->arg = op;
  777. } else {
  778. mp_printf(&mp_plat_print, "code %p, opcode 0x%02x not implemented\n", ip - 1, ip[-1]);
  779. assert(0);
  780. return ip;
  781. }
  782. break;
  783. }
  784. return ip;
  785. }
  786. void mp_prof_print_instr(const byte *ip, mp_code_state_t *code_state) {
  787. mp_dis_instruction_t _instruction, *instruction = &_instruction;
  788. mp_prof_opcode_decode(ip, code_state->fun_bc->rc->const_table, instruction);
  789. const mp_raw_code_t *rc = code_state->fun_bc->rc;
  790. const mp_bytecode_prelude_t *prelude = &rc->prelude;
  791. mp_uint_t offset = ip - prelude->opcodes;
  792. mp_printf(&mp_plat_print, "instr");
  793. /* long path */ if (1) {
  794. mp_printf(&mp_plat_print,
  795. "@0x%p:%q:%q+0x%04x:%d",
  796. ip,
  797. prelude->qstr_source_file,
  798. prelude->qstr_block_name,
  799. offset,
  800. mp_prof_bytecode_lineno(rc, offset)
  801. );
  802. }
  803. /* bytecode */ if (0) {
  804. mp_printf(&mp_plat_print, " %02x %02x %02x %02x", ip[0], ip[1], ip[2], ip[3]);
  805. }
  806. mp_printf(&mp_plat_print, " 0x%02x %q [%d]", *ip, instruction->qstr_opname, instruction->arg);
  807. if (instruction->argobj != mp_const_none) {
  808. mp_printf(&mp_plat_print, " $");
  809. mp_obj_print_helper(&mp_plat_print, instruction->argobj, PRINT_REPR);
  810. }
  811. if (instruction->argobjex_cache != mp_const_none) {
  812. mp_printf(&mp_plat_print, " #");
  813. mp_obj_print_helper(&mp_plat_print, instruction->argobjex_cache, PRINT_REPR);
  814. }
  815. mp_printf(&mp_plat_print, "\n");
  816. }
  817. #endif // MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE
  818. #endif // MICROPY_PY_SYS_SETTRACE