aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/beam/beam_emu.c2
-rw-r--r--erts/emulator/beam/erl_map.c23
-rw-r--r--erts/emulator/beam/erl_map.h2
-rw-r--r--erts/emulator/beam/external.c4
4 files changed, 18 insertions, 13 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 9b4cd38d69..d45aa93f73 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -6589,7 +6589,7 @@ new_map(Process* p, Eterm* reg, BeamInstr* I)
p->htop = mhp;
factory.p = p;
- return erts_hashmap_from_array(&factory, thp, n/2);
+ return erts_hashmap_from_array(&factory, thp, n/2, 0);
}
if (HeapWordsLeft(p) < need) {
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index eacdd0b6c3..3ccfc61b08 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -87,7 +87,7 @@ static Eterm hashmap_values(Process *p, Eterm map);
static Eterm hashmap_delete(Process *p, Uint32 hx, Eterm key, Eterm node);
static Eterm map_from_validated_list(Process *p, Eterm list, Uint size);
static Eterm hashmap_from_validated_list(Process *p, Eterm list, Uint size);
-static Eterm hashmap_from_unsorted_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n);
+static Eterm hashmap_from_unsorted_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, int reject_dupkeys);
static Eterm hashmap_from_sorted_unique_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, int is_root);
static Eterm hashmap_from_chunked_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, int is_root);
static Eterm hashmap_info(Process *p, Eterm node);
@@ -419,7 +419,7 @@ static Eterm hashmap_from_validated_list(Process *p, Eterm list, Uint size) {
}
factory.p = p;
- res = hashmap_from_unsorted_array(&factory, hxns, size);
+ res = hashmap_from_unsorted_array(&factory, hxns, size, 0);
erts_free(ERTS_ALC_T_TMP, (void *) hxns);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(p);
@@ -462,7 +462,8 @@ static Eterm hashmap_from_validated_list(Process *p, Eterm list, Uint size) {
return res;
}
-Eterm erts_hashmap_from_array(ErtsHeapFactory* factory, Eterm *leafs, Uint n) {
+Eterm erts_hashmap_from_array(ErtsHeapFactory* factory, Eterm *leafs, Uint n,
+ int reject_dupkeys) {
Uint32 sw, hx;
Uint ix;
hxnode_t *hxns;
@@ -481,7 +482,7 @@ Eterm erts_hashmap_from_array(ErtsHeapFactory* factory, Eterm *leafs, Uint n) {
leafs += 2;
}
- res = hashmap_from_unsorted_array(factory, hxns, n);
+ res = hashmap_from_unsorted_array(factory, hxns, n, reject_dupkeys);
erts_free(ERTS_ALC_T_TMP, (void *) hxns);
@@ -523,7 +524,7 @@ Eterm erts_hashmap_from_ks_and_vs_extra(Process *p, Eterm *ks, Eterm *vs, Uint n
}
factory.p = p;
- res = hashmap_from_unsorted_array(&factory, hxns, sz);
+ res = hashmap_from_unsorted_array(&factory, hxns, sz, 0);
erts_free(ERTS_ALC_T_TMP, (void *) hxns);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(p);
@@ -532,7 +533,8 @@ Eterm erts_hashmap_from_ks_and_vs_extra(Process *p, Eterm *ks, Eterm *vs, Uint n
}
static Eterm hashmap_from_unsorted_array(ErtsHeapFactory* factory,
- hxnode_t *hxns, Uint n) {
+ hxnode_t *hxns, Uint n,
+ int reject_dupkeys) {
Uint jx = 0, ix = 0, lx, cx;
Eterm res;
@@ -566,7 +568,10 @@ static Eterm hashmap_from_unsorted_array(ErtsHeapFactory* factory,
while(ix < jx) {
lx = ix;
while(ix < jx && EQ(CAR(list_val(hxns[ix].val)), CAR(list_val(hxns[lx].val)))) {
- if (hxns[ix].i > hxns[lx].i) {
+ if (reject_dupkeys)
+ return THE_NON_VALUE;
+
+ if (hxns[ix].i > hxns[lx].i) {
lx = ix;
}
ix++;
@@ -1030,7 +1035,7 @@ static Eterm map_merge(Process *p, Eterm nodeA, Eterm nodeB) {
}
factory.p = p;
- res = hashmap_from_unsorted_array(&factory, hxns, n);
+ res = hashmap_from_unsorted_array(&factory, hxns, n, 0);
erts_free(ERTS_ALC_T_TMP, (void *) hxns);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(p);
@@ -1076,7 +1081,7 @@ static Eterm map_merge_mixed(Process *p, Eterm flat, Eterm tree, int swap_args)
}
factory.p = p;
- res = hashmap_from_unsorted_array(&factory, hxns, n);
+ res = hashmap_from_unsorted_array(&factory, hxns, n, 0);
erts_free(ERTS_ALC_T_TMP, (void *) hxns);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(p);
diff --git a/erts/emulator/beam/erl_map.h b/erts/emulator/beam/erl_map.h
index 35dbed86a9..39d98b9e03 100644
--- a/erts/emulator/beam/erl_map.h
+++ b/erts/emulator/beam/erl_map.h
@@ -102,7 +102,7 @@ int erts_validate_and_sort_map(map_t* map);
void hashmap_iterator_init(struct ErtsWStack_* s, Eterm node);
Eterm* hashmap_iterator_next(struct ErtsWStack_* s);
int hashmap_key_hash_cmp(Eterm* ap, Eterm* bp);
-Eterm erts_hashmap_from_array(ErtsHeapFactory*, Eterm *leafs, Uint n);
+Eterm erts_hashmap_from_array(ErtsHeapFactory*, Eterm *leafs, Uint n, int reject_dupkeys);
const Eterm *erts_hashmap_get(Uint32 hx, Eterm key, Eterm map);
#define erts_hashmap_from_ks_and_vs(P, KS, VS, N) \
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 0e012e9eec..9bcd9a7a50 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -3910,10 +3910,10 @@ dec_term_atom_common:
next = (Eterm *) hamt_list->next;
objp = hamt_list->objp;
- /*SVERK Make it reject duplicate keys */
*objp = erts_hashmap_from_array(&factory,
hamt_list->leaf_array,
- hamt_list->size);
+ hamt_list->size,
+ 1);
if (is_non_value(*objp))
goto error;