[scheduler][static callgraph] remove lazy init now that it's enforced in ProcessPool

Summary:
Building the call graph should be done only in the scheduler process after having forked all workers.  This was achieved by a lazy init pattern, whereby the first time `next` was called, it would build the call graph, on the assumption that `next` is only ever called in the scheduler after forking.

D19769741 made this compulsory regardless the scheduler by passing a thunk to `ProcessPool` which is called to obtain the actual scheduler, on the right process and after the fork.

This means we don't need the custom lazy init logic any more.  In addition, that set up used a DB query to overapproximate the number of procedures to analyse, because this was supposed to be provided *before* forking.  Now this is also not needed, and on top of that we can provide the exact number after building the call graph.

Reviewed By: ezgicicek

Differential Revision: D19833974

fbshipit-source-id: 7f6d51d93
master
Nikos Gorogiannis 5 years ago committed by Facebook Github Bot
parent 7f8ce501d0
commit 757f6ee829

@ -28,7 +28,8 @@ let build_from_captured_procs g =
CallGraph.create_node g proc_name callees )
let build_from_sources g sources =
let build_from_sources sources =
let g = CallGraph.create CallGraph.default_initial_capacity in
let time0 = Mtime_clock.counter () in
L.progress "Building call graph...@\n%!" ;
build_from_captured_procs g ;
@ -41,34 +42,22 @@ let build_from_sources g sources =
L.progress
"Built call graph in %a, from %d total procs, %d reachable defined procs and takes %d bytes@."
Mtime.Span.pp (Mtime_clock.count time0) n_captured (CallGraph.n_procs g)
(Obj.(reachable_words (repr g)) * (Sys.word_size / 8))
let count_procedures () =
let db = ResultsDatabase.get_database () in
let stmt = Sqlite3.prepare db "SELECT COUNT(rowid) FROM procedures" in
let count =
match SqliteUtils.result_single_column_option db ~log:"counting procedures" stmt with
| Some (Sqlite3.Data.INT i64) ->
Int64.to_int i64 |> Option.value ~default:Int.max_value
| _ ->
L.die InternalError "Got no result trying to count procedures"
in
L.debug Analysis Quiet "Found %d procedures in procedures table.@." count ;
count
(Obj.(reachable_words (repr g)) * (Sys.word_size / 8)) ;
g
let bottom_up sources : SchedulerTypes.target ProcessPool.TaskGenerator.t =
let open SchedulerTypes in
(* this will potentially grossly overapproximate the tasks *)
let remaining = ref (count_procedures ()) in
let syntactic_call_graph = build_from_sources sources in
let remaining = ref (CallGraph.n_procs syntactic_call_graph) in
let remaining_tasks () = !remaining in
let syntactic_call_graph = CallGraph.create CallGraph.default_initial_capacity in
let initialized = ref false in
let pending : CallGraph.Node.t list ref = ref [] in
let pending =
(* prime the pending queue so that [empty] doesn't immediately return true *)
ref (CallGraph.get_unflagged_leaves syntactic_call_graph)
in
let scheduled = ref Procname.Set.empty in
let is_empty () =
let empty = !initialized && List.is_empty !pending && Procname.Set.is_empty !scheduled in
let empty = List.is_empty !pending && Procname.Set.is_empty !scheduled in
if empty then (
remaining := 0 ;
L.progress "Finished call graph scheduling, %d procs remaining (in, or reaching, cycles).@."
@ -78,14 +67,14 @@ let bottom_up sources : SchedulerTypes.target ProcessPool.TaskGenerator.t =
CallGraph.reset syntactic_call_graph ) ;
empty
in
let rec next_aux () =
let rec next () =
match !pending with
| [] ->
pending := CallGraph.get_unflagged_leaves syntactic_call_graph ;
if List.is_empty !pending then None else next_aux ()
if List.is_empty !pending then None else next ()
| n :: ns when n.flag || not (CallGraph.mem syntactic_call_graph n.id) ->
pending := ns ;
next_aux ()
next ()
| n :: ns ->
pending := ns ;
scheduled := Procname.Set.add n.pname !scheduled ;
@ -100,13 +89,6 @@ let bottom_up sources : SchedulerTypes.target ProcessPool.TaskGenerator.t =
| File _ ->
L.die InternalError "Only Procnames are scheduled but File target was received"
in
let next () =
(* do construction here, to avoid having the call graph into forked workers *)
if not !initialized then (
build_from_sources syntactic_call_graph sources ;
initialized := true ) ;
next_aux ()
in
{remaining_tasks; is_empty; finished; next}

Loading…
Cancel
Save