Browse Source

Make analyzer thread-safe (#12083)

* remove shared lattice

* lose analyzer data dependency on com

* how bad could it be?

* make var ids atomic

* optimize because stuff fails otherwise

* cleanup

* how far can we take this?
Simon Krajewski 5 months ago
parent
commit
97cc11274e

+ 3 - 3
src/core/tFunctions.ml

@@ -71,14 +71,14 @@ let has_var_flag v (flag : flag_tvar) =
 (* ======= General utility ======= *)
 
 let alloc_var' =
-	let uid = ref 0 in
+	let uid = Atomic.make 0 in
 	uid,(fun kind n t p ->
-		incr uid;
+		Atomic.incr uid;
 		{
 			v_kind = kind;
 			v_name = n;
 			v_type = t;
-			v_id = !uid;
+			v_id = Atomic.get uid;
 			v_extra = None;
 			v_meta = [];
 			v_pos = p;

+ 16 - 9
src/optimization/analyzer.ml

@@ -1119,7 +1119,7 @@ module Run = struct
 		let e = Type.map_expr (reduce_control_flow com) e in
 		Optimizer.reduce_control_flow com e
 
-	let run_on_field com config c cf = match cf.cf_expr with
+	let run_on_field' com config c cf = match cf.cf_expr with
 		| Some e when not (is_ignored cf.cf_meta) && not (Typecore.is_removable_field com cf) && not (has_class_field_flag cf CfPostProcessed) ->
 			let config = update_config_from_meta com config cf.cf_meta in
 			let actx = create_analyzer_context com config (Printf.sprintf "%s.%s" (s_type_path c.cl_path) cf.cf_name) e in
@@ -1154,14 +1154,18 @@ module Run = struct
 		| _ -> ()
 
 	let run_on_field com config c cf =
-		run_on_field com config c cf;
-		List.iter (run_on_field com config c) cf.cf_overloads
+		run_on_field' com config c cf;
+		List.iter (run_on_field' com config c) cf.cf_overloads
 
-	let run_on_class com config c =
+	let run_on_class com pool config c =
 		let config = update_config_from_meta com config c.cl_meta in
+		let fields = DynArray.create () in
 		let process_field stat cf = match cf.cf_kind with
-			| Var _ when not stat -> ()
-			| _ -> run_on_field com config c cf
+			| Var _ when not stat ->
+				()
+			| _ ->
+				DynArray.add fields cf;
+				List.iter (DynArray.add fields) cf.cf_overloads
 		in
 		List.iter (process_field false) c.cl_ordered_fields;
 		List.iter (process_field true) c.cl_ordered_statics;
@@ -1169,6 +1173,7 @@ module Run = struct
 			| None -> ()
 			| Some f -> process_field false f;
 		end;
+		Parallel.run_parallel_on_array pool (DynArray.to_array fields) (run_on_field' com config c);
 		begin match TClass.get_cl_init c with
 			| None ->
 				()
@@ -1184,10 +1189,10 @@ module Run = struct
 				TClass.set_cl_init c e
 		end
 
-	let run_on_type com config t =
+	let run_on_type com pool config t =
 		match t with
 		| TClassDecl c when (is_ignored c.cl_meta) -> ()
-		| TClassDecl c -> run_on_class com config c
+		| TClassDecl c -> run_on_class com pool config c
 		| TEnumDecl _ -> ()
 		| TTypeDecl _ -> ()
 		| TAbstractDecl _ -> ()
@@ -1197,7 +1202,9 @@ module Run = struct
 		with_timer config.detail_times "" ["other"] (fun () ->
 			if config.optimize && config.purity_inference then
 				with_timer config.detail_times "" ["optimize";"purity-inference"] (fun () -> Purity.infer com);
-			List.iter (run_on_type com config) types
+			Parallel.run_in_new_pool (fun pool ->
+				Parallel.run_parallel_on_array pool (Array.of_list types) (run_on_type com pool config);
+			)
 		)
 end
 ;;

+ 3 - 3
src/optimization/analyzerTypes.ml

@@ -343,10 +343,10 @@ module Graph = struct
 		Hashtbl.add g.g_functions bb.bb_id (bb,t,p,tf)
 
 	let alloc_id =
-		let r = ref 1 in
+		let r = Atomic.make 1 in
 		(fun () ->
-			incr r;
-			!r
+			Atomic.incr r;
+			Atomic.get r
 		)
 
 	let create_node g kind t p =

+ 2 - 2
src/typing/typeloadModule.ml

@@ -762,8 +762,8 @@ class hxb_reader_api_typeload
 	method get_var_id (i : int) =
 		(* The v_id in .hxb has no relation to this context, make a new one. *)
 		let uid = fst alloc_var' in
-		incr uid;
-		!uid
+		Atomic.incr uid;
+		Atomic.get uid
 
 	method read_expression_eagerly (cf : tclass_field) =
 		com.is_macro_context || match cf.cf_kind with

+ 1 - 1
tests/unit/compile-each.hxml

@@ -11,4 +11,4 @@
 -D analyzer-optimize
 -D analyzer-user-var-fusion
 -D message.reporting=pretty
--D haxe-next
+-D haxe-next