aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler
diff options
context:
space:
mode:
authorAnthony Ramine <[email protected]>2012-11-10 16:05:41 +0100
committerAnthony Ramine <[email protected]>2012-12-03 11:08:21 +0100
commit42b87beb92c2a145a425fcc9ab8f8698f081088e (patch)
tree9298481bc2de27ea12dbe7115b9b70a73a7ec51f /lib/compiler
parentc4d680549e11e116dcdd95ac29101ef3e54aba5f (diff)
downloadotp-42b87beb92c2a145a425fcc9ab8f8698f081088e.tar.gz
otp-42b87beb92c2a145a425fcc9ab8f8698f081088e.tar.bz2
otp-42b87beb92c2a145a425fcc9ab8f8698f081088e.zip
Remove the reverse eta-conversion from v3_kernel
Local function references should be handled directly as a make_fun internal BIF call instead of creating an extra lambda function every time they are used.
Diffstat (limited to 'lib/compiler')
-rw-r--r--lib/compiler/src/beam_dict.erl18
-rw-r--r--lib/compiler/src/v3_kernel.erl31
2 files changed, 30 insertions, 19 deletions
diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl
index 531968b3c8..ff6c7c11dc 100644
--- a/lib/compiler/src/beam_dict.erl
+++ b/lib/compiler/src/beam_dict.erl
@@ -138,7 +138,17 @@ string(Str, Dict) when is_list(Str) ->
-spec lambda(label(), non_neg_integer(), bdict()) ->
{non_neg_integer(), bdict()}.
-lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
+lambda(Lbl, 0, #asm{lambdas=Lambdas0}=Dict) ->
+ case lists:keyfind(Lbl, 1, Lambdas0) of
+ {Lbl,{OldIndex,_,_,_,_}} ->
+ {OldIndex,Dict};
+ false ->
+ new_lambda(Lbl, 0, Dict)
+ end;
+lambda(Lbl, NumFree, Dict) ->
+ new_lambda(Lbl, NumFree, Dict).
+
+new_lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
OldIndex = length(Lambdas0),
%% Set Index the same as OldIndex.
Index = OldIndex,
@@ -235,10 +245,12 @@ string_table(#asm{strings=Strings,string_offset=Size}) ->
-spec lambda_table(bdict()) -> {non_neg_integer(), [<<_:192>>]}.
-lambda_table(#asm{locals=Loc0,lambdas=Lambdas0}) ->
+lambda_table(#asm{exports=Ext0,locals=Loc0,lambdas=Lambdas0}) ->
Lambdas1 = sofs:relation(Lambdas0),
Loc = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Loc0]),
- Lambdas2 = sofs:relative_product1(Lambdas1, Loc),
+ Ext = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Ext0]),
+ All = sofs:union(Loc, Ext),
+ Lambdas2 = sofs:relative_product1(Lambdas1, All),
Lambdas = [<<F:32,A:32,Lbl:32,Index:32,NumFree:32,OldUniq:32>> ||
{{_,Lbl,Index,NumFree,OldUniq},{F,A}} <- sofs:to_external(Lambdas2)],
{length(Lambdas),Lambdas}.
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index 8ef71e1346..b1bff47f69 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -235,16 +235,8 @@ gexpr_test_add(Ke, St0) ->
%% expr(Cexpr, Sub, State) -> {Kexpr,[PreKexpr],State}.
%% Convert a Core expression, flattening it at the same time.
-expr(#c_var{anno=A,name={_Name,Arity}}=Fname, Sub, St) ->
- %% A local in an expression.
- %% For now, these are wrapped into a fun by reverse
- %% etha-conversion, but really, there should be exactly one
- %% such "lambda function" for each escaping local name,
- %% instead of one for each occurrence as done now.
- Vs = [#c_var{name=list_to_atom("V" ++ integer_to_list(V))} ||
- V <- integers(1, Arity)],
- Fun = #c_fun{anno=A,vars=Vs,body=#c_apply{anno=A,op=Fname,args=Vs}},
- expr(Fun, Sub, St);
+expr(#c_var{anno=A,name={Name,Arity}}, Sub, St) ->
+ {#k_local{anno=A,name=get_fsub(Name, Arity, Sub),arity=Arity},[],St};
expr(#c_var{anno=A,name=V}, Sub, St) ->
{#k_var{anno=A,name=get_vsub(V, Sub)},[],St};
expr(#c_literal{anno=A,val=V}, _Sub, St) ->
@@ -1663,6 +1655,19 @@ uexpr(#ifun{anno=A,vars=Vs,body=B0}, {break,Rs}, St0) ->
#k_int{val=Index},#k_int{val=Uniq}|Fvs],
ret=Rs},
Free,add_local_function(Fun, St)};
+uexpr(#k_local{anno=A,name=Name,arity=Arity}, {break,Rs}, St) ->
+ Fs = get_free(Name, Arity, St),
+ FsCount = length(Fs),
+ Free = lit_list_vars(Fs),
+ %% Set dummy values for Index and Uniq -- the real values will
+ %% be assigned by beam_asm.
+ Index = Uniq = 0,
+ Bif = #k_bif{anno=#k{us=Free,ns=lit_list_vars(Rs),a=A},
+ op=#k_internal{name=make_fun,arity=FsCount+3},
+ args=[#k_atom{val=Name},#k_int{val=FsCount+Arity},
+ #k_int{val=Index},#k_int{val=Uniq}|Fs],
+ ret=Rs},
+ {Bif,Free,St};
uexpr(Lit, {break,Rs0}, St0) ->
%% Transform literals to puts here.
%%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,Lit]),
@@ -1843,12 +1848,6 @@ make_list(Es) ->
#c_cons{hd=E,tl=Acc}
end, #c_literal{val=[]}, Es).
-%% List of integers in interval [N,M]. Empty list if N > M.
-
-integers(N, M) when N =< M ->
- [N|integers(N + 1, M)];
-integers(_, _) -> [].
-
%% is_in_guard(State) -> true|false.
is_in_guard(#kern{guard_refc=Refc}) ->