py: Remove mp_load_const_bytes and instead load precreated bytes object.
Previous to this patch each time a bytes object was referenced a new
instance (with the same data) was created. With this patch a single
bytes object is created in the compiler and is loaded directly at execute
time as a true constant (similar to loading bignum and float objects).
This saves on allocating RAM and means that bytes objects can now be
used when the memory manager is locked (eg in interrupts).
The MP_BC_LOAD_CONST_BYTES bytecode was removed as part of this.
Generated bytecode is slightly larger due to storing a pointer to the
bytes object instead of the qstr identifier.
Code size is reduced by about 60 bytes on Thumb2 architectures.
diff --git a/py/bc0.h b/py/bc0.h
index 0a2d909..c5a3015 100644
--- a/py/bc0.h
+++ b/py/bc0.h
@@ -33,7 +33,6 @@
#define MP_BC_LOAD_CONST_NONE (0x11)
#define MP_BC_LOAD_CONST_TRUE (0x12)
#define MP_BC_LOAD_CONST_SMALL_INT (0x14) // signed var-int
-#define MP_BC_LOAD_CONST_BYTES (0x15) // qstr
#define MP_BC_LOAD_CONST_STRING (0x16) // qstr
#define MP_BC_LOAD_CONST_OBJ (0x17) // ptr
#define MP_BC_LOAD_NULL (0x18)
diff --git a/py/compile.c b/py/compile.c
index 45217cf..141cd2d 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -1078,7 +1078,7 @@
if (comp->have_star) {
comp->num_dict_params += 1;
#if MICROPY_EMIT_CPYTHON
- EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id), false);
+ EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id));
compile_node(comp, pn_equal);
#else
// in Micro Python we put the default dict parameters into a dictionary using the bytecode
@@ -1096,7 +1096,7 @@
// compile value then key, then store it to the dict
compile_node(comp, pn_equal);
- EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id), false);
+ EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id));
EMIT(store_map);
#endif
} else {
@@ -1178,7 +1178,7 @@
close_over_variables_etc(comp, cscope, 0, 0);
// get its name
- EMIT_ARG(load_const_str, cscope->simple_name, false);
+ EMIT_ARG(load_const_str, cscope->simple_name);
// nodes[1] has parent classes, if any
// empty parenthesis (eg class C():) gets here as an empty PN_classdef_2 and needs special handling
@@ -1553,7 +1553,7 @@
#if MICROPY_EMIT_CPYTHON
EMIT_ARG(load_const_verbatim_strn, "('*',)", 6);
#else
- EMIT_ARG(load_const_str, MP_QSTR__star_, false);
+ EMIT_ARG(load_const_str, MP_QSTR__star_);
EMIT_ARG(build_tuple, 1);
#endif
@@ -1597,7 +1597,7 @@
assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
- EMIT_ARG(load_const_str, id2, false);
+ EMIT_ARG(load_const_str, id2);
}
EMIT_ARG(build_tuple, n);
#endif
@@ -2531,7 +2531,7 @@
compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "LHS of keyword arg must be an id");
return;
}
- EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns_arg->nodes[0]), false);
+ EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns_arg->nodes[0]));
compile_node(comp, pns2->nodes[0]);
n_keyword += 1;
} else {
@@ -2979,8 +2979,17 @@
mp_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
case MP_PARSE_NODE_ID: compile_load_id(comp, arg); break;
- case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg, false); break;
- case MP_PARSE_NODE_BYTES: EMIT_ARG(load_const_str, arg, true); break;
+ case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg); break;
+ case MP_PARSE_NODE_BYTES:
+ // only create and load the actual bytes object on the last pass
+ if (comp->pass != MP_PASS_EMIT) {
+ EMIT_ARG(load_const_obj, mp_const_none);
+ } else {
+ mp_uint_t len;
+ const byte *data = qstr_data(arg, &len);
+ EMIT_ARG(load_const_obj, mp_obj_new_bytes(data, len));
+ }
+ break;
case MP_PARSE_NODE_TOKEN: default:
if (arg == MP_TOKEN_NEWLINE) {
// this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
@@ -3367,7 +3376,7 @@
compile_load_id(comp, MP_QSTR___name__);
compile_store_id(comp, MP_QSTR___module__);
- EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]), false); // 0 is class name
+ EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
compile_store_id(comp, MP_QSTR___qualname__);
check_for_doc_string(comp, pns->nodes[2]);
diff --git a/py/emit.h b/py/emit.h
index 35ba08d..8b980c1 100644
--- a/py/emit.h
+++ b/py/emit.h
@@ -84,7 +84,7 @@
void (*import_star)(emit_t *emit);
void (*load_const_tok)(emit_t *emit, mp_token_kind_t tok);
void (*load_const_small_int)(emit_t *emit, mp_int_t arg);
- void (*load_const_str)(emit_t *emit, qstr qst, bool bytes);
+ void (*load_const_str)(emit_t *emit, qstr qst);
void (*load_const_obj)(emit_t *emit, void *obj);
void (*load_null)(emit_t *emit);
void (*load_attr)(emit_t *emit, qstr qst);
@@ -212,7 +212,7 @@
void mp_emit_bc_import_star(emit_t *emit);
void mp_emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok);
void mp_emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg);
-void mp_emit_bc_load_const_str(emit_t *emit, qstr qst, bool bytes);
+void mp_emit_bc_load_const_str(emit_t *emit, qstr qst);
void mp_emit_bc_load_const_obj(emit_t *emit, void *obj);
void mp_emit_bc_load_null(emit_t *emit);
void mp_emit_bc_load_attr(emit_t *emit, qstr qst);
diff --git a/py/emitbc.c b/py/emitbc.c
index f99e703..fef9054 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -486,13 +486,9 @@
}
}
-void mp_emit_bc_load_const_str(emit_t *emit, qstr qst, bool bytes) {
+void mp_emit_bc_load_const_str(emit_t *emit, qstr qst) {
emit_bc_pre(emit, 1);
- if (bytes) {
- emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_CONST_BYTES, qst);
- } else {
- emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qst);
- }
+ emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qst);
}
void mp_emit_bc_load_const_obj(emit_t *emit, void *obj) {
diff --git a/py/emitcpy.c b/py/emitcpy.c
index dc96c52..3bdec17 100644
--- a/py/emitcpy.c
+++ b/py/emitcpy.c
@@ -176,7 +176,7 @@
}
}
-STATIC void print_quoted_str(qstr qst, bool bytes) {
+STATIC void print_quoted_str(qstr qst) {
const char *str = qstr_str(qst);
int len = strlen(str);
bool has_single_quote = false;
@@ -188,9 +188,6 @@
has_double_quote = true;
}
}
- if (bytes) {
- printf("b");
- }
int quote_char = '\'';
if (has_single_quote && !has_double_quote) {
quote_char = '"';
@@ -213,11 +210,11 @@
printf("%c", quote_char);
}
-STATIC void emit_cpy_load_const_str(emit_t *emit, qstr qst, bool bytes) {
+STATIC void emit_cpy_load_const_str(emit_t *emit, qstr qst) {
emit_pre(emit, 1, 3);
if (emit->pass == MP_PASS_EMIT) {
printf("LOAD_CONST ");
- print_quoted_str(qst, bytes);
+ print_quoted_str(qst);
printf("\n");
}
}
diff --git a/py/emitnative.c b/py/emitnative.c
index 974b8fc..0d3f78d 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -167,7 +167,6 @@
STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
[MP_F_CONVERT_OBJ_TO_NATIVE] = 2,
[MP_F_CONVERT_NATIVE_TO_OBJ] = 2,
- [MP_F_LOAD_CONST_BYTES] = 1,
[MP_F_LOAD_NAME] = 1,
[MP_F_LOAD_GLOBAL] = 1,
[MP_F_LOAD_BUILD_CLASS] = 0,
@@ -1295,7 +1294,7 @@
}
}
-STATIC void emit_native_load_const_str(emit_t *emit, qstr qst, bool bytes) {
+STATIC void emit_native_load_const_str(emit_t *emit, qstr qst) {
emit_native_pre(emit);
// TODO: Eventually we want to be able to work with raw pointers in viper to
// do native array access. For now we just load them as any other object.
@@ -1308,12 +1307,7 @@
} else
*/
{
- if (bytes) {
- emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_BYTES, qst, REG_ARG_1);
- emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
- } else {
- emit_post_push_imm(emit, VTYPE_PYOBJ, (mp_uint_t)MP_OBJ_NEW_QSTR(qst));
- }
+ emit_post_push_imm(emit, VTYPE_PYOBJ, (mp_uint_t)MP_OBJ_NEW_QSTR(qst));
}
}
diff --git a/py/nativeglue.c b/py/nativeglue.c
index 4252bb8..8721371 100644
--- a/py/nativeglue.c
+++ b/py/nativeglue.c
@@ -92,7 +92,6 @@
void *const mp_fun_table[MP_F_NUMBER_OF] = {
mp_convert_obj_to_native,
mp_convert_native_to_obj,
- mp_load_const_bytes,
mp_load_name,
mp_load_global,
mp_load_build_class,
diff --git a/py/runtime.c b/py/runtime.c
index 5fcfa6f..fb59292 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -104,13 +104,6 @@
#endif
}
-mp_obj_t mp_load_const_bytes(qstr qst) {
- DEBUG_OP_printf("load b'%s'\n", qstr_str(qst));
- mp_uint_t len;
- const byte *data = qstr_data(qst, &len);
- return mp_obj_new_bytes(data, len);
-}
-
mp_obj_t mp_load_name(qstr qst) {
// logic: search locals, globals, builtins
DEBUG_OP_printf("load name %s\n", qstr_str(qst));
diff --git a/py/runtime.h b/py/runtime.h
index 419b1d0..2282ea0 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -88,10 +88,6 @@
mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg);
mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs);
-mp_obj_t mp_load_const_int(qstr qst);
-mp_obj_t mp_load_const_dec(qstr qst);
-mp_obj_t mp_load_const_bytes(qstr qst);
-
mp_obj_t mp_call_function_0(mp_obj_t fun);
mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg);
mp_obj_t mp_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2);
diff --git a/py/runtime0.h b/py/runtime0.h
index de637fb..294c17b 100644
--- a/py/runtime0.h
+++ b/py/runtime0.h
@@ -109,7 +109,6 @@
typedef enum {
MP_F_CONVERT_OBJ_TO_NATIVE = 0,
MP_F_CONVERT_NATIVE_TO_OBJ,
- MP_F_LOAD_CONST_BYTES,
MP_F_LOAD_NAME,
MP_F_LOAD_GLOBAL,
MP_F_LOAD_BUILD_CLASS,
diff --git a/py/showbc.c b/py/showbc.c
index e08140e..2da8d3f 100644
--- a/py/showbc.c
+++ b/py/showbc.c
@@ -155,11 +155,6 @@
break;
}
- case MP_BC_LOAD_CONST_BYTES:
- DECODE_QSTR;
- printf("LOAD_CONST_BYTES %s", qstr_str(qst));
- break;
-
case MP_BC_LOAD_CONST_STRING:
DECODE_QSTR;
printf("LOAD_CONST_STRING '%s'", qstr_str(qst));
@@ -168,7 +163,7 @@
case MP_BC_LOAD_CONST_OBJ:
DECODE_PTR;
printf("LOAD_CONST_OBJ %p=", (void*)unum);
- mp_obj_print((mp_obj_t)unum, PRINT_REPR);
+ mp_obj_print_helper(&mp_plat_print, (mp_obj_t)unum, PRINT_REPR);
break;
case MP_BC_LOAD_NULL:
diff --git a/py/vm.c b/py/vm.c
index 3423e9e..08749af 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -205,12 +205,6 @@
DISPATCH();
}
- ENTRY(MP_BC_LOAD_CONST_BYTES): {
- DECODE_QSTR;
- PUSH(mp_load_const_bytes(qst));
- DISPATCH();
- }
-
ENTRY(MP_BC_LOAD_CONST_STRING): {
DECODE_QSTR;
PUSH(MP_OBJ_NEW_QSTR(qst));
diff --git a/py/vmentrytable.h b/py/vmentrytable.h
index 413914b..d71a8d4 100644
--- a/py/vmentrytable.h
+++ b/py/vmentrytable.h
@@ -35,7 +35,6 @@
[MP_BC_LOAD_CONST_NONE] = &&entry_MP_BC_LOAD_CONST_NONE,
[MP_BC_LOAD_CONST_TRUE] = &&entry_MP_BC_LOAD_CONST_TRUE,
[MP_BC_LOAD_CONST_SMALL_INT] = &&entry_MP_BC_LOAD_CONST_SMALL_INT,
- [MP_BC_LOAD_CONST_BYTES] = &&entry_MP_BC_LOAD_CONST_BYTES,
[MP_BC_LOAD_CONST_STRING] = &&entry_MP_BC_LOAD_CONST_STRING,
[MP_BC_LOAD_CONST_OBJ] = &&entry_MP_BC_LOAD_CONST_OBJ,
[MP_BC_LOAD_NULL] = &&entry_MP_BC_LOAD_NULL,
diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp
index fc3d85f..10be688 100644
--- a/tests/cmdline/cmd_showbc.py.exp
+++ b/tests/cmdline/cmd_showbc.py.exp
@@ -72,89 +72,89 @@
43 STORE_FAST 3
44 LOAD_CONST_STRING 'a'
47 STORE_FAST 4
-48 LOAD_CONST_BYTES a
-51 STORE_FAST 5
-52 LOAD_CONST_SMALL_INT 1
-53 STORE_FAST 6
-54 LOAD_CONST_SMALL_INT 2
-55 STORE_FAST 7
-56 LOAD_FAST 0
-57 LOAD_DEREF 14
-59 BINARY_OP 5 __add__
-60 STORE_FAST 8
-61 LOAD_FAST 0
-62 UNARY_OP 4
-63 STORE_FAST 9
-64 LOAD_FAST 0
-65 UNARY_OP 0
-66 NOT
-67 STORE_FAST 10
-68 LOAD_FAST 0
-69 LOAD_DEREF 14
-71 DUP_TOP
-72 ROT_THREE
-73 BINARY_OP 27 __eq__
-74 JUMP_IF_FALSE_OR_POP 82
-77 LOAD_FAST 1
-78 BINARY_OP 27 __eq__
-79 JUMP 84
-82 ROT_TWO
-83 POP_TOP
-84 STORE_FAST 10
-85 LOAD_FAST 0
-86 LOAD_DEREF 14
-88 BINARY_OP 27 __eq__
-89 JUMP_IF_FALSE_OR_POP 96
-92 LOAD_DEREF 14
-94 LOAD_FAST 1
-95 BINARY_OP 27 __eq__
-96 UNARY_OP 0
-97 NOT
-98 STORE_FAST 10
-99 LOAD_DEREF 14
-101 LOAD_ATTR c (cache=0)
-105 STORE_FAST 11
-106 LOAD_FAST 11
-107 LOAD_DEREF 14
-109 STORE_ATTR c (cache=0)
-113 LOAD_DEREF 14
-115 LOAD_CONST_SMALL_INT 0
-116 LOAD_SUBSCR
-117 STORE_FAST 12
-118 LOAD_FAST 12
-119 LOAD_DEREF 14
-121 LOAD_CONST_SMALL_INT 0
-122 STORE_SUBSCR
-123 LOAD_DEREF 14
-125 LOAD_CONST_NONE
-126 LOAD_CONST_NONE
-127 BUILD_SLICE 2
-129 LOAD_SUBSCR
-130 STORE_FAST 0
-131 LOAD_FAST 1
-132 UNPACK_SEQUENCE 2
-134 STORE_FAST 0
-135 STORE_DEREF 14
-137 LOAD_DEREF 14
-139 LOAD_FAST 0
-140 ROT_TWO
-141 STORE_FAST 0
-142 STORE_DEREF 14
-144 LOAD_FAST 1
-145 LOAD_DEREF 14
-147 LOAD_FAST 0
-148 ROT_THREE
-149 ROT_TWO
-150 STORE_FAST 0
-151 STORE_DEREF 14
-153 STORE_FAST 1
-154 DELETE_FAST 0
-156 LOAD_FAST 0
-157 STORE_GLOBAL gl
-160 DELETE_GLOBAL gl
-163 LOAD_FAST 14
-164 LOAD_FAST 15
-165 MAKE_CLOSURE \.\+ 2
+48 LOAD_CONST_OBJ \.\+
+\\d\+ STORE_FAST 5
+\\d\+ LOAD_CONST_SMALL_INT 1
+\\d\+ STORE_FAST 6
+\\d\+ LOAD_CONST_SMALL_INT 2
+\\d\+ STORE_FAST 7
+\\d\+ LOAD_FAST 0
+\\d\+ LOAD_DEREF 14
+\\d\+ BINARY_OP 5 __add__
+\\d\+ STORE_FAST 8
+\\d\+ LOAD_FAST 0
+\\d\+ UNARY_OP 4
+\\d\+ STORE_FAST 9
+\\d\+ LOAD_FAST 0
+\\d\+ UNARY_OP 0
+\\d\+ NOT
+\\d\+ STORE_FAST 10
+\\d\+ LOAD_FAST 0
+\\d\+ LOAD_DEREF 14
+\\d\+ DUP_TOP
+\\d\+ ROT_THREE
+\\d\+ BINARY_OP 27 __eq__
+\\d\+ JUMP_IF_FALSE_OR_POP \\d\+
+\\d\+ LOAD_FAST 1
+\\d\+ BINARY_OP 27 __eq__
+\\d\+ JUMP \\d\+
+\\d\+ ROT_TWO
+\\d\+ POP_TOP
+\\d\+ STORE_FAST 10
+\\d\+ LOAD_FAST 0
+\\d\+ LOAD_DEREF 14
+\\d\+ BINARY_OP 27 __eq__
+\\d\+ JUMP_IF_FALSE_OR_POP \\d\+
+\\d\+ LOAD_DEREF 14
+\\d\+ LOAD_FAST 1
+\\d\+ BINARY_OP 27 __eq__
+\\d\+ UNARY_OP 0
+\\d\+ NOT
+\\d\+ STORE_FAST 10
+\\d\+ LOAD_DEREF 14
+\\d\+ LOAD_ATTR c (cache=0)
+\\d\+ STORE_FAST 11
+\\d\+ LOAD_FAST 11
+\\d\+ LOAD_DEREF 14
+\\d\+ STORE_ATTR c (cache=0)
+\\d\+ LOAD_DEREF 14
+\\d\+ LOAD_CONST_SMALL_INT 0
+\\d\+ LOAD_SUBSCR
+\\d\+ STORE_FAST 12
+\\d\+ LOAD_FAST 12
+\\d\+ LOAD_DEREF 14
+\\d\+ LOAD_CONST_SMALL_INT 0
+\\d\+ STORE_SUBSCR
+\\d\+ LOAD_DEREF 14
+\\d\+ LOAD_CONST_NONE
+\\d\+ LOAD_CONST_NONE
+\\d\+ BUILD_SLICE 2
+\\d\+ LOAD_SUBSCR
+\\d\+ STORE_FAST 0
+\\d\+ LOAD_FAST 1
+\\d\+ UNPACK_SEQUENCE 2
+\\d\+ STORE_FAST 0
+\\d\+ STORE_DEREF 14
+\\d\+ LOAD_DEREF 14
+\\d\+ LOAD_FAST 0
+\\d\+ ROT_TWO
+\\d\+ STORE_FAST 0
+\\d\+ STORE_DEREF 14
+\\d\+ LOAD_FAST 1
+\\d\+ LOAD_DEREF 14
+\\d\+ LOAD_FAST 0
+\\d\+ ROT_THREE
+\\d\+ ROT_TWO
+\\d\+ STORE_FAST 0
+\\d\+ STORE_DEREF 14
+\\d\+ STORE_FAST 1
+\\d\+ DELETE_FAST 0
+\\d\+ LOAD_FAST 0
+\\d\+ STORE_GLOBAL gl
+\\d\+ DELETE_GLOBAL gl
+\\d\+ LOAD_FAST 14
+\\d\+ LOAD_FAST 15
+\\d\+ MAKE_CLOSURE \.\+ 2
\\d\+ LOAD_FAST 2
\\d\+ GET_ITER
\\d\+ CALL_FUNCTION n=1 nkw=0