1919//! allocated (and both have a fairly large capacity).
2020
2121use rustc_data_structures:: veccell:: VecCell ;
22+ use std:: cell:: Cell ;
2223use std:: sync:: mpsc:: { self , Sender , Receiver } ;
2324use std:: thread;
2425
@@ -39,6 +40,13 @@ pub enum DepMessage {
3940pub struct DepGraphThreadData {
4041 enabled : bool ,
4142
43+ // Local counter that just tracks how many tasks are pushed onto the
44+ // stack, so that we still get an error in the case where one is
45+ // missing. If dep-graph construction is enabled, we'd get the same
46+ // error when processing tasks later on, but that's annoying because
47+ // it lacks precision about the source of the error.
48+ tasks_pushed : Cell < usize > ,
49+
4250 // current buffer, where we accumulate messages
4351 messages : VecCell < DepMessage > ,
4452
@@ -59,18 +67,26 @@ impl DepGraphThreadData {
5967 let ( tx1, rx1) = mpsc:: channel ( ) ;
6068 let ( tx2, rx2) = mpsc:: channel ( ) ;
6169 let ( txq, rxq) = mpsc:: channel ( ) ;
70+
6271 if enabled {
6372 thread:: spawn ( move || main ( rx1, tx2, txq) ) ;
6473 }
74+
6575 DepGraphThreadData {
6676 enabled : enabled,
77+ tasks_pushed : Cell :: new ( 0 ) ,
6778 messages : VecCell :: with_capacity ( INITIAL_CAPACITY ) ,
6879 swap_in : rx2,
6980 swap_out : tx1,
7081 query_in : rxq,
7182 }
7283 }
7384
85+ #[ inline]
86+ pub fn enabled ( & self ) -> bool {
87+ self . enabled
88+ }
89+
7490 /// Sends the current batch of messages to the thread. Installs a
7591 /// new vector of messages.
7692 fn swap ( & self ) {
@@ -100,13 +116,40 @@ impl DepGraphThreadData {
100116 /// the buffer is full, this may swap.)
101117 #[ inline]
102118 pub fn enqueue ( & self , message : DepMessage ) {
119+ // Regardless of whether dep graph construction is enabled, we
120+ // still want to check that we always have a valid task on the
121+ // stack when a read/write/etc event occurs.
122+ match message {
123+ DepMessage :: Read ( _) | DepMessage :: Write ( _) =>
124+ if self . tasks_pushed . get ( ) == 0 {
125+ self . invalid_message ( "read/write but no current task" )
126+ } ,
127+ DepMessage :: PushTask ( _) | DepMessage :: PushIgnore =>
128+ self . tasks_pushed . set ( self . tasks_pushed . get ( ) + 1 ) ,
129+ DepMessage :: PopTask ( _) | DepMessage :: PopIgnore =>
130+ self . tasks_pushed . set ( self . tasks_pushed . get ( ) - 1 ) ,
131+ DepMessage :: Query =>
132+ ( ) ,
133+ }
134+
103135 if self . enabled {
104- let len = self . messages . push ( message) ;
105- if len == INITIAL_CAPACITY {
106- self . swap ( ) ;
107- }
136+ self . enqueue_enabled ( message) ;
108137 }
109138 }
139+
140+ // Outline this fn since I expect it may want to be inlined
141+ // separately.
142+ fn enqueue_enabled ( & self , message : DepMessage ) {
143+ let len = self . messages . push ( message) ;
144+ if len == INITIAL_CAPACITY {
145+ self . swap ( ) ;
146+ }
147+ }
148+
149+ // Outline this too.
150+ fn invalid_message ( & self , string : & str ) {
151+ panic ! ( "{}; see src/librustc/dep_graph/README.md for more information" , string)
152+ }
110153}
111154
112155/// Definition of the depgraph thread.
0 commit comments