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:
Damien George 2018-10-27 22:41:21 +11:00
parent ba92c79841
commit e328a5d469
5 changed files with 23 additions and 46 deletions

View File

@ -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) { STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) {
if (!added && id_info->kind != ID_INFO_KIND_GLOBAL_EXPLICIT) { 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"); compile_syntax_error(comp, pn, "identifier redefined as global");
return; 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) { STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) {
if (added) { if (id_info->kind == ID_INFO_KIND_UNDECIDED) {
id_info->kind = ID_INFO_KIND_GLOBAL_IMPLICIT; id_info->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;
scope_check_to_close_over(comp->scope_cur, id_info); scope_check_to_close_over(comp->scope_cur, id_info);
if (id_info->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) { 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); int n = mp_parse_node_extract_list(&pns->nodes[0], PN_name_list, &nodes);
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
qstr qst = MP_PARSE_NODE_LEAF_ARG(nodes[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, ID_INFO_KIND_UNDECIDED);
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);
if (is_global) { 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 { } 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) { if (param_name != MP_QSTR_NULL) {
bool added; id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, ID_INFO_KIND_UNDECIDED);
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added); if (id_info->kind != ID_INFO_KIND_UNDECIDED) {
if (!added) {
compile_syntax_error(comp, pn, "argument name reused"); compile_syntax_error(comp, pn, "argument name reused");
return; 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. // so we use the blank qstr.
qstr qstr_arg = MP_QSTR_; qstr qstr_arg = MP_QSTR_;
if (comp->pass == MP_PASS_SCOPE) { if (comp->pass == MP_PASS_SCOPE) {
bool added; scope_find_or_add_id(comp->scope_cur, qstr_arg, ID_INFO_KIND_LOCAL);
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->num_pos_args = 1; 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); assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
if (comp->pass == MP_PASS_SCOPE) { if (comp->pass == MP_PASS_SCOPE) {
bool added; scope_find_or_add_id(scope, MP_QSTR___class__, ID_INFO_KIND_LOCAL);
id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
assert(added);
id_info->kind = ID_INFO_KIND_LOCAL;
} }
compile_load_id(comp, MP_QSTR___name__); compile_load_id(comp, MP_QSTR___name__);

View File

@ -159,7 +159,10 @@ typedef struct _emit_method_table_t {
int mp_native_type_from_qstr(qstr qst); 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_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); 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);

View File

@ -30,26 +30,10 @@
#if MICROPY_ENABLE_COMPILER #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) { void mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst) {
// name adding/lookup // name adding/lookup
bool added; id_info_t *id = scope_find_or_add_id(scope, qst, ID_INFO_KIND_GLOBAL_IMPLICIT);
id_info_t *id = scope_find_or_add_id(scope, qst, &added); if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
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) {
// rebind as a local variable // rebind as a local variable
id->kind = ID_INFO_KIND_LOCAL; id->kind = ID_INFO_KIND_LOCAL;
} }

View File

@ -64,10 +64,9 @@ void scope_free(scope_t *scope) {
m_del(scope_t, scope, 1); 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); id_info_t *id_info = scope_find(scope, qst);
if (id_info != NULL) { if (id_info != NULL) {
*added = false;
return id_info; 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 // handled by the compiler because it adds arguments before compiling the body
id_info = &scope->id_info[scope->id_info_len++]; id_info = &scope->id_info[scope->id_info_len++];
id_info->kind = 0; id_info->kind = kind;
id_info->flags = 0; id_info->flags = 0;
id_info->local_num = 0; id_info->local_num = 0;
id_info->qst = qst; id_info->qst = qst;
*added = true;
return id_info; 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 assert(scope->parent != NULL); // we should have at least 1 parent
for (scope_t *s = scope->parent;; s = s->parent) { for (scope_t *s = scope->parent;; s = s->parent) {
assert(s->parent != NULL); // we should not get to the outer scope 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, ID_INFO_KIND_UNDECIDED);
id_info_t *id = scope_find_or_add_id(s, qst, &added); if (id->kind == ID_INFO_KIND_UNDECIDED) {
if (added) {
// variable not previously declared in this scope, so declare it as free and keep searching parents // variable not previously declared in this scope, so declare it as free and keep searching parents
id->kind = ID_INFO_KIND_FREE; id->kind = ID_INFO_KIND_FREE;
} else { } else {

View File

@ -30,6 +30,7 @@
#include "py/emitglue.h" #include "py/emitglue.h"
enum { enum {
ID_INFO_KIND_UNDECIDED,
ID_INFO_KIND_GLOBAL_IMPLICIT, ID_INFO_KIND_GLOBAL_IMPLICIT,
ID_INFO_KIND_GLOBAL_EXPLICIT, ID_INFO_KIND_GLOBAL_EXPLICIT,
ID_INFO_KIND_LOCAL, // in a function f, written and only referenced by f 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); 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); 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(scope_t *scope, qstr qstr);
id_info_t *scope_find_global(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); void scope_check_to_close_over(scope_t *scope, id_info_t *id);