Skip to content

Commit 7ea7f35

Browse files
lthlsgasche
authored andcommitted
Closure: linear computation of closure environments
1 parent 4c599fd commit 7ea7f35

File tree

1 file changed

+46
-18
lines changed

1 file changed

+46
-18
lines changed

middle_end/closure/closure.ml

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,6 @@ let rec split_list n l =
5050
| a::l -> let (l1, l2) = split_list (n-1) l in (a::l1, l2)
5151
end
5252

53-
let rec build_closure_env env_param pos = function
54-
[] -> V.Map.empty
55-
| id :: rem ->
56-
V.Map.add id
57-
(Uprim(P.Pfield(pos, Pointer, Immutable),
58-
[Uvar env_param], Debuginfo.none))
59-
(build_closure_env env_param (pos+1) rem)
60-
6153
(* Auxiliary for accessing globals. We change the name of the global
6254
to the name of the corresponding asm symbol. This is done here
6355
and no longer in Cmmgen so that approximations stored in .cmx files
@@ -703,9 +695,21 @@ let rec substitute loc ((backend, fpc) as st) sb rn ulam =
703695
| Uunreachable ->
704696
Uunreachable
705697

698+
type closure_entry =
699+
| Free_variable of int
700+
| Function of int
701+
702+
type closure_env =
703+
| Not_in_closure
704+
| In_closure of {
705+
entries: closure_entry V.Map.t;
706+
env_param: V.t;
707+
env_pos: int;
708+
}
709+
706710
type env = {
707711
backend : (module Backend_intf.S);
708-
cenv : ulambda V.Map.t;
712+
cenv : closure_env;
709713
fenv : value_approximation V.Map.t;
710714
mutable_vars : V.Set.t;
711715
}
@@ -884,8 +888,19 @@ let close_approx_var { fenv; cenv } id =
884888
match approx with
885889
Value_const c -> make_const c
886890
| approx ->
887-
let subst = try V.Map.find id cenv with Not_found -> Uvar id in
888-
(subst, approx)
891+
match cenv with
892+
| Not_in_closure -> Uvar id, approx
893+
| In_closure { entries; env_param; env_pos } ->
894+
let subst =
895+
match V.Map.find id entries with
896+
| Free_variable fv_pos ->
897+
Uprim(P.Pfield(fv_pos - env_pos, Pointer, Immutable),
898+
[Uvar env_param], Debuginfo.none)
899+
| Function fun_pos ->
900+
Uoffset(Uvar env_param, fun_pos - env_pos)
901+
| exception Not_found -> Uvar id
902+
in
903+
(subst, approx)
889904

890905
let close_var env id =
891906
let (ulam, _app) = close_approx_var env id in ulam
@@ -1292,16 +1307,29 @@ and close_functions { backend; fenv; cenv; mutable_vars } fun_defs =
12921307
(* This reference will be set to false if the hypothesis that a function
12931308
does not use its environment parameter is invalidated. *)
12941309
let useless_env = ref initially_closed in
1310+
let cenv_entries =
1311+
let rec free_variables_entries fv_pos = function
1312+
[] -> V.Map.empty
1313+
| id :: rem ->
1314+
V.Map.add id (Free_variable fv_pos)
1315+
(free_variables_entries (fv_pos+1) rem)
1316+
in
1317+
let entries_fv = free_variables_entries fv_pos fv in
1318+
List.fold_right2
1319+
(fun (id, _params, _return, _body, _fundesc, _dbg) pos env ->
1320+
V.Map.add id (Function pos) env)
1321+
uncurried_defs clos_offsets entries_fv
1322+
in
12951323
(* Translate each function definition *)
12961324
let clos_fundef (id, params, return, body, fundesc, dbg) env_pos =
12971325
let env_param = V.create_local "env" in
1298-
let cenv_fv =
1299-
build_closure_env env_param (fv_pos - env_pos) fv in
13001326
let cenv_body =
1301-
List.fold_right2
1302-
(fun (id, _params, _return, _body, _fundesc, _dbg) pos env ->
1303-
V.Map.add id (Uoffset(Uvar env_param, pos - env_pos)) env)
1304-
uncurried_defs clos_offsets cenv_fv in
1327+
In_closure {
1328+
entries = cenv_entries;
1329+
env_param;
1330+
env_pos;
1331+
}
1332+
in
13051333
let (ubody, approx) =
13061334
close { backend; fenv = fenv_rec; cenv = cenv_body; mutable_vars } body
13071335
in
@@ -1510,7 +1538,7 @@ let intro ~backend ~size lam =
15101538
Compilenv.set_global_approx(Value_tuple !global_approx);
15111539
let (ulam, _approx) =
15121540
close { backend; fenv = V.Map.empty;
1513-
cenv = V.Map.empty; mutable_vars = V.Set.empty } lam
1541+
cenv = Not_in_closure; mutable_vars = V.Set.empty } lam
15141542
in
15151543
let opaque =
15161544
!Clflags.opaque

0 commit comments

Comments
 (0)