aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2015-03-03 19:26:03 +0100
committerBjörn-Egil Dahlberg <[email protected]>2015-03-12 19:15:31 +0100
commit412c30b4dcdb8388b7472c8abb328f2a2fce92c0 (patch)
tree70325bc1ca23bdd55be031e0e83c4b20aff88f04 /erts/emulator/beam
parent7e859457ef60483f6f99a0506e8abf65abcc06ef (diff)
downloadotp-412c30b4dcdb8388b7472c8abb328f2a2fce92c0.tar.gz
otp-412c30b4dcdb8388b7472c8abb328f2a2fce92c0.tar.bz2
otp-412c30b4dcdb8388b7472c8abb328f2a2fce92c0.zip
erts: Fix various map vs hamt size bugs
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/beam_emu.c2
-rw-r--r--erts/emulator/beam/erl_map.c36
-rw-r--r--erts/emulator/beam/erl_term.h4
3 files changed, 39 insertions, 3 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 8288eb9798..15591c3cad 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -6559,7 +6559,7 @@ new_map(Process* p, Eterm* reg, BeamInstr* I)
ptr = &Arg(4);
- if (n > MAP_SMALL_MAP_LIMIT) {
+ if (n > 2*MAP_SMALL_MAP_LIMIT) {
if (HeapWordsLeft(p) < n) {
erts_garbage_collect(p, n, reg, Arg(2));
}
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index ea041e2303..0cf1c0e59d 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -422,6 +422,41 @@ static Eterm hashmap_from_validated_list(Process *p, Eterm list, Uint size) {
erts_free(ERTS_ALC_T_TMP, (void *) hxns);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(p);
+ if (hashmap_size(res) <= MAP_SMALL_MAP_LIMIT) {
+ DECLARE_WSTACK(wstack);
+ Eterm *kv, *ks, *vs;
+ map_t *mp;
+ Eterm keys;
+ Uint n = hashmap_size(res);
+
+ /* build flat structure */
+ hp = HAlloc(p, 3 + 1 + (2 * n));
+ keys = make_tuple(hp);
+ *hp++ = make_arityval(n);
+ ks = hp;
+ hp += n;
+ mp = (map_t*)hp;
+ hp += MAP_HEADER_SIZE;
+ vs = hp;
+
+ mp->thing_word = MAP_HEADER;
+ mp->size = n;
+ mp->keys = keys;
+
+ hashmap_iterator_init(&wstack, res);
+
+ while ((kv=hashmap_iterator_next(&wstack)) != NULL) {
+ *ks++ = CAR(kv);
+ *vs++ = CDR(kv);
+ }
+
+ /* it cannot have multiple keys */
+ erts_validate_and_sort_map(mp);
+
+ DESTROY_WSTACK(wstack);
+ return make_map(mp);
+ }
+
return res;
}
@@ -461,6 +496,7 @@ Eterm erts_hashmap_from_ks_and_vs_extra(Process *p, Eterm *ks, Eterm *vs, Uint n
Eterm *hp, res;
sz = (key == THE_NON_VALUE) ? n : (n + 1);
+ ASSERT(sz > MAP_SMALL_MAP_LIMIT);
hp = HAlloc(p, 2 * sz);
/* create tmp hx values and leaf ptrs */
diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h
index 953525a45c..6d97344868 100644
--- a/erts/emulator/beam/erl_term.h
+++ b/erts/emulator/beam/erl_term.h
@@ -1110,8 +1110,8 @@ _ET_DECLARE_CHECKED(Uint,y_reg_index,Uint)
#define BINARY_DEF 0x0
#define LIST_DEF 0x1
#define NIL_DEF 0x2
-#define MAP_DEF 0x3
-#define HASHMAP_DEF 0x4
+#define HASHMAP_DEF 0x3
+#define MAP_DEF 0x4
#define TUPLE_DEF 0x5
#define PID_DEF 0x6
#define EXTERNAL_PID_DEF 0x7