Browse Source

improve `has_side_effect` in LocalDce (see #3834)

Simon Krajewski 10 năm trước cách đây
mục cha
commit
ce79775ee1
2 tập tin đã thay đổi với 19 bổ sung6 xóa
  1. 18 5
      analyzer.ml
  2. 1 1
      tests/optimization/src/TestJs.hx

+ 18 - 5
analyzer.ml

@@ -1251,11 +1251,24 @@ module LocalDce = struct
 			| _ -> false
 		in
 		let use v = v.v_meta <- (Meta.Used,[],Ast.null_pos) :: v.v_meta in
-		let has_side_effect e = match e.eexpr with
-			| TVar(v,None) -> is_used v
-			| TVar(v,Some e1) -> is_used v || Optimizer.has_side_effect e1
-			| TBinop((OpAssign | OpAssignOp _),{eexpr = TLocal v},e2) -> is_used v || Optimizer.has_side_effect e2 || is_ref_type v.v_type
-			| _ -> Optimizer.has_side_effect e
+		let rec has_side_effect e =
+			let rec loop e =
+				match e.eexpr with
+				| TLocal v when Meta.has Meta.CompilerGenerated v.v_meta -> raise Exit
+				| TBinop((OpAssign | OpAssignOp _),{eexpr = TLocal v},e2) when is_used v || Optimizer.has_side_effect e2 || is_ref_type v.v_type -> raise Exit
+				| TVar(v,None) when is_used v -> raise Exit
+				| TVar(v,Some e1) when is_used v || Optimizer.has_side_effect e1 -> raise Exit
+				| TConst _ | TLocal _ | TTypeExpr _ | TFunction _ -> ()
+				| TCall ({ eexpr = TField(_,FStatic({ cl_path = ([],"Std") },{ cf_name = "string" })) },args) -> Type.iter loop e
+				| TNew _ | TCall _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> raise Exit
+				| TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) -> raise Exit
+				| TArray _ | TEnumParameter _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _ | TFor _
+				| TField _ | TIf _ | TTry _ | TSwitch _ | TArrayDecl _ | TBlock _ | TObjectDecl _ | TVar _ -> Type.iter loop e
+			in
+			try
+				loop e; false
+			with Exit ->
+				true
 		in
 		let rec collect e = match e.eexpr with
 			| TLocal v ->

+ 1 - 1
tests/optimization/src/TestJs.hx

@@ -13,7 +13,7 @@ class TestJs {
 	//Std.string(x);
 	//}
 
-	@:js("var a = new List();var _g_head = a.h;var _g_val = null;while(_g_head != null) {var tmp;_g_val = _g_head[0];_g_head = _g_head[1];tmp = _g_val;}")
+	@:js("var a = new List();var _g_head = a.h;var _g_val = null;while(_g_head != null) {var tmp;_g_val = _g_head[0];_g_head = _g_head[1];tmp = _g_val;tmp;}")
 	static function testListIteratorInline() {
 		var a = new List();
 		for (v in a) { }