Skip to content

Commit 9028f44

Browse files
committed
Implement prototype
1 parent 0006519 commit 9028f44

45 files changed

Lines changed: 3525 additions & 78 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/rustc_data_structures/src/sharded.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,16 @@ impl<K: Eq + Hash, V> ShardedHashMap<K, V> {
199199
}
200200
}
201201
}
202+
203+
#[inline]
204+
pub fn remove(&self, key: &K) {
205+
let hash = make_hash(key);
206+
let mut shard = self.lock_shard_by_hash(hash);
207+
208+
if let Entry::Occupied(e) = table_entry(&mut shard, hash, key) {
209+
e.remove();
210+
}
211+
}
202212
}
203213

204214
impl<K: Eq + Hash + Copy> ShardedHashMap<K, ()> {

compiler/rustc_data_structures/src/vec_cache.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,24 @@ impl SlotIndex {
206206

207207
index_and_lock.store(extra.checked_add(2).unwrap(), Ordering::Release);
208208
}
209+
210+
#[inline]
211+
unsafe fn remove<V>(&self, buckets: &[AtomicPtr<Slot<V>>; 21]) {
212+
let bucket = &buckets[self.bucket_idx];
213+
let ptr = self.bucket_ptr(bucket);
214+
215+
debug_assert!(self.index_in_bucket < self.bucket_idx.capacity());
216+
217+
// SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this
218+
// must be inbounds.
219+
let slot = unsafe { ptr.add(self.index_in_bucket) };
220+
221+
// SAFETY: initialized bucket has zeroed all memory within the bucket, so we are valid for
222+
// AtomicU32 access.
223+
let index_and_lock = unsafe { &(*slot).index_and_lock };
224+
225+
index_and_lock.store(0, Ordering::Release);
226+
}
209227
}
210228

211229
/// In-memory cache for queries whose keys are densely-numbered IDs
@@ -339,6 +357,39 @@ where
339357
pub fn len(&self) -> usize {
340358
self.len.load(Ordering::Acquire)
341359
}
360+
361+
pub fn remove(&self, key: &K) {
362+
let key = u32::try_from(key.index()).unwrap();
363+
let slot_idx = SlotIndex::from_index(key);
364+
365+
unsafe { slot_idx.remove(&self.buckets) };
366+
}
367+
368+
pub fn invalidate(&self, selector: impl Fn(K) -> bool) {
369+
let mut to_remove = vec![];
370+
let mut remaining = vec![];
371+
372+
self.for_each(&mut |key, _, _| {
373+
if selector(*key) {
374+
to_remove.push(*key);
375+
} else {
376+
remaining.push(*key);
377+
}
378+
});
379+
380+
for key in to_remove {
381+
self.remove(&key);
382+
}
383+
384+
for (index, key) in remaining.iter().enumerate() {
385+
let slot = SlotIndex::from_index(u32::try_from(index).unwrap());
386+
let key = u32::try_from(key.index()).unwrap();
387+
388+
unsafe { slot.put_unique(&self.present, (), key) };
389+
}
390+
391+
self.len.store(remaining.len(), Ordering::Release);
392+
}
342393
}
343394

344395
/// Index into an array of buckets.

compiler/rustc_hir/src/definitions.rs

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use std::fmt::{self, Write};
88
use std::hash::Hash;
99

10+
use rustc_data_structures::indexmap::IndexSet;
1011
use rustc_data_structures::stable_hasher::StableHasher;
1112
use rustc_data_structures::unord::UnordMap;
1213
use rustc_hashes::Hash64;
@@ -30,6 +31,7 @@ pub struct DefPathTable {
3031
// We do only store the local hash, as all the definitions are from the current crate.
3132
def_path_hashes: IndexVec<DefIndex, Hash64>,
3233
def_path_hash_to_index: DefPathHashMap,
34+
allow_overwrite: IndexSet<DefIndex>,
3335
}
3436

3537
impl DefPathTable {
@@ -39,38 +41,45 @@ impl DefPathTable {
3941
index_to_key: Default::default(),
4042
def_path_hashes: Default::default(),
4143
def_path_hash_to_index: Default::default(),
44+
allow_overwrite: Default::default(),
4245
}
4346
}
4447

4548
fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> DefIndex {
4649
// Assert that all DefPathHashes correctly contain the local crate's StableCrateId.
4750
debug_assert_eq!(self.stable_crate_id, def_path_hash.stable_crate_id());
4851
let local_hash = def_path_hash.local_hash();
49-
50-
let index = self.index_to_key.push(key);
51-
debug!("DefPathTable::insert() - {key:?} <-> {index:?}");
52-
53-
self.def_path_hashes.push(local_hash);
54-
debug_assert!(self.def_path_hashes.len() == self.index_to_key.len());
52+
let index = self.index_to_key.next_index();
5553

5654
// Check for hash collisions of DefPathHashes. These should be
5755
// exceedingly rare.
5856
if let Some(existing) = self.def_path_hash_to_index.insert(&local_hash, &index) {
59-
let def_path1 = DefPath::make(LOCAL_CRATE, existing, |idx| self.def_key(idx));
60-
let def_path2 = DefPath::make(LOCAL_CRATE, index, |idx| self.def_key(idx));
61-
62-
// Continuing with colliding DefPathHashes can lead to correctness
63-
// issues. We must abort compilation.
64-
//
65-
// The likelihood of such a collision is very small, so actually
66-
// running into one could be indicative of a poor hash function
67-
// being used.
68-
//
69-
// See the documentation for DefPathHash for more information.
70-
panic!(
71-
"found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \
57+
if !self.allow_overwrite.is_empty() && self.allow_overwrite.swap_remove(&existing) {
58+
self.def_path_hash_to_index.insert(&local_hash, &existing);
59+
return existing;
60+
} else {
61+
let def_path1 = DefPath::make(LOCAL_CRATE, existing, |idx| self.def_key(idx));
62+
let def_path2 = DefPath::make(LOCAL_CRATE, index, |idx| self.def_key(idx));
63+
64+
// Continuing with colliding DefPathHashes can lead to correctness
65+
// issues. We must abort compilation.
66+
//
67+
// The likelihood of such a collision is very small, so actually
68+
// running into one could be indicative of a poor hash function
69+
// being used.
70+
//
71+
// See the documentation for DefPathHash for more information.
72+
panic!(
73+
"found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \
7274
Compilation cannot continue."
73-
);
75+
);
76+
}
77+
} else {
78+
self.index_to_key.push(key);
79+
debug!("DefPathTable::insert() - {key:?} <-> {index:?}");
80+
81+
self.def_path_hashes.push(local_hash);
82+
debug_assert!(self.def_path_hashes.len() == self.index_to_key.len());
7483
}
7584

7685
index
@@ -422,6 +431,10 @@ impl Definitions {
422431
LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) }
423432
}
424433

434+
pub fn add_sandbox_def_id(&mut self, id: LocalDefId) {
435+
assert_eq!(self.table.allow_overwrite.insert(id.local_def_index), true);
436+
}
437+
425438
#[inline(always)]
426439
/// Returns `None` if the `DefPathHash` does not correspond to a `LocalDefId`
427440
/// in the current compilation session. This can legitimately happen if the

compiler/rustc_hir/src/intravisit.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ pub trait Visitor<'v>: Sized {
226226
/// or `ControlFlow<T>`.
227227
type Result: VisitorResult = ();
228228

229+
#[inline]
230+
fn visit_if_delayed(&self, _: LocalDefId) -> bool {
231+
true
232+
}
233+
229234
/// If `type NestedFilter` is set to visit nested items, this method
230235
/// must also be overridden to provide a map to retrieve nested items.
231236
fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
@@ -244,18 +249,23 @@ pub trait Visitor<'v>: Sized {
244249
/// this method is if you want a nested pattern but cannot supply a
245250
/// `TyCtxt`; see `maybe_tcx` for advice.
246251
fn visit_nested_item(&mut self, id: ItemId) -> Self::Result {
247-
if Self::NestedFilter::INTER {
252+
if self.should_visit_maybe_delayed_inter(id.owner_id.def_id) {
248253
let item = self.maybe_tcx().hir_item(id);
249254
try_visit!(self.visit_item(item));
250255
}
251256
Self::Result::output()
252257
}
253258

259+
// Now delayed owners are only delegations, which are either item, trait item or impl item.
260+
fn should_visit_maybe_delayed_inter(&mut self, id: LocalDefId) -> bool {
261+
Self::NestedFilter::INTER && self.visit_if_delayed(id)
262+
}
263+
254264
/// Like `visit_nested_item()`, but for trait items. See
255265
/// `visit_nested_item()` for advice on when to override this
256266
/// method.
257267
fn visit_nested_trait_item(&mut self, id: TraitItemId) -> Self::Result {
258-
if Self::NestedFilter::INTER {
268+
if self.should_visit_maybe_delayed_inter(id.owner_id.def_id) {
259269
let item = self.maybe_tcx().hir_trait_item(id);
260270
try_visit!(self.visit_trait_item(item));
261271
}
@@ -266,7 +276,7 @@ pub trait Visitor<'v>: Sized {
266276
/// `visit_nested_item()` for advice on when to override this
267277
/// method.
268278
fn visit_nested_impl_item(&mut self, id: ImplItemId) -> Self::Result {
269-
if Self::NestedFilter::INTER {
279+
if self.should_visit_maybe_delayed_inter(id.owner_id.def_id) {
270280
let item = self.maybe_tcx().hir_impl_item(id);
271281
try_visit!(self.visit_impl_item(item));
272282
}

compiler/rustc_interface/src/passes.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,8 @@ pub fn emit_delayed_lints(tcx: TyCtxt<'_>) {
10531053
/// Runs all analyses that we guarantee to run, even if errors were reported in earlier analyses.
10541054
/// This function never fails.
10551055
fn run_required_analyses(tcx: TyCtxt<'_>) {
1056+
tcx.force_delayed_owners_lowering();
1057+
10561058
if tcx.sess.opts.unstable_opts.input_stats {
10571059
rustc_passes::input_stats::print_hir_stats(tcx);
10581060
}

compiler/rustc_middle/src/dep_graph/graph.rs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use super::{DepKind, DepNode, WorkProductId, read_deps, with_deps};
2828
use crate::dep_graph::edges::EdgesVec;
2929
use crate::ich::StableHashingContext;
3030
use crate::ty::TyCtxt;
31+
use crate::ty::tls::is_sandbox;
3132
use crate::verify_ich::incremental_verify_ich;
3233

3334
/// Tracks 'side effects' for a particular query.
@@ -187,23 +188,23 @@ impl DepGraph {
187188

188189
#[inline]
189190
pub fn data(&self) -> Option<&DepGraphData> {
190-
self.data.as_deref()
191+
self.data.as_deref().filter(|_| !is_sandbox())
191192
}
192193

193194
/// Returns `true` if we are actually building the full dep-graph, and `false` otherwise.
194195
#[inline]
195196
pub fn is_fully_enabled(&self) -> bool {
196-
self.data.is_some()
197+
self.data().is_some()
197198
}
198199

199200
pub fn with_retained_dep_graph(&self, f: impl Fn(&RetainedDepGraph)) {
200-
if let Some(data) = &self.data {
201+
if let Some(data) = self.data() {
201202
data.current.encoder.with_retained_dep_graph(f)
202203
}
203204
}
204205

205206
pub fn assert_ignored(&self) {
206-
if let Some(..) = self.data {
207+
if let Some(..) = self.data() {
207208
read_deps(|task_deps| {
208209
assert_matches!(
209210
task_deps,
@@ -450,7 +451,7 @@ impl DepGraphData {
450451
impl DepGraph {
451452
#[inline]
452453
pub fn read_index(&self, dep_node_index: DepNodeIndex) {
453-
if let Some(ref data) = self.data {
454+
if let Some(ref data) = self.data() {
454455
read_deps(|task_deps| {
455456
let mut task_deps = match task_deps {
456457
TaskDepsRef::Allow(deps) => deps.lock(),
@@ -507,7 +508,7 @@ impl DepGraph {
507508
/// it with the node, for use in the next session.
508509
#[inline]
509510
pub fn record_diagnostic<'tcx>(&self, tcx: TyCtxt<'tcx>, diagnostic: &DiagInner) {
510-
if let Some(ref data) = self.data {
511+
if let Some(ref data) = self.data() {
511512
read_deps(|task_deps| match task_deps {
512513
TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return,
513514
TaskDepsRef::Forbid | TaskDepsRef::Allow(..) => {
@@ -522,7 +523,7 @@ impl DepGraph {
522523
/// refer to a node created used `encode_side_effect` in the previous session.
523524
#[inline]
524525
pub fn force_side_effect<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) {
525-
if let Some(ref data) = self.data {
526+
if let Some(ref data) = self.data() {
526527
data.force_side_effect(tcx, prev_index);
527528
}
528529
}
@@ -533,7 +534,7 @@ impl DepGraph {
533534
tcx: TyCtxt<'tcx>,
534535
side_effect: QuerySideEffect,
535536
) -> DepNodeIndex {
536-
if let Some(ref data) = self.data {
537+
if let Some(ref data) = self.data() {
537538
data.encode_side_effect(tcx, side_effect)
538539
} else {
539540
self.next_virtual_depnode_index()
@@ -563,7 +564,7 @@ impl DepGraph {
563564
hash_result: Option<fn(&mut StableHashingContext<'_>, &R) -> Fingerprint>,
564565
format_value_fn: fn(&R) -> String,
565566
) -> DepNodeIndex {
566-
if let Some(data) = self.data.as_ref() {
567+
if let Some(data) = self.data().as_ref() {
567568
// The caller query has more dependencies than the node we are creating. We may
568569
// encounter a case where this created node is marked as green, but the caller query is
569570
// subsequently marked as red or recomputed. In this case, we will end up feeding a
@@ -808,23 +809,23 @@ impl DepGraph {
808809
/// Checks whether a previous work product exists for `v` and, if
809810
/// so, return the path that leads to it. Used to skip doing work.
810811
pub fn previous_work_product(&self, v: &WorkProductId) -> Option<WorkProduct> {
811-
self.data.as_ref().and_then(|data| data.previous_work_products.get(v).cloned())
812+
self.data().as_ref().and_then(|data| data.previous_work_products.get(v).cloned())
812813
}
813814

814815
/// Access the map of work-products created during the cached run. Only
815816
/// used during saving of the dep-graph.
816817
pub fn previous_work_products(&self) -> &WorkProductMap {
817-
&self.data.as_ref().unwrap().previous_work_products
818+
&self.data().as_ref().unwrap().previous_work_products
818819
}
819820

820821
pub fn debug_was_loaded_from_disk(&self, dep_node: DepNode) -> bool {
821-
self.data.as_ref().unwrap().debug_loaded_from_disk.lock().contains(&dep_node)
822+
self.data().as_ref().unwrap().debug_loaded_from_disk.lock().contains(&dep_node)
822823
}
823824

824825
pub fn debug_dep_kind_was_loaded_from_disk(&self, dep_kind: DepKind) -> bool {
825826
// We only check if we have a dep node corresponding to the given dep kind.
826827
#[allow(rustc::potential_query_instability)]
827-
self.data
828+
self.data()
828829
.as_ref()
829830
.unwrap()
830831
.debug_loaded_from_disk
@@ -834,7 +835,7 @@ impl DepGraph {
834835
}
835836

836837
fn node_color(&self, dep_node: &DepNode) -> DepNodeColor {
837-
if let Some(ref data) = self.data {
838+
if let Some(ref data) = self.data() {
838839
return data.node_color(dep_node);
839840
}
840841

@@ -980,7 +981,7 @@ impl DepGraph {
980981
dep_node: &DepNode,
981982
msg: impl FnOnce() -> S,
982983
) {
983-
if let Some(data) = &self.data {
984+
if let Some(data) = &self.data() {
984985
data.assert_dep_node_not_yet_allocated_in_current_session(sess, dep_node, msg)
985986
}
986987
}
@@ -996,7 +997,7 @@ impl DepGraph {
996997
pub fn exec_cache_promotions<'tcx>(&self, tcx: TyCtxt<'tcx>) {
997998
let _prof_timer = tcx.prof.generic_activity("incr_comp_query_cache_promotion");
998999

999-
let data = self.data.as_ref().unwrap();
1000+
let data = self.data().unwrap();
10001001
for prev_index in data.colors.values.indices() {
10011002
match data.colors.get(prev_index) {
10021003
DepNodeColor::Green(_) => {
@@ -1017,11 +1018,15 @@ impl DepGraph {
10171018
}
10181019

10191020
pub(crate) fn finish_encoding(&self) -> FileEncodeResult {
1020-
if let Some(data) = &self.data { data.current.encoder.finish(&data.current) } else { Ok(0) }
1021+
if let Some(data) = &self.data() {
1022+
data.current.encoder.finish(&data.current)
1023+
} else {
1024+
Ok(0)
1025+
}
10211026
}
10221027

10231028
pub fn next_virtual_depnode_index(&self) -> DepNodeIndex {
1024-
debug_assert!(self.data.is_none());
1029+
debug_assert!(self.data().is_none() || is_sandbox());
10251030
let index = self.virtual_dep_node_index.fetch_add(1, Ordering::Relaxed);
10261031
DepNodeIndex::from_u32(index)
10271032
}
@@ -1396,7 +1401,7 @@ pub(super) enum TrySetColorResult {
13961401
#[inline(never)]
13971402
#[cold]
13981403
pub(crate) fn print_markframe_trace(graph: &DepGraph, frame: &MarkFrame<'_>) {
1399-
let data = graph.data.as_ref().unwrap();
1404+
let data = graph.data().unwrap();
14001405

14011406
eprintln!("there was a panic while trying to force a dep node");
14021407
eprintln!("try_mark_green dep node stack:");

0 commit comments

Comments
 (0)