瀏覽代碼

[java/cs] Avoid boxing when comparing Null<> basic types

Closes #4048
Cauê Waneck 8 年之前
父節點
當前提交
6046ad7265
共有 3 個文件被更改,包括 53 次插入22 次删除
  1. 2 3
      src/generators/gencommon/dynamicOperators.ml
  2. 24 7
      src/generators/gencs.ml
  3. 27 12
      src/generators/genjava.ml

+ 2 - 3
src/generators/gencommon/dynamicOperators.ml

@@ -62,7 +62,7 @@ open Gencommon
 		must run before OverloadingConstructor due to later priority conflicts. Since ExpressionUnwrap is only
 		must run before OverloadingConstructor due to later priority conflicts. Since ExpressionUnwrap is only
 		defined afterwards, we will set this value with absolute values
 		defined afterwards, we will set this value with absolute values
 *)
 *)
-let init com handle_strings (should_change:texpr->bool) (equals_handler:texpr->texpr->texpr) (dyn_plus_handler:texpr->texpr->texpr->texpr) (compare_handler:texpr->texpr->texpr) =
+let init com handle_strings (should_change:texpr->bool) (equals_handler:texpr->texpr->texpr) (dyn_plus_handler:texpr->texpr->texpr->texpr) (compare_handler:Ast.binop->texpr->texpr->texpr->texpr) =
 	let get_etype_one e =
 	let get_etype_one e =
 		if like_int e.etype then
 		if like_int e.etype then
 			ExprBuilder.make_int com 1 e.epos
 			ExprBuilder.make_int com 1 e.epos
@@ -110,8 +110,7 @@ let init com handle_strings (should_change:texpr->bool) (equals_handler:texpr->t
 				else
 				else
 					dyn_plus_handler e (run e1) (run e2)
 					dyn_plus_handler e (run e1) (run e2)
 			| OpGt | OpGte | OpLt | OpLte  -> (* type 2 *)
 			| OpGt | OpGte | OpLt | OpLte  -> (* type 2 *)
-				let zero = ExprBuilder.make_int com 0 e.epos in
-				mk (TBinop (op, compare_handler (run e1) (run e2), zero)) com.basic.tbool e.epos
+				compare_handler op e (run e1) (run e2)
 			| OpMult | OpDiv | OpSub | OpMod -> (* always cast everything to double *)
 			| OpMult | OpDiv | OpSub | OpMod -> (* always cast everything to double *)
 				let etype = (get_etype_one e).etype in
 				let etype = (get_etype_one e).etype in
 				{ e with eexpr = TBinop (op, mk_cast etype (run e1), mk_cast etype (run e2)) }
 				{ e with eexpr = TBinop (op, mk_cast etype (run e1), mk_cast etype (run e2)) }

+ 24 - 7
src/generators/gencs.ml

@@ -2991,6 +2991,13 @@ let generate con =
 			| _ -> false
 			| _ -> false
 		in
 		in
 
 
+		let nullable_basic t = match gen.gfollow#run_f t with
+			| TType({ t_path = ([],"Null") }, [t]) when is_cs_basic_type t ->
+				Some(t)
+			| _ ->
+				None
+		in
+
 		DynamicOperators.configure gen
 		DynamicOperators.configure gen
 			~handle_strings:false
 			~handle_strings:false
 			(fun e -> match e.eexpr with
 			(fun e -> match e.eexpr with
@@ -3056,13 +3063,23 @@ let generate con =
 					| _ ->
 					| _ ->
 						let static = mk_static_field_access_infer (runtime_cl) "plus"  e1.epos [] in
 						let static = mk_static_field_access_infer (runtime_cl) "plus"  e1.epos [] in
 						mk_cast e.etype { eexpr = TCall(static, [e1; e2]); etype = t_dynamic; epos=e1.epos })
 						mk_cast e.etype { eexpr = TCall(static, [e1; e2]); etype = t_dynamic; epos=e1.epos })
-			(fun e1 e2 ->
-				if is_string e1.etype then begin
-					{ e1 with eexpr = TCall(mk_static_field_access_infer string_cl "Compare" e1.epos [], [ e1; e2 ]); etype = gen.gcon.basic.tint }
-				end else begin
-					let static = mk_static_field_access_infer (runtime_cl) "compare" e1.epos [] in
-					{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos }
-				end);
+		(fun op e e1 e2 ->
+				match nullable_basic e1.etype, nullable_basic e2.etype with
+					| Some(t1), None when is_cs_basic_type e2.etype ->
+						{ e with eexpr = TBinop(op, mk_cast t1 e1, e2) }
+					| None, Some(t2) when is_cs_basic_type e1.etype ->
+						{ e with eexpr = TBinop(op, e1, mk_cast t2 e2) }
+					| _ ->
+							let handler = if is_string e1.etype then begin
+									{ e1 with eexpr = TCall(mk_static_field_access_infer string_cl "Compare" e1.epos [], [ e1; e2 ]); etype = gen.gcon.basic.tint }
+								end else begin
+									let static = mk_static_field_access_infer (runtime_cl) "compare" e1.epos [] in
+									{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos }
+								end
+							in
+							let zero = ExprBuilder.make_int gen.gcon 0 e.epos in
+							{ e with eexpr = TBinop(op, handler, zero) }
+		);
 
 
 		FilterClosures.configure gen (fun e1 s -> true) (ReflectionCFs.get_closure_func rcf_ctx closure_cl);
 		FilterClosures.configure gen (fun e1 s -> true) (ReflectionCFs.get_closure_func rcf_ctx closure_cl);
 
 

+ 27 - 12
src/generators/genjava.ml

@@ -145,11 +145,8 @@ let is_java_basic_type t =
 	match follow t with
 	match follow t with
 		| TInst( { cl_path = (["haxe"], "Int32") }, [] )
 		| TInst( { cl_path = (["haxe"], "Int32") }, [] )
 		| TInst( { cl_path = (["haxe"], "Int64") }, [] )
 		| TInst( { cl_path = (["haxe"], "Int64") }, [] )
-		| TAbstract( { a_path = ([], "Single") }, [] )
 		| TAbstract( { a_path = (["java"], ("Int8" | "Int16" | "Char16" | "Int64")) }, [] )
 		| TAbstract( { a_path = (["java"], ("Int8" | "Int16" | "Char16" | "Int64")) }, [] )
-		| TAbstract( { a_path =	([], "Int") }, [] )
-		| TAbstract( { a_path =	([], "Float") }, [] )
-		| TAbstract( { a_path =	([], "Bool") }, [] ) ->
+		| TAbstract( { a_path =	([], ("Int"|"Float"|"Bool"|"Single")) }, [] ) ->
 			true
 			true
 		| _ -> false
 		| _ -> false
 
 
@@ -2478,6 +2475,13 @@ let generate con =
 	let is_double t = like_float t && not (like_int t) in
 	let is_double t = like_float t && not (like_int t) in
 	let is_int t = like_int t in
 	let is_int t = like_int t in
 
 
+	let nullable_basic t = match gen.gfollow#run_f t with
+		| TType({ t_path = ([],"Null") }, [t]) when is_java_basic_type t ->
+			Some(t)
+		| _ ->
+			None
+	in
+
 	DynamicOperators.configure gen
 	DynamicOperators.configure gen
 		~handle_strings:true
 		~handle_strings:true
 		(fun e -> match e.eexpr with
 		(fun e -> match e.eexpr with
@@ -2488,7 +2492,8 @@ let generate con =
 			| TBinop (Ast.OpLt, e1, e2)
 			| TBinop (Ast.OpLt, e1, e2)
 			| TBinop (Ast.OpLte, e1, e2)
 			| TBinop (Ast.OpLte, e1, e2)
 			| TBinop (Ast.OpGte, e1, e2)
 			| TBinop (Ast.OpGte, e1, e2)
-			| TBinop (Ast.OpGt, e1, e2) -> is_dynamic_op e.etype || is_dynamic_op e1.etype || is_dynamic_op e2.etype || is_string e1.etype || is_string e2.etype
+			| TBinop (Ast.OpGt, e1, e2) ->
+				is_dynamic_op e.etype || is_dynamic_op e1.etype || is_dynamic_op e2.etype || is_string e1.etype || is_string e2.etype
 			| TBinop (_, e1, e2) -> is_dynamic_op e.etype || is_dynamic_expr is_dynamic_op e1 || is_dynamic_expr is_dynamic_op e2
 			| TBinop (_, e1, e2) -> is_dynamic_op e.etype || is_dynamic_expr is_dynamic_op e1 || is_dynamic_expr is_dynamic_op e2
 			| TUnop (_, _, e1) ->
 			| TUnop (_, _, e1) ->
 				is_dynamic_expr is_dynamic_op e1
 				is_dynamic_expr is_dynamic_op e1
@@ -2537,13 +2542,23 @@ let generate con =
 				| _ ->
 				| _ ->
 					let static = mk_static_field_access_infer (runtime_cl) "plus"  e1.epos [] in
 					let static = mk_static_field_access_infer (runtime_cl) "plus"  e1.epos [] in
 					mk_cast e.etype { eexpr = TCall(static, [e1; e2]); etype = t_dynamic; epos=e1.epos })
 					mk_cast e.etype { eexpr = TCall(static, [e1; e2]); etype = t_dynamic; epos=e1.epos })
-		(fun e1 e2 ->
-			if is_string e1.etype then begin
-				{ e1 with eexpr = TCall(mk_field_access gen e1 "compareTo" e1.epos, [ e2 ]); etype = gen.gcon.basic.tint }
-			end else begin
-				let static = mk_static_field_access_infer (runtime_cl) "compare" e1.epos [] in
-				{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos }
-			end);
+		(fun op e e1 e2 ->
+				match nullable_basic e1.etype, nullable_basic e2.etype with
+					| Some(t1), None when is_java_basic_type e2.etype ->
+						{ e with eexpr = TBinop(op, mk_cast t1 e1, e2) }
+					| None, Some(t2) when is_java_basic_type e1.etype ->
+						{ e with eexpr = TBinop(op, e1, mk_cast t2 e2) }
+					| _ ->
+							let handler = if is_string e1.etype then begin
+									{ e1 with eexpr = TCall(mk_field_access gen e1 "compareTo" e1.epos, [ e2 ]); etype = gen.gcon.basic.tint }
+								end else begin
+									let static = mk_static_field_access_infer (runtime_cl) "compare" e1.epos [] in
+									{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos }
+								end
+							in
+							let zero = ExprBuilder.make_int gen.gcon 0 e.epos in
+							{ e with eexpr = TBinop(op, handler, zero) }
+			);
 
 
 	let closure_cl = get_cl (get_type gen (["haxe";"lang"],"Closure")) in
 	let closure_cl = get_cl (get_type gen (["haxe";"lang"],"Closure")) in
 	FilterClosures.configure gen (fun e1 s -> true) (ReflectionCFs.get_closure_func rcf_ctx closure_cl);
 	FilterClosures.configure gen (fun e1 s -> true) (ReflectionCFs.get_closure_func rcf_ctx closure_cl);