aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2015-04-10 15:52:11 +0200
committerBjörn-Egil Dahlberg <[email protected]>2015-04-10 15:52:11 +0200
commitc3b50fc66fced021b0886163b9c7aeb7ce5f20c0 (patch)
tree3385486a3762d6f45af3ccfc87b5da069a14f834 /erts/emulator/beam
parent42b1ee09491706cd255f8c146e07c1cb2cd939cc (diff)
parent30ed5b1cc6aa0efe6ac099b66d33d46c7c0c6b47 (diff)
downloadotp-c3b50fc66fced021b0886163b9c7aeb7ce5f20c0.tar.gz
otp-c3b50fc66fced021b0886163b9c7aeb7ce5f20c0.tar.bz2
otp-c3b50fc66fced021b0886163b9c7aeb7ce5f20c0.zip
Merge branch 'egil/fix-maps-deep-colliding-merge'
* egil/fix-maps-deep-colliding-merge: erts: Fix deep colliding hash values in maps:from_list/1
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/erl_map.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index d1df737723..98023bbb47 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -679,7 +679,35 @@ static Eterm hashmap_from_chunked_array(ErtsHeapFactory *factory, hxnode_t *hxns
DECLARE_ESTACK(stack);
Eterm res = NIL, *hp = NULL, *nhp;
- ASSERT(n > 1);
+
+ /* if we get here with only one element then
+ * we have eight levels of collisions
+ */
+
+ if (n == 1) {
+ res = hxns[0].val;
+ v = hxns[0].hx;
+ for (d = 7; d > 0; d--) {
+ slot = maskval(v,d);
+ hp = erts_produce_heap(factory, HAMT_NODE_BITMAP_SZ(1), HALLOC_EXTRA);
+ hp[0] = MAP_HEADER_HAMT_NODE_BITMAP(1 << slot);
+ hp[1] = res;
+ res = make_hashmap(hp);
+ }
+
+ slot = maskval(v,0);
+ hp = erts_produce_heap(factory, (is_root ? 3 : 2), 0);
+
+ if (is_root) {
+ hp[0] = MAP_HEADER_HAMT_HEAD_BITMAP(1 << slot);
+ hp[1] = size;
+ hp[2] = res;
+ } else {
+ hp[0] = MAP_HEADER_HAMT_NODE_BITMAP(1 << slot);
+ hp[1] = res;
+ }
+ return make_hashmap(hp);
+ }
/* push initial nodes on the stack,
* this is the starting depth */