فهرست منبع

RenameVars cleanup (#11176)

* [timers] fix

* encapsulate overlaps

* change random things because I don't know how to fix the actual issue yet

* cache name lookups

* rework filter timers

* apparently this was important somehow

* lose some more tctx

* I don't think the JVM target cares about local names
Simon Krajewski 2 سال پیش
والد
کامیت
8aa9cc4b5f

+ 1 - 1
src/compiler/compiler.ml

@@ -301,7 +301,7 @@ let finalize_typing ctx tctx =
 let filter ctx tctx =
 	let t = Timer.timer ["filters"] in
 	DeprecationCheck.run ctx.com;
-	Filters.run ctx.com tctx ctx.com.main;
+	Filters.run tctx ctx.com.main;
 	t()
 
 let call_light_init_macro com path =

+ 7 - 4
src/context/typecore.ml

@@ -369,13 +369,16 @@ let add_local_with_origin ctx origin n t p =
 	check_local_variable_name ctx n origin p;
 	add_local ctx (VUser origin) n t p
 
-let gen_local_prefix = "`"
+let gen_local_prefix = "_g"
 
 let gen_local ctx t p =
-	add_local ctx VGenerated "`" t p
+	add_local ctx VGenerated gen_local_prefix t p
 
-let is_gen_local v =
-	String.unsafe_get v.v_name 0 = String.unsafe_get gen_local_prefix 0
+let is_gen_local v = match v.v_kind with
+	| VGenerated ->
+		true
+	| _ ->
+		false
 
 let delay ctx p f =
 	let rec loop = function

+ 4 - 2
src/core/timer.ml

@@ -92,6 +92,8 @@ let close = close (get_time())
 
 (* Printing *)
 
+let timer_threshold = 0.01
+
 type timer_node = {
 	name : string;
 	path : string;
@@ -168,7 +170,7 @@ let build_times_tree () =
 		) node.children;
 		node.children <- List.sort (fun node1 node2 -> compare node2.time node1.time) node.children;
 		if node.num_calls > !max_calls then max_calls := node.num_calls;
-		if node.time > 0.0009 && l > !max_name then max_name := l;
+		if node.time >= timer_threshold && l > !max_name then max_name := l;
 	in
 	loop 0 root;
 	!max_name,!max_calls,root
@@ -180,7 +182,7 @@ let report_times print =
 	let sep = String.make (max_name + max_calls + 27) '-' in
 	print sep;
 	let print_time name node =
-		if node.time > 0.0009 then
+		if node.time >= timer_threshold then
 			print (Printf.sprintf "%-*s | %7.3f | %3.0f | %3.0f | %*i | %s" max_name name node.time (node.time *. 100. /. root.time) (node.time *. 100. /. node.parent.time) max_calls node.num_calls node.info)
 	in
 	let rec loop depth node =

+ 4 - 4
src/filters/exceptions.ml

@@ -217,7 +217,7 @@ class catch ctx catch_local catch_pos =
 			let v =
 				match hx_exception_var with
 				| None ->
-					let v = alloc_var VGenerated "`" ctx.haxe_exception_type p in
+					let v = alloc_var VGenerated gen_local_prefix ctx.haxe_exception_type p in
 					hx_exception_var <- Some v;
 					v
 				| Some v -> v
@@ -228,7 +228,7 @@ class catch ctx catch_local catch_pos =
 			let v =
 				match unwrapped_var with
 				| None ->
-					let v = alloc_var VGenerated "`" t_dynamic p in
+					let v = alloc_var VGenerated gen_local_prefix t_dynamic p in
 					unwrapped_var <- Some v;
 					(* unwrapped_local <- Some e; *)
 					v
@@ -262,7 +262,7 @@ let catches_to_ifs ctx catches t p =
 	match catches with
 	| [] -> []
 	| ((first_v, first_body) :: _) as rest ->
-		let catch_var = alloc_var VGenerated "`" ctx.wildcard_catch_type first_v.v_pos in
+		let catch_var = alloc_var VGenerated gen_local_prefix ctx.wildcard_catch_type first_v.v_pos in
 		add_var_flag catch_var VCaught;
 		let catch_local = mk (TLocal catch_var) catch_var.v_type catch_var.v_pos in
 		let body =
@@ -396,7 +396,7 @@ let catches_as_value_exception ctx non_value_exception_catches value_exception_c
 			| Some (catch_var, _) ->
 				catch_var
 			| None ->
-				let catch_var = alloc_var VGenerated "`" ctx.value_exception_type first_v.v_pos in
+				let catch_var = alloc_var VGenerated gen_local_prefix ctx.value_exception_type first_v.v_pos in
 				add_var_flag catch_var VCaught;
 				catch_var
 		in

+ 9 - 0
src/filters/filterContext.ml

@@ -0,0 +1,9 @@
+let with_timer detail_times label identifier f =
+	let label = match detail_times,identifier with
+		| 0,_ -> ["filters"]
+		| 1,_ -> "filters" :: label :: []
+		| _,Some identifier -> "filters" :: label :: identifier :: []
+		| _ -> ["filters"]
+	in
+	let timer = Timer.timer label in
+	Std.finally timer f ()

+ 73 - 75
src/filters/filters.ml

@@ -320,16 +320,16 @@ let check_unification ctx e t =
 	end;
 	e
 
-let rec fix_return_dynamic_from_void_function ctx return_is_void e =
+let rec fix_return_dynamic_from_void_function return_is_void e =
 	match e.eexpr with
 	| TFunction fn ->
 		let is_void = ExtType.is_void (follow fn.tf_type) in
-		let body = fix_return_dynamic_from_void_function ctx is_void fn.tf_expr in
+		let body = fix_return_dynamic_from_void_function is_void fn.tf_expr in
 		{ e with eexpr = TFunction { fn with tf_expr = body } }
 	| TReturn (Some return_expr) when return_is_void && t_dynamic == follow return_expr.etype ->
 		let return_pos = { e.epos with pmax = return_expr.epos.pmin - 1 } in
 		let exprs = [
-			fix_return_dynamic_from_void_function ctx return_is_void return_expr;
+			fix_return_dynamic_from_void_function return_is_void return_expr;
 			{ e with eexpr = TReturn None; epos = return_pos };
 		] in
 		{ e with
@@ -338,7 +338,7 @@ let rec fix_return_dynamic_from_void_function ctx return_is_void e =
 				mk (TBlock exprs) e.etype e.epos
 			);
 		}
-	| _ -> Type.map_expr (fix_return_dynamic_from_void_function ctx return_is_void) e
+	| _ -> Type.map_expr (fix_return_dynamic_from_void_function return_is_void) e
 
 let check_abstract_as_value e =
 	let rec loop e =
@@ -385,10 +385,10 @@ let remove_extern_fields com t = match t with
 (* PASS 3 begin *)
 
 (* Checks if a private class' path clashes with another path *)
-let check_private_path ctx t = match t with
+let check_private_path com t = match t with
 	| TClassDecl c when c.cl_private ->
 		let rpath = (fst c.cl_module.m_path,"_" ^ snd c.cl_module.m_path) in
-		if ctx.com.type_to_module#mem rpath then raise_typing_error ("This private class name will clash with " ^ s_type_path rpath) c.cl_pos;
+		if com.type_to_module#mem rpath then raise_typing_error ("This private class name will clash with " ^ s_type_path rpath) c.cl_pos;
 	| _ ->
 		()
 
@@ -653,10 +653,10 @@ let commit_features com t =
 		Common.add_feature com k;
 	) m.m_extra.m_features
 
-let check_reserved_type_paths ctx t =
+let check_reserved_type_paths com t =
 	let check path pos =
-		if List.mem path ctx.com.config.pf_reserved_type_paths then begin
-			warning ctx WReservedTypePath ("Type path " ^ (s_type_path path) ^ " is reserved on this target") pos
+		if List.mem path com.config.pf_reserved_type_paths then begin
+			com.warning WReservedTypePath [] ("Type path " ^ (s_type_path path) ^ " is reserved on this target") pos
 		end
 	in
 	match t with
@@ -671,7 +671,8 @@ let is_cached com t =
 	m.m_processed <> 0 && m.m_processed < com.compilation_step
 
 let apply_filters_once ctx filters t =
-	if not (is_cached ctx.com t) then run_expression_filters None ctx filters t
+	let detail_times = (try int_of_string (Common.defined_value_safe ctx.com ~default:"0" Define.FilterTimes) with _ -> 0) in
+	if not (is_cached ctx.com t) then run_expression_filters ctx detail_times filters t
 
 let iter_expressions fl mt =
 	match mt with
@@ -686,13 +687,6 @@ let iter_expressions fl mt =
 	| _ ->
 		()
 
-let filter_timer detailed s =
-	Timer.timer (if detailed then "filters" :: s else ["filters"])
-
-let timer_label detailed s =
-	if detailed then Some ("filters" :: s)
-	else None
-
 module ForRemap = struct
 	let apply ctx e =
 		let rec loop e = match e.eexpr with
@@ -713,43 +707,45 @@ module ForRemap = struct
 		loop e
 end
 
+open FilterContext
+
 let destruction tctx detail_times main locals =
 	let com = tctx.com in
-	let t = filter_timer detail_times ["type 2"] in
-	(* PASS 2: type filters pre-DCE *)
-	List.iter (fun t ->
-		remove_generic_base t;
-		remove_extern_fields com t;
-		(* check @:remove metadata before DCE so it is ignored there (issue #2923) *)
-		check_remove_metadata t;
-	) com.types;
-	t();
+	with_timer detail_times "type 2" None (fun () ->
+		(* PASS 2: type filters pre-DCE *)
+		List.iter (fun t ->
+			remove_generic_base t;
+			remove_extern_fields com t;
+			(* check @:remove metadata before DCE so it is ignored there (issue #2923) *)
+			check_remove_metadata t;
+		) com.types;
+	);
 	com.stage <- CDceStart;
-	let t = filter_timer detail_times ["dce"] in
-	(* DCE *)
-	let dce_mode = try Common.defined_value com Define.Dce with _ -> "no" in
-	let dce_mode = match dce_mode with
-		| "full" -> if Common.defined com Define.Interp then Dce.DceNo else DceFull
-		| "std" -> DceStd
-		| "no" -> DceNo
-		| _ -> failwith ("Unknown DCE mode " ^ dce_mode)
-	in
-	Dce.run com main dce_mode;
-	t();
+	with_timer detail_times "dce" None (fun () ->
+		(* DCE *)
+		let dce_mode = try Common.defined_value com Define.Dce with _ -> "no" in
+		let dce_mode = match dce_mode with
+			| "full" -> if Common.defined com Define.Interp then Dce.DceNo else DceFull
+			| "std" -> DceStd
+			| "no" -> DceNo
+			| _ -> failwith ("Unknown DCE mode " ^ dce_mode)
+		in
+		Dce.run com main dce_mode;
+	);
 	com.stage <- CDceDone;
 	(* PASS 3: type filters post-DCE *)
 	List.iter
 		(run_expression_filters
 			~ignore_processed_status:true
-			(timer_label detail_times [])
 			tctx
+			detail_times
 			(* This has to run after DCE, or otherwise its condition always holds. *)
 			["insert_save_stacks",Exceptions.insert_save_stacks tctx]
 		)
 		com.types;
 	let type_filters = [
 		Exceptions.patch_constructors tctx; (* TODO: I don't believe this should load_instance anything at this point... *)
-		check_private_path tctx;
+		check_private_path com;
 		apply_native_paths;
 		add_rtti com;
 		(match com.platform with | Java | Cs -> (fun _ -> ()) | _ -> (fun mt -> add_field_inits tctx.curclass.cl_path locals com mt));
@@ -757,23 +753,23 @@ let destruction tctx detail_times main locals =
 		check_void_field;
 		(match com.platform with | Cpp -> promote_first_interface_to_super | _ -> (fun _ -> ()));
 		commit_features com;
-		(if com.config.pf_reserved_type_paths <> [] then check_reserved_type_paths tctx else (fun _ -> ()));
+		(if com.config.pf_reserved_type_paths <> [] then check_reserved_type_paths com else (fun _ -> ()));
 	] in
 	let type_filters = match com.platform with
 		| Cs -> type_filters @ [ fun t -> InterfaceProps.run t ]
 		| _ -> type_filters
 	in
-	let t = filter_timer detail_times ["type 3"] in
-	List.iter (fun t ->
-		begin match t with
-		| TClassDecl c ->
-			tctx.curclass <- c
-		| _ ->
-			()
-		end;
-		List.iter (fun f -> f t) type_filters
-	) com.types;
-	t();
+	with_timer detail_times "type 3" None (fun () ->
+		List.iter (fun t ->
+			begin match t with
+			| TClassDecl c ->
+				tctx.curclass <- c
+			| _ ->
+				()
+			end;
+			List.iter (fun f -> f t) type_filters
+		) com.types;
+	);
 	com.callbacks#run com.callbacks#get_after_filters;
 	com.stage <- CFilteringDone
 
@@ -828,10 +824,10 @@ let update_cache_dependencies com t =
 			()
 
 (* Saves a class state so it can be restored later, e.g. after DCE or native path rewrite *)
-let save_class_state ctx t =
+let save_class_state com t =
 	(* Update m_processed here. This means that nothing should add a dependency afterwards because
 	   then the module is immediately considered uncached again *)
-	(t_infos t).mt_module.m_extra.m_processed <- ctx.com.compilation_step;
+	(t_infos t).mt_module.m_extra.m_processed <- com.compilation_step;
 	match t with
 	| TClassDecl c ->
 		let vars = ref [] in
@@ -915,8 +911,9 @@ let save_class_state ctx t =
 			a.a_meta <- List.filter (fun (m,_,_) -> m <> Meta.ValueUsed) a.a_meta
 		)
 
-let run com tctx main =
-	let detail_times = Common.defined com DefineList.FilterTimes in
+let run tctx main =
+	let com = tctx.com in
+	let detail_times = (try int_of_string (Common.defined_value_safe com ~default:"0" Define.FilterTimes) with _ -> 0) in
 	let new_types = List.filter (fun t ->
 		let cached = is_cached com t in
 		begin match t with
@@ -955,10 +952,10 @@ let run com tctx main =
 		"ForRemap",ForRemap.apply tctx;
 		"handle_abstract_casts",AbstractCast.handle_abstract_casts tctx;
 	] in
-	List.iter (run_expression_filters (timer_label detail_times ["expr 0"]) tctx filters) new_types;
+	List.iter (run_expression_filters tctx detail_times filters) new_types;
 	let filters = [
 		"local_statics",LocalStatic.run tctx;
-		"fix_return_dynamic_from_void_function",fix_return_dynamic_from_void_function tctx true;
+		"fix_return_dynamic_from_void_function",fix_return_dynamic_from_void_function true;
 		"check_local_vars_init",check_local_vars_init tctx;
 		"check_abstract_as_value",check_abstract_as_value;
 		"Tre",if defined com Define.AnalyzerOptimize then Tre.run tctx else (fun e -> e);
@@ -977,13 +974,13 @@ let run com tctx main =
 			filters
 		| _ -> filters
 	in
-	List.iter (run_expression_filters (timer_label detail_times ["expr 1"]) tctx filters) new_types;
+	List.iter (run_expression_filters tctx detail_times filters) new_types;
 	(* PASS 1.5: pre-analyzer type filters *)
 	let filters =
 		match com.platform with
 		| Cs ->
 			[
-				check_cs_events tctx.com;
+				check_cs_events com;
 				DefaultArguments.run com;
 			]
 		| Java ->
@@ -993,9 +990,9 @@ let run com tctx main =
 		| _ ->
 			[]
 	in
-	let t = filter_timer detail_times ["type 1"] in
-	List.iter (fun f -> List.iter f new_types) filters;
-	t();
+	with_timer detail_times "type 1" None (fun () ->
+		List.iter (fun f -> List.iter f new_types) filters;
+	);
 	com.stage <- CAnalyzerStart;
 	if com.platform <> Cross then Analyzer.Run.run_on_types com new_types;
 	com.stage <- CAnalyzerDone;
@@ -1005,22 +1002,23 @@ let run com tctx main =
 		"add_final_return",if com.config.pf_add_final_return then add_final_return else (fun e -> e);
 		"RenameVars",(match com.platform with
 		| Eval -> (fun e -> e)
+		| Java when defined com Jvm -> (fun e -> e)
 		| _ -> (fun e -> RenameVars.run tctx.curclass.cl_path locals e));
 		"mark_switch_break_loops",mark_switch_break_loops;
 	] in
-	List.iter (run_expression_filters (timer_label detail_times ["expr 2"]) tctx filters) new_types;
-	let t = filter_timer detail_times ["callbacks"] in
-	com.callbacks#run com.callbacks#get_before_save; (* macros onGenerate etc. *)
-	t();
+	List.iter (run_expression_filters tctx detail_times filters) new_types;
+	with_timer detail_times "callbacks" None (fun () ->
+		com.callbacks#run com.callbacks#get_before_save;
+	);
 	com.stage <- CSaveStart;
-	let t = filter_timer detail_times ["save state"] in
-	List.iter (fun mt ->
-		update_cache_dependencies com mt;
-		save_class_state tctx mt
-	) new_types;
-	t();
+	with_timer detail_times "save state" None (fun () ->
+		List.iter (fun mt ->
+			update_cache_dependencies com mt;
+			save_class_state com mt
+		) new_types;
+	);
 	com.stage <- CSaveDone;
-	let t = filter_timer detail_times ["callbacks"] in
-	com.callbacks#run com.callbacks#get_after_save; (* macros onGenerate etc. *)
-	t();
+	with_timer detail_times "callbacks" None (fun () ->
+		com.callbacks#run com.callbacks#get_after_save;
+	);
 	destruction tctx detail_times main locals

+ 12 - 16
src/filters/filtersCommon.ml

@@ -16,6 +16,7 @@
 	along with this program; if not, write to the Free Software
 	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *)
+open Globals
 open Type
 open Typecore
 
@@ -48,19 +49,12 @@ let is_overridden cls field =
 	in
 	List.exists (fun d -> loop_inheritance d) cls.cl_descendants
 
-let run_expression_filters ?(ignore_processed_status=false) time_details ctx filters t =
-	let run e =
-		List.fold_left
-			(fun e (filter_name,f) ->
-				match time_details with
-				| Some timer_label ->
-					let t = Timer.timer (timer_label @ [filter_name]) in
-					let e = f e in
-					t();
-					e
-				| None -> f e
-			)
-			e filters
+let run_expression_filters ?(ignore_processed_status=false) ctx detail_times filters t =
+	let com = ctx.com in
+	let run identifier e =
+		List.fold_left (fun e (filter_name,f) ->
+			FilterContext.with_timer detail_times filter_name identifier (fun () -> f e)
+		) e filters
 	in
 	match t with
 	| TClassDecl c when is_removable_class c -> ()
@@ -71,8 +65,9 @@ let run_expression_filters ?(ignore_processed_status=false) time_details ctx fil
 			if ignore_processed_status || not (has_class_field_flag f CfPostProcessed) then begin
 				ctx.curfield <- f;
 				(match f.cf_expr with
-				| Some e when not (is_removable_field ctx.com f) ->
-					f.cf_expr <- Some (rec_stack_loop AbstractCast.cast_stack f run e);
+				| Some e when not (is_removable_field com f) ->
+					let identifier = Printf.sprintf "%s.%s" (s_type_path c.cl_path) f.cf_name in
+					f.cf_expr <- Some (rec_stack_loop AbstractCast.cast_stack f (run (Some identifier)) e);
 				| _ -> ());
 			end;
 			List.iter process_field f.cf_overloads
@@ -85,7 +80,8 @@ let run_expression_filters ?(ignore_processed_status=false) time_details ctx fil
 		(match c.cl_init with
 		| None -> ()
 		| Some e ->
-			c.cl_init <- Some (run e));
+			let identifier = Printf.sprintf "%s.__init__" (s_type_path c.cl_path) in
+			c.cl_init <- Some (run (Some identifier) e));
 	| TEnumDecl _ -> ()
 	| TTypeDecl _ -> ()
 	| TAbstractDecl _ -> ()

+ 88 - 45
src/filters/renameVars.ml

@@ -80,6 +80,55 @@ let init com =
 	) com.config.pf_scoping.vs_flags;
 	ri
 
+module Overlaps = struct
+	type t = {
+		mutable ov_vars : tvar IntMap.t;
+		mutable ov_name_cache : bool StringMap.t option;
+	}
+
+	let create () = {
+		ov_vars = IntMap.empty;
+		ov_name_cache = None;
+	}
+
+	let copy ov = {
+		ov_vars = ov.ov_vars;
+		ov_name_cache = ov.ov_name_cache;
+	}
+
+	let add id v ov =
+		ov.ov_vars <- IntMap.add id v ov.ov_vars;
+		ov.ov_name_cache <- None
+
+	let get_cache ov = match ov.ov_name_cache with
+		| Some cache ->
+			cache
+		| None ->
+			let cache = IntMap.fold (fun _ v acc -> StringMap.add v.v_name true acc) ov.ov_vars StringMap.empty in
+			ov.ov_name_cache <- Some cache;
+			cache
+
+	let has_name name ov =
+		StringMap.mem name (get_cache ov)
+
+	let iter f ov =
+		IntMap.iter f ov.ov_vars
+
+	let mem i ov =
+		IntMap.mem i ov.ov_vars
+
+	let exists f ov =
+		IntMap.exists f ov.ov_vars
+
+	let reset ov =
+		ov.ov_vars <- IntMap.empty;
+		ov.ov_name_cache <- None
+
+	let is_empty ov =
+		IntMap.is_empty ov.ov_vars
+
+end
+
 type scope = {
 	(** Parent scope *)
 	parent : scope option;
@@ -97,11 +146,11 @@ type scope = {
 		```
 		in this example `b` overlaps with `a`.
 	*)
-	mutable own_vars : (tvar * (tvar IntMap.t ref)) list;
+	mutable own_vars : (tvar * Overlaps.t) list;
 	(** Variables declared outside of this scope, but used inside of it *)
-	mutable foreign_vars : tvar IntMap.t;
+	mutable foreign_vars : Overlaps.t;
 	(** List of variables used in current loop *)
-	loop_vars : tvar IntMap.t ref;
+	loop_vars : Overlaps.t;
 	(** Current loops depth *)
 	mutable loop_count : int;
 }
@@ -134,8 +183,8 @@ let create_scope parent =
 		parent = parent;
 		children = [];
 		own_vars = [];
-		foreign_vars = IntMap.empty;
-		loop_vars = ref IntMap.empty;
+		foreign_vars = Overlaps.create();
+		loop_vars = Overlaps.create();
 		loop_count = 0;
 	} in
 	Option.may (fun p -> p.children <- scope :: p.children) parent;
@@ -146,24 +195,23 @@ let create_scope parent =
 *)
 let declare_var rc scope v =
 	let overlaps =
-		if not rc.rc_hoisting || IntMap.is_empty scope.foreign_vars then
-			if scope.loop_count = 0 then IntMap.empty
-			else !(scope.loop_vars)
+		if not rc.rc_hoisting || Overlaps.is_empty scope.foreign_vars then
+			if scope.loop_count = 0 then Overlaps.create ()
+			else Overlaps.copy scope.loop_vars
 		else
 			if scope.loop_count = 0 then
-				scope.foreign_vars
+				Overlaps.copy scope.foreign_vars
 			else begin
-				let overlaps = ref !(scope.loop_vars) in
-				IntMap.iter (fun i o ->
-					if not (IntMap.mem i !overlaps) then
-						overlaps := IntMap.add i o !overlaps
+				let overlaps = Overlaps.copy scope.loop_vars in
+				Overlaps.iter (fun i o ->
+					Overlaps.add i o overlaps
 				) scope.foreign_vars;
-				!overlaps
+				overlaps
 			end
 	in
-	scope.own_vars <- (v, ref overlaps) :: scope.own_vars;
+	scope.own_vars <- (v, overlaps) :: scope.own_vars;
 	if scope.loop_count > 0 then
-		scope.loop_vars := IntMap.add v.v_id v !(scope.loop_vars)
+		Overlaps.add v.v_id v scope.loop_vars
 
 (**
 	Invoked for each `TLocal v` texr_expr
@@ -172,21 +220,25 @@ let rec use_var rc scope v =
 	let rec loop declarations =
 		match declarations with
 		| [] ->
-			if (rc.rc_no_shadowing || rc.rc_hoisting) && not (IntMap.mem v.v_id scope.foreign_vars) then
-				scope.foreign_vars <- IntMap.add v.v_id v scope.foreign_vars;
+			if (rc.rc_no_shadowing || rc.rc_hoisting) then
+				Overlaps.add v.v_id v scope.foreign_vars;
 			(match scope.parent with
 			| Some parent -> use_var rc parent v
 			| None -> raise (Failure "Failed to locate variable declaration")
 			)
-		| (d, _) :: _ when d == v -> ()
+		| (d, _) :: _ when d == v ->
+			()
 		| (d, overlaps) :: rest ->
-			if not (IntMap.mem v.v_id !overlaps) then
-				overlaps := IntMap.add v.v_id v !overlaps;
-			loop rest
+			(* If we find a declaration that already knows us, we don't have to keep
+			   looping because we can be sure that we've been here before. *)
+			if not (Overlaps.mem v.v_id overlaps) then begin
+				Overlaps.add v.v_id v overlaps;
+				loop rest
+			end
 	in
 	loop scope.own_vars;
-	if scope.loop_count > 0 && not (IntMap.mem v.v_id !(scope.loop_vars)) then
-		scope.loop_vars := IntMap.add v.v_id v !(scope.loop_vars)
+	if scope.loop_count > 0 then
+		Overlaps.add v.v_id v scope.loop_vars
 
 let collect_loop scope fn =
 	scope.loop_count <- scope.loop_count + 1;
@@ -195,7 +247,7 @@ let collect_loop scope fn =
 	if scope.loop_count < 0 then
 		raise (Failure "Unexpected loop count");
 	if scope.loop_count = 0 then
-		scope.loop_vars := IntMap.empty
+		Overlaps.reset scope.loop_vars
 
 (**
 	Collect all the variables declared and used in `e` expression.
@@ -274,8 +326,6 @@ and collect_ignore_block ?(in_block=false) rc scope e =
 	| TBlock el -> List.iter (collect_vars ~in_block rc scope) el
 	| _ -> collect_vars ~in_block rc scope e
 
-let trailing_numbers = Str.regexp "[0-9]+$"
-
 (**
 	Rename `v` if needed
 *)
@@ -284,22 +334,15 @@ let maybe_rename_var rc reserved (v,overlaps) =
 		v.v_meta <- (Meta.RealPath,[EConst (String(v.v_name,SDoubleQuotes)),null_pos],null_pos) :: v.v_meta;
 		v.v_name <- name
 	in
-	(* chop escape char for all local variables generated *)
-	if is_gen_local v then begin
-		let name = String.sub v.v_name 1 (String.length v.v_name - 1) in
-		commit ("_g" ^ (Str.replace_first trailing_numbers "" name))
-	end;
-	let name = ref v.v_name in
-	let count = ref 0 in
-	let same_name _ o = !name = o.v_name in
-	while (
-		StringMap.mem !name !reserved
-		|| IntMap.exists same_name !overlaps
-	) do
-		incr count;
-		name := v.v_name ^ (string_of_int !count);
-	done;
-	commit !name;
+	let rec loop name count =
+		if StringMap.mem name !reserved || Overlaps.has_name name overlaps then begin
+			let count = count + 1 in
+			loop (v.v_name ^ (string_of_int count)) count
+		end else
+			name
+	in
+	let name = loop v.v_name 0 in
+	commit name;
 	if rc.rc_no_shadowing || (has_var_flag v VCaptured && rc.rc_hoisting) then reserve reserved v.v_name
 
 (**
@@ -307,8 +350,8 @@ let maybe_rename_var rc reserved (v,overlaps) =
 *)
 let rec rename_vars rc scope =
 	let reserved = ref rc.rc_reserved in
-	if (rc.rc_hoisting || rc.rc_no_shadowing) && not (IntMap.is_empty scope.foreign_vars) then
-		IntMap.iter (fun _ v -> reserve reserved v.v_name) scope.foreign_vars;
+	if (rc.rc_hoisting || rc.rc_no_shadowing) && not (Overlaps.is_empty scope.foreign_vars) then
+		Overlaps.iter (fun _ v -> reserve reserved v.v_name) scope.foreign_vars;
 	List.iter (maybe_rename_var rc reserved) (List.rev scope.own_vars);
 	List.iter (rename_vars rc) scope.children
 

+ 2 - 2
src/filters/tre.ml

@@ -6,7 +6,7 @@ let rec collect_new_args_values ctx args declarations values n =
 	match args with
 	| [] -> declarations, values
 	| arg :: rest ->
-		let v = alloc_var VGenerated ("`tmp" ^ (string_of_int n)) arg.etype arg.epos in
+		let v = gen_local ctx arg.etype arg.epos in
 		let decl = { eexpr = TVar (v, Some arg); etype = ctx.t.tvoid; epos = v.v_pos }
 		and value = { arg with eexpr = TLocal v } in
 		collect_new_args_values ctx rest (decl :: declarations) (value :: values) (n + 1)
@@ -51,7 +51,7 @@ let rec redeclare_vars ctx vars declarations replace_list =
 	match vars with
 	| [] -> declarations, replace_list
 	| v :: rest ->
-		let new_v = alloc_var VGenerated ("`" ^ v.v_name) v.v_type v.v_pos in
+		let new_v = alloc_var VGenerated (gen_local_prefix ^ v.v_name) v.v_type v.v_pos in
 		let decl =
 			{
 				eexpr = TVar (new_v, Some { eexpr = TLocal v; etype = v.v_type; epos = v.v_pos; });

+ 0 - 1
src/macro/eval/evalJitContext.ml

@@ -98,7 +98,6 @@ let add_local jit var = match jit.scopes with
 		increase_num_locals jit;
 		let slot = scope.local_offset + i in
 		if jit.ctx.debug.support_debugger then begin
-			if Typecore.is_gen_local var then var.v_name <- "_g" ^ String.sub var.v_name 1 (String.length var.v_name - 1);
 			Hashtbl.replace scope.local_ids var.v_name var.v_id;
 			Hashtbl.replace scope.local_infos i (var_info_of_var var)
 		end;

+ 1 - 3
src/optimization/analyzer.ml

@@ -948,9 +948,7 @@ module Run = struct
 			| _ -> ["analyzer"] (* whatever *)
 		in
 		let timer = Timer.timer name in
-		let r = f() in
-		timer();
-		r
+		Std.finally timer f ()
 
 	let create_analyzer_context com config identifier e =
 		let g = Graph.create e.etype e.epos in

+ 2 - 2
src/typing/calls.ml

@@ -414,12 +414,12 @@ let type_bind ctx (e : texpr) (args,ret) params p =
 				since we'll create a closure for the binding anyway, instead store the instance and
 				call its method inside a bind-generated closure
 			*)
-			let vobj = alloc_var VGenerated "`" eobj.etype eobj.epos in
+			let vobj = alloc_var VGenerated gen_local_prefix eobj.etype eobj.epos in
 			let var_decl = mk (TVar(vobj, Some eobj)) ctx.t.tvoid eobj.epos in
 			let eobj = { eobj with eexpr = TLocal vobj } in
 			{ e with eexpr = TField(eobj, FInstance (cl, tp, cf)) }, var_decl :: var_decls
 		| _ ->
-			let e_var = alloc_var VGenerated "`" e.etype e.epos in
+			let e_var = alloc_var VGenerated gen_local_prefix e.etype e.epos in
 			(mk (TLocal e_var) e.etype e.epos), (mk (TVar(e_var,Some e)) ctx.t.tvoid e.epos) :: var_decls
 	in
 	let call = make_call ctx e ordered_args ret p in

+ 1 - 1
src/typing/typerBase.ml

@@ -158,7 +158,7 @@ let get_this ctx p =
 				let v = if ctx.curfun = FunMemberAbstractLocal then
 					PMap.find "this" ctx.locals
 				else
-					add_local ctx VGenerated "`this" ctx.tthis p
+					add_local ctx VGenerated (Printf.sprintf "%sthis" gen_local_prefix) ctx.tthis p
 				in
 				ctx.vthis <- Some v;
 				v

+ 4 - 4
tests/optimization/src/TestTreGeneration.hx

@@ -5,9 +5,9 @@ class TestTreGeneration {
 		}
 		while(true) {
 			if(Std.random(2) == 0) {
-				var _gtmp = a;
+				var _g = a;
 				a = b + a;
-				b = _gtmp;
+				b = _g;
 				s += "?";
 				continue;
 			}
@@ -59,9 +59,9 @@ class TestTreGeneration {
 			}
 			while(true) {
 				if(Std.random(2) == 0) {
-					var _gtmp = a;
+					var _g = a;
 					a = b + a;
-					b = _gtmp;
+					b = _g;
 					s += "?";
 					continue;
 				}

+ 1 - 1
tests/optimization/src/issues/Issue10188.hx

@@ -12,7 +12,7 @@ enum abstract Value(Int) to Int {
 	}
 }
 
-@:enum abstract ActorStateType(Int) from Int to Int {
+enum abstract ActorStateType(Int) from Int to Int {
     var GoingLeft = 0;
     var GoingRight = 1;
 }