Skip to content

Commit 59fba2d

Browse files
committed
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.
1 parent ed570e4 commit 59fba2d

File tree

14 files changed

+111
-141
lines changed

14 files changed

+111
-141
lines changed

py/bc0.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
#define MP_BC_LOAD_CONST_NONE (0x11)
3434
#define MP_BC_LOAD_CONST_TRUE (0x12)
3535
#define MP_BC_LOAD_CONST_SMALL_INT (0x14) // signed var-int
36-
#define MP_BC_LOAD_CONST_BYTES (0x15) // qstr
3736
#define MP_BC_LOAD_CONST_STRING (0x16) // qstr
3837
#define MP_BC_LOAD_CONST_OBJ (0x17) // ptr
3938
#define MP_BC_LOAD_NULL (0x18)

py/compile.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,7 +1078,7 @@ STATIC void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
10781078
if (comp->have_star) {
10791079
comp->num_dict_params += 1;
10801080
#if MICROPY_EMIT_CPYTHON
1081-
EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id), false);
1081+
EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id));
10821082
compile_node(comp, pn_equal);
10831083
#else
10841084
// in Micro Python we put the default dict parameters into a dictionary using the bytecode
@@ -1096,7 +1096,7 @@ STATIC void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
10961096

10971097
// compile value then key, then store it to the dict
10981098
compile_node(comp, pn_equal);
1099-
EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id), false);
1099+
EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id));
11001100
EMIT(store_map);
11011101
#endif
11021102
} else {
@@ -1178,7 +1178,7 @@ STATIC qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pn
11781178
close_over_variables_etc(comp, cscope, 0, 0);
11791179

11801180
// get its name
1181-
EMIT_ARG(load_const_str, cscope->simple_name, false);
1181+
EMIT_ARG(load_const_str, cscope->simple_name);
11821182

11831183
// nodes[1] has parent classes, if any
11841184
// empty parenthesis (eg class C():) gets here as an empty PN_classdef_2 and needs special handling
@@ -1553,7 +1553,7 @@ STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
15531553
#if MICROPY_EMIT_CPYTHON
15541554
EMIT_ARG(load_const_verbatim_strn, "('*',)", 6);
15551555
#else
1556-
EMIT_ARG(load_const_str, MP_QSTR__star_, false);
1556+
EMIT_ARG(load_const_str, MP_QSTR__star_);
15571557
EMIT_ARG(build_tuple, 1);
15581558
#endif
15591559

@@ -1597,7 +1597,7 @@ STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
15971597
assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
15981598
mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
15991599
qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
1600-
EMIT_ARG(load_const_str, id2, false);
1600+
EMIT_ARG(load_const_str, id2);
16011601
}
16021602
EMIT_ARG(build_tuple, n);
16031603
#endif
@@ -2531,7 +2531,7 @@ STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_ar
25312531
compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "LHS of keyword arg must be an id");
25322532
return;
25332533
}
2534-
EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns_arg->nodes[0]), false);
2534+
EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns_arg->nodes[0]));
25352535
compile_node(comp, pns2->nodes[0]);
25362536
n_keyword += 1;
25372537
} else {
@@ -2979,8 +2979,17 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
29792979
mp_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
29802980
switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
29812981
case MP_PARSE_NODE_ID: compile_load_id(comp, arg); break;
2982-
case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg, false); break;
2983-
case MP_PARSE_NODE_BYTES: EMIT_ARG(load_const_str, arg, true); break;
2982+
case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg); break;
2983+
case MP_PARSE_NODE_BYTES:
2984+
// only create and load the actual bytes object on the last pass
2985+
if (comp->pass != MP_PASS_EMIT) {
2986+
EMIT_ARG(load_const_obj, mp_const_none);
2987+
} else {
2988+
mp_uint_t len;
2989+
const byte *data = qstr_data(arg, &len);
2990+
EMIT_ARG(load_const_obj, mp_obj_new_bytes(data, len));
2991+
}
2992+
break;
29842993
case MP_PARSE_NODE_TOKEN: default:
29852994
if (arg == MP_TOKEN_NEWLINE) {
29862995
// this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
@@ -3367,7 +3376,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
33673376

33683377
compile_load_id(comp, MP_QSTR___name__);
33693378
compile_store_id(comp, MP_QSTR___module__);
3370-
EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]), false); // 0 is class name
3379+
EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
33713380
compile_store_id(comp, MP_QSTR___qualname__);
33723381

33733382
check_for_doc_string(comp, pns->nodes[2]);

py/emit.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ typedef struct _emit_method_table_t {
8484
void (*import_star)(emit_t *emit);
8585
void (*load_const_tok)(emit_t *emit, mp_token_kind_t tok);
8686
void (*load_const_small_int)(emit_t *emit, mp_int_t arg);
87-
void (*load_const_str)(emit_t *emit, qstr qst, bool bytes);
87+
void (*load_const_str)(emit_t *emit, qstr qst);
8888
void (*load_const_obj)(emit_t *emit, void *obj);
8989
void (*load_null)(emit_t *emit);
9090
void (*load_attr)(emit_t *emit, qstr qst);
@@ -212,7 +212,7 @@ void mp_emit_bc_import_from(emit_t *emit, qstr qst);
212212
void mp_emit_bc_import_star(emit_t *emit);
213213
void mp_emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok);
214214
void mp_emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg);
215-
void mp_emit_bc_load_const_str(emit_t *emit, qstr qst, bool bytes);
215+
void mp_emit_bc_load_const_str(emit_t *emit, qstr qst);
216216
void mp_emit_bc_load_const_obj(emit_t *emit, void *obj);
217217
void mp_emit_bc_load_null(emit_t *emit);
218218
void mp_emit_bc_load_attr(emit_t *emit, qstr qst);

py/emitbc.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -486,13 +486,9 @@ void mp_emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg) {
486486
}
487487
}
488488

489-
void mp_emit_bc_load_const_str(emit_t *emit, qstr qst, bool bytes) {
489+
void mp_emit_bc_load_const_str(emit_t *emit, qstr qst) {
490490
emit_bc_pre(emit, 1);
491-
if (bytes) {
492-
emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_CONST_BYTES, qst);
493-
} else {
494-
emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qst);
495-
}
491+
emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qst);
496492
}
497493

498494
void mp_emit_bc_load_const_obj(emit_t *emit, void *obj) {

py/emitcpy.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ STATIC void emit_cpy_load_const_small_int(emit_t *emit, mp_int_t arg) {
176176
}
177177
}
178178

179-
STATIC void print_quoted_str(qstr qst, bool bytes) {
179+
STATIC void print_quoted_str(qstr qst) {
180180
const char *str = qstr_str(qst);
181181
int len = strlen(str);
182182
bool has_single_quote = false;
@@ -188,9 +188,6 @@ STATIC void print_quoted_str(qstr qst, bool bytes) {
188188
has_double_quote = true;
189189
}
190190
}
191-
if (bytes) {
192-
printf("b");
193-
}
194191
int quote_char = '\'';
195192
if (has_single_quote && !has_double_quote) {
196193
quote_char = '"';
@@ -213,11 +210,11 @@ STATIC void print_quoted_str(qstr qst, bool bytes) {
213210
printf("%c", quote_char);
214211
}
215212

216-
STATIC void emit_cpy_load_const_str(emit_t *emit, qstr qst, bool bytes) {
213+
STATIC void emit_cpy_load_const_str(emit_t *emit, qstr qst) {
217214
emit_pre(emit, 1, 3);
218215
if (emit->pass == MP_PASS_EMIT) {
219216
printf("LOAD_CONST ");
220-
print_quoted_str(qst, bytes);
217+
print_quoted_str(qst);
221218
printf("\n");
222219
}
223220
}

py/emitnative.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@
167167
STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
168168
[MP_F_CONVERT_OBJ_TO_NATIVE] = 2,
169169
[MP_F_CONVERT_NATIVE_TO_OBJ] = 2,
170-
[MP_F_LOAD_CONST_BYTES] = 1,
171170
[MP_F_LOAD_NAME] = 1,
172171
[MP_F_LOAD_GLOBAL] = 1,
173172
[MP_F_LOAD_BUILD_CLASS] = 0,
@@ -1295,7 +1294,7 @@ STATIC void emit_native_load_const_small_int(emit_t *emit, mp_int_t arg) {
12951294
}
12961295
}
12971296

1298-
STATIC void emit_native_load_const_str(emit_t *emit, qstr qst, bool bytes) {
1297+
STATIC void emit_native_load_const_str(emit_t *emit, qstr qst) {
12991298
emit_native_pre(emit);
13001299
// TODO: Eventually we want to be able to work with raw pointers in viper to
13011300
// do native array access. For now we just load them as any other object.
@@ -1308,12 +1307,7 @@ STATIC void emit_native_load_const_str(emit_t *emit, qstr qst, bool bytes) {
13081307
} else
13091308
*/
13101309
{
1311-
if (bytes) {
1312-
emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_BYTES, qst, REG_ARG_1);
1313-
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1314-
} else {
1315-
emit_post_push_imm(emit, VTYPE_PYOBJ, (mp_uint_t)MP_OBJ_NEW_QSTR(qst));
1316-
}
1310+
emit_post_push_imm(emit, VTYPE_PYOBJ, (mp_uint_t)MP_OBJ_NEW_QSTR(qst));
13171311
}
13181312
}
13191313

py/nativeglue.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ void mp_native_raise(mp_obj_t o) {
9292
void *const mp_fun_table[MP_F_NUMBER_OF] = {
9393
mp_convert_obj_to_native,
9494
mp_convert_native_to_obj,
95-
mp_load_const_bytes,
9695
mp_load_name,
9796
mp_load_global,
9897
mp_load_build_class,

py/runtime.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,6 @@ void mp_deinit(void) {
104104
#endif
105105
}
106106

107-
mp_obj_t mp_load_const_bytes(qstr qst) {
108-
DEBUG_OP_printf("load b'%s'\n", qstr_str(qst));
109-
mp_uint_t len;
110-
const byte *data = qstr_data(qst, &len);
111-
return mp_obj_new_bytes(data, len);
112-
}
113-
114107
mp_obj_t mp_load_name(qstr qst) {
115108
// logic: search locals, globals, builtins
116109
DEBUG_OP_printf("load name %s\n", qstr_str(qst));

py/runtime.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,6 @@ void mp_delete_global(qstr qst);
8888
mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg);
8989
mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs);
9090

91-
mp_obj_t mp_load_const_int(qstr qst);
92-
mp_obj_t mp_load_const_dec(qstr qst);
93-
mp_obj_t mp_load_const_bytes(qstr qst);
94-
9591
mp_obj_t mp_call_function_0(mp_obj_t fun);
9692
mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg);
9793
mp_obj_t mp_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2);

py/runtime0.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ typedef enum {
109109
typedef enum {
110110
MP_F_CONVERT_OBJ_TO_NATIVE = 0,
111111
MP_F_CONVERT_NATIVE_TO_OBJ,
112-
MP_F_LOAD_CONST_BYTES,
113112
MP_F_LOAD_NAME,
114113
MP_F_LOAD_GLOBAL,
115114
MP_F_LOAD_BUILD_CLASS,

0 commit comments

Comments
 (0)