Browse Source

[dce] add features for some specific cases that can be later used by generators for optimizing output

Dan Korostelev 10 năm trước cách đây
mục cha
commit
95a9411caa
1 tập tin đã thay đổi với 112 bổ sung2 xóa
  1. 112 2
      dce.ml

+ 112 - 2
dce.ml

@@ -86,6 +86,10 @@ let rec check_feature dce s =
 	with Not_found ->
 		()
 
+and check_and_add_feature dce s =
+	check_feature dce s;
+	Common.add_feature dce.com s;
+
 (* mark a field as kept *)
 and mark_field dce c cf stat =
 	let add cf =
@@ -137,6 +141,7 @@ end
 
 let rec mark_enum dce e = if not (Meta.has Meta.Used e.e_meta) then begin
 	e.e_meta <- (Meta.Used,[],e.e_pos) :: e.e_meta;
+	check_and_add_feature dce "has_enum";
 	check_feature dce (Printf.sprintf "%s.*" (s_type_path e.e_path));
 	PMap.iter (fun _ ef -> mark_t dce ef.ef_pos ef.ef_type) e.e_constrs;
 end
@@ -177,7 +182,7 @@ and mark_t dce p t =
 			List.iter (mark_t dce p) pl;
 			if not (Meta.has Meta.CoreType a.a_meta) then
 				mark_t dce p (Abstract.get_underlying_type a pl)
-		| TLazy _ | TDynamic _ | TAnon _ | TType _ | TMono _ -> ()
+		| TLazy _ | TDynamic _ | TType _ | TAnon _ | TMono _ -> ()
 		end;
 		dce.t_stack <- List.tl dce.t_stack
 	end
@@ -300,6 +305,35 @@ and mark_directly_used_mt mt =
 	| _ ->
 		()
 
+and check_dynamic_write dce fa =
+	let n = field_name fa in
+	check_and_add_feature dce ("dynamic_write");
+	check_and_add_feature dce ("dynamic_write." ^ n)
+
+and check_anon_optional_write dce fa =
+	let n = field_name fa in
+	check_and_add_feature dce ("anon_optional_write");
+	check_and_add_feature dce ("anon_optional_write." ^ n)
+
+and is_array t = match follow t with
+	| TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> is_array (Abstract.get_underlying_type a tl)
+	| TInst({ cl_path = ([], ("list" | "Array"))},_) -> true
+	| _ -> false
+
+and is_dynamic t = match follow t with
+	| TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> is_dynamic (Abstract.get_underlying_type a tl)
+	| TDynamic _ -> true
+	| _ -> false
+
+and is_string t = match follow t with
+	| TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> is_string (Abstract.get_underlying_type a tl)
+	| TInst( { cl_path = ([], ("str" | "String"))}, _) -> true
+	| _ -> false
+
+and is_const_string e = match e.eexpr with
+	| TConst(TString(_)) -> true
+	| _ -> false
+
 and expr dce e =
 	mark_t dce e.epos e.etype;
 	match e.eexpr with
@@ -317,6 +351,9 @@ and expr dce e =
 		mark_mt dce mt;
 		mark_directly_used_mt mt;
 		expr dce e;
+	| TObjectDecl(vl) ->
+		check_and_add_feature dce "has_anon";
+		List.iter (fun (_,e) -> expr dce e) vl;
 	| TTypeExpr mt ->
 		mark_mt dce mt;
 		mark_directly_used_mt mt;
@@ -327,10 +364,15 @@ and expr dce e =
 			expr dce e;
 			mark_t dce e.epos v.v_type;
 		) vl;
+	| TCall ({eexpr = TLocal ({v_name = "`trace"})},[p;{ eexpr = TObjectDecl(v)}]) ->
+		check_and_add_feature dce "has_anon_trace";
+		List.iter (fun (_,e) -> expr dce e) v;
+		expr dce p;
 	| TCall ({eexpr = TLocal ({v_name = "__define_feature__"})},[{eexpr = TConst (TString ft)};e]) ->
 		Hashtbl.replace dce.curclass.cl_module.m_extra.m_features ft true;
 		check_feature dce ft;
-		expr dce e
+		expr dce e;
+
 	(* keep toString method when the class is argument to Std.string or haxe.Log.trace *)
 	| TCall ({eexpr = TField({eexpr = TTypeExpr (TClassDecl ({cl_path = (["haxe"],"Log")} as c))},FStatic (_,{cf_name="trace"}))} as ef, ((e2 :: el) as args))
 	| TCall ({eexpr = TField({eexpr = TTypeExpr (TClassDecl ({cl_path = ([],"Std")} as c))},FStatic (_,{cf_name="string"}))} as ef, ((e2 :: el) as args)) ->
@@ -356,6 +398,62 @@ and expr dce e =
 	| TCall ({eexpr = TConst TSuper} as e,el) ->
 		mark_t dce e.epos e.etype;
 		List.iter (expr dce) el;
+	| TBinop(OpAdd,e1,e2) when is_dynamic e1.etype || is_dynamic e2.etype ->
+		check_and_add_feature dce "add_dynamic";
+		expr dce e1;
+		expr dce e2;
+	| TBinop( (OpAdd | (OpAssignOp OpAdd)),e1,e2) when ((is_string e1.etype || is_string e2.etype) && not ( is_const_string e1 && is_const_string e2)) ->
+		check_and_add_feature dce "unsafe_string_concat";
+		expr dce e1;
+		expr dce e2;
+	| TArray(({etype = TDynamic t} as e1),e2) when t == t_dynamic ->
+		check_and_add_feature dce "dynamic_array_read";
+		expr dce e1;
+		expr dce e2;
+	| TBinop( (OpAssign | OpAssignOp _), ({eexpr = TArray({etype = TDynamic t},_)} as e1), e2) when t == t_dynamic ->
+		check_and_add_feature dce "dynamic_array_write";
+		expr dce e1;
+		expr dce e2;
+	| TArray(({etype = t} as e1),e2) when is_array t ->
+		check_and_add_feature dce "array_read";
+		expr dce e1;
+		expr dce e2;
+	| TBinop( (OpAssign | OpAssignOp _), ({eexpr = TArray({etype = t},_)} as e1), e2) when is_array t ->
+		check_and_add_feature dce "array_write";
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpAssign,({eexpr = TField(_,(FDynamic _ as fa) )} as e1),e2) ->
+		check_dynamic_write dce fa;
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpAssign,({eexpr = TField(_,(FAnon cf as fa) )} as e1),e2) when Meta.has Meta.Optional cf.cf_meta ->
+		check_anon_optional_write dce fa;
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpAssignOp op,({eexpr = TField(_,(FDynamic _ as fa) )} as e1),e2) ->
+		check_dynamic_write dce fa;
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpAssignOp op,({eexpr = TField(_,(FAnon cf as fa) )} as e1),e2) when Meta.has Meta.Optional cf.cf_meta ->
+		check_anon_optional_write dce fa;
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpEq,({ etype = t1} as e1), ({ etype = t2} as e2) ) when is_dynamic t1 || is_dynamic t2 ->
+		check_and_add_feature dce "dynamic_binop_==";
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpEq,({ etype = t1} as e1), ({ etype = t2} as e2) ) when is_dynamic t1 || is_dynamic t2 ->
+		check_and_add_feature dce "dynamic_binop_!=";
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpMod,e1,e2) ->
+		check_and_add_feature dce "binop_%";
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpUShr,e1,e2) ->
+		check_and_add_feature dce "binop_>>>";
+		expr dce e1;
+		expr dce e2;
 	| TField(e,fa) ->
 		begin match fa with
 			| FStatic(c,cf) ->
@@ -365,7 +463,16 @@ and expr dce e =
 				mark_class dce c;
 				mark_field dce c cf false;
 			| _ ->
+
 				let n = field_name fa in
+				(match fa with
+				| FAnon cf when Meta.has Meta.Optional cf.cf_meta ->
+					check_and_add_feature dce "anon_optional_read";
+					check_and_add_feature dce ("anon_optional_read." ^ n);
+				| FDynamic _ ->
+					check_and_add_feature dce "dynamic_read";
+					check_and_add_feature dce ("dynamic_read." ^ n);
+				| _ -> ());
 				begin match follow e.etype with
 					| TInst(c,_) ->
 						mark_class dce c;
@@ -376,11 +483,14 @@ and expr dce e =
 							mark_class dce c;
 							field dce c n true;
 						| _ -> ())
+
+
 					| _ -> ()
 				end;
 		end;
 		expr dce e;
 	| TThrow e ->
+		check_and_add_feature dce "has_throw";
 		to_string dce e.etype;
 		expr dce e
 	| _ ->