Skip to content

Commit ab84fd9

Browse files
committed
A Move abstraction; FIXME: Doesn't get rid of the moves
1 parent 6e65cdc commit ab84fd9

File tree

4 files changed

+64
-10
lines changed

4 files changed

+64
-10
lines changed

src/librustc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
#![feature(in_band_lifetimes)]
7272
#![feature(crate_visibility_modifier)]
7373
#![feature(transpose_result)]
74+
#![feature(arbitrary_self_types)]
7475

7576
#![recursion_limit="512"]
7677

src/librustc/ty/query/plumbing.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use util::common::{profq_msg, ProfileQueriesMsg, QueryMsg};
2727

2828
use rustc_data_structures::fx::{FxHashMap};
2929
use rustc_data_structures::sync::{Lrc, Lock};
30+
use rustc_data_structures::by_move::{Move, MoveSlot};
3031
use std::mem;
3132
use std::ptr;
3233
use std::intrinsics::unlikely;
@@ -115,6 +116,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
115116
tcx: TyCtxt<'a, 'tcx, '_>,
116117
span: Span,
117118
key: &Q::Key,
119+
mut job_storage: MoveSlot<'a, JobOwner<'a, 'tcx, Q>>,
118120
) -> TryGetJob<'a, 'tcx, Q> {
119121
let cache = Q::query_cache(tcx);
120122
loop {
@@ -144,12 +146,12 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
144146
query: Q::query(key.clone()),
145147
};
146148
let job = Lrc::new(QueryJob::new(info, icx.query.clone()));
147-
let owner = JobOwner {
149+
let owner = job_storage.init(JobOwner {
148150
cache,
149151
job: job.clone(),
150152
key: (*key).clone(),
151153
layout_depth: icx.layout_depth,
152-
};
154+
});
153155
entry.insert(QueryResult::Started(job));
154156
TryGetJob::NotYetStarted(owner)
155157
})
@@ -172,7 +174,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
172174
/// Completes the query by updating the query cache with the `result`,
173175
/// signals the waiter and forgets the JobOwner, so it won't poison the query
174176
#[inline]
175-
pub(super) fn complete(self, result: &Q::Value, dep_node_index: DepNodeIndex) {
177+
pub(super) fn complete(self: Move<'_, Self>, result: &Q::Value, dep_node_index: DepNodeIndex) {
176178
// We can move out of `self` here because we `mem::forget` it below
177179
let key = unsafe { ptr::read(&self.key) };
178180
let job = unsafe { ptr::read(&self.job) };
@@ -236,14 +238,14 @@ pub struct CycleError<'tcx> {
236238
}
237239

238240
/// The result of `try_get_lock`
239-
pub(super) enum TryGetJob<'a, 'tcx: 'a, D: QueryDescription<'tcx> + 'a> {
241+
pub(super) enum TryGetJob<'a, 'tcx: 'a, Q: QueryDescription<'tcx> + 'a> {
240242
/// The query is not yet started. Contains a guard to the cache eventually used to start it.
241-
NotYetStarted(JobOwner<'a, 'tcx, D>),
243+
NotYetStarted(Move<'a, JobOwner<'a, 'tcx, Q>>),
242244

243245
/// The query was already completed.
244246
/// Returns the result of the query and its dep node index
245247
/// if it succeeded or a cycle error if it failed
246-
JobCompleted(Result<(D::Value, DepNodeIndex), Box<CycleError<'tcx>>>),
248+
JobCompleted(Result<(Q::Value, DepNodeIndex), Box<CycleError<'tcx>>>),
247249
}
248250

249251
impl<'a, 'gcx> TyCtxt<'a, 'gcx, 'gcx> {
@@ -372,7 +374,8 @@ impl<'a, 'gcx> TyCtxt<'a, 'gcx, 'gcx> {
372374

373375
self.sess.profiler(|p| p.record_query(Q::CATEGORY));
374376

375-
let job = match JobOwner::try_get(self, span, &key) {
377+
let job_slot = uninit_slot!();
378+
let job = match JobOwner::try_get(self, span, &key, Move::uninit(job_slot)) {
376379
TryGetJob::NotYetStarted(job) => job,
377380
TryGetJob::JobCompleted(result) => {
378381
return result.map(|(v, index)| {
@@ -438,7 +441,7 @@ impl<'a, 'gcx> TyCtxt<'a, 'gcx, 'gcx> {
438441
fn load_from_disk_and_cache_in_memory<Q: QueryDescription<'gcx>>(
439442
self,
440443
key: Q::Key,
441-
job: JobOwner<'a, 'gcx, Q>,
444+
job: Move<'_, JobOwner<'_, 'gcx, Q>>,
442445
dep_node_index: DepNodeIndex,
443446
dep_node: &DepNode
444447
) -> Result<Q::Value, Box<CycleError<'gcx>>>
@@ -521,7 +524,7 @@ impl<'a, 'gcx> TyCtxt<'a, 'gcx, 'gcx> {
521524
fn force_query_with_job<Q: QueryDescription<'gcx>>(
522525
self,
523526
key: Q::Key,
524-
job: JobOwner<'_, 'gcx, Q>,
527+
job: Move<'_, JobOwner<'_, 'gcx, Q>>,
525528
dep_node: DepNode)
526529
-> Result<(Q::Value, DepNodeIndex), Box<CycleError<'gcx>>> {
527530
// If the following assertion triggers, it can have two reasons:
@@ -616,7 +619,8 @@ impl<'a, 'gcx> TyCtxt<'a, 'gcx, 'gcx> {
616619

617620
// We may be concurrently trying both execute and force a query
618621
// Ensure that only one of them runs the query
619-
let job = match JobOwner::try_get(self, span, &key) {
622+
let job_slot = uninit_slot!();
623+
let job = match JobOwner::try_get(self, span, &key, Move::uninit(job_slot)) {
620624
TryGetJob::NotYetStarted(job) => job,
621625
TryGetJob::JobCompleted(_) => return,
622626
};
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
2+
use std::mem::ManuallyDrop;
3+
use std::mem::MaybeUninit;
4+
use std::ops::{Deref, DerefMut};
5+
6+
pub type MoveSlot<'a, T> = Move<'a, MaybeUninit<T>>;
7+
8+
pub struct Move<'a, T>(&'a mut ManuallyDrop<T>);
9+
10+
impl<'a, T> Move<'a, MaybeUninit<T>> {
11+
pub fn uninit(ptr: &'a mut ManuallyDrop<MaybeUninit<T>>) -> Self {
12+
Move(ptr)
13+
}
14+
15+
// Assumes that MaybeUninit is #[repr(transparent)]
16+
pub fn init(&mut self, value: T) -> Move<'a, T> {
17+
*self.0 = ManuallyDrop::new(MaybeUninit::new(value));
18+
Move(unsafe { &mut *(self.0 as *mut _ as *mut ManuallyDrop<T>) })
19+
}
20+
}
21+
22+
#[macro_export]
23+
#[allow_internal_unstable]
24+
macro_rules! uninit_slot {
25+
() => (&mut std::mem::ManuallyDrop::new(std::mem::MaybeUninit::uninitialized()))
26+
}
27+
28+
impl<'a, T> Deref for Move<'a, T> {
29+
type Target = T;
30+
fn deref(&self) -> &Self::Target {
31+
&*self.0
32+
}
33+
}
34+
35+
impl<'a, T> DerefMut for Move<'a, T> {
36+
fn deref_mut(&mut self) -> &mut Self::Target {
37+
&mut *self.0
38+
}
39+
}
40+
41+
impl<'a, T> Drop for Move<'a, T> {
42+
fn drop(&mut self) {
43+
unsafe {
44+
ManuallyDrop::drop(&mut self.0)
45+
}
46+
}
47+
}

src/librustc_data_structures/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#![feature(stmt_expr_attributes)]
3434
#![feature(core_intrinsics)]
3535
#![feature(integer_atomics)]
36+
#![feature(maybe_uninit)]
3637

3738
#![cfg_attr(unix, feature(libc))]
3839
#![cfg_attr(test, feature(test))]
@@ -104,6 +105,7 @@ pub mod sync;
104105
pub mod tiny_list;
105106
pub mod thin_vec;
106107
pub mod vec;
108+
pub mod by_move;
107109
pub mod transitive_relation;
108110
pub mod tuple_slice;
109111
pub use ena::unify;

0 commit comments

Comments
 (0)