浏览代码

[cs/java] run TryCatchWrapper as a normal filter before analyzer and DCE - much cleaner output \o/ (also lose any gencommon dependency) (#6128)

Dan Korostelev 8 年之前
父节点
当前提交
f6196dd772

+ 10 - 0
src/generators/codegen.ml

@@ -32,6 +32,16 @@ module ExprBuilder = struct
 		let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
 		let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
 		mk (TTypeExpr (TClassDecl c)) ta p
 		mk (TTypeExpr (TClassDecl c)) ta p
 
 
+	let make_typeexpr mt pos =
+		let t =
+			match mt with
+			| TClassDecl c -> TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) }
+			| TEnumDecl e -> TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) }
+			| TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) }
+			| _ -> assert false
+		in
+		mk (TTypeExpr mt) t pos
+
 	let make_static_field c cf p =
 	let make_static_field c cf p =
 		let e_this = make_static_this c p in
 		let e_this = make_static_this c p in
 		mk (TField(e_this,FStatic(c,cf))) cf.cf_type p
 		mk (TField(e_this,FStatic(c,cf))) cf.cf_type p

+ 0 - 9
src/generators/gencommon.ml

@@ -142,15 +142,6 @@ let is_string t =
 	| TInst({ cl_path = ([], "String") }, []) -> true
 	| TInst({ cl_path = ([], "String") }, []) -> true
 	| _ -> false
 	| _ -> false
 
 
-let mk_mt_access mt pos =
-	let t = match mt with
-		| TClassDecl cl -> TAnon { a_fields = cl.cl_statics; a_status = ref (Statics cl) }
-		| TEnumDecl e -> TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) }
-		| TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) }
-		| _ -> assert false
-	in
-	mk (TTypeExpr mt) t pos
-
 let anon_class t =
 let anon_class t =
 	match follow t with
 	match follow t with
 	| TAnon anon ->
 	| TAnon anon ->

+ 2 - 1
src/generators/gencommon/switchToIf.ml

@@ -18,6 +18,7 @@
 *)
 *)
 open Common
 open Common
 open Type
 open Type
+open Codegen
 open Gencommon
 open Gencommon
 
 
 (* ******************************************* *)
 (* ******************************************* *)
@@ -110,7 +111,7 @@ let configure gen (should_convert:texpr->bool) =
 							| _ -> raise Not_found
 							| _ -> raise Not_found
 						in
 						in
 						if Meta.has Meta.Class real_enum.e_meta then raise Not_found;
 						if Meta.has Meta.Class real_enum.e_meta then raise Not_found;
-						let enum_expr = mk_mt_access (TEnumDecl(real_enum)) e.epos in
+						let enum_expr = ExprBuilder.make_typeexpr (TEnumDecl(real_enum)) e.epos in
 						let fields = Hashtbl.create (List.length real_enum.e_names) in
 						let fields = Hashtbl.create (List.length real_enum.e_names) in
 						PMap.iter (fun _ ef -> Hashtbl.add fields ef.ef_index ef) real_enum.e_constrs;
 						PMap.iter (fun _ ef -> Hashtbl.add fields ef.ef_index ef) real_enum.e_constrs;
 						let cases = List.map (fun (el,e) ->
 						let cases = List.map (fun (el,e) ->

+ 97 - 21
src/generators/gencommon/tryCatchWrapper.ml

@@ -22,7 +22,7 @@ open Common
 open Ast
 open Ast
 open Type
 open Type
 open Codegen
 open Codegen
-open Gencommon
+open Codegen.ExprBuilder
 
 
 (* ******************************************* *)
 (* ******************************************* *)
 (* Try / Catch + throw native types handling *)
 (* Try / Catch + throw native types handling *)
@@ -32,15 +32,11 @@ open Gencommon
 	special kinds of objects can be thrown. Because of this, we must wrap some throw
 	special kinds of objects can be thrown. Because of this, we must wrap some throw
 	statements with an expression, and also we must unwrap it on the catch() phase, and
 	statements with an expression, and also we must unwrap it on the catch() phase, and
 	maybe manually test with Std.is()
 	maybe manually test with Std.is()
-
-	dependencies:
-		must run before dynamic field access (?) TODO review
-		It's a syntax filter, as it alters types (throw wrapper)
 *)
 *)
 
 
 (*
 (*
 	should_wrap : does the type should be wrapped? This of course works on the reverse way, so it tells us if the type should be unwrapped as well
 	should_wrap : does the type should be wrapped? This of course works on the reverse way, so it tells us if the type should be unwrapped as well
-	wrap_throw : the wrapper for throw (throw expr->expr inside throw->returning wrapped expression)
+	wrap_throw : the wrapper for throw (throw expr->returning wrapped expression)
 	unwrap_expr : the other way around : given the catch var (maybe will need casting to wrapper_type) , return the unwrap expr
 	unwrap_expr : the other way around : given the catch var (maybe will need casting to wrapper_type) , return the unwrap expr
 	rethrow_expr : how to rethrow ane exception in the platform
 	rethrow_expr : how to rethrow ane exception in the platform
 	catchall_type : the class used for catchall (e:Dynamic)
 	catchall_type : the class used for catchall (e:Dynamic)
@@ -48,11 +44,11 @@ open Gencommon
 	catch_map : maps the catch expression to include some intialization code (e.g. setting up Stack.exceptionStack)
 	catch_map : maps the catch expression to include some intialization code (e.g. setting up Stack.exceptionStack)
 	gen_typecheck : generate Std.is (or similar) check expression for given expression and type
 	gen_typecheck : generate Std.is (or similar) check expression for given expression and type
 *)
 *)
-let init com (should_wrap:t->bool) (wrap_throw:texpr->texpr->texpr) (unwrap_expr:texpr->texpr) (rethrow_expr:texpr->texpr) (catchall_type:t) (wrapper_type:t) (catch_map:tvar->texpr->texpr) (gen_typecheck:texpr->t->pos->texpr) =
+let init com (should_wrap:t->bool) (wrap_throw:texpr->texpr) (unwrap_expr:texpr->texpr) (rethrow_expr:texpr->texpr) (catchall_type:t) (wrapper_type:t) (catch_map:tvar->texpr->texpr) (gen_typecheck:texpr->t->pos->texpr) =
 	let rec run e =
 	let rec run e =
 		match e.eexpr with
 		match e.eexpr with
 		| TThrow texpr when should_wrap texpr.etype ->
 		| TThrow texpr when should_wrap texpr.etype ->
-			wrap_throw e (run texpr)
+			wrap_throw (run texpr)
 		| TTry (ttry, catches) ->
 		| TTry (ttry, catches) ->
 			let nowrap_catches, must_wrap_catches, catchall = List.fold_left (fun (nowrap_catches, must_wrap_catches, catchall) (v, catch) ->
 			let nowrap_catches, must_wrap_catches, catchall = List.fold_left (fun (nowrap_catches, must_wrap_catches, catchall) (v, catch) ->
 				(* first we'll see if the type is Dynamic (catchall) *)
 				(* first we'll see if the type is Dynamic (catchall) *)
@@ -84,10 +80,10 @@ let init com (should_wrap:t->bool) (wrap_throw:texpr->texpr->texpr) (unwrap_expr
 			| _, (v, c) :: _ ->
 			| _, (v, c) :: _ ->
 				let pos = c.epos in
 				let pos = c.epos in
 
 
-				let temp_var = mk_temp "catchallException" catchall_type in
-				let temp_local = ExprBuilder.make_local temp_var pos in
-				let catchall_var = mk_temp "catchall" t_dynamic in
-				let catchall_local = ExprBuilder.make_local catchall_var pos in
+				let temp_var = alloc_var "catchallException" catchall_type pos in
+				let temp_local = make_local temp_var pos in
+				let catchall_var = alloc_var "realException" t_dynamic pos in
+				let catchall_local = make_local catchall_var pos in
 
 
 				(* if it is of type wrapper_type, unwrap it *)
 				(* if it is of type wrapper_type, unwrap it *)
 				let catchall_expr = mk (TIf (gen_typecheck temp_local wrapper_type pos, unwrap_expr temp_local, Some temp_local)) t_dynamic pos in
 				let catchall_expr = mk (TIf (gen_typecheck temp_local wrapper_type pos, unwrap_expr temp_local, Some temp_local)) t_dynamic pos in
@@ -97,7 +93,7 @@ let init com (should_wrap:t->bool) (wrap_throw:texpr->texpr->texpr) (unwrap_expr
 					match must_wrap_catches with
 					match must_wrap_catches with
 					| (vcatch,catch) :: tl ->
 					| (vcatch,catch) :: tl ->
 						mk (TIf (gen_typecheck catchall_local vcatch.v_type catch.epos,
 						mk (TIf (gen_typecheck catchall_local vcatch.v_type catch.epos,
-							     mk (TBlock [(mk (TVar (vcatch, Some(mk_cast (* TODO: this should be a fast non-dynamic cast *) vcatch.v_type catchall_local))) com.basic.tvoid catch.epos); catch]) catch.etype catch.epos,
+							     mk (TBlock [(mk (TVar (vcatch, Some(mk_cast (* TODO: this should be a fast non-dynamic cast *) catchall_local vcatch.v_type pos))) com.basic.tvoid catch.epos); catch]) catch.etype catch.epos,
 							     Some (loop tl))
 							     Some (loop tl))
 						) catch.etype catch.epos
 						) catch.etype catch.epos
 					| [] ->
 					| [] ->
@@ -117,14 +113,94 @@ let init com (should_wrap:t->bool) (wrap_throw:texpr->texpr->texpr) (unwrap_expr
 	in
 	in
 	run
 	run
 
 
-let name = "try_catch"
-let priority = solve_deps name [DBefore DynamicFieldAccess.priority]
+let find_class com path =
+	let mt = List.find (fun mt -> match mt with TClassDecl c -> c.cl_path = path | _ -> false) com.types in
+	match mt with TClassDecl c -> c | _ -> assert false
+
+let configure_cs com =
+	let base_exception = find_class com (["cs";"system"], "Exception") in
+	let base_exception_t = TInst(base_exception, []) in
+
+	let hx_exception = find_class com (["cs";"internal";"_Exceptions"], "HaxeException") in
+	let hx_exception_t = TInst(hx_exception, []) in
+
+	let exc_cl = find_class com (["cs";"internal"],"Exceptions") in
+
+	let rec is_exception t =
+		match follow t with
+		| TInst(cl,_) ->
+			if cl == base_exception then
+				true
+			else
+				(match cl.cl_super with | None -> false | Some (cl,arg) -> is_exception (TInst(cl,arg)))
+		| _ -> false
+	in
+
+	let v_rethrow = alloc_unbound_var "__rethrow__" t_dynamic null_pos in
+	let should_wrap t =
+		not (is_exception t)
+	in
+	let wrap_throw expr =
+		match expr.eexpr with
+		| TLocal { v_name = "__rethrow__" } ->
+			make_throw expr expr.epos
+		| _ ->
+			let e_hxexception = make_static_this hx_exception expr.epos in
+			let e_wrap = fcall e_hxexception "wrap" [expr] base_exception_t expr.epos in
+			make_throw e_wrap expr.epos
+	in
+	let unwrap_expr local_to_unwrap = Codegen.field (mk_cast local_to_unwrap hx_exception_t local_to_unwrap.epos) "obj" t_dynamic local_to_unwrap.epos in
+	let rethrow_expr rethrow = make_throw (make_local v_rethrow rethrow.epos) rethrow.epos in
+	let catch_map v e =
+		let e_exc = make_static_this exc_cl e.epos in
+		let e_field = Codegen.field e_exc "exception" base_exception_t e.epos in
+		let e_setstack = binop OpAssign e_field (make_local v e.epos) v.v_type e.epos in
+		Type.concat e_setstack e
+	in
+	let std_cl = find_class com ([],"Std") in
+	let gen_typecheck e t pos =
+		let std = make_static_this std_cl pos in
+		let e_type = make_typeexpr (module_type_of_type t) pos in
+		fcall std "is" [e; e_type] com.basic.tbool pos
+	in
+	init com should_wrap wrap_throw unwrap_expr rethrow_expr base_exception_t hx_exception_t catch_map gen_typecheck
+
+let configure_java com =
+	let base_exception = find_class com (["java"; "lang"], "Throwable") in
+	let base_exception_t = TInst(base_exception, []) in
+
+	let hx_exception = find_class com (["java";"internal";"_Exceptions"], "HaxeException") in
+	let hx_exception_t = TInst(hx_exception, []) in
 
 
-let configure gen should_wrap wrap_throw unwrap_expr rethrow_expr catchall_type wrapper_type catch_map =
+	let exc_cl = find_class com (["java";"internal"],"Exceptions") in
+
+	let rec is_exception t =
+		match follow t with
+		| TInst(cl,_) ->
+			if cl == base_exception then
+				true
+			else
+				(match cl.cl_super with None -> false | Some (cl,arg) -> is_exception (TInst(cl,arg)))
+		| _ -> false
+	in
+
+	let should_wrap t = not (is_exception t) in
+	let wrap_throw expr =
+		let e_hxexception = make_static_this hx_exception expr.epos in
+		let e_wrap = fcall e_hxexception "wrap" [expr] base_exception_t expr.epos in
+		make_throw e_wrap expr.epos
+	in
+	let unwrap_expr local_to_unwrap = Codegen.field (mk_cast local_to_unwrap hx_exception_t local_to_unwrap.epos) "obj" t_dynamic local_to_unwrap.epos in
+	let rethrow_expr exc = { exc with eexpr = TThrow exc } in
+	let catch_map v e =
+		let exc = make_static_this exc_cl e.epos in
+		let e_setstack = fcall exc "setException" [make_local v e.epos] com.basic.tvoid e.epos in
+		Type.concat e_setstack e;
+	in
+	let std_cl = find_class com ([],"Std") in
 	let gen_typecheck e t pos =
 	let gen_typecheck e t pos =
-		let std_cl = get_cl (get_type gen ([],"Std")) in
-		let std_is = mk_static_field_access_infer std_cl "is" pos [] in
-		mk (TCall (std_is, [e; mk_mt_access (t_to_mt t) pos])) gen.gcon.basic.tbool pos
+		let std = make_static_this std_cl pos in
+		let e_type = make_typeexpr (module_type_of_type t) pos in
+		fcall std "is" [e; e_type] com.basic.tbool pos
 	in
 	in
-	let run = init gen.gcon should_wrap wrap_throw unwrap_expr rethrow_expr catchall_type wrapper_type catch_map gen_typecheck in
-	gen.gsyntax_filters#add name (PCustom priority) run
+	init com should_wrap wrap_throw unwrap_expr rethrow_expr base_exception_t hx_exception_t catch_map gen_typecheck

+ 3 - 42
src/generators/gencs.ml

@@ -152,7 +152,7 @@ let in_runtime_class gen =
 module CSharpSpecificESynf =
 module CSharpSpecificESynf =
 struct
 struct
 	let name = "csharp_specific_e"
 	let name = "csharp_specific_e"
-	let priority = solve_deps name [DBefore ExpressionUnwrap.priority; DBefore ClassInstance.priority; DAfter TryCatchWrapper.priority]
+	let priority = solve_deps name [DBefore ExpressionUnwrap.priority; DBefore ClassInstance.priority]
 
 
 	let get_cl_from_t t =
 	let get_cl_from_t t =
 		match follow t with
 		match follow t with
@@ -1449,8 +1449,6 @@ let generate con =
 						write w "*(";
 						write w "*(";
 						expr_s w e;
 						expr_s w e;
 						write w ")"
 						write w ")"
-					| TCall ({ eexpr = TLocal( { v_name = "__rethrow__" } ) }, _) ->
-						write w "throw"
 					(* operator overloading handling *)
 					(* operator overloading handling *)
 					| TCall({ eexpr = TField(ef, FInstance(cl,_,{ cf_name = "__get" })) }, [idx]) when not (is_hxgen (TClassDecl cl)) ->
 					| TCall({ eexpr = TField(ef, FInstance(cl,_,{ cf_name = "__get" })) }, [idx]) when not (is_hxgen (TClassDecl cl)) ->
 						expr_s w { e with eexpr = TArray(ef, idx) }
 						expr_s w { e with eexpr = TArray(ef, idx) }
@@ -1631,6 +1629,8 @@ let generate con =
 						if is_some eopt then (write w " "; expr_s w (get eopt))
 						if is_some eopt then (write w " "; expr_s w (get eopt))
 					| TBreak -> write w "break"
 					| TBreak -> write w "break"
 					| TContinue -> write w "continue"
 					| TContinue -> write w "continue"
+					| TThrow { eexpr = TLocal { v_name = "__rethrow__" } } ->
+						write w "throw"
 					| TThrow e ->
 					| TThrow e ->
 						write w "throw ";
 						write w "throw ";
 						expr_s w e
 						expr_s w e
@@ -3045,45 +3045,6 @@ let generate con =
 
 
 		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);
 
 
-		begin
-			let base_exception = get_cl (get_type gen (["System"], "Exception")) in
-			let base_exception_t = TInst(base_exception, []) in
-
-			let hx_exception = get_cl (get_type gen (["haxe";"lang"], "HaxeException")) in
-			let hx_exception_t = TInst(hx_exception, []) in
-
-			let exc_cl = get_cl (get_type gen (["haxe";"lang"],"Exceptions")) in
-
-			let rec is_exception t =
-				match follow t with
-					| TInst(cl,_) ->
-						if cl == base_exception then
-							true
-						else
-							(match cl.cl_super with | None -> false | Some (cl,arg) -> is_exception (TInst(cl,arg)))
-					| _ -> false
-			in
-
-			let v_rethrow = alloc_var "__rethrow__" t_dynamic in
-			TryCatchWrapper.configure gen
-				(fun t -> not (is_exception (real_type t)))
-				(fun throwexpr expr ->
-					let e_hxexception = ExprBuilder.make_static_this hx_exception expr.epos in
-					let e_wrap = fcall e_hxexception "wrap" [expr] hx_exception_t expr.epos in
-					mk (TThrow e_wrap) basic.tvoid expr.epos
-				)
-				(fun local_to_unwrap -> Codegen.field (mk_cast hx_exception_t local_to_unwrap) "obj" t_dynamic local_to_unwrap.epos)
-				(fun rethrow -> mk (TCall ((mk_local v_rethrow rethrow.epos),[rethrow])) basic.tvoid rethrow.epos)
-				base_exception_t
-				hx_exception_t
-				(fun v e ->
-					let e_exc = ExprBuilder.make_static_this exc_cl e.epos in
-					let e_field = Codegen.field e_exc "exception" base_exception_t e.epos in
-					let e_setstack = binop OpAssign e_field (mk_local v e.epos) v.v_type e.epos in
-					Type.concat e_setstack e;
-				)
-		end;
-
 		ClassInstance.configure gen;
 		ClassInstance.configure gen;
 
 
 		CastDetect.configure gen (Some empty_ctor_type) (not erase_generics) ~overloads_cast_to_base:true;
 		CastDetect.configure gen (Some empty_ctor_type) (not erase_generics) ~overloads_cast_to_base:true;

+ 1 - 38
src/generators/genjava.ml

@@ -166,7 +166,7 @@ let is_cl t = match follow t with
 module JavaSpecificESynf =
 module JavaSpecificESynf =
 struct
 struct
 	let name = "java_specific_e"
 	let name = "java_specific_e"
-	let priority = solve_deps name [ DBefore ExpressionUnwrap.priority; DBefore ClassInstance.priority; DAfter CastDetect.priority; DAfter TryCatchWrapper.priority ]
+	let priority = solve_deps name [ DBefore ExpressionUnwrap.priority; DBefore ClassInstance.priority; DAfter CastDetect.priority]
 
 
 	let get_cl_from_t t =
 	let get_cl_from_t t =
 		match follow t with
 		match follow t with
@@ -2350,43 +2350,6 @@ let generate con =
 	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);
 
 
-	begin
-		let base_exception = get_cl (get_type gen (["java"; "lang"], "Throwable")) in
-		let base_exception_t = TInst(base_exception, []) in
-
-		let hx_exception = get_cl (get_type gen (["haxe";"lang"], "HaxeException")) in
-		let hx_exception_t = TInst(hx_exception, []) in
-
-		let exc_cl = get_cl (get_type gen (["haxe";"lang"],"Exceptions")) in
-
-		let rec is_exception t =
-			match follow t with
-				| TInst(cl,_) ->
-					if cl == base_exception then
-						true
-					else
-						(match cl.cl_super with | None -> false | Some (cl,arg) -> is_exception (TInst(cl,arg)))
-				| _ -> false
-		in
-
-		TryCatchWrapper.configure gen
-			(fun t -> not (is_exception (real_type t)))
-			(fun throwexpr expr ->
-				let e_hxexception = ExprBuilder.make_static_this hx_exception expr.epos in
-				let e_wrap = fcall e_hxexception "wrap" [expr] hx_exception_t expr.epos in
-				mk (TThrow e_wrap) basic.tvoid expr.epos
-			)
-			(fun local_to_unwrap -> Codegen.field (mk_cast hx_exception_t local_to_unwrap) "obj" t_dynamic local_to_unwrap.epos)
-			(fun exc -> { exc with eexpr = TThrow exc })
-			base_exception_t
-			hx_exception_t
-			(fun v e ->
-				let e_field = mk_static_field_access_infer exc_cl "setException" e.epos [] in
-				let e_setstack = mk (TCall (e_field,[mk_local v e.epos])) basic.tvoid e.epos in
-				Type.concat e_setstack e;
-			)
-	end;
-
 	ClassInstance.configure gen;
 	ClassInstance.configure gen;
 
 
 	CastDetect.configure gen (Some empty_ctor_type) false;
 	CastDetect.configure gen (Some empty_ctor_type) false;

+ 11 - 0
src/optimization/filters.ml

@@ -1130,6 +1130,17 @@ let run com tctx main =
 		Optimizer.reduce_expression tctx;
 		Optimizer.reduce_expression tctx;
 		captured_vars com;
 		captured_vars com;
 	] in
 	] in
+	let filters = match com.platform with
+	| Cs ->
+		filters @ [
+			TryCatchWrapper.configure_cs com
+		]
+	| Java ->
+		filters @ [
+			TryCatchWrapper.configure_java com
+		]
+	| _ -> filters
+	in
 	List.iter (run_expression_filters tctx filters) new_types;
 	List.iter (run_expression_filters tctx filters) new_types;
 	(* PASS 1.5: pre-analyzer type filters *)
 	(* PASS 1.5: pre-analyzer type filters *)
 	List.iter (fun t ->
 	List.iter (fun t ->

+ 1 - 1
std/cs/Lib.hx

@@ -178,7 +178,7 @@ class Lib
 	**/
 	**/
 	@:extern inline public static function rethrow(e:Dynamic):Void
 	@:extern inline public static function rethrow(e:Dynamic):Void
 	{
 	{
-		untyped __rethrow__();
+		throw untyped __rethrow__;
 	}
 	}
 
 
 	/**
 	/**