Преглед на файлове

[java/cs] Cast field field accesses to type parameters to their implementation instead of going through reflection

Closes #3790
Cauê Waneck преди 8 години
родител
ревизия
b0f0ddfe8f
променени са 3 файла, в които са добавени 27 реда и са изтрити 9 реда
  1. 1 1
      src/generators/gencommon/castDetect.ml
  2. 24 6
      src/generators/gencommon/dynamicFieldAccess.ml
  3. 2 2
      src/generators/gencommon/reflectionCFs.ml

+ 1 - 1
src/generators/gencommon/castDetect.ml

@@ -45,7 +45,7 @@ open Gencommon
 		Must run before ExpressionUnwrap
 		Must run before ExpressionUnwrap
 
 
 *)
 *)
-let name = "cast_detect_2"
+let name = "cast_detect"
 let priority = solve_deps name [DBefore RealTypeParams.priority; DBefore ExpressionUnwrap.priority]
 let priority = solve_deps name [DBefore RealTypeParams.priority; DBefore ExpressionUnwrap.priority]
 
 
 (* ******************************************* *)
 (* ******************************************* *)

+ 24 - 6
src/generators/gencommon/dynamicFieldAccess.ml

@@ -56,10 +56,28 @@ let priority = solve_deps name [DAfter DynamicOperators.priority]
 	change_expr (expr) (field_access_expr) (field) (setting expr) (is_unsafe) : changes the expression
 	change_expr (expr) (field_access_expr) (field) (setting expr) (is_unsafe) : changes the expression
 	call_expr (expr) (field_access_expr) (field) (call_params) : changes a call expression
 	call_expr (expr) (field_access_expr) (field) (call_params) : changes a call expression
 *)
 *)
-let configure gen (is_dynamic:texpr->texpr->Type.tfield_access->bool) (change_expr:texpr->texpr->string->texpr option->bool->texpr) (call_expr:texpr->texpr->string->texpr list->texpr) =
+let configure gen ?fix_tparam_access (is_dynamic:texpr->Type.tfield_access->bool) (change_expr:texpr->texpr->string->texpr option->bool->texpr) (call_expr:texpr->texpr->string->texpr list->texpr) =
+	let fix_tparam_access = match fix_tparam_access with
+		| None -> false
+		| Some f -> f
+	in
+	let is_nondynamic_tparam fexpr f = match follow fexpr.etype with
+		| TInst({ cl_kind = KTypeParameter(tl) }, _) ->
+			List.exists (fun t -> not (is_dynamic { fexpr with etype = t } f)) tl
+		| _ -> false
+	in
+
+	let fix_tparam_access = true in
 	let rec run e =
 	let rec run e =
 		match e.eexpr with
 		match e.eexpr with
 		(* class types *)
 		(* class types *)
+		| TField(fexpr, f) when fix_tparam_access && is_nondynamic_tparam fexpr f ->
+			(match follow fexpr.etype with
+				| TInst({ cl_kind = KTypeParameter(tl) }, _) ->
+					let t = List.find (fun t -> not (is_dynamic { fexpr with etype = t } f)) tl in
+					{ e with eexpr = TField(mk_cast t (run fexpr), f) }
+				| _ -> assert false)
+
 		| TField(fexpr, f) when is_some (anon_class fexpr.etype) ->
 		| TField(fexpr, f) when is_some (anon_class fexpr.etype) ->
 			let decl = get (anon_class fexpr.etype) in
 			let decl = get (anon_class fexpr.etype) in
 			let name = field_name f in
 			let name = field_name f in
@@ -81,7 +99,7 @@ let configure gen (is_dynamic:texpr->texpr->Type.tfield_access->bool) (change_ex
 				| _ ->
 				| _ ->
 					change_expr e { fexpr with eexpr = TTypeExpr decl } (field_name f) None true)
 					change_expr e { fexpr with eexpr = TTypeExpr decl } (field_name f) None true)
 
 
-		| TField (fexpr, f) when is_dynamic e fexpr f ->
+		| TField (fexpr, f) when is_dynamic fexpr f ->
 			change_expr e (run fexpr) (field_name f) None true
 			change_expr e (run fexpr) (field_name f) None true
 
 
 		| TCall ({ eexpr = TField (_, FStatic({ cl_path = ([], "Reflect") }, { cf_name = "field" })) }, [obj; { eexpr = TConst (TString field) }]) ->
 		| TCall ({ eexpr = TField (_, FStatic({ cl_path = ([], "Reflect") }, { cf_name = "field" })) }, [obj; { eexpr = TConst (TString field) }]) ->
@@ -94,7 +112,7 @@ let configure gen (is_dynamic:texpr->texpr->Type.tfield_access->bool) (change_ex
 		| TCall ({ eexpr = TField (_, FStatic({ cl_path = ([], "Reflect") }, { cf_name = "setField" } )) }, [obj; { eexpr = TConst(TString field) }; evalue]) ->
 		| TCall ({ eexpr = TField (_, FStatic({ cl_path = ([], "Reflect") }, { cf_name = "setField" } )) }, [obj; { eexpr = TConst(TString field) }; evalue]) ->
 			change_expr (mk_field_access gen obj field obj.epos) (run obj) field (Some (run evalue)) false
 			change_expr (mk_field_access gen obj field obj.epos) (run obj) field (Some (run evalue)) false
 
 
-		| TBinop (OpAssign, { eexpr = TField(fexpr, f) }, evalue) when is_dynamic e fexpr f ->
+		| TBinop (OpAssign, { eexpr = TField(fexpr, f) }, evalue) when is_dynamic fexpr f ->
 			change_expr e (run fexpr) (field_name f) (Some (run evalue)) true
 			change_expr e (run fexpr) (field_name f) (Some (run evalue)) true
 
 
 		| TBinop (OpAssign, { eexpr = TField(fexpr, f) }, evalue) ->
 		| TBinop (OpAssign, { eexpr = TField(fexpr, f) }, evalue) ->
@@ -104,13 +122,13 @@ let configure gen (is_dynamic:texpr->texpr->Type.tfield_access->bool) (change_ex
 			| _ ->
 			| _ ->
 				Type.map_expr run e)
 				Type.map_expr run e)
 
 
-		| TBinop (OpAssignOp _, { eexpr = TField (fexpr, f) }, _) when is_dynamic e fexpr f ->
+		| TBinop (OpAssignOp _, { eexpr = TField (fexpr, f) }, _) when is_dynamic fexpr f ->
 			assert false (* this case shouldn't happen *)
 			assert false (* this case shouldn't happen *)
 		| TUnop (Increment, _, { eexpr = TField (({ eexpr = TLocal _ } as fexpr), f)})
 		| TUnop (Increment, _, { eexpr = TField (({ eexpr = TLocal _ } as fexpr), f)})
-		| TUnop (Decrement, _, { eexpr = TField (({ eexpr = TLocal _ } as fexpr), f)}) when is_dynamic e fexpr f ->
+		| TUnop (Decrement, _, { eexpr = TField (({ eexpr = TLocal _ } as fexpr), f)}) when is_dynamic fexpr f ->
 			assert false (* this case shouldn't happen *)
 			assert false (* this case shouldn't happen *)
 
 
-		| TCall ({ eexpr = TField (fexpr, f) }, params) when is_dynamic e fexpr f ->
+		| TCall ({ eexpr = TField (fexpr, f) }, params) when is_dynamic fexpr f && (not (fix_tparam_access && is_nondynamic_tparam fexpr f)) ->
 			call_expr e (run fexpr) (field_name f) (List.map run params)
 			call_expr e (run fexpr) (field_name f) (List.map run params)
 
 
 		| _ ->
 		| _ ->

+ 2 - 2
src/generators/gencommon/reflectionCFs.ml

@@ -1594,7 +1594,7 @@ let get_closure_func ctx closure_cl =
 
 
 let configure_dynamic_field_access ctx =
 let configure_dynamic_field_access ctx =
 	let gen = ctx.rcf_gen in
 	let gen = ctx.rcf_gen in
-	let is_dynamic expr fexpr field =
+	let is_dynamic fexpr field =
 		match (field_access_esp gen (gen.greal_type fexpr.etype) field) with
 		match (field_access_esp gen (gen.greal_type fexpr.etype) field) with
 		| FEnumField _
 		| FEnumField _
 		| FClassField _ -> false
 		| FClassField _ -> false
@@ -1602,7 +1602,7 @@ let configure_dynamic_field_access ctx =
 	in
 	in
 
 
 	let maybe_hash = if ctx.rcf_optimize then fun str pos -> Some (hash_field_i32 ctx pos str) else fun str pos -> None in
 	let maybe_hash = if ctx.rcf_optimize then fun str pos -> Some (hash_field_i32 ctx pos str) else fun str pos -> None in
-	DynamicFieldAccess.configure gen is_dynamic
+	DynamicFieldAccess.configure gen ~fix_tparam_access:true is_dynamic
 		(fun expr fexpr field set is_unsafe ->
 		(fun expr fexpr field set is_unsafe ->
 			let hash = maybe_hash field fexpr.epos in
 			let hash = maybe_hash field fexpr.epos in
 			ctx.rcf_on_getset_field expr fexpr field hash set is_unsafe
 			ctx.rcf_on_getset_field expr fexpr field hash set is_unsafe