summaryrefslogtreecommitdiff
path: root/erts/emulator/beam/utils.c
diff options
context:
space:
mode:
authorSverker Eriksson <sverker@erlang.org>2015-02-17 20:10:46 +0100
committerBjörn-Egil Dahlberg <egil@erlang.org>2015-03-12 19:15:24 +0100
commit354ec7fe8ee31cde73c811bd5dea4f3e6787d10a (patch)
treedc5dccdb994a289e8d19d46ee91d336392c22fe9 /erts/emulator/beam/utils.c
parent04237c0948fdaba9af1a50c7fd9c5512afd10bb2 (diff)
downloaderlang-354ec7fe8ee31cde73c811bd5dea4f3e6787d10a.tar.gz
erts: Add hashing of hashmaps
Diffstat (limited to 'erts/emulator/beam/utils.c')
-rw-r--r--erts/emulator/beam/utils.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index f79cb8db7d..0f2d89bbfe 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -1288,6 +1288,55 @@ make_hash2(Eterm term)
goto hash2_common;
}
break;
+ case HASHMAP_SUBTAG:
+ {
+ Eterm* ptr = boxed_val(term) + 1;
+ Uint size;
+ int i;
+ switch (hdr & _HEADER_MAP_SUBTAG_MASK) {
+ case HAMT_SUBTAG_HEAD_ARRAY:
+ case HAMT_SUBTAG_HEAD_BITMAP:
+ size = *ptr++;
+ UINT32_HASH(size, HCONST_16);
+ if (size == 0)
+ goto hash2_common;
+ ESTACK_PUSH(s, hash_xor_values);
+ ESTACK_PUSH(s, hash_xor_keys);
+ ESTACK_PUSH(s, hash);
+ ESTACK_PUSH(s, HASH_MAP_TAIL);
+ hash = 0;
+ hash_xor_keys = 0;
+ hash_xor_values = 0;
+ }
+ switch (hdr & _HEADER_MAP_SUBTAG_MASK) {
+ case HAMT_SUBTAG_HEAD_ARRAY:
+ case HAMT_SUBTAG_NODE_ARRAY:
+ i = 16;
+ break;
+ case HAMT_SUBTAG_HEAD_BITMAP:
+ case HAMT_SUBTAG_NODE_BITMAP:
+ i = hashmap_bitcount(MAP_HEADER_VAL(hdr));
+ break;
+ default:
+ erl_exit(1, "bad header");
+ }
+ while (i) {
+ if (is_list(*ptr)) {
+ Eterm* cons = list_val(*ptr);
+ ESTACK_PUSH(s, HASH_MAP_KEY);
+ ESTACK_PUSH(s, CAR(cons));
+ ESTACK_PUSH(s, HASH_MAP_VAL);
+ ESTACK_PUSH(s, CDR(cons));
+ }
+ else {
+ ASSERT(is_boxed(*ptr));
+ ESTACK_PUSH(s, *ptr);
+ }
+ i--; ptr++;
+ }
+ goto hash2_common;
+ }
+ break;
case EXPORT_SUBTAG:
{
Export* ep = *((Export **) (export_val(term) + 1));