Sfoglia il codice sorgente

Reduce shared data in analyzer (#12082)

* remove shared lattice

* lose analyzer data dependency on com
Simon Krajewski 5 mesi fa
parent
commit
c3e42c7e0d

+ 6 - 3
src/codegen/dump.ml

@@ -2,6 +2,9 @@ open Globals
 open Common
 open Common
 open Type
 open Type
 
 
+let dump_path defines =
+	Define.defined_value_safe ~default:"dump" defines Define.DumpPath
+
 (*
 (*
 	Make a dump of the full typed AST of all types
 	Make a dump of the full typed AST of all types
 *)
 *)
@@ -13,7 +16,7 @@ let create_dumpfile acc l =
 		close_out ch)
 		close_out ch)
 
 
 let create_dumpfile_from_path com path =
 let create_dumpfile_from_path com path =
-	let buf,close = create_dumpfile [] ((dump_path com) :: (platform_name_macro com) :: fst path @ [snd path]) in
+	let buf,close = create_dumpfile [] ((dump_path com.defines) :: (platform_name_macro com) :: fst path @ [snd path]) in
 	buf,close
 	buf,close
 
 
 let dump_types com pretty =
 let dump_types com pretty =
@@ -176,7 +179,7 @@ let dump_dependencies ?(target_override=None) com =
 		| None -> platform_name_macro com
 		| None -> platform_name_macro com
 		| Some s -> s
 		| Some s -> s
 	in
 	in
-	let dump_dependencies_path = [dump_path com;target_name;"dependencies"] in
+	let dump_dependencies_path = [dump_path com.defines;target_name;"dependencies"] in
 	let buf,close = create_dumpfile [] dump_dependencies_path in
 	let buf,close = create_dumpfile [] dump_dependencies_path in
 	let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
 	let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
 	let dep = Hashtbl.create 0 in
 	let dep = Hashtbl.create 0 in
@@ -199,7 +202,7 @@ let dump_dependencies ?(target_override=None) com =
 		) m.m_extra.m_deps;
 		) m.m_extra.m_deps;
 	) com.Common.modules;
 	) com.Common.modules;
 	close();
 	close();
-	let dump_dependants_path = [dump_path com;target_name;"dependants"] in
+	let dump_dependants_path = [dump_path com.defines;target_name;"dependants"] in
 	let buf,close = create_dumpfile [] dump_dependants_path in
 	let buf,close = create_dumpfile [] dump_dependants_path in
 	let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
 	let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in
 	Hashtbl.iter (fun n ml ->
 	Hashtbl.iter (fun n ml ->

+ 0 - 3
src/context/common.ml

@@ -1117,9 +1117,6 @@ let display_error_ext com err =
 let display_error com ?(depth = 0) msg p =
 let display_error com ?(depth = 0) msg p =
 	display_error_ext com (Error.make_error ~depth (Custom msg) p)
 	display_error_ext com (Error.make_error ~depth (Custom msg) p)
 
 
-let dump_path com =
-	Define.defined_value_safe ~default:"dump" com.defines Define.DumpPath
-
 let adapt_defines_to_macro_context defines =
 let adapt_defines_to_macro_context defines =
 	let to_remove = "java" :: List.map Globals.platform_name Globals.platforms in
 	let to_remove = "java" :: List.map Globals.platform_name Globals.platforms in
 	let to_remove = List.fold_left (fun acc d -> Define.get_define_key d :: acc) to_remove [Define.NoTraces] in
 	let to_remove = List.fold_left (fun acc d -> Define.get_define_key d :: acc) to_remove [Define.NoTraces] in

+ 92 - 66
src/optimization/analyzer.ml

@@ -20,7 +20,6 @@
 open StringHelper
 open StringHelper
 open Ast
 open Ast
 open Type
 open Type
-open Common
 open AnalyzerTexpr
 open AnalyzerTexpr
 open AnalyzerTypes
 open AnalyzerTypes
 open OptimizerTexpr
 open OptimizerTexpr
@@ -185,17 +184,29 @@ end
 
 
 module type DataFlowApi = sig
 module type DataFlowApi = sig
 	type t
 	type t
+
+	type opt_ctx
+
 	val to_string : t -> string
 	val to_string : t -> string
 	val flag : BasicBlock.cfg_edge_Flag
 	val flag : BasicBlock.cfg_edge_Flag
-	val transfer : analyzer_context -> BasicBlock.t -> texpr -> t (* The transfer function *)
-	val equals : t -> t -> bool                                   (* The equality function *)
-	val bottom : t                                                (* The bottom element of the lattice *)
-	val top : t                                                   (* The top element of the lattice *)
-	val get_cell : int -> t                                       (* Lattice cell getter *)
-	val set_cell : int -> t -> unit                               (* Lattice cell setter *)
-	val init : analyzer_context -> unit                           (* The initialization function which is called at the start *)
-	val commit : analyzer_context -> unit                         (* The commit function which is called at the end *)
-	val conditional : bool                                        (* Whether or not conditional branches are checked *)
+	(* The transfer function *)
+	val transfer : analyzer_context -> opt_ctx -> BasicBlock.t -> texpr -> t
+	(* The equality function *)
+	val equals : t -> t -> bool
+	(* The bottom element of the lattice *)
+	val bottom : t
+	(* The top element of the lattice *)
+	val top : t
+	(* Lattice cell getter *)
+	val get_cell : opt_ctx -> int -> t
+	(* Lattice cell setter *)
+	val set_cell : opt_ctx -> int -> t -> unit
+	(* The initialization function which is called at the start *)
+	val init : analyzer_context -> opt_ctx
+	(* The commit function which is called at the end *)
+	val commit : analyzer_context -> opt_ctx -> unit
+	(* Whether or not conditional branches are checked *)
+	val conditional : bool
 end
 end
 
 
 (*
 (*
@@ -220,8 +231,8 @@ module DataFlow (M : DataFlowApi) = struct
 	let get_ssa_edges_from g v =
 	let get_ssa_edges_from g v =
 		(get_var_info g v).vi_ssa_edges
 		(get_var_info g v).vi_ssa_edges
 
 
-	let run ctx =
-		let g = ctx.graph in
+	let run actx ctx =
+		let g = actx.graph in
 		let ssa_work_list = ref [] in
 		let ssa_work_list = ref [] in
 		let cfg_work_list = ref g.g_root.bb_outgoing in
 		let cfg_work_list = ref g.g_root.bb_outgoing in
 		let add_ssa_edge edge =
 		let add_ssa_edge edge =
@@ -234,7 +245,7 @@ module DataFlow (M : DataFlowApi) = struct
 			let el = List.fold_left2 (fun acc e edge ->
 			let el = List.fold_left2 (fun acc e edge ->
 				if has_flag edge M.flag then e :: acc else acc
 				if has_flag edge M.flag then e :: acc else acc
 			) [] el bb.bb_incoming in
 			) [] el bb.bb_incoming in
-			let el = List.map (fun e -> M.transfer ctx bb e) el in
+			let el = List.map (fun e -> M.transfer actx ctx bb e) el in
 			match el with
 			match el with
 				| e1 :: el when List.for_all (M.equals e1) el ->
 				| e1 :: el when List.for_all (M.equals e1) el ->
 					e1;
 					e1;
@@ -242,8 +253,8 @@ module DataFlow (M : DataFlowApi) = struct
 					M.bottom;
 					M.bottom;
 		in
 		in
 		let set_lattice_cell v e =
 		let set_lattice_cell v e =
-			let e' = M.get_cell v.v_id in
-			M.set_cell v.v_id e;
+			let e' = M.get_cell ctx v.v_id in
+			M.set_cell ctx v.v_id e;
 			if not (M.equals e e') then
 			if not (M.equals e e') then
 				List.iter (fun edge -> add_ssa_edge edge) (get_ssa_edges_from g v);
 				List.iter (fun edge -> add_ssa_edge edge) (get_ssa_edges_from g v);
 		in
 		in
@@ -253,7 +264,7 @@ module DataFlow (M : DataFlowApi) = struct
 				set_lattice_cell v (visit_phi bb v el)
 				set_lattice_cell v (visit_phi bb v el)
 			| _ ->
 			| _ ->
 				if List.exists (fun edge -> has_flag edge M.flag) bb.bb_incoming then
 				if List.exists (fun edge -> has_flag edge M.flag) bb.bb_incoming then
-					set_lattice_cell v (M.transfer ctx bb e)
+					set_lattice_cell v (M.transfer actx ctx bb e)
 		in
 		in
 		let visit_expression bb cond_branch e =
 		let visit_expression bb cond_branch e =
 			match e.eexpr with
 			match e.eexpr with
@@ -261,7 +272,7 @@ module DataFlow (M : DataFlowApi) = struct
 				visit_assignment bb v e2;
 				visit_assignment bb v e2;
 				false
 				false
 			| _ when M.conditional && cond_branch ->
 			| _ when M.conditional && cond_branch ->
-				let e1 = M.transfer ctx bb e in
+				let e1 = M.transfer actx ctx bb e in
 				let edges = if e1 == M.bottom || e1 == M.top then
 				let edges = if e1 == M.bottom || e1 == M.top then
 					bb.bb_outgoing
 					bb.bb_outgoing
 				else begin
 				else begin
@@ -269,7 +280,7 @@ module DataFlow (M : DataFlowApi) = struct
 						| edge :: edges ->
 						| edge :: edges ->
 							begin match edge.cfg_kind with
 							begin match edge.cfg_kind with
 							| CFGCondBranch e ->
 							| CFGCondBranch e ->
-								let e = M.transfer ctx bb e in
+								let e = M.transfer actx ctx bb e in
 								if M.equals e e1 then
 								if M.equals e e1 then
 									loop (edge :: yes) maybe also edges
 									loop (edge :: yes) maybe also edges
 								else
 								else
@@ -341,10 +352,10 @@ module DataFlow (M : DataFlowApi) = struct
 		in
 		in
 		loop ()
 		loop ()
 
 
-	let apply ctx =
-		M.init ctx;
-		run ctx;
-		M.commit ctx
+	let apply actx =
+		let ctx = M.init actx in
+		run actx ctx;
+		M.commit actx ctx
 end
 end
 
 
 (*
 (*
@@ -354,7 +365,7 @@ end
 
 
 	This module also deals with binop/unop optimization and standard API inlining.
 	This module also deals with binop/unop optimization and standard API inlining.
 *)
 *)
-module ConstPropagation = DataFlow(struct
+module ConstPropagationImpl = struct
 	open BasicBlock
 	open BasicBlock
 
 
 	type t =
 	type t =
@@ -365,6 +376,8 @@ module ConstPropagation = DataFlow(struct
 		| EnumValue of int * t list
 		| EnumValue of int * t list
 		| ModuleType of module_type * Type.t
 		| ModuleType of module_type * Type.t
 
 
+	type opt_ctx = (int,t) Hashtbl.t
+
 	let rec to_string =
 	let rec to_string =
 		let st = s_type (print_context()) in
 		let st = s_type (print_context()) in
 		function
 		function
@@ -378,10 +391,8 @@ module ConstPropagation = DataFlow(struct
 	let conditional = true
 	let conditional = true
 	let flag = FlagExecutable
 	let flag = FlagExecutable
 
 
-	let lattice = Hashtbl.create 0
-
-	let get_cell i = try Hashtbl.find lattice i with Not_found -> Top
-	let set_cell i ct = Hashtbl.replace lattice i ct
+	let get_cell ctx i = try Hashtbl.find ctx i with Not_found -> Top
+	let set_cell ctx i ct = Hashtbl.replace ctx i ct
 
 
 	let top = Top
 	let top = Top
 	let bottom = Bottom
 	let bottom = Bottom
@@ -394,7 +405,7 @@ module ConstPropagation = DataFlow(struct
 		| ModuleType(mt1,_),ModuleType (mt2,_) -> mt1 == mt2
 		| ModuleType(mt1,_),ModuleType (mt2,_) -> mt1 == mt2
 		| _ -> false
 		| _ -> false
 
 
-	let transfer ctx bb e =
+	let transfer actx ctx bb e =
 		let rec eval bb e =
 		let rec eval bb e =
 			let wrap = function
 			let wrap = function
 				| Const(ct,t) -> mk (TConst ct) t null_pos
 				| Const(ct,t) -> mk (TConst ct) t null_pos
@@ -418,7 +429,7 @@ module ConstPropagation = DataFlow(struct
 				if (follow v.v_type) == t_dynamic || has_var_flag v VCaptured then
 				if (follow v.v_type) == t_dynamic || has_var_flag v VCaptured then
 					Bottom
 					Bottom
 				else
 				else
-					get_cell v.v_id
+					get_cell ctx v.v_id
 			| TBinop(OpAssign,_,e2) ->
 			| TBinop(OpAssign,_,e2) ->
 				eval bb e2
 				eval bb e2
 			| TBinop(op,e1,e2) ->
 			| TBinop(op,e1,e2) ->
@@ -453,14 +464,14 @@ module ConstPropagation = DataFlow(struct
 				end;
 				end;
 			| TEnumIndex e1 ->
 			| TEnumIndex e1 ->
 				begin match eval bb e1 with
 				begin match eval bb e1 with
-					| EnumValue(i,_) -> Const (TInt (Int32.of_int i),ctx.com.basic.tint)
+					| EnumValue(i,_) -> Const (TInt (Int32.of_int i),actx.com.basic.tint)
 					| _ -> raise Exit
 					| _ -> raise Exit
 				end;
 				end;
-			| TCall ({ eexpr = TField (_,FStatic({cl_path=[],"Type"} as c,({cf_name="enumIndex"} as cf)))},[e1]) when ctx.com.platform = Eval ->
+			| TCall ({ eexpr = TField (_,FStatic({cl_path=[],"Type"} as c,({cf_name="enumIndex"} as cf)))},[e1]) when actx.com.platform = Eval ->
 				begin match follow e1.etype,eval bb e1 with
 				begin match follow e1.etype,eval bb e1 with
-					| TEnum _,EnumValue(i,_) -> Const (TInt (Int32.of_int i),ctx.com.basic.tint)
+					| TEnum _,EnumValue(i,_) -> Const (TInt (Int32.of_int i),actx.com.basic.tint)
 					| _,e1 ->
 					| _,e1 ->
-						begin match Inline.api_inline2 ctx.com c cf.cf_name [wrap e1] e.epos with
+						begin match Inline.api_inline2 actx.com.basic actx.com.platform c cf.cf_name [wrap e1] e.epos with
 							| None -> raise Exit
 							| None -> raise Exit
 							| Some e -> eval bb e
 							| Some e -> eval bb e
 						end
 						end
@@ -468,22 +479,22 @@ module ConstPropagation = DataFlow(struct
 			| TCall ({ eexpr = TField (_,FStatic(c,cf))},el) ->
 			| TCall ({ eexpr = TField (_,FStatic(c,cf))},el) ->
 				let el = List.map (eval bb) el in
 				let el = List.map (eval bb) el in
 				let el = List.map wrap el in
 				let el = List.map wrap el in
-				begin match Inline.api_inline2 ctx.com c cf.cf_name el e.epos with
+				begin match Inline.api_inline2 actx.com.basic actx.com.platform c cf.cf_name el e.epos with
 					| None -> raise Exit
 					| None -> raise Exit
 					| Some e -> eval bb e
 					| Some e -> eval bb e
 				end
 				end
 			| TParenthesis e1 | TMeta(_,e1) | TCast(e1,None) ->
 			| TParenthesis e1 | TMeta(_,e1) | TCast(e1,None) ->
 				eval bb e1
 				eval bb e1
 			| _ ->
 			| _ ->
-				let e1 = match ctx.com.platform,e.eexpr with
-					| Js,TArray(e1,{eexpr = TConst(TInt i)}) when Int32.to_int i = 1 && Define.defined ctx.com.defines Define.JsEnumsAsArrays -> e1
-					| Js,TField(e1,FDynamic "_hx_index") when not (Define.defined ctx.com.defines Define.JsEnumsAsArrays) -> e1
+				let e1 = match actx.com.platform,e.eexpr with
+					| Js,TArray(e1,{eexpr = TConst(TInt i)}) when Int32.to_int i = 1 && Define.defined actx.com.defines Define.JsEnumsAsArrays -> e1
+					| Js,TField(e1,FDynamic "_hx_index") when not (Define.defined actx.com.defines Define.JsEnumsAsArrays) -> e1
 					| Cpp,TCall({eexpr = TField(e1,FDynamic "__Index")},[]) -> e1
 					| Cpp,TCall({eexpr = TField(e1,FDynamic "__Index")},[]) -> e1
 					| Neko,TField(e1,FDynamic "index") -> e1
 					| Neko,TField(e1,FDynamic "index") -> e1
 					| _ -> raise Exit
 					| _ -> raise Exit
 				in
 				in
 				begin match follow e1.etype,eval bb e1 with
 				begin match follow e1.etype,eval bb e1 with
-					| TEnum _,EnumValue(i,_) -> Const (TInt (Int32.of_int i),ctx.com.basic.tint)
+					| TEnum _,EnumValue(i,_) -> Const (TInt (Int32.of_int i),actx.com.basic.tint)
 					| _ -> raise Exit
 					| _ -> raise Exit
 				end
 				end
 		in
 		in
@@ -493,19 +504,19 @@ module ConstPropagation = DataFlow(struct
 			Bottom
 			Bottom
 
 
 	let init ctx =
 	let init ctx =
-		Hashtbl.clear lattice
+		Hashtbl.create 0
 
 
-	let commit ctx =
-		let inline e i = match get_cell i with
+	let commit actx ctx =
+		let inline e i = match get_cell ctx i with
 			| Top | Bottom | EnumValue _ | Null _ ->
 			| Top | Bottom | EnumValue _ | Null _ ->
 				raise Not_found
 				raise Not_found
 			| Const(ct,t) ->
 			| Const(ct,t) ->
-				let e' = Texpr.type_constant ctx.com.basic (tconst_to_const ct) e.epos in
+				let e' = Texpr.type_constant actx.com.basic (tconst_to_const ct) e.epos in
 				let e' = {e' with etype = t} in
 				let e' = {e' with etype = t} in
-				if not (type_change_ok ctx.com e'.etype e.etype) then raise Not_found;
+				if not (type_change_ok actx.com e'.etype e.etype) then raise Not_found;
 				e'
 				e'
 			| ModuleType(mt,t) ->
 			| ModuleType(mt,t) ->
-				if not (type_change_ok ctx.com t e.etype) then raise Not_found;
+				if not (type_change_ok actx.com t e.etype) then raise Not_found;
 				mk (TTypeExpr mt) t e.epos
 				mk (TTypeExpr mt) t e.epos
 		in
 		in
 		let is_special_var v = has_var_flag v VCaptured || ExtType.has_variable_semantics v.v_type in
 		let is_special_var v = has_var_flag v VCaptured || ExtType.has_variable_semantics v.v_type in
@@ -530,19 +541,21 @@ module ConstPropagation = DataFlow(struct
 			| _ ->
 			| _ ->
 				Type.map_expr commit e
 				Type.map_expr commit e
 		in
 		in
-		Graph.iter_dom_tree ctx.graph (fun bb ->
-			if not (List.exists (fun edge -> has_flag edge FlagExecutable) bb.bb_incoming) then bb.bb_dominator <- ctx.graph.Graph.g_unreachable;
+		Graph.iter_dom_tree actx.graph (fun bb ->
+			if not (List.exists (fun edge -> has_flag edge FlagExecutable) bb.bb_incoming) then bb.bb_dominator <- actx.graph.Graph.g_unreachable;
 			dynarray_map commit bb.bb_el;
 			dynarray_map commit bb.bb_el;
 			bb.bb_terminator <- terminator_map commit bb.bb_terminator;
 			bb.bb_terminator <- terminator_map commit bb.bb_terminator;
 		);
 		);
-end)
+end
+
+module ConstPropagation = DataFlow(ConstPropagationImpl)
 
 
 (*
 (*
 	Propagates local variables to other local variables.
 	Propagates local variables to other local variables.
 
 
 	Respects scopes on targets where it matters (all except JS).
 	Respects scopes on targets where it matters (all except JS).
 *)
 *)
-module CopyPropagation = DataFlow(struct
+module CopyPropagationImpl = struct
 	open BasicBlock
 	open BasicBlock
 	open Graph
 	open Graph
 
 
@@ -552,6 +565,8 @@ module CopyPropagation = DataFlow(struct
 		| Local of tvar
 		| Local of tvar
 		| This of Type.t
 		| This of Type.t
 
 
+	type opt_ctx = (int,t) Hashtbl.t
+
 	let to_string = function
 	let to_string = function
 		| Top -> "Top"
 		| Top -> "Top"
 		| Bottom -> "Bottom"
 		| Bottom -> "Bottom"
@@ -560,10 +575,9 @@ module CopyPropagation = DataFlow(struct
 
 
 	let conditional = false
 	let conditional = false
 	let flag = FlagCopyPropagation
 	let flag = FlagCopyPropagation
-	let lattice = Hashtbl.create 0
 
 
-	let get_cell i = try Hashtbl.find lattice i with Not_found -> Top
-	let set_cell i ct = Hashtbl.replace lattice i ct
+	let get_cell ctx i = try Hashtbl.find ctx i with Not_found -> Top
+	let set_cell ctx i ct = Hashtbl.replace ctx i ct
 
 
 	let top = Top
 	let top = Top
 	let bottom = Bottom
 	let bottom = Bottom
@@ -575,7 +589,7 @@ module CopyPropagation = DataFlow(struct
 		| This t1,This t2 -> t1 == t2
 		| This t1,This t2 -> t1 == t2
 		| _ -> false
 		| _ -> false
 
 
-	let transfer ctx bb e =
+	let transfer actx ctx bb e =
 		let rec loop e = match e.eexpr with
 		let rec loop e = match e.eexpr with
 			| TLocal v when not (has_var_flag v VCaptured) ->
 			| TLocal v when not (has_var_flag v VCaptured) ->
 				Local v
 				Local v
@@ -588,33 +602,33 @@ module CopyPropagation = DataFlow(struct
 		in
 		in
 		loop e
 		loop e
 
 
-	let init ctx =
-		Hashtbl.clear lattice
+	let init actx =
+		Hashtbl.create 0
 
 
-	let commit ctx =
+	let commit actx ctx =
 		let rec commit bb e = match e.eexpr with
 		let rec commit bb e = match e.eexpr with
 			| TLocal v when not (has_var_flag v VCaptured) ->
 			| TLocal v when not (has_var_flag v VCaptured) ->
 				begin try
 				begin try
-					let lat = get_cell v.v_id in
+					let lat = get_cell ctx v.v_id in
 					let leave () =
 					let leave () =
-						Hashtbl.remove lattice v.v_id;
+						Hashtbl.remove ctx v.v_id;
 						raise Not_found
 						raise Not_found
 					in
 					in
 					begin match lat with
 					begin match lat with
 					| Local v' ->
 					| Local v' ->
-						if not (type_change_ok ctx.com v'.v_type v.v_type) then leave();
-						let v'' = get_var_origin ctx.graph v' in
+						if not (type_change_ok actx.com v'.v_type v.v_type) then leave();
+						let v'' = get_var_origin actx.graph v' in
 						(* This restriction is in place due to how we currently reconstruct the AST. Multiple SSA-vars may be turned back to
 						(* This restriction is in place due to how we currently reconstruct the AST. Multiple SSA-vars may be turned back to
 						the same origin var, which creates interference that is not tracked in the analysis. We address this by only
 						the same origin var, which creates interference that is not tracked in the analysis. We address this by only
 						considering variables whose origin-variables are assigned to at most once. *)
 						considering variables whose origin-variables are assigned to at most once. *)
-						let writes = (get_var_info ctx.graph v'').vi_writes in
+						let writes = (get_var_info actx.graph v'').vi_writes in
 						begin match writes with
 						begin match writes with
 							| [bb'] when in_scope bb bb' -> ()
 							| [bb'] when in_scope bb bb' -> ()
 							| _ -> leave()
 							| _ -> leave()
 						end;
 						end;
 						commit bb {e with eexpr = TLocal v'}
 						commit bb {e with eexpr = TLocal v'}
 					| This t ->
 					| This t ->
-						if not (type_change_ok ctx.com t v.v_type) then leave();
+						if not (type_change_ok actx.com t v.v_type) then leave();
 						mk (TConst TThis) t e.epos
 						mk (TConst TThis) t e.epos
 					| Top | Bottom ->
 					| Top | Bottom ->
 						leave()
 						leave()
@@ -628,11 +642,13 @@ module CopyPropagation = DataFlow(struct
 			| _ ->
 			| _ ->
 				Type.map_expr (commit bb) e
 				Type.map_expr (commit bb) e
 		in
 		in
-		Graph.iter_dom_tree ctx.graph (fun bb ->
+		Graph.iter_dom_tree actx.graph (fun bb ->
 			dynarray_map (commit bb) bb.bb_el;
 			dynarray_map (commit bb) bb.bb_el;
 			bb.bb_terminator <- terminator_map (commit bb) bb.bb_terminator;
 			bb.bb_terminator <- terminator_map (commit bb) bb.bb_terminator;
 		);
 		);
-end)
+end
+
+module CopyPropagation = DataFlow(CopyPropagationImpl)
 
 
 (*
 (*
 	LocalDce implements a mark & sweep dead code elimination. The mark phase follows the CFG edges of the graphs to find
 	LocalDce implements a mark & sweep dead code elimination. The mark phase follows the CFG edges of the graphs to find
@@ -853,8 +869,12 @@ module Debug = struct
 			end
 			end
 		) g.g_var_infos
 		) g.g_var_infos
 
 
+	let platform_name_macro com =
+		if Define.defined com.defines Define.Macro then "macro"
+		else platform_name com.platform
+
 	let get_dump_path ctx c cf =
 	let get_dump_path ctx c cf =
-		(dump_path ctx.com) :: [platform_name_macro ctx.com] @ (fst c.cl_path) @ [Printf.sprintf "%s.%s" (snd c.cl_path) cf.cf_name]
+		(Dump.dump_path ctx.com.defines) :: [platform_name_macro ctx.com] @ (fst c.cl_path) @ [Printf.sprintf "%s.%s" (snd c.cl_path) cf.cf_name]
 
 
 	let dot_debug ctx c cf =
 	let dot_debug ctx c cf =
 		let g = ctx.graph in
 		let g = ctx.graph in
@@ -961,10 +981,16 @@ module Run = struct
 		let timer = Timer.timer name in
 		let timer = Timer.timer name in
 		Std.finally timer f ()
 		Std.finally timer f ()
 
 
-	let create_analyzer_context com config identifier e =
+	let create_analyzer_context (com : Common.context) config identifier e =
 		let g = Graph.create e.etype e.epos in
 		let g = Graph.create e.etype e.epos in
 		let ctx = {
 		let ctx = {
-			com = com;
+			com = {
+				basic = com.basic;
+				platform = com.platform;
+				platform_config = com.config;
+				defines = com.defines;
+				debug = com.debug;
+			};
 			config = config;
 			config = config;
 			graph = g;
 			graph = g;
 			(* For CPP we want to use variable names which are "probably" not used by users in order to
 			(* For CPP we want to use variable names which are "probably" not used by users in order to

+ 5 - 4
src/optimization/analyzerTexpr.ml

@@ -20,6 +20,7 @@
 open Ast
 open Ast
 open Type
 open Type
 open Common
 open Common
+open AnalyzerTypes
 open OptimizerTexpr
 open OptimizerTexpr
 open Globals
 open Globals
 
 
@@ -108,11 +109,11 @@ let target_handles_unops com = match com.platform with
 let target_handles_assign_ops com e2 = match com.platform with
 let target_handles_assign_ops com e2 = match com.platform with
 	| Php -> not (has_side_effect e2)
 	| Php -> not (has_side_effect e2)
 	| Lua -> false
 	| Lua -> false
-	| Cpp when not (Common.defined com Define.Cppia) -> false
+	| Cpp when not (Define.defined com.defines Define.Cppia) -> false
 	| _ -> true
 	| _ -> true
 
 
 let target_handles_side_effect_order com = match com.platform with
 let target_handles_side_effect_order com = match com.platform with
-	| Cpp -> Common.defined com Define.Cppia
+	| Cpp -> Define.defined com.defines Define.Cppia
 	| Php -> false
 	| Php -> false
 	| _ -> true
 	| _ -> true
 
 
@@ -183,7 +184,7 @@ let type_change_ok com t1 t2 =
 		t1 == t2 || match follow t1,follow t2 with
 		t1 == t2 || match follow t1,follow t2 with
 			| TDynamic _,_ | _,TDynamic _ -> false
 			| TDynamic _,_ | _,TDynamic _ -> false
 			| _ ->
 			| _ ->
-				if com.config.pf_static && is_nullable_or_whatever t1 <> is_nullable_or_whatever t2 then false
+				if com.platform_config.pf_static && is_nullable_or_whatever t1 <> is_nullable_or_whatever t2 then false
 				else type_iseq t1 t2
 				else type_iseq t1 t2
 	end
 	end
 
 
@@ -827,7 +828,7 @@ module Fusion = struct
 				can_be_used_as_value com e1 &&
 				can_be_used_as_value com e1 &&
 				not (ExtType.is_void e1.etype) &&
 				not (ExtType.is_void e1.etype) &&
 				(match com.platform with
 				(match com.platform with
-					| Cpp when not (Common.defined com Define.Cppia) -> false
+					| Cpp when not (Define.defined com.defines Define.Cppia) -> false
 					| _ -> true)
 					| _ -> true)
 				->
 				->
 				begin try
 				begin try

+ 9 - 1
src/optimization/analyzerTypes.ml

@@ -597,8 +597,16 @@ module Graph = struct
 		Hashtbl.iter (fun _ (bb,_,_,_) -> loop [0] bb) g.g_functions
 		Hashtbl.iter (fun _ (bb,_,_,_) -> loop [0] bb) g.g_functions
 end
 end
 
 
+type light_com = {
+	basic : basic_types;
+	platform : platform;
+	defines : Define.define;
+	platform_config : platform_config;
+	debug : bool;
+}
+
 type analyzer_context = {
 type analyzer_context = {
-	com : Common.context;
+	com : light_com;
 	config : AnalyzerConfig.t;
 	config : AnalyzerConfig.t;
 	graph : Graph.t;
 	graph : Graph.t;
 	temp_var_name : string;
 	temp_var_name : string;

+ 15 - 15
src/optimization/inline.ml

@@ -15,36 +15,36 @@ let mk_untyped_call name p params =
 		epos = p;
 		epos = p;
 	}
 	}
 
 
-let api_inline2 com c field params p =
+let api_inline2 basic platform c field params p =
 	match c.cl_path, field, params with
 	match c.cl_path, field, params with
 	| ([],"Type"),"enumIndex",[{ eexpr = TField (_,FEnum (en,f)) }] ->
 	| ([],"Type"),"enumIndex",[{ eexpr = TField (_,FEnum (en,f)) }] ->
-		Some (mk (TConst (TInt (Int32.of_int f.ef_index))) com.basic.tint p)
+		Some (mk (TConst (TInt (Int32.of_int f.ef_index))) basic.tint p)
 	| ([],"Type"),"enumIndex",[{ eexpr = TCall({ eexpr = TField (_,FEnum (en,f)) },pl) }] when List.for_all (fun e -> not (has_side_effect e)) pl ->
 	| ([],"Type"),"enumIndex",[{ eexpr = TCall({ eexpr = TField (_,FEnum (en,f)) },pl) }] when List.for_all (fun e -> not (has_side_effect e)) pl ->
-		Some (mk (TConst (TInt (Int32.of_int f.ef_index))) com.basic.tint p)
+		Some (mk (TConst (TInt (Int32.of_int f.ef_index))) basic.tint p)
 	| ([],"Std"),"int",[{ eexpr = TConst (TInt _) } as e] ->
 	| ([],"Std"),"int",[{ eexpr = TConst (TInt _) } as e] ->
 		Some { e with epos = p }
 		Some { e with epos = p }
 	| ([],"String"),"fromCharCode",[{ eexpr = TConst (TInt i) }] when i > 0l && i < 128l ->
 	| ([],"String"),"fromCharCode",[{ eexpr = TConst (TInt i) }] when i > 0l && i < 128l ->
-		Some (mk (TConst (TString (String.make 1 (char_of_int (Int32.to_int i))))) com.basic.tstring p)
+		Some (mk (TConst (TString (String.make 1 (char_of_int (Int32.to_int i))))) basic.tstring p)
 	| ([],"Std"),"string",[{ eexpr = TCast ({ eexpr = TConst c } as e, None)}]
 	| ([],"Std"),"string",[{ eexpr = TCast ({ eexpr = TConst c } as e, None)}]
 	| ([],"Std"),"string",[{ eexpr = TConst c } as e] ->
 	| ([],"Std"),"string",[{ eexpr = TConst c } as e] ->
 		(match c with
 		(match c with
 		| TString s ->
 		| TString s ->
 			Some { e with epos = p }
 			Some { e with epos = p }
 		| TInt i ->
 		| TInt i ->
-			Some { eexpr = TConst (TString (Int32.to_string i)); epos = p; etype = com.basic.tstring }
+			Some { eexpr = TConst (TString (Int32.to_string i)); epos = p; etype = basic.tstring }
 		| TBool b ->
 		| TBool b ->
-			Some { eexpr = TConst (TString (if b then "true" else "false")); epos = p; etype = com.basic.tstring }
+			Some { eexpr = TConst (TString (if b then "true" else "false")); epos = p; etype = basic.tstring }
 		| _ ->
 		| _ ->
 			None)
 			None)
 	| ([],"Std"),"string",[{ eexpr = TIf (_,{ eexpr = TConst (TString _)},Some { eexpr = TConst (TString _) }) } as e] ->
 	| ([],"Std"),"string",[{ eexpr = TIf (_,{ eexpr = TConst (TString _)},Some { eexpr = TConst (TString _) }) } as e] ->
 		Some e
 		Some e
-	| ([],"Std"),"string",[{ eexpr = TLocal v | TField({ eexpr = TLocal v },_) } as ev] when (com.platform = Js || com.platform = Flash) && (match v.v_kind with VUser _ -> true | _ -> false) ->
+	| ([],"Std"),"string",[{ eexpr = TLocal v | TField({ eexpr = TLocal v },_) } as ev] when (platform = Js || platform = Flash) && (match v.v_kind with VUser _ -> true | _ -> false) ->
 		let pos = ev.epos in
 		let pos = ev.epos in
 		let stringv() =
 		let stringv() =
-			let to_str = mk (TBinop (Ast.OpAdd, mk (TConst (TString "")) com.basic.tstring pos, ev)) com.basic.tstring pos in
-			if com.platform = Js || is_nullable ev.etype then
-				let chk_null = mk (TBinop (Ast.OpEq, ev, mk (TConst TNull) t_dynamic pos)) com.basic.tbool pos in
-				mk (TIf (chk_null, mk (TConst (TString "null")) com.basic.tstring pos, Some to_str)) com.basic.tstring pos
+			let to_str = mk (TBinop (Ast.OpAdd, mk (TConst (TString "")) basic.tstring pos, ev)) basic.tstring pos in
+			if platform = Js || is_nullable ev.etype then
+				let chk_null = mk (TBinop (Ast.OpEq, ev, mk (TConst TNull) t_dynamic pos)) basic.tbool pos in
+				mk (TIf (chk_null, mk (TConst (TString "null")) basic.tstring pos, Some to_str)) basic.tstring pos
 			else
 			else
 				to_str
 				to_str
 		in
 		in
@@ -69,7 +69,7 @@ let api_inline2 com c field params p =
 		| _ when f <= Int32.to_float Int32.min_int -. 1. || f >= Int32.to_float Int32.max_int +. 1. ->
 		| _ when f <= Int32.to_float Int32.min_int -. 1. || f >= Int32.to_float Int32.max_int +. 1. ->
 			None (* out range, keep platform-specific behavior *)
 			None (* out range, keep platform-specific behavior *)
 		| _ ->
 		| _ ->
-			Some { eexpr = TConst (TInt (Int32.of_float f)); etype = com.basic.tint; epos = p })
+			Some { eexpr = TConst (TInt (Int32.of_float f)); etype = basic.tint; epos = p })
 	| ([],"Math"),"ceil",[{ eexpr = TConst (TFloat f) }] ->
 	| ([],"Math"),"ceil",[{ eexpr = TConst (TFloat f) }] ->
 		let f = float_of_string f in
 		let f = float_of_string f in
 		(match classify_float f with
 		(match classify_float f with
@@ -78,7 +78,7 @@ let api_inline2 com c field params p =
 		| _ when f <= Int32.to_float Int32.min_int -. 1. || f >= Int32.to_float Int32.max_int ->
 		| _ when f <= Int32.to_float Int32.min_int -. 1. || f >= Int32.to_float Int32.max_int ->
 			None (* out range, keep platform-specific behavior *)
 			None (* out range, keep platform-specific behavior *)
 		| _ ->
 		| _ ->
-			Some { eexpr = TConst (TInt (Int32.of_float (ceil f))); etype = com.basic.tint; epos = p })
+			Some { eexpr = TConst (TInt (Int32.of_float (ceil f))); etype = basic.tint; epos = p })
 	| ([],"Math"),"floor",[{ eexpr = TConst (TFloat f) }] ->
 	| ([],"Math"),"floor",[{ eexpr = TConst (TFloat f) }] ->
 		let f = float_of_string f in
 		let f = float_of_string f in
 		(match classify_float f with
 		(match classify_float f with
@@ -87,7 +87,7 @@ let api_inline2 com c field params p =
 		| _ when f <= Int32.to_float Int32.min_int || f >= Int32.to_float Int32.max_int +. 1. ->
 		| _ when f <= Int32.to_float Int32.min_int || f >= Int32.to_float Int32.max_int +. 1. ->
 			None (* out range, keep platform-specific behavior *)
 			None (* out range, keep platform-specific behavior *)
 		| _ ->
 		| _ ->
-			Some { eexpr = TConst (TInt (Int32.of_float (floor f))); etype = com.basic.tint; epos = p })
+			Some { eexpr = TConst (TInt (Int32.of_float (floor f))); etype = basic.tint; epos = p })
 	| (["java"],"Lib"),("lock"),[obj;block] ->
 	| (["java"],"Lib"),("lock"),[obj;block] ->
 			Some (mk_untyped_call ("__lock__") p [obj;mk_block block])
 			Some (mk_untyped_call ("__lock__") p [obj;mk_block block])
 	| _ ->
 	| _ ->
@@ -185,7 +185,7 @@ let api_inline ctx c field params p =
 		with | Exit ->
 		with | Exit ->
 			None)
 			None)
 	| _ ->
 	| _ ->
-		api_inline2 ctx.com c field params p
+		api_inline2 ctx.com.basic ctx.com.platform c field params p
 
 
 type in_local = {
 type in_local = {
 	i_var : tvar;
 	i_var : tvar;

+ 1 - 1
src/typing/macroContext.ml

@@ -41,7 +41,7 @@ let macro_interp_cache = ref None
 
 
 let safe_decode com v expected t p f =
 let safe_decode com v expected t p f =
 	let raise_decode_error s =
 	let raise_decode_error s =
-		let path = [dump_path com;"decoding_error"] in
+		let path = [Dump.dump_path com.defines;"decoding_error"] in
 		let ch = Path.create_file false ".txt" [] path  in
 		let ch = Path.create_file false ".txt" [] path  in
 		let errors = Interp.handle_decoding_error (output_string ch) v t in
 		let errors = Interp.handle_decoding_error (output_string ch) v t in
 		List.iter (fun (s,i) -> Printf.fprintf ch "\nline %i: %s" i s) (List.rev errors);
 		List.iter (fun (s,i) -> Printf.fprintf ch "\nline %i: %s" i s) (List.rev errors);