aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/cerl_inline.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2010-03-18 08:45:03 +0100
committerBjörn Gustavsson <[email protected]>2010-03-26 08:09:26 +0100
commit0320836d1b58438ef4467832b00306672d22f8d6 (patch)
tree6953fb68c2c04e162ecb7e5cd9a568a43ceacddf /lib/compiler/src/cerl_inline.erl
parente74235df989995f5bd2b66b7102857446ff10d11 (diff)
downloadotp-0320836d1b58438ef4467832b00306672d22f8d6.tar.gz
otp-0320836d1b58438ef4467832b00306672d22f8d6.tar.bz2
otp-0320836d1b58438ef4467832b00306672d22f8d6.zip
Consistently rewrite an inlined function_clause exception to case_clause
A function_clause exception is generated by jumping to a func_info/3 instruction at the beginning of the function. The x registers are assumed to contain the arguments for the function. That means that a func_info/3 instruction copied from another function (or even from the same function if not at the top level) will not work, so it must be replaced with an instruction that generates a case_clause exception. In Core Erlang, a func_info/3 instruction is represented as a the primop match_fail({function_clause,Arg1,...ArgN}). The current mechanism that is supposed to replace the primop match_fail(function_clause) with match_fail(case_clause) will fail to do that in the following circumstances: 1. If the inliner has inlined a function into itself. Fix that by having the inliner clear the function_name annotations on all match_fail primops in functions that are inlined. (To simplify doing that, the annotation is now on the primop node itself and not on the 'function_clause' atom inside it.) 2. If the inliner has rewritten the tuple node in the primop node to a literal (when inlining a function call with literal arguments), v3_kernel would not recognize the match_fail(function_clause) primop and would not rewrite it. Fix it by making v3_kernel smarter. Also simplify the "old" inliner (sys_core_inline) to only clear the function_name annotations instead of rewriting function_clause execptions to case_clause execptions itself.
Diffstat (limited to 'lib/compiler/src/cerl_inline.erl')
-rw-r--r--lib/compiler/src/cerl_inline.erl32
1 files changed, 27 insertions, 5 deletions
diff --git a/lib/compiler/src/cerl_inline.erl b/lib/compiler/src/cerl_inline.erl
index 191efa3032..f4eaa17e72 100644
--- a/lib/compiler/src/cerl_inline.erl
+++ b/lib/compiler/src/cerl_inline.erl
@@ -1429,17 +1429,26 @@ inline(E, #app{opnds = Opnds, ctxt = Ctxt, loc = L}, Ren, Env, S) ->
{E, S};
true ->
%% Create local bindings for the parameters to their
- %% respective operand structures from the app-structure, and
- %% visit the body in the context saved in the structure.
+ %% respective operand structures from the app-structure.
{Rs, Ren1, Env1, S1} = bind_locals(Vs, Opnds, Ren, Env, S),
- {E1, S2} = i(fun_body(E), Ctxt, Ren1, Env1, S1),
+
+ %% function_clause exceptions that have been inlined
+ %% into another function (or even into the same function)
+ %% will not work properly. The v3_kernel pass will
+ %% take care of it, but we will need to help it by
+ %% removing any function_name annotations on match_fail
+ %% primops that we inline.
+ E1 = kill_function_name_anns(fun_body(E)),
+
+ %% Visit the body in the context saved in the structure.
+ {E2, S2} = i(E1, Ctxt, Ren1, Env1, S1),
%% Create necessary bindings and/or set flags.
- {E2, S3} = make_let_bindings(Rs, E1, S2),
+ {E3, S3} = make_let_bindings(Rs, E2, S2),
%% Lastly, flag the application as inlined, since the inlining
%% attempt was not aborted before we reached this point.
- {E2, st__set_app_inlined(L, S3)}
+ {E3, st__set_app_inlined(L, S3)}
end.
%% For the (possibly renamed) argument variables to an inlined call,
@@ -2370,6 +2379,19 @@ kill_id_anns([A | As]) ->
kill_id_anns([]) ->
[].
+kill_function_name_anns(Body) ->
+ F = fun(P) ->
+ case type(P) of
+ primop ->
+ Ann = get_ann(P),
+ Ann1 = lists:keydelete(function_name, 1, Ann),
+ set_ann(P, Ann1);
+ _ ->
+ P
+ end
+ end,
+ cerl_trees:map(F, Body).
+
%% =====================================================================
%% General utilities