aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/beam/beam_debug.c8
-rw-r--r--erts/emulator/beam/beam_emu.c26
-rw-r--r--erts/emulator/beam/beam_load.c33
-rw-r--r--erts/emulator/beam/ops.tab20
-rw-r--r--erts/emulator/test/beam_literals_SUITE.erl7
-rw-r--r--erts/emulator/test/beam_literals_SUITE_data/literal_case_expression.S80
6 files changed, 147 insertions, 27 deletions
diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c
index 6c16c24d0d..46b831fa88 100644
--- a/erts/emulator/beam/beam_debug.c
+++ b/erts/emulator/beam/beam_debug.c
@@ -555,7 +555,9 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
unpacked = ap;
ap = addr + size;
switch (op) {
- case op_i_select_val_sfI:
+ case op_i_select_val_rfI:
+ case op_i_select_val_xfI:
+ case op_i_select_val_yfI:
{
int n = ap[-1];
@@ -567,7 +569,9 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
}
}
break;
- case op_i_select_tuple_arity_sfI:
+ case op_i_select_tuple_arity_rfI:
+ case op_i_select_tuple_arity_xfI:
+ case op_i_select_tuple_arity_yfI:
{
int n = ap[-1];
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 09f6fc8cef..6cd7fa78e0 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -1865,9 +1865,19 @@ void process_main(void)
{
Eterm select_val;
- OpCase(i_select_tuple_arity_sfI):
- GetArg1(0, select_val);
+ OpCase(i_select_tuple_arity_xfI):
+ select_val = xb(Arg(0));
+ goto do_select_tuple_arity;
+ OpCase(i_select_tuple_arity_yfI):
+ select_val = yb(Arg(0));
+ goto do_select_tuple_arity;
+
+ OpCase(i_select_tuple_arity_rfI):
+ select_val = r(0);
+ I--;
+
+ do_select_tuple_arity:
if (is_tuple(select_val)) {
select_val = *tuple_val(select_val);
goto do_binary_search;
@@ -1875,9 +1885,17 @@ void process_main(void)
SET_I((BeamInstr *) Arg(1));
Goto(*I);
+ OpCase(i_select_val_xfI):
+ select_val = xb(Arg(0));
+ goto do_binary_search;
- OpCase(i_select_val_sfI):
- GetArg1(0, select_val);
+ OpCase(i_select_val_yfI):
+ select_val = yb(Arg(0));
+ goto do_binary_search;
+
+ OpCase(i_select_val_rfI):
+ select_val = r(0);
+ I--;
do_binary_search:
{
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 73f057929e..54c8ad0eb1 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -3282,7 +3282,6 @@ const_select_val(LoaderState* stp, GenOpArg S, GenOpArg Fail,
int i;
ASSERT(Size.type == TAG_u);
- ASSERT(S.type == TAG_q);
NEW_GENOP(stp, op);
op->next = NULL;
@@ -3293,18 +3292,32 @@ const_select_val(LoaderState* stp, GenOpArg S, GenOpArg Fail,
* Search for a literal matching the controlling expression.
*/
- if (S.type == TAG_q) {
- Eterm expr = stp->literals[S.val].term;
- for (i = 0; i < Size.val; i += 2) {
- if (Rest[i].type == TAG_q) {
- Eterm term = stp->literals[Rest[i].val].term;
- if (eq(term, expr)) {
- ASSERT(Rest[i+1].type == TAG_f);
- op->a[0] = Rest[i+1];
- return op;
+ switch (S.type) {
+ case TAG_q:
+ {
+ Eterm expr = stp->literals[S.val].term;
+ for (i = 0; i < Size.val; i += 2) {
+ if (Rest[i].type == TAG_q) {
+ Eterm term = stp->literals[Rest[i].val].term;
+ if (eq(term, expr)) {
+ ASSERT(Rest[i+1].type == TAG_f);
+ op->a[0] = Rest[i+1];
+ return op;
+ }
}
}
}
+ break;
+ case TAG_i:
+ case TAG_a:
+ for (i = 0; i < Size.val; i += 2) {
+ if (Rest[i].val == S.val && Rest[i].type == S.type) {
+ ASSERT(Rest[i+1].type == TAG_f);
+ op->a[0] = Rest[i+1];
+ return op;
+ }
+ }
+ break;
}
/*
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index f629cc80b6..45b2e197b4 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -124,7 +124,7 @@ init Y1 | init Y2 => init2 Y1 Y2
# Selecting values
-select_val S=q Fail=f Size=u Rest=* => const_select_val(S, Fail, Size, Rest)
+select_val S=aiq Fail=f Size=u Rest=* => const_select_val(S, Fail, Size, Rest)
select_val S=s Fail=f Size=u Rest=* | use_jump_tab(Size, Rest) => \
gen_jump_tab(S, Fail, Size, Rest)
@@ -139,26 +139,30 @@ is_integer TypeFail=f S | select_val S=s Fail=f Size=u Rest=* | \
select_val S=s Fail=f Size=u Rest=* | mixed_types(Size, Rest) => \
gen_split_values(S, Fail, Fail, Size, Rest)
-is_integer Fail=f S | select_val S=s Fail=f Size=u Rest=* | \
+is_integer Fail=f S | select_val S=d Fail=f Size=u Rest=* | \
fixed_size_values(Size, Rest) => gen_select_val(S, Fail, Size, Rest)
-is_atom Fail=f S | select_val S=s Fail=f Size=u Rest=* | \
+is_atom Fail=f S | select_val S=d Fail=f Size=u Rest=* | \
fixed_size_values(Size, Rest) => gen_select_val(S, Fail, Size, Rest)
select_val S=s Fail=f Size=u Rest=* | floats_or_bignums(Size, Rest) => \
gen_select_literals(S, Fail, Size, Rest)
-select_val S=s Fail=f Size=u Rest=* | fixed_size_values(Size, Rest) => \
+select_val S=d Fail=f Size=u Rest=* | fixed_size_values(Size, Rest) => \
gen_select_val(S, Fail, Size, Rest)
-is_tuple Fail=f S | select_tuple_arity S=s Fail=f Size=u Rest=* => \
+is_tuple Fail=f S | select_tuple_arity S=d Fail=f Size=u Rest=* => \
gen_select_tuple_arity(S, Fail, Size, Rest)
-select_tuple_arity S=s Fail=f Size=u Rest=* => \
+select_tuple_arity S=d Fail=f Size=u Rest=* => \
gen_select_tuple_arity(S, Fail, Size, Rest)
-i_select_val s f I
-i_select_tuple_arity s f I
+i_select_val r f I
+i_select_val x f I
+i_select_val y f I
+i_select_tuple_arity r f I
+i_select_tuple_arity x f I
+i_select_tuple_arity y f I
i_jump_on_val_zero s f I
i_jump_on_val s f I I
diff --git a/erts/emulator/test/beam_literals_SUITE.erl b/erts/emulator/test/beam_literals_SUITE.erl
index 2238e89748..f56d7ac1c5 100644
--- a/erts/emulator/test/beam_literals_SUITE.erl
+++ b/erts/emulator/test/beam_literals_SUITE.erl
@@ -406,10 +406,15 @@ fconv_2(F) when is_float(F) ->
literal_case_expression(Config) when is_list(Config) ->
?line DataDir = ?config(data_dir, Config),
?line Src = filename:join(DataDir, "literal_case_expression"),
- ?line {ok,literal_case_expression=Mod,Code} = compile:file(Src, [from_asm,binary]),
+ ?line {ok,literal_case_expression=Mod,Code} =
+ compile:file(Src, [from_asm,binary]),
?line {module,Mod} = code:load_binary(Mod, Src, Code),
?line ok = Mod:x(),
?line ok = Mod:y(),
+ ?line ok = Mod:zi1(),
+ ?line ok = Mod:zi2(),
+ ?line ok = Mod:za1(),
+ ?line ok = Mod:za2(),
?line true = code:delete(Mod),
?line code:purge(Mod),
ok.
diff --git a/erts/emulator/test/beam_literals_SUITE_data/literal_case_expression.S b/erts/emulator/test/beam_literals_SUITE_data/literal_case_expression.S
index c0ffe9ab53..bfdfc079dc 100644
--- a/erts/emulator/test/beam_literals_SUITE_data/literal_case_expression.S
+++ b/erts/emulator/test/beam_literals_SUITE_data/literal_case_expression.S
@@ -1,10 +1,11 @@
{module, literal_case_expression}. %% version = 0
-{exports, [{module_info,0},{module_info,1},{x,0},{y,0}]}.
+{exports, [{module_info,0},{module_info,1},{x,0},{y,0},
+ {zi1,0},{zi2,0},{za1,0},{za2,0}]}.
{attributes, []}.
-{labels, 15}.
+{labels, 32}.
{function, x, 0, 2}.
@@ -52,6 +53,81 @@
{label,10}.
{case_end,{float,34.0000}}.
+{function, zi1, 0, 16}.
+ {label,15}.
+ {func_info,{atom,literal_case_expression},{atom,zi1},0}.
+ {label,16}.
+ {test,is_integer,{f,19},[{integer,42}]}.
+ {select_val,{integer,42},
+ {f,18},
+ {list,[{integer,42},
+ {f,17},
+ {integer,1000},
+ {f,18}]}}.
+ {label,17}.
+ {move,{atom,ok},{x,0}}.
+ return.
+ {label,18}.
+ {move,{atom,error},{x,0}}.
+ return.
+ {label,19}.
+ {case_end,{integer,42}}.
+
+{function, zi2, 0, 16}.
+ {label,20}.
+ {func_info,{atom,literal_case_expression},{atom,zi2},0}.
+ {label,21}.
+ {test,is_integer,{f,23},[{integer,42}]}.
+ {select_val,{integer,42},
+ {f,23},
+ {list,[{integer,42},
+ {f,22},
+ {integer,1000},
+ {f,23}]}}.
+ {label,22}.
+ {move,{atom,ok},{x,0}}.
+ return.
+ {label,23}.
+ {move,{atom,error},{x,0}}.
+ return.
+
+{function, za1, 0, 25}.
+ {label,24}.
+ {func_info,{atom,literal_case_expression},{atom,za1},0}.
+ {label,25}.
+ {test,is_atom,{f,28},[{atom,x}]}.
+ {select_val,{atom,x},
+ {f,27},
+ {list,[{atom,a},
+ {f,27},
+ {atom,x},
+ {f,26}]}}.
+ {label,26}.
+ {move,{atom,ok},{x,0}}.
+ return.
+ {label,27}.
+ {move,{atom,error},{x,0}}.
+ return.
+ {label,28}.
+ {case_end,{atom,x}}.
+
+{function, za2, 0, 30}.
+ {label,29}.
+ {func_info,{atom,literal_case_expression},{atom,za2},0}.
+ {label,30}.
+ {test,is_atom,{f,32},[{atom,x}]}.
+ {select_val,{atom,x},
+ {f,32},
+ {list,[{atom,a},
+ {f,32},
+ {atom,x},
+ {f,31}]}}.
+ {label,31}.
+ {move,{atom,ok},{x,0}}.
+ return.
+ {label,32}.
+ {move,{atom,error},{x,0}}.
+ return.
{function, module_info, 0, 12}.
{label,11}.