Skip to content

Commit dbf69ef

Browse files
committed
Global roots fix (ocaml#38)
1 parent f3ce1a8 commit dbf69ef

File tree

1 file changed

+45
-14
lines changed

1 file changed

+45
-14
lines changed

middle_end/flambda2.0/to_cmm/un_cps.ml

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,14 @@ module R = struct
5454
init : Cmm.expression;
5555
current_data : Cmm.data_item list;
5656
other_data : Cmm.data_item list list;
57+
gc_roots : Symbol.t list;
5758
}
5859

5960
let empty = {
6061
init = C.void;
6162
current_data = [];
6263
other_data = [];
64+
gc_roots = [];
6365
}
6466

6567
let add_if_not_empty x l =
@@ -74,8 +76,13 @@ module R = struct
7476
add_if_not_empty r.current_data (
7577
add_if_not_empty t.current_data (
7678
(r.other_data @ t.other_data)));
79+
gc_roots = r.gc_roots @ t.gc_roots;
7780
}
7881

82+
let archive_data r =
83+
{ r with current_data = [];
84+
other_data = add_if_not_empty r.current_data r.other_data; }
85+
7986
let wrap_init f r =
8087
{ r with init = f r.init; }
8188

@@ -85,6 +92,9 @@ module R = struct
8592
let update_data f r =
8693
{ r with current_data = f r.current_data; }
8794

95+
let add_gc_roots l r =
96+
{ r with gc_roots = l @ r.gc_roots; }
97+
8898
let to_cmm r =
8999
let entry =
90100
let dbg = Debuginfo.none in
@@ -101,7 +111,7 @@ module R = struct
101111
in
102112
let data_list = add_if_not_empty r.current_data r.other_data in
103113
let data = List.map C.cdata data_list in
104-
data, entry
114+
data, entry, r.gc_roots
105115

106116
end
107117

@@ -1342,18 +1352,34 @@ let static_structure_item env r
13421352
R.update_data data r
13431353
end
13441354

1345-
let static_structure env s =
1346-
List.fold_left (static_structure_item env) R.empty s
1355+
let static_structure env is_fully_static s =
1356+
(* Gc roots: statically allocated blocks themselves do not need to be scanned,
1357+
however if statically allocated blocks contain dynamically allocated contents,
1358+
then that block has to be registered as Gc roots for the Gc to correctly patch
1359+
it if/when it moves some of the dynamically allocated blocks. As a safe
1360+
over-approximation, we thus register as gc_roots all symbols who have an
1361+
associated computation (and thus are not fully_static). *)
1362+
let roots =
1363+
if is_fully_static then []
1364+
else Symbol.Set.elements
1365+
(Flambda_static.Program_body.Static_structure.being_defined s)
1366+
in
1367+
let r = R.add_gc_roots roots R.empty in
1368+
List.fold_left (fun acc item ->
1369+
(* Archive_data helps keep definitions of separate symbols in different
1370+
data_item lists and this increases readability of the generated cmm. *)
1371+
R.archive_data (static_structure_item env acc item)
1372+
) r s
13471373

13481374
(* Definition *)
13491375

13501376
let computation_wrapper offsets used_closure_vars c =
13511377
match c with
13521378
| None ->
1353-
Env.dummy offsets used_closure_vars, (fun x -> x)
1379+
Env.dummy offsets used_closure_vars, (fun x -> x), true
13541380
| Some (c : Flambda_static.Program_body.Computation.t) ->
13551381
(* The env for the computation is given a dummy continuation,
1356-
since the return continuation will be explictly bound to a
1382+
since the return continuation will be explicitly bound to a
13571383
jump before translating the computation. *)
13581384
let dummy_k = Continuation.create () in
13591385
let k_exn = Exn_continuation.exn_handler c.exn_continuation in
@@ -1383,14 +1409,14 @@ let computation_wrapper offsets used_closure_vars c =
13831409
code to move assignments closer to the variable definitions
13841410
Or better: add traps to the env to insert assignemnts after
13851411
the variable definitions. *)
1386-
s_env, wrap
1412+
s_env, wrap, false
13871413

13881414
let definition offsets ~used_closure_vars
13891415
(d : Flambda_static.Program_body.Definition.t) =
1390-
let env, wrapper =
1416+
let env, wrapper, is_fully_static =
13911417
computation_wrapper offsets used_closure_vars d.computation
13921418
in
1393-
let r = static_structure env d.static_structure in
1419+
let r = static_structure env is_fully_static d.static_structure in
13941420
R.wrap_init wrapper r
13951421

13961422

@@ -1401,7 +1427,7 @@ let is_var_used v e =
14011427
let occurrence = Name_occurrences.greatest_name_mode_var free_names v in
14021428
match (occurrence : Name_mode.Or_absent.t) with
14031429
| Absent -> false
1404-
| Present _k ->
1430+
| Present _k ->
14051431
(* CR mshinwell: I think this should always be [true]. Even if the
14061432
variable is only used by phantom bindings, it still needs to be
14071433
there. This may only arise in unusual cases (e.g. [my_closure]
@@ -1468,8 +1494,12 @@ let function_decl offsets used_closure_vars fun_name _ d =
14681494

14691495
let rec program_body offsets ~used_closure_vars acc body =
14701496
match Flambda_static.Program_body.descr body with
1471-
| Flambda_static.Program_body.Root sym ->
1472-
sym, List.fold_left (fun acc r -> R.combine r acc) R.empty acc
1497+
| Flambda_static.Program_body.Root _sym ->
1498+
(* The root symbol does not really deserve any particular treatment.
1499+
Concerning gc_roots, it's like any other statically allocated symbol:
1500+
if if has an associated computation, then it will already be included
1501+
in the list of gc_roots, else it does not *have* to be a root. *)
1502+
List.fold_left (fun acc r -> R.combine r acc) R.empty acc
14731503
| Flambda_static.Program_body.Define_symbol (def, rest) ->
14741504
let r = definition offsets ~used_closure_vars def in
14751505
program_body offsets ~used_closure_vars (r :: acc) rest
@@ -1492,9 +1522,10 @@ let program (p : Flambda_static.Program.t) =
14921522
Name_occurrences.closure_vars (Flambda_static.Program.free_names p)
14931523
in
14941524
let functions = program_functions offsets used_closure_vars p in
1495-
let sym, res = program_body ~used_closure_vars offsets [] p.body in
1496-
let data, entry = R.to_cmm res in
1525+
let res = program_body ~used_closure_vars offsets [] p.body in
1526+
let data, entry, gc_roots = R.to_cmm res in
14971527
let cmm_data = C.flush_cmmgen_state () in
1498-
(C.gc_root_table [symbol sym]) :: data @ cmm_data @ functions @ [entry]
1528+
let roots = List.map symbol gc_roots in
1529+
(C.gc_root_table roots) :: data @ cmm_data @ functions @ [entry]
14991530
)
15001531

0 commit comments

Comments
 (0)