diff options
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/beam/beam_emu.c | 14 | ||||
-rw-r--r-- | erts/emulator/beam/beam_load.c | 41 | ||||
-rw-r--r-- | erts/emulator/beam/ops.tab | 2 |
3 files changed, 49 insertions, 8 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 5f49032e23..6fde14bc8d 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -2427,7 +2427,7 @@ do { \ * i.e. that it follows a test is_map if needed. */ - n = (Uint)Arg(2) / 2; + n = (Uint)Arg(2) / 3; fs = &Arg(3); /* pattern fields and target registers */ if (is_flatmap(map)) { @@ -2450,12 +2450,11 @@ do { \ if (EQ((Eterm)*fs,*ks)) { PUT_TERM_REG(*vs, fs[1]); n--; - fs += 2; + fs += 3; /* no more values to fetch, we are done */ if (n == 0) break; } - ks++; sz--; - vs++; + ks++, sz--, vs++; } if (n) { @@ -2467,13 +2466,14 @@ do { \ Uint32 hx; ASSERT(is_hashmap(map)); while(n--) { - hx = hashmap_make_hash((Eterm)*fs); - if ((v = erts_hashmap_get(hx,(Eterm)*fs, map)) == NULL) { + hx = fs[2]; + ASSERT(hx == hashmap_make_hash((Eterm)fs[0])); + if ((v = erts_hashmap_get(hx, (Eterm)fs[0], map)) == NULL) { SET_I((BeamInstr *) Arg(0)); goto get_map_elements_fail; } PUT_TERM_REG(*v, fs[1]); - fs += 2; + fs += 3; } } diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index ee319d0a78..8d7beb4eb4 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -4219,6 +4219,47 @@ gen_get_map_element(LoaderState* stp, GenOpArg Fail, GenOpArg Src, } static GenOp* +gen_get_map_elements(LoaderState* stp, GenOpArg Fail, GenOpArg Src, + GenOpArg Size, GenOpArg* Rest) +{ + GenOp* op; + Uint32 hx; + Uint i; + GenOpArg* dst; +#ifdef DEBUG + int good_hash; +#endif + + ASSERT(Size.type == TAG_u); + + NEW_GENOP(stp, op); + op->op = genop_i_get_map_elements_3; + GENOP_ARITY(op, 3 + 3*(Size.val/2)); + op->next = NULL; + op->a[0] = Fail; + op->a[1] = Src; + op->a[2].type = TAG_u; + op->a[2].val = 3*(Size.val/2); + + dst = op->a+3; + for (i = 0; i < Size.val / 2; i++) { + dst[0] = Rest[2*i]; + dst[1] = Rest[2*i+1]; +#ifdef DEBUG + good_hash = +#endif + hash_genop_arg(stp, dst[0], &hx); +#ifdef DEBUG + ASSERT(good_hash); +#endif + dst[2].type = TAG_u; + dst[2].val = (BeamInstr) hx; + dst += 3; + } + return op; +} + +static GenOp* gen_has_map_fields(LoaderState* stp, GenOpArg Fail, GenOpArg Src, GenOpArg Size, GenOpArg* Rest) { diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab index 456f879ab5..9bdc9cb88d 100644 --- a/erts/emulator/beam/ops.tab +++ b/erts/emulator/beam/ops.tab @@ -1515,7 +1515,7 @@ has_map_fields Fail Src Size Rest=* => \ get_map_elements Fail Src=rxy Size=u==2 Rest=* => \ gen_get_map_element(Fail, Src, Size, Rest) get_map_elements Fail Src Size Rest=* | map_key_sort(Size, Rest) => \ - i_get_map_elements Fail Src Size Rest + gen_get_map_elements(Fail, Src, Size, Rest) i_get_map_elements f s I |