aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-03-25 13:10:30 +0100
committerBjörn Gustavsson <[email protected]>2015-04-13 12:37:55 +0200
commit9b940b12210500e615ea05b447b0e1be34e70d39 (patch)
tree2592ce44da307877a30d2ff0ea2e13c368aa83b8 /erts/emulator/beam
parent5f1e301dfec48fccbf865a8b54af5908bebb77c4 (diff)
downloadotp-9b940b12210500e615ea05b447b0e1be34e70d39.tar.gz
otp-9b940b12210500e615ea05b447b0e1be34e70d39.tar.bz2
otp-9b940b12210500e615ea05b447b0e1be34e70d39.zip
Pre-compute hash values for the general get_map_elements instruction
See the previous commit for justification and use cases.
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/beam_emu.c14
-rw-r--r--erts/emulator/beam/beam_load.c41
-rw-r--r--erts/emulator/beam/ops.tab2
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