py/scope: Optimise scope_find_or_add_id to not need "added" arg.
Taking the address of a local variable is mildly expensive, in code size and stack usage. So optimise scope_find_or_add_id() to not need to take a pointer to the "added" variable, and instead take the kind to use for newly added identifiers.
This commit is contained in:
parent
ba92c79841
commit
e328a5d469
30
py/compile.c
30
py/compile.c
|
@ -1180,8 +1180,8 @@ STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
|||
}
|
||||
}
|
||||
|
||||
STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, bool added, id_info_t *id_info) {
|
||||
if (!added && id_info->kind != ID_INFO_KIND_GLOBAL_EXPLICIT) {
|
||||
STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) {
|
||||
if (id_info->kind != ID_INFO_KIND_UNDECIDED && id_info->kind != ID_INFO_KIND_GLOBAL_EXPLICIT) {
|
||||
compile_syntax_error(comp, pn, "identifier redefined as global");
|
||||
return;
|
||||
}
|
||||
|
@ -1194,8 +1194,8 @@ STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, bool ad
|
|||
}
|
||||
}
|
||||
|
||||
STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, bool added, id_info_t *id_info) {
|
||||
if (added) {
|
||||
STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) {
|
||||
if (id_info->kind == ID_INFO_KIND_UNDECIDED) {
|
||||
id_info->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;
|
||||
scope_check_to_close_over(comp->scope_cur, id_info);
|
||||
if (id_info->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
|
||||
|
@ -1219,12 +1219,11 @@ STATIC void compile_global_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_
|
|||
int n = mp_parse_node_extract_list(&pns->nodes[0], PN_name_list, &nodes);
|
||||
for (int i = 0; i < n; i++) {
|
||||
qstr qst = MP_PARSE_NODE_LEAF_ARG(nodes[i]);
|
||||
bool added;
|
||||
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);
|
||||
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, ID_INFO_KIND_UNDECIDED);
|
||||
if (is_global) {
|
||||
compile_declare_global(comp, (mp_parse_node_t)pns, added, id_info);
|
||||
compile_declare_global(comp, (mp_parse_node_t)pns, id_info);
|
||||
} else {
|
||||
compile_declare_nonlocal(comp, (mp_parse_node_t)pns, added, id_info);
|
||||
compile_declare_nonlocal(comp, (mp_parse_node_t)pns, id_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2836,9 +2835,8 @@ STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn
|
|||
}
|
||||
|
||||
if (param_name != MP_QSTR_NULL) {
|
||||
bool added;
|
||||
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
|
||||
if (!added) {
|
||||
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, ID_INFO_KIND_UNDECIDED);
|
||||
if (id_info->kind != ID_INFO_KIND_UNDECIDED) {
|
||||
compile_syntax_error(comp, pn, "argument name reused");
|
||||
return;
|
||||
}
|
||||
|
@ -3034,10 +3032,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
|
|||
// so we use the blank qstr.
|
||||
qstr qstr_arg = MP_QSTR_;
|
||||
if (comp->pass == MP_PASS_SCOPE) {
|
||||
bool added;
|
||||
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);
|
||||
assert(added);
|
||||
id_info->kind = ID_INFO_KIND_LOCAL;
|
||||
scope_find_or_add_id(comp->scope_cur, qstr_arg, ID_INFO_KIND_LOCAL);
|
||||
scope->num_pos_args = 1;
|
||||
}
|
||||
|
||||
|
@ -3077,10 +3072,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
|
|||
assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
|
||||
|
||||
if (comp->pass == MP_PASS_SCOPE) {
|
||||
bool added;
|
||||
id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
|
||||
assert(added);
|
||||
id_info->kind = ID_INFO_KIND_LOCAL;
|
||||
scope_find_or_add_id(scope, MP_QSTR___class__, ID_INFO_KIND_LOCAL);
|
||||
}
|
||||
|
||||
compile_load_id(comp, MP_QSTR___name__);
|
||||
|
|
|
@ -159,7 +159,10 @@ typedef struct _emit_method_table_t {
|
|||
|
||||
int mp_native_type_from_qstr(qstr qst);
|
||||
|
||||
void mp_emit_common_get_id_for_load(scope_t *scope, qstr qst);
|
||||
static inline void mp_emit_common_get_id_for_load(scope_t *scope, qstr qst) {
|
||||
scope_find_or_add_id(scope, qst, ID_INFO_KIND_GLOBAL_IMPLICIT);
|
||||
}
|
||||
|
||||
void mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst);
|
||||
void mp_emit_common_id_op(emit_t *emit, const mp_emit_method_table_id_ops_t *emit_method_table, scope_t *scope, qstr qst);
|
||||
|
||||
|
|
|
@ -30,26 +30,10 @@
|
|||
|
||||
#if MICROPY_ENABLE_COMPILER
|
||||
|
||||
void mp_emit_common_get_id_for_load(scope_t *scope, qstr qst) {
|
||||
// name adding/lookup
|
||||
bool added;
|
||||
id_info_t *id = scope_find_or_add_id(scope, qst, &added);
|
||||
if (added) {
|
||||
id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;
|
||||
}
|
||||
}
|
||||
|
||||
void mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst) {
|
||||
// name adding/lookup
|
||||
bool added;
|
||||
id_info_t *id = scope_find_or_add_id(scope, qst, &added);
|
||||
if (added) {
|
||||
if (SCOPE_IS_FUNC_LIKE(scope->kind)) {
|
||||
id->kind = ID_INFO_KIND_LOCAL;
|
||||
} else {
|
||||
id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;
|
||||
}
|
||||
} else if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
|
||||
id_info_t *id = scope_find_or_add_id(scope, qst, ID_INFO_KIND_GLOBAL_IMPLICIT);
|
||||
if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
|
||||
// rebind as a local variable
|
||||
id->kind = ID_INFO_KIND_LOCAL;
|
||||
}
|
||||
|
|
11
py/scope.c
11
py/scope.c
|
@ -64,10 +64,9 @@ void scope_free(scope_t *scope) {
|
|||
m_del(scope_t, scope, 1);
|
||||
}
|
||||
|
||||
id_info_t *scope_find_or_add_id(scope_t *scope, qstr qst, bool *added) {
|
||||
id_info_t *scope_find_or_add_id(scope_t *scope, qstr qst, scope_kind_t kind) {
|
||||
id_info_t *id_info = scope_find(scope, qst);
|
||||
if (id_info != NULL) {
|
||||
*added = false;
|
||||
return id_info;
|
||||
}
|
||||
|
||||
|
@ -82,11 +81,10 @@ id_info_t *scope_find_or_add_id(scope_t *scope, qstr qst, bool *added) {
|
|||
// handled by the compiler because it adds arguments before compiling the body
|
||||
id_info = &scope->id_info[scope->id_info_len++];
|
||||
|
||||
id_info->kind = 0;
|
||||
id_info->kind = kind;
|
||||
id_info->flags = 0;
|
||||
id_info->local_num = 0;
|
||||
id_info->qst = qst;
|
||||
*added = true;
|
||||
return id_info;
|
||||
}
|
||||
|
||||
|
@ -110,9 +108,8 @@ STATIC void scope_close_over_in_parents(scope_t *scope, qstr qst) {
|
|||
assert(scope->parent != NULL); // we should have at least 1 parent
|
||||
for (scope_t *s = scope->parent;; s = s->parent) {
|
||||
assert(s->parent != NULL); // we should not get to the outer scope
|
||||
bool added;
|
||||
id_info_t *id = scope_find_or_add_id(s, qst, &added);
|
||||
if (added) {
|
||||
id_info_t *id = scope_find_or_add_id(s, qst, ID_INFO_KIND_UNDECIDED);
|
||||
if (id->kind == ID_INFO_KIND_UNDECIDED) {
|
||||
// variable not previously declared in this scope, so declare it as free and keep searching parents
|
||||
id->kind = ID_INFO_KIND_FREE;
|
||||
} else {
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "py/emitglue.h"
|
||||
|
||||
enum {
|
||||
ID_INFO_KIND_UNDECIDED,
|
||||
ID_INFO_KIND_GLOBAL_IMPLICIT,
|
||||
ID_INFO_KIND_GLOBAL_EXPLICIT,
|
||||
ID_INFO_KIND_LOCAL, // in a function f, written and only referenced by f
|
||||
|
@ -90,7 +91,7 @@ typedef struct _scope_t {
|
|||
|
||||
scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, mp_uint_t emit_options);
|
||||
void scope_free(scope_t *scope);
|
||||
id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added);
|
||||
id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, scope_kind_t kind);
|
||||
id_info_t *scope_find(scope_t *scope, qstr qstr);
|
||||
id_info_t *scope_find_global(scope_t *scope, qstr qstr);
|
||||
void scope_check_to_close_over(scope_t *scope, id_info_t *id);
|
||||
|
|
Loading…
Reference in New Issue