From 487dbdb26748b86cf247600af187437310311145 Mon Sep 17 00:00:00 2001
From: Damien George <damien.p.george@gmail.com>
Date: Wed, 1 Nov 2017 13:16:16 +1100
Subject: [PATCH] py/compile: Use alloca instead of qstr_build when compiling
 import name.

The technique of using alloca is how dotted import names are composed in
mp_import_from and mp_builtin___import__, so use the same technique in the
compiler.  This puts less pressure on the heap (only the stack is used if
the qstr already exists, and if it doesn't exist then the standard qstr
block memory is used for the new qstr rather than a separate chunk of the
heap) and reduces overall code size.
---
 py/compile.c |  6 +++---
 py/qstr.c    | 23 -----------------------
 py/qstr.h    |  3 ---
 3 files changed, 3 insertions(+), 29 deletions(-)

diff --git a/py/compile.c b/py/compile.c
index 4e704abfb..ee017498a 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -1050,8 +1050,8 @@ STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) {
             for (int i = 0; i < n; i++) {
                 len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
             }
-            byte *q_ptr;
-            byte *str_dest = qstr_build_start(len, &q_ptr);
+            char *q_ptr = alloca(len);
+            char *str_dest = q_ptr;
             for (int i = 0; i < n; i++) {
                 if (i > 0) {
                     *str_dest++ = '.';
@@ -1061,7 +1061,7 @@ STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) {
                 memcpy(str_dest, str_src, str_src_len);
                 str_dest += str_src_len;
             }
-            qstr q_full = qstr_build_end(q_ptr);
+            qstr q_full = qstr_from_strn(q_ptr, len);
             EMIT_ARG(import_name, q_full);
             if (is_as) {
                 for (int i = 1; i < n; i++) {
diff --git a/py/qstr.c b/py/qstr.c
index 95c9b6835..a3c9612c6 100644
--- a/py/qstr.c
+++ b/py/qstr.c
@@ -243,29 +243,6 @@ qstr qstr_from_strn(const char *str, size_t len) {
     return q;
 }
 
-byte *qstr_build_start(size_t len, byte **q_ptr) {
-    assert(len < (1 << (8 * MICROPY_QSTR_BYTES_IN_LEN)));
-    *q_ptr = m_new(byte, MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len + 1);
-    Q_SET_LENGTH(*q_ptr, len);
-    return Q_GET_DATA(*q_ptr);
-}
-
-qstr qstr_build_end(byte *q_ptr) {
-    QSTR_ENTER();
-    qstr q = qstr_find_strn((const char*)Q_GET_DATA(q_ptr), Q_GET_LENGTH(q_ptr));
-    if (q == 0) {
-        size_t len = Q_GET_LENGTH(q_ptr);
-        mp_uint_t hash = qstr_compute_hash(Q_GET_DATA(q_ptr), len);
-        Q_SET_HASH(q_ptr, hash);
-        q_ptr[MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len] = '\0';
-        q = qstr_add(q_ptr);
-    } else {
-        m_del(byte, q_ptr, Q_GET_ALLOC(q_ptr));
-    }
-    QSTR_EXIT();
-    return q;
-}
-
 mp_uint_t qstr_hash(qstr q) {
     return Q_GET_HASH(find_qstr(q));
 }
diff --git a/py/qstr.h b/py/qstr.h
index e2bdcc351..63fd0c369 100644
--- a/py/qstr.h
+++ b/py/qstr.h
@@ -65,9 +65,6 @@ qstr qstr_find_strn(const char *str, size_t str_len); // returns MP_QSTR_NULL if
 qstr qstr_from_str(const char *str);
 qstr qstr_from_strn(const char *str, size_t len);
 
-byte *qstr_build_start(size_t len, byte **q_ptr);
-qstr qstr_build_end(byte *q_ptr);
-
 mp_uint_t qstr_hash(qstr q);
 const char *qstr_str(qstr q);
 size_t qstr_len(qstr q);
-- 
GitLab