From 5f3bda422a18d49fb282a93968b658c568343b7d Mon Sep 17 00:00:00 2001
From: Damien George <damien.p.george@gmail.com>
Date: Fri, 2 Sep 2016 14:42:53 +1000
Subject: [PATCH] py: If str/bytes hash is 0 then explicitly compute it.

---
 py/objstr.c  | 6 ++++++
 py/objstr.h  | 1 +
 py/runtime.c | 4 ++++
 3 files changed, 11 insertions(+)

diff --git a/py/objstr.c b/py/objstr.c
index e83ff7c84..406ccf290 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -158,6 +158,9 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
             if (MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
                 GET_STR_DATA_LEN(args[0], str_data, str_len);
                 GET_STR_HASH(args[0], str_hash);
+                if (str_hash == 0) {
+                    str_hash = qstr_compute_hash(str_data, str_len);
+                }
                 mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(type, NULL, str_len));
                 o->data = str_data;
                 o->hash = str_hash;
@@ -191,6 +194,9 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size
         }
         GET_STR_DATA_LEN(args[0], str_data, str_len);
         GET_STR_HASH(args[0], str_hash);
+        if (str_hash == 0) {
+            str_hash = qstr_compute_hash(str_data, str_len);
+        }
         mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(&mp_type_bytes, NULL, str_len));
         o->data = str_data;
         o->hash = str_hash;
diff --git a/py/objstr.h b/py/objstr.h
index 07929156c..e14568dac 100644
--- a/py/objstr.h
+++ b/py/objstr.h
@@ -39,6 +39,7 @@ typedef struct _mp_obj_str_t {
 #define MP_DEFINE_STR_OBJ(obj_name, str) mp_obj_str_t obj_name = {{&mp_type_str}, 0, sizeof(str) - 1, (const byte*)str}
 
 // use this macro to extract the string hash
+// warning: the hash can be 0, meaning invalid, and must then be explicitly computed from the data
 #define GET_STR_HASH(str_obj_in, str_hash) \
     mp_uint_t str_hash; if (MP_OBJ_IS_QSTR(str_obj_in)) \
     { str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->hash; }
diff --git a/py/runtime.c b/py/runtime.c
index 04b3a34de..48e815f0f 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -217,6 +217,10 @@ mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) {
     } else if (op == MP_UNARY_OP_HASH && MP_OBJ_IS_STR_OR_BYTES(arg)) {
         // fast path for hashing str/bytes
         GET_STR_HASH(arg, h);
+        if (h == 0) {
+            GET_STR_DATA_LEN(arg, data, len);
+            h = qstr_compute_hash(data, len);
+        }
         return MP_OBJ_NEW_SMALL_INT(h);
     } else {
         mp_obj_type_t *type = mp_obj_get_type(arg);
-- 
GitLab