2
0
Эх сурвалжийг харах

refine interference checker

Simon Krajewski 9 жил өмнө
parent
commit
d18081c11f

+ 16 - 14
analyzer.ml

@@ -386,6 +386,18 @@ module TexprFilter = struct
 			| ({eexpr = TVar(v1,Some e1)} as ev) :: e2 :: el when Meta.has Meta.CompilerGenerated v1.v_meta && get_num_uses v1 <= 1 && can_be_used_as_value com e1 ->
 				let found = ref false in
 				let affected = ref false in
+				let rec check_non_var_side_effect e2 = match e2.eexpr with
+						| TBinop((OpAssign | OpAssignOp _),{eexpr = TLocal _},e2) ->
+							check_non_var_side_effect e2
+						| TUnop((Increment | Decrement),_,{eexpr = TLocal _}) ->
+							()
+						| TBinop((OpAssign | OpAssignOp _),_,_) | TUnop((Increment | Decrement),_,_) ->
+							raise Exit
+						| TCall _ | TNew _ ->
+							raise Exit
+						| _ ->
+							Type.iter check_non_var_side_effect e2
+				in
 				let check_interference e2 =
 					let rec check e1 e2 = match e1.eexpr with
 						| TLocal v1 ->
@@ -396,20 +408,10 @@ module TexprFilter = struct
 									Type.iter check2 e2
 							in
 							check2 e2
-						| TField _ ->
-							let rec check2 e2 = match e2.eexpr with
-								| TBinop((OpAssign | OpAssignOp _),{eexpr = TLocal _},e2) ->
-									check2 e2
-								| TUnop((Increment | Decrement),_,{eexpr = TLocal _}) ->
-									()
-								| TBinop((OpAssign | OpAssignOp _),_,_) | TUnop((Increment | Decrement),_,_) ->
-									raise Exit
-								| TCall _ | TNew _ ->
-									raise Exit
-								| _ ->
-									Type.iter check2 e2
-							in
-							check2 e2
+						| TField _ when Optimizer.is_affected_type e1.etype ->
+							check_non_var_side_effect e2;
+						| TCall _ | TNew _ | TBinop((OpAssign | OpAssignOp _),_,_) | TUnop((Increment | Decrement),_,_) ->
+							check_non_var_side_effect e2
 						| _ ->
 							()
 					in

+ 5 - 4
optimizer.ml

@@ -220,11 +220,12 @@ let api_inline ctx c field params p = match c.cl_path, field, params with
 	| _ ->
 		api_inline2 ctx.com c field params p
 
+let is_affected_type t = match follow t with
+	| TAbstract({a_path = [],("Int" | "Float" | "Bool")},_) -> true
+	| TDynamic _ -> true (* sadly *)
+	| _ -> false
+
 let create_affection_checker () =
-	let is_affected_type t = match follow t with
-		| TAbstract({a_path = [],("Int" | "Float" | "Bool")},_) -> true
-		| _ -> false
-	in
 	let modified_locals = Hashtbl.create 0 in
 	let rec might_be_affected e =
 		let rec loop e = match e.eexpr with

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

@@ -464,7 +464,102 @@ class TestJs {
 		}
 	}
 
+	@:js('
+		var d1 = TestJs.intField;
+		TestJs.call(TestJs["use"](null),d1);
+	')
+	static function testInlineRebuilding1() {
+		inlineCall(intField, use(null));
+	}
+
+	@:js('
+		TestJs.call(TestJs["use"](null),TestJs.stringField);
+	')
+	static function testInlineRebuilding2() {
+		inlineCall(stringField, use(null));
+	}
+
+	@:js('
+		var a = TestJs.getArray();
+		var d1 = a[0]++;
+		TestJs.call(a[1]++,d1);
+	')
+	static function testInlineRebuilding3() {
+		var a = getArray();
+		inlineCall(a[0]++, a[1]++);
+	}
+
+	@:js('
+		var a = TestJs.getArray();
+		var d1 = a[0] = 1;
+		TestJs.call(a[1] = 1,d1);
+	')
+	static function testInlineRebuilding4() {
+		var a = getArray();
+		inlineCall(a[0] = 1, a[1] = 1);
+	}
+
+	@:js('
+		var a = TestJs.getArray();
+		var d1 = a[0] += 1;
+		TestJs.call(a[1] += 1,d1);
+	')
+	static function testInlineRebuilding5() {
+		var a = getArray();
+		inlineCall(a[0] += 1, a[1] += 1);
+	}
+
+	@:js('
+		var d1 = TestJs.call(1,2);
+		TestJs.call(TestJs.call(3,4),d1);
+	')
+	static function testInlineRebuilding6() {
+		inlineCall(call(1, 2), call(3, 4));
+	}
+
+	@:js('
+		var d1;
+		var d11 = TestJs.call(1,2);
+		d1 = TestJs.call(TestJs.call(3,4),d11);
+		var d2;
+		var d12 = TestJs.call(5,6);
+		d2 = TestJs.call(TestJs.call(7,8),d12);
+		TestJs.call(d2,d1);
+	')
+	static function testInlineRebuilding7() {
+		inlineCall(inlineCall(call(1, 2), call(3, 4)), inlineCall(call(5, 6), call(7, 8)));
+	}
+
+	@:js('
+		var d1;
+		var d11 = TestJs.call(1,2);
+		d1 = TestJs.call(TestJs.intField,d11);
+		var d2;
+		var d12 = TestJs.intField;
+		d2 = TestJs.call(TestJs.call(5,6),d12);
+		TestJs.call(d2,d1);
+	')
+	static function testInlineRebuilding8() {
+		inlineCall(inlineCall(call(1, 2), intField), inlineCall(intField, call(5, 6)));
+	}
+
+	@:js('
+		var d1 = TestJs.call(TestJs.stringField,TestJs.call(1,2));
+		TestJs.call(TestJs.call(TestJs.call(5,6),TestJs.stringField),d1);
+	')
+	static function testInlineRebuilding9() {
+		inlineCall(inlineCall(call(1, 2), stringField), inlineCall(stringField, call(5, 6)));
+	}
+
+	static inline function inlineCall(d1:Dynamic, d2:Dynamic) {
+		return call(d2, d1);
+	}
+
 	static function getInt(?d:Dynamic) { return 1; }
+	static function getArray() { return [0, 1]; }
 	static function call(d1:Dynamic, d2:Dynamic) { return d1; }
-	static function use<T>(t:T) { }
+	static function use<T>(t:T) { return t; }
+
+	static var intField = 12;
+	static var stringField = "foo";
 }