@@ -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
106116end
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
13501376let 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
13881414let 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
14691495let 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