summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2019-02-27 00:10:04 +1100
committerDamien George <damien.p.george@gmail.com>2019-03-01 15:22:46 +1100
commit0779693c23fcc55993a06e4e0adf30a3d41f90f5 (patch)
tree7f80921f2b287bad50173f031a611b323fdab78c /py
parent8ce22662feadeb6b564f1087134346cb287251f0 (diff)
py/compile: Add optimisation to compile OrderedDict inplace.
This optimisation eliminates the need to create a temporary normal dict. The optimisation is enabled via MICROPY_COMP_CONST_LITERAL which is enabled by default (although only has an effect if OrderdDict is enabled). Thanks to @pfalcon for the initial idea and implementation.
Diffstat (limited to 'py')
-rw-r--r--py/compile.c33
-rw-r--r--py/mpconfig.h5
2 files changed, 34 insertions, 4 deletions
diff --git a/py/compile.c b/py/compile.c
index e660e668c..42222528e 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -164,6 +164,7 @@ STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const cha
STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra);
STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind);
+STATIC void compile_atom_brace_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool create_map);
STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn);
STATIC uint comp_next_label(compiler_t *comp) {
@@ -2247,6 +2248,20 @@ STATIC void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *p
EMIT_ARG(call_function, 2, 0, 0);
i = 1;
}
+
+ #if MICROPY_COMP_CONST_LITERAL && MICROPY_PY_COLLECTIONS_ORDEREDDICT
+ // handle special OrderedDict constructor
+ } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])
+ && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_OrderedDict
+ && MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_trailer_paren
+ && MP_PARSE_NODE_IS_STRUCT_KIND(pns_trail[0]->nodes[0], PN_atom_brace)) {
+ // at this point we have matched "OrderedDict({...})"
+
+ EMIT_ARG(call_function, 0, 0, 0);
+ mp_parse_node_struct_t *pns_dict = (mp_parse_node_struct_t*)pns_trail[0]->nodes[0];
+ compile_atom_brace_helper(comp, pns_dict, false);
+ i = 1;
+ #endif
}
// compile the remaining trailers
@@ -2455,16 +2470,20 @@ STATIC void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns)
}
}
-STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
+STATIC void compile_atom_brace_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool create_map) {
mp_parse_node_t pn = pns->nodes[0];
if (MP_PARSE_NODE_IS_NULL(pn)) {
// empty dict
- EMIT_ARG(build, 0, MP_EMIT_BUILD_MAP);
+ if (create_map) {
+ EMIT_ARG(build, 0, MP_EMIT_BUILD_MAP);
+ }
} else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
pns = (mp_parse_node_struct_t*)pn;
if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
// dict with one element
- EMIT_ARG(build, 1, MP_EMIT_BUILD_MAP);
+ if (create_map) {
+ EMIT_ARG(build, 1, MP_EMIT_BUILD_MAP);
+ }
compile_node(comp, pn);
EMIT(store_map);
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
@@ -2481,7 +2500,9 @@ STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
bool is_dict;
if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
// a dictionary
- EMIT_ARG(build, 1 + n, MP_EMIT_BUILD_MAP);
+ if (create_map) {
+ EMIT_ARG(build, 1 + n, MP_EMIT_BUILD_MAP);
+ }
compile_node(comp, pns->nodes[0]);
EMIT(store_map);
is_dict = true;
@@ -2551,6 +2572,10 @@ STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
}
}
+STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
+ compile_atom_brace_helper(comp, pns, true);
+}
+
STATIC void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
compile_trailer_paren_helper(comp, pns->nodes[0], false, 0);
}
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 47638fb0a..c4b62dd84 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -356,6 +356,11 @@
#define MICROPY_COMP_CONST_FOLDING (1)
#endif
+// Whether to enable optimisations for constant literals, eg OrderedDict
+#ifndef MICROPY_COMP_CONST_LITERAL
+#define MICROPY_COMP_CONST_LITERAL (1)
+#endif
+
// Whether to enable lookup of constants in modules; eg module.CONST
#ifndef MICROPY_COMP_MODULE_CONST
#define MICROPY_COMP_MODULE_CONST (0)