bc.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2014 Damien P. George
  7. * Copyright (c) 2014 Paul Sokolovsky
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. */
  27. #include <stdbool.h>
  28. #include <string.h>
  29. #include <assert.h>
  30. #include "py/runtime.h"
  31. #include "py/bc0.h"
  32. #include "py/bc.h"
  33. #if MICROPY_DEBUG_VERBOSE // print debugging info
  34. #define DEBUG_PRINT (1)
  35. #else // don't print debugging info
  36. #define DEBUG_PRINT (0)
  37. #define DEBUG_printf(...) (void)0
  38. #endif
  39. #if !MICROPY_PERSISTENT_CODE
  40. mp_uint_t mp_decode_uint(const byte **ptr) {
  41. mp_uint_t unum = 0;
  42. byte val;
  43. const byte *p = *ptr;
  44. do {
  45. val = *p++;
  46. unum = (unum << 7) | (val & 0x7f);
  47. } while ((val & 0x80) != 0);
  48. *ptr = p;
  49. return unum;
  50. }
  51. // This function is used to help reduce stack usage at the caller, for the case when
  52. // the caller doesn't need to increase the ptr argument. If ptr is a local variable
  53. // and the caller uses mp_decode_uint(&ptr) instead of this function, then the compiler
  54. // must allocate a slot on the stack for ptr, and this slot cannot be reused for
  55. // anything else in the function because the pointer may have been stored in a global
  56. // and reused later in the function.
  57. mp_uint_t mp_decode_uint_value(const byte *ptr) {
  58. return mp_decode_uint(&ptr);
  59. }
  60. // This function is used to help reduce stack usage at the caller, for the case when
  61. // the caller doesn't need the actual value and just wants to skip over it.
  62. const byte *mp_decode_uint_skip(const byte *ptr) {
  63. while ((*ptr++) & 0x80) {
  64. }
  65. return ptr;
  66. }
  67. #endif
  68. STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) {
  69. #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE
  70. // generic message, used also for other argument issues
  71. (void)f;
  72. (void)expected;
  73. (void)given;
  74. mp_arg_error_terse_mismatch();
  75. #elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL
  76. (void)f;
  77. mp_raise_msg_varg(&mp_type_TypeError,
  78. MP_ERROR_TEXT("function takes %d positional arguments but %d were given"), expected, given);
  79. #elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
  80. mp_raise_msg_varg(&mp_type_TypeError,
  81. MP_ERROR_TEXT("%q() takes %d positional arguments but %d were given"),
  82. mp_obj_fun_get_name(MP_OBJ_FROM_PTR(f)), expected, given);
  83. #endif
  84. }
  85. #if DEBUG_PRINT
  86. STATIC void dump_args(const mp_obj_t *a, size_t sz) {
  87. DEBUG_printf("%p: ", a);
  88. for (size_t i = 0; i < sz; i++) {
  89. DEBUG_printf("%p ", a[i]);
  90. }
  91. DEBUG_printf("\n");
  92. }
  93. #else
  94. #define dump_args(...) (void)0
  95. #endif
  96. // On entry code_state should be allocated somewhere (stack/heap) and
  97. // contain the following valid entries:
  98. // - code_state->fun_bc should contain a pointer to the function object
  99. // - code_state->ip should contain the offset in bytes from the pointer
  100. // code_state->fun_bc->bytecode to the entry n_state (0 for bytecode, non-zero for native)
  101. void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args) {
  102. // This function is pretty complicated. It's main aim is to be efficient in speed and RAM
  103. // usage for the common case of positional only args.
  104. // get the function object that we want to set up (could be bytecode or native code)
  105. mp_obj_fun_bc_t *self = code_state->fun_bc;
  106. // ip comes in as an offset into bytecode, so turn it into a true pointer
  107. code_state->ip = self->bytecode + (size_t)code_state->ip;
  108. #if MICROPY_STACKLESS
  109. code_state->prev = NULL;
  110. #endif
  111. #if MICROPY_PY_SYS_SETTRACE
  112. code_state->prev_state = NULL;
  113. code_state->frame = NULL;
  114. #endif
  115. // Get cached n_state (rather than decode it again)
  116. size_t n_state = code_state->n_state;
  117. // Decode prelude
  118. size_t n_state_unused, n_exc_stack_unused, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args;
  119. MP_BC_PRELUDE_SIG_DECODE_INTO(code_state->ip, n_state_unused, n_exc_stack_unused, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args);
  120. (void)n_state_unused;
  121. (void)n_exc_stack_unused;
  122. code_state->sp = &code_state->state[0] - 1;
  123. code_state->exc_sp_idx = 0;
  124. // zero out the local stack to begin with
  125. memset(code_state->state, 0, n_state * sizeof(*code_state->state));
  126. const mp_obj_t *kwargs = args + n_args;
  127. // var_pos_kw_args points to the stack where the var-args tuple, and var-kw dict, should go (if they are needed)
  128. mp_obj_t *var_pos_kw_args = &code_state->state[n_state - 1 - n_pos_args - n_kwonly_args];
  129. // check positional arguments
  130. if (n_args > n_pos_args) {
  131. // given more than enough arguments
  132. if ((scope_flags & MP_SCOPE_FLAG_VARARGS) == 0) {
  133. fun_pos_args_mismatch(self, n_pos_args, n_args);
  134. }
  135. // put extra arguments in varargs tuple
  136. *var_pos_kw_args-- = mp_obj_new_tuple(n_args - n_pos_args, args + n_pos_args);
  137. n_args = n_pos_args;
  138. } else {
  139. if ((scope_flags & MP_SCOPE_FLAG_VARARGS) != 0) {
  140. DEBUG_printf("passing empty tuple as *args\n");
  141. *var_pos_kw_args-- = mp_const_empty_tuple;
  142. }
  143. // Apply processing and check below only if we don't have kwargs,
  144. // otherwise, kw handling code below has own extensive checks.
  145. if (n_kw == 0 && (scope_flags & MP_SCOPE_FLAG_DEFKWARGS) == 0) {
  146. if (n_args >= (size_t)(n_pos_args - n_def_pos_args)) {
  147. // given enough arguments, but may need to use some default arguments
  148. for (size_t i = n_args; i < n_pos_args; i++) {
  149. code_state->state[n_state - 1 - i] = self->extra_args[i - (n_pos_args - n_def_pos_args)];
  150. }
  151. } else {
  152. fun_pos_args_mismatch(self, n_pos_args - n_def_pos_args, n_args);
  153. }
  154. }
  155. }
  156. // copy positional args into state
  157. for (size_t i = 0; i < n_args; i++) {
  158. code_state->state[n_state - 1 - i] = args[i];
  159. }
  160. // check keyword arguments
  161. if (n_kw != 0 || (scope_flags & MP_SCOPE_FLAG_DEFKWARGS) != 0) {
  162. DEBUG_printf("Initial args: ");
  163. dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);
  164. mp_obj_t dict = MP_OBJ_NULL;
  165. if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {
  166. dict = mp_obj_new_dict(n_kw); // TODO: better go conservative with 0?
  167. *var_pos_kw_args = dict;
  168. }
  169. // get pointer to arg_names array
  170. const mp_obj_t *arg_names = (const mp_obj_t *)self->const_table;
  171. for (size_t i = 0; i < n_kw; i++) {
  172. // the keys in kwargs are expected to be qstr objects
  173. mp_obj_t wanted_arg_name = kwargs[2 * i];
  174. for (size_t j = 0; j < n_pos_args + n_kwonly_args; j++) {
  175. if (wanted_arg_name == arg_names[j]) {
  176. if (code_state->state[n_state - 1 - j] != MP_OBJ_NULL) {
  177. mp_raise_msg_varg(&mp_type_TypeError,
  178. MP_ERROR_TEXT("function got multiple values for argument '%q'"), MP_OBJ_QSTR_VALUE(wanted_arg_name));
  179. }
  180. code_state->state[n_state - 1 - j] = kwargs[2 * i + 1];
  181. goto continue2;
  182. }
  183. }
  184. // Didn't find name match with positional args
  185. if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) == 0) {
  186. #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE
  187. mp_raise_TypeError(MP_ERROR_TEXT("unexpected keyword argument"));
  188. #else
  189. mp_raise_msg_varg(&mp_type_TypeError,
  190. MP_ERROR_TEXT("unexpected keyword argument '%q'"), MP_OBJ_QSTR_VALUE(wanted_arg_name));
  191. #endif
  192. }
  193. mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]);
  194. continue2:;
  195. }
  196. DEBUG_printf("Args with kws flattened: ");
  197. dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);
  198. // fill in defaults for positional args
  199. mp_obj_t *d = &code_state->state[n_state - n_pos_args];
  200. mp_obj_t *s = &self->extra_args[n_def_pos_args - 1];
  201. for (size_t i = n_def_pos_args; i > 0; i--, d++, s--) {
  202. if (*d == MP_OBJ_NULL) {
  203. *d = *s;
  204. }
  205. }
  206. DEBUG_printf("Args after filling default positional: ");
  207. dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);
  208. // Check that all mandatory positional args are specified
  209. while (d < &code_state->state[n_state]) {
  210. if (*d++ == MP_OBJ_NULL) {
  211. mp_raise_msg_varg(&mp_type_TypeError,
  212. MP_ERROR_TEXT("function missing required positional argument #%d"), &code_state->state[n_state] - d);
  213. }
  214. }
  215. // Check that all mandatory keyword args are specified
  216. // Fill in default kw args if we have them
  217. for (size_t i = 0; i < n_kwonly_args; i++) {
  218. if (code_state->state[n_state - 1 - n_pos_args - i] == MP_OBJ_NULL) {
  219. mp_map_elem_t *elem = NULL;
  220. if ((scope_flags & MP_SCOPE_FLAG_DEFKWARGS) != 0) {
  221. elem = mp_map_lookup(&((mp_obj_dict_t *)MP_OBJ_TO_PTR(self->extra_args[n_def_pos_args]))->map, arg_names[n_pos_args + i], MP_MAP_LOOKUP);
  222. }
  223. if (elem != NULL) {
  224. code_state->state[n_state - 1 - n_pos_args - i] = elem->value;
  225. } else {
  226. mp_raise_msg_varg(&mp_type_TypeError,
  227. MP_ERROR_TEXT("function missing required keyword argument '%q'"), MP_OBJ_QSTR_VALUE(arg_names[n_pos_args + i]));
  228. }
  229. }
  230. }
  231. } else {
  232. // no keyword arguments given
  233. if (n_kwonly_args != 0) {
  234. mp_raise_TypeError(MP_ERROR_TEXT("function missing keyword-only argument"));
  235. }
  236. if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {
  237. *var_pos_kw_args = mp_obj_new_dict(0);
  238. }
  239. }
  240. // read the size part of the prelude
  241. const byte *ip = code_state->ip;
  242. MP_BC_PRELUDE_SIZE_DECODE(ip);
  243. // jump over code info (source file and line-number mapping)
  244. ip += n_info;
  245. // bytecode prelude: initialise closed over variables
  246. for (; n_cell; --n_cell) {
  247. size_t local_num = *ip++;
  248. code_state->state[n_state - 1 - local_num] =
  249. mp_obj_new_cell(code_state->state[n_state - 1 - local_num]);
  250. }
  251. #if !MICROPY_PERSISTENT_CODE
  252. // so bytecode is aligned
  253. ip = MP_ALIGN(ip, sizeof(mp_uint_t));
  254. #endif
  255. // now that we skipped over the prelude, set the ip for the VM
  256. code_state->ip = ip;
  257. DEBUG_printf("Calling: n_pos_args=%d, n_kwonly_args=%d\n", n_pos_args, n_kwonly_args);
  258. dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);
  259. dump_args(code_state->state, n_state);
  260. }
  261. #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE
  262. // The following table encodes the number of bytes that a specific opcode
  263. // takes up. Some opcodes have an extra byte, defined by MP_BC_MASK_EXTRA_BYTE.
  264. // There are 4 special opcodes that have an extra byte only when
  265. // MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE is enabled (and they take a qstr):
  266. // MP_BC_LOAD_NAME
  267. // MP_BC_LOAD_GLOBAL
  268. // MP_BC_LOAD_ATTR
  269. // MP_BC_STORE_ATTR
  270. uint mp_opcode_format(const byte *ip, size_t *opcode_size, bool count_var_uint) {
  271. uint f = MP_BC_FORMAT(*ip);
  272. const byte *ip_start = ip;
  273. if (f == MP_BC_FORMAT_QSTR) {
  274. if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) {
  275. if (*ip == MP_BC_LOAD_NAME
  276. || *ip == MP_BC_LOAD_GLOBAL
  277. || *ip == MP_BC_LOAD_ATTR
  278. || *ip == MP_BC_STORE_ATTR) {
  279. ip += 1;
  280. }
  281. }
  282. ip += 3;
  283. } else {
  284. int extra_byte = (*ip & MP_BC_MASK_EXTRA_BYTE) == 0;
  285. ip += 1;
  286. if (f == MP_BC_FORMAT_VAR_UINT) {
  287. if (count_var_uint) {
  288. while ((*ip++ & 0x80) != 0) {
  289. }
  290. }
  291. } else if (f == MP_BC_FORMAT_OFFSET) {
  292. ip += 2;
  293. }
  294. ip += extra_byte;
  295. }
  296. *opcode_size = ip - ip_start;
  297. return f;
  298. }
  299. #endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE