19
19
//! allocated (and both have a fairly large capacity).
20
20
21
21
use rustc_data_structures:: veccell:: VecCell ;
22
+ use std:: cell:: Cell ;
22
23
use std:: sync:: mpsc:: { self , Sender , Receiver } ;
23
24
use std:: thread;
24
25
@@ -39,6 +40,13 @@ pub enum DepMessage {
39
40
pub struct DepGraphThreadData {
40
41
enabled : bool ,
41
42
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
+
42
50
// current buffer, where we accumulate messages
43
51
messages : VecCell < DepMessage > ,
44
52
@@ -59,18 +67,26 @@ impl DepGraphThreadData {
59
67
let ( tx1, rx1) = mpsc:: channel ( ) ;
60
68
let ( tx2, rx2) = mpsc:: channel ( ) ;
61
69
let ( txq, rxq) = mpsc:: channel ( ) ;
70
+
62
71
if enabled {
63
72
thread:: spawn ( move || main ( rx1, tx2, txq) ) ;
64
73
}
74
+
65
75
DepGraphThreadData {
66
76
enabled : enabled,
77
+ tasks_pushed : Cell :: new ( 0 ) ,
67
78
messages : VecCell :: with_capacity ( INITIAL_CAPACITY ) ,
68
79
swap_in : rx2,
69
80
swap_out : tx1,
70
81
query_in : rxq,
71
82
}
72
83
}
73
84
85
+ #[ inline]
86
+ pub fn enabled ( & self ) -> bool {
87
+ self . enabled
88
+ }
89
+
74
90
/// Sends the current batch of messages to the thread. Installs a
75
91
/// new vector of messages.
76
92
fn swap ( & self ) {
@@ -100,13 +116,40 @@ impl DepGraphThreadData {
100
116
/// the buffer is full, this may swap.)
101
117
#[ inline]
102
118
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
+
103
135
if self . enabled {
104
- let len = self . messages . push ( message) ;
105
- if len == INITIAL_CAPACITY {
106
- self . swap ( ) ;
107
- }
136
+ self . enqueue_enabled ( message) ;
108
137
}
109
138
}
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
+ }
110
153
}
111
154
112
155
/// Definition of the depgraph thread.
0 commit comments