From 6d66e21dd6b1b891f917e86902edaea3ed86a6eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 May 2016 13:15:04 +0200 Subject: test_lib: Correct calculation of number of processes Correct calculation of the number of parallel processes to use when cover is used. It was supposed not to exceed 4 (according to the comment), but it was calculated as the number of schedulers. On my computer, having 8 schedulers, this change made the compiler test suite with cover run almost twice as fast. --- lib/compiler/test/test_lib.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl index d141d86021..a9236df414 100644 --- a/lib/compiler/test/test_lib.erl +++ b/lib/compiler/test/test_lib.erl @@ -106,8 +106,9 @@ p_run(Test, List) -> %% slightly faster than using 3. Using more than %% 4 would not buy us much and could actually be %% slower. - max(S, 4) + min(S, 4) end, + io:format("p_run: ~p parallel processes\n", [N]), p_run_loop(Test, List, N, [], 0, 0). p_run_loop(_, [], _, [], Errors, Ws) -> -- cgit v1.2.3 From 747e9cebee47272704342895bc57cf5edd83b550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 May 2016 12:29:41 +0200 Subject: trycatch_SUITE: Cover the only uncovered line in sys_core_fold Recent spring cleaning in the test suite left a line in sys_core_fold dealing with an unnecessary catch uncovered. --- lib/compiler/test/trycatch_SUITE.erl | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl index f7ad78cb8d..a591d6cc93 100644 --- a/lib/compiler/test/trycatch_SUITE.erl +++ b/lib/compiler/test/trycatch_SUITE.erl @@ -1034,6 +1034,9 @@ grab_bag(_Config) -> end end, + %% Unnecessary catch. + 22 = (catch 22), + ok. -- cgit v1.2.3 From 0e78d96d9a4a46316ba3be0f4bd17ea4eafb597a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 12 May 2016 09:58:36 +0200 Subject: test_lib: Add is_cloned_mod/1 Add is_cloned_mod(Mod) to determine whether Mod is the original name for a module (e.g. record_SUITE) or a cloned module (e.g. record_no_opt_SUITE). --- lib/compiler/test/test_lib.erl | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl index a9236df414..d5b79e2357 100644 --- a/lib/compiler/test/test_lib.erl +++ b/lib/compiler/test/test_lib.erl @@ -22,7 +22,7 @@ -include_lib("common_test/include/ct.hrl"). -compile({no_auto_import,[binary_part/2]}). -export([id/1,recompile/1,parallel/0,uniq/0,opt_opts/1,get_data_dir/1, - smoke_disasm/1,p_run/2,binary_part/2]). + is_cloned_mod/1,smoke_disasm/1,p_run/2,binary_part/2]). id(I) -> I. @@ -91,6 +91,17 @@ get_data_dir(Config) -> Data = re:replace(Data1, "_post_opt_SUITE", "_SUITE", Opts), re:replace(Data, "_inline_SUITE", "_SUITE", Opts). +is_cloned_mod(Mod) -> + is_cloned_mod_1(atom_to_list(Mod)). + +%% Test whether Mod is a cloned module. + +is_cloned_mod_1("no_opt_SUITE") -> true; +is_cloned_mod_1("post_opt_SUITE") -> true; +is_cloned_mod_1("inline_SUITE") -> true; +is_cloned_mod_1([_|T]) -> is_cloned_mod_1(T); +is_cloned_mod_1([]) -> false. + %% p_run(fun(Data) -> ok|error, List) -> ok %% Will fail the test case if there were any errors. -- cgit v1.2.3 From a1493984f80b42c9bff13ea13e6bbae8db0830c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 12 May 2016 10:30:30 +0200 Subject: compile_SUITE: Eliminate clones when re-compiling test suites Several test cases in compile_SUITE (e.g. core/1) extracts the abstract code from a BEAM file and runs the compiler on it. It is only a waste of time to use the abstract code from cloned versions of test case modules. That is, use record_SUITE, but don't use record_no_opt_SUITE, record_post_opt_SUITE, or record_inline_SUITE since they all contain essentially the same abstract code. --- lib/compiler/test/compile_SUITE.erl | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index e634f0fcc2..45b9a5a389 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -693,8 +693,7 @@ core(Config) when is_list(Config) -> Outdir = filename:join(PrivDir, "core"), ok = file:make_dir(Outdir), - Wc = filename:join(filename:dirname(code:which(?MODULE)), "*.beam"), - TestBeams = filelib:wildcard(Wc), + TestBeams = get_unique_beam_files(), Abstr = [begin {ok,{Mod,[{abstract_code, {raw_abstract_v1,Abstr}}]}} = beam_lib:chunks(Beam, [abstract_code]), @@ -755,8 +754,7 @@ core_roundtrip(Config) -> Outdir = filename:join(PrivDir, atom_to_list(?FUNCTION_NAME)), ok = file:make_dir(Outdir), - Wc = filename:join(filename:dirname(code:which(?MODULE)), "*.beam"), - TestBeams = filelib:wildcard(Wc), + TestBeams = get_unique_beam_files(), test_lib:p_run(fun(F) -> do_core_roundtrip(F, Outdir) end, TestBeams). do_core_roundtrip(Beam, Outdir) -> @@ -870,8 +868,7 @@ asm(Config) when is_list(Config) -> Outdir = filename:join(PrivDir, "asm"), ok = file:make_dir(Outdir), - Wc = filename:join(filename:dirname(code:which(?MODULE)), "*.beam"), - TestBeams = filelib:wildcard(Wc), + TestBeams = get_unique_beam_files(), Res = test_lib:p_run(fun(F) -> do_asm(F, Outdir) end, TestBeams), Res. @@ -947,8 +944,7 @@ dialyzer(Config) -> %% Test that warnings contain filenames and line numbers. warnings(_Config) -> - TestDir = filename:dirname(code:which(?MODULE)), - Files = filelib:wildcard(filename:join(TestDir, "*.erl")), + Files = get_unique_files(".erl"), test_lib:p_run(fun do_warnings/1, Files). do_warnings(F) -> @@ -1102,3 +1098,14 @@ compile_and_verify(Name, Target, Opts) -> beam_lib:chunks(Target, [compile_info]), {options,BeamOpts} = lists:keyfind(options, 1, CInfo), Opts = BeamOpts. + +get_unique_beam_files() -> + get_unique_files(".beam"). + +get_unique_files(Ext) -> + Wc = filename:join(filename:dirname(code:which(?MODULE)), "*"++Ext), + [F || F <- filelib:wildcard(Wc), not is_cloned(F, Ext)]. + +is_cloned(File, Ext) -> + Mod = list_to_atom(filename:basename(File, Ext)), + test_lib:is_cloned_mod(Mod). -- cgit v1.2.3 From 0bfa13f404c2c9155d9f948f9c3ef7b1fb247ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 12 May 2016 10:36:37 +0200 Subject: compile_SUITE: Cover numeric variable names in core_pp The inliner generates variable whose names are numeric. Run the inliner to cover one more line in core_pp. --- lib/compiler/test/compile_SUITE.erl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index 45b9a5a389..a15efc2a00 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -779,8 +779,13 @@ do_core_roundtrip_1(Mod, Abstr, Outdir) -> %% Primarily, test that annotations are accepted for all %% constructs. Secondarily, smoke test cerl_trees:label/1. - {Core,_} = cerl_trees:label(Core0), - do_core_roundtrip_2(Mod, Core, Outdir). + {Core1,_} = cerl_trees:label(Core0), + do_core_roundtrip_2(Mod, Core1, Outdir), + + %% Run the inliner to force generation of variables + %% with numeric names. + {ok,Mod,Core2} = compile:forms(Abstr, [inline,to_core]), + do_core_roundtrip_2(Mod, Core2, Outdir). do_core_roundtrip_2(M, Core0, Outdir) -> CoreFile = filename:join(Outdir, atom_to_list(M)++".core"), -- cgit v1.2.3 From 372702b3ec641ce133d05395c69c6d87f6be7519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 12 May 2016 06:38:51 +0200 Subject: core_pp: Simplify printing of map literals Map patterns are never represented as literals. Therefore, a map literal should always be printed with the 'assoc' operator. That also means that there is no remaining use of the 'class' field and that it can be removed from the 'ctxt' record. --- lib/compiler/src/core_pp.erl | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/core_pp.erl b/lib/compiler/src/core_pp.erl index f34a5c034f..a1501400ae 100644 --- a/lib/compiler/src/core_pp.erl +++ b/lib/compiler/src/core_pp.erl @@ -33,8 +33,7 @@ %% Prettyprint-formats (naively) an abstract Core Erlang syntax %% tree. --record(ctxt, {class = term :: 'clause' | 'def' | 'expr' | 'term', - indent = 0 :: integer(), +-record(ctxt, {indent = 0 :: integer(), item_indent = 2 :: integer(), body_indent = 4 :: integer(), line = 0 :: integer(), @@ -132,14 +131,11 @@ format_1(#c_literal{anno=A,val=Bitstring}, Ctxt) when is_bitstring(Bitstring) -> format_1(#c_binary{anno=A,segments=Segs}, Ctxt); format_1(#c_literal{anno=A,val=M},Ctxt) when is_map(M) -> Pairs = maps:to_list(M), - Op = case Ctxt of - #ctxt{ class = clause } -> exact; - _ -> assoc - end, - Cpairs = [#c_map_pair{op=#c_literal{val=Op}, + Op = #c_literal{val=assoc}, + Cpairs = [#c_map_pair{op=Op, key=#c_literal{val=K}, val=#c_literal{val=V}} || {K,V} <- Pairs], - format_1(#c_map{anno=A,arg=#c_literal{val=#{}},es=Cpairs},Ctxt); + format_1(#c_map{anno=A,arg=#c_literal{val=#{}},es=Cpairs},Ctxt); format_1(#c_var{name={I,A}}, _) -> [core_atom(I),$/,integer_to_list(A)]; format_1(#c_var{name=V}, _) -> @@ -340,14 +336,14 @@ format_1(#c_module{name=N,exports=Es,attrs=As,defs=Ds}, Ctxt) -> [Mod," [", format_vseq(Es, "", ",", - add_indent(set_class(Ctxt, term), width(Mod, Ctxt)+2), + add_indent(Ctxt, width(Mod, Ctxt)+2), fun format/2), "]", nl_indent(Ctxt), " attributes [", format_vseq(As, "", ",", - add_indent(set_class(Ctxt, def), 16), + add_indent(Ctxt, 16), fun format_def/2), "]", nl_indent(Ctxt), @@ -364,11 +360,11 @@ format_1(Type, _) -> format_funcs(Fs, Ctxt) -> format_vseq(Fs, "", "", - set_class(Ctxt, def), + Ctxt, fun format_def/2). format_def({N,V}, Ctxt0) -> - Ctxt1 = add_indent(set_class(Ctxt0, expr), Ctxt0#ctxt.body_indent), + Ctxt1 = add_indent(Ctxt0, Ctxt0#ctxt.body_indent), [format(N, Ctxt0), " =", nl_indent(Ctxt1) @@ -392,8 +388,7 @@ do_format_bitstr(#c_bitstr{val=V,size=S,unit=U,type=T,flags=Fs}, Ctxt0) -> ["#<", Val, ">(", format_hseq(Vs,",", Ctxt2, fun format/2), $)]. format_clauses(Cs, Ctxt) -> - format_vseq(Cs, "", "", set_class(Ctxt, clause), - fun format_clause/2). + format_vseq(Cs, "", "", Ctxt, fun format_clause/2). format_clause(Node, Ctxt) -> maybe_anno(Node, fun format_clause_1/2, Ctxt). @@ -405,15 +400,13 @@ format_clause_1(#c_clause{pats=Ps,guard=G,body=B}, Ctxt) -> case is_trivial_guard(G) of true -> [" when ", - format_guard(G, add_indent(set_class(Ctxt, expr), - width(Ptxt, Ctxt) + 6))]; + format_guard(G, add_indent(Ctxt, width(Ptxt, Ctxt) + 6))]; false -> [nl_indent(Ctxt2), "when ", - format_guard(G, add_indent(set_class(Ctxt2, expr), 2))] + format_guard(G, add_indent(Ctxt2, 2))] end++ " ->", - nl_indent(Ctxt2) - | format(B, set_class(Ctxt2, expr)) + nl_indent(Ctxt2) | format(B, Ctxt2) ]. is_trivial_guard(#c_literal{val=Val}) when is_atom(Val) -> true; @@ -467,7 +460,7 @@ format_list_tail(Tail, Ctxt) -> format_map_pair(Op, K, V, Ctxt0) -> Ctxt1 = add_indent(Ctxt0, 1), - Txt = format(K, set_class(Ctxt1, expr)), + Txt = format(K, Ctxt1), Ctxt2 = add_indent(Ctxt0, width(Txt, Ctxt1)), [Txt,Op,format(V, Ctxt2)]. @@ -533,9 +526,6 @@ width([], A, _, []) -> A. add_indent(Ctxt, Dx) -> Ctxt#ctxt{indent = Ctxt#ctxt.indent + Dx}. -set_class(Ctxt, Class) -> - Ctxt#ctxt{class = Class}. - core_atom(A) -> io_lib:write_string(atom_to_list(A), $'). -- cgit v1.2.3 From 5f2b8912d234c834b6f8c24ab38cf02dd52fc31b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 12 May 2016 12:12:48 +0200 Subject: core_pp: Remove useless try...catch We will get more information if we don't catch the exception. --- lib/compiler/src/core_pp.erl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/core_pp.erl b/lib/compiler/src/core_pp.erl index a1501400ae..b2bb1ecd32 100644 --- a/lib/compiler/src/core_pp.erl +++ b/lib/compiler/src/core_pp.erl @@ -507,9 +507,7 @@ unindent([], _, []) -> []. width(Txt, Ctxt) -> - try width(Txt, 0, Ctxt, []) - catch error:_ -> exit({bad_text,Txt}) - end. + width(Txt, 0, Ctxt, []). width([$\t|T], A, Ctxt, C) -> width(T, A + ?TAB_WIDTH, Ctxt, C); -- cgit v1.2.3 From 8bc4519e7337904354029580684f3c173b65fb5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 12 May 2016 12:14:33 +0200 Subject: core_pp: Remove unused clauses in unindent/3 to improve coverage --- lib/compiler/src/core_pp.erl | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/core_pp.erl b/lib/compiler/src/core_pp.erl index b2bb1ecd32..623722df94 100644 --- a/lib/compiler/src/core_pp.erl +++ b/lib/compiler/src/core_pp.erl @@ -483,6 +483,7 @@ spaces(5) -> " "; spaces(6) -> " "; spaces(7) -> " ". +%% Undo indentation done by nl_indent/1. unindent(T, Ctxt) -> unindent(T, Ctxt#ctxt.indent, []). @@ -498,12 +499,7 @@ unindent([$\t|T], N, C) -> unindent([spaces(Tab - N)|T], 0, C) end; unindent([L|T], N, C) when is_list(L) -> - unindent(L, N, [T|C]); -unindent([H|T], _, C) -> - [H|[T|C]]; -unindent([], N, [H|T]) -> - unindent(H, N, T); -unindent([], _, []) -> []. + unindent(L, N, [T|C]). width(Txt, Ctxt) -> -- cgit v1.2.3 From 3a8638e89e90dd2cfd311e3b98541ca3d6ac2b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 12 May 2016 12:17:27 +0200 Subject: core_pp: Crash on unhandled Core Erlang forms Don't try to be nice. Since we now have good test suites for Core Erlang, just let it crash. --- lib/compiler/src/core_pp.erl | 5 ----- 1 file changed, 5 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/core_pp.erl b/lib/compiler/src/core_pp.erl index 623722df94..22171a70c7 100644 --- a/lib/compiler/src/core_pp.erl +++ b/lib/compiler/src/core_pp.erl @@ -350,11 +350,6 @@ format_1(#c_module{name=N,exports=Es,attrs=As,defs=Ds}, Ctxt) -> format_funcs(Ds, Ctxt), nl_indent(Ctxt) | "end" - ]; -format_1(Type, _) -> - ["** Unsupported type: ", - io_lib:write(Type) - | " **" ]. format_funcs(Fs, Ctxt) -> -- cgit v1.2.3 From 467c4e5d198e0c4b9262c8e150a572050071ad41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 12 May 2016 15:53:36 +0200 Subject: core_pp: Remove uncovered clause in is_simple_term/1 The clause for handling #c_values{} in is_simple_term/1 is never executed. It can be safely removed, since there is a default clause that will return 'false' in the extremly unlikely event that a Without the clause, code such as: let <_v1,_v2> = <1,2> in {_v1,_v2} would be printed with an extra newline: let <_v1,_v2> = <1,2> in {_v1,_v2} --- lib/compiler/src/core_pp.erl | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/core_pp.erl b/lib/compiler/src/core_pp.erl index 22171a70c7..67209d06be 100644 --- a/lib/compiler/src/core_pp.erl +++ b/lib/compiler/src/core_pp.erl @@ -518,8 +518,6 @@ add_indent(Ctxt, Dx) -> core_atom(A) -> io_lib:write_string(atom_to_list(A), $'). -is_simple_term(#c_values{es=Es}) -> - length(Es) < 3 andalso lists:all(fun is_simple_term/1, Es); is_simple_term(#c_tuple{es=Es}) -> length(Es) < 4 andalso lists:all(fun is_simple_term/1, Es); is_simple_term(#c_var{}) -> true; -- cgit v1.2.3 From f36d67e637e2a3346384902a8499c8317a1a5ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 May 2016 15:10:31 +0200 Subject: beam_utils: Correct translation of BIFs to tests Two lines were never covered, because '[]' was used instead of 'nil'. --- lib/compiler/src/beam_utils.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index 37f89dd677..d187a180de 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -164,10 +164,10 @@ bif_to_test('=<', [A,B], Fail) -> {test,is_ge,Fail,[B,A]}; bif_to_test('>', [A,B], Fail) -> {test,is_lt,Fail,[B,A]}; bif_to_test('<', [_,_]=Ops, Fail) -> {test,is_lt,Fail,Ops}; bif_to_test('>=', [_,_]=Ops, Fail) -> {test,is_ge,Fail,Ops}; -bif_to_test('==', [A,[]], Fail) -> {test,is_nil,Fail,[A]}; +bif_to_test('==', [A,nil], Fail) -> {test,is_nil,Fail,[A]}; bif_to_test('==', [_,_]=Ops, Fail) -> {test,is_eq,Fail,Ops}; bif_to_test('/=', [_,_]=Ops, Fail) -> {test,is_ne,Fail,Ops}; -bif_to_test('=:=', [A,[]], Fail) -> {test,is_nil,Fail,[A]}; +bif_to_test('=:=', [A,nil], Fail) -> {test,is_nil,Fail,[A]}; bif_to_test('=:=', [_,_]=Ops, Fail) -> {test,is_eq_exact,Fail,Ops}; bif_to_test('=/=', [_,_]=Ops, Fail) -> {test,is_ne_exact,Fail,Ops}; bif_to_test(is_record, [_,_,_]=Ops, Fail) -> {test,is_record,Fail,Ops}. -- cgit v1.2.3 From 293962a8ee0af2e15dc8459c7a85e917b84b402a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 10 May 2016 15:21:38 +0200 Subject: beam_utils: Remove unused handling of try/3 in live_opt/4 30cc5c902d moved try/3 instruction inside blocks, so the clause for handling try/3 in live_opt/4 is never executed. --- lib/compiler/src/beam_utils.erl | 5 ----- 1 file changed, 5 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index d187a180de..a96f2bdc65 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -756,11 +756,6 @@ live_opt([{select,_,Src,Fail,List}=I|Is], Regs0, D, Acc) -> Regs1 = x_live([Src], Regs0), Regs = live_join_labels([Fail|List], D, Regs1), live_opt(Is, Regs, D, [I|Acc]); -live_opt([{'try',_,_}=I|Is], Regs, D, Acc) -> - %% If an exeption happens, all x registers will be killed. - %% Therefore, we should only base liveness of the code inside - %% the try. - live_opt(Is, Regs, D, [I|Acc]); live_opt([{try_case,_}=I|Is], _, D, Acc) -> live_opt(Is, live_call(1), D, [I|Acc]); live_opt([{loop_rec,_Fail,_Dst}=I|Is], _, D, Acc) -> -- cgit v1.2.3 From 8c76f74c376d8ced1742e59b8bee851502411124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 11 May 2016 06:59:15 +0200 Subject: beam_utils: Let code_at/2 fail if the label does not exist All callers only calls code_at/2 for existing labels and they don't handle the return value 'none'. --- lib/compiler/src/beam_utils.erl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index a96f2bdc65..dd3c2ff913 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -137,10 +137,7 @@ index_label(Lbl, Is0, Acc) -> %% Retrieve the code at the given label. code_at(L, Ll) -> - case gb_trees:lookup(L, Ll) of - {value,Code} -> Code; - none -> none - end. + gb_trees:get(L, Ll). %% bif_to_test(Bif, [Op], Fail) -> {test,Test,Fail,[Op]} %% Convert a BIF to a test. Fail if not possible. -- cgit v1.2.3 From 3701f7078627d6a4daab3049f09036c4e410d5fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 11 May 2016 13:22:01 +0200 Subject: beam_utils: Remove unused code --- lib/compiler/src/beam_utils.erl | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index dd3c2ff913..9169a494f6 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -591,8 +591,10 @@ check_killed_block(_, []) -> transparent. %% killed - Reg is assigned a new value or killed by an allocation instruction %% transparent - Reg is neither used nor killed %% used - Reg is explicitly used by an instruction -%% -%% (Unknown instructions will cause an exception.) +%% +%% '%live' annotations are not allowed. +%% +%% (Unknown instructions will cause an exception.) check_used_block({x,X}=R, [{set,Ds,Ss,{alloc,Live,Op}}|Is], St) -> if @@ -601,11 +603,6 @@ check_used_block({x,X}=R, [{set,Ds,Ss,{alloc,Live,Op}}|Is], St) -> end; check_used_block(R, [{set,Ds,Ss,Op}|Is], St) -> check_used_block_1(R, Ss, Ds, Op, Is, St); -check_used_block(R, [{'%live',Live,_}|Is], St) -> - case R of - {x,X} when X >= Live -> {killed,St}; - _ -> check_used_block(R, Is, St) - end; check_used_block(_, [], St) -> {transparent,St}. check_used_block_1(R, Ss, Ds, Op, Is, St0) -> -- cgit v1.2.3 From 8fa837e84dbeeb01d9dd4525719558b4909bd2b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 11 May 2016 13:22:11 +0200 Subject: beam_utils: Simplify the return value for check_liveness/3 check_liveness/3 returns {unknown,State} if an instruction is not handled. All callers will handle 'unknown' the same way as 'used'. Therefore, we can simplify the code and improve the coverage if we return {used,State} instead of {unknown,State}. --- lib/compiler/src/beam_utils.erl | 45 +++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 27 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index 9169a494f6..5c54680403 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -67,8 +67,7 @@ is_killed(R, Is, D) -> St = #live{bl=check_killed_block_fun(),lbl=D,res=gb_trees:empty()}, case check_liveness(R, Is, St) of {killed,_} -> true; - {used,_} -> false; - {unknown,_} -> false + {used,_} -> false end. %% is_killed_at(Reg, Lbl, State) -> true|false @@ -78,8 +77,7 @@ is_killed_at(R, Lbl, D) when is_integer(Lbl) -> St0 = #live{bl=check_killed_block_fun(),lbl=D,res=gb_trees:empty()}, case check_liveness_at(R, Lbl, St0) of {killed,_} -> true; - {used,_} -> false; - {unknown,_} -> false + {used,_} -> false end. %% is_not_used(Register, [Instruction], State) -> true|false @@ -93,8 +91,7 @@ is_not_used(R, Is, D) -> St = #live{bl=fun check_used_block/3,lbl=D,res=gb_trees:empty()}, case check_liveness(R, Is, St) of {killed,_} -> true; - {used,_} -> false; - {unknown,_} -> false + {used,_} -> false end. %% is_not_used(Register, [Instruction], State) -> true|false @@ -108,8 +105,7 @@ is_not_used_at(R, Lbl, D) -> St = #live{bl=fun check_used_block/3,lbl=D,res=gb_trees:empty()}, case check_liveness_at(R, Lbl, St) of {killed,_} -> true; - {used,_} -> false; - {unknown,_} -> false + {used,_} -> false end. %% index_labels(FunctionIs) -> State @@ -237,13 +233,11 @@ combine_heap_needs(H1, H2) when is_integer(H1), is_integer(H2) -> %%% -%% check_liveness(Reg, [Instruction], {State,BlockCheckFun}) -> -%% {killed | used | unknown,UpdateState} -%% Finds out how Reg is used in the instruction sequence. Returns one of: -%% killed - Reg is assigned a new value or killed by an allocation instruction -%% used - Reg is used (or possibly referenced by an allocation instruction) -%% unknown - not possible to determine (perhaps because of an instruction -%% that we don't recognize) +%% check_liveness(Reg, [Instruction], #live{}) -> +%% {killed | used, #live{}} +%% Find out whether Reg is used or killed in instruction sequence. +%% 'killed' means that Reg is assigned a new value or killed by an +%% allocation instruction. 'used' means that Reg is used in some way. check_liveness(R, [{set,_,_,_}=I|_], St) -> erlang:error(only_allowed_in_blocks, [R,I,St]); @@ -458,8 +452,9 @@ check_liveness(R, [{loop_rec,{f,_},{x,0}}|_], St) -> {x,_} -> {killed,St}; _ -> - %% y register. Rarely happens. Be very conversative. - {unknown,St} + %% y register. Rarely happens. Be very conversative and + %% assume it's used. + {used,St} end; check_liveness(R, [{loop_rec_end,{f,Fail}}|_], St) -> check_liveness_at(R, Fail, St); @@ -490,7 +485,8 @@ check_liveness(R, [{put_map,{f,_},_,Src,_D,Live,{list,_}}|_], St0) -> {x,_} -> {killed,St0}; {y,_} -> - {unknown,St0} + %% Conservatively mark it as used. + {used,St0} end; check_liveness(R, [{test_heap,N,Live}|Is], St) -> I = {block,[{set,[],[],{alloc,Live,{nozero,nostack,N,[]}}}]}, @@ -502,12 +498,8 @@ check_liveness(R, [{get_list,S,D1,D2}|Is], St) -> I = {block,[{set,[D1,D2],[S],get_list}]}, check_liveness(R, [I|Is], St); check_liveness(_R, Is, St) when is_list(Is) -> -%% case Is of -%% [I|_] -> -%% io:format("~p ~p\n", [_R,I]); -%% _ -> ok -%% end, - {unknown,St}. + %% Not implemented. Conservatively assume that the register is used. + {used,St}. check_liveness_everywhere(R, [{f,Lbl}|T], St0) -> case check_liveness_at(R, Lbl, St0) of @@ -526,7 +518,7 @@ check_liveness_at(R, Lbl, #live{lbl=Ll,res=ResMemorized}=St0) -> none -> {Res,St} = case gb_trees:lookup(Lbl, Ll) of {value,Is} -> check_liveness(R, Is, St0); - none -> {unknown,St0} + none -> {used,St0} end, {Res,St#live{res=gb_trees:insert(Lbl, Res, St#live.res)}} end. @@ -633,8 +625,7 @@ is_reg_used_at_1(_, 0, St) -> is_reg_used_at_1(R, Lbl, St0) -> case check_liveness_at(R, Lbl, St0) of {killed,St} -> {false,St}; - {used,St} -> {true,St}; - {unknown,St} -> {true,St} + {used,St} -> {true,St} end. index_labels_1([{label,Lbl}|Is0], Acc) -> -- cgit v1.2.3 From 94feb3f8f9c5e7b67ee06c84ea68932bbebc12e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 13 May 2016 07:08:22 +0200 Subject: beam_utils: Remove clause checking for illegal set/4 instruction I can't remember that clause ever trigger during development. Remove it to eliminated an uncovered line. --- lib/compiler/src/beam_utils.erl | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index 5c54680403..eed30ad6b7 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -239,8 +239,6 @@ combine_heap_needs(H1, H2) when is_integer(H1), is_integer(H2) -> %% 'killed' means that Reg is assigned a new value or killed by an %% allocation instruction. 'used' means that Reg is used in some way. -check_liveness(R, [{set,_,_,_}=I|_], St) -> - erlang:error(only_allowed_in_blocks, [R,I,St]); check_liveness(R, [{block,Blk}|Is], #live{bl=BlockCheck}=St0) -> case BlockCheck(R, Blk, St0) of {transparent,St} -> check_liveness(R, Is, St); -- cgit v1.2.3 From c4336b7ba8e39589f395f2bc86089a34b81d3cb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 13 May 2016 06:55:09 +0200 Subject: beam_utils: Correct break in conventions for split_even/1 and join_even/1 Exported functions in this file should appear at the top of the file. Also add missing spaces after commas. --- lib/compiler/src/beam_utils.erl | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index eed30ad6b7..47703b4aa3 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -25,9 +25,8 @@ is_not_used/3,is_not_used_at/3, empty_label_index/0,index_label/3,index_labels/1, code_at/2,bif_to_test/3,is_pure_test/1, - live_opt/1,delete_live_annos/1,combine_heap_needs/2]). - --export([join_even/2,split_even/1]). + live_opt/1,delete_live_annos/1,combine_heap_needs/2, + join_even/2,split_even/1]). -import(lists, [member/2,sort/1,reverse/1,splitwith/2]). @@ -228,6 +227,17 @@ combine_heap_needs(Words, {alloc,Alloc}) when is_integer(Words) -> combine_heap_needs(H1, H2) when is_integer(H1), is_integer(H2) -> H1+H2. +%% split_even/1 +%% [1,2,3,4,5,6] -> {[1,3,5],[2,4,6]} + +split_even(Rs) -> split_even(Rs, [], []). + +%% join_even/1 +%% {[1,3,5],[2,4,6]} -> [1,2,3,4,5,6] + +join_even([], []) -> []; +join_even([S|Ss], [D|Ds]) -> [S,D|join_even(Ss, Ds)]. + %%% %%% Local functions. %%% @@ -838,14 +848,7 @@ x_live([], Regs) -> Regs. is_live(X, Regs) -> ((Regs bsr X) band 1) =:= 1. -%% split_even/1 -%% [1,2,3,4,5,6] -> {[1,3,5],[2,4,6]} -split_even(Rs) -> split_even(Rs,[],[]). -split_even([],Ss,Ds) -> {reverse(Ss),reverse(Ds)}; -split_even([S,D|Rs],Ss,Ds) -> - split_even(Rs,[S|Ss],[D|Ds]). - -%% join_even/1 -%% {[1,3,5],[2,4,6]} -> [1,2,3,4,5,6] -join_even([],[]) -> []; -join_even([S|Ss],[D|Ds]) -> [S,D|join_even(Ss,Ds)]. +split_even([], Ss, Ds) -> + {reverse(Ss),reverse(Ds)}; +split_even([S,D|Rs], Ss, Ds) -> + split_even(Rs, [S|Ss], [D|Ds]). -- cgit v1.2.3