aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-03-26 13:16:45 +0100
committerBjörn Gustavsson <[email protected]>2015-04-13 12:37:54 +0200
commitc92cf260bb888c004fb02651670d19989dbc2b74 (patch)
tree1aea823e83a9696bcf9285742e73cd806cd98de1 /erts
parentfea64943212cd96764b595c91b22da68bc72e999 (diff)
downloadotp-c92cf260bb888c004fb02651670d19989dbc2b74.tar.gz
otp-c92cf260bb888c004fb02651670d19989dbc2b74.tar.bz2
otp-c92cf260bb888c004fb02651670d19989dbc2b74.zip
De-optimize the has_map_fields instructions
The has_map_fields instruction is infrequently used. Thus there is no need to have the fastest possible implementation; it is better to have an implementation that reduces the code size in the already big process_main() function. We can transform has_map_fields to a get_map_elements instruction, targeting the same unused x[0] register for all keys. That instruction will only be marginally slower than existing implementation.
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/beam_debug.c1
-rw-r--r--erts/emulator/beam/beam_emu.c96
-rw-r--r--erts/emulator/beam/beam_load.c20
-rw-r--r--erts/emulator/beam/ops.tab29
4 files changed, 19 insertions, 127 deletions
diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c
index 38e54e9d1a..0367ca8aba 100644
--- a/erts/emulator/beam/beam_debug.c
+++ b/erts/emulator/beam/beam_debug.c
@@ -664,7 +664,6 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
case op_new_map_dII:
case op_update_map_assoc_jsdII:
case op_update_map_exact_jsdII:
- case op_i_has_map_fields_fsI:
case op_i_get_map_elements_fsI:
{
int n = unpacked[-1];
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index a264669e50..f25b9f594d 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -701,8 +701,6 @@ void** beam_ops;
#define IsMap(Src, Fail) if (!is_map(Src)) { Fail; }
-#define HasMapField(Src, Key, Fail) if (has_not_map_field(Src, Key)) { Fail; }
-
#define GetMapElement(Src, Key, Dst, Fail) \
do { \
Eterm _res = get_map_element(Src, Key); \
@@ -960,7 +958,6 @@ static Eterm update_map_assoc(Process* p, Eterm* reg,
Eterm map, BeamInstr* I) NOINLINE;
static Eterm update_map_exact(Process* p, Eterm* reg,
Eterm map, BeamInstr* I) NOINLINE;
-static int has_not_map_field(Eterm map, Eterm key);
static Eterm get_map_element(Eterm map, Eterm key);
/*
@@ -2391,67 +2388,6 @@ void process_main(void)
Next(3+Arg(2));
}
- OpCase(i_has_map_fields_fsI): {
- flatmap_t* mp;
- Eterm map;
- Eterm field;
- Eterm *ks;
- BeamInstr* fs;
- Uint sz,n;
-
- GetArg1(1, map);
- n = (Uint)Arg(2);
- fs = &Arg(3); /* pattern fields */
-
- /* get term from field? */
- if (is_hashmap(map)) {
- Uint32 hx;
- while(n--) {
- field = *fs++;
- hx = hashmap_make_hash(field);
- if (!erts_hashmap_get(hx,field,map)) {
- SET_I((BeamInstr *) Arg(0));
- goto has_map_fields_fail;
- }
- }
- goto has_map_fields_ok;
- }
-
- ASSERT(is_flatmap(map));
-
- mp = (flatmap_t *)flatmap_val(map);
- sz = flatmap_get_size(mp);
-
- if (sz == 0) {
- SET_I((BeamInstr *) Arg(0));
- goto has_map_fields_fail;
- }
-
- ks = flatmap_get_keys(mp);
-
- ASSERT(n>0);
-
- while(sz) {
- field = (Eterm)*fs;
- if (EQ(field,*ks)) {
- n--;
- fs++;
- if (n == 0) break;
- }
- ks++; sz--;
- }
-
- if (n) {
- SET_I((BeamInstr *) Arg(0));
- goto has_map_fields_fail;
- }
-has_map_fields_ok:
- I += 4 + Arg(2);
-has_map_fields_fail:
- ASSERT(VALID_INSTR(*I));
- Goto(*I);
- }
-
#define PUT_TERM_REG(term, desc) \
do { \
switch ((desc) & _TAG_IMMED1_MASK) { \
@@ -6470,38 +6406,6 @@ new_fun(Process* p, Eterm* reg, ErlFunEntry* fe, int num_free)
return make_fun(funp);
}
-static int has_not_map_field(Eterm map, Eterm key)
-{
- Uint32 hx;
- if (is_flatmap(map)) {
- flatmap_t* mp;
- Eterm* keys;
- Uint i;
- Uint n;
-
- mp = (flatmap_t *)flatmap_val(map);
- keys = flatmap_get_keys(mp);
- n = flatmap_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;
- }
- }
- }
- 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)
{
Uint32 hx;
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 60f4ab5280..18e1e312ad 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -4107,21 +4107,31 @@ gen_get_map_element(LoaderState* stp, GenOpArg Fail, GenOpArg Src,
}
static GenOp*
-gen_has_map_field(LoaderState* stp, GenOpArg Fail, GenOpArg Src,
- GenOpArg Size, GenOpArg* Rest)
+gen_has_map_fields(LoaderState* stp, GenOpArg Fail, GenOpArg Src,
+ GenOpArg Size, GenOpArg* Rest)
{
GenOp* op;
+ Uint i;
+ Uint n;
ASSERT(Size.type == TAG_u);
+ n = Size.val;
NEW_GENOP(stp, op);
+ GENOP_ARITY(op, 3 + 2*n);
op->next = NULL;
- op->op = genop_has_map_field_3;
- op->arity = 4;
+ op->op = genop_get_map_elements_3;
op->a[0] = Fail;
op->a[1] = Src;
- op->a[2] = Rest[0];
+ op->a[2].type = TAG_u;
+ op->a[2].val = 2*n;
+
+ for (i = 0; i < n; i++) {
+ op->a[3+2*i] = Rest[i];
+ op->a[3+2*i+1].type = TAG_x;
+ op->a[3+2*i+1].val = 0; /* x(0); normally not used */
+ }
return op;
}
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index a5a89b3990..abaa47217a 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -1497,31 +1497,10 @@ is_map f r
is_map f x
is_map f y
-## Transform has_map_field(s) #{ K1 := _, K2 := _ }
-
-has_map_field/3
-
-has_map_fields Fail Src Size=u==1 Rest=* => gen_has_map_field(Fail,Src,Size,Rest)
-has_map_fields Fail Src Size Rest=* => i_has_map_fields Fail Src Size Rest
-
-i_has_map_fields f s I
-
-has_map_field Fail Src=rxy Key=arxy => i_has_map_field Fail Src Key
-has_map_field Fail Src Key => move Key x | i_has_map_field Fail Src x
-
-%macro: i_has_map_field HasMapField -fail_action
-i_has_map_field f r a
-i_has_map_field f x a
-i_has_map_field f y a
-i_has_map_field f r r
-i_has_map_field f x r
-i_has_map_field f y r
-i_has_map_field f r x
-i_has_map_field f x x
-i_has_map_field f y x
-i_has_map_field f r y
-i_has_map_field f x y
-i_has_map_field f y y
+## Transform has_map_fields #{ K1 := _, K2 := _ } to has_map_elements
+
+has_map_fields Fail Src Size Rest=* => \
+ gen_has_map_fields(Fail, Src, Size, Rest)
## Transform get_map_elements(s) #{ K1 := V1, K2 := V2 }