py/compile: Allow new qstrs to be allocated at all compiler passes.

Prior to this commit, all qstrs were required to be allocated (by calling
mp_emit_common_use_qstr) in the MP_PASS_SCOPE pass (the first one).  But
this is an unnecessary restriction, which is lifted by this commit.
Lifting the restriction simplifies the compiler because it can allocate
qstrs in later passes.

This also generates better code, because in some cases (eg when a variable
is closed over) the scope of an identifier is not known until a bit later
and then the identifier no longer needs its qstr allocated in the global
table.

Code size is reduced for all ports with this commit.

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Damien George 2022-05-06 22:43:03 +10:00
parent 1fb01bd6c5
commit 90682f43af
4 changed files with 22 additions and 33 deletions

View File

@ -188,7 +188,6 @@ typedef struct _compiler_t {
mp_emit_common_t emit_common; mp_emit_common_t emit_common;
emit_t *emit; // current emitter emit_t *emit; // current emitter
emit_t *emit_bc;
#if NEED_METHOD_TABLE #if NEED_METHOD_TABLE
const emit_method_table_t *emit_method_table; // current emit method table const emit_method_table_t *emit_method_table; // current emit method table
#endif #endif
@ -359,8 +358,7 @@ STATIC void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *
STATIC void compile_load_id(compiler_t *comp, qstr qst) { STATIC void compile_load_id(compiler_t *comp, qstr qst) {
if (comp->pass == MP_PASS_SCOPE) { if (comp->pass == MP_PASS_SCOPE) {
mp_emit_common_get_id_for_load(comp->scope_cur, qst); mp_emit_common_get_id_for_load(comp->scope_cur, qst);
} } else {
{
#if NEED_METHOD_TABLE #if NEED_METHOD_TABLE
mp_emit_common_id_op(comp->emit, &comp->emit_method_table->load_id, comp->scope_cur, qst); mp_emit_common_id_op(comp->emit, &comp->emit_method_table->load_id, comp->scope_cur, qst);
#else #else
@ -372,8 +370,7 @@ STATIC void compile_load_id(compiler_t *comp, qstr qst) {
STATIC void compile_store_id(compiler_t *comp, qstr qst) { STATIC void compile_store_id(compiler_t *comp, qstr qst) {
if (comp->pass == MP_PASS_SCOPE) { if (comp->pass == MP_PASS_SCOPE) {
mp_emit_common_get_id_for_modification(comp->scope_cur, qst); mp_emit_common_get_id_for_modification(comp->scope_cur, qst);
} } else {
{
#if NEED_METHOD_TABLE #if NEED_METHOD_TABLE
mp_emit_common_id_op(comp->emit, &comp->emit_method_table->store_id, comp->scope_cur, qst); mp_emit_common_id_op(comp->emit, &comp->emit_method_table->store_id, comp->scope_cur, qst);
#else #else
@ -385,8 +382,7 @@ STATIC void compile_store_id(compiler_t *comp, qstr qst) {
STATIC void compile_delete_id(compiler_t *comp, qstr qst) { STATIC void compile_delete_id(compiler_t *comp, qstr qst) {
if (comp->pass == MP_PASS_SCOPE) { if (comp->pass == MP_PASS_SCOPE) {
mp_emit_common_get_id_for_modification(comp->scope_cur, qst); mp_emit_common_get_id_for_modification(comp->scope_cur, qst);
} } else {
{
#if NEED_METHOD_TABLE #if NEED_METHOD_TABLE
mp_emit_common_id_op(comp->emit, &comp->emit_method_table->delete_id, comp->scope_cur, qst); mp_emit_common_id_op(comp->emit, &comp->emit_method_table->delete_id, comp->scope_cur, qst);
#else #else
@ -2154,7 +2150,6 @@ STATIC void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
STATIC void compile_namedexpr_helper(compiler_t *comp, mp_parse_node_t pn_name, mp_parse_node_t pn_expr) { STATIC void compile_namedexpr_helper(compiler_t *comp, mp_parse_node_t pn_name, mp_parse_node_t pn_expr) {
if (!MP_PARSE_NODE_IS_ID(pn_name)) { if (!MP_PARSE_NODE_IS_ID(pn_name)) {
compile_syntax_error(comp, (mp_parse_node_t)pn_name, MP_ERROR_TEXT("can't assign to expression")); compile_syntax_error(comp, (mp_parse_node_t)pn_name, MP_ERROR_TEXT("can't assign to expression"));
return; // because pn_name is not a valid qstr (in compile_store_id below)
} }
compile_node(comp, pn_expr); compile_node(comp, pn_expr);
EMIT(dup_top); EMIT(dup_top);
@ -2858,7 +2853,6 @@ STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn
// comes before a star, so counts as a positional parameter // comes before a star, so counts as a positional parameter
comp->scope_cur->num_pos_args += 1; comp->scope_cur->num_pos_args += 1;
} }
mp_emit_common_use_qstr(&comp->emit_common, param_name);
} else { } else {
assert(MP_PARSE_NODE_IS_STRUCT(pn)); assert(MP_PARSE_NODE_IS_STRUCT(pn));
pns = (mp_parse_node_struct_t *)pn; pns = (mp_parse_node_struct_t *)pn;
@ -2872,7 +2866,6 @@ STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn
// comes before a star, so counts as a positional parameter // comes before a star, so counts as a positional parameter
comp->scope_cur->num_pos_args += 1; comp->scope_cur->num_pos_args += 1;
} }
mp_emit_common_use_qstr(&comp->emit_common, param_name);
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) { } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
if (comp->have_star) { if (comp->have_star) {
// more than one star // more than one star
@ -3111,7 +3104,6 @@ STATIC bool compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
if (comp->pass == MP_PASS_SCOPE) { if (comp->pass == MP_PASS_SCOPE) {
scope_find_or_add_id(comp->scope_cur, qstr_arg, ID_INFO_KIND_LOCAL); scope_find_or_add_id(comp->scope_cur, qstr_arg, ID_INFO_KIND_LOCAL);
scope->num_pos_args = 1; scope->num_pos_args = 1;
mp_emit_common_use_qstr(&comp->emit_common, MP_QSTR__star_);
} }
// Set the source line number for the start of the comprehension // Set the source line number for the start of the comprehension
@ -3361,7 +3353,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
} }
#endif #endif
STATIC void scope_compute_things(scope_t *scope, mp_emit_common_t *emit_common) { STATIC void scope_compute_things(scope_t *scope) {
// in MicroPython we put the *x parameter after all other parameters (except **y) // in MicroPython we put the *x parameter after all other parameters (except **y)
if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) { if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) {
id_info_t *id_param = NULL; id_info_t *id_param = NULL;
@ -3450,7 +3442,6 @@ STATIC void scope_compute_things(scope_t *scope, mp_emit_common_t *emit_common)
} }
scope->num_pos_args += num_free; // free vars are counted as params for passing them into the function scope->num_pos_args += num_free; // free vars are counted as params for passing them into the function
scope->num_locals += num_free; scope->num_locals += num_free;
mp_emit_common_use_qstr(emit_common, MP_QSTR__star_);
} }
} }
} }
@ -3481,7 +3472,6 @@ mp_compiled_module_t mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr so
// compile MP_PASS_SCOPE // compile MP_PASS_SCOPE
comp->emit = emit_bc; comp->emit = emit_bc;
comp->emit_bc = emit_bc;
#if MICROPY_EMIT_NATIVE #if MICROPY_EMIT_NATIVE
comp->emit_method_table = &emit_bc_method_table; comp->emit_method_table = &emit_bc_method_table;
#endif #endif
@ -3519,7 +3509,7 @@ mp_compiled_module_t mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr so
} }
#endif #endif
scope_compute_things(s, &comp->emit_common); scope_compute_things(s);
} }
// set max number of labels now that it's calculated // set max number of labels now that it's calculated

View File

@ -34,7 +34,6 @@
qstr_short_t mp_emit_common_use_qstr(mp_emit_common_t *emit, qstr qst) { qstr_short_t mp_emit_common_use_qstr(mp_emit_common_t *emit, qstr qst) {
mp_map_elem_t *elem = mp_map_lookup(&emit->qstr_map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); mp_map_elem_t *elem = mp_map_lookup(&emit->qstr_map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
if (elem->value == MP_OBJ_NULL) { if (elem->value == MP_OBJ_NULL) {
assert(emit->pass == MP_PASS_SCOPE);
elem->value = MP_OBJ_NEW_SMALL_INT(emit->qstr_map.used - 1); elem->value = MP_OBJ_NEW_SMALL_INT(emit->qstr_map.used - 1);
} }
return MP_OBJ_SMALL_INT_VALUE(elem->value); return MP_OBJ_SMALL_INT_VALUE(elem->value);

View File

@ -42,9 +42,9 @@
File cmdline/cmd_parsetree.py, code block '<module>' (descriptor: \.\+, bytecode @\.\+ 62 bytes) File cmdline/cmd_parsetree.py, code block '<module>' (descriptor: \.\+, bytecode @\.\+ 62 bytes)
Raw bytecode (code_info_size=13, bytecode_size=49): Raw bytecode (code_info_size=13, bytecode_size=49):
20 16 01 60 27 22 23 24 24 24 24 24 25 2a 00 5f 20 16 01 60 27 22 23 24 24 24 24 24 25 2a 00 5f
4b 04 16 02 42 3a 51 16 03 10 04 16 05 23 00 16 4b 04 16 04 42 3a 51 16 05 10 02 16 06 23 00 16
06 23 01 16 07 23 02 16 08 23 03 16 09 22 80 7b 07 23 01 16 08 23 02 16 09 23 03 16 0a 22 80 7b
16 0a 23 04 14 0b 11 05 36 01 16 0c 51 63 16 0b 23 04 14 03 11 06 36 01 16 0c 51 63
arg names: arg names:
(N_STATE 5) (N_STATE 5)
(N_EXC_STACK 0) (N_EXC_STACK 0)

View File

@ -1,9 +1,9 @@
File cmdline/cmd_showbc.py, code block '<module>' (descriptor: \.\+, bytecode @\.\+ 63 bytes) File cmdline/cmd_showbc.py, code block '<module>' (descriptor: \.\+, bytecode @\.\+ 63 bytes)
Raw bytecode (code_info_size=18, bytecode_size=45): Raw bytecode (code_info_size=18, bytecode_size=45):
10 20 01 60 20 84 7d 64 60 88 07 64 60 69 20 62 10 20 01 60 20 84 7d 64 60 88 07 64 60 69 20 62
64 20 32 00 16 02 32 01 16 02 81 2a 01 53 33 02 64 20 32 00 16 05 32 01 16 05 81 2a 01 53 33 02
16 02 32 03 16 02 54 32 04 10 03 34 02 16 03 19 16 05 32 03 16 05 54 32 04 10 02 34 02 16 02 19
03 32 05 16 02 80 10 04 2a 01 1b 05 69 51 63 02 32 05 16 05 80 10 03 2a 01 1b 04 69 51 63
arg names: arg names:
(N_STATE 3) (N_STATE 3)
(N_EXC_STACK 0) (N_EXC_STACK 0)
@ -49,7 +49,7 @@ arg names:
44 RETURN_VALUE 44 RETURN_VALUE
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 45\[46\] bytes) File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 45\[46\] bytes)
Raw bytecode (code_info_size=8\[46\], bytecode_size=370): Raw bytecode (code_info_size=8\[46\], bytecode_size=370):
a8 12 9\[bf\] 03 02 60 60 26 22 24 64 22 24 25 25 24 a8 12 9\[bf\] 03 05 60 60 26 22 24 64 22 24 25 25 24
26 23 63 22 22 25 23 23 2f 6c 25 65 25 25 69 68 26 23 63 22 22 25 23 23 2f 6c 25 65 25 25 69 68
26 65 27 6a 62 20 23 62 2a 29 69 24 25 28 67 26 26 65 27 6a 62 20 23 62 2a 29 69 24 25 28 67 26
######## ########
@ -405,7 +405,7 @@ arg names:
369 RETURN_VALUE 369 RETURN_VALUE
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 59 bytes) File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 59 bytes)
Raw bytecode (code_info_size=8, bytecode_size=51): Raw bytecode (code_info_size=8, bytecode_size=51):
a8 10 0a 02 80 82 34 38 81 57 c0 57 c1 57 c2 57 a8 10 0a 05 80 82 34 38 81 57 c0 57 c1 57 c2 57
c3 57 c4 57 c5 57 c6 57 c7 57 c8 c9 82 57 ca 57 c3 57 c4 57 c5 57 c6 57 c7 57 c8 c9 82 57 ca 57
cb 57 cc 57 cd 57 ce 57 cf 57 26 10 57 26 11 57 cb 57 cc 57 cd 57 ce 57 cf 57 26 10 57 26 11 57
26 12 26 13 b9 24 13 f2 59 51 63 26 12 26 13 b9 24 13 f2 59 51 63
@ -464,7 +464,7 @@ arg names:
50 RETURN_VALUE 50 RETURN_VALUE
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 20 bytes) File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 20 bytes)
Raw bytecode (code_info_size=9, bytecode_size=11): Raw bytecode (code_info_size=9, bytecode_size=11):
a1 01 0b 02 06 80 88 40 00 82 2a 01 53 b0 21 00 a1 01 0b 05 06 80 88 40 00 82 2a 01 53 b0 21 00
01 c1 51 63 01 c1 51 63
arg names: a arg names: a
(N_STATE 5) (N_STATE 5)
@ -483,7 +483,7 @@ arg names: a
10 RETURN_VALUE 10 RETURN_VALUE
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 21 bytes) File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 21 bytes)
Raw bytecode (code_info_size=8, bytecode_size=13): Raw bytecode (code_info_size=8, bytecode_size=13):
88 40 0a 02 80 8f 23 23 51 67 59 81 67 59 81 5e 88 40 0a 05 80 8f 23 23 51 67 59 81 67 59 81 5e
51 68 59 51 63 51 68 59 51 63
arg names: arg names:
(N_STATE 2) (N_STATE 2)
@ -507,7 +507,7 @@ arg names:
12 RETURN_VALUE 12 RETURN_VALUE
File cmdline/cmd_showbc.py, code block 'Class' (descriptor: \.\+, bytecode @\.\+ 1\[56\] bytes) File cmdline/cmd_showbc.py, code block 'Class' (descriptor: \.\+, bytecode @\.\+ 1\[56\] bytes)
Raw bytecode (code_info_size=\[56\], bytecode_size=10): Raw bytecode (code_info_size=\[56\], bytecode_size=10):
00 \.\+ 11 0c 16 0d 10 03 16 0e 51 63 00 \.\+ 11 0f 16 10 10 02 16 11 51 63
arg names: arg names:
(N_STATE 1) (N_STATE 1)
(N_EXC_STACK 0) (N_EXC_STACK 0)
@ -522,7 +522,7 @@ arg names:
09 RETURN_VALUE 09 RETURN_VALUE
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 18 bytes) File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 18 bytes)
Raw bytecode (code_info_size=6, bytecode_size=12): Raw bytecode (code_info_size=6, bytecode_size=12):
19 08 02 0f 80 9c 12 10 12 11 b0 15 02 36 00 59 19 08 05 12 80 9c 12 13 12 14 b0 15 05 36 00 59
51 63 51 63
arg names: self arg names: self
(N_STATE 4) (N_STATE 4)
@ -539,7 +539,7 @@ arg names: self
11 RETURN_VALUE 11 RETURN_VALUE
File cmdline/cmd_showbc.py, code block '<genexpr>' (descriptor: \.\+, bytecode @\.\+ 28 bytes) File cmdline/cmd_showbc.py, code block '<genexpr>' (descriptor: \.\+, bytecode @\.\+ 28 bytes)
Raw bytecode (code_info_size=9, bytecode_size=19): Raw bytecode (code_info_size=9, bytecode_size=19):
c3 40 0c 12 04 04 04 80 3b 53 b2 53 53 4b 0b c3 c3 40 0c 09 03 03 03 80 3b 53 b2 53 53 4b 0b c3
25 01 44 39 25 00 67 59 42 33 51 63 25 01 44 39 25 00 67 59 42 33 51 63
arg names: * * * arg names: * * *
(N_STATE 9) (N_STATE 9)
@ -562,7 +562,7 @@ arg names: * * *
18 RETURN_VALUE 18 RETURN_VALUE
File cmdline/cmd_showbc.py, code block '<listcomp>' (descriptor: \.\+, bytecode @\.\+ 26 bytes) File cmdline/cmd_showbc.py, code block '<listcomp>' (descriptor: \.\+, bytecode @\.\+ 26 bytes)
Raw bytecode (code_info_size=8, bytecode_size=18): Raw bytecode (code_info_size=8, bytecode_size=18):
4b 0c 14 04 04 04 80 3c 2b 00 b2 5f 4b 0b c3 25 4b 0c 0a 03 03 03 80 3c 2b 00 b2 5f 4b 0b c3 25
01 44 39 25 00 2f 14 42 33 63 01 44 39 25 00 2f 14 42 33 63
arg names: * * * arg names: * * *
(N_STATE 10) (N_STATE 10)
@ -582,7 +582,7 @@ arg names: * * *
17 RETURN_VALUE 17 RETURN_VALUE
File cmdline/cmd_showbc.py, code block '<dictcomp>' (descriptor: \.\+, bytecode @\.\+ 28 bytes) File cmdline/cmd_showbc.py, code block '<dictcomp>' (descriptor: \.\+, bytecode @\.\+ 28 bytes)
Raw bytecode (code_info_size=8, bytecode_size=20): Raw bytecode (code_info_size=8, bytecode_size=20):
53 0c 15 04 04 04 80 3d 2c 00 b2 5f 4b 0d c3 25 53 0c 0b 03 03 03 80 3d 2c 00 b2 5f 4b 0d c3 25
01 44 39 25 00 25 00 2f 19 42 31 63 01 44 39 25 00 25 00 2f 19 42 31 63
arg names: * * * arg names: * * *
(N_STATE 11) (N_STATE 11)
@ -603,7 +603,7 @@ arg names: * * *
19 RETURN_VALUE 19 RETURN_VALUE
File cmdline/cmd_showbc.py, code block 'closure' (descriptor: \.\+, bytecode @\.\+ 20 bytes) File cmdline/cmd_showbc.py, code block 'closure' (descriptor: \.\+, bytecode @\.\+ 20 bytes)
Raw bytecode (code_info_size=8, bytecode_size=12): Raw bytecode (code_info_size=8, bytecode_size=12):
19 0c 16 04 80 6f 25 23 25 00 81 f2 c1 81 27 00 19 0c 0c 03 80 6f 25 23 25 00 81 f2 c1 81 27 00
29 00 51 63 29 00 51 63
arg names: * arg names: *
(N_STATE 4) (N_STATE 4)
@ -623,7 +623,7 @@ arg names: *
11 RETURN_VALUE 11 RETURN_VALUE
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 13 bytes) File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ 13 bytes)
Raw bytecode (code_info_size=8, bytecode_size=5): Raw bytecode (code_info_size=8, bytecode_size=5):
9a 01 0a 02 04 09 80 8b b1 25 00 f2 63 9a 01 0a 05 03 08 80 8b b1 25 00 f2 63
arg names: * b arg names: * b
(N_STATE 4) (N_STATE 4)
(N_EXC_STACK 0) (N_EXC_STACK 0)