diff options
author | Anthony Ramine <[email protected]> | 2013-04-09 22:20:00 +0200 |
---|---|---|
committer | Fredrik Gustafsson <[email protected]> | 2013-04-19 11:47:00 +0200 |
commit | 8aa46fd40d759de2d6a13fbafb5e88cdf1047220 (patch) | |
tree | fe67482bb0901c12b94f4db547afe20a846127ef /lib/compiler/test | |
parent | 4e220f07593c80ba20c6ce968ae608f5363ef75b (diff) | |
download | otp-8aa46fd40d759de2d6a13fbafb5e88cdf1047220.tar.gz otp-8aa46fd40d759de2d6a13fbafb5e88cdf1047220.tar.bz2 otp-8aa46fd40d759de2d6a13fbafb5e88cdf1047220.zip |
Use a set to store ref registers in beam_receive
In some circumstances, as when inlining code, when some optimization
passes are disabled or with hand-written but semantically correct Core
Erlang or BEAM assembly, a fresh reference may be live in more than one
register:
...
{allocate_zero,2,2}.
...
{call_ext,0,{extfunc,erlang,make_ref,0}}. % Ref in [x0]
...
{move,{x,0},{y,0}}. % Ref in [x0,y0]
{move,{y,1},{x,0}}. % Ref in [y0]
...
{move,{y,0},{x,0}}. % Ref in [x0,y0]
{move,{x,0},{y,1}}. % Ref in [x0,y0,y1]
{label,5}.
{loop_rec,{f,6},{x,0}}. % Ref in [y0,y1]
...
{loop_rec_end,{f,5}}.
{label,6}.
{wait,{f,5}}.
...
Pass beam_receive expects a single live register for the ref when it
encounters the loop_rec instruction and crashes with the following
reason:
$ erlc t.S
...
crash reason: {{case_clause,
{'EXIT',
{{case_clause,[{y,1},{y,0}]},
[{beam_receive,opt_recv,5,
[{file,"beam_receive.erl"},{line,154}]},
...]}}},
...}
This commit teaches beam_receive how to use a set of registers instead
of a single one when tracking fresh references, thus avoiding the crash.
Diffstat (limited to 'lib/compiler/test')
-rw-r--r-- | lib/compiler/test/receive_SUITE.erl | 13 | ||||
-rw-r--r-- | lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.S | 71 |
2 files changed, 80 insertions, 4 deletions
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl index b91f2922fb..e60584d4ab 100644 --- a/lib/compiler/test/receive_SUITE.erl +++ b/lib/compiler/test/receive_SUITE.erl @@ -188,7 +188,7 @@ ref_opt(Config) when is_list(Config) -> 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"])), + Sources = filelib:wildcard(filename:join([DataDir,"ref_opt","*.{erl,S}"])), ?line test_lib:p_run(fun(Src) -> do_ref_opt(Src, PrivDir) end, Sources), @@ -196,10 +196,15 @@ ref_opt_1(Config) -> do_ref_opt(Source, PrivDir) -> try - {ok,Mod} = c:c(Source, [{outdir,PrivDir}]), + Ext = filename:extension(Source), + {ok,Mod} = compile:file(Source, [report_errors,report_warnings, + {outdir,PrivDir}] ++ + [from_asm || Ext =:= ".S" ]), + Base = filename:rootname(filename:basename(Source), Ext), + code:purge(list_to_atom(Base)), + BeamFile = filename:join(PrivDir, Base), + code:load_abs(BeamFile), 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_"++_ -> diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.S b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.S new file mode 100644 index 0000000000..fd14228135 --- /dev/null +++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.S @@ -0,0 +1,71 @@ +{module, yes_14}. %% version = 0 + +{exports, [{f,2},{module_info,0},{module_info,1},{yes_14,0}]}. + +{attributes, []}. + +{labels, 12}. + + +{function, yes_14, 0, 2}. + {label,1}. + {func_info,{atom,yes_14},{atom,yes_14},0}. + {label,2}. + {move,{atom,ok},{x,0}}. + return. + + +{function, f, 2, 4}. + {label,3}. + {func_info,{atom,yes_14},{atom,f},2}. + {label,4}. + {allocate_heap,2,3,2}. + {move,{x,0},{y,1}}. + {put_tuple,2,{y,0}}. + {put,{atom,data}}. + {put,{x,1}}. + {call_ext,0,{extfunc,erlang,make_ref,0}}. % Ref in [x0] + {test_heap,4,1}. + {put_tuple,3,{x,1}}. + {put,{atom,request}}. + {put,{x,0}}. + {put,{y,0}}. + {move,{x,0},{y,0}}. % Ref in [x0,y0] + {move,{y,1},{x,0}}. % Ref in [y0] + {kill,{y,1}}. + send. + {move,{y,0},{x,0}}. % Ref in [x0,y0] + {move,{x,0},{y,1}}. % Ref in [x0,y0,y1] + {label,5}. + {loop_rec,{f,7},{x,0}}. % Ref in [y0,y1] + {test,is_tuple,{f,6},[{x,0}]}. + {test,test_arity,{f,6},[{x,0},2]}. + {get_tuple_element,{x,0},0,{x,1}}. + {get_tuple_element,{x,0},1,{x,2}}. + {test,is_eq_exact,{f,6},[{x,1},{atom,reply}]}. + {test,is_eq_exact,{f,6},[{x,2},{y,1}]}. + remove_message. + {move,{atom,ok},{x,0}}. + {deallocate,2}. + return. + {label,6}. + {loop_rec_end,{f,5}}. + {label,7}. + {wait,{f,5}}. + + +{function, module_info, 0, 9}. + {label,8}. + {func_info,{atom,yes_14},{atom,module_info},0}. + {label,9}. + {move,{atom,yes_14},{x,0}}. + {call_ext_only,1,{extfunc,erlang,get_module_info,1}}. + + +{function, module_info, 1, 11}. + {label,10}. + {func_info,{atom,yes_14},{atom,module_info},1}. + {label,11}. + {move,{x,0},{x,1}}. + {move,{atom,yes_14},{x,0}}. + {call_ext_only,2,{extfunc,erlang,get_module_info,2}}. |