Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion erts/emulator/beam/beam_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,11 @@ static int parse_lambda_chunk(BeamFile *beam, IFF_Chunk *chunk) {
BeamFile_AtomTable *atoms;
BeamReader reader;
Sint32 count;
Uint label_count;
int i;

label_count = beam->code.label_count;

lambdas = &beam->lambdas;
ASSERT(lambdas->entries == NULL);

Expand All @@ -421,7 +424,7 @@ static int parse_lambda_chunk(BeamFile *beam, IFF_Chunk *chunk) {
LoadAssert(beamreader_read_i32(&reader, &old_uniq));

LoadAssert(atom_index >= 0 && atom_index < atoms->count);
LoadAssert(label >= 0);
LoadAssert(label > 0 && label < label_count);

lambdas->entries[i].function = atoms->entries[atom_index];
lambdas->entries[i].num_free = num_free;
Expand Down
8 changes: 5 additions & 3 deletions erts/emulator/beam/jit/arm/instr_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,8 @@ void BeamModuleAssembler::emit_put_list_deallocate(const ArgSource &Hd,

ASSERT(dealloc < MAX_REG * sizeof(Eterm));

if (Hd.isYRegister() && !Tl.isYRegister() && dealloc > 0) {
if (Hd.isYRegister() && !Tl.isYRegister() && dealloc > 0 &&
Support::is_int_n<9>(dealloc)) {
auto hd_index = Hd.as<ArgYRegister>().get();

if (hd_index == 0) {
Expand All @@ -741,7 +742,8 @@ void BeamModuleAssembler::emit_put_list_deallocate(const ArgSource &Hd,
tl_reg = load_source(Tl, TMP2).reg;
dealloc = 0;
}
} else if (!Hd.isYRegister() && Tl.isYRegister() && dealloc > 0) {
} else if (!Hd.isYRegister() && Tl.isYRegister() && dealloc > 0 &&
Support::is_int_n<9>(dealloc)) {
auto tl_index = Tl.as<ArgYRegister>().get();

if (tl_index == 0) {
Expand Down Expand Up @@ -2204,7 +2206,7 @@ void BeamModuleAssembler::emit_is_lt(const ArgLabel &Fail,
Label next = a.new_label();
comment("simplified test because it always succeeds when LHS is a "
"bignum");
emit_is_not_boxed(next, rhs.reg);
emit_is_not_boxed(next, lhs.reg);
a.cmp(lhs.reg, rhs.reg);
a.b_ge(resolve_beam_label(Fail, disp1MB));
a.bind(next);
Expand Down
2 changes: 1 addition & 1 deletion erts/emulator/beam/jit/arm/instr_guard_bifs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ void BeamModuleAssembler::emit_bif_and(const ArgLabel &Fail,
a.b_eq(next);
mov_var(XREG0, src1);
mov_var(XREG1, src2);
fragment_call(ga->get_handle_or_error());
fragment_call(ga->get_handle_and_error());
}

a.bind(next);
Expand Down
11 changes: 6 additions & 5 deletions erts/emulator/beam/jit/arm/instr_select.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,11 @@ void BeamModuleAssembler::emit_i_jump_on_val(const ArgSource &Src,

ASSERT(Size.get() == args.size());

if (Fail.isNil()) {
/* NIL means fallthrough to the next instruction. */
fail = a.new_label();
}

if (always_small(Src)) {
comment("(skipped type test)");
} else {
Expand All @@ -465,10 +470,6 @@ void BeamModuleAssembler::emit_i_jump_on_val(const ArgSource &Src,
if (Fail.isLabel()) {
a.b_ne(resolve_beam_label(Fail, disp1MB));
} else {
/* NIL means fallthrough to the next instruction. */
ASSERT(Fail.isNil());

fail = a.new_label();
a.b_ne(fail);
}
}
Expand Down Expand Up @@ -511,7 +512,7 @@ void BeamModuleAssembler::emit_i_jump_on_val(const ArgSource &Src,
}
}

if (Fail.getType() == ArgVal::Type::Immediate) {
if (Fail.isNil()) {
a.bind(fail);
}
}
Expand Down
2 changes: 1 addition & 1 deletion erts/emulator/beam/jit/beam_jit_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ void *BeamModuleAssembler::register_metadata(const BeamCodeHeader *header) {
}

n = erts_snprintf(name_buffer,
1024,
sizeof(name_buffer),
"%T:%T/%d",
ci->mfa.module,
ci->mfa.function,
Expand Down
30 changes: 28 additions & 2 deletions erts/emulator/test/beam_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
heap_sizes/1, big_lists/1, fconv/1,
select_val/1, select_tuple_arity/1,
swap_temp_apply/1, beam_init_yregs/1,
beam_register_cache/1]).
beam_register_cache/1, put_list_dealloc/1]).

-export([applied/2,swap_temp_applied/1]).

Expand All @@ -42,7 +42,7 @@ all() ->
heap_sizes, big_lists, fconv,
select_val, select_tuple_arity,
swap_temp_apply, beam_init_yregs,
beam_register_cache].
beam_register_cache, put_list_dealloc].

groups() ->
[].
Expand Down Expand Up @@ -529,6 +529,32 @@ beam_register_cache(Config) ->

ok.

put_list_dealloc(_Config) ->
Seq = lists:seq(1, 32),
RevSeq = lists:reverse(Seq),
RevSeq = do_put_list_dealloc(head, Seq),

HdRevSeq = hd(RevSeq),
TlRevSeq = tl(RevSeq),
[TlRevSeq|HdRevSeq] = do_put_list_dealloc(tail, Seq),

ok.

do_put_list_dealloc(Where, List0) ->
[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,
Å,Ä,Ö,AA,AE,OE] = List0,
put(force_vars_to_stack, true),
List = [AE,AA,Ö,Ä,Å,Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,
I,H,G,F,E,D,C,B,A],
%% put_list and dealloc would be combined into put_list_dealloc
%% with deallocation being done as post-increment in the ldr
%% instruction loading y0. With 32 or more Y registers, the
%% post-increment offset would exceed its upper limit.
case Where of
head -> [OE|List];
tail -> [List|OE]
end.

%%% Common utilities.
spawn_exec(F) ->
{Pid,Ref} = spawn_monitor(fun() ->
Expand Down
175 changes: 164 additions & 11 deletions erts/emulator/test/op_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ t_not(Config) when is_list(Config) ->
run_test_module(Cases, false),
{comment,integer_to_list(length(Cases)) ++ " cases"}.

%% Test that simlpe relations between relation operators hold.
%% Test that simple relations between relation operators hold.
relop_simple(Config) when is_list(Config) ->
Big1 = 19738924729729787487784874,
Big2 = 38374938373887374983978484,
Expand Down Expand Up @@ -170,19 +170,33 @@ relop_simple_do(V1,V2) ->
%%io:format("compare ~p\n and ~p\n",[V1,V2]),

L = V1 < V2,
L = not (V1 >= V2),
L = not id(V1 >= V2),
L = V2 > V1,
L = not (V2 =< V1),

G = V1 > V2,
G = not (V1 =< V2),
G = V2 < V1,
G = not (V2 >= V1),
L = not id(V2 =< V1),

LE = V1 =< V2,
LE = not id(V1 > V2),
LE = V2 >= V1,
LE = not id(V2 < V1),

G = id(if
V1 > V2 -> id(true);
true -> false
end),
G = id(V1 > V2),
G = not id(V1 =< V2),
G = id(V2 < V1),
G = not id(V2 >= V1),

GE = id(V1 >= V2),
GE = not id(V1 < V2),
GE = id(V2 =< V1),
GE = not id(V2 > V1),

ID = V1 =:= V2,
ID = V2 =:= V1,
ID = not (V1 =/= V2),
ID = not (V2 =/= V1),
ID = not id(V1 =/= V2),
ID = not id(V2 =/= V1),

implies(ID, V1 == V2),

Expand All @@ -196,7 +210,146 @@ relop_simple_do(V1,V2) ->
{false, true, false, false, 0} -> ok;
{false, true, true, false, 0} -> ok;
{false, false, false, true, +1} -> ok
end.
end,

LE = L orelse EQ,
GE = G orelse EQ,

relop_simple_do1(id(V1), id(V2)).

relop_simple_do1(V1, V2) ->
if
is_integer(V1), -1 bsl 56 =< V1, V1 =< 1 bsl 56,
is_integer(V2), V2 < 1 bsl 56 ->
L = id(if
V1 < V2 -> id(true);
true -> false
end),
L = id(V1 < V2),
L = not id(V1 >= V2),
L = id(V2 > V1),
L = not id(V2 =< V1),

LE = id(if
V1 =< V2 -> id(true);
true -> false
end),
LE = id(V1 =< V2),
LE = not id(V1 > V2),
LE = id(V2 >= V1),
LE = not id(V2 < V1),

G = id(if
V1 > V2 -> id(true);
true -> false
end),
G = id(V1 > V2),
G = not id(V1 =< V2),
G = id(V2 < V1),
G = not id(V2 >= V1),

GE = id(if
V1 >= V2 -> id(true);
true -> false
end),
GE = id(V1 >= V2),
GE = not id(V1 < V2),
GE = id(V2 =< V1),
GE = not id(V2 > V1),

ok;
true ->
ok
end,
relop_simple_do2(id(V1), id(V2)).

relop_simple_do2(V1, V2) ->
if
is_integer(V1), -1 bsl 56 =< V1, V1 =< 1 bsl 56,
is_integer(V2), V2 > 1 bsl 50 ->
L = id(if
V1 < V2 -> id(true);
true -> false
end),
L = id(V1 < V2),
L = not id(V1 >= V2),
L = id(V2 > V1),
L = not id(V2 =< V1),

LE = id(if
V1 =< V2 -> id(true);
true -> false
end),
LE = id(V1 =< V2),
LE = not id(V1 > V2),
LE = id(V2 >= V1),
LE = not id(V2 < V1),

G = id(V1 > V2),
G = not id(V1 =< V2),
G = id(V2 < V1),
G = not id(V2 >= V1),

GE = id(if
V1 >= V2 -> id(true);
true -> false
end),
GE = id(V1 >= V2),
GE = not id(V1 < V2),
GE = id(V2 =< V1),
GE = not id(V2 > V1),

ok;
true ->
ok
end,
relop_simple_do3(id(V1), id(V2)).

relop_simple_do3(V1, V2) ->
if
is_integer(V1),
is_integer(V2), -1 bsl 56 =< V2, V2 =< 1 bsl 56 ->
L = id(if
V1 < V2 -> id(true);
true -> false
end),
L = id(V1 < V2),
L = not id(V1 >= V2),
L = id(V2 > V1),
L = not id(V2 =< V1),

LE = id(if
V1 =< V2 -> id(true);
true -> false
end),
LE = id(V1 =< V2),
LE = not id(V1 > V2),
LE = id(V2 >= V1),
LE = not id(V2 < V1),

G = id(if
V1 > V2 -> id(true);
true -> false
end),
G = V1 > V2,
G = not id(V1 =< V2),
G = V2 < V1,
G = not id(V2 >= V1),

GE = id(if
V1 >= V2 -> id(true);
true -> false
end),
GE = id(V1 >= V2),
GE = not id(V1 < V2),
GE = id(V2 =< V1),
GE = not id(V2 > V1),

ok;
true ->
ok
end,
ok.

implies(false, _) -> ok;
implies(true, true) -> ok.
Expand Down
Loading