Skip to content

Commit f86814f

Browse files
authored
Compiler: track block mutability (#1603)
1 parent b734348 commit f86814f

14 files changed

+99
-54
lines changed

compiler/lib/code.ml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -333,13 +333,17 @@ type special =
333333
| Undefined
334334
| Alias_prim of string
335335

336+
type mutability =
337+
| Immutable
338+
| Maybe_mutable
339+
336340
type expr =
337341
| Apply of
338342
{ f : Var.t
339343
; args : Var.t list
340344
; exact : bool
341345
}
342-
| Block of int * Var.t array * array_or_not
346+
| Block of int * Var.t array * array_or_not * mutability
343347
| Field of Var.t * int
344348
| Closure of Var.t list * cont
345349
| Constant of constant
@@ -479,8 +483,14 @@ module Print = struct
479483
if exact
480484
then Format.fprintf f "%a!(%a)" Var.print g var_list args
481485
else Format.fprintf f "%a(%a)" Var.print g var_list args
482-
| Block (t, a, _) ->
483-
Format.fprintf f "{tag=%d" t;
486+
| Block (t, a, _, mut) ->
487+
Format.fprintf
488+
f
489+
"%s{tag=%d"
490+
(match mut with
491+
| Immutable -> "imm"
492+
| Maybe_mutable -> "")
493+
t;
484494
for i = 0 to Array.length a - 1 do
485495
Format.fprintf f "; %d = %a" i Var.print a.(i)
486496
done;
@@ -732,7 +742,7 @@ let invariant { blocks; start; _ } =
732742
in
733743
let check_expr = function
734744
| Apply _ -> ()
735-
| Block (_, _, _) -> ()
745+
| Block (_, _, _, _) -> ()
736746
| Field (_, _) -> ()
737747
| Closure (l, cont) ->
738748
List.iter l ~f:define;

compiler/lib/code.mli

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,17 @@ type special =
180180
| Undefined
181181
| Alias_prim of string
182182

183+
type mutability =
184+
| Immutable
185+
| Maybe_mutable
186+
183187
type expr =
184188
| Apply of
185189
{ f : Var.t
186190
; args : Var.t list
187191
; exact : bool (* if true, then # of arguments = # of parameters *)
188192
}
189-
| Block of int * Var.t array * array_or_not
193+
| Block of int * Var.t array * array_or_not * mutability
190194
| Field of Var.t * int
191195
| Closure of Var.t list * cont
192196
| Constant of constant

compiler/lib/deadcode.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ and mark_expr st e =
7070
| Apply { f; args; _ } ->
7171
mark_var st f;
7272
List.iter args ~f:(fun x -> mark_var st x)
73-
| Block (_, a, _) -> Array.iter a ~f:(fun x -> mark_var st x)
73+
| Block (_, a, _, _) -> Array.iter a ~f:(fun x -> mark_var st x)
7474
| Field (x, _) -> mark_var st x
7575
| Closure (_, (pc, _)) -> mark_reachable st pc
7676
| Special _ -> ()

compiler/lib/duplicate.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ let expr s e =
2626
| Constant _ -> e
2727
| Apply { f; args; exact } ->
2828
Apply { f = s f; args = List.map args ~f:(fun x -> s x); exact }
29-
| Block (n, a, k) -> Block (n, Array.map a ~f:(fun x -> s x), k)
29+
| Block (n, a, k, mut) -> Block (n, Array.map a ~f:(fun x -> s x), k, mut)
3030
| Field (x, n) -> Field (s x, n)
3131
| Closure _ -> failwith "Inlining/Duplicating closure is currenly not supported"
3232
| Special x -> Special x

compiler/lib/eval.ml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ let is_int info x =
177177
(fun x ->
178178
match Flow.Info.def info x with
179179
| Some (Constant (Int _)) -> Y
180-
| Some (Block (_, _, _) | Constant _) -> N
180+
| Some (Block (_, _, _, _) | Constant _) -> N
181181
| None | Some _ -> Unknown)
182182
Unknown
183183
(fun u v ->
@@ -196,8 +196,12 @@ let the_tag_of info x get =
196196
info
197197
(fun x ->
198198
match Flow.Info.def info x with
199-
| Some (Block (j, _, _)) ->
200-
if Flow.Info.possibly_mutable info x then None else get j
199+
| Some (Block (j, _, _, mut)) ->
200+
if Flow.Info.possibly_mutable info x
201+
then (
202+
assert (Poly.(mut = Maybe_mutable));
203+
None)
204+
else get j
201205
| Some (Constant (Tuple (j, _, _))) -> get j
202206
| None | Some _ -> None)
203207
None
@@ -278,7 +282,7 @@ let eval_instr info ((x, loc) as i) =
278282
| Let (x, Prim (Extern "caml_sys_const_backend_type", [ _ ])) ->
279283
let jsoo = Code.Var.fresh () in
280284
[ Let (jsoo, Constant (String "js_of_ocaml")), noloc
281-
; Let (x, Block (0, [| jsoo |], NotArray)), loc
285+
; Let (x, Block (0, [| jsoo |], NotArray, Immutable)), loc
282286
]
283287
| Let (_, Prim (Extern ("%resume" | "%perform" | "%reperform"), _)) ->
284288
[ i ] (* We need that the arguments to this primitives remain variables *)
@@ -338,7 +342,7 @@ let the_cond_of info x =
338342
| NativeString _
339343
| Float_array _
340344
| Int64 _ )) -> Non_zero
341-
| Some (Block (_, _, _)) -> Non_zero
345+
| Some (Block (_, _, _, _)) -> Non_zero
342346
| Some (Field _ | Closure _ | Prim _ | Apply _ | Special _) -> Unknown
343347
| None -> Unknown)
344348
Unknown
@@ -381,7 +385,7 @@ let rec do_not_raise pc visited blocks =
381385
| Array_set (_, _, _) | Offset_ref (_, _) | Set_field (_, _, _) | Assign _ -> ()
382386
| Let (_, e) -> (
383387
match e with
384-
| Block (_, _, _) | Field (_, _) | Constant _ | Closure _ -> ()
388+
| Block (_, _, _, _) | Field (_, _) | Constant _ | Closure _ -> ()
385389
| Apply _ -> raise May_raise
386390
| Special _ -> ()
387391
| Prim (Extern name, _) when Primitive.is_pure name -> ()

compiler/lib/flow.ml

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ let expr_deps blocks vars deps defs x e =
103103
| Closure (l, cont) ->
104104
List.iter l ~f:(fun x -> add_param_def vars defs x);
105105
cont_deps blocks vars deps defs cont
106-
| Block (_, a, _) -> Array.iter a ~f:(fun y -> add_dep deps x y)
106+
| Block (_, a, _, _) -> Array.iter a ~f:(fun y -> add_dep deps x y)
107107
| Field (y, _) -> add_dep deps x y
108108

109109
let program_deps { blocks; _ } =
@@ -152,7 +152,7 @@ let propagate1 deps defs st x =
152152
var_set_lift
153153
(fun z ->
154154
match defs.(Var.idx z) with
155-
| Expr (Block (_, a, _)) when n < Array.length a ->
155+
| Expr (Block (_, a, _, _)) when n < Array.length a ->
156156
let t = a.(n) in
157157
add_dep deps x t;
158158
Var.Tbl.get st t
@@ -194,7 +194,7 @@ let rec block_escape st x =
194194
Code.Var.ISet.add st.may_escape y;
195195
Code.Var.ISet.add st.possibly_mutable y;
196196
match st.defs.(Var.idx y) with
197-
| Expr (Block (_, l, _)) -> Array.iter l ~f:(fun z -> block_escape st z)
197+
| Expr (Block (_, l, _, _)) -> Array.iter l ~f:(fun z -> block_escape st z)
198198
| _ -> ()))
199199
(Var.Tbl.get st.known_origins x)
200200

@@ -226,15 +226,16 @@ let expr_escape st _x e =
226226
| Pv v, `Shallow_const -> (
227227
match st.defs.(Var.idx v) with
228228
| Expr (Constant (Tuple _)) -> ()
229-
| Expr (Block (_, a, _)) -> Array.iter a ~f:(fun x -> block_escape st x)
229+
| Expr (Block (_, a, _, _)) ->
230+
Array.iter a ~f:(fun x -> block_escape st x)
230231
| _ -> block_escape st v)
231232
| Pv v, `Object_literal -> (
232233
match st.defs.(Var.idx v) with
233234
| Expr (Constant (Tuple _)) -> ()
234-
| Expr (Block (_, a, _)) ->
235+
| Expr (Block (_, a, _, _)) ->
235236
Array.iter a ~f:(fun x ->
236237
match st.defs.(Var.idx x) with
237-
| Expr (Block (_, [| _k; v |], _)) -> block_escape st v
238+
| Expr (Block (_, [| _k; v |], _, _)) -> block_escape st v
238239
| Expr (Constant _) -> ()
239240
| _ -> block_escape st x)
240241
| _ -> block_escape st v)
@@ -282,7 +283,7 @@ let propagate2 ?(skip_param = false) defs known_origins possibly_mutable st x =
282283
|| Var.Set.exists
283284
(fun z ->
284285
match defs.(Var.idx z) with
285-
| Expr (Block (_, a, _)) ->
286+
| Expr (Block (_, a, _, _)) ->
286287
n >= Array.length a
287288
|| Var.ISet.mem possibly_mutable z
288289
|| Var.Tbl.get st a.(n)
@@ -382,7 +383,7 @@ let direct_approx (info : Info.t) x =
382383
then None
383384
else
384385
match info.info_defs.(Var.idx z) with
385-
| Expr (Block (_, a, _)) when n < Array.length a -> Some a.(n)
386+
| Expr (Block (_, a, _, _)) when n < Array.length a -> Some a.(n)
386387
| _ -> None)
387388
None
388389
(fun u v ->

compiler/lib/freevars.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ let iter_expr_free_vars f e =
3333
| Apply { f = x; args; _ } ->
3434
f x;
3535
List.iter ~f args
36-
| Block (_, a, _) -> Array.iter ~f a
36+
| Block (_, a, _, _) -> Array.iter ~f a
3737
| Field (x, _) -> f x
3838
| Closure _ -> ()
3939
| Special _ -> ()

compiler/lib/generate.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,7 @@ let rec translate_expr ctx queue loc x e level : _ * J.statement_list =
10421042
let prop = or_p prop prop' in
10431043
let e = apply_fun ctx f args exact cps loc in
10441044
(e, prop, queue), []
1045-
| Block (tag, a, array_or_not) ->
1045+
| Block (tag, a, array_or_not, _mut) ->
10461046
let contents, prop, queue =
10471047
List.fold_right
10481048
~f:(fun x (args, prop, queue) ->

compiler/lib/global_deadcode.ml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ let usages prog (global_info : Global_flow.info) : usage_kind Var.Map.t Var.Tbl.
126126
List.iter
127127
~f:(fun a -> if variable_may_escape a global_info then add_use Compute x a)
128128
args
129-
| Block (_, vars, _) -> Array.iter ~f:(add_use Compute x) vars
129+
| Block (_, vars, _, _) -> Array.iter ~f:(add_use Compute x) vars
130130
| Field (z, _) -> add_use Compute x z
131131
| Constant _ -> ()
132132
| Special _ -> ()
@@ -172,7 +172,7 @@ let expr_vars e =
172172
| Apply { f; args; _ } ->
173173
let vars = Var.Set.add f vars in
174174
List.fold_left ~f:(fun acc x -> Var.Set.add x acc) ~init:vars args
175-
| Block (_, params, _) ->
175+
| Block (_, params, _, _) ->
176176
Array.fold_left ~f:(fun acc x -> Var.Set.add x acc) ~init:vars params
177177
| Field (z, _) -> Var.Set.add z vars
178178
| Prim (_, args) ->
@@ -223,7 +223,7 @@ let liveness prog pure_funs (global_info : Global_flow.info) =
223223
List.iter
224224
~f:(fun x -> if variable_may_escape x global_info then add_top x)
225225
args
226-
| Block (_, _, _)
226+
| Block (_, _, _, _)
227227
| Field (_, _)
228228
| Closure (_, _)
229229
| Constant _
@@ -286,7 +286,7 @@ let propagate uses defs live_vars live_table x =
286286
(* If y is a live block, then x is the join of liveness fields that are x *)
287287
| Live fields -> (
288288
match Var.Tbl.get defs y with
289-
| Expr (Block (_, vars, _)) ->
289+
| Expr (Block (_, vars, _, _)) ->
290290
let found = ref false in
291291
Array.iteri
292292
~f:(fun i v ->
@@ -341,7 +341,7 @@ let zero prog sentinal live_table =
341341
match instr with
342342
| Let (x, e) -> (
343343
match e with
344-
| Block (start, vars, is_array) -> (
344+
| Block (start, vars, is_array, mut) -> (
345345
match Var.Tbl.get live_table x with
346346
| Live fields ->
347347
let vars =
@@ -350,7 +350,7 @@ let zero prog sentinal live_table =
350350
vars
351351
|> compact_vars
352352
in
353-
let e = Block (start, vars, is_array) in
353+
let e = Block (start, vars, is_array, mut) in
354354
Let (x, e)
355355
| _ -> instr)
356356
| Apply ap ->

compiler/lib/global_flow.ml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -194,15 +194,15 @@ let expr_deps blocks st x e =
194194
| Pv v, `Const -> do_escape st Escape_constant v
195195
| Pv v, `Shallow_const -> (
196196
match st.defs.(Var.idx v) with
197-
| Expr (Block (_, a, _)) ->
197+
| Expr (Block (_, a, _, _)) ->
198198
Array.iter a ~f:(fun x -> do_escape st Escape x)
199199
| _ -> do_escape st Escape v)
200200
| Pv v, `Object_literal -> (
201201
match st.defs.(Var.idx v) with
202-
| Expr (Block (_, a, _)) ->
202+
| Expr (Block (_, a, _, _)) ->
203203
Array.iter a ~f:(fun x ->
204204
match st.defs.(Var.idx x) with
205-
| Expr (Block (_, [| _k; v |], _)) -> do_escape st Escape v
205+
| Expr (Block (_, [| _k; v |], _, _)) -> do_escape st Escape v
206206
| _ -> do_escape st Escape x)
207207
| _ -> do_escape st Escape v)
208208
| Pv v, `Mutable -> do_escape st Escape v);
@@ -325,7 +325,7 @@ module Domain = struct
325325
then (
326326
st.may_escape.(idx) <- s;
327327
match st.defs.(idx) with
328-
| Expr (Block (_, a, _)) -> (
328+
| Expr (Block (_, a, _, _)) -> (
329329
Array.iter ~f:(fun y -> variable_escape ~update ~st ~approx s y) a;
330330
match s with
331331
| Escape ->
@@ -410,7 +410,7 @@ let propagate st ~update approx x =
410410
~approx
411411
(fun z ->
412412
match st.defs.(Var.idx z) with
413-
| Expr (Block (t, a, _))
413+
| Expr (Block (t, a, _, _))
414414
when n < Array.length a
415415
&&
416416
match tags with
@@ -440,7 +440,7 @@ let propagate st ~update approx x =
440440
~others
441441
(fun z ->
442442
match st.defs.(Var.idx z) with
443-
| Expr (Block (_, lst, _)) ->
443+
| Expr (Block (_, lst, _, _)) ->
444444
Array.iter ~f:(fun t -> add_dep st x t) lst;
445445
let a =
446446
Array.fold_left

0 commit comments

Comments
 (0)