@@ -55,6 +55,7 @@ let black_block_header tag sz = Nativeint.logor (block_header tag sz) caml_black
55
55
let local_block_header tag sz = Nativeint. logor (block_header tag sz) caml_local
56
56
let white_closure_header sz = block_header Obj. closure_tag sz
57
57
let black_closure_header sz = black_block_header Obj. closure_tag sz
58
+ let local_closure_header sz = local_block_header Obj. closure_tag sz
58
59
let infix_header ofs = block_header Obj. infix_tag ofs
59
60
let float_header = block_header Obj. double_tag (size_float / size_addr)
60
61
let floatarray_header len =
@@ -76,6 +77,11 @@ let pos_arity_in_closinfo = 8 * size_addr - 8
76
77
(* arity = the top 8 bits of the closinfo word *)
77
78
78
79
let closure_info ~arity ~startenv =
80
+ let arity =
81
+ match arity with
82
+ | Lambda. Tupled , n -> - n
83
+ | Lambda. Curried _ , n -> n
84
+ in
79
85
assert (- 128 < = arity && arity < = 127 );
80
86
assert (0 < = startenv && startenv < 1 lsl (pos_arity_in_closinfo - 1 ));
81
87
Nativeint. (add (shift_left (of_int arity) pos_arity_in_closinfo)
@@ -84,7 +90,10 @@ let closure_info ~arity ~startenv =
84
90
85
91
let alloc_float_header dbg = Cconst_natint (float_header, dbg)
86
92
let alloc_floatarray_header len dbg = Cconst_natint (floatarray_header len, dbg)
87
- let alloc_closure_header sz dbg = Cconst_natint (white_closure_header sz, dbg)
93
+ let alloc_closure_header ~mode sz dbg =
94
+ match (mode : Lambda.alloc_mode ) with
95
+ | Alloc_heap -> Cconst_natint (white_closure_header sz, dbg)
96
+ | Alloc_local -> Cconst_natint (local_closure_header sz, dbg)
88
97
let alloc_infix_header ofs dbg = Cconst_natint (infix_header ofs, dbg)
89
98
let alloc_closure_info ~arity ~startenv dbg =
90
99
Cconst_natint (closure_info ~arity ~startenv , dbg)
@@ -838,12 +847,16 @@ let make_checkbound dbg = function
838
847
(* Record application and currying functions *)
839
848
840
849
let apply_function_sym n =
850
+ assert (n > 0 );
841
851
Compilenv. need_apply_fun n; " caml_apply" ^ Int. to_string n
842
- let curry_function_sym n =
843
- Compilenv. need_curry_fun n;
844
- if n > = 0
845
- then " caml_curry" ^ Int. to_string n
846
- else " caml_tuplify" ^ Int. to_string (- n)
852
+ let curry_function_sym ar =
853
+ Compilenv. need_curry_fun ar;
854
+ match ar with
855
+ | Lambda. Curried {nlocal} , n ->
856
+ " caml_curry" ^ Int. to_string n ^
857
+ (if nlocal > 0 then " L" ^ Int. to_string nlocal else " " )
858
+ | Lambda. Tupled , n ->
859
+ " caml_tuplify" ^ Int. to_string n
847
860
848
861
(* Big arrays *)
849
862
@@ -1969,7 +1982,7 @@ let tuplify_function arity =
1969
1982
*)
1970
1983
1971
1984
let max_arity_optimized = 15
1972
- let final_curry_function arity =
1985
+ let final_curry_function ~ nlocal ~ arity =
1973
1986
let dbg = placeholder_dbg in
1974
1987
let last_arg = V. create_local " arg" in
1975
1988
let last_clos = V. create_local " clos" in
@@ -1998,7 +2011,9 @@ let final_curry_function arity =
1998
2011
newclos (n-1 ))
1999
2012
end in
2000
2013
let fun_name =
2001
- " caml_curry" ^ Int. to_string arity ^ " _" ^ Int. to_string (arity-1 )
2014
+ " caml_curry" ^ Int. to_string arity
2015
+ ^ (if nlocal > 0 then " L" ^ Int. to_string nlocal else " " )
2016
+ ^ " _" ^ Int. to_string (arity-1 )
2002
2017
in
2003
2018
let fun_dbg = placeholder_fun_dbg ~human_name: fun_name in
2004
2019
Cfunction
@@ -2009,34 +2024,38 @@ let final_curry_function arity =
2009
2024
fun_dbg;
2010
2025
}
2011
2026
2012
- let rec intermediate_curry_functions arity num =
2027
+ let rec intermediate_curry_functions ~ nlocal ~ arity num =
2013
2028
let dbg = placeholder_dbg in
2014
2029
if num = arity - 1 then
2015
- [final_curry_function arity]
2030
+ [final_curry_function ~nlocal ~ arity ]
2016
2031
else begin
2017
- let name1 = " caml_curry" ^ Int. to_string arity in
2032
+ let name1 = " caml_curry" ^ Int. to_string arity
2033
+ ^ (if nlocal > 0 then " L" ^ Int. to_string nlocal else " " ) in
2018
2034
let name2 = if num = 0 then name1 else name1 ^ " _" ^ Int. to_string num in
2019
2035
let arg = V. create_local " arg" and clos = V. create_local " clos" in
2020
2036
let fun_dbg = placeholder_fun_dbg ~human_name: name2 in
2037
+ let mode : Lambda.alloc_mode =
2038
+ if num > = arity - nlocal then Alloc_local else Alloc_heap in
2039
+ let curried n : Clambda.arity = (Curried {nlocal= min nlocal n}, n) in
2021
2040
Cfunction
2022
2041
{fun_name = name2;
2023
2042
fun_args = [VP. create arg, typ_val; VP. create clos, typ_val];
2024
2043
fun_body =
2025
2044
if arity - num > 2 && arity < = max_arity_optimized then
2026
- Cop (Calloc Alloc_heap ,
2027
- [alloc_closure_header 5 (dbg () );
2045
+ Cop (Calloc mode ,
2046
+ [alloc_closure_header ~mode 5 (dbg () );
2028
2047
Cconst_symbol (name1 ^ " _" ^ Int. to_string (num+ 1 ), dbg () );
2029
- alloc_closure_info ~arity: (arity - num - 1 )
2048
+ alloc_closure_info ~arity: (curried ( arity - num - 1 ) )
2030
2049
~startenv: 3 (dbg () );
2031
2050
Cconst_symbol (name1 ^ " _" ^ Int. to_string (num+ 1 ) ^ " _app" ,
2032
2051
dbg () );
2033
2052
Cvar arg; Cvar clos],
2034
2053
dbg () )
2035
2054
else
2036
- Cop (Calloc Alloc_heap ,
2037
- [alloc_closure_header 4 (dbg () );
2055
+ Cop (Calloc mode ,
2056
+ [alloc_closure_header ~mode 4 (dbg () );
2038
2057
Cconst_symbol (name1 ^ " _" ^ Int. to_string (num+ 1 ), dbg () );
2039
- alloc_closure_info ~arity: 1 ~startenv: 2 (dbg () );
2058
+ alloc_closure_info ~arity: (curried 1 ) ~startenv: 2 (dbg () );
2040
2059
Cvar arg; Cvar clos],
2041
2060
dbg () );
2042
2061
fun_codegen_options = [] ;
@@ -2082,19 +2101,21 @@ let rec intermediate_curry_functions arity num =
2082
2101
fun_dbg;
2083
2102
}
2084
2103
in
2085
- cf :: intermediate_curry_functions arity (num+ 1 )
2104
+ cf :: intermediate_curry_functions ~nlocal ~ arity (num+ 1 )
2086
2105
else
2087
- intermediate_curry_functions arity (num+ 1 ))
2106
+ intermediate_curry_functions ~nlocal ~ arity (num+ 1 ))
2088
2107
end
2089
2108
2090
- let curry_function arity =
2091
- assert (arity <> 0 );
2092
- (* Functions with arity = 0 does not have a curry_function *)
2093
- if arity > 0
2094
- then intermediate_curry_functions arity 0
2095
- else [tuplify_function ( - arity)]
2109
+ let curry_function = function
2110
+ | Lambda. Tupled , n ->
2111
+ assert (n > 0 ); [tuplify_function n]
2112
+ | Lambda. Curried {nlocal} , n ->
2113
+ assert (n > 0 );
2114
+ intermediate_curry_functions ~nlocal ~ arity: n 0
2096
2115
2097
2116
module Int = Numbers. Int
2117
+ module AritySet =
2118
+ Set. Make (struct type t = Clambda. arity let compare = compare end )
2098
2119
2099
2120
let default_apply = Int.Set. add 2 (Int.Set. add 3 Int.Set. empty)
2100
2121
(* These apply funs are always present in the main program because
@@ -2106,13 +2127,13 @@ let generic_functions shared units =
2106
2127
(fun (apply ,send ,curry ) (ui : Cmx_format.unit_infos ) ->
2107
2128
List. fold_right Int.Set. add ui.ui_apply_fun apply,
2108
2129
List. fold_right Int.Set. add ui.ui_send_fun send,
2109
- List. fold_right Int.Set . add ui.ui_curry_fun curry)
2110
- (Int.Set. empty,Int.Set. empty,Int.Set . empty)
2130
+ List. fold_right AritySet . add ui.ui_curry_fun curry)
2131
+ (Int.Set. empty,Int.Set. empty,AritySet . empty)
2111
2132
units in
2112
2133
let apply = if shared then apply else Int.Set. union apply default_apply in
2113
2134
let accu = Int.Set. fold (fun n accu -> apply_function n :: accu) apply [] in
2114
2135
let accu = Int.Set. fold (fun n accu -> send_function n :: accu) send accu in
2115
- Int.Set. fold (fun n accu -> curry_function n @ accu) curry accu
2136
+ AritySet. fold (fun arity accu -> curry_function arity @ accu) curry accu
2116
2137
2117
2138
(* Primitives *)
2118
2139
@@ -2713,7 +2734,7 @@ let fundecls_size fundecls =
2713
2734
(fun (f : Clambda.ufunction ) ->
2714
2735
let indirect_call_code_pointer_size =
2715
2736
match f.arity with
2716
- | 0 | 1 -> 0
2737
+ | Curried _ , ( 0 | 1 ) -> 0
2717
2738
(* arity 1 does not need an indirect call handler.
2718
2739
arity 0 cannot be indirect called *)
2719
2740
| _ -> 1
@@ -2746,30 +2767,32 @@ let emit_constant_closure ((_, global_symb) as symb) fundecls clos_vars cont =
2746
2767
let rec emit_others pos = function
2747
2768
[] -> clos_vars @ cont
2748
2769
| (f2 : Clambda.ufunction ) :: rem ->
2749
- if f2.arity = 1 || f2.arity = 0 then
2770
+ match f2.arity with
2771
+ | Curried _ , (0 |1 ) as arity ->
2750
2772
Cint (infix_header pos) ::
2751
2773
(closure_symbol f2) @
2752
2774
Csymbol_address f2.label ::
2753
- Cint (closure_info ~arity: f2.arity ~startenv: (startenv - pos)) ::
2775
+ Cint (closure_info ~arity ~startenv: (startenv - pos)) ::
2754
2776
emit_others (pos + 3 ) rem
2755
- else
2777
+ | arity ->
2756
2778
Cint (infix_header pos) ::
2757
2779
(closure_symbol f2) @
2758
2780
Csymbol_address (curry_function_sym f2.arity) ::
2759
- Cint (closure_info ~arity: f2.arity ~startenv: (startenv - pos)) ::
2781
+ Cint (closure_info ~arity ~startenv: (startenv - pos)) ::
2760
2782
Csymbol_address f2.label ::
2761
2783
emit_others (pos + 4 ) rem in
2762
2784
Cint (black_closure_header (fundecls_size fundecls
2763
2785
+ List. length clos_vars)) ::
2764
2786
cdefine_symbol symb @
2765
2787
(closure_symbol f1) @
2766
- if f1.arity = 1 || f1.arity = 0 then
2788
+ match f1.arity with
2789
+ | Curried _ , (0 |1 ) as arity ->
2767
2790
Csymbol_address f1.label ::
2768
- Cint (closure_info ~arity: f1.arity ~startenv ) ::
2791
+ Cint (closure_info ~arity ~startenv ) ::
2769
2792
emit_others 3 remainder
2770
- else
2793
+ | arity ->
2771
2794
Csymbol_address (curry_function_sym f1.arity) ::
2772
- Cint (closure_info ~arity: f1.arity ~startenv ) ::
2795
+ Cint (closure_info ~arity ~startenv ) ::
2773
2796
Csymbol_address f1.label ::
2774
2797
emit_others 4 remainder
2775
2798
0 commit comments