[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