Kaynağa Gözat

Less local variable renaming in compiled code (#9304)

Aleksandr Kuzmenko 5 yıl önce
ebeveyn
işleme
de834cfc89

+ 77 - 15
src/context/common.ml

@@ -94,13 +94,42 @@ type exceptions_config = {
 	ec_base_throw : path;
 }
 
-type nested_function_scoping =
-	(** each TFunction has its own scope in the output **)
-	| Independent
-	(** TFunction nodes are nested in the output **)
-	| Nested
-	(** TFunction nodes are nested in the output and there is var hoisting **)
-	| Hoisted
+type var_scope =
+	| FunctionScope
+	| BlockScope
+
+type var_scoping_flags =
+	(**
+		Variables are hoisted in their scope
+	*)
+	| VarHoisting
+	(**
+		It's not allowed to shadow existing variables in a scope.
+	*)
+	| NoShadowing
+	(**
+		Local vars cannot have the same name as the current top-level package or
+		(if in the root package) current class name
+	*)
+	| ReserveCurrentTopLevelSymbol
+	(**
+		Local vars cannot have a name used for any top-level symbol
+		(packages and classes in the root package)
+	*)
+	| ReserveAllTopLevelSymbols
+	(**
+		Reserve all type-paths converted to "flat path" with `Path.flat_path`
+	*)
+	| ReserveAllTypesFlat
+	(**
+		List of names cannot be taken by local vars
+	*)
+	| ReserveNames of string list
+
+type var_scoping_config = {
+	vs_flags : var_scoping_flags list;
+	vs_scope : var_scope;
+}
 
 type platform_config = {
 	(** has a static type system, with not-nullable basic types (Int/Float/Bool) *)
@@ -131,8 +160,8 @@ type platform_config = {
 	pf_supports_unicode : bool;
 	(** exceptions handling config **)
 	pf_exceptions : exceptions_config;
-	(** the scoping behavior of nested functions **)
-	pf_nested_function_scoping : nested_function_scoping;
+	(** the scoping of local variables *)
+	pf_scoping : var_scoping_config;
 }
 
 class compiler_callbacks = object(self)
@@ -353,7 +382,10 @@ let default_config =
 			ec_wildcard_catch = (["StdTypes"],"Dynamic");
 			ec_base_throw = (["StdTypes"],"Dynamic");
 		};
-		pf_nested_function_scoping = Independent;
+		pf_scoping = {
+			vs_scope = BlockScope;
+			vs_flags = [];
+		}
 	}
 
 let get_config com =
@@ -375,7 +407,13 @@ let get_config com =
 					["haxe"],"Exception";
 				];
 			};
-			pf_nested_function_scoping = Hoisted;
+			pf_scoping = {
+				vs_scope = FunctionScope;
+				vs_flags = [
+					VarHoisting;
+					if defined Define.JsUnflatten then ReserveAllTopLevelSymbols else ReserveAllTypesFlat
+				];
+			}
 		}
 	| Lua ->
 		{
@@ -392,6 +430,9 @@ let get_config com =
 			pf_uses_utf16 = false;
 			pf_supports_threads = true;
 			pf_supports_unicode = false;
+			pf_scoping = { default_config.pf_scoping with
+				vs_flags = [ReserveCurrentTopLevelSymbol];
+			}
 		}
 	| Flash ->
 		{
@@ -428,7 +469,10 @@ let get_config com =
 				ec_wildcard_catch = (["php"],"Throwable");
 				ec_base_throw = (["php"],"Throwable");
 			};
-			pf_nested_function_scoping = Nested;
+			pf_scoping = {
+				vs_scope = FunctionScope;
+				vs_flags = [VarHoisting]
+			}
 		}
 	| Cpp ->
 		{
@@ -438,6 +482,9 @@ let get_config com =
 			pf_add_final_return = true;
 			pf_supports_threads = true;
 			pf_supports_unicode = (defined Define.Cppia) || not (defined Define.DisableUnicodeStrings);
+			pf_scoping = { default_config.pf_scoping with
+				vs_flags = [NoShadowing]
+			}
 		}
 	| Cs ->
 		{
@@ -457,7 +504,11 @@ let get_config com =
 				];
 				ec_wildcard_catch = (["cs";"system"],"Exception");
 				ec_base_throw = (["cs";"system"],"Exception");
-			}
+			};
+			pf_scoping = {
+				vs_scope = FunctionScope;
+				vs_flags = [NoShadowing]
+			};
 		}
 	| Java ->
 		{
@@ -478,7 +529,15 @@ let get_config com =
 				];
 				ec_wildcard_catch = (["java";"lang"],"Throwable");
 				ec_base_throw = (["java";"lang"],"RuntimeException");
-			}
+			};
+			pf_scoping =
+				if defined Jvm then
+					default_config.pf_scoping
+				else
+					{
+						vs_scope = FunctionScope;
+						vs_flags = [NoShadowing; ReserveCurrentTopLevelSymbol; ReserveNames(["_"])];
+					}
 		}
 	| Python ->
 		{
@@ -496,7 +555,10 @@ let get_config com =
 				ec_wildcard_catch = ["python";"Exceptions"],"BaseException";
 				ec_base_throw = ["python";"Exceptions"],"BaseException";
 			};
-			pf_nested_function_scoping = Nested;
+			pf_scoping = {
+				vs_scope = FunctionScope;
+				vs_flags = [VarHoisting]
+			};
 		}
 	| Hl ->
 		{

+ 5 - 141
src/filters/filters.ml

@@ -192,142 +192,6 @@ let check_local_vars_init com e =
 	loop (ref PMap.empty) e;
 	e
 
-(* -------------------------------------------------------------------------- *)
-(* RENAME LOCAL VARS *)
-
-let collect_reserved_local_names com =
-	match com.platform with
-	| Js ->
-		let h = ref StringMap.empty in
-		let add name = h := StringMap.add name true !h in
-		List.iter (fun mt ->
-			let tinfos = t_infos mt in
-			let native_name = try fst (get_native_name tinfos.mt_meta) with Not_found -> Path.flat_path tinfos.mt_path in
-			if native_name = "" then
-				match mt with
-				| TClassDecl c ->
-					List.iter (fun cf ->
-						let native_name = try fst (get_native_name cf.cf_meta) with Not_found -> cf.cf_name in
-						add native_name
-					) c.cl_ordered_statics;
-				| _ -> ()
-			else
-				add native_name
-		) com.types;
-		!h
-	| _ -> StringMap.empty
-
-let rec rename_local_vars_aux ctx reserved e =
-	let initial_reserved = reserved in
-	let own_vars = Hashtbl.create 10 in
-	let own_vars_ordered = ref [] in
-	let foreign_vars = Hashtbl.create 5 in (* Variables which are declared outside of `e` *)
-	let declare v =
-		own_vars_ordered := v :: !own_vars_ordered;
-		Hashtbl.add own_vars v.v_id v
-	in
-	let referenced v =
-		if not (Hashtbl.mem own_vars v.v_id) && not (Hashtbl.mem foreign_vars v.v_name) then
-			Hashtbl.add foreign_vars v.v_name ()
-	in
-	let reserved = ref reserved in
-	let reserve name =
-		reserved := StringMap.add name true !reserved
-	in
-	let check t =
-		match (t_infos t).mt_path with
-		| [], name | name :: _, _ -> reserve name
-	in
-	let check_type t =
-		match follow t with
-		| TInst (c,_) -> check (TClassDecl c)
-		| TEnum (e,_) -> check (TEnumDecl e)
-		| TType (t,_) -> check (TTypeDecl t)
-		| TAbstract (a,_) -> check (TAbstractDecl a)
-		| TMono _ | TLazy _ | TAnon _ | TDynamic _ | TFun _ -> ()
-	in
-	let funcs = ref [] in
-	let rec collect e = match e.eexpr with
-		| TLocal v ->
-			referenced v
- 		| TVar(v,eo) ->
-			declare v;
-			(match eo with None -> () | Some e -> collect e)
-		| TFor(v,e1,e2) ->
-			declare v;
-			collect e1;
-			collect e2;
-		| TTry(e1,catches) ->
-			collect e1;
-			List.iter (fun (v,e) ->
-				declare v;
-				check_type v.v_type;
-				collect e
-			) catches
-		| TFunction tf ->
-			begin match ctx.com.config.pf_nested_function_scoping with
-			| Hoisted ->
-				funcs := tf :: !funcs;
-			| Nested | Independent ->
-				List.iter (fun (v,_) -> declare v) tf.tf_args;
-				collect tf.tf_expr
-			end
-		| TTypeExpr t ->
-			check t
-		| TNew (c,_,_) ->
-			Type.iter collect e;
-			check (TClassDecl c);
-		| TCast (e,Some t) ->
-			collect e;
-			check t;
-		| TConst TSuper ->
-			check_type e.etype
-		| _ ->
-			Type.iter collect e
-	in
-	(* Pass 1: Collect used identifiers and variables. *)
-	collect e;
-	(* Pass 2: Check and rename variables. *)
-	let count_table = Hashtbl.create 0 in
-	let maybe_rename v =
-		(* chop escape char for all local variables generated *)
-		if is_gen_local v then v.v_name <- "_g" ^ String.sub v.v_name 1 (String.length v.v_name - 1);
-		let name = ref v.v_name in
-		let count = ref (try Hashtbl.find count_table v.v_name with Not_found -> 0) in
-		while StringMap.mem !name !reserved do
-			incr count;
-			name := v.v_name ^ (string_of_int !count);
-		done;
-		reserve !name;
-		Hashtbl.replace count_table v.v_name !count;
-		if not (Meta.has Meta.RealPath v.v_meta) then
-			v.v_meta <- (Meta.RealPath,[EConst (String(v.v_name,SDoubleQuotes)),e.epos],e.epos) :: v.v_meta;
-		v.v_name <- !name;
-	in
-	Hashtbl.iter (fun name _ -> reserve name) foreign_vars;
-	List.iter maybe_rename (List.rev !own_vars_ordered);
-	(* Pass 3: Recurse into nested functions. *)
-	List.iter (fun tf ->
-		reserved := initial_reserved;
-		List.iter (fun (v,_) ->
-			maybe_rename v;
-		) tf.tf_args;
-		ignore(rename_local_vars_aux ctx !reserved tf.tf_expr);
-	) !funcs
-
-let rename_local_vars ctx reserved e =
-	let reserved = ref reserved in
-	let reserve name =
-		reserved := StringMap.add name true !reserved
-	in
-	reserve "this";
-	if ctx.com.platform = Java then reserve "_";
-	begin match ctx.curclass.cl_path with
-		| s :: _,_ | [],s -> reserve s
-	end;
-	rename_local_vars_aux ctx !reserved e;
-	e
-
 let mark_switch_break_loops e =
 	let add_loop_label n e =
 		{ e with eexpr = TMeta ((Meta.LoopLabel,[(EConst(Int(string_of_int n)),e.epos)],e.epos), e) }
@@ -580,7 +444,7 @@ let add_rtti ctx t =
 		()
 
 (* Adds member field initializations as assignments to the constructor *)
-let add_field_inits reserved ctx t =
+let add_field_inits locals ctx t =
 	let apply c =
 		let ethis = mk (TConst TThis) (TInst (c,List.map snd c.cl_params)) c.cl_pos in
 		(* TODO: we have to find a variable name which is not used in any of the functions *)
@@ -629,7 +493,7 @@ let add_field_inits reserved ctx t =
 			(match cf.cf_expr with
 			| Some e ->
 				(* This seems a bit expensive, but hopefully constructor expressions aren't that massive. *)
-				let e = rename_local_vars ctx reserved e in
+				let e = RenameVars.run ctx locals e in
 				let e = Optimizer.sanitize ctx.com e in
 				cf.cf_expr <- Some e
 			| _ ->
@@ -896,13 +760,13 @@ let run com tctx main =
 	com.stage <- CAnalyzerStart;
 	if com.platform <> Cross then Analyzer.Run.run_on_types tctx new_types;
 	com.stage <- CAnalyzerDone;
-	let reserved = collect_reserved_local_names com in
+	let locals = RenameVars.init com in
 	let filters = [
 		Optimizer.sanitize com;
 		if com.config.pf_add_final_return then add_final_return else (fun e -> e);
 		(match com.platform with
 		| Eval -> (fun e -> e)
-		| _ -> rename_local_vars tctx reserved);
+		| _ -> RenameVars.run tctx locals);
 		mark_switch_break_loops;
 	] in
 	let t = filter_timer detail_times ["expr 2"] in
@@ -950,7 +814,7 @@ let run com tctx main =
 		check_private_path;
 		apply_native_paths;
 		add_rtti;
-		(match com.platform with | Java | Cs -> (fun _ _ -> ()) | _ -> add_field_inits reserved);
+		(match com.platform with | Java | Cs -> (fun _ _ -> ()) | _ -> add_field_inits locals);
 		(match com.platform with Hl -> (fun _ _ -> ()) | _ -> add_meta_field);
 		check_void_field;
 		(match com.platform with | Cpp -> promote_first_interface_to_super | _ -> (fun _ _ -> ()) );

+ 291 - 0
src/filters/renameVars.ml

@@ -0,0 +1,291 @@
+open Globals
+open Type
+open Typecore
+open Common
+open Ast
+
+type rename_init = {
+	mutable ri_scope : var_scope;
+	mutable ri_hoisting : bool;
+	mutable ri_no_shadowing : bool;
+	mutable ri_reserved : bool StringMap.t;
+	mutable ri_reserve_current_top_level_symbol : bool;
+}
+
+(**
+	For initialization.
+	Make the `name` a reserved word.
+	No local variable will be allowed to have such name.
+*)
+let reserve_init ri name =
+	ri.ri_reserved <- StringMap.add name true ri.ri_reserved
+
+(**
+	Make all class names reserved names.
+	No local variable will have a name matching a class.
+*)
+let reserve_all_types ri com path_to_name =
+	List.iter (fun mt ->
+		let tinfos = t_infos mt in
+		let native_name = try fst (TypeloadCheck.get_native_name tinfos.mt_meta) with Not_found -> path_to_name tinfos.mt_path in
+		if native_name = "" then
+			match mt with
+			| TClassDecl c ->
+				List.iter (fun cf ->
+					let native_name = try fst (TypeloadCheck.get_native_name cf.cf_meta) with Not_found -> cf.cf_name in
+					reserve_init ri native_name
+				) c.cl_ordered_statics;
+			| _ -> ()
+		else
+			reserve_init ri native_name
+	) com.types
+
+(**
+	Initialize the context for local variables renaming
+*)
+let init com =
+	let ri = {
+		ri_scope = com.config.pf_scoping.vs_scope;
+		ri_reserved = StringMap.empty;
+		ri_hoisting = false;
+		ri_no_shadowing = false;
+		ri_reserve_current_top_level_symbol = false;
+	} in
+	reserve_init ri "this";
+	List.iter (fun flag ->
+		match flag with
+		| VarHoisting ->
+			ri.ri_hoisting <- true;
+		| NoShadowing ->
+			ri.ri_no_shadowing <- true;
+		| ReserveNames names ->
+			List.iter (reserve_init ri) names
+		| ReserveAllTopLevelSymbols ->
+			reserve_all_types ri com (fun (pack,name) -> if pack = [] then name else List.hd pack)
+		| ReserveAllTypesFlat ->
+			reserve_all_types ri com Path.flat_path
+		| ReserveCurrentTopLevelSymbol -> ri.ri_reserve_current_top_level_symbol <- true
+	) com.config.pf_scoping.vs_flags;
+	ri
+
+type scope = {
+	(** Parent scope *)
+	parent : scope option;
+	(** Child scopes *)
+	mutable children : scope list;
+	(**
+		Pairs of "variable declared => the list of variables it overlaps with".
+		That list contains variables, which were declared _before_ the current one, but
+		used _after_ the current one was declared.
+		Example:
+		```
+		var a = 123;
+		var b = 324;
+		trace(a);
+		```
+		in this example `b` overlaps with `a`.
+	*)
+	mutable own_vars : (tvar * (tvar IntMap.t ref)) list;
+	(** Variables declared outside of this scope, but used inside of it *)
+	mutable foreign_vars : tvar IntMap.t;
+	(** List of variables used in current loop *)
+	loop_vars : tvar IntMap.t ref;
+	(** Current loops depth *)
+	mutable loop_count : int;
+}
+
+type rename_context = {
+	rc_hoisting : bool;
+	rc_no_shadowing : bool;
+	rc_scope : var_scope;
+	mutable rc_reserved : bool StringMap.t;
+}
+
+(**
+	Make `name` a reserved word.
+	No local variable will be allowed to have such name.
+*)
+let reserve_ctx rc name =
+	rc.rc_reserved <- StringMap.add name true rc.rc_reserved
+
+(**
+	Make `name` a reserved word.
+	No local variable will be allowed to have such name.
+*)
+let reserve reserved name =
+	reserved := StringMap.add name true !reserved
+
+let create_scope parent =
+	let scope = {
+		parent = parent;
+		children = [];
+		own_vars = [];
+		foreign_vars = IntMap.empty;
+		loop_vars = ref IntMap.empty;
+		loop_count = 0;
+	} in
+	Option.may (fun p -> p.children <- scope :: p.children) parent;
+	scope
+
+(**
+	Invoked for each `TVar v` texpr_expr
+*)
+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)
+		else
+			if scope.loop_count = 0 then
+				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
+				) scope.foreign_vars;
+				!overlaps
+			end
+	in
+	scope.own_vars <- (v, ref overlaps) :: scope.own_vars;
+	if scope.loop_count > 0 then
+		scope.loop_vars := IntMap.add v.v_id v !(scope.loop_vars)
+
+(**
+	Invoked for each `TLocal v` texr_expr
+*)
+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;
+			(match scope.parent with
+			| Some parent -> use_var rc parent v
+			| None -> assert false
+			)
+		| (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
+	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)
+
+let collect_loop scope fn =
+	scope.loop_count <- scope.loop_count + 1;
+	fn();
+	scope.loop_count <- scope.loop_count - 1;
+	if scope.loop_count < 0 then
+		assert false;
+	if scope.loop_count = 0 then
+		scope.loop_vars := IntMap.empty
+
+(**
+	Collect all the variables declared and used in `e` expression.
+*)
+let rec collect_vars ?(in_block=false) rc scope e =
+	match e.eexpr with
+	| TVar (v, e_opt) when rc.rc_hoisting ->
+		declare_var rc scope v;
+		Option.may (collect_vars rc scope) e_opt
+	| TVar (v, e_opt) ->
+		Option.may (collect_vars rc scope) e_opt;
+		declare_var rc scope v
+	| TLocal v ->
+		use_var rc scope v
+	| TFunction fn ->
+		let scope = create_scope (Some scope) in
+		List.iter (fun (v,_) -> declare_var rc scope v) fn.tf_args;
+		List.iter (fun (v,_) -> use_var rc scope v) fn.tf_args;
+		collect_vars rc scope fn.tf_expr
+	| TTry (try_expr, catches) ->
+		collect_vars rc scope try_expr;
+		List.iter (fun (v, catch_expr) ->
+			declare_var rc scope v;
+			collect_vars rc scope catch_expr
+		) catches
+	| TBlock exprs when rc.rc_scope = BlockScope ->
+		let scope =
+			if in_block then scope (* parent expression is a block too, that means current block will be merged into the parent one *)
+			else create_scope (Some scope)
+		in
+		List.iter (collect_vars ~in_block:true rc scope) exprs
+	| TWhile (condition, body, flag) ->
+		collect_loop scope (fun() ->
+			if flag = NormalWhile then
+				collect_vars rc scope condition;
+			collect_vars rc scope body;
+			if flag = DoWhile then
+				collect_vars rc scope condition;
+		)
+	(*
+		This only happens for `cross` target, because for real targets all loops are converted to `while` at this point
+		Idk if this works correctly.
+	*)
+	| TFor (v, iterator, body) ->
+		collect_loop scope (fun() ->
+			if rc.rc_hoisting then
+				declare_var rc scope v;
+			collect_vars rc scope iterator;
+			if not rc.rc_hoisting then
+				declare_var rc scope v;
+			collect_vars
+		)
+	| _ ->
+		iter (collect_vars rc scope) e
+
+let trailing_numbers = Str.regexp "[0-9]+$"
+
+(**
+	Rename `v` if needed
+*)
+let maybe_rename_var rc reserved (v,overlaps) =
+	(* 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
+		v.v_name <- "_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;
+	v.v_name <- !name;
+	if rc.rc_no_shadowing || (v.v_capture && rc.rc_hoisting) then reserve reserved v.v_name
+
+(**
+	Rename variables found in `scope`
+*)
+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;
+	List.iter (maybe_rename_var rc reserved) (List.rev scope.own_vars);
+	List.iter (rename_vars rc) scope.children
+
+(**
+	Rename local variables in `e` expression if needed.
+*)
+let run ctx ri e =
+	let rc = {
+		rc_scope = ri.ri_scope;
+		rc_hoisting = ri.ri_hoisting;
+		rc_no_shadowing = ri.ri_no_shadowing;
+		rc_reserved = ri.ri_reserved;
+	} in
+	if ri.ri_reserve_current_top_level_symbol then begin
+		match ctx.curclass.cl_path with
+		| s :: _,_ | [],s -> reserve_ctx rc s
+	end;
+	let scope = create_scope None in
+	collect_vars rc scope e;
+	rename_vars rc scope;
+	e

+ 1 - 1
src/typing/macroContext.ml

@@ -441,7 +441,7 @@ and flush_macro_context mint ctx =
 	in
 	let type_filters = [
 		Exceptions.patch_constructors mctx;
-		Filters.add_field_inits (StringMap.empty) mctx;
+		Filters.add_field_inits (RenameVars.init mctx.com) mctx;
 		minimal_restore;
 		Filters.apply_native_paths mctx
 	] in

+ 24 - 0
tests/misc/projects/Issue9296/Main.hx

@@ -0,0 +1,24 @@
+class Main {
+	static function main() {
+		var v = 1;
+		var success = false;
+		function next(b:Bool) {
+			run(v, bool(), function() {
+				if(b) next(!b)
+				else success = true;
+			});
+		}
+		next(true);
+		if(!success) {
+			throw 'Test failed';
+		}
+	}
+
+	static function bool():Bool {
+		return true;
+	}
+
+	static function run(v:Int, b:Bool, cb:()->Void) {
+		cb();
+	}
+}

+ 3 - 0
tests/misc/projects/Issue9296/compile.hxml

@@ -0,0 +1,3 @@
+-main Main
+-js bin/test.js
+--cmd node bin/test.js

+ 14 - 14
tests/optimization/src/TestJs.hx

@@ -62,7 +62,7 @@ class TestJs {
 		return v + v2;
 	}
 
-	@:js("var a = [];var tmp;try {tmp = a[0];} catch( _g3 ) {tmp = null;}tmp;")
+	@:js("var a = [];var tmp;try {tmp = a[0];} catch( _g ) {tmp = null;}tmp;")
 	@:analyzer(no_local_dce)
 	static function testInlineWithComplexExpr() {
 		var a = [];
@@ -167,27 +167,27 @@ class TestJs {
 		var vRand = new Inl(Math.random());
 	}
 
-	@:js("try {throw haxe_Exception.thrown(false);} catch( _g9 ) {}")
+	@:js("try {throw haxe_Exception.thrown(false);} catch( _g ) {}")
 	static function testNoHaxeErrorUnwrappingWhenNotRequired() {
 		try throw false catch (e:Dynamic) {}
 	}
 
-	@:js('try {throw haxe_Exception.thrown(false);} catch( _g12 ) {TestJs.use(haxe_Exception.caught(_g12).unwrap());}')
+	@:js('try {throw haxe_Exception.thrown(false);} catch( _g ) {TestJs.use(haxe_Exception.caught(_g).unwrap());}')
 	static function testHaxeErrorUnwrappingWhenUsed() {
 		try throw false catch (e:Dynamic) use(e);
 	}
 
-	@:js('try {throw haxe_Exception.thrown(false);} catch( _g15 ) {if(typeof(haxe_Exception.caught(_g15).unwrap()) != "boolean") {throw _g15;}}')
+	@:js('try {throw haxe_Exception.thrown(false);} catch( _g ) {if(typeof(haxe_Exception.caught(_g).unwrap()) != "boolean") {throw _g;}}')
 	static function testHaxeErrorUnwrappingWhenTypeChecked() {
 		try throw false catch (e:Bool) {};
 	}
 
-	@:js('try {throw haxe_Exception.thrown(false);} catch( _g18 ) {if(typeof(haxe_Exception.caught(_g18).unwrap()) == "boolean") {TestJs.use(_g18);} else {throw _g18;}}')
+	@:js('try {throw haxe_Exception.thrown(false);} catch( _g ) {if(typeof(haxe_Exception.caught(_g).unwrap()) == "boolean") {TestJs.use(_g);} else {throw _g;}}')
 	static function testGetOriginalException() {
 		try throw false catch (e:Bool) use(js.Lib.getOriginalException());
 	}
 
-	@:js('try {throw haxe_Exception.thrown(false);} catch( _g21 ) {if(typeof(haxe_Exception.caught(_g21).unwrap()) == "boolean") {throw _g21;} else {throw _g21;}}')
+	@:js('try {throw haxe_Exception.thrown(false);} catch( _g ) {if(typeof(haxe_Exception.caught(_g).unwrap()) == "boolean") {throw _g;} else {throw _g;}}')
 	static function testRethrow() {
 		try throw false catch (e:Bool) js.Lib.rethrow();
 	}
@@ -432,8 +432,8 @@ class TestJs {
 	@:js('
 		var d1 = TestJs.call(1,2);
 		var d11 = TestJs.call(TestJs.call(3,4),d1);
-		var d12 = TestJs.call(5,6);
-		TestJs.call(TestJs.call(TestJs.call(7,8),d12),d11);
+		var d1 = TestJs.call(5,6);
+		TestJs.call(TestJs.call(TestJs.call(7,8),d1),d11);
 	')
 	static function testInlineRebuilding7() {
 		inlineCall(inlineCall(call(1, 2), call(3, 4)), inlineCall(call(5, 6), call(7, 8)));
@@ -442,8 +442,8 @@ class TestJs {
 	@:js('
 		var d1 = TestJs.call(1,2);
 		var d11 = TestJs.call(TestJs.intField,d1);
-		var d12 = TestJs.intField;
-		TestJs.call(TestJs.call(TestJs.call(5,6),d12),d11);
+		var d1 = TestJs.intField;
+		TestJs.call(TestJs.call(TestJs.call(5,6),d1),d11);
 	')
 	static function testInlineRebuilding8() {
 		inlineCall(inlineCall(call(1, 2), intField), inlineCall(intField, call(5, 6)));
@@ -527,11 +527,11 @@ class TestJs {
 	@:js('
 		var tmp = "foo";
 		Extern.test(tmp);
-		var tmp1 = "bar";
-		Extern.test(tmp1);
+		var tmp = "bar";
+		Extern.test(tmp);
 		var closure = Extern.test;
-		var tmp2 = "baz";
-		closure(tmp2);
+		var tmp = "baz";
+		closure(tmp);
 	')
 	static function testAsVar() {
 		Extern.test("foo");

+ 3 - 3
tests/optimization/src/TestLocalDce.hx

@@ -175,9 +175,9 @@ class TestLocalDce {
 
 	@:js('
 		var s = TestLocalDce.keep(1);
-		var _g1 = [0,3,4];
-		while(0 < _g1.length) {
-			var i = _g1[0];
+		var _g = [0,3,4];
+		while(0 < _g.length) {
+			var i = _g[0];
 			s += i * 2;
 			break;
 		}

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

@@ -5,9 +5,9 @@ class TestTreGeneration {
 		}
 		while(true) {
 			if(Std.random(2) == 0) {
-				var _gtmp1 = a;
+				var _gtmp = a;
 				a = b + a;
-				b = _gtmp1;
+				b = _gtmp;
 				s += "?";
 				continue;
 			}
@@ -59,9 +59,9 @@ class TestTreGeneration {
 			}
 			while(true) {
 				if(Std.random(2) == 0) {
-					var _gtmp1 = a;
+					var _gtmp = a;
 					a = b + a;
-					b = _gtmp1;
+					b = _gtmp;
 					s += "?";
 					continue;
 				}
@@ -134,7 +134,7 @@ class TestTreGeneration {
 					throw haxe_Exception.thrown("exit");
 				}
 				return TestTreGeneration.testTryCancelsTre(n - 1);
-			} catch( _g24 ) {
+			} catch( _g ) {
 				if(n == 0) {
 					n -= 1;
 					continue;

+ 3 - 3
tests/optimization/src/issues/Issue6296.hx

@@ -2,9 +2,9 @@ package issues;
 
 class Issue6296 {
 	@:js('
-		var a1 = [];
-		if(a1.push != null) {
-			a1.push(1);
+		var a = [];
+		if(a.push != null) {
+			a.push(1);
 		}'
 	)
 	@:analyzer(no_local_dce)

+ 8 - 8
tests/optimization/src/issues/Issue6715.hx

@@ -11,10 +11,10 @@ class Issue6715 {
 		issues_Issue6715.x = f;
 		var x = 1;
 		x = 2;
-		var x1 = 1;
-		x1 = 2;
-		var x2 = 1;
-		x2 = 2;
+		var x = 1;
+		x = 2;
+		var x = 1;
+		x = 2;
 	')
 	@:analyzer(no_local_dce)
 	static public function test1() {
@@ -24,10 +24,10 @@ class Issue6715 {
 	@:js('
 		var x = 1;
 		x = 2;
-		var x1 = 1;
-		x1 = 2;
-		var x2 = 1;
-		x2 = 2;
+		var x = 1;
+		x = 2;
+		var x = 1;
+		x = 2;
 	')
 	@:analyzer(no_local_dce)
 	static public function test2() {