persistentcode.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2013-2020 Damien P. George
  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 <stdint.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <assert.h>
  30. #include "py/reader.h"
  31. #include "py/nativeglue.h"
  32. #include "py/persistentcode.h"
  33. #include "py/bc0.h"
  34. #include "py/objstr.h"
  35. #include "py/mpthread.h"
  36. #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE
  37. #include "py/smallint.h"
  38. #define QSTR_LAST_STATIC MP_QSTR_zip
  39. #if MICROPY_DYNAMIC_COMPILER
  40. #define MPY_FEATURE_ARCH_DYNAMIC mp_dynamic_compiler.native_arch
  41. #else
  42. #define MPY_FEATURE_ARCH_DYNAMIC MPY_FEATURE_ARCH
  43. #endif
  44. #if MICROPY_PERSISTENT_CODE_LOAD || (MICROPY_PERSISTENT_CODE_SAVE && !MICROPY_DYNAMIC_COMPILER)
  45. // The bytecode will depend on the number of bits in a small-int, and
  46. // this function computes that (could make it a fixed constant, but it
  47. // would need to be defined in mpconfigport.h).
  48. STATIC int mp_small_int_bits(void) {
  49. mp_int_t i = MP_SMALL_INT_MAX;
  50. int n = 1;
  51. while (i != 0) {
  52. i >>= 1;
  53. ++n;
  54. }
  55. return n;
  56. }
  57. #endif
  58. #define QSTR_WINDOW_SIZE (32)
  59. typedef struct _qstr_window_t {
  60. uint16_t idx; // indexes the head of the window
  61. uint16_t window[QSTR_WINDOW_SIZE];
  62. } qstr_window_t;
  63. // Push a qstr to the head of the window, and the tail qstr is overwritten
  64. STATIC void qstr_window_push(qstr_window_t *qw, qstr qst) {
  65. qw->idx = (qw->idx + 1) % QSTR_WINDOW_SIZE;
  66. qw->window[qw->idx] = qst;
  67. }
  68. // Pull an existing qstr from within the window to the head of the window
  69. STATIC qstr qstr_window_pull(qstr_window_t *qw, size_t idx) {
  70. qstr qst = qw->window[idx];
  71. if (idx > qw->idx) {
  72. memmove(&qw->window[idx], &qw->window[idx + 1], (QSTR_WINDOW_SIZE - idx - 1) * sizeof(uint16_t));
  73. qw->window[QSTR_WINDOW_SIZE - 1] = qw->window[0];
  74. idx = 0;
  75. }
  76. memmove(&qw->window[idx], &qw->window[idx + 1], (qw->idx - idx) * sizeof(uint16_t));
  77. qw->window[qw->idx] = qst;
  78. return qst;
  79. }
  80. #if MICROPY_PERSISTENT_CODE_LOAD
  81. // Access a qstr at the given index, relative to the head of the window (0=head)
  82. STATIC qstr qstr_window_access(qstr_window_t *qw, size_t idx) {
  83. return qstr_window_pull(qw, (qw->idx + QSTR_WINDOW_SIZE - idx) % QSTR_WINDOW_SIZE);
  84. }
  85. #endif
  86. #if MICROPY_PERSISTENT_CODE_SAVE
  87. // Insert a qstr at the head of the window, either by pulling an existing one or pushing a new one
  88. STATIC size_t qstr_window_insert(qstr_window_t *qw, qstr qst) {
  89. for (size_t idx = 0; idx < QSTR_WINDOW_SIZE; ++idx) {
  90. if (qw->window[idx] == qst) {
  91. qstr_window_pull(qw, idx);
  92. return (qw->idx + QSTR_WINDOW_SIZE - idx) % QSTR_WINDOW_SIZE;
  93. }
  94. }
  95. qstr_window_push(qw, qst);
  96. return QSTR_WINDOW_SIZE;
  97. }
  98. #endif
  99. typedef struct _bytecode_prelude_t {
  100. uint n_state;
  101. uint n_exc_stack;
  102. uint scope_flags;
  103. uint n_pos_args;
  104. uint n_kwonly_args;
  105. uint n_def_pos_args;
  106. uint code_info_size;
  107. } bytecode_prelude_t;
  108. // ip will point to start of opcodes
  109. // return value will point to simple_name, source_file qstrs
  110. STATIC byte *extract_prelude(const byte **ip, bytecode_prelude_t *prelude) {
  111. MP_BC_PRELUDE_SIG_DECODE(*ip);
  112. prelude->n_state = n_state;
  113. prelude->n_exc_stack = n_exc_stack;
  114. prelude->scope_flags = scope_flags;
  115. prelude->n_pos_args = n_pos_args;
  116. prelude->n_kwonly_args = n_kwonly_args;
  117. prelude->n_def_pos_args = n_def_pos_args;
  118. MP_BC_PRELUDE_SIZE_DECODE(*ip);
  119. byte *ip_info = (byte *)*ip;
  120. *ip += n_info;
  121. *ip += n_cell;
  122. return ip_info;
  123. }
  124. #endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE
  125. #if MICROPY_PERSISTENT_CODE_LOAD
  126. #include "py/parsenum.h"
  127. STATIC int read_byte(mp_reader_t *reader);
  128. STATIC size_t read_uint(mp_reader_t *reader, byte **out);
  129. #if MICROPY_EMIT_MACHINE_CODE
  130. typedef struct _reloc_info_t {
  131. mp_reader_t *reader;
  132. mp_uint_t *const_table;
  133. } reloc_info_t;
  134. #if MICROPY_EMIT_THUMB
  135. STATIC void asm_thumb_rewrite_mov(uint8_t *pc, uint16_t val) {
  136. // high part
  137. *(uint16_t *)pc = (*(uint16_t *)pc & 0xfbf0) | (val >> 1 & 0x0400) | (val >> 12);
  138. // low part
  139. *(uint16_t *)(pc + 2) = (*(uint16_t *)(pc + 2) & 0x0f00) | (val << 4 & 0x7000) | (val & 0x00ff);
  140. }
  141. #endif
  142. STATIC void arch_link_qstr(uint8_t *pc, bool is_obj, qstr qst) {
  143. mp_uint_t val = qst;
  144. if (is_obj) {
  145. val = (mp_uint_t)MP_OBJ_NEW_QSTR(qst);
  146. }
  147. #if MICROPY_EMIT_X86 || MICROPY_EMIT_X64 || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA || MICROPY_EMIT_XTENSAWIN
  148. pc[0] = val & 0xff;
  149. pc[1] = (val >> 8) & 0xff;
  150. pc[2] = (val >> 16) & 0xff;
  151. pc[3] = (val >> 24) & 0xff;
  152. #elif MICROPY_EMIT_THUMB
  153. if (is_obj) {
  154. // qstr object, movw and movt
  155. asm_thumb_rewrite_mov(pc, val); // movw
  156. asm_thumb_rewrite_mov(pc + 4, val >> 16); // movt
  157. } else {
  158. // qstr number, movw instruction
  159. asm_thumb_rewrite_mov(pc, val); // movw
  160. }
  161. #endif
  162. }
  163. void mp_native_relocate(void *ri_in, uint8_t *text, uintptr_t reloc_text) {
  164. // Relocate native code
  165. reloc_info_t *ri = ri_in;
  166. uint8_t op;
  167. uintptr_t *addr_to_adjust = NULL;
  168. while ((op = read_byte(ri->reader)) != 0xff) {
  169. if (op & 1) {
  170. // Point to new location to make adjustments
  171. size_t addr = read_uint(ri->reader, NULL);
  172. if ((addr & 1) == 0) {
  173. // Point to somewhere in text
  174. addr_to_adjust = &((uintptr_t *)text)[addr >> 1];
  175. } else {
  176. // Point to somewhere in rodata
  177. addr_to_adjust = &((uintptr_t *)ri->const_table[1])[addr >> 1];
  178. }
  179. }
  180. op >>= 1;
  181. uintptr_t dest;
  182. size_t n = 1;
  183. if (op <= 5) {
  184. if (op & 1) {
  185. // Read in number of adjustments to make
  186. n = read_uint(ri->reader, NULL);
  187. }
  188. op >>= 1;
  189. if (op == 0) {
  190. // Destination is text
  191. dest = reloc_text;
  192. } else {
  193. // Destination is rodata (op=1) or bss (op=1 if no rodata, else op=2)
  194. dest = ri->const_table[op];
  195. }
  196. } else if (op == 6) {
  197. // Destination is mp_fun_table itself
  198. dest = (uintptr_t)&mp_fun_table;
  199. } else {
  200. // Destination is an entry in mp_fun_table
  201. dest = ((uintptr_t *)&mp_fun_table)[op - 7];
  202. }
  203. while (n--) {
  204. *addr_to_adjust++ += dest;
  205. }
  206. }
  207. }
  208. #endif
  209. STATIC int read_byte(mp_reader_t *reader) {
  210. return reader->readbyte(reader->data);
  211. }
  212. STATIC void read_bytes(mp_reader_t *reader, byte *buf, size_t len) {
  213. while (len-- > 0) {
  214. *buf++ = reader->readbyte(reader->data);
  215. }
  216. }
  217. STATIC size_t read_uint(mp_reader_t *reader, byte **out) {
  218. size_t unum = 0;
  219. for (;;) {
  220. byte b = reader->readbyte(reader->data);
  221. if (out != NULL) {
  222. **out = b;
  223. ++*out;
  224. }
  225. unum = (unum << 7) | (b & 0x7f);
  226. if ((b & 0x80) == 0) {
  227. break;
  228. }
  229. }
  230. return unum;
  231. }
  232. STATIC qstr load_qstr(mp_reader_t *reader, qstr_window_t *qw) {
  233. size_t len = read_uint(reader, NULL);
  234. if (len == 0) {
  235. // static qstr
  236. return read_byte(reader);
  237. }
  238. if (len & 1) {
  239. // qstr in window
  240. return qstr_window_access(qw, len >> 1);
  241. }
  242. len >>= 1;
  243. char *str = m_new(char, len);
  244. read_bytes(reader, (byte *)str, len);
  245. qstr qst = qstr_from_strn(str, len);
  246. m_del(char, str, len);
  247. qstr_window_push(qw, qst);
  248. return qst;
  249. }
  250. STATIC mp_obj_t load_obj(mp_reader_t *reader) {
  251. byte obj_type = read_byte(reader);
  252. if (obj_type == 'e') {
  253. return MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj);
  254. } else {
  255. size_t len = read_uint(reader, NULL);
  256. vstr_t vstr;
  257. vstr_init_len(&vstr, len);
  258. read_bytes(reader, (byte *)vstr.buf, len);
  259. if (obj_type == 's' || obj_type == 'b') {
  260. return mp_obj_new_str_from_vstr(obj_type == 's' ? &mp_type_str : &mp_type_bytes, &vstr);
  261. } else if (obj_type == 'i') {
  262. return mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL);
  263. } else {
  264. assert(obj_type == 'f' || obj_type == 'c');
  265. return mp_parse_num_decimal(vstr.buf, vstr.len, obj_type == 'c', false, NULL);
  266. }
  267. }
  268. }
  269. STATIC void load_prelude_qstrs(mp_reader_t *reader, qstr_window_t *qw, byte *ip) {
  270. qstr simple_name = load_qstr(reader, qw);
  271. ip[0] = simple_name;
  272. ip[1] = simple_name >> 8;
  273. qstr source_file = load_qstr(reader, qw);
  274. ip[2] = source_file;
  275. ip[3] = source_file >> 8;
  276. }
  277. STATIC void load_prelude(mp_reader_t *reader, qstr_window_t *qw, byte **ip, bytecode_prelude_t *prelude) {
  278. // Read in the prelude header
  279. byte *ip_read = *ip;
  280. read_uint(reader, &ip_read); // read in n_state/etc (is effectively a var-uint)
  281. read_uint(reader, &ip_read); // read in n_info/n_cell (is effectively a var-uint)
  282. // Prelude header has been read into *ip, now decode and extract values from it
  283. extract_prelude((const byte **)ip, prelude);
  284. // Load qstrs in prelude
  285. load_prelude_qstrs(reader, qw, ip_read);
  286. ip_read += 4;
  287. // Read remaining code info
  288. read_bytes(reader, ip_read, *ip - ip_read);
  289. }
  290. STATIC void load_bytecode(mp_reader_t *reader, qstr_window_t *qw, byte *ip, byte *ip_top) {
  291. while (ip < ip_top) {
  292. *ip = read_byte(reader);
  293. size_t sz;
  294. uint f = mp_opcode_format(ip, &sz, false);
  295. ++ip;
  296. --sz;
  297. if (f == MP_BC_FORMAT_QSTR) {
  298. qstr qst = load_qstr(reader, qw);
  299. *ip++ = qst;
  300. *ip++ = qst >> 8;
  301. sz -= 2;
  302. } else if (f == MP_BC_FORMAT_VAR_UINT) {
  303. while ((*ip++ = read_byte(reader)) & 0x80) {
  304. }
  305. }
  306. read_bytes(reader, ip, sz);
  307. ip += sz;
  308. }
  309. }
  310. STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) {
  311. // Load function kind and data length
  312. size_t kind_len = read_uint(reader, NULL);
  313. int kind = (kind_len & 3) + MP_CODE_BYTECODE;
  314. size_t fun_data_len = kind_len >> 2;
  315. #if !MICROPY_EMIT_MACHINE_CODE
  316. if (kind != MP_CODE_BYTECODE) {
  317. mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy file"));
  318. }
  319. #endif
  320. uint8_t *fun_data = NULL;
  321. bytecode_prelude_t prelude = {0};
  322. #if MICROPY_EMIT_MACHINE_CODE
  323. size_t prelude_offset = 0;
  324. mp_uint_t type_sig = 0;
  325. size_t n_qstr_link = 0;
  326. #endif
  327. if (kind == MP_CODE_BYTECODE) {
  328. // Allocate memory for the bytecode
  329. fun_data = m_new(uint8_t, fun_data_len);
  330. // Load prelude
  331. byte *ip = fun_data;
  332. load_prelude(reader, qw, &ip, &prelude);
  333. // Load bytecode
  334. load_bytecode(reader, qw, ip, fun_data + fun_data_len);
  335. #if MICROPY_EMIT_MACHINE_CODE
  336. } else {
  337. // Allocate memory for native data and load it
  338. size_t fun_alloc;
  339. MP_PLAT_ALLOC_EXEC(fun_data_len, (void **)&fun_data, &fun_alloc);
  340. read_bytes(reader, fun_data, fun_data_len);
  341. if (kind == MP_CODE_NATIVE_PY || kind == MP_CODE_NATIVE_VIPER) {
  342. // Parse qstr link table and link native code
  343. n_qstr_link = read_uint(reader, NULL);
  344. for (size_t i = 0; i < n_qstr_link; ++i) {
  345. size_t off = read_uint(reader, NULL);
  346. qstr qst = load_qstr(reader, qw);
  347. uint8_t *dest = fun_data + (off >> 2);
  348. if ((off & 3) == 0) {
  349. // Generic 16-bit link
  350. dest[0] = qst & 0xff;
  351. dest[1] = (qst >> 8) & 0xff;
  352. } else if ((off & 3) == 3) {
  353. // Generic, aligned qstr-object link
  354. *(mp_obj_t *)dest = MP_OBJ_NEW_QSTR(qst);
  355. } else {
  356. // Architecture-specific link
  357. arch_link_qstr(dest, (off & 3) == 2, qst);
  358. }
  359. }
  360. }
  361. if (kind == MP_CODE_NATIVE_PY) {
  362. // Extract prelude for later use
  363. prelude_offset = read_uint(reader, NULL);
  364. const byte *ip = fun_data + prelude_offset;
  365. byte *ip_info = extract_prelude(&ip, &prelude);
  366. // Load qstrs in prelude
  367. load_prelude_qstrs(reader, qw, ip_info);
  368. } else {
  369. // Load basic scope info for viper and asm
  370. prelude.scope_flags = read_uint(reader, NULL);
  371. prelude.n_pos_args = 0;
  372. prelude.n_kwonly_args = 0;
  373. if (kind == MP_CODE_NATIVE_ASM) {
  374. prelude.n_pos_args = read_uint(reader, NULL);
  375. type_sig = read_uint(reader, NULL);
  376. }
  377. }
  378. #endif
  379. }
  380. size_t n_obj = 0;
  381. size_t n_raw_code = 0;
  382. mp_uint_t *const_table = NULL;
  383. if (kind != MP_CODE_NATIVE_ASM) {
  384. // Load constant table for bytecode, native and viper
  385. // Number of entries in constant table
  386. n_obj = read_uint(reader, NULL);
  387. n_raw_code = read_uint(reader, NULL);
  388. // Allocate constant table
  389. size_t n_alloc = prelude.n_pos_args + prelude.n_kwonly_args + n_obj + n_raw_code;
  390. #if MICROPY_EMIT_MACHINE_CODE
  391. if (kind != MP_CODE_BYTECODE) {
  392. ++n_alloc; // additional entry for mp_fun_table
  393. if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRODATA) {
  394. ++n_alloc; // additional entry for rodata
  395. }
  396. if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERBSS) {
  397. ++n_alloc; // additional entry for BSS
  398. }
  399. }
  400. #endif
  401. const_table = m_new(mp_uint_t, n_alloc);
  402. mp_uint_t *ct = const_table;
  403. // Load function argument names (initial entries in const_table)
  404. // (viper has n_pos_args=n_kwonly_args=0 so doesn't load any qstrs here)
  405. for (size_t i = 0; i < prelude.n_pos_args + prelude.n_kwonly_args; ++i) {
  406. *ct++ = (mp_uint_t)MP_OBJ_NEW_QSTR(load_qstr(reader, qw));
  407. }
  408. #if MICROPY_EMIT_MACHINE_CODE
  409. if (kind != MP_CODE_BYTECODE) {
  410. // Populate mp_fun_table entry
  411. *ct++ = (mp_uint_t)(uintptr_t)&mp_fun_table;
  412. // Allocate and load rodata if needed
  413. if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRODATA) {
  414. size_t size = read_uint(reader, NULL);
  415. uint8_t *rodata = m_new(uint8_t, size);
  416. read_bytes(reader, rodata, size);
  417. *ct++ = (uintptr_t)rodata;
  418. }
  419. // Allocate BSS if needed
  420. if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERBSS) {
  421. size_t size = read_uint(reader, NULL);
  422. uint8_t *bss = m_new0(uint8_t, size);
  423. *ct++ = (uintptr_t)bss;
  424. }
  425. }
  426. #endif
  427. // Load constant objects and raw code children
  428. for (size_t i = 0; i < n_obj; ++i) {
  429. *ct++ = (mp_uint_t)load_obj(reader);
  430. }
  431. for (size_t i = 0; i < n_raw_code; ++i) {
  432. *ct++ = (mp_uint_t)(uintptr_t)load_raw_code(reader, qw);
  433. }
  434. }
  435. // Create raw_code and return it
  436. mp_raw_code_t *rc = mp_emit_glue_new_raw_code();
  437. if (kind == MP_CODE_BYTECODE) {
  438. // Assign bytecode to raw code object
  439. mp_emit_glue_assign_bytecode(rc, fun_data,
  440. #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
  441. fun_data_len,
  442. #endif
  443. const_table,
  444. #if MICROPY_PERSISTENT_CODE_SAVE
  445. n_obj, n_raw_code,
  446. #endif
  447. prelude.scope_flags);
  448. #if MICROPY_EMIT_MACHINE_CODE
  449. } else {
  450. // Relocate and commit code to executable address space
  451. reloc_info_t ri = {reader, const_table};
  452. #if defined(MP_PLAT_COMMIT_EXEC)
  453. void *opt_ri = (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRELOC) ? &ri : NULL;
  454. fun_data = MP_PLAT_COMMIT_EXEC(fun_data, fun_data_len, opt_ri);
  455. #else
  456. if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRELOC) {
  457. #if MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE
  458. // If native code needs relocations then it's not guaranteed that a pointer to
  459. // the head of `buf` (containing the machine code) will be retained for the GC
  460. // to trace. This is because native functions can start inside `buf` and so
  461. // it's possible that the only GC-reachable pointers are pointers inside `buf`.
  462. // So put this `buf` on a list of reachable root pointers.
  463. if (MP_STATE_PORT(track_reloc_code_list) == MP_OBJ_NULL) {
  464. MP_STATE_PORT(track_reloc_code_list) = mp_obj_new_list(0, NULL);
  465. }
  466. mp_obj_list_append(MP_STATE_PORT(track_reloc_code_list), MP_OBJ_FROM_PTR(fun_data));
  467. #endif
  468. // Do the relocations.
  469. mp_native_relocate(&ri, fun_data, (uintptr_t)fun_data);
  470. }
  471. #endif
  472. // Assign native code to raw code object
  473. mp_emit_glue_assign_native(rc, kind,
  474. fun_data, fun_data_len, const_table,
  475. #if MICROPY_PERSISTENT_CODE_SAVE
  476. prelude_offset,
  477. n_obj, n_raw_code,
  478. n_qstr_link, NULL,
  479. #endif
  480. prelude.n_pos_args, prelude.scope_flags, type_sig);
  481. #endif
  482. }
  483. return rc;
  484. }
  485. mp_raw_code_t *mp_raw_code_load(mp_reader_t *reader) {
  486. byte header[4];
  487. read_bytes(reader, header, sizeof(header));
  488. if (header[0] != 'M'
  489. || header[1] != MPY_VERSION
  490. || MPY_FEATURE_DECODE_FLAGS(header[2]) != MPY_FEATURE_FLAGS
  491. || header[3] > mp_small_int_bits()
  492. || read_uint(reader, NULL) > QSTR_WINDOW_SIZE) {
  493. mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy file"));
  494. }
  495. if (MPY_FEATURE_DECODE_ARCH(header[2]) != MP_NATIVE_ARCH_NONE) {
  496. byte arch = MPY_FEATURE_DECODE_ARCH(header[2]);
  497. if (!MPY_FEATURE_ARCH_TEST(arch)) {
  498. mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy arch"));
  499. }
  500. }
  501. qstr_window_t qw;
  502. qw.idx = 0;
  503. mp_raw_code_t *rc = load_raw_code(reader, &qw);
  504. reader->close(reader->data);
  505. return rc;
  506. }
  507. mp_raw_code_t *mp_raw_code_load_mem(const byte *buf, size_t len) {
  508. mp_reader_t reader;
  509. mp_reader_new_mem(&reader, buf, len, 0);
  510. return mp_raw_code_load(&reader);
  511. }
  512. #if MICROPY_HAS_FILE_READER
  513. mp_raw_code_t *mp_raw_code_load_file(const char *filename) {
  514. mp_reader_t reader;
  515. mp_reader_new_file(&reader, filename);
  516. return mp_raw_code_load(&reader);
  517. }
  518. #endif // MICROPY_HAS_FILE_READER
  519. #endif // MICROPY_PERSISTENT_CODE_LOAD
  520. #if MICROPY_PERSISTENT_CODE_SAVE
  521. #include "py/objstr.h"
  522. STATIC void mp_print_bytes(mp_print_t *print, const byte *data, size_t len) {
  523. print->print_strn(print->data, (const char *)data, len);
  524. }
  525. #define BYTES_FOR_INT ((BYTES_PER_WORD * 8 + 6) / 7)
  526. STATIC void mp_print_uint(mp_print_t *print, size_t n) {
  527. byte buf[BYTES_FOR_INT];
  528. byte *p = buf + sizeof(buf);
  529. *--p = n & 0x7f;
  530. n >>= 7;
  531. for (; n != 0; n >>= 7) {
  532. *--p = 0x80 | (n & 0x7f);
  533. }
  534. print->print_strn(print->data, (char *)p, buf + sizeof(buf) - p);
  535. }
  536. STATIC void save_qstr(mp_print_t *print, qstr_window_t *qw, qstr qst) {
  537. if (qst <= QSTR_LAST_STATIC) {
  538. // encode static qstr
  539. byte buf[2] = {0, qst & 0xff};
  540. mp_print_bytes(print, buf, 2);
  541. return;
  542. }
  543. size_t idx = qstr_window_insert(qw, qst);
  544. if (idx < QSTR_WINDOW_SIZE) {
  545. // qstr found in window, encode index to it
  546. mp_print_uint(print, idx << 1 | 1);
  547. return;
  548. }
  549. size_t len;
  550. const byte *str = qstr_data(qst, &len);
  551. mp_print_uint(print, len << 1);
  552. mp_print_bytes(print, str, len);
  553. }
  554. STATIC void save_obj(mp_print_t *print, mp_obj_t o) {
  555. if (mp_obj_is_str_or_bytes(o)) {
  556. byte obj_type;
  557. if (mp_obj_is_str(o)) {
  558. obj_type = 's';
  559. } else {
  560. obj_type = 'b';
  561. }
  562. size_t len;
  563. const char *str = mp_obj_str_get_data(o, &len);
  564. mp_print_bytes(print, &obj_type, 1);
  565. mp_print_uint(print, len);
  566. mp_print_bytes(print, (const byte *)str, len);
  567. } else if (MP_OBJ_TO_PTR(o) == &mp_const_ellipsis_obj) {
  568. byte obj_type = 'e';
  569. mp_print_bytes(print, &obj_type, 1);
  570. } else {
  571. // we save numbers using a simplistic text representation
  572. // TODO could be improved
  573. byte obj_type;
  574. if (mp_obj_is_type(o, &mp_type_int)) {
  575. obj_type = 'i';
  576. #if MICROPY_PY_BUILTINS_COMPLEX
  577. } else if (mp_obj_is_type(o, &mp_type_complex)) {
  578. obj_type = 'c';
  579. #endif
  580. } else {
  581. assert(mp_obj_is_float(o));
  582. obj_type = 'f';
  583. }
  584. vstr_t vstr;
  585. mp_print_t pr;
  586. vstr_init_print(&vstr, 10, &pr);
  587. mp_obj_print_helper(&pr, o, PRINT_REPR);
  588. mp_print_bytes(print, &obj_type, 1);
  589. mp_print_uint(print, vstr.len);
  590. mp_print_bytes(print, (const byte *)vstr.buf, vstr.len);
  591. vstr_clear(&vstr);
  592. }
  593. }
  594. STATIC void save_prelude_qstrs(mp_print_t *print, qstr_window_t *qw, const byte *ip) {
  595. save_qstr(print, qw, ip[0] | (ip[1] << 8)); // simple_name
  596. save_qstr(print, qw, ip[2] | (ip[3] << 8)); // source_file
  597. }
  598. STATIC void save_bytecode(mp_print_t *print, qstr_window_t *qw, const byte *ip, const byte *ip_top) {
  599. while (ip < ip_top) {
  600. size_t sz;
  601. uint f = mp_opcode_format(ip, &sz, true);
  602. if (f == MP_BC_FORMAT_QSTR) {
  603. mp_print_bytes(print, ip, 1);
  604. qstr qst = ip[1] | (ip[2] << 8);
  605. save_qstr(print, qw, qst);
  606. ip += 3;
  607. sz -= 3;
  608. }
  609. mp_print_bytes(print, ip, sz);
  610. ip += sz;
  611. }
  612. }
  613. STATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc, qstr_window_t *qstr_window) {
  614. // Save function kind and data length
  615. mp_print_uint(print, (rc->fun_data_len << 2) | (rc->kind - MP_CODE_BYTECODE));
  616. bytecode_prelude_t prelude;
  617. if (rc->kind == MP_CODE_BYTECODE) {
  618. // Extract prelude
  619. const byte *ip = rc->fun_data;
  620. const byte *ip_info = extract_prelude(&ip, &prelude);
  621. // Save prelude
  622. mp_print_bytes(print, rc->fun_data, ip_info - (const byte *)rc->fun_data);
  623. save_prelude_qstrs(print, qstr_window, ip_info);
  624. ip_info += 4;
  625. mp_print_bytes(print, ip_info, ip - ip_info);
  626. // Save bytecode
  627. const byte *ip_top = (const byte *)rc->fun_data + rc->fun_data_len;
  628. save_bytecode(print, qstr_window, ip, ip_top);
  629. #if MICROPY_EMIT_MACHINE_CODE
  630. } else {
  631. // Save native code
  632. mp_print_bytes(print, rc->fun_data, rc->fun_data_len);
  633. if (rc->kind == MP_CODE_NATIVE_PY || rc->kind == MP_CODE_NATIVE_VIPER) {
  634. // Save qstr link table for native code
  635. mp_print_uint(print, rc->n_qstr);
  636. for (size_t i = 0; i < rc->n_qstr; ++i) {
  637. mp_print_uint(print, rc->qstr_link[i].off);
  638. save_qstr(print, qstr_window, rc->qstr_link[i].qst);
  639. }
  640. }
  641. if (rc->kind == MP_CODE_NATIVE_PY) {
  642. // Save prelude size
  643. mp_print_uint(print, rc->prelude_offset);
  644. // Extract prelude and save qstrs in prelude
  645. const byte *ip = (const byte *)rc->fun_data + rc->prelude_offset;
  646. const byte *ip_info = extract_prelude(&ip, &prelude);
  647. save_prelude_qstrs(print, qstr_window, ip_info);
  648. } else {
  649. // Save basic scope info for viper and asm
  650. mp_print_uint(print, rc->scope_flags & MP_SCOPE_FLAG_ALL_SIG);
  651. prelude.n_pos_args = 0;
  652. prelude.n_kwonly_args = 0;
  653. if (rc->kind == MP_CODE_NATIVE_ASM) {
  654. mp_print_uint(print, rc->n_pos_args);
  655. mp_print_uint(print, rc->type_sig);
  656. }
  657. }
  658. #endif
  659. }
  660. if (rc->kind != MP_CODE_NATIVE_ASM) {
  661. // Save constant table for bytecode, native and viper
  662. // Number of entries in constant table
  663. mp_print_uint(print, rc->n_obj);
  664. mp_print_uint(print, rc->n_raw_code);
  665. const mp_uint_t *const_table = rc->const_table;
  666. // Save function argument names (initial entries in const_table)
  667. // (viper has n_pos_args=n_kwonly_args=0 so doesn't save any qstrs here)
  668. for (size_t i = 0; i < prelude.n_pos_args + prelude.n_kwonly_args; ++i) {
  669. mp_obj_t o = (mp_obj_t)*const_table++;
  670. save_qstr(print, qstr_window, MP_OBJ_QSTR_VALUE(o));
  671. }
  672. if (rc->kind != MP_CODE_BYTECODE) {
  673. // Skip saving mp_fun_table entry
  674. ++const_table;
  675. }
  676. // Save constant objects and raw code children
  677. for (size_t i = 0; i < rc->n_obj; ++i) {
  678. save_obj(print, (mp_obj_t)*const_table++);
  679. }
  680. for (size_t i = 0; i < rc->n_raw_code; ++i) {
  681. save_raw_code(print, (mp_raw_code_t *)(uintptr_t)*const_table++, qstr_window);
  682. }
  683. }
  684. }
  685. STATIC bool mp_raw_code_has_native(mp_raw_code_t *rc) {
  686. if (rc->kind != MP_CODE_BYTECODE) {
  687. return true;
  688. }
  689. const byte *ip = rc->fun_data;
  690. bytecode_prelude_t prelude;
  691. extract_prelude(&ip, &prelude);
  692. const mp_uint_t *const_table = rc->const_table
  693. + prelude.n_pos_args + prelude.n_kwonly_args
  694. + rc->n_obj;
  695. for (size_t i = 0; i < rc->n_raw_code; ++i) {
  696. if (mp_raw_code_has_native((mp_raw_code_t *)(uintptr_t)*const_table++)) {
  697. return true;
  698. }
  699. }
  700. return false;
  701. }
  702. void mp_raw_code_save(mp_raw_code_t *rc, mp_print_t *print) {
  703. // header contains:
  704. // byte 'M'
  705. // byte version
  706. // byte feature flags
  707. // byte number of bits in a small int
  708. // uint size of qstr window
  709. byte header[4] = {
  710. 'M',
  711. MPY_VERSION,
  712. MPY_FEATURE_ENCODE_FLAGS(MPY_FEATURE_FLAGS_DYNAMIC),
  713. #if MICROPY_DYNAMIC_COMPILER
  714. mp_dynamic_compiler.small_int_bits,
  715. #else
  716. mp_small_int_bits(),
  717. #endif
  718. };
  719. if (mp_raw_code_has_native(rc)) {
  720. header[2] |= MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH_DYNAMIC);
  721. }
  722. mp_print_bytes(print, header, sizeof(header));
  723. mp_print_uint(print, QSTR_WINDOW_SIZE);
  724. qstr_window_t qw;
  725. qw.idx = 0;
  726. memset(qw.window, 0, sizeof(qw.window));
  727. save_raw_code(print, rc, &qw);
  728. }
  729. // here we define mp_raw_code_save_file depending on the port
  730. // TODO abstract this away properly
  731. #if defined(__i386__) || defined(__x86_64__) || defined(_WIN32) || defined(__unix__)
  732. #include <unistd.h>
  733. #include <sys/stat.h>
  734. #include <fcntl.h>
  735. STATIC void fd_print_strn(void *env, const char *str, size_t len) {
  736. int fd = (intptr_t)env;
  737. MP_THREAD_GIL_EXIT();
  738. ssize_t ret = write(fd, str, len);
  739. MP_THREAD_GIL_ENTER();
  740. (void)ret;
  741. }
  742. void mp_raw_code_save_file(mp_raw_code_t *rc, const char *filename) {
  743. MP_THREAD_GIL_EXIT();
  744. int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  745. MP_THREAD_GIL_ENTER();
  746. mp_print_t fd_print = {(void *)(intptr_t)fd, fd_print_strn};
  747. mp_raw_code_save(rc, &fd_print);
  748. MP_THREAD_GIL_EXIT();
  749. close(fd);
  750. MP_THREAD_GIL_ENTER();
  751. }
  752. #else
  753. #error mp_raw_code_save_file not implemented for this platform
  754. #endif
  755. #endif // MICROPY_PERSISTENT_CODE_SAVE