[mercury-users] Erlang backend
Richard O'Keefe
ok at cs.otago.ac.nz
Thu Feb 5 11:28:42 AEDT 2009
I'm CC-ing Kostis on this because we now have an example
of what needed to be treated as constant terms for the
Mercury->Erlang back end to be efficient.
On 4 Feb 2009, at 6:59 pm, Peter Wang wrote:
> Function references rather than closures.
...
>
> RTTI for list(T).
>
> l__type_ctor_info_list_1() ->
> V_8_8 = [] ,
> V_9_9 = [{erlang_du_functor , "[|]" , 2 , 1 , 1 , '[|]' ,
> [{du_arg_info , {no } , type_var_1()} | [{du_arg_info , {no } ,
> pti_l__pti_list_1__pseudo_1()} | [] ] ] , {no } } | V_8_8 ] ,
> {1 , 13 , (fun(V_3_3 , V_2_2 , V_1_1 ) ->
> '__Unify____list_1_0'(V_3_3 , V_2_2 , V_1_1 )
> end), (fun(V_7_7 , V_5_5 , V_4_4 ) ->
> '__Compare____list_1_0'(V_7_7 , V_5_5 , V_4_4 )
> end), "l" , "list" , {etcr_du } , [{erlang_du_functor , "[]" , 0 , 0
> , 0 , '[]' , [] , {no } } | V_9_9 ] } .
In fact there are two closures in that.
Let's reindent and do some constant propagation:
l__type_ctor_info_list_1() ->
{1
,13
,fun(A, B, C) -> '__Unify____list_1_0'(A, B, C) end %CLOSURE
,fun(X, Y, Z) -> '__Compare____list_1_0'(X, Y, Z) end %CLOSURE
,"l"
,"list"
,{etcr_du}
,[{erlang_du_functor, "[]", 0, 0, 0, '[]', [], {no}}
,{erlang_du_functor, "[|]", 2, 1, 1, '[|]',
[{du_arg_info, {no}, type_var_1()} %CALL
,{du_arg_info, {no}, pti_l__pti_list_1__pseudo_1()}%CALL
], {no}}]}.
In this example there are no function references (fun F/N)
but two closures. I'll grant you they _could_ have been
function references, but they aren't. What's more, there are
two function calls; this can by no means be said to be a constant
term. If type_var_1() and pti_l__pti_list_1__pseudo_1() are
similar functions, then in-line expansion might turn this into
constant terms, but it's not a constant term as it stands.
>
> pti_l__pti_list_1__pseudo_1() ->
> {pseudo , (fun() ->
> {fun l__type_ctor_info_list_1/0 , type_var_1()}
> end)} .
This contains a function reference *and* a closure:
pti_l__pti_list_1__pseudo_1() ->
{pseudo
,fun () -> %CLOSURE
{fun l__type_ctor_info_list_1/0 %REFERENCE
,type_var_1() %CALL
} end}.
>
> type_var_1() ->
> {pseudo , (fun() ->
> 1
> end)} .
type_var_1() ->
{pseudo
,fun () -> %CLOSURE
1 end}.
You didn't show me any inline declaration for type_var_1/0 or
pti_l__pti_list_1__pseudo_1/0, so those calls probably were not
inlined, and remained as calls, meaning there are definitely no
constant terms here.
Now fun (A, ..., X) -> foo(A, ..., X) end
can arguably be replaced by fun foo/N,
but fun () -> 1 end
and fun () -> {....} end
do not have that form. It appears that you really do want
a closure with no free variables to be treated as a constant.
I don't have any hard figures, but a quick trawl through the
OTP sources suggested to me that such closures are actually
quite common. I do have some hard figures for a body of
Smalltalk code, where about 30% of "blocks" (Smalltalk closures)
could be statically allocated like that, which is consistent
with what I was seeing in the OTP sources.
So it is possible that this might be a useful technique for
Erlang in general.
--------------------------------------------------------------------------
mercury-users mailing list
Post messages to: mercury-users at csse.unimelb.edu.au
Administrative Queries: owner-mercury-users at csse.unimelb.edu.au
Subscriptions: mercury-users-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the users
mailing list