profile.c 31 KB

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