@@ -807,12 +807,16 @@ let lookup_label obj lab dbg =
807
807
let table = Cop (Cload (Word_val , Mutable ), [obj], dbg) in
808
808
addr_array_ref table lab dbg)
809
809
810
- let call_cached_method obj tag cache pos args apos dbg =
810
+ let send_function_name n (mode : Lambda.alloc_mode ) =
811
+ let suff = match mode with Alloc_heap -> " " | Alloc_local -> " L" in
812
+ " caml_send" ^ Int. to_string n ^ suff
813
+
814
+ let call_cached_method obj tag cache pos args (apos ,mode ) dbg =
811
815
let arity = List. length args in
812
816
let cache = array_indexing log2_size_addr cache pos dbg in
813
- Compilenv. need_send_fun arity;
817
+ Compilenv. need_send_fun arity mode ;
814
818
Cop (Capply (typ_val, apos),
815
- Cconst_symbol (" caml_send " ^ Int. to_string arity, dbg) ::
819
+ Cconst_symbol (send_function_name arity mode , dbg) ::
816
820
obj :: tag :: cache :: args,
817
821
dbg)
818
822
@@ -859,10 +863,13 @@ let make_checkbound dbg = function
859
863
Cop (Ccheckbound , args, dbg)
860
864
861
865
(* Record application and currying functions *)
862
-
863
- let apply_function_sym n =
866
+ let apply_function_name (n , (mode : Lambda.alloc_mode )) =
867
+ let suff = match mode with Alloc_heap -> " " | Alloc_local -> " L" in
868
+ " caml_apply" ^ Int. to_string n ^ suff
869
+ let apply_function_sym n mode =
864
870
assert (n > 0 );
865
- Compilenv. need_apply_fun n; " caml_apply" ^ Int. to_string n
871
+ Compilenv. need_apply_fun n mode;
872
+ apply_function_name (n, mode)
866
873
let curry_function_sym ar =
867
874
Compilenv. need_curry_fun ar;
868
875
match ar with
@@ -1713,10 +1720,10 @@ let ptr_offset ptr offset dbg =
1713
1720
then ptr
1714
1721
else Cop (Caddv , [ptr; Cconst_int (offset * size_addr, dbg)], dbg)
1715
1722
1716
- let direct_apply lbl args pos dbg =
1723
+ let direct_apply lbl args ( pos , _mode ) dbg =
1717
1724
Cop (Capply (typ_val, pos), Cconst_symbol (lbl, dbg) :: args, dbg)
1718
1725
1719
- let generic_apply mut clos args pos dbg =
1726
+ let generic_apply mut clos args ( pos , mode ) dbg =
1720
1727
match args with
1721
1728
| [arg] ->
1722
1729
bind " fun" clos (fun clos ->
@@ -1725,23 +1732,23 @@ let generic_apply mut clos args pos dbg =
1725
1732
| _ ->
1726
1733
let arity = List. length args in
1727
1734
let cargs =
1728
- Cconst_symbol (apply_function_sym arity, dbg) :: args @ [clos]
1735
+ Cconst_symbol (apply_function_sym arity mode , dbg) :: args @ [clos]
1729
1736
in
1730
1737
Cop (Capply (typ_val, pos), cargs, dbg)
1731
1738
1732
- let send kind met obj args apos dbg =
1739
+ let send kind met obj args akind dbg =
1733
1740
let call_met obj args clos =
1734
1741
(* met is never a simple expression, so it never gets turned into an
1735
1742
Immutable load *)
1736
- generic_apply Asttypes. Mutable clos (obj :: args) apos dbg
1743
+ generic_apply Asttypes. Mutable clos (obj :: args) akind dbg
1737
1744
in
1738
1745
bind " obj" obj (fun obj ->
1739
1746
match (kind : Lambda.meth_kind ), args with
1740
1747
Self , _ ->
1741
1748
bind " met" (lookup_label obj met dbg)
1742
1749
(call_met obj args)
1743
1750
| Cached , cache :: pos :: args ->
1744
- call_cached_method obj met cache pos args apos dbg
1751
+ call_cached_method obj met cache pos args akind dbg
1745
1752
| _ ->
1746
1753
bind " met" (lookup_tag obj met dbg)
1747
1754
(call_met obj args))
@@ -1807,23 +1814,51 @@ let cache_public_method meths tag cache dbg =
1807
1814
Csequence (Cop (Cstore (Word_int , Assignment ), [cache; Cvar tagged], dbg),
1808
1815
Cvar tagged)))))
1809
1816
1810
- let region e =
1811
- (* [Cregion e] is equivalent to [e] if [e] contains no local allocs *)
1812
- let rec check_local_allocs = function
1813
- | Cregion _ ->
1814
- (* Local allocations within a nested region do not affect this region.
1815
- Note this prevents O(n^2) behaviour with many nested regions. *)
1816
- ()
1817
+ let has_local_allocs e =
1818
+ let rec loop = function
1819
+ | Cregion e ->
1820
+ (* Local allocations within a nested region do not affect this region,
1821
+ except inside a Ctail block *)
1822
+ loop_until_tail e
1817
1823
| Cop (Calloc Alloc_local , _, _)
1818
1824
| Cop ((Cextcall _ | Capply _ ), _ , _ ) ->
1819
- raise Exit
1825
+ raise Exit
1826
+ | e ->
1827
+ iter_shallow loop e
1828
+ and loop_until_tail = function
1829
+ | Ctail e -> loop e
1830
+ | Cregion _ -> ()
1831
+ | e -> ignore (iter_shallow_tail loop_until_tail e)
1832
+ in
1833
+ match loop e with
1834
+ | () -> false
1835
+ | exception Exit -> true
1836
+
1837
+ let remove_region_tail e =
1838
+ let rec has_tail = function
1839
+ | Ctail _
1840
+ | Cop (Capply(_ , Apply_tail), _ , _ ) -> raise Exit
1841
+ | Cregion _ -> ()
1842
+ | e -> ignore (iter_shallow_tail has_tail e)
1843
+ in
1844
+ let rec remove_tail = function
1845
+ | Ctail e -> e
1846
+ | Cop (Capply(mach , Apply_tail), args , dbg ) ->
1847
+ Cop (Capply (mach, Apply_nontail ), args, dbg)
1848
+ | Cregion _ as e -> e
1820
1849
| e ->
1821
- iter_shallow check_local_allocs e
1850
+ map_shallow_tail remove_tail e
1822
1851
in
1823
- match check_local_allocs e with
1852
+ match has_tail e with
1824
1853
| () -> e
1825
- | exception Exit -> Cregion e
1854
+ | exception Exit -> remove_tail e
1826
1855
1856
+ let region e =
1857
+ (* [Cregion e] is equivalent to [e] if [e] contains no local allocs *)
1858
+ if has_local_allocs e then
1859
+ Cregion e
1860
+ else
1861
+ remove_region_tail e
1827
1862
1828
1863
(* CR mshinwell: These will be filled in by later pull requests. *)
1829
1864
let placeholder_dbg () = Debuginfo. none
@@ -1840,7 +1875,7 @@ let placeholder_fun_dbg ~human_name:_ = Debuginfo.none
1840
1875
(app closN-1.code aN closN-1))))
1841
1876
*)
1842
1877
1843
- let apply_function_body arity =
1878
+ let apply_function_body ( arity , ( mode : Lambda.alloc_mode )) =
1844
1879
let dbg = placeholder_dbg in
1845
1880
let arg = Array. make arity (V. create_local " arg" ) in
1846
1881
for i = 1 to arity - 1 do arg.(i) < - V. create_local " arg" done ;
@@ -1875,13 +1910,15 @@ let apply_function_body arity =
1875
1910
:: List. map (fun s -> Cvar s) all_args,
1876
1911
dbg () ),
1877
1912
dbg () ,
1878
- app_fun clos 0 ,
1913
+ (match mode with
1914
+ | Alloc_heap -> Cregion (app_fun clos 0 )
1915
+ | Alloc_local -> app_fun clos 0 ),
1879
1916
dbg () ))
1880
1917
1881
- let send_function arity =
1918
+ let send_function ( arity , mode ) =
1882
1919
let dbg = placeholder_dbg in
1883
1920
let cconst_int i = Cconst_int (i, dbg () ) in
1884
- let (args, clos', body) = apply_function_body (1 + arity) in
1921
+ let (args, clos', body) = apply_function_body (1 + arity, mode ) in
1885
1922
let cache = V. create_local " cache"
1886
1923
and obj = List. hd args
1887
1924
and tag = V. create_local " tag" in
@@ -1915,7 +1952,7 @@ let send_function arity =
1915
1952
in
1916
1953
let body = Clet (VP. create clos', clos, body) in
1917
1954
let cache = cache in
1918
- let fun_name = " caml_send " ^ Int. to_string arity in
1955
+ let fun_name = send_function_name arity mode in
1919
1956
let fun_args =
1920
1957
[obj, typ_val; tag, typ_int; cache, typ_val]
1921
1958
@ List. map (fun id -> (id, typ_val)) (List. tl args) in
@@ -1931,7 +1968,7 @@ let send_function arity =
1931
1968
let apply_function arity =
1932
1969
let (args, clos, body) = apply_function_body arity in
1933
1970
let all_args = args @ [clos] in
1934
- let fun_name = " caml_apply " ^ Int. to_string arity in
1971
+ let fun_name = apply_function_name arity in
1935
1972
let fun_dbg = placeholder_fun_dbg ~human_name: fun_name in
1936
1973
Cfunction
1937
1974
{fun_name;
@@ -2129,26 +2166,27 @@ let curry_function = function
2129
2166
assert (n > 0 );
2130
2167
intermediate_curry_functions ~nlocal ~arity: n 0
2131
2168
2132
- module Int = Numbers. Int
2169
+ module ApplyFnSet =
2170
+ Set. Make (struct type t = int * Lambda. alloc_mode let compare = compare end )
2133
2171
module AritySet =
2134
2172
Set. Make (struct type t = Clambda. arity let compare = compare end )
2135
2173
2136
- let default_apply = Int.Set. add 2 ( Int.Set. add 3 Int.Set. empty)
2174
+ let default_apply = ApplyFnSet. of_list [ 2 , Alloc_heap ; 3 , Alloc_heap ]
2137
2175
(* These apply funs are always present in the main program because
2138
2176
the run-time system needs them (cf. runtime/<arch>.S) . *)
2139
2177
2140
2178
let generic_functions shared units =
2141
2179
let (apply,send,curry) =
2142
2180
List. fold_left
2143
2181
(fun (apply ,send ,curry ) (ui : Cmx_format.unit_infos ) ->
2144
- List. fold_right Int.Set . add ui.ui_apply_fun apply,
2145
- List. fold_right Int.Set . add ui.ui_send_fun send,
2182
+ List. fold_right ApplyFnSet . add ui.ui_apply_fun apply,
2183
+ List. fold_right ApplyFnSet . add ui.ui_send_fun send,
2146
2184
List. fold_right AritySet. add ui.ui_curry_fun curry)
2147
- (Int.Set. empty,Int.Set . empty,AritySet. empty)
2185
+ (ApplyFnSet. empty,ApplyFnSet . empty,AritySet. empty)
2148
2186
units in
2149
- let apply = if shared then apply else Int.Set . union apply default_apply in
2150
- let accu = Int.Set. fold (fun n accu -> apply_function n :: accu) apply [] in
2151
- let accu = Int.Set. fold (fun n accu -> send_function n :: accu) send accu in
2187
+ let apply = if shared then apply else ApplyFnSet . union apply default_apply in
2188
+ let accu = ApplyFnSet. fold (fun nr accu -> apply_function nr :: accu) apply [] in
2189
+ let accu = ApplyFnSet. fold (fun nr accu -> send_function nr :: accu) send accu in
2152
2190
AritySet. fold (fun arity accu -> curry_function arity @ accu) curry accu
2153
2191
2154
2192
(* Primitives *)
0 commit comments