From a8919ebd73167ff0fc88bd70f3b5d32f27516fee Mon Sep 17 00:00:00 2001 From: ZhangHongbo Date: Wed, 15 Sep 2021 21:09:24 +0800 Subject: [PATCH 01/10] format --- jscomp/core/lam_beta_reduce.ml | 158 +++++----- jscomp/core/lam_beta_reduce_util.ml | 147 +++++---- jscomp/core/lam_pass_remove_alias.ml | 432 +++++++++++++-------------- 3 files changed, 347 insertions(+), 390 deletions(-) diff --git a/jscomp/core/lam_beta_reduce.ml b/jscomp/core/lam_beta_reduce.ml index 2990be2b55..bf1f797b25 100644 --- a/jscomp/core/lam_beta_reduce.ml +++ b/jscomp/core/lam_beta_reduce.ml @@ -22,15 +22,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - - - - - - - - - (* A naive beta reduce would break the invariants of the optmization. @@ -53,85 +44,80 @@ ]} we can bound [x] to [100] in a single step *) -let propogate_beta_reduce - (meta : Lam_stats.t) (params : Ident.t list) (body : Lam.t) (args : Lam.t list) = - match Lam_beta_reduce_util.simple_beta_reduce params body args with - | Some x -> x - | None -> - let rest_bindings, rev_new_params = - Ext_list.fold_left2 params args ([],[]) (fun old_param arg (rest_bindings, acc) -> - match arg with - | Lconst _ - | Lvar _ -> rest_bindings , arg :: acc - | _ -> - let p = Ident.rename old_param in - (p,arg) :: rest_bindings , (Lam.var p) :: acc - ) in - let new_body = Lam_bounded_vars.rewrite (Hash_ident.of_list2 (List.rev params) (rev_new_params)) body in - Ext_list.fold_right rest_bindings new_body - (fun (param, arg ) l -> - begin match arg with - | Lprim {primitive = Pmakeblock (_, _, Immutable) ;args ; _} -> - Hash_ident.replace meta.ident_tbl param - (Lam_util.kind_of_lambda_block args ) - | Lprim {primitive = Psome | Psome_not_nest; args = [v]; _} -> - Hash_ident.replace meta.ident_tbl param - (Normal_optional(v)) - | _ -> () end; - Lam_util.refine_let ~kind:Strict param arg l) - - -let propogate_beta_reduce_with_map - (meta : Lam_stats.t) (map : Lam_var_stats.stats Map_ident.t ) params body args = +let propogate_beta_reduce (meta : Lam_stats.t) (params : Ident.t list) + (body : Lam.t) (args : Lam.t list) = match Lam_beta_reduce_util.simple_beta_reduce params body args with | Some x -> x | None -> - let rest_bindings, rev_new_params = - Ext_list.fold_left2 params args ([],[]) - (fun old_param arg (rest_bindings, acc) -> - match arg with - | Lconst _ - | Lvar _ -> rest_bindings , arg :: acc - | Lglobal_module _ - -> - let p = Ident.rename old_param in - (p,arg) :: rest_bindings , (Lam.var p) :: acc - - | _ -> - if Lam_analysis.no_side_effects arg then - match Map_ident.find_exn map old_param with - | stat -> - if Lam_var_stats.top_and_used_zero_or_one stat then - rest_bindings, arg :: acc - else - let p = Ident.rename old_param in - (p,arg) :: rest_bindings , (Lam.var p) :: acc - else - let p = Ident.rename old_param in - (p,arg) :: rest_bindings , (Lam.var p) :: acc ) in - let new_body = Lam_bounded_vars.rewrite (Hash_ident.of_list2 (List.rev params) (rev_new_params)) body in - Ext_list.fold_right rest_bindings new_body - (fun (param, (arg : Lam.t)) l -> - begin match arg with - | Lprim {primitive = Pmakeblock (_, _, Immutable ) ; args} -> - Hash_ident.replace meta.ident_tbl param - (Lam_util.kind_of_lambda_block args ) - - | Lprim {primitive = Psome | Psome_not_nest; args = [v]} -> - Hash_ident.replace meta.ident_tbl param - (Normal_optional(v)); - - | _ -> () end; - Lam_util.refine_let ~kind:Strict param arg l) - - - + let rest_bindings, rev_new_params = + Ext_list.fold_left2 params args ([], []) + (fun old_param arg (rest_bindings, acc) -> + match arg with + | Lconst _ | Lvar _ -> (rest_bindings, arg :: acc) + | _ -> + let p = Ident.rename old_param in + ((p, arg) :: rest_bindings, Lam.var p :: acc)) + in + let new_body = + Lam_bounded_vars.rewrite + (Hash_ident.of_list2 (List.rev params) rev_new_params) + body + in + Ext_list.fold_right rest_bindings new_body (fun (param, arg) l -> + (match arg with + | Lprim { primitive = Pmakeblock (_, _, Immutable); args; _ } -> + Hash_ident.replace meta.ident_tbl param + (Lam_util.kind_of_lambda_block args) + | Lprim { primitive = Psome | Psome_not_nest; args = [ v ]; _ } -> + Hash_ident.replace meta.ident_tbl param (Normal_optional v) + | _ -> ()); + Lam_util.refine_let ~kind:Strict param arg l) + +let propogate_beta_reduce_with_map (meta : Lam_stats.t) + (map : Lam_var_stats.stats Map_ident.t) params body args = + match Lam_beta_reduce_util.simple_beta_reduce params body args with + | Some x -> x + | None -> + let rest_bindings, rev_new_params = + Ext_list.fold_left2 params args ([], []) + (fun old_param arg (rest_bindings, acc) -> + match arg with + | Lconst _ | Lvar _ -> (rest_bindings, arg :: acc) + | Lglobal_module _ -> + let p = Ident.rename old_param in + ((p, arg) :: rest_bindings, Lam.var p :: acc) + | _ -> + if Lam_analysis.no_side_effects arg then + match Map_ident.find_exn map old_param with + | stat -> + if Lam_var_stats.top_and_used_zero_or_one stat then + (rest_bindings, arg :: acc) + else + let p = Ident.rename old_param in + ((p, arg) :: rest_bindings, Lam.var p :: acc) + else + let p = Ident.rename old_param in + ((p, arg) :: rest_bindings, Lam.var p :: acc)) + in + let new_body = + Lam_bounded_vars.rewrite + (Hash_ident.of_list2 (List.rev params) rev_new_params) + body + in + Ext_list.fold_right rest_bindings new_body + (fun (param, (arg : Lam.t)) l -> + (match arg with + | Lprim { primitive = Pmakeblock (_, _, Immutable); args } -> + Hash_ident.replace meta.ident_tbl param + (Lam_util.kind_of_lambda_block args) + | Lprim { primitive = Psome | Psome_not_nest; args = [ v ] } -> + Hash_ident.replace meta.ident_tbl param (Normal_optional v) + | _ -> ()); + Lam_util.refine_let ~kind:Strict param arg l) let no_names_beta_reduce params body args = - match Lam_beta_reduce_util.simple_beta_reduce params body args with - | Some x -> x - | None -> - Ext_list.fold_left2 params args body - (fun param arg l -> - Lam_util.refine_let ~kind:Strict param arg l) - + match Lam_beta_reduce_util.simple_beta_reduce params body args with + | Some x -> x + | None -> + Ext_list.fold_left2 params args body (fun param arg l -> + Lam_util.refine_let ~kind:Strict param arg l) diff --git a/jscomp/core/lam_beta_reduce_util.ml b/jscomp/core/lam_beta_reduce_util.ml index 4a0e815267..3e4e95f5e1 100644 --- a/jscomp/core/lam_beta_reduce_util.ml +++ b/jscomp/core/lam_beta_reduce_util.ml @@ -22,11 +22,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - - - - - (* Principle: since in ocaml, the apply order is not specified rules: @@ -36,12 +31,9 @@ other wise the evaluation order is tricky (make sure eval order is correct) *) -type value = - { mutable used : bool ; - lambda : Lam.t - } -let param_hash : _ Hash_ident.t = Hash_ident.create 20 +type value = { mutable used : bool; lambda : Lam.t } +let param_hash : _ Hash_ident.t = Hash_ident.create 20 (* optimize cases like (fun f (a,b){ g (a,b,1)} (e0, e1)) @@ -57,74 +49,75 @@ let param_hash : _ Hash_ident.t = Hash_ident.create 20 | _ -> false ) params args' ]} *) -let simple_beta_reduce params body args = +let simple_beta_reduce params body args = let exception Not_simple_apply in - let find_param v opt = - match Hash_ident.find_opt param_hash v with - | Some exp -> - if exp.used then raise_notrace Not_simple_apply - else - exp.used <- true; exp.lambda + let find_param v opt = + match Hash_ident.find_opt param_hash v with + | Some exp -> + if exp.used then raise_notrace Not_simple_apply else exp.used <- true; + exp.lambda | None -> opt - in - let rec aux acc (us : Lam.t list) = - match us with + in + let rec aux acc (us : Lam.t list) = + match us with | [] -> List.rev acc - | (Lvar x as a ) :: rest - -> - aux (find_param x a :: acc) rest - | (Lconst _ as u) :: rest - -> aux (u :: acc) rest - | _ :: _ -> raise_notrace Not_simple_apply - in - match (body : Lam.t) with - | Lprim { primitive ; args = ap_args ; loc = ap_loc} (* There is no lambda in primitive *) - -> (* catch a special case of primitives *) - - let () = - List.iter2 (fun p a -> Hash_ident.add param_hash p {lambda = a; used = false }) params args - in - begin match aux [] ap_args with - | new_args -> - let result = - Hash_ident.fold param_hash (Lam.prim ~primitive ~args:new_args ap_loc) (fun _param {lambda; used} acc -> - if not used then - Lam.seq lambda acc - else acc) in - Hash_ident.clear param_hash; - Some result - | exception _ -> - Hash_ident.clear param_hash ; - None - end - | Lapply { ap_func = - (Lvar _ | Lprim {primitive = Pfield _; args = [Lglobal_module _ ]} as f) ; ap_args ; ap_info } - -> - let () = - List.iter2 (fun p a -> Hash_ident.add param_hash p {lambda = a; used = false }) params args - in - (*since we adde each param only once, - iff it is removed once, no exception, - if it is removed twice there will be exception. - if it is never removed, we have it as rest keys - *) - begin match aux [] ap_args with - | new_args -> - let f = - match f with - | Lvar fn_name -> find_param fn_name f - | _ -> f in - let result = - Hash_ident.fold param_hash (Lam.apply f new_args ap_info ) - (fun _param {lambda; used} acc -> - if not used then - Lam.seq lambda acc - else acc ) - in - Hash_ident.clear param_hash; - Some result - | exception _ -> - Hash_ident.clear param_hash; - None - end + | (Lvar x as a) :: rest -> aux (find_param x a :: acc) rest + | (Lconst _ as u) :: rest -> aux (u :: acc) rest + | _ :: _ -> raise_notrace Not_simple_apply + in + match (body : Lam.t) with + | Lprim { primitive; args = ap_args; loc = ap_loc } + (* There is no lambda in primitive *) -> ( + (* catch a special case of primitives *) + let () = + List.iter2 + (fun p a -> Hash_ident.add param_hash p { lambda = a; used = false }) + params args + in + match aux [] ap_args with + | new_args -> + let result = + Hash_ident.fold param_hash + (Lam.prim ~primitive ~args:new_args ap_loc) + (fun _param { lambda; used } acc -> + if not used then Lam.seq lambda acc else acc) + in + Hash_ident.clear param_hash; + Some result + | exception _ -> + Hash_ident.clear param_hash; + None) + | Lapply + { + ap_func = + (Lvar _ | Lprim { primitive = Pfield _; args = [ Lglobal_module _ ] }) + as f; + ap_args; + ap_info; + } -> ( + let () = + List.iter2 + (fun p a -> Hash_ident.add param_hash p { lambda = a; used = false }) + params args + in + (*since we adde each param only once, + iff it is removed once, no exception, + if it is removed twice there will be exception. + if it is never removed, we have it as rest keys + *) + match aux [] ap_args with + | new_args -> + let f = + match f with Lvar fn_name -> find_param fn_name f | _ -> f + in + let result = + Hash_ident.fold param_hash (Lam.apply f new_args ap_info) + (fun _param { lambda; used } acc -> + if not used then Lam.seq lambda acc else acc) + in + Hash_ident.clear param_hash; + Some result + | exception _ -> + Hash_ident.clear param_hash; + None) | _ -> None diff --git a/jscomp/core/lam_pass_remove_alias.ml b/jscomp/core/lam_pass_remove_alias.ml index d2ff699cbe..0cc5409e06 100644 --- a/jscomp/core/lam_pass_remove_alias.ml +++ b/jscomp/core/lam_pass_remove_alias.ml @@ -22,198 +22,181 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - - - - -let id_is_for_sure_true_in_boolean (tbl : Lam_stats.ident_tbl) id = - match Hash_ident.find_opt tbl id with - | Some (ImmutableBlock(_)) - | Some (Normal_optional _ ) - | Some (MutableBlock _) -> true - | Some - (Constant _ | Module _ | FunctionId _ | Exception | Parameter | NA - | OptionalBlock(_, (Undefined | Null | Null_undefined)) - ) - - | None -> false - -let simplify_alias - (meta : Lam_stats.t) - (lam : Lam.t) - : Lam.t = - - let rec simpl (lam : Lam.t) : Lam.t = - match lam with +let id_is_for_sure_true_in_boolean (tbl : Lam_stats.ident_tbl) id = + match Hash_ident.find_opt tbl id with + | Some (ImmutableBlock _) | Some (Normal_optional _) | Some (MutableBlock _) + -> + true + | Some + ( Constant _ | Module _ | FunctionId _ | Exception | Parameter | NA + | OptionalBlock (_, (Undefined | Null | Null_undefined)) ) + | None -> + false + +let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t = + let rec simpl (lam : Lam.t) : Lam.t = + match lam with | Lvar _ -> lam - | Lprim {primitive = (Pfield (i,info) as primitive); args = [arg]; loc} -> - (* ATTENTION: - Main use case, we should detect inline all immutable block .. *) - begin match simpl arg with - | Lvar v as l-> - Lam_util.field_flatten_get (fun _ -> Lam.prim ~primitive ~args:[l] loc ) - v i info meta.ident_tbl - | l -> - Lam.prim ~primitive ~args:[l] loc - end - | Lprim {primitive = (Pval_from_option | Pval_from_option_not_nest as p ); args = [Lvar v as lvar ]} as x -> - begin match Hash_ident.find_opt meta.ident_tbl v with - | Some (OptionalBlock (l,_)) -> l - | _ -> if p = Pval_from_option_not_nest then lvar else x - end - | Lglobal_module _ -> lam - | Lprim {primitive; args; loc } - -> Lam.prim ~primitive ~args:(Ext_list.map args simpl) loc - - | Lifthenelse(Lprim {primitive = Pis_not_none; args = [Lvar id ]} as l1, l2, l3) - -> - begin match Hash_ident.find_opt meta.ident_tbl id with - | Some (ImmutableBlock ( _) | (MutableBlock _ ) - | Normal_optional _) - -> simpl l2 - | Some (OptionalBlock(l, Null)) -> - Lam.if_ - (Lam.not_ (Location.none) ( Lam.prim ~primitive:Pis_null ~args:[l] Location.none)) - (simpl l2) (simpl l3) - | Some (OptionalBlock(l, Undefined)) -> - Lam.if_ - (Lam.not_ Location.none (Lam.prim ~primitive:Pis_undefined ~args:[l] Location.none)) - (simpl l2) (simpl l3) - | Some (OptionalBlock(l, Null_undefined)) -> - Lam.if_ - (Lam.not_ Location.none - ( Lam.prim ~primitive:Pis_null_undefined ~args:[l] Location.none) ) - (simpl l2) (simpl l3) - | Some _ - | None -> Lam.if_ l1 (simpl l2) (simpl l3) - end + | Lprim { primitive = Pfield (i, info) as primitive; args = [ arg ]; loc } + -> ( + (* ATTENTION: + Main use case, we should detect inline all immutable block .. *) + match simpl arg with + | Lvar v as l -> + Lam_util.field_flatten_get + (fun _ -> Lam.prim ~primitive ~args:[ l ] loc) + v i info meta.ident_tbl + | l -> Lam.prim ~primitive ~args:[ l ] loc) + | Lprim + { + primitive = (Pval_from_option | Pval_from_option_not_nest) as p; + args = [ (Lvar v as lvar) ]; + } as x -> ( + match Hash_ident.find_opt meta.ident_tbl v with + | Some (OptionalBlock (l, _)) -> l + | _ -> if p = Pval_from_option_not_nest then lvar else x) + | Lglobal_module _ -> lam + | Lprim { primitive; args; loc } -> + Lam.prim ~primitive ~args:(Ext_list.map args simpl) loc + | Lifthenelse + ((Lprim { primitive = Pis_not_none; args = [ Lvar id ] } as l1), l2, l3) + -> ( + match Hash_ident.find_opt meta.ident_tbl id with + | Some (ImmutableBlock _ | MutableBlock _ | Normal_optional _) -> + simpl l2 + | Some (OptionalBlock (l, Null)) -> + Lam.if_ + (Lam.not_ Location.none + (Lam.prim ~primitive:Pis_null ~args:[ l ] Location.none)) + (simpl l2) (simpl l3) + | Some (OptionalBlock (l, Undefined)) -> + Lam.if_ + (Lam.not_ Location.none + (Lam.prim ~primitive:Pis_undefined ~args:[ l ] Location.none)) + (simpl l2) (simpl l3) + | Some (OptionalBlock (l, Null_undefined)) -> + Lam.if_ + (Lam.not_ Location.none + (Lam.prim ~primitive:Pis_null_undefined ~args:[ l ] + Location.none)) + (simpl l2) (simpl l3) + | Some _ | None -> Lam.if_ l1 (simpl l2) (simpl l3)) (* could be the code path - {[ match x with - | h::hs -> + {[ match x with + | h::hs -> ]} - *) - | Lifthenelse (l1, l2, l3) -> - begin match l1 with - | Lvar id when id_is_for_sure_true_in_boolean meta.ident_tbl id-> - simpl l2 - | _ -> - Lam.if_ (simpl l1) (simpl l2) (simpl l3) - end + *) + | Lifthenelse (l1, l2, l3) -> ( + match l1 with + | Lvar id when id_is_for_sure_true_in_boolean meta.ident_tbl id -> + simpl l2 + | _ -> Lam.if_ (simpl l1) (simpl l2) (simpl l3)) | Lconst _ -> lam - | Llet(str, v, l1, l2) -> - Lam.let_ str v (simpl l1) (simpl l2 ) - | Lletrec(bindings, body) -> - let bindings = Ext_list.map_snd bindings simpl in - Lam.letrec bindings (simpl body) - - (* complicated - 1. inline this function - 2. ... - exports.Make= - function(funarg) - {var $$let=Make(funarg); - return [0, $$let[5],... $$let[16]]} - *) - | Lapply{ap_func = - Lprim {primitive = Pfield (_, Fld_module {name = fld_name}) ; - args = [ Lglobal_module ident ]; - _} as l1; - ap_args = args; ap_info } -> - begin - match Lam_compile_env.query_external_id_info ident fld_name with - | {persistent_closed_lambda=Some Lfunction{params; body; _} } - (* be more cautious when do cross module inlining *) - when - Ext_list.same_length params args && - Ext_list.for_all args (fun arg -> - match arg with - | Lvar p -> - begin - match Hash_ident.find_opt meta.ident_tbl p with - | Some v -> v <> Parameter - | None -> true - end - | _ -> true - ) -> - simpl (Lam_beta_reduce.propogate_beta_reduce - meta params body args) - | _ -> - Lam.apply (simpl l1) (Ext_list.map args simpl) ap_info - - - end + | Llet (str, v, l1, l2) -> Lam.let_ str v (simpl l1) (simpl l2) + | Lletrec (bindings, body) -> + let bindings = Ext_list.map_snd bindings simpl in + Lam.letrec bindings (simpl body) + (* complicated + 1. inline this function + 2. ... + exports.Make= + function(funarg) + {var $$let=Make(funarg); + return [0, $$let[5],... $$let[16]]} + *) + | Lapply + { + ap_func = + Lprim + { + primitive = Pfield (_, Fld_module { name = fld_name }); + args = [ Lglobal_module ident ]; + _; + } as l1; + ap_args = args; + ap_info; + } -> ( + match Lam_compile_env.query_external_id_info ident fld_name with + | { persistent_closed_lambda = Some (Lfunction { params; body; _ }) } + (* be more cautious when do cross module inlining *) + when Ext_list.same_length params args + && Ext_list.for_all args (fun arg -> + match arg with + | Lvar p -> ( + match Hash_ident.find_opt meta.ident_tbl p with + | Some v -> v <> Parameter + | None -> true) + | _ -> true) -> + simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) + | _ -> Lam.apply (simpl l1) (Ext_list.map args simpl) ap_info) (* Function inlining interact with other optimizations... - parameter attributes - - scope issues - - code bloat - *) - | Lapply{ap_func = (Lvar v as fn); ap_args = args; ap_info } -> - (* Check info for always inlining *) - - (* Ext_log.dwarn __LOC__ "%s/%d" v.name v.stamp; *) - let normal () = Lam.apply ( simpl fn) (Ext_list.map args simpl) ap_info in - begin + - scope issues + - code bloat + *) + | Lapply { ap_func = Lvar v as fn; ap_args = args; ap_info } -> ( + (* Check info for always inlining *) + + (* Ext_log.dwarn __LOC__ "%s/%d" v.name v.stamp; *) + let normal () = + Lam.apply (simpl fn) (Ext_list.map args simpl) ap_info + in match Hash_ident.find_opt meta.ident_tbl v with - | Some (FunctionId {lambda = Some(Lfunction ({params; body; attr = {is_a_functor}} as m), - rec_flag) - }) - -> - - if Ext_list.same_length args params (* && false *) - then - if is_a_functor - (* && (Set_ident.mem v meta.export_idents) && false *) - then - (* TODO: check l1 if it is exported, - if so, maybe not since in that case, - we are going to have two copy? - *) - - (* Check: recursive applying may result in non-termination *) - begin + | Some + (FunctionId + { + lambda = + Some + ( Lfunction ({ params; body; attr = { is_a_functor } } as m), + rec_flag ); + }) -> + if Ext_list.same_length args params (* && false *) then + if + is_a_functor + (* && (Set_ident.mem v meta.export_idents) && false *) + then + (* TODO: check l1 if it is exported, + if so, maybe not since in that case, + we are going to have two copy? + *) + + (* Check: recursive applying may result in non-termination *) (* Ext_log.dwarn __LOC__ "beta .. %s/%d" v.name v.stamp ; *) - simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) - end - else - if (* Lam_analysis.size body < Lam_analysis.small_inline_size *) - (* ap_inlined = Always_inline || *) - Lam_analysis.ok_to_inline_fun_when_app m args - then - - (* let param_map = *) - (* Lam_analysis.free_variables meta.export_idents *) - (* (Lam_analysis.param_map_of_list params) body in *) - (* let old_count = List.length params in *) - (* let new_count = Map_ident.cardinal param_map in *) - let param_map = - Lam_closure.is_closed_with_map - meta.export_idents params body in - let is_export_id = Set_ident.mem meta.export_idents v in - match is_export_id, param_map with - | false, (_, param_map) - | true, (true, param_map) -> - begin match rec_flag with - - | Lam_rec -> Lam_beta_reduce.propogate_beta_reduce_with_map meta param_map params body args - | Lam_self_rec -> normal () - | Lam_non_rec -> - simpl - (Lam_beta_reduce.propogate_beta_reduce_with_map meta param_map params body args) - end - | _ -> normal () - else - normal () - else - normal () - | Some _ - | None -> normal () - - end - - | Lapply{ ap_func = Lfunction{ params; body}; ap_args = args; _} - when Ext_list.same_length params args -> - simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) + simpl + (Lam_beta_reduce.propogate_beta_reduce meta params body args) + else if + (* Lam_analysis.size body < Lam_analysis.small_inline_size *) + (* ap_inlined = Always_inline || *) + Lam_analysis.ok_to_inline_fun_when_app m args + then + (* let param_map = *) + (* Lam_analysis.free_variables meta.export_idents *) + (* (Lam_analysis.param_map_of_list params) body in *) + (* let old_count = List.length params in *) + (* let new_count = Map_ident.cardinal param_map in *) + let param_map = + Lam_closure.is_closed_with_map meta.export_idents params body + in + let is_export_id = Set_ident.mem meta.export_idents v in + match (is_export_id, param_map) with + | false, (_, param_map) | true, (true, param_map) -> ( + match rec_flag with + | Lam_rec -> + Lam_beta_reduce.propogate_beta_reduce_with_map meta + param_map params body args + | Lam_self_rec -> normal () + | Lam_non_rec -> + simpl + (Lam_beta_reduce.propogate_beta_reduce_with_map meta + param_map params body args)) + | _ -> normal () + else normal () + else normal () + | Some _ | None -> normal ()) + | Lapply { ap_func = Lfunction { params; body }; ap_args = args; _ } + when Ext_list.same_length params args -> + simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) (* | Lapply{ fn = Lfunction{function_kind = Tupled; params; body}; *) (* args = [Lprim {primitive = Pmakeblock _; args; _}]; _} *) (* (\** TODO: keep track of this parameter in ocaml trunk, *) @@ -221,48 +204,43 @@ let simplify_alias (* *\) *) (* when Ext_list.same_length params args -> *) (* simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) *) - - | Lapply { ap_func = l1; ap_args = ll; ap_info; } -> - Lam.apply (simpl l1) (Ext_list.map ll simpl) ap_info - | Lfunction {arity; params; body; attr} - -> Lam.function_ ~arity ~params ~body:(simpl body) ~attr - | Lswitch (l, {sw_failaction; - sw_consts; - sw_blocks; - sw_blocks_full; - sw_consts_full; - sw_names; - }) -> - Lam.switch (simpl l) - {sw_consts = - Ext_list.map_snd sw_consts simpl; - sw_blocks = Ext_list.map_snd sw_blocks simpl; - sw_consts_full; - sw_blocks_full; - sw_failaction = Ext_option.map sw_failaction simpl; - sw_names; - } - | Lstringswitch(l, sw, d) -> - Lam.stringswitch (simpl l ) - (Ext_list.map_snd sw simpl) - (Ext_option.map d simpl) - | Lstaticraise (i,ls) -> - Lam.staticraise i (Ext_list.map ls simpl ) - | Lstaticcatch (l1, ids, l2) -> - Lam.staticcatch (simpl l1) ids (simpl l2) - | Ltrywith (l1, v, l2) -> Lam.try_ (simpl l1) v (simpl l2) - | Lsequence(l1, l2) - -> Lam.seq (simpl l1) (simpl l2) - | Lwhile(l1, l2) - -> Lam.while_ (simpl l1) (simpl l2) - | Lfor(flag, l1, l2, dir, l3) - -> - Lam.for_ flag (simpl l1) (simpl l2) dir (simpl l3) - | Lassign(v, l) -> - (* Lalias-bound variables are never assigned, so don't increase - v's refsimpl *) - Lam.assign v (simpl l) - in + | Lapply { ap_func = l1; ap_args = ll; ap_info } -> + Lam.apply (simpl l1) (Ext_list.map ll simpl) ap_info + | Lfunction { arity; params; body; attr } -> + Lam.function_ ~arity ~params ~body:(simpl body) ~attr + | Lswitch + ( l, + { + sw_failaction; + sw_consts; + sw_blocks; + sw_blocks_full; + sw_consts_full; + sw_names; + } ) -> + Lam.switch (simpl l) + { + sw_consts = Ext_list.map_snd sw_consts simpl; + sw_blocks = Ext_list.map_snd sw_blocks simpl; + sw_consts_full; + sw_blocks_full; + sw_failaction = Ext_option.map sw_failaction simpl; + sw_names; + } + | Lstringswitch (l, sw, d) -> + Lam.stringswitch (simpl l) + (Ext_list.map_snd sw simpl) + (Ext_option.map d simpl) + | Lstaticraise (i, ls) -> Lam.staticraise i (Ext_list.map ls simpl) + | Lstaticcatch (l1, ids, l2) -> Lam.staticcatch (simpl l1) ids (simpl l2) + | Ltrywith (l1, v, l2) -> Lam.try_ (simpl l1) v (simpl l2) + | Lsequence (l1, l2) -> Lam.seq (simpl l1) (simpl l2) + | Lwhile (l1, l2) -> Lam.while_ (simpl l1) (simpl l2) + | Lfor (flag, l1, l2, dir, l3) -> + Lam.for_ flag (simpl l1) (simpl l2) dir (simpl l3) + | Lassign (v, l) -> + (* Lalias-bound variables are never assigned, so don't increase + v's refsimpl *) + Lam.assign v (simpl l) + in simpl lam - - From b3a896aedcbf627612fabdf659a35f6bf8ccf51d Mon Sep 17 00:00:00 2001 From: ZhangHongbo Date: Wed, 15 Sep 2021 21:14:36 +0800 Subject: [PATCH 02/10] add exn suffix to indicate that it is gonna raise --- jscomp/core/lam_beta_reduce_util.ml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/jscomp/core/lam_beta_reduce_util.ml b/jscomp/core/lam_beta_reduce_util.ml index 3e4e95f5e1..059b786c32 100644 --- a/jscomp/core/lam_beta_reduce_util.ml +++ b/jscomp/core/lam_beta_reduce_util.ml @@ -51,18 +51,18 @@ let param_hash : _ Hash_ident.t = Hash_ident.create 20 *) let simple_beta_reduce params body args = let exception Not_simple_apply in - let find_param v opt = + let find_param_exn v opt = match Hash_ident.find_opt param_hash v with | Some exp -> if exp.used then raise_notrace Not_simple_apply else exp.used <- true; exp.lambda | None -> opt in - let rec aux acc (us : Lam.t list) = + let rec aux_exn acc (us : Lam.t list) = match us with | [] -> List.rev acc - | (Lvar x as a) :: rest -> aux (find_param x a :: acc) rest - | (Lconst _ as u) :: rest -> aux (u :: acc) rest + | (Lvar x as a) :: rest -> aux_exn (find_param_exn x a :: acc) rest + | (Lconst _ as u) :: rest -> aux_exn (u :: acc) rest | _ :: _ -> raise_notrace Not_simple_apply in match (body : Lam.t) with @@ -74,7 +74,7 @@ let simple_beta_reduce params body args = (fun p a -> Hash_ident.add param_hash p { lambda = a; used = false }) params args in - match aux [] ap_args with + match aux_exn [] ap_args with | new_args -> let result = Hash_ident.fold param_hash @@ -105,10 +105,10 @@ let simple_beta_reduce params body args = if it is removed twice there will be exception. if it is never removed, we have it as rest keys *) - match aux [] ap_args with + match aux_exn [] ap_args with | new_args -> let f = - match f with Lvar fn_name -> find_param fn_name f | _ -> f + match f with Lvar fn_name -> find_param_exn fn_name f | _ -> f in let result = Hash_ident.fold param_hash (Lam.apply f new_args ap_info) From 2bc96769c3bd76aa652e4bd96c08030654a25343 Mon Sep 17 00:00:00 2001 From: ZhangHongbo Date: Thu, 16 Sep 2021 09:06:09 +0800 Subject: [PATCH 03/10] avoid an edge case where a function happens to be the parameter --- jscomp/core/js_dump.ml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/jscomp/core/js_dump.ml b/jscomp/core/js_dump.ml index eaaaa62e37..8e27d1df81 100644 --- a/jscomp/core/js_dump.ml +++ b/jscomp/core/js_dump.ml @@ -319,7 +319,16 @@ and pp_function ~return_unit ~is_method cxt (f : P.t) ~fn_state {[ function(x,y){ return u(x,y) } ]} it can be optimized in to either [u] or [Curry.__n(u)] *) - (not is_method) && Ext_list.for_all2_no_exn ls l is_var -> ( + (not is_method) + && Ext_list.for_all2_no_exn ls l is_var + && + match v with + (* This check is needed to avoid some edge cases + {[function(x){return x(x)}]} + here the function is also called `x` + *) + | Id id -> not (Ext_list.exists l (fun x -> Ident.same x id)) + | Qualified _ -> true -> ( let optimize len ~p cxt f v = if p then try_optimize_curry cxt f len function_id else vident cxt f v in From a6960bd2ce95b8b1ef2d464e5e66d81edea683d3 Mon Sep 17 00:00:00 2001 From: ZhangHongbo Date: Thu, 16 Sep 2021 09:11:13 +0800 Subject: [PATCH 04/10] also catch exception raised by find_param_exn --- jscomp/core/lam_beta_reduce_util.ml | 55 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/jscomp/core/lam_beta_reduce_util.ml b/jscomp/core/lam_beta_reduce_util.ml index 059b786c32..1eaceebea5 100644 --- a/jscomp/core/lam_beta_reduce_util.ml +++ b/jscomp/core/lam_beta_reduce_util.ml @@ -74,19 +74,18 @@ let simple_beta_reduce params body args = (fun p a -> Hash_ident.add param_hash p { lambda = a; used = false }) params args in - match aux_exn [] ap_args with - | new_args -> - let result = - Hash_ident.fold param_hash - (Lam.prim ~primitive ~args:new_args ap_loc) - (fun _param { lambda; used } acc -> - if not used then Lam.seq lambda acc else acc) - in - Hash_ident.clear param_hash; - Some result - | exception _ -> - Hash_ident.clear param_hash; - None) + try + let new_args = aux_exn [] ap_args in + let result = + Hash_ident.fold param_hash (Lam.prim ~primitive ~args:new_args ap_loc) + (fun _param { lambda; used } acc -> + if not used then Lam.seq lambda acc else acc) + in + Hash_ident.clear param_hash; + Some result + with Not_simple_apply -> + Hash_ident.clear param_hash; + None) | Lapply { ap_func = @@ -105,19 +104,19 @@ let simple_beta_reduce params body args = if it is removed twice there will be exception. if it is never removed, we have it as rest keys *) - match aux_exn [] ap_args with - | new_args -> - let f = - match f with Lvar fn_name -> find_param_exn fn_name f | _ -> f - in - let result = - Hash_ident.fold param_hash (Lam.apply f new_args ap_info) - (fun _param { lambda; used } acc -> - if not used then Lam.seq lambda acc else acc) - in - Hash_ident.clear param_hash; - Some result - | exception _ -> - Hash_ident.clear param_hash; - None) + try + let new_args = aux_exn [] ap_args in + let f = + match f with Lvar fn_name -> find_param_exn fn_name f | _ -> f + in + let result = + Hash_ident.fold param_hash (Lam.apply f new_args ap_info) + (fun _param { lambda; used } acc -> + if not used then Lam.seq lambda acc else acc) + in + Hash_ident.clear param_hash; + Some result + with Not_simple_apply -> + Hash_ident.clear param_hash; + None) | _ -> None From 361a38291fed1adb76edbc1684476424df668da2 Mon Sep 17 00:00:00 2001 From: ZhangHongbo Date: Thu, 16 Sep 2021 09:31:52 +0800 Subject: [PATCH 05/10] simplify args first --- jscomp/core/lam_pass_remove_alias.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jscomp/core/lam_pass_remove_alias.ml b/jscomp/core/lam_pass_remove_alias.ml index 0cc5409e06..584147af4f 100644 --- a/jscomp/core/lam_pass_remove_alias.ml +++ b/jscomp/core/lam_pass_remove_alias.ml @@ -139,8 +139,9 @@ let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t = (* Check info for always inlining *) (* Ext_log.dwarn __LOC__ "%s/%d" v.name v.stamp; *) + let args = Ext_list.map args simpl in let normal () = - Lam.apply (simpl fn) (Ext_list.map args simpl) ap_info + Lam.apply (simpl fn) args ap_info in match Hash_ident.find_opt meta.ident_tbl v with | Some From 017dc629c01ae6385cbb4aaa633538f056a8f548 Mon Sep 17 00:00:00 2001 From: ZhangHongbo Date: Thu, 16 Sep 2021 09:38:04 +0800 Subject: [PATCH 06/10] tweak --- jscomp/core/lam_pass_remove_alias.ml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/jscomp/core/lam_pass_remove_alias.ml b/jscomp/core/lam_pass_remove_alias.ml index 584147af4f..12be93964e 100644 --- a/jscomp/core/lam_pass_remove_alias.ml +++ b/jscomp/core/lam_pass_remove_alias.ml @@ -135,14 +135,12 @@ let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t = - scope issues - code bloat *) - | Lapply { ap_func = Lvar v as fn; ap_args = args; ap_info } -> ( + | Lapply { ap_func = Lvar v as fn; ap_args; ap_info } -> ( (* Check info for always inlining *) (* Ext_log.dwarn __LOC__ "%s/%d" v.name v.stamp; *) - let args = Ext_list.map args simpl in - let normal () = - Lam.apply (simpl fn) args ap_info - in + let ap_args = Ext_list.map ap_args simpl in + let[@local] normal () = Lam.apply (simpl fn) ap_args ap_info in match Hash_ident.find_opt meta.ident_tbl v with | Some (FunctionId @@ -152,7 +150,7 @@ let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t = ( Lfunction ({ params; body; attr = { is_a_functor } } as m), rec_flag ); }) -> - if Ext_list.same_length args params (* && false *) then + if Ext_list.same_length ap_args params (* && false *) then if is_a_functor (* && (Set_ident.mem v meta.export_idents) && false *) @@ -165,11 +163,12 @@ let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t = (* Check: recursive applying may result in non-termination *) (* Ext_log.dwarn __LOC__ "beta .. %s/%d" v.name v.stamp ; *) simpl - (Lam_beta_reduce.propogate_beta_reduce meta params body args) + (Lam_beta_reduce.propogate_beta_reduce meta params body + ap_args) else if (* Lam_analysis.size body < Lam_analysis.small_inline_size *) (* ap_inlined = Always_inline || *) - Lam_analysis.ok_to_inline_fun_when_app m args + Lam_analysis.ok_to_inline_fun_when_app m ap_args then (* let param_map = *) (* Lam_analysis.free_variables meta.export_idents *) @@ -185,12 +184,12 @@ let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t = match rec_flag with | Lam_rec -> Lam_beta_reduce.propogate_beta_reduce_with_map meta - param_map params body args + param_map params body ap_args | Lam_self_rec -> normal () | Lam_non_rec -> simpl (Lam_beta_reduce.propogate_beta_reduce_with_map meta - param_map params body args)) + param_map params body ap_args)) | _ -> normal () else normal () else normal () From 01ab7eb756f5211afbe2d6515e8fcc662b5a8a33 Mon Sep 17 00:00:00 2001 From: ZhangHongbo Date: Thu, 16 Sep 2021 09:40:12 +0800 Subject: [PATCH 07/10] fix an edge case of non-termination `g (g)` --- jscomp/core/lam_pass_remove_alias.ml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/jscomp/core/lam_pass_remove_alias.ml b/jscomp/core/lam_pass_remove_alias.ml index 12be93964e..70230c7d15 100644 --- a/jscomp/core/lam_pass_remove_alias.ml +++ b/jscomp/core/lam_pass_remove_alias.ml @@ -187,9 +187,15 @@ let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t = param_map params body ap_args | Lam_self_rec -> normal () | Lam_non_rec -> - simpl - (Lam_beta_reduce.propogate_beta_reduce_with_map meta - param_map params body ap_args)) + if + Ext_list.exists ap_args (fun lam -> + Lam_hit.hit_variable v lam) + (*avoid nontermination, e.g, `g(g)`*) + then normal () + else + simpl + (Lam_beta_reduce.propogate_beta_reduce_with_map meta + param_map params body ap_args)) | _ -> normal () else normal () else normal () From 0dde294efc607a7fbd8a4a7f86443e24804e69ce Mon Sep 17 00:00:00 2001 From: ZhangHongbo Date: Wed, 15 Sep 2021 20:57:43 +0800 Subject: [PATCH 08/10] add a crashed case --- jscomp/test/unboxed_crash.js | 13 +++++++++++++ jscomp/test/unboxed_crash.ml | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 jscomp/test/unboxed_crash.js create mode 100644 jscomp/test/unboxed_crash.ml diff --git a/jscomp/test/unboxed_crash.js b/jscomp/test/unboxed_crash.js new file mode 100644 index 0000000000..8325c6d740 --- /dev/null +++ b/jscomp/test/unboxed_crash.js @@ -0,0 +1,13 @@ +'use strict'; + +var Curry = require("../../lib/js/curry.js"); + +function g(x) { + return Curry._1(x, x); +} + +var loop = g(g); + +exports.g = g; +exports.loop = loop; +/* loop Not a pure module */ diff --git a/jscomp/test/unboxed_crash.ml b/jscomp/test/unboxed_crash.ml new file mode 100644 index 0000000000..6a6a376c8e --- /dev/null +++ b/jscomp/test/unboxed_crash.ml @@ -0,0 +1,20 @@ +[@@@config +{ + flags = + [| + "-w"; + "@A"; + "-drawlambda"; + (* "-dtypedtree"; *) + "-bs-diagnose" + (* "-dparsetree"; *) + (* "-dsource"; *) + (* "-bs-no-builtin-ppx"; *); + |]; +}] + +type t = A of (t -> int) [@@unboxed] + +let g x = match x with A v -> v x + +let loop = g (A g) From 4f96ca6dffadc9082ff4b751a2cb5e1d62a807bc Mon Sep 17 00:00:00 2001 From: ZhangHongbo Date: Thu, 16 Sep 2021 09:40:57 +0800 Subject: [PATCH 09/10] snapshot build --- jscomp/test/build.ninja | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jscomp/test/build.ninja b/jscomp/test/build.ninja index 24c3456dc9..562914a2d8 100644 --- a/jscomp/test/build.ninja +++ b/jscomp/test/build.ninja @@ -704,6 +704,7 @@ o test/typeof_test.cmi test/typeof_test.cmj : cc test/typeof_test.ml | test/mt.c o test/ui_defs.cmi : cc test/ui_defs.mli | $bsc $stdlib o test/unboxed_attribute.cmi test/unboxed_attribute.cmj : cc test/unboxed_attribute.res | $bsc $stdlib o test/unboxed_attribute_test.cmi test/unboxed_attribute_test.cmj : cc test/unboxed_attribute_test.ml | test/mt.cmj $bsc $stdlib +o test/unboxed_crash.cmi test/unboxed_crash.cmj : cc test/unboxed_crash.ml | $bsc $stdlib o test/unboxed_use_case.cmj : cc_cmi test/unboxed_use_case.ml | test/unboxed_use_case.cmi $bsc $stdlib o test/unboxed_use_case.cmi : cc test/unboxed_use_case.mli | $bsc $stdlib o test/uncurry_external_test.cmi test/uncurry_external_test.cmj : cc test/uncurry_external_test.ml | test/mt.cmj $bsc $stdlib @@ -726,4 +727,4 @@ o test/utf8_decode_test.cmi test/utf8_decode_test.cmj : cc test/utf8_decode_test o test/variant.cmi test/variant.cmj : cc test/variant.ml | $bsc $stdlib o test/watch_test.cmi test/watch_test.cmj : cc test/watch_test.ml | $bsc $stdlib o test/webpack_config.cmi test/webpack_config.cmj : cc test/webpack_config.ml | $bsc $stdlib -o test : phony test/406_primitive_test.cmi test/406_primitive_test.cmj test/a.cmi test/a.cmj test/a_filename_test.cmi test/a_filename_test.cmj test/a_list_test.cmi test/a_list_test.cmj test/a_recursive_type.cmi test/a_recursive_type.cmj test/a_scope_bug.cmi test/a_scope_bug.cmj test/a_string_test.cmi test/a_string_test.cmj test/abstract_type.cmi test/abstract_type.cmj test/adt_optimize_test.cmi test/adt_optimize_test.cmj test/alias_test.cmi test/alias_test.cmj test/and_or_tailcall_test.cmi test/and_or_tailcall_test.cmj test/app_root_finder.cmi test/app_root_finder.cmj test/argv_test.cmi test/argv_test.cmj test/ari_regress_test.cmi test/ari_regress_test.cmj test/arith_lexer.cmi test/arith_lexer.cmj test/arith_parser.cmi test/arith_parser.cmj test/arith_syntax.cmi test/arith_syntax.cmj test/arity.cmi test/arity.cmj test/arity_deopt.cmi test/arity_deopt.cmj test/arity_infer.cmi test/arity_infer.cmj test/arity_ml.cmi test/arity_ml.cmj test/array_data_util.cmi test/array_data_util.cmj test/array_safe_get.cmi test/array_safe_get.cmj test/array_subtle_test.cmi test/array_subtle_test.cmj test/array_test.cmi test/array_test.cmj test/ast_abstract_test.cmi test/ast_abstract_test.cmj test/ast_js_mapper_poly_test.cmi test/ast_js_mapper_poly_test.cmj test/ast_js_mapper_test.cmi test/ast_js_mapper_test.cmj test/ast_mapper_defensive_test.cmi test/ast_mapper_defensive_test.cmj test/ast_mapper_unused_warning_test.cmi test/ast_mapper_unused_warning_test.cmj test/async_ideas.cmi test/async_ideas.cmj test/attr_test.cmi test/attr_test.cmj test/b.cmi test/b.cmj test/bal_set_mini.cmi test/bal_set_mini.cmj test/bang_primitive.cmi test/bang_primitive.cmj test/basic_module_test.cmi test/basic_module_test.cmj test/bb.cmi test/bb.cmj test/bdd.cmi test/bdd.cmj test/belt_internal_test.cmi test/belt_internal_test.cmj test/belt_result_alias_test.cmi test/belt_result_alias_test.cmj test/bench.cmi test/bench.cmj test/big_enum.cmi test/big_enum.cmj test/big_polyvar_test.cmi test/big_polyvar_test.cmj test/block_alias_test.cmi test/block_alias_test.cmj test/boolean_test.cmi test/boolean_test.cmj test/bs_MapInt_test.cmi test/bs_MapInt_test.cmj test/bs_abstract_test.cmi test/bs_abstract_test.cmj test/bs_array_test.cmi test/bs_array_test.cmj test/bs_auto_uncurry.cmi test/bs_auto_uncurry.cmj test/bs_auto_uncurry_test.cmi test/bs_auto_uncurry_test.cmj test/bs_float_test.cmi test/bs_float_test.cmj test/bs_hashmap_test.cmi test/bs_hashmap_test.cmj test/bs_hashset_int_test.cmi test/bs_hashset_int_test.cmj test/bs_hashtbl_string_test.cmi test/bs_hashtbl_string_test.cmj test/bs_ignore_effect.cmi test/bs_ignore_effect.cmj test/bs_ignore_test.cmi test/bs_ignore_test.cmj test/bs_int_test.cmi test/bs_int_test.cmj test/bs_list_test.cmi test/bs_list_test.cmj test/bs_map_set_dict_test.cmi test/bs_map_set_dict_test.cmj test/bs_map_test.cmi test/bs_map_test.cmj test/bs_min_max_test.cmi test/bs_min_max_test.cmj test/bs_mutable_set_test.cmi test/bs_mutable_set_test.cmj test/bs_node_string_buffer_test.cmi test/bs_node_string_buffer_test.cmj test/bs_poly_map_test.cmi test/bs_poly_map_test.cmj test/bs_poly_mutable_map_test.cmi test/bs_poly_mutable_map_test.cmj test/bs_poly_mutable_set_test.cmi test/bs_poly_mutable_set_test.cmj test/bs_poly_set_test.cmi test/bs_poly_set_test.cmj test/bs_qualified.cmi test/bs_qualified.cmj test/bs_queue_test.cmi test/bs_queue_test.cmj test/bs_rbset_int_bench.cmi test/bs_rbset_int_bench.cmj test/bs_rest_test.cmi test/bs_rest_test.cmj test/bs_set_bench.cmi test/bs_set_bench.cmj test/bs_set_int_test.cmi test/bs_set_int_test.cmj test/bs_sort_test.cmi test/bs_sort_test.cmj test/bs_splice_partial.cmi test/bs_splice_partial.cmj test/bs_stack_test.cmi test/bs_stack_test.cmj test/bs_string_test.cmi test/bs_string_test.cmj test/bs_unwrap_test.cmi test/bs_unwrap_test.cmj test/buffer_test.cmi test/buffer_test.cmj test/bytes_split_gpr_743_test.cmi test/bytes_split_gpr_743_test.cmj test/caml_compare_test.cmi test/caml_compare_test.cmj test/caml_format_test.cmi test/caml_format_test.cmj test/caml_sys_poly_fill_test.cmi test/caml_sys_poly_fill_test.cmj test/chain_code_test.cmi test/chain_code_test.cmj test/chn_test.cmi test/chn_test.cmj test/class_setter_getter.cmi test/class_setter_getter.cmj test/class_type_ffi_test.cmi test/class_type_ffi_test.cmj test/coercion_module_alias_test.cmi test/coercion_module_alias_test.cmj test/compare_test.cmi test/compare_test.cmj test/complete_parmatch_test.cmi test/complete_parmatch_test.cmj test/complex_if_test.cmi test/complex_if_test.cmj test/complex_test.cmi test/complex_test.cmj test/complex_while_loop.cmi test/complex_while_loop.cmj test/condition_compilation_test.cmi test/condition_compilation_test.cmj test/config1_test.cmi test/config1_test.cmj test/config2_test.cmi test/config2_test.cmj test/console_log_test.cmi test/console_log_test.cmj test/const_block_test.cmi test/const_block_test.cmj test/const_defs.cmi test/const_defs.cmj test/const_defs_test.cmi test/const_defs_test.cmj test/const_test.cmi test/const_test.cmj test/cont_int_fold_test.cmi test/cont_int_fold_test.cmj test/cps_test.cmi test/cps_test.cmj test/cross_module_inline_test.cmi test/cross_module_inline_test.cmj test/custom_error_test.cmi test/custom_error_test.cmj test/debug_keep_test.cmi test/debug_keep_test.cmj test/debug_mode_value.cmi test/debug_mode_value.cmj test/debug_tmp.cmi test/debug_tmp.cmj test/debugger_test.cmi test/debugger_test.cmj test/default_export_test.cmi test/default_export_test.cmj test/defunctor_make_test.cmi test/defunctor_make_test.cmj test/demo.cmi test/demo.cmj test/demo_binding.cmi test/demo_binding.cmj test/demo_int_map.cmi test/demo_int_map.cmj test/demo_page.cmi test/demo_page.cmj test/demo_pipe.cmi test/demo_pipe.cmj test/derive_dyntype.cmi test/derive_dyntype.cmj test/derive_projector_test.cmi test/derive_projector_test.cmj test/derive_type_test.cmi test/derive_type_test.cmj test/digest_test.cmi test/digest_test.cmj test/div_by_zero_test.cmi test/div_by_zero_test.cmj test/dollar_escape_test.cmi test/dollar_escape_test.cmj test/earger_curry_test.cmi test/earger_curry_test.cmj test/effect.cmi test/effect.cmj test/epsilon_test.cmi test/epsilon_test.cmj test/equal_box_test.cmi test/equal_box_test.cmj test/equal_exception_test.cmi test/equal_exception_test.cmj test/equal_test.cmi test/equal_test.cmj test/es6_export.cmi test/es6_export.cmj test/es6_import.cmi test/es6_import.cmj test/es6_module_test.cmi test/es6_module_test.cmj test/escape_esmodule.cmi test/escape_esmodule.cmj test/esmodule_ref.cmi test/esmodule_ref.cmj test/event_ffi.cmi test/event_ffi.cmj test/exception_alias.cmi test/exception_alias.cmj test/exception_def.cmi test/exception_def.cmj test/exception_raise_test.cmi test/exception_raise_test.cmj test/exception_rebind_test.cmi test/exception_rebind_test.cmj test/exception_rebound_err_test.cmi test/exception_rebound_err_test.cmj test/exception_repr_test.cmi test/exception_repr_test.cmj test/exception_value_test.cmi test/exception_value_test.cmj test/exn_error_pattern.cmi test/exn_error_pattern.cmj test/export_keyword.cmi test/export_keyword.cmj test/ext_array_test.cmi test/ext_array_test.cmj test/ext_bytes_test.cmi test/ext_bytes_test.cmj test/ext_filename_test.cmi test/ext_filename_test.cmj test/ext_list_test.cmi test/ext_list_test.cmj test/ext_pervasives_test.cmi test/ext_pervasives_test.cmj test/ext_string_test.cmi test/ext_string_test.cmj test/ext_sys_test.cmi test/ext_sys_test.cmj test/extensible_variant_test.cmi test/extensible_variant_test.cmj test/external_polyfill_test.cmi test/external_polyfill_test.cmj test/external_ppx.cmi test/external_ppx.cmj test/fail_comp.cmi test/fail_comp.cmj test/ffi_arity_test.cmi test/ffi_arity_test.cmj test/ffi_array_test.cmi test/ffi_array_test.cmj test/ffi_js_test.cmi test/ffi_js_test.cmj test/ffi_splice_test.cmi test/ffi_splice_test.cmj test/ffi_test.cmi test/ffi_test.cmj test/fib.cmi test/fib.cmj test/flattern_order_test.cmi test/flattern_order_test.cmj test/flexible_array_test.cmi test/flexible_array_test.cmj test/float_array.cmi test/float_array.cmj test/float_of_bits_test.cmi test/float_of_bits_test.cmj test/float_record.cmi test/float_record.cmj test/float_test.cmi test/float_test.cmj test/floatarray_test.cmi test/floatarray_test.cmj test/flow_parser_reg_test.cmi test/flow_parser_reg_test.cmj test/for_loop_test.cmi test/for_loop_test.cmj test/for_side_effect_test.cmi test/for_side_effect_test.cmj test/format_regression.cmi test/format_regression.cmj test/format_test.cmi test/format_test.cmj test/fs_test.cmi test/fs_test.cmj test/fun_pattern_match.cmi test/fun_pattern_match.cmj test/functor_app_test.cmi test/functor_app_test.cmj test/functor_def.cmi test/functor_def.cmj test/functor_ffi.cmi test/functor_ffi.cmj test/functor_inst.cmi test/functor_inst.cmj test/functors.cmi test/functors.cmj test/gbk.cmi test/gbk.cmj test/genlex_test.cmi test/genlex_test.cmj test/gentTypeReTest.cmi test/gentTypeReTest.cmj test/global_exception_regression_test.cmi test/global_exception_regression_test.cmj test/global_mangles.cmi test/global_mangles.cmj test/global_module_alias_test.cmi test/global_module_alias_test.cmj test/google_closure_test.cmi test/google_closure_test.cmj test/gpr496_test.cmi test/gpr496_test.cmj test/gpr_1063_test.cmi test/gpr_1063_test.cmj test/gpr_1072.cmi test/gpr_1072.cmj test/gpr_1072_reg.cmi test/gpr_1072_reg.cmj test/gpr_1150.cmi test/gpr_1150.cmj test/gpr_1154_test.cmi test/gpr_1154_test.cmj test/gpr_1170.cmi test/gpr_1170.cmj test/gpr_1240_missing_unbox.cmi test/gpr_1240_missing_unbox.cmj test/gpr_1245_test.cmi test/gpr_1245_test.cmj test/gpr_1268.cmi test/gpr_1268.cmj test/gpr_1409_test.cmi test/gpr_1409_test.cmj test/gpr_1423_app_test.cmi test/gpr_1423_app_test.cmj test/gpr_1423_nav.cmi test/gpr_1423_nav.cmj test/gpr_1438.cmi test/gpr_1438.cmj test/gpr_1481.cmi test/gpr_1481.cmj test/gpr_1484.cmi test/gpr_1484.cmj test/gpr_1501_test.cmi test/gpr_1501_test.cmj test/gpr_1503_test.cmi test/gpr_1503_test.cmj test/gpr_1539_test.cmi test/gpr_1539_test.cmj test/gpr_1600_test.cmi test/gpr_1600_test.cmj test/gpr_1658_test.cmi test/gpr_1658_test.cmj test/gpr_1667_test.cmi test/gpr_1667_test.cmj test/gpr_1692_test.cmi test/gpr_1692_test.cmj test/gpr_1698_test.cmi test/gpr_1698_test.cmj test/gpr_1701_test.cmi test/gpr_1701_test.cmj test/gpr_1716_test.cmi test/gpr_1716_test.cmj test/gpr_1717_test.cmi test/gpr_1717_test.cmj test/gpr_1728_test.cmi test/gpr_1728_test.cmj test/gpr_1749_test.cmi test/gpr_1749_test.cmj test/gpr_1759_test.cmi test/gpr_1759_test.cmj test/gpr_1760_test.cmi test/gpr_1760_test.cmj test/gpr_1762_test.cmi test/gpr_1762_test.cmj test/gpr_1817_test.cmi test/gpr_1817_test.cmj test/gpr_1822_test.cmi test/gpr_1822_test.cmj test/gpr_1891_test.cmi test/gpr_1891_test.cmj test/gpr_1943_test.cmi test/gpr_1943_test.cmj test/gpr_1946_test.cmi test/gpr_1946_test.cmj test/gpr_2316_test.cmi test/gpr_2316_test.cmj test/gpr_2352_test.cmi test/gpr_2352_test.cmj test/gpr_2413_test.cmi test/gpr_2413_test.cmj test/gpr_2474.cmi test/gpr_2474.cmj test/gpr_2487.cmi test/gpr_2487.cmj test/gpr_2503_test.cmi test/gpr_2503_test.cmj test/gpr_2608_test.cmi test/gpr_2608_test.cmj test/gpr_2614_test.cmi test/gpr_2614_test.cmj test/gpr_2633_test.cmi test/gpr_2633_test.cmj test/gpr_2642_test.cmi test/gpr_2642_test.cmj test/gpr_2652_test.cmi test/gpr_2652_test.cmj test/gpr_2682_test.cmi test/gpr_2682_test.cmj test/gpr_2700_test.cmi test/gpr_2700_test.cmj test/gpr_2731_test.cmi test/gpr_2731_test.cmj test/gpr_2789_test.cmi test/gpr_2789_test.cmj test/gpr_2863_test.cmi test/gpr_2863_test.cmj test/gpr_2931_test.cmi test/gpr_2931_test.cmj test/gpr_3142_test.cmi test/gpr_3142_test.cmj test/gpr_3154_test.cmi test/gpr_3154_test.cmj test/gpr_3209_test.cmi test/gpr_3209_test.cmj test/gpr_3492_test.cmi test/gpr_3492_test.cmj test/gpr_3502_test.cmi test/gpr_3502_test.cmj test/gpr_3519_jsx_test.cmi test/gpr_3519_jsx_test.cmj test/gpr_3519_test.cmi test/gpr_3519_test.cmj test/gpr_3536_test.cmi test/gpr_3536_test.cmj test/gpr_3546_test.cmi test/gpr_3546_test.cmj test/gpr_3548_test.cmi test/gpr_3548_test.cmj test/gpr_3549_test.cmi test/gpr_3549_test.cmj test/gpr_3566_drive_test.cmi test/gpr_3566_drive_test.cmj test/gpr_3566_test.cmi test/gpr_3566_test.cmj test/gpr_3595_test.cmi test/gpr_3595_test.cmj test/gpr_3609_test.cmi test/gpr_3609_test.cmj test/gpr_3697_test.cmi test/gpr_3697_test.cmj test/gpr_373_test.cmi test/gpr_373_test.cmj test/gpr_3770_test.cmi test/gpr_3770_test.cmj test/gpr_3852_alias.cmi test/gpr_3852_alias.cmj test/gpr_3852_alias_reify.cmi test/gpr_3852_alias_reify.cmj test/gpr_3852_effect.cmi test/gpr_3852_effect.cmj test/gpr_3865.cmi test/gpr_3865.cmj test/gpr_3865_bar.cmi test/gpr_3865_bar.cmj test/gpr_3865_foo.cmi test/gpr_3865_foo.cmj test/gpr_3875_test.cmi test/gpr_3875_test.cmj test/gpr_3877_test.cmi test/gpr_3877_test.cmj test/gpr_3895_test.cmi test/gpr_3895_test.cmj test/gpr_3897_test.cmi test/gpr_3897_test.cmj test/gpr_3931_test.cmi test/gpr_3931_test.cmj test/gpr_3980_test.cmi test/gpr_3980_test.cmj test/gpr_4025_test.cmi test/gpr_4025_test.cmj test/gpr_405_test.cmi test/gpr_405_test.cmj test/gpr_4069_test.cmi test/gpr_4069_test.cmj test/gpr_4265_test.cmi test/gpr_4265_test.cmj test/gpr_4274_test.cmi test/gpr_4274_test.cmj test/gpr_4280_test.cmi test/gpr_4280_test.cmj test/gpr_4407_test.cmi test/gpr_4407_test.cmj test/gpr_441.cmi test/gpr_441.cmj test/gpr_4442_test.cmi test/gpr_4442_test.cmj test/gpr_4491_test.cmi test/gpr_4491_test.cmj test/gpr_4494_test.cmi test/gpr_4494_test.cmj test/gpr_4519_test.cmi test/gpr_4519_test.cmj test/gpr_459_test.cmi test/gpr_459_test.cmj test/gpr_4632.cmi test/gpr_4632.cmj test/gpr_4639_test.cmi test/gpr_4639_test.cmj test/gpr_4900_test.cmi test/gpr_4900_test.cmj test/gpr_4924_test.cmi test/gpr_4924_test.cmj test/gpr_4931.cmi test/gpr_4931.cmj test/gpr_5071_test.cmi test/gpr_5071_test.cmj test/gpr_5169_test.cmi test/gpr_5169_test.cmj test/gpr_5218_test.cmi test/gpr_5218_test.cmj test/gpr_627_test.cmi test/gpr_627_test.cmj test/gpr_658.cmi test/gpr_658.cmj test/gpr_858_test.cmi test/gpr_858_test.cmj test/gpr_858_unit2_test.cmi test/gpr_858_unit2_test.cmj test/gpr_904_test.cmi test/gpr_904_test.cmj test/gpr_974_test.cmi test/gpr_974_test.cmj test/gpr_977_test.cmi test/gpr_977_test.cmj test/gpr_return_type_unused_attribute.cmi test/gpr_return_type_unused_attribute.cmj test/gray_code_test.cmi test/gray_code_test.cmj test/guide_for_ext.cmi test/guide_for_ext.cmj test/hamming_test.cmi test/hamming_test.cmj test/hash_collision_test.cmi test/hash_collision_test.cmj test/hash_sugar_desugar.cmi test/hash_sugar_desugar.cmj test/hash_test.cmi test/hash_test.cmj test/hashtbl_test.cmi test/hashtbl_test.cmj test/hello.foo.cmi test/hello.foo.cmj test/hello_res.cmi test/hello_res.cmj test/http_types.cmi test/http_types.cmj test/ignore_test.cmi test/ignore_test.cmj test/imm_map_bench.cmi test/imm_map_bench.cmj test/include_side_effect.cmi test/include_side_effect.cmj test/include_side_effect_free.cmi test/include_side_effect_free.cmj test/incomplete_toplevel_test.cmi test/incomplete_toplevel_test.cmj test/infer_type_test.cmi test/infer_type_test.cmj test/inline_const.cmi test/inline_const.cmj test/inline_const_test.cmi test/inline_const_test.cmj test/inline_edge_cases.cmi test/inline_edge_cases.cmj test/inline_map2_test.cmi test/inline_map2_test.cmj test/inline_map_demo.cmi test/inline_map_demo.cmj test/inline_map_test.cmi test/inline_map_test.cmj test/inline_record_test.cmi test/inline_record_test.cmj test/inline_regression_test.cmi test/inline_regression_test.cmj test/inline_string_test.cmi test/inline_string_test.cmj test/inner_call.cmi test/inner_call.cmj test/inner_define.cmi test/inner_define.cmj test/inner_unused.cmi test/inner_unused.cmj test/installation_test.cmi test/installation_test.cmj test/int32_test.cmi test/int32_test.cmj test/int64_mul_div_test.cmi test/int64_mul_div_test.cmj test/int64_string_bench.cmi test/int64_string_bench.cmj test/int64_string_test.cmi test/int64_string_test.cmj test/int64_test.cmi test/int64_test.cmj test/int_hashtbl_test.cmi test/int_hashtbl_test.cmj test/int_map.cmi test/int_map.cmj test/int_overflow_test.cmi test/int_overflow_test.cmj test/int_poly_var.cmi test/int_poly_var.cmj test/int_switch_test.cmi test/int_switch_test.cmj test/internal_unused_test.cmi test/internal_unused_test.cmj test/io_test.cmi test/io_test.cmj test/js_array_test.cmi test/js_array_test.cmj test/js_bool_test.cmi test/js_bool_test.cmj test/js_cast_test.cmi test/js_cast_test.cmj test/js_date_test.cmi test/js_date_test.cmj test/js_dict_test.cmi test/js_dict_test.cmj test/js_exception_catch_test.cmi test/js_exception_catch_test.cmj test/js_float_test.cmi test/js_float_test.cmj test/js_global_test.cmi test/js_global_test.cmj test/js_int_test.cmi test/js_int_test.cmj test/js_json_test.cmi test/js_json_test.cmj test/js_list_test.cmi test/js_list_test.cmj test/js_math_test.cmi test/js_math_test.cmj test/js_null_test.cmi test/js_null_test.cmj test/js_null_undefined_test.cmi test/js_null_undefined_test.cmj test/js_nullable_test.cmi test/js_nullable_test.cmj test/js_obj_test.cmi test/js_obj_test.cmj test/js_option_test.cmi test/js_option_test.cmj test/js_promise_basic_test.cmi test/js_promise_basic_test.cmj test/js_re_test.cmi test/js_re_test.cmj test/js_string_test.cmi test/js_string_test.cmj test/js_typed_array_test.cmi test/js_typed_array_test.cmj test/js_undefined_test.cmi test/js_undefined_test.cmj test/js_val.cmi test/js_val.cmj test/jsoo_400_test.cmi test/jsoo_400_test.cmj test/jsoo_485_test.cmi test/jsoo_485_test.cmj test/key_word_property.cmi test/key_word_property.cmj test/key_word_property2.cmi test/key_word_property2.cmj test/key_word_property_plus_test.cmi test/key_word_property_plus_test.cmj test/label_uncurry.cmi test/label_uncurry.cmj test/large_integer_pat.cmi test/large_integer_pat.cmj test/large_record_duplication_test.cmi test/large_record_duplication_test.cmj test/largest_int_flow.cmi test/largest_int_flow.cmj test/lazy_demo.cmi test/lazy_demo.cmj test/lazy_test.cmi test/lazy_test.cmj test/lexer_test.cmi test/lexer_test.cmj test/lib_js_test.cmi test/lib_js_test.cmj test/libarg_test.cmi test/libarg_test.cmj test/libqueue_test.cmi test/libqueue_test.cmj test/limits_test.cmi test/limits_test.cmj test/list_stack.cmi test/list_stack.cmj test/list_test.cmi test/list_test.cmj test/local_class_type.cmi test/local_class_type.cmj test/local_exception_test.cmi test/local_exception_test.cmj test/loop_regression_test.cmi test/loop_regression_test.cmj test/loop_suites_test.cmi test/loop_suites_test.cmj test/map_find_test.cmi test/map_find_test.cmj test/map_test.cmi test/map_test.cmj test/mario_game.cmi test/mario_game.cmj test/marshal.cmi test/marshal.cmj test/method_chain.cmi test/method_chain.cmj test/method_name_test.cmi test/method_name_test.cmj test/method_string_name.cmi test/method_string_name.cmj test/minimal_test.cmi test/minimal_test.cmj test/miss_colon_test.cmi test/miss_colon_test.cmj test/mock_mt.cmi test/mock_mt.cmj test/module_alias_test.cmi test/module_alias_test.cmj test/module_as_class_ffi.cmi test/module_as_class_ffi.cmj test/module_as_function.cmi test/module_as_function.cmj test/module_missing_conversion.cmi test/module_missing_conversion.cmj test/module_parameter_test.cmi test/module_parameter_test.cmj test/module_splice_test.cmi test/module_splice_test.cmj test/more_poly_variant_test.cmi test/more_poly_variant_test.cmj test/more_uncurry.cmi test/more_uncurry.cmj test/mpr_6033_test.cmi test/mpr_6033_test.cmj test/mt.cmi test/mt.cmj test/mt_global.cmi test/mt_global.cmj test/mutable_obj_test.cmi test/mutable_obj_test.cmj test/mutable_uncurry_test.cmi test/mutable_uncurry_test.cmj test/mutual_non_recursive_type.cmi test/mutual_non_recursive_type.cmj test/name_mangle_test.cmi test/name_mangle_test.cmj test/nested_include.cmi test/nested_include.cmj test/nested_module_alias.cmi test/nested_module_alias.cmj test/nested_obj_literal.cmi test/nested_obj_literal.cmj test/nested_obj_test.cmi test/nested_obj_test.cmj test/nested_pattern_match_test.cmi test/nested_pattern_match_test.cmj test/noassert.cmi test/noassert.cmj test/node_fs_test.cmi test/node_fs_test.cmj test/node_path_test.cmi test/node_path_test.cmj test/null_list_test.cmi test/null_list_test.cmj test/number_lexer.cmi test/number_lexer.cmj test/obj_literal_ppx.cmi test/obj_literal_ppx.cmj test/obj_literal_ppx_test.cmi test/obj_literal_ppx_test.cmj test/obj_magic_test.cmi test/obj_magic_test.cmj test/obj_type_test.cmi test/obj_type_test.cmj test/ocaml_re_test.cmi test/ocaml_re_test.cmj test/of_string_test.cmi test/of_string_test.cmj test/offset.cmi test/offset.cmj test/oo_js_test_date.cmi test/oo_js_test_date.cmj test/option_encoding_test.cmi test/option_encoding_test.cmj test/option_record_none_test.cmi test/option_record_none_test.cmj test/option_repr_test.cmi test/option_repr_test.cmj test/optional_ffi_test.cmi test/optional_ffi_test.cmj test/optional_regression_test.cmi test/optional_regression_test.cmj test/pipe_send_readline.cmi test/pipe_send_readline.cmj test/pipe_syntax.cmi test/pipe_syntax.cmj test/poly_empty_array.cmi test/poly_empty_array.cmj test/poly_type.cmi test/poly_type.cmj test/poly_variant_test.cmi test/poly_variant_test.cmj test/polymorphic_raw_test.cmi test/polymorphic_raw_test.cmj test/polymorphism_test.cmi test/polymorphism_test.cmj test/polyvar_convert.cmi test/polyvar_convert.cmj test/polyvar_test.cmi test/polyvar_test.cmj test/ppx_apply_test.cmi test/ppx_apply_test.cmj test/ppx_this_obj_field.cmi test/ppx_this_obj_field.cmj test/ppx_this_obj_test.cmi test/ppx_this_obj_test.cmj test/pq_test.cmi test/pq_test.cmj test/pr6726.cmi test/pr6726.cmj test/pr_regression_test.cmi test/pr_regression_test.cmj test/prepend_data_ffi.cmi test/prepend_data_ffi.cmj test/primitive_reg_test.cmi test/primitive_reg_test.cmj test/print_alpha_test.cmi test/print_alpha_test.cmj test/promise.cmi test/promise.cmj test/promise_catch_test.cmi test/promise_catch_test.cmj test/queue_402.cmi test/queue_402.cmj test/queue_test.cmi test/queue_test.cmj test/random_test.cmi test/random_test.cmj test/raw_hash_tbl_bench.cmi test/raw_hash_tbl_bench.cmj test/raw_output_test.cmi test/raw_output_test.cmj test/raw_pure_test.cmi test/raw_pure_test.cmj test/rbset.cmi test/rbset.cmj test/re_first_test.cmi test/re_first_test.cmj test/react.cmi test/react.cmj test/reactDOMRe.cmi test/reactDOMRe.cmj test/reactDOMServerRe.cmi test/reactDOMServerRe.cmj test/reactEvent.cmi test/reactEvent.cmj test/reactTestUtils.cmi test/reactTestUtils.cmj test/reasonReact.cmi test/reasonReact.cmj test/reasonReactCompat.cmi test/reasonReactCompat.cmj test/reasonReactOptimizedCreateClass.cmi test/reasonReactOptimizedCreateClass.cmj test/reasonReactRouter.cmi test/reasonReactRouter.cmj test/rebind_module.cmi test/rebind_module.cmj test/rebind_module_test.cmi test/rebind_module_test.cmj test/rec_fun_test.cmi test/rec_fun_test.cmj test/rec_module_opt.cmi test/rec_module_opt.cmj test/rec_module_test.cmi test/rec_module_test.cmj test/rec_value_test.cmi test/rec_value_test.cmj test/record_debug_test.cmi test/record_debug_test.cmj test/record_extension_test.cmi test/record_extension_test.cmj test/record_name_test.cmi test/record_name_test.cmj test/record_regression.cmi test/record_regression.cmj test/record_with_test.cmi test/record_with_test.cmj test/recursive_module.cmi test/recursive_module.cmj test/recursive_module_test.cmi test/recursive_module_test.cmj test/recursive_react_component.cmi test/recursive_react_component.cmj test/recursive_records_test.cmi test/recursive_records_test.cmj test/recursive_unbound_module_test.cmi test/recursive_unbound_module_test.cmj test/regression_print.cmi test/regression_print.cmj test/relative_path.cmi test/relative_path.cmj test/res_debug.cmi test/res_debug.cmj test/return_check.cmi test/return_check.cmj test/runtime_encoding_test.cmi test/runtime_encoding_test.cmj test/set_gen.cmi test/set_gen.cmj test/sexp.cmi test/sexp.cmj test/sexpm.cmi test/sexpm.cmj test/sexpm_test.cmi test/sexpm_test.cmj test/side_effect.cmi test/side_effect.cmj test/side_effect_free.cmi test/side_effect_free.cmj test/simple_derive_test.cmi test/simple_derive_test.cmj test/simple_derive_use.cmi test/simple_derive_use.cmj test/simple_lexer_test.cmi test/simple_lexer_test.cmj test/simplify_lambda_632o.cmi test/simplify_lambda_632o.cmj test/single_module_alias.cmi test/single_module_alias.cmj test/singular_unit_test.cmi test/singular_unit_test.cmj test/small_inline_test.cmi test/small_inline_test.cmj test/splice_test.cmi test/splice_test.cmj test/stack_comp_test.cmi test/stack_comp_test.cmj test/stack_test.cmi test/stack_test.cmj test/stream_parser_test.cmi test/stream_parser_test.cmj test/string_bound_get_test.cmi test/string_bound_get_test.cmj test/string_get_set_test.cmi test/string_get_set_test.cmj test/string_interp_test.cmi test/string_interp_test.cmj test/string_literal_print_test.cmi test/string_literal_print_test.cmj test/string_runtime_test.cmi test/string_runtime_test.cmj test/string_set.cmi test/string_set.cmj test/string_set_test.cmi test/string_set_test.cmj test/string_test.cmi test/string_test.cmj test/string_unicode_test.cmi test/string_unicode_test.cmj test/stringmatch_test.cmi test/stringmatch_test.cmj test/submodule.cmi test/submodule.cmj test/submodule_call.cmi test/submodule_call.cmj test/switch_case_test.cmi test/switch_case_test.cmj test/tailcall_inline_test.cmi test/tailcall_inline_test.cmj test/test.cmi test/test.cmj test/test2.cmi test/test2.cmj test/test_alias.cmi test/test_alias.cmj test/test_ari.cmi test/test_ari.cmj test/test_array.cmi test/test_array.cmj test/test_array_append.cmi test/test_array_append.cmj test/test_array_primitive.cmi test/test_array_primitive.cmj test/test_bool_equal.cmi test/test_bool_equal.cmj test/test_bs_this.cmi test/test_bs_this.cmj test/test_bug.cmi test/test_bug.cmj test/test_bytes.cmi test/test_bytes.cmj test/test_case_opt_collision.cmi test/test_case_opt_collision.cmj test/test_case_set.cmi test/test_case_set.cmj test/test_char.cmi test/test_char.cmj test/test_closure.cmi test/test_closure.cmj test/test_common.cmi test/test_common.cmj test/test_const_elim.cmi test/test_const_elim.cmj test/test_const_propogate.cmi test/test_const_propogate.cmj test/test_cpp.cmi test/test_cpp.cmj test/test_cps.cmi test/test_cps.cmj test/test_demo.cmi test/test_demo.cmj test/test_dup_param.cmi test/test_dup_param.cmj test/test_eq.cmi test/test_eq.cmj test/test_exception.cmi test/test_exception.cmj test/test_exception_escape.cmi test/test_exception_escape.cmj test/test_export2.cmi test/test_export2.cmj test/test_external.cmi test/test_external.cmj test/test_external_unit.cmi test/test_external_unit.cmj test/test_ffi.cmi test/test_ffi.cmj test/test_fib.cmi test/test_fib.cmj test/test_filename.cmi test/test_filename.cmj test/test_for_loop.cmi test/test_for_loop.cmj test/test_for_map.cmi test/test_for_map.cmj test/test_for_map2.cmi test/test_for_map2.cmj test/test_format.cmi test/test_format.cmj test/test_formatter.cmi test/test_formatter.cmj test/test_functor_dead_code.cmi test/test_functor_dead_code.cmj test/test_generative_module.cmi test/test_generative_module.cmj test/test_global_print.cmi test/test_global_print.cmj test/test_google_closure.cmi test/test_google_closure.cmj test/test_http_server.cmi test/test_http_server.cmj test/test_include.cmi test/test_include.cmj test/test_incomplete.cmi test/test_incomplete.cmj test/test_incr_ref.cmi test/test_incr_ref.cmj test/test_index.cmi test/test_index.cmj test/test_int_map_find.cmi test/test_int_map_find.cmj test/test_internalOO.cmi test/test_internalOO.cmj test/test_is_js.cmi test/test_is_js.cmj test/test_js_ffi.cmi test/test_js_ffi.cmj test/test_let.cmi test/test_let.cmj test/test_list.cmi test/test_list.cmj test/test_literal.cmi test/test_literal.cmj test/test_literals.cmi test/test_literals.cmj test/test_match_exception.cmi test/test_match_exception.cmj test/test_mutliple.cmi test/test_mutliple.cmj test/test_nat64.cmi test/test_nat64.cmj test/test_nested_let.cmi test/test_nested_let.cmj test/test_nested_print.cmi test/test_nested_print.cmj test/test_non_export.cmi test/test_non_export.cmj test/test_nullary.cmi test/test_nullary.cmj test/test_obj.cmi test/test_obj.cmj test/test_obj_simple_ffi.cmi test/test_obj_simple_ffi.cmj test/test_order.cmi test/test_order.cmj test/test_order_tailcall.cmi test/test_order_tailcall.cmj test/test_other_exn.cmi test/test_other_exn.cmj test/test_pack.cmi test/test_pack.cmj test/test_per.cmi test/test_per.cmj test/test_pervasive.cmi test/test_pervasive.cmj test/test_pervasives2.cmi test/test_pervasives2.cmj test/test_pervasives3.cmi test/test_pervasives3.cmj test/test_primitive.cmi test/test_primitive.cmj test/test_promise_bind.cmi test/test_promise_bind.cmj test/test_ramification.cmi test/test_ramification.cmj test/test_react.cmi test/test_react.cmj test/test_react_case.cmi test/test_react_case.cmj test/test_regex.cmi test/test_regex.cmj test/test_require.cmi test/test_require.cmj test/test_runtime_encoding.cmi test/test_runtime_encoding.cmj test/test_scope.cmi test/test_scope.cmj test/test_seq.cmi test/test_seq.cmj test/test_set.cmi test/test_set.cmj test/test_side_effect_functor.cmi test/test_side_effect_functor.cmj test/test_simple_include.cmi test/test_simple_include.cmj test/test_simple_pattern_match.cmi test/test_simple_pattern_match.cmj test/test_simple_ref.cmi test/test_simple_ref.cmj test/test_simple_tailcall.cmi test/test_simple_tailcall.cmj test/test_small.cmi test/test_small.cmj test/test_sprintf.cmi test/test_sprintf.cmj test/test_stack.cmi test/test_stack.cmj test/test_static_catch_ident.cmi test/test_static_catch_ident.cmj test/test_string.cmi test/test_string.cmj test/test_string_case.cmi test/test_string_case.cmj test/test_string_const.cmi test/test_string_const.cmj test/test_string_map.cmi test/test_string_map.cmj test/test_string_switch.cmi test/test_string_switch.cmj test/test_switch.cmi test/test_switch.cmj test/test_trywith.cmi test/test_trywith.cmj test/test_tuple.cmi test/test_tuple.cmj test/test_tuple_destructring.cmi test/test_tuple_destructring.cmj test/test_type_based_arity.cmi test/test_type_based_arity.cmj test/test_u.cmi test/test_u.cmj test/test_unsafe_cmp.cmi test/test_unsafe_cmp.cmj test/test_unsafe_obj_ffi.cmi test/test_unsafe_obj_ffi.cmj test/test_unsafe_obj_ffi_ppx.cmi test/test_unsafe_obj_ffi_ppx.cmj test/test_unsupported_primitive.cmi test/test_unsupported_primitive.cmj test/test_while_closure.cmi test/test_while_closure.cmj test/test_while_side_effect.cmi test/test_while_side_effect.cmj test/test_zero_nullable.cmi test/test_zero_nullable.cmj test/then_mangle_test.cmi test/then_mangle_test.cmj test/ticker.cmi test/ticker.cmj test/to_string_test.cmi test/to_string_test.cmj test/topsort_test.cmi test/topsort_test.cmj test/tramp_fib.cmi test/tramp_fib.cmj test/tuple_alloc.cmi test/tuple_alloc.cmj test/type_disambiguate.cmi test/type_disambiguate.cmj test/typeof_test.cmi test/typeof_test.cmj test/ui_defs.cmi test/unboxed_attribute.cmi test/unboxed_attribute.cmj test/unboxed_attribute_test.cmi test/unboxed_attribute_test.cmj test/unboxed_use_case.cmi test/unboxed_use_case.cmj test/uncurry_external_test.cmi test/uncurry_external_test.cmj test/uncurry_glob_test.cmi test/uncurry_glob_test.cmj test/uncurry_method.cmi test/uncurry_method.cmj test/uncurry_test.cmi test/uncurry_test.cmj test/undef_regression2_test.cmi test/undef_regression2_test.cmj test/undef_regression_test.cmi test/undef_regression_test.cmj test/unicode_type_error.cmi test/unicode_type_error.cmj test/unit_undefined_test.cmi test/unit_undefined_test.cmj test/unitest_string.cmi test/unitest_string.cmj test/unsafe_full_apply_primitive.cmi test/unsafe_full_apply_primitive.cmj test/unsafe_obj_external.cmi test/unsafe_obj_external.cmj test/unsafe_ppx_test.cmi test/unsafe_ppx_test.cmj test/unsafe_this.cmi test/unsafe_this.cmj test/update_record_test.cmi test/update_record_test.cmj test/utf8_decode_test.cmi test/utf8_decode_test.cmj test/variant.cmi test/variant.cmj test/watch_test.cmi test/watch_test.cmj test/webpack_config.cmi test/webpack_config.cmj +o test : phony test/406_primitive_test.cmi test/406_primitive_test.cmj test/a.cmi test/a.cmj test/a_filename_test.cmi test/a_filename_test.cmj test/a_list_test.cmi test/a_list_test.cmj test/a_recursive_type.cmi test/a_recursive_type.cmj test/a_scope_bug.cmi test/a_scope_bug.cmj test/a_string_test.cmi test/a_string_test.cmj test/abstract_type.cmi test/abstract_type.cmj test/adt_optimize_test.cmi test/adt_optimize_test.cmj test/alias_test.cmi test/alias_test.cmj test/and_or_tailcall_test.cmi test/and_or_tailcall_test.cmj test/app_root_finder.cmi test/app_root_finder.cmj test/argv_test.cmi test/argv_test.cmj test/ari_regress_test.cmi test/ari_regress_test.cmj test/arith_lexer.cmi test/arith_lexer.cmj test/arith_parser.cmi test/arith_parser.cmj test/arith_syntax.cmi test/arith_syntax.cmj test/arity.cmi test/arity.cmj test/arity_deopt.cmi test/arity_deopt.cmj test/arity_infer.cmi test/arity_infer.cmj test/arity_ml.cmi test/arity_ml.cmj test/array_data_util.cmi test/array_data_util.cmj test/array_safe_get.cmi test/array_safe_get.cmj test/array_subtle_test.cmi test/array_subtle_test.cmj test/array_test.cmi test/array_test.cmj test/ast_abstract_test.cmi test/ast_abstract_test.cmj test/ast_js_mapper_poly_test.cmi test/ast_js_mapper_poly_test.cmj test/ast_js_mapper_test.cmi test/ast_js_mapper_test.cmj test/ast_mapper_defensive_test.cmi test/ast_mapper_defensive_test.cmj test/ast_mapper_unused_warning_test.cmi test/ast_mapper_unused_warning_test.cmj test/async_ideas.cmi test/async_ideas.cmj test/attr_test.cmi test/attr_test.cmj test/b.cmi test/b.cmj test/bal_set_mini.cmi test/bal_set_mini.cmj test/bang_primitive.cmi test/bang_primitive.cmj test/basic_module_test.cmi test/basic_module_test.cmj test/bb.cmi test/bb.cmj test/bdd.cmi test/bdd.cmj test/belt_internal_test.cmi test/belt_internal_test.cmj test/belt_result_alias_test.cmi test/belt_result_alias_test.cmj test/bench.cmi test/bench.cmj test/big_enum.cmi test/big_enum.cmj test/big_polyvar_test.cmi test/big_polyvar_test.cmj test/block_alias_test.cmi test/block_alias_test.cmj test/boolean_test.cmi test/boolean_test.cmj test/bs_MapInt_test.cmi test/bs_MapInt_test.cmj test/bs_abstract_test.cmi test/bs_abstract_test.cmj test/bs_array_test.cmi test/bs_array_test.cmj test/bs_auto_uncurry.cmi test/bs_auto_uncurry.cmj test/bs_auto_uncurry_test.cmi test/bs_auto_uncurry_test.cmj test/bs_float_test.cmi test/bs_float_test.cmj test/bs_hashmap_test.cmi test/bs_hashmap_test.cmj test/bs_hashset_int_test.cmi test/bs_hashset_int_test.cmj test/bs_hashtbl_string_test.cmi test/bs_hashtbl_string_test.cmj test/bs_ignore_effect.cmi test/bs_ignore_effect.cmj test/bs_ignore_test.cmi test/bs_ignore_test.cmj test/bs_int_test.cmi test/bs_int_test.cmj test/bs_list_test.cmi test/bs_list_test.cmj test/bs_map_set_dict_test.cmi test/bs_map_set_dict_test.cmj test/bs_map_test.cmi test/bs_map_test.cmj test/bs_min_max_test.cmi test/bs_min_max_test.cmj test/bs_mutable_set_test.cmi test/bs_mutable_set_test.cmj test/bs_node_string_buffer_test.cmi test/bs_node_string_buffer_test.cmj test/bs_poly_map_test.cmi test/bs_poly_map_test.cmj test/bs_poly_mutable_map_test.cmi test/bs_poly_mutable_map_test.cmj test/bs_poly_mutable_set_test.cmi test/bs_poly_mutable_set_test.cmj test/bs_poly_set_test.cmi test/bs_poly_set_test.cmj test/bs_qualified.cmi test/bs_qualified.cmj test/bs_queue_test.cmi test/bs_queue_test.cmj test/bs_rbset_int_bench.cmi test/bs_rbset_int_bench.cmj test/bs_rest_test.cmi test/bs_rest_test.cmj test/bs_set_bench.cmi test/bs_set_bench.cmj test/bs_set_int_test.cmi test/bs_set_int_test.cmj test/bs_sort_test.cmi test/bs_sort_test.cmj test/bs_splice_partial.cmi test/bs_splice_partial.cmj test/bs_stack_test.cmi test/bs_stack_test.cmj test/bs_string_test.cmi test/bs_string_test.cmj test/bs_unwrap_test.cmi test/bs_unwrap_test.cmj test/buffer_test.cmi test/buffer_test.cmj test/bytes_split_gpr_743_test.cmi test/bytes_split_gpr_743_test.cmj test/caml_compare_test.cmi test/caml_compare_test.cmj test/caml_format_test.cmi test/caml_format_test.cmj test/caml_sys_poly_fill_test.cmi test/caml_sys_poly_fill_test.cmj test/chain_code_test.cmi test/chain_code_test.cmj test/chn_test.cmi test/chn_test.cmj test/class_setter_getter.cmi test/class_setter_getter.cmj test/class_type_ffi_test.cmi test/class_type_ffi_test.cmj test/coercion_module_alias_test.cmi test/coercion_module_alias_test.cmj test/compare_test.cmi test/compare_test.cmj test/complete_parmatch_test.cmi test/complete_parmatch_test.cmj test/complex_if_test.cmi test/complex_if_test.cmj test/complex_test.cmi test/complex_test.cmj test/complex_while_loop.cmi test/complex_while_loop.cmj test/condition_compilation_test.cmi test/condition_compilation_test.cmj test/config1_test.cmi test/config1_test.cmj test/config2_test.cmi test/config2_test.cmj test/console_log_test.cmi test/console_log_test.cmj test/const_block_test.cmi test/const_block_test.cmj test/const_defs.cmi test/const_defs.cmj test/const_defs_test.cmi test/const_defs_test.cmj test/const_test.cmi test/const_test.cmj test/cont_int_fold_test.cmi test/cont_int_fold_test.cmj test/cps_test.cmi test/cps_test.cmj test/cross_module_inline_test.cmi test/cross_module_inline_test.cmj test/custom_error_test.cmi test/custom_error_test.cmj test/debug_keep_test.cmi test/debug_keep_test.cmj test/debug_mode_value.cmi test/debug_mode_value.cmj test/debug_tmp.cmi test/debug_tmp.cmj test/debugger_test.cmi test/debugger_test.cmj test/default_export_test.cmi test/default_export_test.cmj test/defunctor_make_test.cmi test/defunctor_make_test.cmj test/demo.cmi test/demo.cmj test/demo_binding.cmi test/demo_binding.cmj test/demo_int_map.cmi test/demo_int_map.cmj test/demo_page.cmi test/demo_page.cmj test/demo_pipe.cmi test/demo_pipe.cmj test/derive_dyntype.cmi test/derive_dyntype.cmj test/derive_projector_test.cmi test/derive_projector_test.cmj test/derive_type_test.cmi test/derive_type_test.cmj test/digest_test.cmi test/digest_test.cmj test/div_by_zero_test.cmi test/div_by_zero_test.cmj test/dollar_escape_test.cmi test/dollar_escape_test.cmj test/earger_curry_test.cmi test/earger_curry_test.cmj test/effect.cmi test/effect.cmj test/epsilon_test.cmi test/epsilon_test.cmj test/equal_box_test.cmi test/equal_box_test.cmj test/equal_exception_test.cmi test/equal_exception_test.cmj test/equal_test.cmi test/equal_test.cmj test/es6_export.cmi test/es6_export.cmj test/es6_import.cmi test/es6_import.cmj test/es6_module_test.cmi test/es6_module_test.cmj test/escape_esmodule.cmi test/escape_esmodule.cmj test/esmodule_ref.cmi test/esmodule_ref.cmj test/event_ffi.cmi test/event_ffi.cmj test/exception_alias.cmi test/exception_alias.cmj test/exception_def.cmi test/exception_def.cmj test/exception_raise_test.cmi test/exception_raise_test.cmj test/exception_rebind_test.cmi test/exception_rebind_test.cmj test/exception_rebound_err_test.cmi test/exception_rebound_err_test.cmj test/exception_repr_test.cmi test/exception_repr_test.cmj test/exception_value_test.cmi test/exception_value_test.cmj test/exn_error_pattern.cmi test/exn_error_pattern.cmj test/export_keyword.cmi test/export_keyword.cmj test/ext_array_test.cmi test/ext_array_test.cmj test/ext_bytes_test.cmi test/ext_bytes_test.cmj test/ext_filename_test.cmi test/ext_filename_test.cmj test/ext_list_test.cmi test/ext_list_test.cmj test/ext_pervasives_test.cmi test/ext_pervasives_test.cmj test/ext_string_test.cmi test/ext_string_test.cmj test/ext_sys_test.cmi test/ext_sys_test.cmj test/extensible_variant_test.cmi test/extensible_variant_test.cmj test/external_polyfill_test.cmi test/external_polyfill_test.cmj test/external_ppx.cmi test/external_ppx.cmj test/fail_comp.cmi test/fail_comp.cmj test/ffi_arity_test.cmi test/ffi_arity_test.cmj test/ffi_array_test.cmi test/ffi_array_test.cmj test/ffi_js_test.cmi test/ffi_js_test.cmj test/ffi_splice_test.cmi test/ffi_splice_test.cmj test/ffi_test.cmi test/ffi_test.cmj test/fib.cmi test/fib.cmj test/flattern_order_test.cmi test/flattern_order_test.cmj test/flexible_array_test.cmi test/flexible_array_test.cmj test/float_array.cmi test/float_array.cmj test/float_of_bits_test.cmi test/float_of_bits_test.cmj test/float_record.cmi test/float_record.cmj test/float_test.cmi test/float_test.cmj test/floatarray_test.cmi test/floatarray_test.cmj test/flow_parser_reg_test.cmi test/flow_parser_reg_test.cmj test/for_loop_test.cmi test/for_loop_test.cmj test/for_side_effect_test.cmi test/for_side_effect_test.cmj test/format_regression.cmi test/format_regression.cmj test/format_test.cmi test/format_test.cmj test/fs_test.cmi test/fs_test.cmj test/fun_pattern_match.cmi test/fun_pattern_match.cmj test/functor_app_test.cmi test/functor_app_test.cmj test/functor_def.cmi test/functor_def.cmj test/functor_ffi.cmi test/functor_ffi.cmj test/functor_inst.cmi test/functor_inst.cmj test/functors.cmi test/functors.cmj test/gbk.cmi test/gbk.cmj test/genlex_test.cmi test/genlex_test.cmj test/gentTypeReTest.cmi test/gentTypeReTest.cmj test/global_exception_regression_test.cmi test/global_exception_regression_test.cmj test/global_mangles.cmi test/global_mangles.cmj test/global_module_alias_test.cmi test/global_module_alias_test.cmj test/google_closure_test.cmi test/google_closure_test.cmj test/gpr496_test.cmi test/gpr496_test.cmj test/gpr_1063_test.cmi test/gpr_1063_test.cmj test/gpr_1072.cmi test/gpr_1072.cmj test/gpr_1072_reg.cmi test/gpr_1072_reg.cmj test/gpr_1150.cmi test/gpr_1150.cmj test/gpr_1154_test.cmi test/gpr_1154_test.cmj test/gpr_1170.cmi test/gpr_1170.cmj test/gpr_1240_missing_unbox.cmi test/gpr_1240_missing_unbox.cmj test/gpr_1245_test.cmi test/gpr_1245_test.cmj test/gpr_1268.cmi test/gpr_1268.cmj test/gpr_1409_test.cmi test/gpr_1409_test.cmj test/gpr_1423_app_test.cmi test/gpr_1423_app_test.cmj test/gpr_1423_nav.cmi test/gpr_1423_nav.cmj test/gpr_1438.cmi test/gpr_1438.cmj test/gpr_1481.cmi test/gpr_1481.cmj test/gpr_1484.cmi test/gpr_1484.cmj test/gpr_1501_test.cmi test/gpr_1501_test.cmj test/gpr_1503_test.cmi test/gpr_1503_test.cmj test/gpr_1539_test.cmi test/gpr_1539_test.cmj test/gpr_1600_test.cmi test/gpr_1600_test.cmj test/gpr_1658_test.cmi test/gpr_1658_test.cmj test/gpr_1667_test.cmi test/gpr_1667_test.cmj test/gpr_1692_test.cmi test/gpr_1692_test.cmj test/gpr_1698_test.cmi test/gpr_1698_test.cmj test/gpr_1701_test.cmi test/gpr_1701_test.cmj test/gpr_1716_test.cmi test/gpr_1716_test.cmj test/gpr_1717_test.cmi test/gpr_1717_test.cmj test/gpr_1728_test.cmi test/gpr_1728_test.cmj test/gpr_1749_test.cmi test/gpr_1749_test.cmj test/gpr_1759_test.cmi test/gpr_1759_test.cmj test/gpr_1760_test.cmi test/gpr_1760_test.cmj test/gpr_1762_test.cmi test/gpr_1762_test.cmj test/gpr_1817_test.cmi test/gpr_1817_test.cmj test/gpr_1822_test.cmi test/gpr_1822_test.cmj test/gpr_1891_test.cmi test/gpr_1891_test.cmj test/gpr_1943_test.cmi test/gpr_1943_test.cmj test/gpr_1946_test.cmi test/gpr_1946_test.cmj test/gpr_2316_test.cmi test/gpr_2316_test.cmj test/gpr_2352_test.cmi test/gpr_2352_test.cmj test/gpr_2413_test.cmi test/gpr_2413_test.cmj test/gpr_2474.cmi test/gpr_2474.cmj test/gpr_2487.cmi test/gpr_2487.cmj test/gpr_2503_test.cmi test/gpr_2503_test.cmj test/gpr_2608_test.cmi test/gpr_2608_test.cmj test/gpr_2614_test.cmi test/gpr_2614_test.cmj test/gpr_2633_test.cmi test/gpr_2633_test.cmj test/gpr_2642_test.cmi test/gpr_2642_test.cmj test/gpr_2652_test.cmi test/gpr_2652_test.cmj test/gpr_2682_test.cmi test/gpr_2682_test.cmj test/gpr_2700_test.cmi test/gpr_2700_test.cmj test/gpr_2731_test.cmi test/gpr_2731_test.cmj test/gpr_2789_test.cmi test/gpr_2789_test.cmj test/gpr_2863_test.cmi test/gpr_2863_test.cmj test/gpr_2931_test.cmi test/gpr_2931_test.cmj test/gpr_3142_test.cmi test/gpr_3142_test.cmj test/gpr_3154_test.cmi test/gpr_3154_test.cmj test/gpr_3209_test.cmi test/gpr_3209_test.cmj test/gpr_3492_test.cmi test/gpr_3492_test.cmj test/gpr_3502_test.cmi test/gpr_3502_test.cmj test/gpr_3519_jsx_test.cmi test/gpr_3519_jsx_test.cmj test/gpr_3519_test.cmi test/gpr_3519_test.cmj test/gpr_3536_test.cmi test/gpr_3536_test.cmj test/gpr_3546_test.cmi test/gpr_3546_test.cmj test/gpr_3548_test.cmi test/gpr_3548_test.cmj test/gpr_3549_test.cmi test/gpr_3549_test.cmj test/gpr_3566_drive_test.cmi test/gpr_3566_drive_test.cmj test/gpr_3566_test.cmi test/gpr_3566_test.cmj test/gpr_3595_test.cmi test/gpr_3595_test.cmj test/gpr_3609_test.cmi test/gpr_3609_test.cmj test/gpr_3697_test.cmi test/gpr_3697_test.cmj test/gpr_373_test.cmi test/gpr_373_test.cmj test/gpr_3770_test.cmi test/gpr_3770_test.cmj test/gpr_3852_alias.cmi test/gpr_3852_alias.cmj test/gpr_3852_alias_reify.cmi test/gpr_3852_alias_reify.cmj test/gpr_3852_effect.cmi test/gpr_3852_effect.cmj test/gpr_3865.cmi test/gpr_3865.cmj test/gpr_3865_bar.cmi test/gpr_3865_bar.cmj test/gpr_3865_foo.cmi test/gpr_3865_foo.cmj test/gpr_3875_test.cmi test/gpr_3875_test.cmj test/gpr_3877_test.cmi test/gpr_3877_test.cmj test/gpr_3895_test.cmi test/gpr_3895_test.cmj test/gpr_3897_test.cmi test/gpr_3897_test.cmj test/gpr_3931_test.cmi test/gpr_3931_test.cmj test/gpr_3980_test.cmi test/gpr_3980_test.cmj test/gpr_4025_test.cmi test/gpr_4025_test.cmj test/gpr_405_test.cmi test/gpr_405_test.cmj test/gpr_4069_test.cmi test/gpr_4069_test.cmj test/gpr_4265_test.cmi test/gpr_4265_test.cmj test/gpr_4274_test.cmi test/gpr_4274_test.cmj test/gpr_4280_test.cmi test/gpr_4280_test.cmj test/gpr_4407_test.cmi test/gpr_4407_test.cmj test/gpr_441.cmi test/gpr_441.cmj test/gpr_4442_test.cmi test/gpr_4442_test.cmj test/gpr_4491_test.cmi test/gpr_4491_test.cmj test/gpr_4494_test.cmi test/gpr_4494_test.cmj test/gpr_4519_test.cmi test/gpr_4519_test.cmj test/gpr_459_test.cmi test/gpr_459_test.cmj test/gpr_4632.cmi test/gpr_4632.cmj test/gpr_4639_test.cmi test/gpr_4639_test.cmj test/gpr_4900_test.cmi test/gpr_4900_test.cmj test/gpr_4924_test.cmi test/gpr_4924_test.cmj test/gpr_4931.cmi test/gpr_4931.cmj test/gpr_5071_test.cmi test/gpr_5071_test.cmj test/gpr_5169_test.cmi test/gpr_5169_test.cmj test/gpr_5218_test.cmi test/gpr_5218_test.cmj test/gpr_627_test.cmi test/gpr_627_test.cmj test/gpr_658.cmi test/gpr_658.cmj test/gpr_858_test.cmi test/gpr_858_test.cmj test/gpr_858_unit2_test.cmi test/gpr_858_unit2_test.cmj test/gpr_904_test.cmi test/gpr_904_test.cmj test/gpr_974_test.cmi test/gpr_974_test.cmj test/gpr_977_test.cmi test/gpr_977_test.cmj test/gpr_return_type_unused_attribute.cmi test/gpr_return_type_unused_attribute.cmj test/gray_code_test.cmi test/gray_code_test.cmj test/guide_for_ext.cmi test/guide_for_ext.cmj test/hamming_test.cmi test/hamming_test.cmj test/hash_collision_test.cmi test/hash_collision_test.cmj test/hash_sugar_desugar.cmi test/hash_sugar_desugar.cmj test/hash_test.cmi test/hash_test.cmj test/hashtbl_test.cmi test/hashtbl_test.cmj test/hello.foo.cmi test/hello.foo.cmj test/hello_res.cmi test/hello_res.cmj test/http_types.cmi test/http_types.cmj test/ignore_test.cmi test/ignore_test.cmj test/imm_map_bench.cmi test/imm_map_bench.cmj test/include_side_effect.cmi test/include_side_effect.cmj test/include_side_effect_free.cmi test/include_side_effect_free.cmj test/incomplete_toplevel_test.cmi test/incomplete_toplevel_test.cmj test/infer_type_test.cmi test/infer_type_test.cmj test/inline_const.cmi test/inline_const.cmj test/inline_const_test.cmi test/inline_const_test.cmj test/inline_edge_cases.cmi test/inline_edge_cases.cmj test/inline_map2_test.cmi test/inline_map2_test.cmj test/inline_map_demo.cmi test/inline_map_demo.cmj test/inline_map_test.cmi test/inline_map_test.cmj test/inline_record_test.cmi test/inline_record_test.cmj test/inline_regression_test.cmi test/inline_regression_test.cmj test/inline_string_test.cmi test/inline_string_test.cmj test/inner_call.cmi test/inner_call.cmj test/inner_define.cmi test/inner_define.cmj test/inner_unused.cmi test/inner_unused.cmj test/installation_test.cmi test/installation_test.cmj test/int32_test.cmi test/int32_test.cmj test/int64_mul_div_test.cmi test/int64_mul_div_test.cmj test/int64_string_bench.cmi test/int64_string_bench.cmj test/int64_string_test.cmi test/int64_string_test.cmj test/int64_test.cmi test/int64_test.cmj test/int_hashtbl_test.cmi test/int_hashtbl_test.cmj test/int_map.cmi test/int_map.cmj test/int_overflow_test.cmi test/int_overflow_test.cmj test/int_poly_var.cmi test/int_poly_var.cmj test/int_switch_test.cmi test/int_switch_test.cmj test/internal_unused_test.cmi test/internal_unused_test.cmj test/io_test.cmi test/io_test.cmj test/js_array_test.cmi test/js_array_test.cmj test/js_bool_test.cmi test/js_bool_test.cmj test/js_cast_test.cmi test/js_cast_test.cmj test/js_date_test.cmi test/js_date_test.cmj test/js_dict_test.cmi test/js_dict_test.cmj test/js_exception_catch_test.cmi test/js_exception_catch_test.cmj test/js_float_test.cmi test/js_float_test.cmj test/js_global_test.cmi test/js_global_test.cmj test/js_int_test.cmi test/js_int_test.cmj test/js_json_test.cmi test/js_json_test.cmj test/js_list_test.cmi test/js_list_test.cmj test/js_math_test.cmi test/js_math_test.cmj test/js_null_test.cmi test/js_null_test.cmj test/js_null_undefined_test.cmi test/js_null_undefined_test.cmj test/js_nullable_test.cmi test/js_nullable_test.cmj test/js_obj_test.cmi test/js_obj_test.cmj test/js_option_test.cmi test/js_option_test.cmj test/js_promise_basic_test.cmi test/js_promise_basic_test.cmj test/js_re_test.cmi test/js_re_test.cmj test/js_string_test.cmi test/js_string_test.cmj test/js_typed_array_test.cmi test/js_typed_array_test.cmj test/js_undefined_test.cmi test/js_undefined_test.cmj test/js_val.cmi test/js_val.cmj test/jsoo_400_test.cmi test/jsoo_400_test.cmj test/jsoo_485_test.cmi test/jsoo_485_test.cmj test/key_word_property.cmi test/key_word_property.cmj test/key_word_property2.cmi test/key_word_property2.cmj test/key_word_property_plus_test.cmi test/key_word_property_plus_test.cmj test/label_uncurry.cmi test/label_uncurry.cmj test/large_integer_pat.cmi test/large_integer_pat.cmj test/large_record_duplication_test.cmi test/large_record_duplication_test.cmj test/largest_int_flow.cmi test/largest_int_flow.cmj test/lazy_demo.cmi test/lazy_demo.cmj test/lazy_test.cmi test/lazy_test.cmj test/lexer_test.cmi test/lexer_test.cmj test/lib_js_test.cmi test/lib_js_test.cmj test/libarg_test.cmi test/libarg_test.cmj test/libqueue_test.cmi test/libqueue_test.cmj test/limits_test.cmi test/limits_test.cmj test/list_stack.cmi test/list_stack.cmj test/list_test.cmi test/list_test.cmj test/local_class_type.cmi test/local_class_type.cmj test/local_exception_test.cmi test/local_exception_test.cmj test/loop_regression_test.cmi test/loop_regression_test.cmj test/loop_suites_test.cmi test/loop_suites_test.cmj test/map_find_test.cmi test/map_find_test.cmj test/map_test.cmi test/map_test.cmj test/mario_game.cmi test/mario_game.cmj test/marshal.cmi test/marshal.cmj test/method_chain.cmi test/method_chain.cmj test/method_name_test.cmi test/method_name_test.cmj test/method_string_name.cmi test/method_string_name.cmj test/minimal_test.cmi test/minimal_test.cmj test/miss_colon_test.cmi test/miss_colon_test.cmj test/mock_mt.cmi test/mock_mt.cmj test/module_alias_test.cmi test/module_alias_test.cmj test/module_as_class_ffi.cmi test/module_as_class_ffi.cmj test/module_as_function.cmi test/module_as_function.cmj test/module_missing_conversion.cmi test/module_missing_conversion.cmj test/module_parameter_test.cmi test/module_parameter_test.cmj test/module_splice_test.cmi test/module_splice_test.cmj test/more_poly_variant_test.cmi test/more_poly_variant_test.cmj test/more_uncurry.cmi test/more_uncurry.cmj test/mpr_6033_test.cmi test/mpr_6033_test.cmj test/mt.cmi test/mt.cmj test/mt_global.cmi test/mt_global.cmj test/mutable_obj_test.cmi test/mutable_obj_test.cmj test/mutable_uncurry_test.cmi test/mutable_uncurry_test.cmj test/mutual_non_recursive_type.cmi test/mutual_non_recursive_type.cmj test/name_mangle_test.cmi test/name_mangle_test.cmj test/nested_include.cmi test/nested_include.cmj test/nested_module_alias.cmi test/nested_module_alias.cmj test/nested_obj_literal.cmi test/nested_obj_literal.cmj test/nested_obj_test.cmi test/nested_obj_test.cmj test/nested_pattern_match_test.cmi test/nested_pattern_match_test.cmj test/noassert.cmi test/noassert.cmj test/node_fs_test.cmi test/node_fs_test.cmj test/node_path_test.cmi test/node_path_test.cmj test/null_list_test.cmi test/null_list_test.cmj test/number_lexer.cmi test/number_lexer.cmj test/obj_literal_ppx.cmi test/obj_literal_ppx.cmj test/obj_literal_ppx_test.cmi test/obj_literal_ppx_test.cmj test/obj_magic_test.cmi test/obj_magic_test.cmj test/obj_type_test.cmi test/obj_type_test.cmj test/ocaml_re_test.cmi test/ocaml_re_test.cmj test/of_string_test.cmi test/of_string_test.cmj test/offset.cmi test/offset.cmj test/oo_js_test_date.cmi test/oo_js_test_date.cmj test/option_encoding_test.cmi test/option_encoding_test.cmj test/option_record_none_test.cmi test/option_record_none_test.cmj test/option_repr_test.cmi test/option_repr_test.cmj test/optional_ffi_test.cmi test/optional_ffi_test.cmj test/optional_regression_test.cmi test/optional_regression_test.cmj test/pipe_send_readline.cmi test/pipe_send_readline.cmj test/pipe_syntax.cmi test/pipe_syntax.cmj test/poly_empty_array.cmi test/poly_empty_array.cmj test/poly_type.cmi test/poly_type.cmj test/poly_variant_test.cmi test/poly_variant_test.cmj test/polymorphic_raw_test.cmi test/polymorphic_raw_test.cmj test/polymorphism_test.cmi test/polymorphism_test.cmj test/polyvar_convert.cmi test/polyvar_convert.cmj test/polyvar_test.cmi test/polyvar_test.cmj test/ppx_apply_test.cmi test/ppx_apply_test.cmj test/ppx_this_obj_field.cmi test/ppx_this_obj_field.cmj test/ppx_this_obj_test.cmi test/ppx_this_obj_test.cmj test/pq_test.cmi test/pq_test.cmj test/pr6726.cmi test/pr6726.cmj test/pr_regression_test.cmi test/pr_regression_test.cmj test/prepend_data_ffi.cmi test/prepend_data_ffi.cmj test/primitive_reg_test.cmi test/primitive_reg_test.cmj test/print_alpha_test.cmi test/print_alpha_test.cmj test/promise.cmi test/promise.cmj test/promise_catch_test.cmi test/promise_catch_test.cmj test/queue_402.cmi test/queue_402.cmj test/queue_test.cmi test/queue_test.cmj test/random_test.cmi test/random_test.cmj test/raw_hash_tbl_bench.cmi test/raw_hash_tbl_bench.cmj test/raw_output_test.cmi test/raw_output_test.cmj test/raw_pure_test.cmi test/raw_pure_test.cmj test/rbset.cmi test/rbset.cmj test/re_first_test.cmi test/re_first_test.cmj test/react.cmi test/react.cmj test/reactDOMRe.cmi test/reactDOMRe.cmj test/reactDOMServerRe.cmi test/reactDOMServerRe.cmj test/reactEvent.cmi test/reactEvent.cmj test/reactTestUtils.cmi test/reactTestUtils.cmj test/reasonReact.cmi test/reasonReact.cmj test/reasonReactCompat.cmi test/reasonReactCompat.cmj test/reasonReactOptimizedCreateClass.cmi test/reasonReactOptimizedCreateClass.cmj test/reasonReactRouter.cmi test/reasonReactRouter.cmj test/rebind_module.cmi test/rebind_module.cmj test/rebind_module_test.cmi test/rebind_module_test.cmj test/rec_fun_test.cmi test/rec_fun_test.cmj test/rec_module_opt.cmi test/rec_module_opt.cmj test/rec_module_test.cmi test/rec_module_test.cmj test/rec_value_test.cmi test/rec_value_test.cmj test/record_debug_test.cmi test/record_debug_test.cmj test/record_extension_test.cmi test/record_extension_test.cmj test/record_name_test.cmi test/record_name_test.cmj test/record_regression.cmi test/record_regression.cmj test/record_with_test.cmi test/record_with_test.cmj test/recursive_module.cmi test/recursive_module.cmj test/recursive_module_test.cmi test/recursive_module_test.cmj test/recursive_react_component.cmi test/recursive_react_component.cmj test/recursive_records_test.cmi test/recursive_records_test.cmj test/recursive_unbound_module_test.cmi test/recursive_unbound_module_test.cmj test/regression_print.cmi test/regression_print.cmj test/relative_path.cmi test/relative_path.cmj test/res_debug.cmi test/res_debug.cmj test/return_check.cmi test/return_check.cmj test/runtime_encoding_test.cmi test/runtime_encoding_test.cmj test/set_gen.cmi test/set_gen.cmj test/sexp.cmi test/sexp.cmj test/sexpm.cmi test/sexpm.cmj test/sexpm_test.cmi test/sexpm_test.cmj test/side_effect.cmi test/side_effect.cmj test/side_effect_free.cmi test/side_effect_free.cmj test/simple_derive_test.cmi test/simple_derive_test.cmj test/simple_derive_use.cmi test/simple_derive_use.cmj test/simple_lexer_test.cmi test/simple_lexer_test.cmj test/simplify_lambda_632o.cmi test/simplify_lambda_632o.cmj test/single_module_alias.cmi test/single_module_alias.cmj test/singular_unit_test.cmi test/singular_unit_test.cmj test/small_inline_test.cmi test/small_inline_test.cmj test/splice_test.cmi test/splice_test.cmj test/stack_comp_test.cmi test/stack_comp_test.cmj test/stack_test.cmi test/stack_test.cmj test/stream_parser_test.cmi test/stream_parser_test.cmj test/string_bound_get_test.cmi test/string_bound_get_test.cmj test/string_get_set_test.cmi test/string_get_set_test.cmj test/string_interp_test.cmi test/string_interp_test.cmj test/string_literal_print_test.cmi test/string_literal_print_test.cmj test/string_runtime_test.cmi test/string_runtime_test.cmj test/string_set.cmi test/string_set.cmj test/string_set_test.cmi test/string_set_test.cmj test/string_test.cmi test/string_test.cmj test/string_unicode_test.cmi test/string_unicode_test.cmj test/stringmatch_test.cmi test/stringmatch_test.cmj test/submodule.cmi test/submodule.cmj test/submodule_call.cmi test/submodule_call.cmj test/switch_case_test.cmi test/switch_case_test.cmj test/tailcall_inline_test.cmi test/tailcall_inline_test.cmj test/test.cmi test/test.cmj test/test2.cmi test/test2.cmj test/test_alias.cmi test/test_alias.cmj test/test_ari.cmi test/test_ari.cmj test/test_array.cmi test/test_array.cmj test/test_array_append.cmi test/test_array_append.cmj test/test_array_primitive.cmi test/test_array_primitive.cmj test/test_bool_equal.cmi test/test_bool_equal.cmj test/test_bs_this.cmi test/test_bs_this.cmj test/test_bug.cmi test/test_bug.cmj test/test_bytes.cmi test/test_bytes.cmj test/test_case_opt_collision.cmi test/test_case_opt_collision.cmj test/test_case_set.cmi test/test_case_set.cmj test/test_char.cmi test/test_char.cmj test/test_closure.cmi test/test_closure.cmj test/test_common.cmi test/test_common.cmj test/test_const_elim.cmi test/test_const_elim.cmj test/test_const_propogate.cmi test/test_const_propogate.cmj test/test_cpp.cmi test/test_cpp.cmj test/test_cps.cmi test/test_cps.cmj test/test_demo.cmi test/test_demo.cmj test/test_dup_param.cmi test/test_dup_param.cmj test/test_eq.cmi test/test_eq.cmj test/test_exception.cmi test/test_exception.cmj test/test_exception_escape.cmi test/test_exception_escape.cmj test/test_export2.cmi test/test_export2.cmj test/test_external.cmi test/test_external.cmj test/test_external_unit.cmi test/test_external_unit.cmj test/test_ffi.cmi test/test_ffi.cmj test/test_fib.cmi test/test_fib.cmj test/test_filename.cmi test/test_filename.cmj test/test_for_loop.cmi test/test_for_loop.cmj test/test_for_map.cmi test/test_for_map.cmj test/test_for_map2.cmi test/test_for_map2.cmj test/test_format.cmi test/test_format.cmj test/test_formatter.cmi test/test_formatter.cmj test/test_functor_dead_code.cmi test/test_functor_dead_code.cmj test/test_generative_module.cmi test/test_generative_module.cmj test/test_global_print.cmi test/test_global_print.cmj test/test_google_closure.cmi test/test_google_closure.cmj test/test_http_server.cmi test/test_http_server.cmj test/test_include.cmi test/test_include.cmj test/test_incomplete.cmi test/test_incomplete.cmj test/test_incr_ref.cmi test/test_incr_ref.cmj test/test_index.cmi test/test_index.cmj test/test_int_map_find.cmi test/test_int_map_find.cmj test/test_internalOO.cmi test/test_internalOO.cmj test/test_is_js.cmi test/test_is_js.cmj test/test_js_ffi.cmi test/test_js_ffi.cmj test/test_let.cmi test/test_let.cmj test/test_list.cmi test/test_list.cmj test/test_literal.cmi test/test_literal.cmj test/test_literals.cmi test/test_literals.cmj test/test_match_exception.cmi test/test_match_exception.cmj test/test_mutliple.cmi test/test_mutliple.cmj test/test_nat64.cmi test/test_nat64.cmj test/test_nested_let.cmi test/test_nested_let.cmj test/test_nested_print.cmi test/test_nested_print.cmj test/test_non_export.cmi test/test_non_export.cmj test/test_nullary.cmi test/test_nullary.cmj test/test_obj.cmi test/test_obj.cmj test/test_obj_simple_ffi.cmi test/test_obj_simple_ffi.cmj test/test_order.cmi test/test_order.cmj test/test_order_tailcall.cmi test/test_order_tailcall.cmj test/test_other_exn.cmi test/test_other_exn.cmj test/test_pack.cmi test/test_pack.cmj test/test_per.cmi test/test_per.cmj test/test_pervasive.cmi test/test_pervasive.cmj test/test_pervasives2.cmi test/test_pervasives2.cmj test/test_pervasives3.cmi test/test_pervasives3.cmj test/test_primitive.cmi test/test_primitive.cmj test/test_promise_bind.cmi test/test_promise_bind.cmj test/test_ramification.cmi test/test_ramification.cmj test/test_react.cmi test/test_react.cmj test/test_react_case.cmi test/test_react_case.cmj test/test_regex.cmi test/test_regex.cmj test/test_require.cmi test/test_require.cmj test/test_runtime_encoding.cmi test/test_runtime_encoding.cmj test/test_scope.cmi test/test_scope.cmj test/test_seq.cmi test/test_seq.cmj test/test_set.cmi test/test_set.cmj test/test_side_effect_functor.cmi test/test_side_effect_functor.cmj test/test_simple_include.cmi test/test_simple_include.cmj test/test_simple_pattern_match.cmi test/test_simple_pattern_match.cmj test/test_simple_ref.cmi test/test_simple_ref.cmj test/test_simple_tailcall.cmi test/test_simple_tailcall.cmj test/test_small.cmi test/test_small.cmj test/test_sprintf.cmi test/test_sprintf.cmj test/test_stack.cmi test/test_stack.cmj test/test_static_catch_ident.cmi test/test_static_catch_ident.cmj test/test_string.cmi test/test_string.cmj test/test_string_case.cmi test/test_string_case.cmj test/test_string_const.cmi test/test_string_const.cmj test/test_string_map.cmi test/test_string_map.cmj test/test_string_switch.cmi test/test_string_switch.cmj test/test_switch.cmi test/test_switch.cmj test/test_trywith.cmi test/test_trywith.cmj test/test_tuple.cmi test/test_tuple.cmj test/test_tuple_destructring.cmi test/test_tuple_destructring.cmj test/test_type_based_arity.cmi test/test_type_based_arity.cmj test/test_u.cmi test/test_u.cmj test/test_unsafe_cmp.cmi test/test_unsafe_cmp.cmj test/test_unsafe_obj_ffi.cmi test/test_unsafe_obj_ffi.cmj test/test_unsafe_obj_ffi_ppx.cmi test/test_unsafe_obj_ffi_ppx.cmj test/test_unsupported_primitive.cmi test/test_unsupported_primitive.cmj test/test_while_closure.cmi test/test_while_closure.cmj test/test_while_side_effect.cmi test/test_while_side_effect.cmj test/test_zero_nullable.cmi test/test_zero_nullable.cmj test/then_mangle_test.cmi test/then_mangle_test.cmj test/ticker.cmi test/ticker.cmj test/to_string_test.cmi test/to_string_test.cmj test/topsort_test.cmi test/topsort_test.cmj test/tramp_fib.cmi test/tramp_fib.cmj test/tuple_alloc.cmi test/tuple_alloc.cmj test/type_disambiguate.cmi test/type_disambiguate.cmj test/typeof_test.cmi test/typeof_test.cmj test/ui_defs.cmi test/unboxed_attribute.cmi test/unboxed_attribute.cmj test/unboxed_attribute_test.cmi test/unboxed_attribute_test.cmj test/unboxed_crash.cmi test/unboxed_crash.cmj test/unboxed_use_case.cmi test/unboxed_use_case.cmj test/uncurry_external_test.cmi test/uncurry_external_test.cmj test/uncurry_glob_test.cmi test/uncurry_glob_test.cmj test/uncurry_method.cmi test/uncurry_method.cmj test/uncurry_test.cmi test/uncurry_test.cmj test/undef_regression2_test.cmi test/undef_regression2_test.cmj test/undef_regression_test.cmi test/undef_regression_test.cmj test/unicode_type_error.cmi test/unicode_type_error.cmj test/unit_undefined_test.cmi test/unit_undefined_test.cmj test/unitest_string.cmi test/unitest_string.cmj test/unsafe_full_apply_primitive.cmi test/unsafe_full_apply_primitive.cmj test/unsafe_obj_external.cmi test/unsafe_obj_external.cmj test/unsafe_ppx_test.cmi test/unsafe_ppx_test.cmj test/unsafe_this.cmi test/unsafe_this.cmj test/update_record_test.cmi test/update_record_test.cmj test/utf8_decode_test.cmi test/utf8_decode_test.cmj test/variant.cmi test/variant.cmj test/watch_test.cmi test/watch_test.cmj test/webpack_config.cmi test/webpack_config.cmj From a486a38638be8d6d717ad9f695123c7c738f482f Mon Sep 17 00:00:00 2001 From: ZhangHongbo Date: Thu, 16 Sep 2021 09:41:06 +0800 Subject: [PATCH 10/10] snapshot --- lib/4.06.1/unstable/js_compiler.ml | 741 ++++++++++++++--------------- lib/4.06.1/whole_compiler.ml | 741 ++++++++++++++--------------- 2 files changed, 712 insertions(+), 770 deletions(-) diff --git a/lib/4.06.1/unstable/js_compiler.ml b/lib/4.06.1/unstable/js_compiler.ml index 435ca7d8fb..59493c66b0 100644 --- a/lib/4.06.1/unstable/js_compiler.ml +++ b/lib/4.06.1/unstable/js_compiler.ml @@ -73643,7 +73643,16 @@ and pp_function ~return_unit ~is_method cxt (f : P.t) ~fn_state {[ function(x,y){ return u(x,y) } ]} it can be optimized in to either [u] or [Curry.__n(u)] *) - (not is_method) && Ext_list.for_all2_no_exn ls l is_var -> ( + (not is_method) + && Ext_list.for_all2_no_exn ls l is_var + && + match v with + (* This check is needed to avoid some edge cases + {[function(x){return x(x)}]} + here the function is also called `x` + *) + | Id id -> not (Ext_list.exists l (fun x -> Ident.same x id)) + | Qualified _ -> true -> ( let optimize len ~p cxt f v = if p then try_optimize_curry cxt f len function_id else vident cxt f v in @@ -89197,11 +89206,6 @@ end = struct * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - - - - - (* Principle: since in ocaml, the apply order is not specified rules: @@ -89211,12 +89215,9 @@ end = struct other wise the evaluation order is tricky (make sure eval order is correct) *) -type value = - { mutable used : bool ; - lambda : Lam.t - } -let param_hash : _ Hash_ident.t = Hash_ident.create 20 +type value = { mutable used : bool; lambda : Lam.t } +let param_hash : _ Hash_ident.t = Hash_ident.create 20 (* optimize cases like (fun f (a,b){ g (a,b,1)} (e0, e1)) @@ -89232,76 +89233,76 @@ let param_hash : _ Hash_ident.t = Hash_ident.create 20 | _ -> false ) params args' ]} *) -let simple_beta_reduce params body args = +let simple_beta_reduce params body args = let exception Not_simple_apply in - let find_param v opt = - match Hash_ident.find_opt param_hash v with - | Some exp -> - if exp.used then raise_notrace Not_simple_apply - else - exp.used <- true; exp.lambda + let find_param_exn v opt = + match Hash_ident.find_opt param_hash v with + | Some exp -> + if exp.used then raise_notrace Not_simple_apply else exp.used <- true; + exp.lambda | None -> opt - in - let rec aux acc (us : Lam.t list) = - match us with + in + let rec aux_exn acc (us : Lam.t list) = + match us with | [] -> List.rev acc - | (Lvar x as a ) :: rest - -> - aux (find_param x a :: acc) rest - | (Lconst _ as u) :: rest - -> aux (u :: acc) rest - | _ :: _ -> raise_notrace Not_simple_apply - in - match (body : Lam.t) with - | Lprim { primitive ; args = ap_args ; loc = ap_loc} (* There is no lambda in primitive *) - -> (* catch a special case of primitives *) - - let () = - List.iter2 (fun p a -> Hash_ident.add param_hash p {lambda = a; used = false }) params args - in - begin match aux [] ap_args with - | new_args -> - let result = - Hash_ident.fold param_hash (Lam.prim ~primitive ~args:new_args ap_loc) (fun _param {lambda; used} acc -> - if not used then - Lam.seq lambda acc - else acc) in + | (Lvar x as a) :: rest -> aux_exn (find_param_exn x a :: acc) rest + | (Lconst _ as u) :: rest -> aux_exn (u :: acc) rest + | _ :: _ -> raise_notrace Not_simple_apply + in + match (body : Lam.t) with + | Lprim { primitive; args = ap_args; loc = ap_loc } + (* There is no lambda in primitive *) -> ( + (* catch a special case of primitives *) + let () = + List.iter2 + (fun p a -> Hash_ident.add param_hash p { lambda = a; used = false }) + params args + in + try + let new_args = aux_exn [] ap_args in + let result = + Hash_ident.fold param_hash (Lam.prim ~primitive ~args:new_args ap_loc) + (fun _param { lambda; used } acc -> + if not used then Lam.seq lambda acc else acc) + in Hash_ident.clear param_hash; - Some result - | exception _ -> - Hash_ident.clear param_hash ; - None - end - | Lapply { ap_func = - (Lvar _ | Lprim {primitive = Pfield _; args = [Lglobal_module _ ]} as f) ; ap_args ; ap_info } - -> - let () = - List.iter2 (fun p a -> Hash_ident.add param_hash p {lambda = a; used = false }) params args - in - (*since we adde each param only once, - iff it is removed once, no exception, - if it is removed twice there will be exception. - if it is never removed, we have it as rest keys - *) - begin match aux [] ap_args with - | new_args -> - let f = - match f with - | Lvar fn_name -> find_param fn_name f - | _ -> f in - let result = - Hash_ident.fold param_hash (Lam.apply f new_args ap_info ) - (fun _param {lambda; used} acc -> - if not used then - Lam.seq lambda acc - else acc ) + Some result + with Not_simple_apply -> + Hash_ident.clear param_hash; + None) + | Lapply + { + ap_func = + (Lvar _ | Lprim { primitive = Pfield _; args = [ Lglobal_module _ ] }) + as f; + ap_args; + ap_info; + } -> ( + let () = + List.iter2 + (fun p a -> Hash_ident.add param_hash p { lambda = a; used = false }) + params args + in + (*since we adde each param only once, + iff it is removed once, no exception, + if it is removed twice there will be exception. + if it is never removed, we have it as rest keys + *) + try + let new_args = aux_exn [] ap_args in + let f = + match f with Lvar fn_name -> find_param_exn fn_name f | _ -> f + in + let result = + Hash_ident.fold param_hash (Lam.apply f new_args ap_info) + (fun _param { lambda; used } acc -> + if not used then Lam.seq lambda acc else acc) in Hash_ident.clear param_hash; - Some result - | exception _ -> - Hash_ident.clear param_hash; - None - end + Some result + with Not_simple_apply -> + Hash_ident.clear param_hash; + None) | _ -> None end @@ -89747,15 +89748,6 @@ end = struct * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - - - - - - - - - (* A naive beta reduce would break the invariants of the optmization. @@ -89778,88 +89770,83 @@ end = struct ]} we can bound [x] to [100] in a single step *) -let propogate_beta_reduce - (meta : Lam_stats.t) (params : Ident.t list) (body : Lam.t) (args : Lam.t list) = - match Lam_beta_reduce_util.simple_beta_reduce params body args with - | Some x -> x - | None -> - let rest_bindings, rev_new_params = - Ext_list.fold_left2 params args ([],[]) (fun old_param arg (rest_bindings, acc) -> - match arg with - | Lconst _ - | Lvar _ -> rest_bindings , arg :: acc - | _ -> - let p = Ident.rename old_param in - (p,arg) :: rest_bindings , (Lam.var p) :: acc - ) in - let new_body = Lam_bounded_vars.rewrite (Hash_ident.of_list2 (List.rev params) (rev_new_params)) body in - Ext_list.fold_right rest_bindings new_body - (fun (param, arg ) l -> - begin match arg with - | Lprim {primitive = Pmakeblock (_, _, Immutable) ;args ; _} -> - Hash_ident.replace meta.ident_tbl param - (Lam_util.kind_of_lambda_block args ) - | Lprim {primitive = Psome | Psome_not_nest; args = [v]; _} -> - Hash_ident.replace meta.ident_tbl param - (Normal_optional(v)) - | _ -> () end; - Lam_util.refine_let ~kind:Strict param arg l) - - -let propogate_beta_reduce_with_map - (meta : Lam_stats.t) (map : Lam_var_stats.stats Map_ident.t ) params body args = +let propogate_beta_reduce (meta : Lam_stats.t) (params : Ident.t list) + (body : Lam.t) (args : Lam.t list) = match Lam_beta_reduce_util.simple_beta_reduce params body args with | Some x -> x | None -> - let rest_bindings, rev_new_params = - Ext_list.fold_left2 params args ([],[]) - (fun old_param arg (rest_bindings, acc) -> - match arg with - | Lconst _ - | Lvar _ -> rest_bindings , arg :: acc - | Lglobal_module _ - -> - let p = Ident.rename old_param in - (p,arg) :: rest_bindings , (Lam.var p) :: acc - - | _ -> - if Lam_analysis.no_side_effects arg then - match Map_ident.find_exn map old_param with - | stat -> - if Lam_var_stats.top_and_used_zero_or_one stat then - rest_bindings, arg :: acc - else - let p = Ident.rename old_param in - (p,arg) :: rest_bindings , (Lam.var p) :: acc - else - let p = Ident.rename old_param in - (p,arg) :: rest_bindings , (Lam.var p) :: acc ) in - let new_body = Lam_bounded_vars.rewrite (Hash_ident.of_list2 (List.rev params) (rev_new_params)) body in - Ext_list.fold_right rest_bindings new_body - (fun (param, (arg : Lam.t)) l -> - begin match arg with - | Lprim {primitive = Pmakeblock (_, _, Immutable ) ; args} -> - Hash_ident.replace meta.ident_tbl param - (Lam_util.kind_of_lambda_block args ) - - | Lprim {primitive = Psome | Psome_not_nest; args = [v]} -> - Hash_ident.replace meta.ident_tbl param - (Normal_optional(v)); - - | _ -> () end; - Lam_util.refine_let ~kind:Strict param arg l) - - + let rest_bindings, rev_new_params = + Ext_list.fold_left2 params args ([], []) + (fun old_param arg (rest_bindings, acc) -> + match arg with + | Lconst _ | Lvar _ -> (rest_bindings, arg :: acc) + | _ -> + let p = Ident.rename old_param in + ((p, arg) :: rest_bindings, Lam.var p :: acc)) + in + let new_body = + Lam_bounded_vars.rewrite + (Hash_ident.of_list2 (List.rev params) rev_new_params) + body + in + Ext_list.fold_right rest_bindings new_body (fun (param, arg) l -> + (match arg with + | Lprim { primitive = Pmakeblock (_, _, Immutable); args; _ } -> + Hash_ident.replace meta.ident_tbl param + (Lam_util.kind_of_lambda_block args) + | Lprim { primitive = Psome | Psome_not_nest; args = [ v ]; _ } -> + Hash_ident.replace meta.ident_tbl param (Normal_optional v) + | _ -> ()); + Lam_util.refine_let ~kind:Strict param arg l) +let propogate_beta_reduce_with_map (meta : Lam_stats.t) + (map : Lam_var_stats.stats Map_ident.t) params body args = + match Lam_beta_reduce_util.simple_beta_reduce params body args with + | Some x -> x + | None -> + let rest_bindings, rev_new_params = + Ext_list.fold_left2 params args ([], []) + (fun old_param arg (rest_bindings, acc) -> + match arg with + | Lconst _ | Lvar _ -> (rest_bindings, arg :: acc) + | Lglobal_module _ -> + let p = Ident.rename old_param in + ((p, arg) :: rest_bindings, Lam.var p :: acc) + | _ -> + if Lam_analysis.no_side_effects arg then + match Map_ident.find_exn map old_param with + | stat -> + if Lam_var_stats.top_and_used_zero_or_one stat then + (rest_bindings, arg :: acc) + else + let p = Ident.rename old_param in + ((p, arg) :: rest_bindings, Lam.var p :: acc) + else + let p = Ident.rename old_param in + ((p, arg) :: rest_bindings, Lam.var p :: acc)) + in + let new_body = + Lam_bounded_vars.rewrite + (Hash_ident.of_list2 (List.rev params) rev_new_params) + body + in + Ext_list.fold_right rest_bindings new_body + (fun (param, (arg : Lam.t)) l -> + (match arg with + | Lprim { primitive = Pmakeblock (_, _, Immutable); args } -> + Hash_ident.replace meta.ident_tbl param + (Lam_util.kind_of_lambda_block args) + | Lprim { primitive = Psome | Psome_not_nest; args = [ v ] } -> + Hash_ident.replace meta.ident_tbl param (Normal_optional v) + | _ -> ()); + Lam_util.refine_let ~kind:Strict param arg l) let no_names_beta_reduce params body args = - match Lam_beta_reduce_util.simple_beta_reduce params body args with - | Some x -> x - | None -> - Ext_list.fold_left2 params args body - (fun param arg l -> - Lam_util.refine_let ~kind:Strict param arg l) - + match Lam_beta_reduce_util.simple_beta_reduce params body args with + | Some x -> x + | None -> + Ext_list.fold_left2 params args body (fun param arg l -> + Lam_util.refine_let ~kind:Strict param arg l) end module Lam_closure : sig @@ -380102,198 +380089,187 @@ end = struct * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) +let id_is_for_sure_true_in_boolean (tbl : Lam_stats.ident_tbl) id = + match Hash_ident.find_opt tbl id with + | Some (ImmutableBlock _) | Some (Normal_optional _) | Some (MutableBlock _) + -> + true + | Some + ( Constant _ | Module _ | FunctionId _ | Exception | Parameter | NA + | OptionalBlock (_, (Undefined | Null | Null_undefined)) ) + | None -> + false - - - -let id_is_for_sure_true_in_boolean (tbl : Lam_stats.ident_tbl) id = - match Hash_ident.find_opt tbl id with - | Some (ImmutableBlock(_)) - | Some (Normal_optional _ ) - | Some (MutableBlock _) -> true - | Some - (Constant _ | Module _ | FunctionId _ | Exception | Parameter | NA - | OptionalBlock(_, (Undefined | Null | Null_undefined)) - ) - - | None -> false - -let simplify_alias - (meta : Lam_stats.t) - (lam : Lam.t) - : Lam.t = - - let rec simpl (lam : Lam.t) : Lam.t = - match lam with +let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t = + let rec simpl (lam : Lam.t) : Lam.t = + match lam with | Lvar _ -> lam - | Lprim {primitive = (Pfield (i,info) as primitive); args = [arg]; loc} -> - (* ATTENTION: - Main use case, we should detect inline all immutable block .. *) - begin match simpl arg with - | Lvar v as l-> - Lam_util.field_flatten_get (fun _ -> Lam.prim ~primitive ~args:[l] loc ) - v i info meta.ident_tbl - | l -> - Lam.prim ~primitive ~args:[l] loc - end - | Lprim {primitive = (Pval_from_option | Pval_from_option_not_nest as p ); args = [Lvar v as lvar ]} as x -> - begin match Hash_ident.find_opt meta.ident_tbl v with - | Some (OptionalBlock (l,_)) -> l - | _ -> if p = Pval_from_option_not_nest then lvar else x - end - | Lglobal_module _ -> lam - | Lprim {primitive; args; loc } - -> Lam.prim ~primitive ~args:(Ext_list.map args simpl) loc - - | Lifthenelse(Lprim {primitive = Pis_not_none; args = [Lvar id ]} as l1, l2, l3) - -> - begin match Hash_ident.find_opt meta.ident_tbl id with - | Some (ImmutableBlock ( _) | (MutableBlock _ ) - | Normal_optional _) - -> simpl l2 - | Some (OptionalBlock(l, Null)) -> - Lam.if_ - (Lam.not_ (Location.none) ( Lam.prim ~primitive:Pis_null ~args:[l] Location.none)) - (simpl l2) (simpl l3) - | Some (OptionalBlock(l, Undefined)) -> - Lam.if_ - (Lam.not_ Location.none (Lam.prim ~primitive:Pis_undefined ~args:[l] Location.none)) - (simpl l2) (simpl l3) - | Some (OptionalBlock(l, Null_undefined)) -> - Lam.if_ - (Lam.not_ Location.none - ( Lam.prim ~primitive:Pis_null_undefined ~args:[l] Location.none) ) - (simpl l2) (simpl l3) - | Some _ - | None -> Lam.if_ l1 (simpl l2) (simpl l3) - end + | Lprim { primitive = Pfield (i, info) as primitive; args = [ arg ]; loc } + -> ( + (* ATTENTION: + Main use case, we should detect inline all immutable block .. *) + match simpl arg with + | Lvar v as l -> + Lam_util.field_flatten_get + (fun _ -> Lam.prim ~primitive ~args:[ l ] loc) + v i info meta.ident_tbl + | l -> Lam.prim ~primitive ~args:[ l ] loc) + | Lprim + { + primitive = (Pval_from_option | Pval_from_option_not_nest) as p; + args = [ (Lvar v as lvar) ]; + } as x -> ( + match Hash_ident.find_opt meta.ident_tbl v with + | Some (OptionalBlock (l, _)) -> l + | _ -> if p = Pval_from_option_not_nest then lvar else x) + | Lglobal_module _ -> lam + | Lprim { primitive; args; loc } -> + Lam.prim ~primitive ~args:(Ext_list.map args simpl) loc + | Lifthenelse + ((Lprim { primitive = Pis_not_none; args = [ Lvar id ] } as l1), l2, l3) + -> ( + match Hash_ident.find_opt meta.ident_tbl id with + | Some (ImmutableBlock _ | MutableBlock _ | Normal_optional _) -> + simpl l2 + | Some (OptionalBlock (l, Null)) -> + Lam.if_ + (Lam.not_ Location.none + (Lam.prim ~primitive:Pis_null ~args:[ l ] Location.none)) + (simpl l2) (simpl l3) + | Some (OptionalBlock (l, Undefined)) -> + Lam.if_ + (Lam.not_ Location.none + (Lam.prim ~primitive:Pis_undefined ~args:[ l ] Location.none)) + (simpl l2) (simpl l3) + | Some (OptionalBlock (l, Null_undefined)) -> + Lam.if_ + (Lam.not_ Location.none + (Lam.prim ~primitive:Pis_null_undefined ~args:[ l ] + Location.none)) + (simpl l2) (simpl l3) + | Some _ | None -> Lam.if_ l1 (simpl l2) (simpl l3)) (* could be the code path - {[ match x with - | h::hs -> + {[ match x with + | h::hs -> ]} - *) - | Lifthenelse (l1, l2, l3) -> - begin match l1 with - | Lvar id when id_is_for_sure_true_in_boolean meta.ident_tbl id-> - simpl l2 - | _ -> - Lam.if_ (simpl l1) (simpl l2) (simpl l3) - end + *) + | Lifthenelse (l1, l2, l3) -> ( + match l1 with + | Lvar id when id_is_for_sure_true_in_boolean meta.ident_tbl id -> + simpl l2 + | _ -> Lam.if_ (simpl l1) (simpl l2) (simpl l3)) | Lconst _ -> lam - | Llet(str, v, l1, l2) -> - Lam.let_ str v (simpl l1) (simpl l2 ) - | Lletrec(bindings, body) -> - let bindings = Ext_list.map_snd bindings simpl in - Lam.letrec bindings (simpl body) - - (* complicated - 1. inline this function - 2. ... - exports.Make= - function(funarg) - {var $$let=Make(funarg); - return [0, $$let[5],... $$let[16]]} - *) - | Lapply{ap_func = - Lprim {primitive = Pfield (_, Fld_module {name = fld_name}) ; - args = [ Lglobal_module ident ]; - _} as l1; - ap_args = args; ap_info } -> - begin - match Lam_compile_env.query_external_id_info ident fld_name with - | {persistent_closed_lambda=Some Lfunction{params; body; _} } - (* be more cautious when do cross module inlining *) - when - Ext_list.same_length params args && - Ext_list.for_all args (fun arg -> - match arg with - | Lvar p -> - begin - match Hash_ident.find_opt meta.ident_tbl p with - | Some v -> v <> Parameter - | None -> true - end - | _ -> true - ) -> - simpl (Lam_beta_reduce.propogate_beta_reduce - meta params body args) - | _ -> - Lam.apply (simpl l1) (Ext_list.map args simpl) ap_info - - - end + | Llet (str, v, l1, l2) -> Lam.let_ str v (simpl l1) (simpl l2) + | Lletrec (bindings, body) -> + let bindings = Ext_list.map_snd bindings simpl in + Lam.letrec bindings (simpl body) + (* complicated + 1. inline this function + 2. ... + exports.Make= + function(funarg) + {var $$let=Make(funarg); + return [0, $$let[5],... $$let[16]]} + *) + | Lapply + { + ap_func = + Lprim + { + primitive = Pfield (_, Fld_module { name = fld_name }); + args = [ Lglobal_module ident ]; + _; + } as l1; + ap_args = args; + ap_info; + } -> ( + match Lam_compile_env.query_external_id_info ident fld_name with + | { persistent_closed_lambda = Some (Lfunction { params; body; _ }) } + (* be more cautious when do cross module inlining *) + when Ext_list.same_length params args + && Ext_list.for_all args (fun arg -> + match arg with + | Lvar p -> ( + match Hash_ident.find_opt meta.ident_tbl p with + | Some v -> v <> Parameter + | None -> true) + | _ -> true) -> + simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) + | _ -> Lam.apply (simpl l1) (Ext_list.map args simpl) ap_info) (* Function inlining interact with other optimizations... - parameter attributes - - scope issues - - code bloat - *) - | Lapply{ap_func = (Lvar v as fn); ap_args = args; ap_info } -> - (* Check info for always inlining *) - - (* Ext_log.dwarn __LOC__ "%s/%d" v.name v.stamp; *) - let normal () = Lam.apply ( simpl fn) (Ext_list.map args simpl) ap_info in - begin - match Hash_ident.find_opt meta.ident_tbl v with - | Some (FunctionId {lambda = Some(Lfunction ({params; body; attr = {is_a_functor}} as m), - rec_flag) - }) - -> + - scope issues + - code bloat + *) + | Lapply { ap_func = Lvar v as fn; ap_args; ap_info } -> ( + (* Check info for always inlining *) - if Ext_list.same_length args params (* && false *) - then - if is_a_functor - (* && (Set_ident.mem v meta.export_idents) && false *) - then - (* TODO: check l1 if it is exported, - if so, maybe not since in that case, - we are going to have two copy? - *) + (* Ext_log.dwarn __LOC__ "%s/%d" v.name v.stamp; *) + let ap_args = Ext_list.map ap_args simpl in + let[@local] normal () = Lam.apply (simpl fn) ap_args ap_info in + match Hash_ident.find_opt meta.ident_tbl v with + | Some + (FunctionId + { + lambda = + Some + ( Lfunction ({ params; body; attr = { is_a_functor } } as m), + rec_flag ); + }) -> + if Ext_list.same_length ap_args params (* && false *) then + if + is_a_functor + (* && (Set_ident.mem v meta.export_idents) && false *) + then + (* TODO: check l1 if it is exported, + if so, maybe not since in that case, + we are going to have two copy? + *) - (* Check: recursive applying may result in non-termination *) - begin + (* Check: recursive applying may result in non-termination *) (* Ext_log.dwarn __LOC__ "beta .. %s/%d" v.name v.stamp ; *) - simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) - end - else - if (* Lam_analysis.size body < Lam_analysis.small_inline_size *) - (* ap_inlined = Always_inline || *) - Lam_analysis.ok_to_inline_fun_when_app m args - then - - (* let param_map = *) - (* Lam_analysis.free_variables meta.export_idents *) - (* (Lam_analysis.param_map_of_list params) body in *) - (* let old_count = List.length params in *) - (* let new_count = Map_ident.cardinal param_map in *) - let param_map = - Lam_closure.is_closed_with_map - meta.export_idents params body in - let is_export_id = Set_ident.mem meta.export_idents v in - match is_export_id, param_map with - | false, (_, param_map) - | true, (true, param_map) -> - begin match rec_flag with - - | Lam_rec -> Lam_beta_reduce.propogate_beta_reduce_with_map meta param_map params body args - | Lam_self_rec -> normal () - | Lam_non_rec -> - simpl - (Lam_beta_reduce.propogate_beta_reduce_with_map meta param_map params body args) - end - | _ -> normal () - else - normal () - else - normal () - | Some _ - | None -> normal () - - end - - | Lapply{ ap_func = Lfunction{ params; body}; ap_args = args; _} - when Ext_list.same_length params args -> - simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) + simpl + (Lam_beta_reduce.propogate_beta_reduce meta params body + ap_args) + else if + (* Lam_analysis.size body < Lam_analysis.small_inline_size *) + (* ap_inlined = Always_inline || *) + Lam_analysis.ok_to_inline_fun_when_app m ap_args + then + (* let param_map = *) + (* Lam_analysis.free_variables meta.export_idents *) + (* (Lam_analysis.param_map_of_list params) body in *) + (* let old_count = List.length params in *) + (* let new_count = Map_ident.cardinal param_map in *) + let param_map = + Lam_closure.is_closed_with_map meta.export_idents params body + in + let is_export_id = Set_ident.mem meta.export_idents v in + match (is_export_id, param_map) with + | false, (_, param_map) | true, (true, param_map) -> ( + match rec_flag with + | Lam_rec -> + Lam_beta_reduce.propogate_beta_reduce_with_map meta + param_map params body ap_args + | Lam_self_rec -> normal () + | Lam_non_rec -> + if + Ext_list.exists ap_args (fun lam -> + Lam_hit.hit_variable v lam) + (*avoid nontermination, e.g, `g(g)`*) + then normal () + else + simpl + (Lam_beta_reduce.propogate_beta_reduce_with_map meta + param_map params body ap_args)) + | _ -> normal () + else normal () + else normal () + | Some _ | None -> normal ()) + | Lapply { ap_func = Lfunction { params; body }; ap_args = args; _ } + when Ext_list.same_length params args -> + simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) (* | Lapply{ fn = Lfunction{function_kind = Tupled; params; body}; *) (* args = [Lprim {primitive = Pmakeblock _; args; _}]; _} *) (* (\** TODO: keep track of this parameter in ocaml trunk, *) @@ -380301,52 +380277,47 @@ let simplify_alias (* *\) *) (* when Ext_list.same_length params args -> *) (* simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) *) - - | Lapply { ap_func = l1; ap_args = ll; ap_info; } -> - Lam.apply (simpl l1) (Ext_list.map ll simpl) ap_info - | Lfunction {arity; params; body; attr} - -> Lam.function_ ~arity ~params ~body:(simpl body) ~attr - | Lswitch (l, {sw_failaction; - sw_consts; - sw_blocks; - sw_blocks_full; - sw_consts_full; - sw_names; - }) -> - Lam.switch (simpl l) - {sw_consts = - Ext_list.map_snd sw_consts simpl; - sw_blocks = Ext_list.map_snd sw_blocks simpl; - sw_consts_full; - sw_blocks_full; - sw_failaction = Ext_option.map sw_failaction simpl; - sw_names; - } - | Lstringswitch(l, sw, d) -> - Lam.stringswitch (simpl l ) - (Ext_list.map_snd sw simpl) - (Ext_option.map d simpl) - | Lstaticraise (i,ls) -> - Lam.staticraise i (Ext_list.map ls simpl ) - | Lstaticcatch (l1, ids, l2) -> - Lam.staticcatch (simpl l1) ids (simpl l2) - | Ltrywith (l1, v, l2) -> Lam.try_ (simpl l1) v (simpl l2) - | Lsequence(l1, l2) - -> Lam.seq (simpl l1) (simpl l2) - | Lwhile(l1, l2) - -> Lam.while_ (simpl l1) (simpl l2) - | Lfor(flag, l1, l2, dir, l3) - -> - Lam.for_ flag (simpl l1) (simpl l2) dir (simpl l3) - | Lassign(v, l) -> - (* Lalias-bound variables are never assigned, so don't increase - v's refsimpl *) - Lam.assign v (simpl l) - in + | Lapply { ap_func = l1; ap_args = ll; ap_info } -> + Lam.apply (simpl l1) (Ext_list.map ll simpl) ap_info + | Lfunction { arity; params; body; attr } -> + Lam.function_ ~arity ~params ~body:(simpl body) ~attr + | Lswitch + ( l, + { + sw_failaction; + sw_consts; + sw_blocks; + sw_blocks_full; + sw_consts_full; + sw_names; + } ) -> + Lam.switch (simpl l) + { + sw_consts = Ext_list.map_snd sw_consts simpl; + sw_blocks = Ext_list.map_snd sw_blocks simpl; + sw_consts_full; + sw_blocks_full; + sw_failaction = Ext_option.map sw_failaction simpl; + sw_names; + } + | Lstringswitch (l, sw, d) -> + Lam.stringswitch (simpl l) + (Ext_list.map_snd sw simpl) + (Ext_option.map d simpl) + | Lstaticraise (i, ls) -> Lam.staticraise i (Ext_list.map ls simpl) + | Lstaticcatch (l1, ids, l2) -> Lam.staticcatch (simpl l1) ids (simpl l2) + | Ltrywith (l1, v, l2) -> Lam.try_ (simpl l1) v (simpl l2) + | Lsequence (l1, l2) -> Lam.seq (simpl l1) (simpl l2) + | Lwhile (l1, l2) -> Lam.while_ (simpl l1) (simpl l2) + | Lfor (flag, l1, l2, dir, l3) -> + Lam.for_ flag (simpl l1) (simpl l2) dir (simpl l3) + | Lassign (v, l) -> + (* Lalias-bound variables are never assigned, so don't increase + v's refsimpl *) + Lam.assign v (simpl l) + in simpl lam - - end module Ext_log : sig #1 "ext_log.mli" diff --git a/lib/4.06.1/whole_compiler.ml b/lib/4.06.1/whole_compiler.ml index a673e8eec7..dd3c0a3b2d 100644 --- a/lib/4.06.1/whole_compiler.ml +++ b/lib/4.06.1/whole_compiler.ml @@ -365134,7 +365134,16 @@ and pp_function ~return_unit ~is_method cxt (f : P.t) ~fn_state {[ function(x,y){ return u(x,y) } ]} it can be optimized in to either [u] or [Curry.__n(u)] *) - (not is_method) && Ext_list.for_all2_no_exn ls l is_var -> ( + (not is_method) + && Ext_list.for_all2_no_exn ls l is_var + && + match v with + (* This check is needed to avoid some edge cases + {[function(x){return x(x)}]} + here the function is also called `x` + *) + | Id id -> not (Ext_list.exists l (fun x -> Ident.same x id)) + | Qualified _ -> true -> ( let optimize len ~p cxt f v = if p then try_optimize_curry cxt f len function_id else vident cxt f v in @@ -373252,11 +373261,6 @@ end = struct * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - - - - - (* Principle: since in ocaml, the apply order is not specified rules: @@ -373266,12 +373270,9 @@ end = struct other wise the evaluation order is tricky (make sure eval order is correct) *) -type value = - { mutable used : bool ; - lambda : Lam.t - } -let param_hash : _ Hash_ident.t = Hash_ident.create 20 +type value = { mutable used : bool; lambda : Lam.t } +let param_hash : _ Hash_ident.t = Hash_ident.create 20 (* optimize cases like (fun f (a,b){ g (a,b,1)} (e0, e1)) @@ -373287,76 +373288,76 @@ let param_hash : _ Hash_ident.t = Hash_ident.create 20 | _ -> false ) params args' ]} *) -let simple_beta_reduce params body args = +let simple_beta_reduce params body args = let exception Not_simple_apply in - let find_param v opt = - match Hash_ident.find_opt param_hash v with - | Some exp -> - if exp.used then raise_notrace Not_simple_apply - else - exp.used <- true; exp.lambda + let find_param_exn v opt = + match Hash_ident.find_opt param_hash v with + | Some exp -> + if exp.used then raise_notrace Not_simple_apply else exp.used <- true; + exp.lambda | None -> opt - in - let rec aux acc (us : Lam.t list) = - match us with + in + let rec aux_exn acc (us : Lam.t list) = + match us with | [] -> List.rev acc - | (Lvar x as a ) :: rest - -> - aux (find_param x a :: acc) rest - | (Lconst _ as u) :: rest - -> aux (u :: acc) rest - | _ :: _ -> raise_notrace Not_simple_apply - in - match (body : Lam.t) with - | Lprim { primitive ; args = ap_args ; loc = ap_loc} (* There is no lambda in primitive *) - -> (* catch a special case of primitives *) - - let () = - List.iter2 (fun p a -> Hash_ident.add param_hash p {lambda = a; used = false }) params args - in - begin match aux [] ap_args with - | new_args -> - let result = - Hash_ident.fold param_hash (Lam.prim ~primitive ~args:new_args ap_loc) (fun _param {lambda; used} acc -> - if not used then - Lam.seq lambda acc - else acc) in + | (Lvar x as a) :: rest -> aux_exn (find_param_exn x a :: acc) rest + | (Lconst _ as u) :: rest -> aux_exn (u :: acc) rest + | _ :: _ -> raise_notrace Not_simple_apply + in + match (body : Lam.t) with + | Lprim { primitive; args = ap_args; loc = ap_loc } + (* There is no lambda in primitive *) -> ( + (* catch a special case of primitives *) + let () = + List.iter2 + (fun p a -> Hash_ident.add param_hash p { lambda = a; used = false }) + params args + in + try + let new_args = aux_exn [] ap_args in + let result = + Hash_ident.fold param_hash (Lam.prim ~primitive ~args:new_args ap_loc) + (fun _param { lambda; used } acc -> + if not used then Lam.seq lambda acc else acc) + in Hash_ident.clear param_hash; - Some result - | exception _ -> - Hash_ident.clear param_hash ; - None - end - | Lapply { ap_func = - (Lvar _ | Lprim {primitive = Pfield _; args = [Lglobal_module _ ]} as f) ; ap_args ; ap_info } - -> - let () = - List.iter2 (fun p a -> Hash_ident.add param_hash p {lambda = a; used = false }) params args - in - (*since we adde each param only once, - iff it is removed once, no exception, - if it is removed twice there will be exception. - if it is never removed, we have it as rest keys - *) - begin match aux [] ap_args with - | new_args -> - let f = - match f with - | Lvar fn_name -> find_param fn_name f - | _ -> f in - let result = - Hash_ident.fold param_hash (Lam.apply f new_args ap_info ) - (fun _param {lambda; used} acc -> - if not used then - Lam.seq lambda acc - else acc ) + Some result + with Not_simple_apply -> + Hash_ident.clear param_hash; + None) + | Lapply + { + ap_func = + (Lvar _ | Lprim { primitive = Pfield _; args = [ Lglobal_module _ ] }) + as f; + ap_args; + ap_info; + } -> ( + let () = + List.iter2 + (fun p a -> Hash_ident.add param_hash p { lambda = a; used = false }) + params args + in + (*since we adde each param only once, + iff it is removed once, no exception, + if it is removed twice there will be exception. + if it is never removed, we have it as rest keys + *) + try + let new_args = aux_exn [] ap_args in + let f = + match f with Lvar fn_name -> find_param_exn fn_name f | _ -> f + in + let result = + Hash_ident.fold param_hash (Lam.apply f new_args ap_info) + (fun _param { lambda; used } acc -> + if not used then Lam.seq lambda acc else acc) in Hash_ident.clear param_hash; - Some result - | exception _ -> - Hash_ident.clear param_hash; - None - end + Some result + with Not_simple_apply -> + Hash_ident.clear param_hash; + None) | _ -> None end @@ -373802,15 +373803,6 @@ end = struct * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - - - - - - - - - (* A naive beta reduce would break the invariants of the optmization. @@ -373833,88 +373825,83 @@ end = struct ]} we can bound [x] to [100] in a single step *) -let propogate_beta_reduce - (meta : Lam_stats.t) (params : Ident.t list) (body : Lam.t) (args : Lam.t list) = - match Lam_beta_reduce_util.simple_beta_reduce params body args with - | Some x -> x - | None -> - let rest_bindings, rev_new_params = - Ext_list.fold_left2 params args ([],[]) (fun old_param arg (rest_bindings, acc) -> - match arg with - | Lconst _ - | Lvar _ -> rest_bindings , arg :: acc - | _ -> - let p = Ident.rename old_param in - (p,arg) :: rest_bindings , (Lam.var p) :: acc - ) in - let new_body = Lam_bounded_vars.rewrite (Hash_ident.of_list2 (List.rev params) (rev_new_params)) body in - Ext_list.fold_right rest_bindings new_body - (fun (param, arg ) l -> - begin match arg with - | Lprim {primitive = Pmakeblock (_, _, Immutable) ;args ; _} -> - Hash_ident.replace meta.ident_tbl param - (Lam_util.kind_of_lambda_block args ) - | Lprim {primitive = Psome | Psome_not_nest; args = [v]; _} -> - Hash_ident.replace meta.ident_tbl param - (Normal_optional(v)) - | _ -> () end; - Lam_util.refine_let ~kind:Strict param arg l) - - -let propogate_beta_reduce_with_map - (meta : Lam_stats.t) (map : Lam_var_stats.stats Map_ident.t ) params body args = +let propogate_beta_reduce (meta : Lam_stats.t) (params : Ident.t list) + (body : Lam.t) (args : Lam.t list) = match Lam_beta_reduce_util.simple_beta_reduce params body args with | Some x -> x | None -> - let rest_bindings, rev_new_params = - Ext_list.fold_left2 params args ([],[]) - (fun old_param arg (rest_bindings, acc) -> - match arg with - | Lconst _ - | Lvar _ -> rest_bindings , arg :: acc - | Lglobal_module _ - -> - let p = Ident.rename old_param in - (p,arg) :: rest_bindings , (Lam.var p) :: acc - - | _ -> - if Lam_analysis.no_side_effects arg then - match Map_ident.find_exn map old_param with - | stat -> - if Lam_var_stats.top_and_used_zero_or_one stat then - rest_bindings, arg :: acc - else - let p = Ident.rename old_param in - (p,arg) :: rest_bindings , (Lam.var p) :: acc - else - let p = Ident.rename old_param in - (p,arg) :: rest_bindings , (Lam.var p) :: acc ) in - let new_body = Lam_bounded_vars.rewrite (Hash_ident.of_list2 (List.rev params) (rev_new_params)) body in - Ext_list.fold_right rest_bindings new_body - (fun (param, (arg : Lam.t)) l -> - begin match arg with - | Lprim {primitive = Pmakeblock (_, _, Immutable ) ; args} -> - Hash_ident.replace meta.ident_tbl param - (Lam_util.kind_of_lambda_block args ) - - | Lprim {primitive = Psome | Psome_not_nest; args = [v]} -> - Hash_ident.replace meta.ident_tbl param - (Normal_optional(v)); - - | _ -> () end; - Lam_util.refine_let ~kind:Strict param arg l) - - + let rest_bindings, rev_new_params = + Ext_list.fold_left2 params args ([], []) + (fun old_param arg (rest_bindings, acc) -> + match arg with + | Lconst _ | Lvar _ -> (rest_bindings, arg :: acc) + | _ -> + let p = Ident.rename old_param in + ((p, arg) :: rest_bindings, Lam.var p :: acc)) + in + let new_body = + Lam_bounded_vars.rewrite + (Hash_ident.of_list2 (List.rev params) rev_new_params) + body + in + Ext_list.fold_right rest_bindings new_body (fun (param, arg) l -> + (match arg with + | Lprim { primitive = Pmakeblock (_, _, Immutable); args; _ } -> + Hash_ident.replace meta.ident_tbl param + (Lam_util.kind_of_lambda_block args) + | Lprim { primitive = Psome | Psome_not_nest; args = [ v ]; _ } -> + Hash_ident.replace meta.ident_tbl param (Normal_optional v) + | _ -> ()); + Lam_util.refine_let ~kind:Strict param arg l) +let propogate_beta_reduce_with_map (meta : Lam_stats.t) + (map : Lam_var_stats.stats Map_ident.t) params body args = + match Lam_beta_reduce_util.simple_beta_reduce params body args with + | Some x -> x + | None -> + let rest_bindings, rev_new_params = + Ext_list.fold_left2 params args ([], []) + (fun old_param arg (rest_bindings, acc) -> + match arg with + | Lconst _ | Lvar _ -> (rest_bindings, arg :: acc) + | Lglobal_module _ -> + let p = Ident.rename old_param in + ((p, arg) :: rest_bindings, Lam.var p :: acc) + | _ -> + if Lam_analysis.no_side_effects arg then + match Map_ident.find_exn map old_param with + | stat -> + if Lam_var_stats.top_and_used_zero_or_one stat then + (rest_bindings, arg :: acc) + else + let p = Ident.rename old_param in + ((p, arg) :: rest_bindings, Lam.var p :: acc) + else + let p = Ident.rename old_param in + ((p, arg) :: rest_bindings, Lam.var p :: acc)) + in + let new_body = + Lam_bounded_vars.rewrite + (Hash_ident.of_list2 (List.rev params) rev_new_params) + body + in + Ext_list.fold_right rest_bindings new_body + (fun (param, (arg : Lam.t)) l -> + (match arg with + | Lprim { primitive = Pmakeblock (_, _, Immutable); args } -> + Hash_ident.replace meta.ident_tbl param + (Lam_util.kind_of_lambda_block args) + | Lprim { primitive = Psome | Psome_not_nest; args = [ v ] } -> + Hash_ident.replace meta.ident_tbl param (Normal_optional v) + | _ -> ()); + Lam_util.refine_let ~kind:Strict param arg l) let no_names_beta_reduce params body args = - match Lam_beta_reduce_util.simple_beta_reduce params body args with - | Some x -> x - | None -> - Ext_list.fold_left2 params args body - (fun param arg l -> - Lam_util.refine_let ~kind:Strict param arg l) - + match Lam_beta_reduce_util.simple_beta_reduce params body args with + | Some x -> x + | None -> + Ext_list.fold_left2 params args body (fun param arg l -> + Lam_util.refine_let ~kind:Strict param arg l) end module Lam_closure : sig @@ -384712,198 +384699,187 @@ end = struct * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) +let id_is_for_sure_true_in_boolean (tbl : Lam_stats.ident_tbl) id = + match Hash_ident.find_opt tbl id with + | Some (ImmutableBlock _) | Some (Normal_optional _) | Some (MutableBlock _) + -> + true + | Some + ( Constant _ | Module _ | FunctionId _ | Exception | Parameter | NA + | OptionalBlock (_, (Undefined | Null | Null_undefined)) ) + | None -> + false - - - -let id_is_for_sure_true_in_boolean (tbl : Lam_stats.ident_tbl) id = - match Hash_ident.find_opt tbl id with - | Some (ImmutableBlock(_)) - | Some (Normal_optional _ ) - | Some (MutableBlock _) -> true - | Some - (Constant _ | Module _ | FunctionId _ | Exception | Parameter | NA - | OptionalBlock(_, (Undefined | Null | Null_undefined)) - ) - - | None -> false - -let simplify_alias - (meta : Lam_stats.t) - (lam : Lam.t) - : Lam.t = - - let rec simpl (lam : Lam.t) : Lam.t = - match lam with +let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t = + let rec simpl (lam : Lam.t) : Lam.t = + match lam with | Lvar _ -> lam - | Lprim {primitive = (Pfield (i,info) as primitive); args = [arg]; loc} -> - (* ATTENTION: - Main use case, we should detect inline all immutable block .. *) - begin match simpl arg with - | Lvar v as l-> - Lam_util.field_flatten_get (fun _ -> Lam.prim ~primitive ~args:[l] loc ) - v i info meta.ident_tbl - | l -> - Lam.prim ~primitive ~args:[l] loc - end - | Lprim {primitive = (Pval_from_option | Pval_from_option_not_nest as p ); args = [Lvar v as lvar ]} as x -> - begin match Hash_ident.find_opt meta.ident_tbl v with - | Some (OptionalBlock (l,_)) -> l - | _ -> if p = Pval_from_option_not_nest then lvar else x - end - | Lglobal_module _ -> lam - | Lprim {primitive; args; loc } - -> Lam.prim ~primitive ~args:(Ext_list.map args simpl) loc - - | Lifthenelse(Lprim {primitive = Pis_not_none; args = [Lvar id ]} as l1, l2, l3) - -> - begin match Hash_ident.find_opt meta.ident_tbl id with - | Some (ImmutableBlock ( _) | (MutableBlock _ ) - | Normal_optional _) - -> simpl l2 - | Some (OptionalBlock(l, Null)) -> - Lam.if_ - (Lam.not_ (Location.none) ( Lam.prim ~primitive:Pis_null ~args:[l] Location.none)) - (simpl l2) (simpl l3) - | Some (OptionalBlock(l, Undefined)) -> - Lam.if_ - (Lam.not_ Location.none (Lam.prim ~primitive:Pis_undefined ~args:[l] Location.none)) - (simpl l2) (simpl l3) - | Some (OptionalBlock(l, Null_undefined)) -> - Lam.if_ - (Lam.not_ Location.none - ( Lam.prim ~primitive:Pis_null_undefined ~args:[l] Location.none) ) - (simpl l2) (simpl l3) - | Some _ - | None -> Lam.if_ l1 (simpl l2) (simpl l3) - end + | Lprim { primitive = Pfield (i, info) as primitive; args = [ arg ]; loc } + -> ( + (* ATTENTION: + Main use case, we should detect inline all immutable block .. *) + match simpl arg with + | Lvar v as l -> + Lam_util.field_flatten_get + (fun _ -> Lam.prim ~primitive ~args:[ l ] loc) + v i info meta.ident_tbl + | l -> Lam.prim ~primitive ~args:[ l ] loc) + | Lprim + { + primitive = (Pval_from_option | Pval_from_option_not_nest) as p; + args = [ (Lvar v as lvar) ]; + } as x -> ( + match Hash_ident.find_opt meta.ident_tbl v with + | Some (OptionalBlock (l, _)) -> l + | _ -> if p = Pval_from_option_not_nest then lvar else x) + | Lglobal_module _ -> lam + | Lprim { primitive; args; loc } -> + Lam.prim ~primitive ~args:(Ext_list.map args simpl) loc + | Lifthenelse + ((Lprim { primitive = Pis_not_none; args = [ Lvar id ] } as l1), l2, l3) + -> ( + match Hash_ident.find_opt meta.ident_tbl id with + | Some (ImmutableBlock _ | MutableBlock _ | Normal_optional _) -> + simpl l2 + | Some (OptionalBlock (l, Null)) -> + Lam.if_ + (Lam.not_ Location.none + (Lam.prim ~primitive:Pis_null ~args:[ l ] Location.none)) + (simpl l2) (simpl l3) + | Some (OptionalBlock (l, Undefined)) -> + Lam.if_ + (Lam.not_ Location.none + (Lam.prim ~primitive:Pis_undefined ~args:[ l ] Location.none)) + (simpl l2) (simpl l3) + | Some (OptionalBlock (l, Null_undefined)) -> + Lam.if_ + (Lam.not_ Location.none + (Lam.prim ~primitive:Pis_null_undefined ~args:[ l ] + Location.none)) + (simpl l2) (simpl l3) + | Some _ | None -> Lam.if_ l1 (simpl l2) (simpl l3)) (* could be the code path - {[ match x with - | h::hs -> + {[ match x with + | h::hs -> ]} - *) - | Lifthenelse (l1, l2, l3) -> - begin match l1 with - | Lvar id when id_is_for_sure_true_in_boolean meta.ident_tbl id-> - simpl l2 - | _ -> - Lam.if_ (simpl l1) (simpl l2) (simpl l3) - end + *) + | Lifthenelse (l1, l2, l3) -> ( + match l1 with + | Lvar id when id_is_for_sure_true_in_boolean meta.ident_tbl id -> + simpl l2 + | _ -> Lam.if_ (simpl l1) (simpl l2) (simpl l3)) | Lconst _ -> lam - | Llet(str, v, l1, l2) -> - Lam.let_ str v (simpl l1) (simpl l2 ) - | Lletrec(bindings, body) -> - let bindings = Ext_list.map_snd bindings simpl in - Lam.letrec bindings (simpl body) - - (* complicated - 1. inline this function - 2. ... - exports.Make= - function(funarg) - {var $$let=Make(funarg); - return [0, $$let[5],... $$let[16]]} - *) - | Lapply{ap_func = - Lprim {primitive = Pfield (_, Fld_module {name = fld_name}) ; - args = [ Lglobal_module ident ]; - _} as l1; - ap_args = args; ap_info } -> - begin - match Lam_compile_env.query_external_id_info ident fld_name with - | {persistent_closed_lambda=Some Lfunction{params; body; _} } - (* be more cautious when do cross module inlining *) - when - Ext_list.same_length params args && - Ext_list.for_all args (fun arg -> - match arg with - | Lvar p -> - begin - match Hash_ident.find_opt meta.ident_tbl p with - | Some v -> v <> Parameter - | None -> true - end - | _ -> true - ) -> - simpl (Lam_beta_reduce.propogate_beta_reduce - meta params body args) - | _ -> - Lam.apply (simpl l1) (Ext_list.map args simpl) ap_info - - - end + | Llet (str, v, l1, l2) -> Lam.let_ str v (simpl l1) (simpl l2) + | Lletrec (bindings, body) -> + let bindings = Ext_list.map_snd bindings simpl in + Lam.letrec bindings (simpl body) + (* complicated + 1. inline this function + 2. ... + exports.Make= + function(funarg) + {var $$let=Make(funarg); + return [0, $$let[5],... $$let[16]]} + *) + | Lapply + { + ap_func = + Lprim + { + primitive = Pfield (_, Fld_module { name = fld_name }); + args = [ Lglobal_module ident ]; + _; + } as l1; + ap_args = args; + ap_info; + } -> ( + match Lam_compile_env.query_external_id_info ident fld_name with + | { persistent_closed_lambda = Some (Lfunction { params; body; _ }) } + (* be more cautious when do cross module inlining *) + when Ext_list.same_length params args + && Ext_list.for_all args (fun arg -> + match arg with + | Lvar p -> ( + match Hash_ident.find_opt meta.ident_tbl p with + | Some v -> v <> Parameter + | None -> true) + | _ -> true) -> + simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) + | _ -> Lam.apply (simpl l1) (Ext_list.map args simpl) ap_info) (* Function inlining interact with other optimizations... - parameter attributes - - scope issues - - code bloat - *) - | Lapply{ap_func = (Lvar v as fn); ap_args = args; ap_info } -> - (* Check info for always inlining *) - - (* Ext_log.dwarn __LOC__ "%s/%d" v.name v.stamp; *) - let normal () = Lam.apply ( simpl fn) (Ext_list.map args simpl) ap_info in - begin - match Hash_ident.find_opt meta.ident_tbl v with - | Some (FunctionId {lambda = Some(Lfunction ({params; body; attr = {is_a_functor}} as m), - rec_flag) - }) - -> + - scope issues + - code bloat + *) + | Lapply { ap_func = Lvar v as fn; ap_args; ap_info } -> ( + (* Check info for always inlining *) - if Ext_list.same_length args params (* && false *) - then - if is_a_functor - (* && (Set_ident.mem v meta.export_idents) && false *) - then - (* TODO: check l1 if it is exported, - if so, maybe not since in that case, - we are going to have two copy? - *) + (* Ext_log.dwarn __LOC__ "%s/%d" v.name v.stamp; *) + let ap_args = Ext_list.map ap_args simpl in + let[@local] normal () = Lam.apply (simpl fn) ap_args ap_info in + match Hash_ident.find_opt meta.ident_tbl v with + | Some + (FunctionId + { + lambda = + Some + ( Lfunction ({ params; body; attr = { is_a_functor } } as m), + rec_flag ); + }) -> + if Ext_list.same_length ap_args params (* && false *) then + if + is_a_functor + (* && (Set_ident.mem v meta.export_idents) && false *) + then + (* TODO: check l1 if it is exported, + if so, maybe not since in that case, + we are going to have two copy? + *) - (* Check: recursive applying may result in non-termination *) - begin + (* Check: recursive applying may result in non-termination *) (* Ext_log.dwarn __LOC__ "beta .. %s/%d" v.name v.stamp ; *) - simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) - end - else - if (* Lam_analysis.size body < Lam_analysis.small_inline_size *) - (* ap_inlined = Always_inline || *) - Lam_analysis.ok_to_inline_fun_when_app m args - then - - (* let param_map = *) - (* Lam_analysis.free_variables meta.export_idents *) - (* (Lam_analysis.param_map_of_list params) body in *) - (* let old_count = List.length params in *) - (* let new_count = Map_ident.cardinal param_map in *) - let param_map = - Lam_closure.is_closed_with_map - meta.export_idents params body in - let is_export_id = Set_ident.mem meta.export_idents v in - match is_export_id, param_map with - | false, (_, param_map) - | true, (true, param_map) -> - begin match rec_flag with - - | Lam_rec -> Lam_beta_reduce.propogate_beta_reduce_with_map meta param_map params body args - | Lam_self_rec -> normal () - | Lam_non_rec -> - simpl - (Lam_beta_reduce.propogate_beta_reduce_with_map meta param_map params body args) - end - | _ -> normal () - else - normal () - else - normal () - | Some _ - | None -> normal () - - end - - | Lapply{ ap_func = Lfunction{ params; body}; ap_args = args; _} - when Ext_list.same_length params args -> - simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) + simpl + (Lam_beta_reduce.propogate_beta_reduce meta params body + ap_args) + else if + (* Lam_analysis.size body < Lam_analysis.small_inline_size *) + (* ap_inlined = Always_inline || *) + Lam_analysis.ok_to_inline_fun_when_app m ap_args + then + (* let param_map = *) + (* Lam_analysis.free_variables meta.export_idents *) + (* (Lam_analysis.param_map_of_list params) body in *) + (* let old_count = List.length params in *) + (* let new_count = Map_ident.cardinal param_map in *) + let param_map = + Lam_closure.is_closed_with_map meta.export_idents params body + in + let is_export_id = Set_ident.mem meta.export_idents v in + match (is_export_id, param_map) with + | false, (_, param_map) | true, (true, param_map) -> ( + match rec_flag with + | Lam_rec -> + Lam_beta_reduce.propogate_beta_reduce_with_map meta + param_map params body ap_args + | Lam_self_rec -> normal () + | Lam_non_rec -> + if + Ext_list.exists ap_args (fun lam -> + Lam_hit.hit_variable v lam) + (*avoid nontermination, e.g, `g(g)`*) + then normal () + else + simpl + (Lam_beta_reduce.propogate_beta_reduce_with_map meta + param_map params body ap_args)) + | _ -> normal () + else normal () + else normal () + | Some _ | None -> normal ()) + | Lapply { ap_func = Lfunction { params; body }; ap_args = args; _ } + when Ext_list.same_length params args -> + simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) (* | Lapply{ fn = Lfunction{function_kind = Tupled; params; body}; *) (* args = [Lprim {primitive = Pmakeblock _; args; _}]; _} *) (* (\** TODO: keep track of this parameter in ocaml trunk, *) @@ -384911,52 +384887,47 @@ let simplify_alias (* *\) *) (* when Ext_list.same_length params args -> *) (* simpl (Lam_beta_reduce.propogate_beta_reduce meta params body args) *) - - | Lapply { ap_func = l1; ap_args = ll; ap_info; } -> - Lam.apply (simpl l1) (Ext_list.map ll simpl) ap_info - | Lfunction {arity; params; body; attr} - -> Lam.function_ ~arity ~params ~body:(simpl body) ~attr - | Lswitch (l, {sw_failaction; - sw_consts; - sw_blocks; - sw_blocks_full; - sw_consts_full; - sw_names; - }) -> - Lam.switch (simpl l) - {sw_consts = - Ext_list.map_snd sw_consts simpl; - sw_blocks = Ext_list.map_snd sw_blocks simpl; - sw_consts_full; - sw_blocks_full; - sw_failaction = Ext_option.map sw_failaction simpl; - sw_names; - } - | Lstringswitch(l, sw, d) -> - Lam.stringswitch (simpl l ) - (Ext_list.map_snd sw simpl) - (Ext_option.map d simpl) - | Lstaticraise (i,ls) -> - Lam.staticraise i (Ext_list.map ls simpl ) - | Lstaticcatch (l1, ids, l2) -> - Lam.staticcatch (simpl l1) ids (simpl l2) - | Ltrywith (l1, v, l2) -> Lam.try_ (simpl l1) v (simpl l2) - | Lsequence(l1, l2) - -> Lam.seq (simpl l1) (simpl l2) - | Lwhile(l1, l2) - -> Lam.while_ (simpl l1) (simpl l2) - | Lfor(flag, l1, l2, dir, l3) - -> - Lam.for_ flag (simpl l1) (simpl l2) dir (simpl l3) - | Lassign(v, l) -> - (* Lalias-bound variables are never assigned, so don't increase - v's refsimpl *) - Lam.assign v (simpl l) - in + | Lapply { ap_func = l1; ap_args = ll; ap_info } -> + Lam.apply (simpl l1) (Ext_list.map ll simpl) ap_info + | Lfunction { arity; params; body; attr } -> + Lam.function_ ~arity ~params ~body:(simpl body) ~attr + | Lswitch + ( l, + { + sw_failaction; + sw_consts; + sw_blocks; + sw_blocks_full; + sw_consts_full; + sw_names; + } ) -> + Lam.switch (simpl l) + { + sw_consts = Ext_list.map_snd sw_consts simpl; + sw_blocks = Ext_list.map_snd sw_blocks simpl; + sw_consts_full; + sw_blocks_full; + sw_failaction = Ext_option.map sw_failaction simpl; + sw_names; + } + | Lstringswitch (l, sw, d) -> + Lam.stringswitch (simpl l) + (Ext_list.map_snd sw simpl) + (Ext_option.map d simpl) + | Lstaticraise (i, ls) -> Lam.staticraise i (Ext_list.map ls simpl) + | Lstaticcatch (l1, ids, l2) -> Lam.staticcatch (simpl l1) ids (simpl l2) + | Ltrywith (l1, v, l2) -> Lam.try_ (simpl l1) v (simpl l2) + | Lsequence (l1, l2) -> Lam.seq (simpl l1) (simpl l2) + | Lwhile (l1, l2) -> Lam.while_ (simpl l1) (simpl l2) + | Lfor (flag, l1, l2, dir, l3) -> + Lam.for_ flag (simpl l1) (simpl l2) dir (simpl l3) + | Lassign (v, l) -> + (* Lalias-bound variables are never assigned, so don't increase + v's refsimpl *) + Lam.assign v (simpl l) + in simpl lam - - end module Ext_log : sig #1 "ext_log.mli"