@@ -19,6 +19,11 @@ use std::iter::repeat;
1919use std:: path:: Path ;
2020use std:: time:: { Duration , Instant } ;
2121
22+ use std:: sync:: mpsc:: { Sender } ;
23+ use syntax_pos:: { Span } ;
24+ use ty:: maps:: { QueryMsg } ;
25+ use dep_graph:: { DepNode } ;
26+
2227// The name of the associated type for `Fn` return types
2328pub const FN_OUTPUT_NAME : & ' static str = "Output" ;
2429
@@ -29,6 +34,72 @@ pub struct ErrorReported;
2934
3035thread_local ! ( static TIME_DEPTH : Cell <usize > = Cell :: new( 0 ) ) ;
3136
37+ /// Initialized for -Z profile-queries
38+ thread_local ! ( static PROFQ_CHAN : RefCell <Option <Sender <ProfileQueriesMsg >>> = RefCell :: new( None ) ) ;
39+
40+ /// Parameters to the `Dump` variant of type `ProfileQueriesMsg`.
41+ #[ derive( Clone , Debug ) ]
42+ pub struct ProfQDumpParams {
43+ /// A base path for the files we will dump
44+ pub path : String ,
45+ /// To ensure that the compiler waits for us to finish our dumps
46+ pub ack : Sender < ( ) > ,
47+ /// toggle dumping a log file with every `ProfileQueriesMsg`
48+ pub dump_profq_msg_log : bool ,
49+ }
50+
51+ /// A sequence of these messages induce a trace of query-based incremental compilation.
52+ /// FIXME(matthewhammer): Determine whether we should include cycle detection here or not.
53+ #[ derive( Clone , Debug ) ]
54+ pub enum ProfileQueriesMsg {
55+ /// begin a timed pass
56+ TimeBegin ( String ) ,
57+ /// end a timed pass
58+ TimeEnd ,
59+ /// begin a task (see dep_graph::graph::with_task)
60+ TaskBegin ( DepNode ) ,
61+ /// end a task
62+ TaskEnd ,
63+ /// begin a new query
64+ QueryBegin ( Span , QueryMsg ) ,
65+ /// query is satisfied by using an already-known value for the given key
66+ CacheHit ,
67+ /// query requires running a provider; providers may nest, permitting queries to nest.
68+ ProviderBegin ,
69+ /// query is satisfied by a provider terminating with a value
70+ ProviderEnd ,
71+ /// dump a record of the queries to the given path
72+ Dump ( ProfQDumpParams ) ,
73+ /// halt the profiling/monitoring background thread
74+ Halt
75+ }
76+
77+ /// If enabled, send a message to the profile-queries thread
78+ pub fn profq_msg ( msg : ProfileQueriesMsg ) {
79+ PROFQ_CHAN . with ( |sender|{
80+ if let Some ( s) = sender. borrow ( ) . as_ref ( ) {
81+ s. send ( msg) . unwrap ( )
82+ } else {
83+ // Do nothing.
84+ //
85+ // FIXME(matthewhammer): Multi-threaded translation phase triggers the panic below.
86+ // From backtrace: rustc_trans::back::write::spawn_work::{{closure}}.
87+ //
88+ // panic!("no channel on which to send profq_msg: {:?}", msg)
89+ }
90+ } )
91+ }
92+
93+ /// Set channel for profile queries channel
94+ pub fn profq_set_chan ( s : Sender < ProfileQueriesMsg > ) -> bool {
95+ PROFQ_CHAN . with ( |chan|{
96+ if chan. borrow ( ) . is_none ( ) {
97+ * chan. borrow_mut ( ) = Some ( s) ;
98+ true
99+ } else { false }
100+ } )
101+ }
102+
32103/// Read the current depth of `time()` calls. This is used to
33104/// encourage indentation across threads.
34105pub fn time_depth ( ) -> usize {
@@ -53,9 +124,15 @@ pub fn time<T, F>(do_it: bool, what: &str, f: F) -> T where
53124 r
54125 } ) ;
55126
127+ if cfg ! ( debug_assertions) {
128+ profq_msg ( ProfileQueriesMsg :: TimeBegin ( what. to_string ( ) ) )
129+ } ;
56130 let start = Instant :: now ( ) ;
57131 let rv = f ( ) ;
58132 let dur = start. elapsed ( ) ;
133+ if cfg ! ( debug_assertions) {
134+ profq_msg ( ProfileQueriesMsg :: TimeEnd )
135+ } ;
59136
60137 print_time_passes_entry_internal ( what, dur) ;
61138
0 commit comments