Browse Source

optimize hlopt cache

Nicolas Cannasse 6 years ago
parent
commit
5c458f06f8
2 changed files with 40 additions and 28 deletions
  1. 2 1
      src/generators/genhl.ml
  2. 38 27
      src/generators/hlopt.ml

+ 2 - 1
src/generators/genhl.ml

@@ -3242,7 +3242,7 @@ and make_fun ?gen_content ctx name fidx f cthis cparent =
 	} in
 	ctx.m <- old;
 	Hashtbl.add ctx.defined_funs fidx ();
-	let f = if ctx.optimize then begin
+	let f = if ctx.optimize && (gen_content = None || name <> ("","")) then begin
 		let t = Timer.timer ["generate";"hl";"opt"] in
 		let f = Hlopt.optimize ctx.dump_out (DynArray.get ctx.cstrings.arr) hlf f in
 		t();
@@ -4050,6 +4050,7 @@ let generate com =
 		output_string ch str;
 		close_out ch;
 	end;
+	Hlopt.clean_cache();
 	t();
 	if Common.raw_defined com "run" then begin
 		if com.run_command ("haxelib run hashlink run " ^ escape_command com.file) <> 0 then failwith "Failed to run HL";

+ 38 - 27
src/generators/hlopt.ml

@@ -984,24 +984,23 @@ let _optimize (f:fundecl) =
 	}
 
 type cache_elt = {
-	c_hfx : Type.tfunc;
 	c_code : opcode array;
 	c_rctx : rctx;
+	c_remap_indexes : int array;
 	mutable c_last_used : int;
 }
 
-let opt_cache = Hashtbl.create 0
+let opt_cache = ref PMap.empty
 let used_mark = ref 0
 
-let optimize dump get_str (f:fundecl) hxf =
+let optimize dump get_str (f:fundecl) (hxf:Type.tfunc) =
 	try
-		let c = Hashtbl.find opt_cache f.fpath in
-		if c.c_hfx != hxf then raise Not_found;
+		let c = PMap.find hxf (!opt_cache) in
 		c.c_last_used <- !used_mark;
 		if Array.length f.code <> Array.length c.c_code then assert false;
-		let f = { f with code = Array.mapi (fun i op ->
-			match op, Array.unsafe_get f.code i with
-			(* only regs : ok ! *)
+		let code = c.c_code in
+		Array.iter (fun i ->
+			let op = (match Array.unsafe_get code i, Array.unsafe_get f.code i with
 			| OInt (r,_), OInt (_,idx) -> OInt (r,idx)
 			| OFloat (r,_), OFloat (_,idx) -> OFloat (r,idx)
 			| OBytes (r,_), OBytes (_,idx) -> OBytes (r,idx)
@@ -1019,28 +1018,40 @@ let optimize dump get_str (f:fundecl) hxf =
 			| ODynGet (r,o,_), ODynGet (_,_,idx) -> ODynGet (r,o,idx)
 			| ODynSet (o,_,v), ODynSet (_,idx,_) -> ODynSet (o,idx,v)
 			| OType (r,_), OType (_,t) -> OType (r,t)
-			| (ONop _ | OMov _ | OBool _ | ONull _
-			  | OAdd _ | OSub _ | OMul _ | OSDiv _ | OUDiv _ | OSMod _ | OUMod _ | OShl _ | OSShr _ | OUShr _ | OAnd _ | OOr _ | OXor _
-			  | ONeg _ | ONot _ | OIncr _ | ODecr _ | OCallMethod _ | OCallThis _ | OCallClosure _ | OVirtualClosure _
-			  | OField _ | OSetField _ | OGetThis _ | OSetThis _
-			  | OJTrue _ | OJFalse _ | OJNull _ | OJNotNull _ | OJSLt _ | OJSGte _ | OJSGt _ | OJSLte _ | OJULt _ | OJUGte _ | OJNotLt _ | OJNotGte _ | OJEq _ | OJNotEq _ | OJAlways _
-			  | OToDyn _ | OToSFloat _ | OToUFloat _ | OToInt _ | OSafeCast _ | OUnsafeCast _ | OToVirtual _ | OLabel _ | ORet _ | OThrow _ | ORethrow _ | OSwitch _ | ONullCheck _
-			  | OTrap _ | OEndTrap _ | OGetUI8 _ | OGetUI16 _ | OGetMem _ | OGetArray _ | OSetUI8 _ | OSetUI16 _ | OSetMem _ | OSetArray _ | ONew _ | OArraySize _ | OGetType _
-			  | OGetTID _ | ORef _ | OUnref _ | OSetref _ | OMakeEnum _ | OEnumAlloc _ | OEnumIndex _ | OEnumField _ | OSetEnumField _ | OAssert _ | ORefData _ | ORefOffset _)
-			  , _ -> op
-			| a, b ->
-				prerr_endline (ostr get_str a);
-				prerr_endline (ostr get_str b);
-				assert false
-		) c.c_code } in
-		remap_fun c.c_rctx f dump get_str
+			| _ -> assert false) in
+			Array.unsafe_set code i op
+		) c.c_remap_indexes;
+		remap_fun c.c_rctx { f with code = code } dump get_str
 	with Not_found ->
 		let rctx = _optimize f in
+		let old_code = f.code in
 		let fopt = remap_fun rctx f dump get_str in
-		if f.fpath <> ("","") then Hashtbl.replace opt_cache f.fpath {
-			c_hfx = hxf;
-			c_code = f.code;
+		Hashtbl.iter (fun _ b ->
+			b.bstate <- None;
+			if dump = None then begin
+				b.bneed <- ISet.empty;
+				b.bneed_all <- None;
+			end;
+		) rctx.r_blocks_pos;
+		let idxs = DynArray.create() in
+		Array.iteri (fun i op ->
+			match op with
+			| OInt _ | OFloat _ | OBytes _ | OString _
+			| OCall0 _ | OCall1 _ | OCall2 _ | OCall3 _ | OCall4 _ | OCallN _ | OStaticClosure _
+			| OInstanceClosure _ | OGetGlobal _	| OSetGlobal _ | ODynGet _ | ODynSet _	| OType _ ->
+				DynArray.add idxs i
+			| _ -> ()
+		) old_code;
+		opt_cache := PMap.add hxf {
+			c_code = old_code;
 			c_rctx = rctx;
 			c_last_used = !used_mark;
-		};
+			c_remap_indexes = DynArray.to_array idxs;
+		} (!opt_cache);
 		fopt
+
+let clean_cache() =
+	PMap.iter (fun k c ->
+		if !used_mark - c.c_last_used > 3 then opt_cache := PMap.remove k !opt_cache;
+	) (!opt_cache);
+	incr used_mark