瀏覽代碼

[analyzer] respect C#s ref types in local DCE

Simon Krajewski 10 年之前
父節點
當前提交
0a9ca00734
共有 2 個文件被更改,包括 15 次插入2 次删除
  1. 6 2
      analyzer.ml
  2. 9 0
      tests/unit/src/unit/TestCSharp.hx

+ 6 - 2
analyzer.ml

@@ -1246,11 +1246,15 @@ end
 module LocalDce = struct
 	let apply e =
 		let is_used v = Meta.has Meta.Used v.v_meta || type_has_analyzer_option v.v_type flag_no_local_dce in
+		let is_ref_type t = match t with
+			| TType({t_path = ["cs"],("Ref" | "Out")},_) -> true
+			| _ -> 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
+			| 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
 		in
 		let rec collect e = match e.eexpr with
@@ -1268,7 +1272,7 @@ module LocalDce = struct
 				e
 			| TBinop(OpAssign,({eexpr = TLocal v} as e1),e2) ->
 				let e2 = loop false e2 in
-				if not (is_used v) then
+				if not (is_used v) && not (is_ref_type v.v_type) then
 					e2
 				else
 					{e with eexpr = TBinop(OpAssign,{e1 with eexpr = TLocal v},e2)}

+ 9 - 0
tests/unit/src/unit/TestCSharp.hx

@@ -295,6 +295,11 @@ class TestCSharp extends Test
 		i *= 2;
 	}
 
+	@:skipReflection private function refTestAssign(i:cs.Ref<Int>):Void
+	{
+		i = 2;
+	}
+
 	@:skipReflection private function outTest(out:cs.Out<Int>, x:Int):Void
 	{
 		out = x * 2;
@@ -317,6 +322,10 @@ class TestCSharp extends Test
 
 	public function testRef()
 	{
+		var i = 10;
+		refTestAssign(i);
+		eq(i, 2);
+
 		var i = 10;
 		refTest(i);
 		eq(i, 20);