Skip to content

Commit 5071cca

Browse files
committed
Auto merge of #67791 - Zoxc:lift-interning, r=<try>
Implement Lift using interners instead of in_arena r? @eddyb cc @cjgillot
2 parents 0ec3706 + bd9ef8c commit 5071cca

File tree

8 files changed

+67
-132
lines changed

8 files changed

+67
-132
lines changed

src/libarena/lib.rs

-73
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
extern crate alloc;
2222

2323
use rustc_data_structures::cold_path;
24-
use rustc_data_structures::sync::MTLock;
2524
use smallvec::SmallVec;
2625

2726
use std::cell::{Cell, RefCell};
@@ -116,11 +115,6 @@ impl<T> Default for TypedArena<T> {
116115
}
117116

118117
impl<T> TypedArena<T> {
119-
pub fn in_arena(&self, ptr: *const T) -> bool {
120-
let ptr = ptr as *const T as *mut T;
121-
122-
self.chunks.borrow().iter().any(|chunk| chunk.start() <= ptr && ptr < chunk.end())
123-
}
124118
/// Allocates an object in the `TypedArena`, returning a reference to it.
125119
#[inline]
126120
pub fn alloc(&self, object: T) -> &mut T {
@@ -334,12 +328,6 @@ impl Default for DroplessArena {
334328
}
335329

336330
impl DroplessArena {
337-
pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
338-
let ptr = ptr as *const u8 as *mut u8;
339-
340-
self.chunks.borrow().iter().any(|chunk| chunk.start() <= ptr && ptr < chunk.end())
341-
}
342-
343331
#[inline]
344332
fn align(&self, align: usize) {
345333
let final_address = ((self.ptr.get() as usize) + align - 1) & !(align - 1);
@@ -500,66 +488,5 @@ impl DroplessArena {
500488
}
501489
}
502490

503-
#[derive(Default)]
504-
// FIXME(@Zoxc): this type is entirely unused in rustc
505-
pub struct SyncTypedArena<T> {
506-
lock: MTLock<TypedArena<T>>,
507-
}
508-
509-
impl<T> SyncTypedArena<T> {
510-
#[inline(always)]
511-
pub fn alloc(&self, object: T) -> &mut T {
512-
// Extend the lifetime of the result since it's limited to the lock guard
513-
unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) }
514-
}
515-
516-
#[inline(always)]
517-
pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
518-
where
519-
T: Copy,
520-
{
521-
// Extend the lifetime of the result since it's limited to the lock guard
522-
unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) }
523-
}
524-
525-
#[inline(always)]
526-
pub fn clear(&mut self) {
527-
self.lock.get_mut().clear();
528-
}
529-
}
530-
531-
#[derive(Default)]
532-
pub struct SyncDroplessArena {
533-
lock: MTLock<DroplessArena>,
534-
}
535-
536-
impl SyncDroplessArena {
537-
#[inline(always)]
538-
pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
539-
self.lock.lock().in_arena(ptr)
540-
}
541-
542-
#[inline(always)]
543-
pub fn alloc_raw(&self, bytes: usize, align: usize) -> &mut [u8] {
544-
// Extend the lifetime of the result since it's limited to the lock guard
545-
unsafe { &mut *(self.lock.lock().alloc_raw(bytes, align) as *mut [u8]) }
546-
}
547-
548-
#[inline(always)]
549-
pub fn alloc<T>(&self, object: T) -> &mut T {
550-
// Extend the lifetime of the result since it's limited to the lock guard
551-
unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) }
552-
}
553-
554-
#[inline(always)]
555-
pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
556-
where
557-
T: Copy,
558-
{
559-
// Extend the lifetime of the result since it's limited to the lock guard
560-
unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) }
561-
}
562-
}
563-
564491
#[cfg(test)]
565492
mod tests;

src/librustc/arena.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ macro_rules! arena_types {
123123
[few] inferred_outlives_crate: rustc::ty::CratePredicatesMap<'tcx>,
124124
[] upvars: rustc_data_structures::fx::FxIndexMap<rustc::hir::HirId, rustc::hir::Upvar>,
125125

126+
// Interned types
127+
[] tys: rustc::ty::TyS<$tcx>,
128+
126129
// HIR types
127130
[few] hir_forest: rustc::hir::map::Forest<$tcx>,
128131
[] arm: rustc::hir::Arm<$tcx>,
@@ -176,7 +179,7 @@ macro_rules! declare_arena {
176179
([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
177180
#[derive(Default)]
178181
pub struct Arena<$tcx> {
179-
dropless: DroplessArena,
182+
pub dropless: DroplessArena,
180183
drop: DropArena,
181184
$($name: arena_for_type!($a[$ty]),)*
182185
}

src/librustc/ty/context.rs

+26-33
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,9 @@ use crate::util::common::ErrorReported;
4949
use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet, NodeMap};
5050
use crate::util::nodemap::{FxHashMap, FxHashSet};
5151

52-
use arena::SyncDroplessArena;
5352
use errors::DiagnosticBuilder;
5453
use rustc_data_structures::profiling::SelfProfilerRef;
55-
use rustc_data_structures::sharded::ShardedHashMap;
54+
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
5655
use rustc_data_structures::stable_hasher::{
5756
hash_stable_hashmap, HashStable, StableHasher, StableVec,
5857
};
@@ -78,21 +77,11 @@ use syntax::expand::allocator::AllocatorKind;
7877
use syntax::source_map::MultiSpan;
7978
use syntax::symbol::{kw, sym, Symbol};
8079

81-
pub struct AllArenas {
82-
pub interner: SyncDroplessArena,
83-
}
84-
85-
impl AllArenas {
86-
pub fn new() -> Self {
87-
AllArenas { interner: SyncDroplessArena::default() }
88-
}
89-
}
90-
9180
type InternedSet<'tcx, T> = ShardedHashMap<Interned<'tcx, T>, ()>;
9281

9382
pub struct CtxtInterners<'tcx> {
9483
/// The arena that types, regions, etc. are allocated from.
95-
arena: &'tcx SyncDroplessArena,
84+
arena: &'tcx WorkerLocal<Arena<'tcx>>,
9685

9786
/// Specifically use a speedy hash algorithm for these hash sets, since
9887
/// they're accessed quite often.
@@ -112,7 +101,7 @@ pub struct CtxtInterners<'tcx> {
112101
}
113102

114103
impl<'tcx> CtxtInterners<'tcx> {
115-
fn new(arena: &'tcx SyncDroplessArena) -> CtxtInterners<'tcx> {
104+
fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> {
116105
CtxtInterners {
117106
arena,
118107
type_: Default::default(),
@@ -1115,7 +1104,6 @@ impl<'tcx> TyCtxt<'tcx> {
11151104
lint_store: Lrc<lint::LintStore>,
11161105
local_providers: ty::query::Providers<'tcx>,
11171106
extern_providers: ty::query::Providers<'tcx>,
1118-
arenas: &'tcx AllArenas,
11191107
arena: &'tcx WorkerLocal<Arena<'tcx>>,
11201108
resolutions: ty::ResolverOutputs,
11211109
hir: hir_map::Map<'tcx>,
@@ -1126,7 +1114,7 @@ impl<'tcx> TyCtxt<'tcx> {
11261114
let data_layout = TargetDataLayout::parse(&s.target.target).unwrap_or_else(|err| {
11271115
s.fatal(&err);
11281116
});
1129-
let interners = CtxtInterners::new(&arenas.interner);
1117+
let interners = CtxtInterners::new(arena);
11301118
let common_types = CommonTypes::new(&interners);
11311119
let common_lifetimes = CommonLifetimes::new(&interners);
11321120
let common_consts = CommonConsts::new(&interners, &common_types);
@@ -1557,11 +1545,11 @@ pub trait Lift<'tcx>: fmt::Debug {
15571545
}
15581546

15591547
macro_rules! nop_lift {
1560-
($ty:ty => $lifted:ty) => {
1548+
($set:ident; $ty:ty => $lifted:ty) => {
15611549
impl<'a, 'tcx> Lift<'tcx> for $ty {
15621550
type Lifted = $lifted;
15631551
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
1564-
if tcx.interners.arena.in_arena(*self as *const _) {
1552+
if tcx.interners.$set.contains_pointer_to(&Interned(*self)) {
15651553
Some(unsafe { mem::transmute(*self) })
15661554
} else {
15671555
None
@@ -1572,14 +1560,14 @@ macro_rules! nop_lift {
15721560
}
15731561

15741562
macro_rules! nop_list_lift {
1575-
($ty:ty => $lifted:ty) => {
1563+
($set:ident; $ty:ty => $lifted:ty) => {
15761564
impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
15771565
type Lifted = &'tcx List<$lifted>;
15781566
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
15791567
if self.is_empty() {
15801568
return Some(List::empty());
15811569
}
1582-
if tcx.interners.arena.in_arena(*self as *const _) {
1570+
if tcx.interners.$set.contains_pointer_to(&Interned(*self)) {
15831571
Some(unsafe { mem::transmute(*self) })
15841572
} else {
15851573
None
@@ -1589,21 +1577,21 @@ macro_rules! nop_list_lift {
15891577
};
15901578
}
15911579

1592-
nop_lift! {Ty<'a> => Ty<'tcx>}
1593-
nop_lift! {Region<'a> => Region<'tcx>}
1594-
nop_lift! {Goal<'a> => Goal<'tcx>}
1595-
nop_lift! {&'a Const<'a> => &'tcx Const<'tcx>}
1580+
nop_lift! {type_; Ty<'a> => Ty<'tcx>}
1581+
nop_lift! {region; Region<'a> => Region<'tcx>}
1582+
nop_lift! {goal; Goal<'a> => Goal<'tcx>}
1583+
nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
15961584

1597-
nop_list_lift! {Goal<'a> => Goal<'tcx>}
1598-
nop_list_lift! {Clause<'a> => Clause<'tcx>}
1599-
nop_list_lift! {Ty<'a> => Ty<'tcx>}
1600-
nop_list_lift! {ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
1601-
nop_list_lift! {Predicate<'a> => Predicate<'tcx>}
1602-
nop_list_lift! {CanonicalVarInfo => CanonicalVarInfo}
1603-
nop_list_lift! {ProjectionKind => ProjectionKind}
1585+
nop_list_lift! {goal_list; Goal<'a> => Goal<'tcx>}
1586+
nop_list_lift! {clauses; Clause<'a> => Clause<'tcx>}
1587+
nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
1588+
nop_list_lift! {existential_predicates; ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
1589+
nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
1590+
nop_list_lift! {canonical_var_infos; CanonicalVarInfo => CanonicalVarInfo}
1591+
nop_list_lift! {projs; ProjectionKind => ProjectionKind}
16041592

16051593
// This is the impl for `&'a InternalSubsts<'a>`.
1606-
nop_list_lift! {GenericArg<'a> => GenericArg<'tcx>}
1594+
nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
16071595

16081596
pub mod tls {
16091597
use super::{ptr_eq, GlobalCtxt, TyCtxt};
@@ -1927,6 +1915,11 @@ impl<'tcx, T: 'tcx + ?Sized> Clone for Interned<'tcx, T> {
19271915
}
19281916
impl<'tcx, T: 'tcx + ?Sized> Copy for Interned<'tcx, T> {}
19291917

1918+
unsafe impl<'tcx, T: 'tcx + ?Sized> IntoPointer for Interned<'tcx, T> {
1919+
fn into_pointer(&self) -> *const () {
1920+
self.0 as *const _ as *const ()
1921+
}
1922+
}
19301923
// N.B., an `Interned<Ty>` compares and hashes as a `TyKind`.
19311924
impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> {
19321925
fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool {
@@ -2079,7 +2072,7 @@ macro_rules! slice_interners {
20792072
$(impl<'tcx> TyCtxt<'tcx> {
20802073
pub fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
20812074
self.interners.$field.intern_ref(v, || {
2082-
Interned(List::from_arena(&self.interners.arena, v))
2075+
Interned(List::from_arena(&*self.arena, v))
20832076
}).0
20842077
}
20852078
})+

src/librustc/ty/mod.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub use self::BorrowKind::*;
66
pub use self::IntVarValue::*;
77
pub use self::Variance::*;
88

9+
use crate::arena::Arena;
910
use crate::hir::def::{CtorKind, CtorOf, DefKind, ExportMap, Res};
1011
use crate::hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
1112
use crate::hir::Node;
@@ -29,7 +30,6 @@ use crate::ty::util::{Discr, IntTypeExt};
2930
use crate::ty::walk::TypeWalker;
3031
use crate::util::captures::Captures;
3132
use crate::util::nodemap::{DefIdMap, FxHashMap, NodeMap, NodeSet};
32-
use arena::SyncDroplessArena;
3333
use rustc_data_structures::svh::Svh;
3434
use rustc_macros::HashStable;
3535

@@ -76,7 +76,7 @@ pub use crate::ty::diagnostics::*;
7676
pub use self::binding::BindingMode;
7777
pub use self::binding::BindingMode::*;
7878

79-
pub use self::context::{keep_local, tls, AllArenas, FreeRegionInfo, TyCtxt};
79+
pub use self::context::{keep_local, tls, FreeRegionInfo, TyCtxt};
8080
pub use self::context::{
8181
CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, ResolvedOpaqueTy,
8282
UserType, UserTypeAnnotationIndex,
@@ -611,7 +611,7 @@ unsafe impl<T: Sync> Sync for List<T> {}
611611

612612
impl<T: Copy> List<T> {
613613
#[inline]
614-
fn from_arena<'tcx>(arena: &'tcx SyncDroplessArena, slice: &[T]) -> &'tcx List<T> {
614+
fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List<T> {
615615
assert!(!mem::needs_drop::<T>());
616616
assert!(mem::size_of::<T>() != 0);
617617
assert!(slice.len() != 0);
@@ -624,7 +624,9 @@ impl<T: Copy> List<T> {
624624

625625
let size = offset + slice.len() * mem::size_of::<T>();
626626

627-
let mem = arena.alloc_raw(size, cmp::max(mem::align_of::<T>(), mem::align_of::<usize>()));
627+
let mem = arena
628+
.dropless
629+
.alloc_raw(size, cmp::max(mem::align_of::<T>(), mem::align_of::<usize>()));
628630
unsafe {
629631
let result = &mut *(mem.as_mut_ptr() as *mut List<T>);
630632
// Write the length

src/librustc_data_structures/sharded.rs

+14
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,20 @@ impl<K: Eq + Hash + Copy> ShardedHashMap<K, ()> {
137137
}
138138
}
139139

140+
pub unsafe trait IntoPointer {
141+
/// Returns a pointer which outlives `self`.
142+
fn into_pointer(&self) -> *const ();
143+
}
144+
145+
impl<K: Eq + Hash + Copy + IntoPointer> ShardedHashMap<K, ()> {
146+
pub fn contains_pointer_to<T: Hash + IntoPointer>(&self, value: &T) -> bool {
147+
let hash = make_hash(&value);
148+
let shard = self.get_shard_by_hash(hash).lock();
149+
let value = value.into_pointer();
150+
shard.raw_entry().from_hash(hash, |entry| entry.into_pointer() == value).is_some()
151+
}
152+
}
153+
140154
#[inline]
141155
fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
142156
let mut state = FxHasher::default();

src/librustc_interface/passes.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc::session::search_paths::PathKind;
1616
use rustc::session::Session;
1717
use rustc::traits;
1818
use rustc::ty::steal::Steal;
19-
use rustc::ty::{self, AllArenas, GlobalCtxt, ResolverOutputs, TyCtxt};
19+
use rustc::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt};
2020
use rustc::util::common::{time, ErrorReported};
2121
use rustc_builtin_macros;
2222
use rustc_codegen_ssa::back::link::emit_metadata;
@@ -726,7 +726,6 @@ pub fn create_global_ctxt<'tcx>(
726726
outputs: OutputFilenames,
727727
crate_name: &str,
728728
global_ctxt: &'tcx Once<GlobalCtxt<'tcx>>,
729-
all_arenas: &'tcx AllArenas,
730729
arena: &'tcx WorkerLocal<Arena<'tcx>>,
731730
) -> QueryContext<'tcx> {
732731
let sess = &compiler.session();
@@ -759,7 +758,6 @@ pub fn create_global_ctxt<'tcx>(
759758
lint_store,
760759
local_providers,
761760
extern_providers,
762-
&all_arenas,
763761
arena,
764762
resolver_outputs,
765763
hir_map,

src/librustc_interface/queries.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc::lint::LintStore;
1010
use rustc::session::config::{OutputFilenames, OutputType};
1111
use rustc::session::Session;
1212
use rustc::ty::steal::Steal;
13-
use rustc::ty::{AllArenas, GlobalCtxt, ResolverOutputs};
13+
use rustc::ty::{GlobalCtxt, ResolverOutputs};
1414
use rustc::util::common::{time, ErrorReported};
1515
use rustc_codegen_utils::codegen_backend::CodegenBackend;
1616
use rustc_data_structures::sync::{Lrc, Once, WorkerLocal};
@@ -67,7 +67,6 @@ pub struct Queries<'tcx> {
6767
compiler: &'tcx Compiler,
6868
gcx: Once<GlobalCtxt<'tcx>>,
6969

70-
all_arenas: AllArenas,
7170
arena: WorkerLocal<Arena<'tcx>>,
7271

7372
dep_graph_future: Query<Option<DepGraphFuture>>,
@@ -87,7 +86,6 @@ impl<'tcx> Queries<'tcx> {
8786
Queries {
8887
compiler,
8988
gcx: Once::new(),
90-
all_arenas: AllArenas::new(),
9189
arena: WorkerLocal::new(|_| Arena::default()),
9290
dep_graph_future: Default::default(),
9391
parse: Default::default(),
@@ -264,7 +262,6 @@ impl<'tcx> Queries<'tcx> {
264262
outputs,
265263
&crate_name,
266264
&self.gcx,
267-
&self.all_arenas,
268265
&self.arena,
269266
))
270267
})

0 commit comments

Comments
 (0)