Skip to content

Compiler: track block mutability #1603

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions compiler/lib/code.ml
Original file line number Diff line number Diff line change
Expand Up @@ -333,13 +333,17 @@ type special =
| Undefined
| Alias_prim of string

type mutability =
| Immutable
| Maybe_mutable

type expr =
| Apply of
{ f : Var.t
; args : Var.t list
; exact : bool
}
| Block of int * Var.t array * array_or_not
| Block of int * Var.t array * array_or_not * mutability
| Field of Var.t * int
| Closure of Var.t list * cont
| Constant of constant
Expand Down Expand Up @@ -479,8 +483,14 @@ module Print = struct
if exact
then Format.fprintf f "%a!(%a)" Var.print g var_list args
else Format.fprintf f "%a(%a)" Var.print g var_list args
| Block (t, a, _) ->
Format.fprintf f "{tag=%d" t;
| Block (t, a, _, mut) ->
Format.fprintf
f
"%s{tag=%d"
(match mut with
| Immutable -> "imm"
| Maybe_mutable -> "")
t;
for i = 0 to Array.length a - 1 do
Format.fprintf f "; %d = %a" i Var.print a.(i)
done;
Expand Down Expand Up @@ -732,7 +742,7 @@ let invariant { blocks; start; _ } =
in
let check_expr = function
| Apply _ -> ()
| Block (_, _, _) -> ()
| Block (_, _, _, _) -> ()
| Field (_, _) -> ()
| Closure (l, cont) ->
List.iter l ~f:define;
Expand Down
6 changes: 5 additions & 1 deletion compiler/lib/code.mli
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,17 @@ type special =
| Undefined
| Alias_prim of string

type mutability =
| Immutable
| Maybe_mutable

type expr =
| Apply of
{ f : Var.t
; args : Var.t list
; exact : bool (* if true, then # of arguments = # of parameters *)
}
| Block of int * Var.t array * array_or_not
| Block of int * Var.t array * array_or_not * mutability
| Field of Var.t * int
| Closure of Var.t list * cont
| Constant of constant
Expand Down
2 changes: 1 addition & 1 deletion compiler/lib/deadcode.ml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ and mark_expr st e =
| Apply { f; args; _ } ->
mark_var st f;
List.iter args ~f:(fun x -> mark_var st x)
| Block (_, a, _) -> Array.iter a ~f:(fun x -> mark_var st x)
| Block (_, a, _, _) -> Array.iter a ~f:(fun x -> mark_var st x)
| Field (x, _) -> mark_var st x
| Closure (_, (pc, _)) -> mark_reachable st pc
| Special _ -> ()
Expand Down
2 changes: 1 addition & 1 deletion compiler/lib/duplicate.ml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ let expr s e =
| Constant _ -> e
| Apply { f; args; exact } ->
Apply { f = s f; args = List.map args ~f:(fun x -> s x); exact }
| Block (n, a, k) -> Block (n, Array.map a ~f:(fun x -> s x), k)
| Block (n, a, k, mut) -> Block (n, Array.map a ~f:(fun x -> s x), k, mut)
| Field (x, n) -> Field (s x, n)
| Closure _ -> failwith "Inlining/Duplicating closure is currenly not supported"
| Special x -> Special x
Expand Down
16 changes: 10 additions & 6 deletions compiler/lib/eval.ml
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ let is_int info x =
(fun x ->
match Flow.Info.def info x with
| Some (Constant (Int _)) -> Y
| Some (Block (_, _, _) | Constant _) -> N
| Some (Block (_, _, _, _) | Constant _) -> N
| None | Some _ -> Unknown)
Unknown
(fun u v ->
Expand All @@ -196,8 +196,12 @@ let the_tag_of info x get =
info
(fun x ->
match Flow.Info.def info x with
| Some (Block (j, _, _)) ->
if Flow.Info.possibly_mutable info x then None else get j
| Some (Block (j, _, _, mut)) ->
if Flow.Info.possibly_mutable info x
then (
assert (Poly.(mut = Maybe_mutable));
None)
else get j
| Some (Constant (Tuple (j, _, _))) -> get j
| None | Some _ -> None)
None
Expand Down Expand Up @@ -278,7 +282,7 @@ let eval_instr info ((x, loc) as i) =
| Let (x, Prim (Extern "caml_sys_const_backend_type", [ _ ])) ->
let jsoo = Code.Var.fresh () in
[ Let (jsoo, Constant (String "js_of_ocaml")), noloc
; Let (x, Block (0, [| jsoo |], NotArray)), loc
; Let (x, Block (0, [| jsoo |], NotArray, Immutable)), loc
]
| Let (_, Prim (Extern ("%resume" | "%perform" | "%reperform"), _)) ->
[ i ] (* We need that the arguments to this primitives remain variables *)
Expand Down Expand Up @@ -338,7 +342,7 @@ let the_cond_of info x =
| NativeString _
| Float_array _
| Int64 _ )) -> Non_zero
| Some (Block (_, _, _)) -> Non_zero
| Some (Block (_, _, _, _)) -> Non_zero
| Some (Field _ | Closure _ | Prim _ | Apply _ | Special _) -> Unknown
| None -> Unknown)
Unknown
Expand Down Expand Up @@ -381,7 +385,7 @@ let rec do_not_raise pc visited blocks =
| Array_set (_, _, _) | Offset_ref (_, _) | Set_field (_, _, _) | Assign _ -> ()
| Let (_, e) -> (
match e with
| Block (_, _, _) | Field (_, _) | Constant _ | Closure _ -> ()
| Block (_, _, _, _) | Field (_, _) | Constant _ | Closure _ -> ()
| Apply _ -> raise May_raise
| Special _ -> ()
| Prim (Extern name, _) when Primitive.is_pure name -> ()
Expand Down
17 changes: 9 additions & 8 deletions compiler/lib/flow.ml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ let expr_deps blocks vars deps defs x e =
| Closure (l, cont) ->
List.iter l ~f:(fun x -> add_param_def vars defs x);
cont_deps blocks vars deps defs cont
| Block (_, a, _) -> Array.iter a ~f:(fun y -> add_dep deps x y)
| Block (_, a, _, _) -> Array.iter a ~f:(fun y -> add_dep deps x y)
| Field (y, _) -> add_dep deps x y

let program_deps { blocks; _ } =
Expand Down Expand Up @@ -152,7 +152,7 @@ let propagate1 deps defs st x =
var_set_lift
(fun z ->
match defs.(Var.idx z) with
| Expr (Block (_, a, _)) when n < Array.length a ->
| Expr (Block (_, a, _, _)) when n < Array.length a ->
let t = a.(n) in
add_dep deps x t;
Var.Tbl.get st t
Expand Down Expand Up @@ -194,7 +194,7 @@ let rec block_escape st x =
Code.Var.ISet.add st.may_escape y;
Code.Var.ISet.add st.possibly_mutable y;
match st.defs.(Var.idx y) with
| Expr (Block (_, l, _)) -> Array.iter l ~f:(fun z -> block_escape st z)
| Expr (Block (_, l, _, _)) -> Array.iter l ~f:(fun z -> block_escape st z)
| _ -> ()))
(Var.Tbl.get st.known_origins x)

Expand Down Expand Up @@ -226,15 +226,16 @@ let expr_escape st _x e =
| Pv v, `Shallow_const -> (
match st.defs.(Var.idx v) with
| Expr (Constant (Tuple _)) -> ()
| Expr (Block (_, a, _)) -> Array.iter a ~f:(fun x -> block_escape st x)
| Expr (Block (_, a, _, _)) ->
Array.iter a ~f:(fun x -> block_escape st x)
| _ -> block_escape st v)
| Pv v, `Object_literal -> (
match st.defs.(Var.idx v) with
| Expr (Constant (Tuple _)) -> ()
| Expr (Block (_, a, _)) ->
| Expr (Block (_, a, _, _)) ->
Array.iter a ~f:(fun x ->
match st.defs.(Var.idx x) with
| Expr (Block (_, [| _k; v |], _)) -> block_escape st v
| Expr (Block (_, [| _k; v |], _, _)) -> block_escape st v
| Expr (Constant _) -> ()
| _ -> block_escape st x)
| _ -> block_escape st v)
Expand Down Expand Up @@ -282,7 +283,7 @@ let propagate2 ?(skip_param = false) defs known_origins possibly_mutable st x =
|| Var.Set.exists
(fun z ->
match defs.(Var.idx z) with
| Expr (Block (_, a, _)) ->
| Expr (Block (_, a, _, _)) ->
n >= Array.length a
|| Var.ISet.mem possibly_mutable z
|| Var.Tbl.get st a.(n)
Expand Down Expand Up @@ -382,7 +383,7 @@ let direct_approx (info : Info.t) x =
then None
else
match info.info_defs.(Var.idx z) with
| Expr (Block (_, a, _)) when n < Array.length a -> Some a.(n)
| Expr (Block (_, a, _, _)) when n < Array.length a -> Some a.(n)
| _ -> None)
None
(fun u v ->
Expand Down
2 changes: 1 addition & 1 deletion compiler/lib/freevars.ml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ let iter_expr_free_vars f e =
| Apply { f = x; args; _ } ->
f x;
List.iter ~f args
| Block (_, a, _) -> Array.iter ~f a
| Block (_, a, _, _) -> Array.iter ~f a
| Field (x, _) -> f x
| Closure _ -> ()
| Special _ -> ()
Expand Down
2 changes: 1 addition & 1 deletion compiler/lib/generate.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,7 @@ let rec translate_expr ctx queue loc x e level : _ * J.statement_list =
let prop = or_p prop prop' in
let e = apply_fun ctx f args exact cps loc in
(e, prop, queue), []
| Block (tag, a, array_or_not) ->
| Block (tag, a, array_or_not, _mut) ->
let contents, prop, queue =
List.fold_right
~f:(fun x (args, prop, queue) ->
Expand Down
12 changes: 6 additions & 6 deletions compiler/lib/global_deadcode.ml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ let usages prog (global_info : Global_flow.info) : usage_kind Var.Map.t Var.Tbl.
List.iter
~f:(fun a -> if variable_may_escape a global_info then add_use Compute x a)
args
| Block (_, vars, _) -> Array.iter ~f:(add_use Compute x) vars
| Block (_, vars, _, _) -> Array.iter ~f:(add_use Compute x) vars
| Field (z, _) -> add_use Compute x z
| Constant _ -> ()
| Special _ -> ()
Expand Down Expand Up @@ -172,7 +172,7 @@ let expr_vars e =
| Apply { f; args; _ } ->
let vars = Var.Set.add f vars in
List.fold_left ~f:(fun acc x -> Var.Set.add x acc) ~init:vars args
| Block (_, params, _) ->
| Block (_, params, _, _) ->
Array.fold_left ~f:(fun acc x -> Var.Set.add x acc) ~init:vars params
| Field (z, _) -> Var.Set.add z vars
| Prim (_, args) ->
Expand Down Expand Up @@ -223,7 +223,7 @@ let liveness prog pure_funs (global_info : Global_flow.info) =
List.iter
~f:(fun x -> if variable_may_escape x global_info then add_top x)
args
| Block (_, _, _)
| Block (_, _, _, _)
| Field (_, _)
| Closure (_, _)
| Constant _
Expand Down Expand Up @@ -286,7 +286,7 @@ let propagate uses defs live_vars live_table x =
(* If y is a live block, then x is the join of liveness fields that are x *)
| Live fields -> (
match Var.Tbl.get defs y with
| Expr (Block (_, vars, _)) ->
| Expr (Block (_, vars, _, _)) ->
let found = ref false in
Array.iteri
~f:(fun i v ->
Expand Down Expand Up @@ -341,7 +341,7 @@ let zero prog sentinal live_table =
match instr with
| Let (x, e) -> (
match e with
| Block (start, vars, is_array) -> (
| Block (start, vars, is_array, mut) -> (
match Var.Tbl.get live_table x with
| Live fields ->
let vars =
Expand All @@ -350,7 +350,7 @@ let zero prog sentinal live_table =
vars
|> compact_vars
in
let e = Block (start, vars, is_array) in
let e = Block (start, vars, is_array, mut) in
Let (x, e)
| _ -> instr)
| Apply ap ->
Expand Down
12 changes: 6 additions & 6 deletions compiler/lib/global_flow.ml
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,15 @@ let expr_deps blocks st x e =
| Pv v, `Const -> do_escape st Escape_constant v
| Pv v, `Shallow_const -> (
match st.defs.(Var.idx v) with
| Expr (Block (_, a, _)) ->
| Expr (Block (_, a, _, _)) ->
Array.iter a ~f:(fun x -> do_escape st Escape x)
| _ -> do_escape st Escape v)
| Pv v, `Object_literal -> (
match st.defs.(Var.idx v) with
| Expr (Block (_, a, _)) ->
| Expr (Block (_, a, _, _)) ->
Array.iter a ~f:(fun x ->
match st.defs.(Var.idx x) with
| Expr (Block (_, [| _k; v |], _)) -> do_escape st Escape v
| Expr (Block (_, [| _k; v |], _, _)) -> do_escape st Escape v
| _ -> do_escape st Escape x)
| _ -> do_escape st Escape v)
| Pv v, `Mutable -> do_escape st Escape v);
Expand Down Expand Up @@ -325,7 +325,7 @@ module Domain = struct
then (
st.may_escape.(idx) <- s;
match st.defs.(idx) with
| Expr (Block (_, a, _)) -> (
| Expr (Block (_, a, _, _)) -> (
Array.iter ~f:(fun y -> variable_escape ~update ~st ~approx s y) a;
match s with
| Escape ->
Expand Down Expand Up @@ -410,7 +410,7 @@ let propagate st ~update approx x =
~approx
(fun z ->
match st.defs.(Var.idx z) with
| Expr (Block (t, a, _))
| Expr (Block (t, a, _, _))
when n < Array.length a
&&
match tags with
Expand Down Expand Up @@ -440,7 +440,7 @@ let propagate st ~update approx x =
~others
(fun z ->
match st.defs.(Var.idx z) with
| Expr (Block (_, lst, _)) ->
| Expr (Block (_, lst, _, _)) ->
Array.iter ~f:(fun t -> add_dep st x t) lst;
let a =
Array.fold_left
Expand Down
Loading
Loading