@@ -19,6 +19,11 @@ use std::iter::repeat;
19
19
use std:: path:: Path ;
20
20
use std:: time:: { Duration , Instant } ;
21
21
22
+ use std:: sync:: mpsc:: { Sender } ;
23
+ use syntax_pos:: { Span } ;
24
+ use ty:: maps:: { QueryMsg } ;
25
+ use dep_graph:: { DepNode } ;
26
+
22
27
// The name of the associated type for `Fn` return types
23
28
pub const FN_OUTPUT_NAME : & ' static str = "Output" ;
24
29
@@ -29,6 +34,72 @@ pub struct ErrorReported;
29
34
30
35
thread_local ! ( static TIME_DEPTH : Cell <usize > = Cell :: new( 0 ) ) ;
31
36
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
+
32
103
/// Read the current depth of `time()` calls. This is used to
33
104
/// encourage indentation across threads.
34
105
pub fn time_depth ( ) -> usize {
@@ -53,9 +124,15 @@ pub fn time<T, F>(do_it: bool, what: &str, f: F) -> T where
53
124
r
54
125
} ) ;
55
126
127
+ if cfg ! ( debug_assertions) {
128
+ profq_msg ( ProfileQueriesMsg :: TimeBegin ( what. to_string ( ) ) )
129
+ } ;
56
130
let start = Instant :: now ( ) ;
57
131
let rv = f ( ) ;
58
132
let dur = start. elapsed ( ) ;
133
+ if cfg ! ( debug_assertions) {
134
+ profq_msg ( ProfileQueriesMsg :: TimeEnd )
135
+ } ;
59
136
60
137
print_time_passes_entry_internal ( what, dur) ;
61
138
0 commit comments