aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2010-04-22 13:37:18 +0200
committerBjörn Gustavsson <[email protected]>2010-05-11 08:54:26 +0200
commitf39e0b6bbc5f5d9f6a55b87847bcad7707309883 (patch)
tree716d2cd1cfa00e1854ccba637484c8a7aec68919 /lib
parent1d3148a8532b9319265fbe4107cdde81b554b3a2 (diff)
downloadotp-f39e0b6bbc5f5d9f6a55b87847bcad7707309883.tar.gz
otp-f39e0b6bbc5f5d9f6a55b87847bcad7707309883.tar.bz2
otp-f39e0b6bbc5f5d9f6a55b87847bcad7707309883.zip
compiler test: Test optimization of receive statements
We don't attempt to run the generated code, but use beam_disasm and check for the presence or absence (as appropriate) of the recv_mark/1 and recv_set/1 instructions.
Diffstat (limited to 'lib')
-rw-r--r--lib/compiler/test/receive_SUITE.erl53
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/no_1.erl99
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/no_2.erl26
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/no_3.erl14
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_1.erl12
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_2.erl13
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_3.erl16
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_4.erl16
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_5.erl46
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_6.erl15
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_7.erl12
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_8.erl15
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_9.erl13
13 files changed, 347 insertions, 3 deletions
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index cb8833759a..3cfc22ddc9 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -21,7 +21,7 @@
-module(receive_SUITE).
-export([all/1,init_per_testcase/2,fin_per_testcase/2,
- recv/1,coverage/1,otp_7980/1]).
+ recv/1,coverage/1,otp_7980/1,ref_opt/1]).
-include("test_server.hrl").
@@ -36,7 +36,7 @@ fin_per_testcase(_Case, Config) ->
all(suite) ->
test_lib:recompile(?MODULE),
- [recv,coverage,otp_7980].
+ [recv,coverage,otp_7980,ref_opt].
-record(state, {ena = true}).
@@ -157,5 +157,52 @@ otp_7980_add_clients(Count) ->
end,
N - 1
end, Count, [1,2,3]).
-
+
+ref_opt(Config) when is_list(Config) ->
+ case ?MODULE of
+ receive_SUITE -> ref_opt_1(Config);
+ _ -> {skip,"Enough to run this case once."}
+ end.
+
+ref_opt_1(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Sources = filelib:wildcard(filename:join([DataDir,"ref_opt","*.erl"])),
+ ?line test_lib:p_run(fun(Src) ->
+ do_ref_opt(Src, PrivDir)
+ end, Sources),
+ ok.
+
+do_ref_opt(Source, PrivDir) ->
+ try
+ {ok,Mod} = c:c(Source, [{outdir,PrivDir}]),
+ ok = Mod:Mod(),
+ Base = filename:rootname(filename:basename(Source), ".erl"),
+ BeamFile = filename:join(PrivDir, Base),
+ {beam_file,Mod,_,_,_,Code} = beam_disasm:file(BeamFile),
+ case Base of
+ "no_"++_ ->
+ [] = collect_recv_opt_instrs(Code);
+ "yes_"++_ ->
+ [{recv_mark,{f,L}},{recv_set,{f,L}}] =
+ collect_recv_opt_instrs(Code)
+ end,
+ ok
+ catch Class:Error ->
+ io:format("~s: ~p ~p\n~p\n",
+ [Source,Class,Error,erlang:get_stacktrace()]),
+ error
+ end.
+
+collect_recv_opt_instrs(Code) ->
+ L = [ [I || I <- Is,
+ begin
+ case I of
+ {recv_mark,{f,_}} -> true;
+ {recv_set,{f,_}} -> true;
+ _ -> false
+ end
+ end] || {function,_,_,_,Is} <- Code],
+ lists:append(L).
+
id(I) -> I.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/no_1.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/no_1.erl
new file mode 100644
index 0000000000..bc63dac437
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/no_1.erl
@@ -0,0 +1,99 @@
+-module(no_1).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+f1(X) ->
+ Ref = make_ref(),
+ receive
+ _ when [X] =:= Ref ->
+ ok
+ end.
+
+f2(X, Y) ->
+ _Ref = make_ref(),
+ receive
+ _ when X =:= Y ->
+ ok
+ end.
+
+f3(X) ->
+ Ref = make_ref(),
+ receive
+ _ when X =:= Ref ->
+ ok
+ end.
+
+f4(X) ->
+ Ref = make_ref(),
+ receive
+ {X,_} when not X =:= Ref ->
+ ok
+ end.
+
+f5(X) ->
+ Ref = make_ref(),
+ receive
+ {Y,_} when X =:= Y; Y =:= Ref ->
+ ok
+ end.
+
+f6(X) ->
+ Ref = make_ref(),
+ receive
+ {Y,_} when Y =:= Ref; Ref =:= X ->
+ ok
+ end.
+
+f7(X) ->
+ Ref = make_ref(),
+ receive
+ {Y,_} when Y =:= Ref; not (X =:= Ref) ->
+ ok
+ end.
+
+f8(X) ->
+ Ref = make_ref(),
+ receive
+ {Y,_} when not (X =:= Ref); Y =:= Ref ->
+ ok
+ end.
+
+f9(X) ->
+ Ref = make_ref(),
+ receive
+ {Y,_} when (not (X =:= Ref)) or (Y =:= Ref) ->
+ ok
+ end.
+
+f10(X, Y) ->
+ Ref = make_ref(),
+ receive
+ {Z,_} when not (X =:= Y andalso Z =:= Ref) ->
+ ok
+ end.
+
+f11(X, Y) ->
+ Ref = make_ref(),
+ receive
+ {Z,_} when not ((X =:= Y) and (Z =:= Ref)) ->
+ ok
+ end.
+
+f12(X, Y) ->
+ Ref = make_ref(),
+ receive
+ {Z,_} when not ((Z =:= Ref) and (X =:= Y)) ->
+ ok
+ end.
+
+f13() ->
+ Ref = make_ref(),
+ RefCopy = id(Ref),
+ receive
+ _ when hd([RefCopy]) =:= Ref ->
+ ok
+ end.
+
+id(I) -> I.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/no_2.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/no_2.erl
new file mode 100644
index 0000000000..bc8d30c2ac
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/no_2.erl
@@ -0,0 +1,26 @@
+-module(no_2).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+f1() ->
+ Ref = make_ref(),
+ receive
+ {'DOWN',Ref} ->
+ ok;
+ {'DOWN',_} ->
+ ok
+ end.
+
+f2(Pid, Msg) ->
+ Ref = erlang:monitor(process, Pid),
+ Pid ! Msg,
+ receive
+ {ok,Ref,Reply} ->
+ {ok,Reply};
+ {error,Ref,Reply} ->
+ {error,Reply};
+ {error,A,B} ->
+ {error,A,B}
+ end.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/no_3.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/no_3.erl
new file mode 100644
index 0000000000..44cf8d7f71
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/no_3.erl
@@ -0,0 +1,14 @@
+-module(no_3).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+f(X) ->
+ Ref = case X of
+ false -> ref;
+ true -> make_ref()
+ end,
+ receive
+ Ref -> ok
+ end.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_1.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_1.erl
new file mode 100644
index 0000000000..e2ebe234c1
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_1.erl
@@ -0,0 +1,12 @@
+-module(yes_1).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+f() ->
+ Ref = make_ref(),
+ receive
+ {Ref,Reply} ->
+ Reply
+ end.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_2.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_2.erl
new file mode 100644
index 0000000000..6077cdcab9
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_2.erl
@@ -0,0 +1,13 @@
+-module(yes_2).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+f(Pid, Msg) ->
+ Ref = make_ref(),
+ Pid ! Msg,
+ receive
+ {Ref,Reply} ->
+ Reply
+ end.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_3.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_3.erl
new file mode 100644
index 0000000000..28efc542ae
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_3.erl
@@ -0,0 +1,16 @@
+-module(yes_3).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+f(Pid, Msg) ->
+ Ref = make_ref(),
+ do_send(Pid, Msg),
+ receive
+ {Ref,Reply} ->
+ Reply
+ end.
+
+do_send(Pid, Msg) ->
+ Pid ! Msg.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_4.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_4.erl
new file mode 100644
index 0000000000..d1ba4832c7
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_4.erl
@@ -0,0 +1,16 @@
+-module(yes_4).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+f(Pid, Msg) ->
+ Ref = make_ref(),
+ catch do_send(Pid, Msg),
+ receive
+ {Ref,Reply} ->
+ Reply
+ end.
+
+do_send(Pid, Msg) ->
+ Pid ! Msg.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_5.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_5.erl
new file mode 100644
index 0000000000..3f02fba6a6
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_5.erl
@@ -0,0 +1,46 @@
+-module(yes_5).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+do_call(Process, Label, Request, Timeout) ->
+ Node = case Process of
+ {_S, N} when is_atom(N) ->
+ N;
+ _ when is_pid(Process) ->
+ node(Process)
+ end,
+ try erlang:monitor(process, Process) of
+ Mref ->
+ catch erlang:send(Process, {Label, {self(), Mref}, Request},
+ [noconnect]),
+ receive
+ {Mref, Reply} ->
+ erlang:demonitor(Mref, [flush]),
+ {ok, Reply};
+ {'DOWN', Mref, _, _, noconnection} ->
+ exit({nodedown, Node});
+ {'DOWN', Mref, _, _, Reason} ->
+ exit(Reason)
+ after Timeout ->
+ erlang:demonitor(Mref),
+ receive
+ {'DOWN', Mref, _, _, _} -> true
+ after 0 -> true
+ end,
+ exit(timeout)
+ end
+ catch
+ error:_ ->
+ monitor_node(Node, true),
+ receive
+ {nodedown, Node} ->
+ monitor_node(Node, false),
+ exit({nodedown, Node})
+ after 0 ->
+ Tag = make_ref(),
+ Process ! {Label, {self(), Tag}, Request},
+ ?MODULE:wait_resp(Node, Tag, Timeout)
+ end
+ end.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_6.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_6.erl
new file mode 100644
index 0000000000..c54b636aa6
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_6.erl
@@ -0,0 +1,15 @@
+-module(yes_6).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+f(Pid, Msg) ->
+ Ref = erlang:monitor(process, Pid),
+ Pid ! Msg,
+ receive
+ {ok,Ref,Reply} ->
+ {ok,Reply};
+ {error,Ref,Reply} ->
+ {error,Reply}
+ end.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_7.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_7.erl
new file mode 100644
index 0000000000..849eab1746
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_7.erl
@@ -0,0 +1,12 @@
+-module(yes_7).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+f(X, Y) ->
+ Ref = make_ref(),
+ receive
+ {Z,_} when X =:= Y, Ref =:= Z ->
+ ok
+ end.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_8.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_8.erl
new file mode 100644
index 0000000000..a47fe8cfbf
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_8.erl
@@ -0,0 +1,15 @@
+-module(yes_8).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+%% Cover use of floating point registers.
+
+f(Pid, X) when is_float(X) ->
+ Ref = make_ref(),
+ Pid ! {X+3},
+ receive
+ Ref ->
+ ok
+ end.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_9.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_9.erl
new file mode 100644
index 0000000000..97fce5e734
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_9.erl
@@ -0,0 +1,13 @@
+-module(yes_9).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+f(Fun) ->
+ Ref = make_ref(),
+ Fun(),
+ receive
+ {Ref,Reply} ->
+ Reply
+ end.