Skip to content

Commit de6a468

Browse files
committedDec 4, 2018
Refactor task system for efficiency
1 parent cf3e67e commit de6a468

File tree

4 files changed

+244
-201
lines changed

4 files changed

+244
-201
lines changed
 

‎src/librustc/dep_graph/graph.rs

+188-140
Original file line numberDiff line numberDiff line change
@@ -202,197 +202,245 @@ impl DepGraph {
202202
arg: A,
203203
task: fn(C, A) -> R)
204204
-> (R, DepNodeIndex)
205-
where C: DepGraphSafe + StableHashingContextProvider<'gcx>,
205+
where C: DepGraphSafe + StableHashingContextProvider<'gcx> + Clone,
206206
R: HashStable<StableHashingContext<'gcx>>,
207207
{
208-
self.with_task_impl(key, cx, arg, false, task,
209-
|key| OpenTask::Regular(Lock::new(RegularOpenTask {
208+
if let Some(ref data) = self.data {
209+
let open_task = OpenTask::Regular(Lock::new(RegularOpenTask {
210210
node: key,
211211
reads: SmallVec::new(),
212212
read_set: Default::default(),
213-
})),
214-
|data, key, task| data.borrow_mut().complete_task(key, task))
213+
}));
214+
let result = ty::tls::with_context(|icx| {
215+
let icx = ty::tls::ImplicitCtxt {
216+
task: &open_task,
217+
..icx.clone()
218+
};
219+
220+
ty::tls::enter_context(&icx, |_| {
221+
task(cx.clone(), arg)
222+
})
223+
});
224+
let dep_node_index = data.current.borrow_mut().complete_task(key, open_task);
225+
self.finish_task_incr_on(data, key, cx, &result, dep_node_index);
226+
(result, dep_node_index)
227+
} else {
228+
let result = task(cx.clone(), arg);
229+
self.finish_task_incr_off(key, cx, &result);
230+
(result, DepNodeIndex::INVALID)
231+
}
215232
}
216233

217-
/// Creates a new dep-graph input with value `input`
218-
pub fn input_task<'gcx, C, R>(&self,
219-
key: DepNode,
220-
cx: C,
221-
input: R)
222-
-> (R, DepNodeIndex)
223-
where C: DepGraphSafe + StableHashingContextProvider<'gcx>,
224-
R: HashStable<StableHashingContext<'gcx>>,
234+
/// Execute something within an "eval-always" task which is a task
235+
// that runs whenever anything changes.
236+
// FIXME: Find a way to make F: DepGraphSafe
237+
pub fn with_eval_always_task<'a, F, R>(
238+
&self,
239+
tcx: TyCtxt<'a, '_, '_>,
240+
key: DepNode,
241+
task: F,
242+
) -> (R, DepNodeIndex)
243+
where F: FnOnce(&OpenTask) -> R,
244+
R: HashStable<StableHashingContext<'a>>,
225245
{
226-
fn identity_fn<C, A>(_: C, arg: A) -> A {
227-
arg
246+
if let Some(ref data) = self.data {
247+
let open_task = OpenTask::EvalAlways { node: key };
248+
let result = task(&open_task);
249+
let dep_node_index = data.current.borrow_mut()
250+
.complete_eval_always_task(key, open_task);
251+
self.finish_task_incr_on(data, key, tcx, &result, dep_node_index);
252+
(result, dep_node_index)
253+
} else {
254+
debug_assert!(!key.kind.fingerprint_needed_for_crate_hash());
255+
(task(&OpenTask::Ignore), DepNodeIndex::INVALID)
228256
}
257+
}
229258

230-
self.with_task_impl(key, cx, input, true, identity_fn,
231-
|_| OpenTask::Ignore,
232-
|data, key, _| data.borrow_mut().alloc_node(key, SmallVec::new()))
259+
// FIXME: Merge with with_task?
260+
pub fn with_query_task<'a, F, R>(
261+
&self,
262+
tcx: TyCtxt<'a, '_, '_>,
263+
key: DepNode,
264+
task: F,
265+
) -> (R, DepNodeIndex)
266+
where F: FnOnce(&OpenTask) -> R,
267+
R: HashStable<StableHashingContext<'a>>,
268+
{
269+
if let Some(ref data) = self.data {
270+
let open_task = OpenTask::Regular(Lock::new(RegularOpenTask {
271+
node: key,
272+
reads: SmallVec::new(),
273+
read_set: Default::default(),
274+
}));
275+
let result = task(&open_task);
276+
// FIXME: Look at `complete_task` and the same for other functions
277+
let dep_node_index = data.current.borrow_mut().complete_task(key, open_task);
278+
self.finish_task_incr_on(data, key, tcx, &result, dep_node_index);
279+
(result, dep_node_index)
280+
} else {
281+
debug_assert!(!key.kind.fingerprint_needed_for_crate_hash());
282+
// with_task runs finish_task_incr_off here
283+
(task(&OpenTask::Ignore), DepNodeIndex::INVALID)
284+
}
285+
}
286+
287+
/// Creates a new dep-graph input with value `input`
288+
pub fn input_dep_index<'gcx, R>(
289+
&self,
290+
key: DepNode,
291+
cx: &StableHashingContext<'gcx>,
292+
input: &R
293+
) -> DepNodeIndex
294+
where R: HashStable<StableHashingContext<'gcx>>,
295+
{
296+
// This assumes that we don't have an ImplicitCtxt and thus have
297+
// an implicit OpenTask::Ignore task
298+
debug_assert!(ty::tls::with_opt(|tcx| tcx.is_none()));
299+
300+
if let Some(ref data) = self.data {
301+
let dep_node_index = data.current.borrow_mut().alloc_node(key, SmallVec::new());
302+
self.finish_task_incr_on(data, key, cx, input, dep_node_index);
303+
dep_node_index
304+
} else {
305+
self.finish_task_incr_off(key, cx, input)
306+
}
233307
}
234308

235-
fn with_task_impl<'gcx, C, A, R>(
309+
fn finish_task_incr_on<'gcx, C, R>(
236310
&self,
311+
data: &DepGraphData,
237312
key: DepNode,
238313
cx: C,
239-
arg: A,
240-
no_tcx: bool,
241-
task: fn(C, A) -> R,
242-
// FIXME: Take OpenTask as a parameter instead
243-
create_task: fn(DepNode) -> OpenTask,
244-
finish_task_and_alloc_depnode: fn(&Lock<CurrentDepGraph>,
245-
DepNode,
246-
OpenTask) -> DepNodeIndex
247-
) -> (R, DepNodeIndex)
314+
result: &R,
315+
dep_node_index: DepNodeIndex,
316+
)
248317
where
249318
C: DepGraphSafe + StableHashingContextProvider<'gcx>,
250319
R: HashStable<StableHashingContext<'gcx>>,
251320
{
252-
if let Some(ref data) = self.data {
253-
let open_task = create_task(key);
321+
// In incremental mode, hash the result of the task. We don't
322+
// do anything with the hash yet, but we are computing it
323+
// anyway so that
324+
// - we make sure that the infrastructure works and
325+
// - we can get an idea of the runtime cost.
326+
let mut hcx = cx.get_stable_hashing_context();
327+
328+
if cfg!(debug_assertions) {
329+
profq_msg(hcx.sess(), ProfileQueriesMsg::TaskBegin(key.clone()))
330+
};
254331

255-
// In incremental mode, hash the result of the task. We don't
256-
// do anything with the hash yet, but we are computing it
257-
// anyway so that
258-
// - we make sure that the infrastructure works and
259-
// - we can get an idea of the runtime cost.
260-
let mut hcx = cx.get_stable_hashing_context();
332+
if cfg!(debug_assertions) {
333+
profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd)
334+
};
261335

262-
if cfg!(debug_assertions) {
263-
profq_msg(hcx.sess(), ProfileQueriesMsg::TaskBegin(key.clone()))
264-
};
336+
let mut stable_hasher = StableHasher::new();
337+
result.hash_stable(&mut hcx, &mut stable_hasher);
265338

266-
let result = if no_tcx {
267-
task(cx, arg)
268-
} else {
269-
ty::tls::with_context(|icx| {
270-
let icx = ty::tls::ImplicitCtxt {
271-
task: &open_task,
272-
..icx.clone()
273-
};
274-
275-
ty::tls::enter_context(&icx, |_| {
276-
task(cx, arg)
277-
})
278-
})
279-
};
339+
let current_fingerprint = stable_hasher.finish();
280340

281-
if cfg!(debug_assertions) {
282-
profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd)
283-
};
341+
// Store the current fingerprint
342+
{
343+
let mut fingerprints = self.fingerprints.borrow_mut();
284344

285-
let dep_node_index = finish_task_and_alloc_depnode(&data.current, key, open_task);
345+
if dep_node_index.index() >= fingerprints.len() {
346+
fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO);
347+
}
286348

287-
let mut stable_hasher = StableHasher::new();
288-
result.hash_stable(&mut hcx, &mut stable_hasher);
349+
debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO,
350+
"DepGraph::with_task() - Duplicate fingerprint \
351+
insertion for {:?}", key);
352+
fingerprints[dep_node_index] = current_fingerprint;
353+
}
289354

290-
let current_fingerprint = stable_hasher.finish();
355+
// Determine the color of the new DepNode.
356+
if let Some(prev_index) = data.previous.node_to_index_opt(&key) {
357+
let prev_fingerprint = data.previous.fingerprint_by_index(prev_index);
291358

292-
// Store the current fingerprint
293-
{
294-
let mut fingerprints = self.fingerprints.borrow_mut();
359+
let color = if current_fingerprint == prev_fingerprint {
360+
DepNodeColor::Green(dep_node_index)
361+
} else {
362+
DepNodeColor::Red
363+
};
295364

296-
if dep_node_index.index() >= fingerprints.len() {
297-
fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO);
298-
}
365+
let mut colors = data.colors.borrow_mut();
366+
debug_assert!(colors.get(prev_index).is_none(),
367+
"DepGraph::with_task() - Duplicate DepNodeColor \
368+
insertion for {:?}", key);
299369

300-
debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO,
301-
"DepGraph::with_task() - Duplicate fingerprint \
302-
insertion for {:?}", key);
303-
fingerprints[dep_node_index] = current_fingerprint;
304-
}
370+
colors.insert(prev_index, color);
371+
}
372+
}
305373

306-
// Determine the color of the new DepNode.
307-
if let Some(prev_index) = data.previous.node_to_index_opt(&key) {
308-
let prev_fingerprint = data.previous.fingerprint_by_index(prev_index);
374+
fn finish_task_incr_off<'gcx, C, R>(
375+
&self,
376+
key: DepNode,
377+
cx: C,
378+
result: &R,
379+
) -> DepNodeIndex
380+
where
381+
C: DepGraphSafe + StableHashingContextProvider<'gcx>,
382+
R: HashStable<StableHashingContext<'gcx>>,
383+
{
384+
debug_assert!(self.data.is_none());
309385

310-
let color = if current_fingerprint == prev_fingerprint {
311-
DepNodeColor::Green(dep_node_index)
312-
} else {
313-
DepNodeColor::Red
314-
};
386+
if key.kind.fingerprint_needed_for_crate_hash() {
387+
let mut hcx = cx.get_stable_hashing_context();
388+
let mut stable_hasher = StableHasher::new();
389+
result.hash_stable(&mut hcx, &mut stable_hasher);
390+
let fingerprint = stable_hasher.finish();
315391

316-
let mut colors = data.colors.borrow_mut();
317-
debug_assert!(colors.get(prev_index).is_none(),
318-
"DepGraph::with_task() - Duplicate DepNodeColor \
319-
insertion for {:?}", key);
392+
let mut fingerprints = self.fingerprints.borrow_mut();
393+
let dep_node_index = DepNodeIndex::new(fingerprints.len());
394+
fingerprints.push(fingerprint);
320395

321-
colors.insert(prev_index, color);
322-
}
396+
debug_assert!(fingerprints[dep_node_index] == fingerprint,
397+
"DepGraph::with_task() - Assigned fingerprint to \
398+
unexpected index for {:?}", key);
323399

324-
(result, dep_node_index)
400+
dep_node_index
325401
} else {
326-
if key.kind.fingerprint_needed_for_crate_hash() {
327-
let mut hcx = cx.get_stable_hashing_context();
328-
let result = task(cx, arg);
329-
let mut stable_hasher = StableHasher::new();
330-
result.hash_stable(&mut hcx, &mut stable_hasher);
331-
let fingerprint = stable_hasher.finish();
332-
333-
let mut fingerprints = self.fingerprints.borrow_mut();
334-
let dep_node_index = DepNodeIndex::new(fingerprints.len());
335-
fingerprints.push(fingerprint);
336-
337-
debug_assert!(fingerprints[dep_node_index] == fingerprint,
338-
"DepGraph::with_task() - Assigned fingerprint to \
339-
unexpected index for {:?}", key);
340-
341-
(result, dep_node_index)
342-
} else {
343-
(task(cx, arg), DepNodeIndex::INVALID)
344-
}
402+
DepNodeIndex::INVALID
345403
}
346404
}
347405

348406
/// Execute something within an "anonymous" task, that is, a task the
349407
/// DepNode of which is determined by the list of inputs it read from.
350-
pub fn with_anon_task<OP,R>(&self, dep_kind: DepKind, op: OP) -> (R, DepNodeIndex)
351-
where OP: FnOnce() -> R
408+
pub fn with_anon_open_task<OP,R>(&self, dep_kind: DepKind, op: OP) -> (R, DepNodeIndex)
409+
where OP: FnOnce(&OpenTask) -> R
352410
{
353411
if let Some(ref data) = self.data {
354-
let (result, open_task) = ty::tls::with_context(|icx| {
355-
let task = OpenTask::Anon(Lock::new(AnonOpenTask {
356-
reads: SmallVec::new(),
357-
read_set: Default::default(),
358-
}));
359-
360-
let r = {
361-
let icx = ty::tls::ImplicitCtxt {
362-
task: &task,
363-
..icx.clone()
364-
};
365-
366-
ty::tls::enter_context(&icx, |_| {
367-
op()
368-
})
369-
};
412+
let task = OpenTask::Anon(Lock::new(AnonOpenTask {
413+
reads: SmallVec::new(),
414+
read_set: Default::default(),
415+
}));
370416

371-
(r, task)
372-
});
417+
let result = op(&task);
373418
let dep_node_index = data.current
374419
.borrow_mut()
375-
.pop_anon_task(dep_kind, open_task);
420+
.pop_anon_task(dep_kind, task);
376421
(result, dep_node_index)
377422
} else {
378-
(op(), DepNodeIndex::INVALID)
423+
(op(&OpenTask::Ignore), DepNodeIndex::INVALID)
379424
}
380425
}
381426

382-
/// Execute something within an "eval-always" task which is a task
383-
// that runs whenever anything changes.
384-
pub fn with_eval_always_task<'gcx, C, A, R>(&self,
385-
key: DepNode,
386-
cx: C,
387-
arg: A,
388-
task: fn(C, A) -> R)
389-
-> (R, DepNodeIndex)
390-
where C: DepGraphSafe + StableHashingContextProvider<'gcx>,
391-
R: HashStable<StableHashingContext<'gcx>>,
427+
/// Execute something within an "anonymous" task, that is, a task the
428+
/// DepNode of which is determined by the list of inputs it read from.
429+
pub fn with_anon_task<OP,R>(&self, dep_kind: DepKind, op: OP) -> (R, DepNodeIndex)
430+
where OP: FnOnce() -> R
392431
{
393-
self.with_task_impl(key, cx, arg, false, task,
394-
|key| OpenTask::EvalAlways { node: key },
395-
|data, key, task| data.borrow_mut().complete_eval_always_task(key, task))
432+
self.with_anon_open_task(dep_kind, |task| {
433+
ty::tls::with_context(|icx| {
434+
let icx = ty::tls::ImplicitCtxt {
435+
task,
436+
..icx.clone()
437+
};
438+
439+
ty::tls::enter_context(&icx, |_| {
440+
op()
441+
})
442+
})
443+
})
396444
}
397445

398446
#[inline]

0 commit comments

Comments
 (0)
Please sign in to comment.