diff options
author | Sverker Eriksson <[email protected]> | 2015-03-03 19:26:03 +0100 |
---|---|---|
committer | Björn-Egil Dahlberg <[email protected]> | 2015-03-12 19:15:31 +0100 |
commit | 412c30b4dcdb8388b7472c8abb328f2a2fce92c0 (patch) | |
tree | 70325bc1ca23bdd55be031e0e83c4b20aff88f04 /erts/emulator/beam | |
parent | 7e859457ef60483f6f99a0506e8abf65abcc06ef (diff) | |
download | otp-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.c | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_map.c | 36 | ||||
-rw-r--r-- | erts/emulator/beam/erl_term.h | 4 |
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 |