Browse Source

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.
pull/4318/head
Damien George 6 years ago
parent
commit
e328a5d469
  1. 30
      py/compile.c
  2. 5
      py/emit.h
  3. 20
      py/emitcommon.c
  4. 11
      py/scope.c
  5. 3
      py/scope.h

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__);

5
py/emit.h

@ -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);

20
py/emitcommon.c

@ -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

@ -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 {

3
py/scope.h

@ -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…
Cancel
Save