瀏覽代碼

always concatenate strings if one is empty (closes #4739)

Simon Krajewski 9 年之前
父節點
當前提交
e90911be56
共有 4 個文件被更改,包括 35 次插入12 次删除
  1. 11 10
      analyzer.ml
  2. 2 0
      optimizer.ml
  3. 21 0
      tests/optimization/src/TestJs.hx
  4. 1 2
      tests/optimization/src/TestLocalDce.hx

+ 11 - 10
analyzer.ml

@@ -1674,22 +1674,23 @@ module ConstPropagation = DataFlow(struct
 		lattice := IntMap.empty
 		lattice := IntMap.empty
 
 
 	let commit ctx =
 	let commit ctx =
+		let inline e i = match get_cell i with
+			| Top | Bottom | EnumValue _ ->
+				raise Not_found
+			| Const ct ->
+				let e' = Codegen.type_constant ctx.com (tconst_to_const ct) e.epos in
+				if not (type_iseq e'.etype e.etype) then raise Not_found;
+				e'
+		in
 		let rec commit e = match e.eexpr with
 		let rec commit e = match e.eexpr with
 			| TLocal v when not v.v_capture ->
 			| TLocal v when not v.v_capture ->
 				begin try
 				begin try
-					begin match get_cell v.v_id with
-						| Top | Bottom | EnumValue _ ->
-							raise Not_found
-						| Const ct ->
-							let e' = Codegen.type_constant ctx.com (tconst_to_const ct) e.epos in
-							if not (type_iseq e'.etype e.etype) then raise Not_found;
-							e'
-					end
+					inline e v.v_id
 				with Not_found ->
 				with Not_found ->
 					e
 					e
 				end
 				end
-			| TBinop((OpAssign | OpAssignOp _ as op),({eexpr = TLocal _} as e1),e2) ->
-				let e2 = commit e2 in
+			| TBinop((OpAssign | OpAssignOp _ as op),({eexpr = TLocal v} as e1),e2) ->
+				let e2 = try inline e2 v.v_id with Not_found -> commit e2 in
 				{e with eexpr = TBinop(op,e1,e2)}
 				{e with eexpr = TBinop(op,e1,e2)}
 			| _ ->
 			| _ ->
 				Type.map_expr commit e
 				Type.map_expr commit e

+ 2 - 0
optimizer.ml

@@ -1161,6 +1161,8 @@ let optimize_binop e op e1 e2 =
 		| OpLt -> ebool (<)
 		| OpLt -> ebool (<)
 		| OpLte -> ebool (<=)
 		| OpLte -> ebool (<=)
 		| _ -> e)
 		| _ -> e)
+	| TConst (TString ""),TConst (TString s) | TConst (TString s),TConst (TString "") when op = OpAdd ->
+		{e with eexpr = TConst (TString s)}
 	| TConst (TBool a), TConst (TBool b) ->
 	| TConst (TBool a), TConst (TBool b) ->
 		let ebool f =
 		let ebool f =
 			{ e with eexpr = TConst (TBool (f a b)) }
 			{ e with eexpr = TConst (TBool (f a b)) }

+ 21 - 0
tests/optimization/src/TestJs.hx

@@ -286,6 +286,27 @@ class TestJs {
 		});
 		});
 	}
 	}
 
 
+	@:js('
+		var a = 0;
+		if(Math.random() < 0.5) a = 2;
+		var b = "";
+		if(Math.random() < 0.5) b = "hello";
+		TestJs["use"](a);
+		TestJs["use"](b);
+	')
+	static function testIssue4739() {
+        var a = 0;
+        if (Math.random() < 0.5)
+            a += 2;
+
+        var b = "";
+        if (Math.random() < 0.5)
+            b = b + "hello";
+
+        use(a);
+		use(b);
+	}
+
 	static function getInt(?d:Dynamic) { return 1; }
 	static function getInt(?d:Dynamic) { return 1; }
 	static function call(d1:Dynamic, d2:Dynamic) { return d1; }
 	static function call(d1:Dynamic, d2:Dynamic) { return d1; }
 	static function use<T>(t:T) { }
 	static function use<T>(t:T) { }

+ 1 - 2
tests/optimization/src/TestLocalDce.hx

@@ -120,8 +120,7 @@ class TestLocalDce {
 	}
 	}
 
 
 	@:js('
 	@:js('
-		var s = "" + "a";
-		console.log(s);
+		console.log("a");
 	')
 	')
 	static function testAbstractOverStringBinop() {
 	static function testAbstractOverStringBinop() {
 		var s = "" + A;
 		var s = "" + A;