aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2015-02-26 14:45:38 +0100
committerBjörn-Egil Dahlberg <[email protected]>2015-03-12 19:15:29 +0100
commitf7ee6181417f05670e2e733085dd7f038d6f30f8 (patch)
tree514d5d97fc1640d2cc46a037b740414da742d6a0 /erts
parent02c573ba7fee64cc65ec7c7ee286aa9ce5415546 (diff)
downloadotp-f7ee6181417f05670e2e733085dd7f038d6f30f8.tar.gz
otp-f7ee6181417f05670e2e733085dd7f038d6f30f8.tar.bz2
otp-f7ee6181417f05670e2e733085dd7f038d6f30f8.zip
erts: Handle hashmap in get_map_element(s) instructions
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/beam_emu.c160
-rw-r--r--erts/emulator/beam/erl_map.c5
-rw-r--r--erts/emulator/beam/erl_map.h3
3 files changed, 99 insertions, 69 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 034436e975..9a05e26859 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -2460,12 +2460,8 @@ do { \
OpCase(i_get_map_elements_fsI): {
Eterm map;
- map_t *mp;
- Eterm field;
- Eterm *ks;
- Eterm *vs;
BeamInstr *fs;
- Uint sz,n;
+ Uint sz, n;
GetArg1(1, map);
@@ -2473,36 +2469,56 @@ do { \
* i.e. that it follows a test is_map if needed.
*/
- mp = (map_t *)map_val(map);
- sz = map_get_size(mp);
-
- if (sz == 0) {
- SET_I((BeamInstr *) Arg(0));
- goto get_map_elements_fail;
- }
-
n = (Uint)Arg(2) / 2;
fs = &Arg(3); /* pattern fields and target registers */
- ks = map_get_keys(mp);
- vs = map_get_values(mp);
- while(sz) {
- field = (Eterm)*fs;
- if (EQ(field,*ks)) {
- PUT_TERM_REG(*vs, fs[1]);
- n--;
+ if (is_map(map)) {
+ map_t *mp;
+ Eterm *ks;
+ Eterm *vs;
+
+ mp = (map_t *)map_val(map);
+ sz = map_get_size(mp);
+
+ if (sz == 0) {
+ SET_I((BeamInstr *) Arg(0));
+ goto get_map_elements_fail;
+ }
+
+ ks = map_get_keys(mp);
+ vs = map_get_values(mp);
+
+ while(sz) {
+ if (EQ((Eterm)*fs,*ks)) {
+ PUT_TERM_REG(*vs, fs[1]);
+ n--;
+ fs += 2;
+ /* no more values to fetch, we are done */
+ if (n == 0) break;
+ }
+ ks++; sz--;
+ vs++;
+ }
+
+ if (n) {
+ SET_I((BeamInstr *) Arg(0));
+ goto get_map_elements_fail;
+ }
+ } else {
+ const Eterm *v;
+ Uint32 hx;
+ ASSERT(is_hashmap(map));
+ while(n--) {
+ hx = hashmap_make_hash((Eterm)*fs);
+ if ((v = erts_hashmap_get(hx,(Eterm)*fs, map)) == NULL) {
+ SET_I((BeamInstr *) Arg(0));
+ goto get_map_elements_fail;
+ }
+ PUT_TERM_REG(*v, fs[1]);
fs += 2;
- /* no more values to fetch, we are done */
- if (n == 0) break;
}
- ks++; sz--;
- vs++;
}
- if (n) {
- SET_I((BeamInstr *) Arg(0));
- goto get_map_elements_fail;
- }
I += 4 + Arg(2);
get_map_elements_fail:
@@ -6444,55 +6460,69 @@ new_fun(Process* p, Eterm* reg, ErlFunEntry* fe, int num_free)
static int has_not_map_field(Eterm map, Eterm key)
{
- map_t* mp;
- Eterm* keys;
- Uint i;
- Uint n;
-
- mp = (map_t *)map_val(map);
- keys = map_get_keys(mp);
- n = map_get_size(mp);
- if (is_immed(key)) {
- for (i = 0; i < n; i++) {
- if (keys[i] == key) {
- return 0;
+ Uint32 hx;
+ if (is_map(map)) {
+ map_t* mp;
+ Eterm* keys;
+ Uint i;
+ Uint n;
+
+ mp = (map_t *)map_val(map);
+ keys = map_get_keys(mp);
+ n = map_get_size(mp);
+ if (is_immed(key)) {
+ for (i = 0; i < n; i++) {
+ if (keys[i] == key) {
+ return 0;
+ }
}
- }
- } else {
- for (i = 0; i < n; i++) {
- if (EQ(keys[i], key)) {
- return 0;
+ } else {
+ for (i = 0; i < n; i++) {
+ if (EQ(keys[i], key)) {
+ return 0;
+ }
}
}
+ return 1;
}
- return 1;
+ ASSERT(is_hashmap(map));
+ hx = hashmap_make_hash(key);
+ return erts_hashmap_get(hx,key,map) ? 0 : 1;
}
static Eterm get_map_element(Eterm map, Eterm key)
{
- map_t *mp;
- Eterm* ks, *vs;
- Uint i;
- Uint n;
-
- mp = (map_t *)map_val(map);
- ks = map_get_keys(mp);
- vs = map_get_values(mp);
- n = map_get_size(mp);
- if (is_immed(key)) {
- for (i = 0; i < n; i++) {
- if (ks[i] == key) {
- return vs[i];
+ Uint32 hx;
+ const Eterm *vs;
+ if (is_map(map)) {
+ map_t *mp;
+ Eterm *ks;
+ Uint i;
+ Uint n;
+
+ mp = (map_t *)map_val(map);
+ ks = map_get_keys(mp);
+ vs = map_get_values(mp);
+ n = map_get_size(mp);
+ if (is_immed(key)) {
+ for (i = 0; i < n; i++) {
+ if (ks[i] == key) {
+ return vs[i];
+ }
}
- }
- } else {
- for (i = 0; i < n; i++) {
- if (EQ(ks[i], key)) {
- return vs[i];
+ } else {
+ for (i = 0; i < n; i++) {
+ if (EQ(ks[i], key)) {
+ return vs[i];
+ }
}
}
+ return THE_NON_VALUE;
}
- return THE_NON_VALUE;
+ ASSERT(is_hashmap(map));
+ hx = hashmap_make_hash(key);
+ vs = erts_hashmap_get(hx,key,map);
+ return vs ? *vs : THE_NON_VALUE;
}
#define GET_TERM(term, dest) \
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index 4242807933..2be4c9a730 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -77,7 +77,6 @@ typedef struct {
Eterm val;
} hxnode_t;
-static const Eterm *hashmap_get(Uint32 hx, Eterm key, Eterm node);
static Eterm hashmap_insert(Process *p, Uint32 hx, Eterm key, Eterm value, Eterm node, int is_update);
static Eterm map_merge(Process *p, Eterm nodeA, Eterm nodeB);
static Eterm map_merge_mixed(Process *p, Eterm flat, Eterm tree, int swap_args);
@@ -199,7 +198,7 @@ erts_maps_get(Eterm key, Eterm map)
ASSERT(is_hashmap(map));
hx = hashmap_make_hash(key);
- return hashmap_get(hx, key, map);
+ return erts_hashmap_get(hx, key, map);
}
BIF_RETTYPE maps_find_2(BIF_ALIST_2) {
@@ -1660,7 +1659,7 @@ Eterm* hashmap_iterator_next(ErtsWStack* s) {
}
}
-static const Eterm *hashmap_get(Uint32 hx, Eterm key, Eterm node) {
+const Eterm *erts_hashmap_get(Uint32 hx, Eterm key, Eterm node) {
Eterm *ptr, hdr;
Eterm th[2];
Uint ix,slot, lvl = 0;
diff --git a/erts/emulator/beam/erl_map.h b/erts/emulator/beam/erl_map.h
index 7fddc9c240..7175e653d9 100644
--- a/erts/emulator/beam/erl_map.h
+++ b/erts/emulator/beam/erl_map.h
@@ -92,8 +92,9 @@ 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_get(Eterm key, Eterm map);
Eterm erts_hashmap_from_array(Process *p, Eterm *leafs, Uint n);
+Eterm erts_hashmap_insert(Process *p, Uint32 hx, Eterm key, Eterm val, Eterm node, int is_update);
+const Eterm *erts_hashmap_get(Uint32 hx, Eterm key, Eterm map);
#if HALFWORD_HEAP
const Eterm *