Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Lift using interners instead of in_arena #67791

Merged
merged 4 commits into from
Jan 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 0 additions & 73 deletions src/libarena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
extern crate alloc;

use rustc_data_structures::cold_path;
use rustc_data_structures::sync::MTLock;
use smallvec::SmallVec;

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

impl<T> TypedArena<T> {
pub fn in_arena(&self, ptr: *const T) -> bool {
let ptr = ptr as *const T as *mut T;

self.chunks.borrow().iter().any(|chunk| chunk.start() <= ptr && ptr < chunk.end())
}
/// Allocates an object in the `TypedArena`, returning a reference to it.
#[inline]
pub fn alloc(&self, object: T) -> &mut T {
Expand Down Expand Up @@ -334,12 +328,6 @@ impl Default for DroplessArena {
}

impl DroplessArena {
pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
let ptr = ptr as *const u8 as *mut u8;

self.chunks.borrow().iter().any(|chunk| chunk.start() <= ptr && ptr < chunk.end())
}

#[inline]
fn align(&self, align: usize) {
let final_address = ((self.ptr.get() as usize) + align - 1) & !(align - 1);
Expand Down Expand Up @@ -500,66 +488,5 @@ impl DroplessArena {
}
}

#[derive(Default)]
// FIXME(@Zoxc): this type is entirely unused in rustc
pub struct SyncTypedArena<T> {
lock: MTLock<TypedArena<T>>,
}

impl<T> SyncTypedArena<T> {
#[inline(always)]
pub fn alloc(&self, object: T) -> &mut T {
// Extend the lifetime of the result since it's limited to the lock guard
unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) }
}

#[inline(always)]
pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
where
T: Copy,
{
// Extend the lifetime of the result since it's limited to the lock guard
unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) }
}

#[inline(always)]
pub fn clear(&mut self) {
self.lock.get_mut().clear();
}
}

#[derive(Default)]
pub struct SyncDroplessArena {
lock: MTLock<DroplessArena>,
}

impl SyncDroplessArena {
#[inline(always)]
pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
self.lock.lock().in_arena(ptr)
}

#[inline(always)]
pub fn alloc_raw(&self, bytes: usize, align: usize) -> &mut [u8] {
// Extend the lifetime of the result since it's limited to the lock guard
unsafe { &mut *(self.lock.lock().alloc_raw(bytes, align) as *mut [u8]) }
}

#[inline(always)]
pub fn alloc<T>(&self, object: T) -> &mut T {
// Extend the lifetime of the result since it's limited to the lock guard
unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) }
}

#[inline(always)]
pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
where
T: Copy,
{
// Extend the lifetime of the result since it's limited to the lock guard
unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) }
}
}

#[cfg(test)]
mod tests;
5 changes: 4 additions & 1 deletion src/librustc/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ macro_rules! arena_types {
[few] inferred_outlives_crate: rustc::ty::CratePredicatesMap<'tcx>,
[] upvars: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,

// Interned types
[] tys: rustc::ty::TyS<$tcx>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, so we're not using the DroplessArena for these anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do, but TyS is not Copy, so we have to declare it.


// HIR types
[few] hir_forest: rustc::hir::map::Forest<$tcx>,
[] arm: rustc_hir::Arm<$tcx>,
Expand Down Expand Up @@ -176,7 +179,7 @@ macro_rules! declare_arena {
([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
#[derive(Default)]
pub struct Arena<$tcx> {
dropless: DroplessArena,
pub dropless: DroplessArena,
drop: DropArena,
$($name: arena_for_type!($a[$ty]),)*
}
Expand Down
59 changes: 26 additions & 33 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,9 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex, LOCAL_CRA
use rustc_hir::{HirId, Node, TraitCandidate};
use rustc_hir::{ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet};

use arena::SyncDroplessArena;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::sharded::ShardedHashMap;
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
use rustc_data_structures::stable_hasher::{
hash_stable_hashmap, HashStable, StableHasher, StableVec,
};
Expand Down Expand Up @@ -81,21 +80,11 @@ use syntax::ast;
use syntax::attr;
use syntax::expand::allocator::AllocatorKind;

pub struct AllArenas {
pub interner: SyncDroplessArena,
}

impl AllArenas {
pub fn new() -> Self {
AllArenas { interner: SyncDroplessArena::default() }
}
}

type InternedSet<'tcx, T> = ShardedHashMap<Interned<'tcx, T>, ()>;

pub struct CtxtInterners<'tcx> {
/// The arena that types, regions, etc. are allocated from.
arena: &'tcx SyncDroplessArena,
arena: &'tcx WorkerLocal<Arena<'tcx>>,

/// Specifically use a speedy hash algorithm for these hash sets, since
/// they're accessed quite often.
Expand All @@ -115,7 +104,7 @@ pub struct CtxtInterners<'tcx> {
}

impl<'tcx> CtxtInterners<'tcx> {
fn new(arena: &'tcx SyncDroplessArena) -> CtxtInterners<'tcx> {
fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> {
CtxtInterners {
arena,
type_: Default::default(),
Expand Down Expand Up @@ -1118,7 +1107,6 @@ impl<'tcx> TyCtxt<'tcx> {
lint_store: Lrc<lint::LintStore>,
local_providers: ty::query::Providers<'tcx>,
extern_providers: ty::query::Providers<'tcx>,
arenas: &'tcx AllArenas,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
resolutions: ty::ResolverOutputs,
hir: hir_map::Map<'tcx>,
Expand All @@ -1129,7 +1117,7 @@ impl<'tcx> TyCtxt<'tcx> {
let data_layout = TargetDataLayout::parse(&s.target.target).unwrap_or_else(|err| {
s.fatal(&err);
});
let interners = CtxtInterners::new(&arenas.interner);
let interners = CtxtInterners::new(arena);
let common_types = CommonTypes::new(&interners);
let common_lifetimes = CommonLifetimes::new(&interners);
let common_consts = CommonConsts::new(&interners, &common_types);
Expand Down Expand Up @@ -1560,11 +1548,11 @@ pub trait Lift<'tcx>: fmt::Debug {
}

macro_rules! nop_lift {
($ty:ty => $lifted:ty) => {
($set:ident; $ty:ty => $lifted:ty) => {
impl<'a, 'tcx> Lift<'tcx> for $ty {
type Lifted = $lifted;
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
if tcx.interners.arena.in_arena(*self as *const _) {
if tcx.interners.$set.contains_pointer_to(&Interned(*self)) {
Some(unsafe { mem::transmute(*self) })
} else {
None
Expand All @@ -1575,14 +1563,14 @@ macro_rules! nop_lift {
}

macro_rules! nop_list_lift {
($ty:ty => $lifted:ty) => {
($set:ident; $ty:ty => $lifted:ty) => {
impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
type Lifted = &'tcx List<$lifted>;
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
if self.is_empty() {
return Some(List::empty());
}
if tcx.interners.arena.in_arena(*self as *const _) {
if tcx.interners.$set.contains_pointer_to(&Interned(*self)) {
Some(unsafe { mem::transmute(*self) })
} else {
None
Expand All @@ -1592,21 +1580,21 @@ macro_rules! nop_list_lift {
};
}

nop_lift! {Ty<'a> => Ty<'tcx>}
nop_lift! {Region<'a> => Region<'tcx>}
nop_lift! {Goal<'a> => Goal<'tcx>}
nop_lift! {&'a Const<'a> => &'tcx Const<'tcx>}
nop_lift! {type_; Ty<'a> => Ty<'tcx>}
nop_lift! {region; Region<'a> => Region<'tcx>}
nop_lift! {goal; Goal<'a> => Goal<'tcx>}
nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}

nop_list_lift! {Goal<'a> => Goal<'tcx>}
nop_list_lift! {Clause<'a> => Clause<'tcx>}
nop_list_lift! {Ty<'a> => Ty<'tcx>}
nop_list_lift! {ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
nop_list_lift! {Predicate<'a> => Predicate<'tcx>}
nop_list_lift! {CanonicalVarInfo => CanonicalVarInfo}
nop_list_lift! {ProjectionKind => ProjectionKind}
nop_list_lift! {goal_list; Goal<'a> => Goal<'tcx>}
nop_list_lift! {clauses; Clause<'a> => Clause<'tcx>}
nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
nop_list_lift! {existential_predicates; ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
nop_list_lift! {canonical_var_infos; CanonicalVarInfo => CanonicalVarInfo}
nop_list_lift! {projs; ProjectionKind => ProjectionKind}

// This is the impl for `&'a InternalSubsts<'a>`.
nop_list_lift! {GenericArg<'a> => GenericArg<'tcx>}
nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}

pub mod tls {
use super::{ptr_eq, GlobalCtxt, TyCtxt};
Expand Down Expand Up @@ -1930,6 +1918,11 @@ impl<'tcx, T: 'tcx + ?Sized> Clone for Interned<'tcx, T> {
}
impl<'tcx, T: 'tcx + ?Sized> Copy for Interned<'tcx, T> {}

impl<'tcx, T: 'tcx + ?Sized> IntoPointer for Interned<'tcx, T> {
fn into_pointer(&self) -> *const () {
self.0 as *const _ as *const ()
}
}
// N.B., an `Interned<Ty>` compares and hashes as a `TyKind`.
impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> {
fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool {
Expand Down Expand Up @@ -2082,7 +2075,7 @@ macro_rules! slice_interners {
$(impl<'tcx> TyCtxt<'tcx> {
pub fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
self.interners.$field.intern_ref(v, || {
Interned(List::from_arena(&self.interners.arena, v))
Interned(List::from_arena(&*self.arena, v))
}).0
}
})+
Expand Down
10 changes: 6 additions & 4 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub use self::BorrowKind::*;
pub use self::IntVarValue::*;
pub use self::Variance::*;

use crate::arena::Arena;
use crate::hir::exports::ExportMap;
use crate::hir::map as hir_map;

Expand All @@ -26,7 +27,6 @@ use crate::ty::layout::VariantIdx;
use crate::ty::subst::{InternalSubsts, Subst, SubstsRef};
use crate::ty::util::{Discr, IntTypeExt};
use crate::ty::walk::TypeWalker;
use arena::SyncDroplessArena;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::FxIndexMap;
Expand Down Expand Up @@ -76,7 +76,7 @@ pub use crate::ty::diagnostics::*;
pub use self::binding::BindingMode;
pub use self::binding::BindingMode::*;

pub use self::context::{keep_local, tls, AllArenas, FreeRegionInfo, TyCtxt};
pub use self::context::{keep_local, tls, FreeRegionInfo, TyCtxt};
pub use self::context::{
CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, ResolvedOpaqueTy,
UserType, UserTypeAnnotationIndex,
Expand Down Expand Up @@ -606,7 +606,7 @@ unsafe impl<T: Sync> Sync for List<T> {}

impl<T: Copy> List<T> {
#[inline]
fn from_arena<'tcx>(arena: &'tcx SyncDroplessArena, slice: &[T]) -> &'tcx List<T> {
fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List<T> {
assert!(!mem::needs_drop::<T>());
assert!(mem::size_of::<T>() != 0);
assert!(slice.len() != 0);
Expand All @@ -619,7 +619,9 @@ impl<T: Copy> List<T> {

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

let mem = arena.alloc_raw(size, cmp::max(mem::align_of::<T>(), mem::align_of::<usize>()));
let mem = arena
.dropless
.alloc_raw(size, cmp::max(mem::align_of::<T>(), mem::align_of::<usize>()));
unsafe {
let result = &mut *(mem.as_mut_ptr() as *mut List<T>);
// Write the length
Expand Down
14 changes: 14 additions & 0 deletions src/librustc_data_structures/sharded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,20 @@ impl<K: Eq + Hash + Copy> ShardedHashMap<K, ()> {
}
}

pub trait IntoPointer {
/// Returns a pointer which outlives `self`.
fn into_pointer(&self) -> *const ();
}

impl<K: Eq + Hash + Copy + IntoPointer> ShardedHashMap<K, ()> {
pub fn contains_pointer_to<T: Hash + IntoPointer>(&self, value: &T) -> bool {
let hash = make_hash(&value);
let shard = self.get_shard_by_hash(hash).lock();
let value = value.into_pointer();
shard.raw_entry().from_hash(hash, |entry| entry.into_pointer() == value).is_some()
}
}

#[inline]
fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
let mut state = FxHasher::default();
Expand Down
4 changes: 1 addition & 3 deletions src/librustc_interface/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use rustc::session::search_paths::PathKind;
use rustc::session::Session;
use rustc::traits;
use rustc::ty::steal::Steal;
use rustc::ty::{self, AllArenas, GlobalCtxt, ResolverOutputs, TyCtxt};
use rustc::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt};
use rustc::util::common::ErrorReported;
use rustc_builtin_macros;
use rustc_codegen_ssa::back::link::emit_metadata;
Expand Down Expand Up @@ -711,7 +711,6 @@ pub fn create_global_ctxt<'tcx>(
outputs: OutputFilenames,
crate_name: &str,
global_ctxt: &'tcx Once<GlobalCtxt<'tcx>>,
all_arenas: &'tcx AllArenas,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
) -> QueryContext<'tcx> {
let sess = &compiler.session();
Expand Down Expand Up @@ -742,7 +741,6 @@ pub fn create_global_ctxt<'tcx>(
lint_store,
local_providers,
extern_providers,
&all_arenas,
arena,
resolver_outputs,
hir_map,
Expand Down
5 changes: 1 addition & 4 deletions src/librustc_interface/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc::lint::LintStore;
use rustc::session::config::{OutputFilenames, OutputType};
use rustc::session::Session;
use rustc::ty::steal::Steal;
use rustc::ty::{AllArenas, GlobalCtxt, ResolverOutputs};
use rustc::ty::{GlobalCtxt, ResolverOutputs};
use rustc::util::common::ErrorReported;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_data_structures::sync::{Lrc, Once, WorkerLocal};
Expand Down Expand Up @@ -67,7 +67,6 @@ pub struct Queries<'tcx> {
compiler: &'tcx Compiler,
gcx: Once<GlobalCtxt<'tcx>>,

all_arenas: AllArenas,
arena: WorkerLocal<Arena<'tcx>>,

dep_graph_future: Query<Option<DepGraphFuture>>,
Expand All @@ -87,7 +86,6 @@ impl<'tcx> Queries<'tcx> {
Queries {
compiler,
gcx: Once::new(),
all_arenas: AllArenas::new(),
arena: WorkerLocal::new(|_| Arena::default()),
dep_graph_future: Default::default(),
parse: Default::default(),
Expand Down Expand Up @@ -266,7 +264,6 @@ impl<'tcx> Queries<'tcx> {
outputs,
&crate_name,
&self.gcx,
&self.all_arenas,
&self.arena,
))
})
Expand Down
Loading