Skip to content

Commit 63ac4af

Browse files
committed
Auto merge of #56382 - Zoxc:arena-drops, r=<try>
Promote types which allocate to an arena to avoid the use of Lrc
2 parents d48ab69 + b207b8e commit 63ac4af

File tree

33 files changed

+340
-101
lines changed

33 files changed

+340
-101
lines changed

src/libarena/lib.rs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,18 @@
3535
extern crate alloc;
3636
extern crate rustc_data_structures;
3737

38-
use rustc_data_structures::sync::MTLock;
38+
use rustc_data_structures::OnDrop;
39+
use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs};
40+
use rustc_data_structures::sync::{MTLock, WorkerLocal};
3941

42+
use std::process;
4043
use std::cell::{Cell, RefCell};
4144
use std::cmp;
4245
use std::intrinsics;
4346
use std::marker::{PhantomData, Send};
4447
use std::mem;
4548
use std::ptr;
4649
use std::slice;
47-
4850
use alloc::raw_vec::RawVec;
4951

5052
/// An arena that can hold objects of only one type.
@@ -450,12 +452,20 @@ impl<T> SyncTypedArena<T> {
450452
}
451453
}
452454

453-
#[derive(Default)]
454455
pub struct SyncDroplessArena {
455456
lock: MTLock<DroplessArena>,
457+
deferred: WorkerLocal<RefCell<DeferredDeallocs>>,
456458
}
457459

458460
impl SyncDroplessArena {
461+
#[inline]
462+
pub fn new() -> Self {
463+
SyncDroplessArena {
464+
lock: Default::default(),
465+
deferred: WorkerLocal::new(|_| Default::default()),
466+
}
467+
}
468+
459469
#[inline(always)]
460470
pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
461471
self.lock.lock().in_arena(ptr)
@@ -481,6 +491,39 @@ impl SyncDroplessArena {
481491
// Extend the lifetime of the result since it's limited to the lock guard
482492
unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) }
483493
}
494+
495+
#[inline]
496+
pub fn promote<T: DeferDeallocs>(&self, object: T) -> &T {
497+
let mem = self.alloc_raw(mem::size_of::<T>(), mem::align_of::<T>()) as *mut _ as *mut T;
498+
499+
{
500+
// Abort the process if we panic here to ensure that we don't both
501+
// record and allocation and also destroy object, resulting in a double free
502+
let abort = OnDrop(|| process::abort());
503+
504+
// Defer the allocations
505+
object.defer(&mut *self.deferred.borrow_mut());
506+
507+
mem::forget(abort);
508+
}
509+
510+
unsafe {
511+
// Write into uninitialized memory.
512+
ptr::write(mem, object);
513+
&mut *mem
514+
}
515+
}
516+
517+
#[inline(always)]
518+
pub fn promote_vec<T: DeferDeallocs>(&self, vec: Vec<T>) -> &[T] {
519+
// Defer the allocations
520+
vec.defer(&mut *self.deferred.borrow_mut());
521+
522+
// Then just return the slice
523+
let result = &vec[..] as *const [T];
524+
mem::forget(vec);
525+
unsafe { &*result }
526+
}
484527
}
485528

486529
#[cfg(test)]

src/librustc/hir/def_id.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ pub struct DefId {
223223
pub index: DefIndex,
224224
}
225225

226+
impl_defer_dellocs_for_no_drop_type!([] DefId);
227+
226228
impl fmt::Debug for DefId {
227229
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228230
write!(f, "DefId({}/{}:{}",

src/librustc/hir/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ mod item_local_id_inner {
135135
}
136136
}
137137

138+
impl_defer_dellocs_for_no_drop_type!([] ItemLocalId);
139+
138140
pub use self::item_local_id_inner::ItemLocalId;
139141

140142
/// The `HirId` corresponding to CRATE_NODE_ID and CRATE_DEF_INDEX
@@ -1269,6 +1271,8 @@ pub struct BodyId {
12691271
pub node_id: NodeId,
12701272
}
12711273

1274+
impl_defer_dellocs_for_no_drop_type!([] BodyId);
1275+
12721276
/// The body of a function, closure, or constant value. In the case of
12731277
/// a function, the body contains not only the function body itself
12741278
/// (which is an expression), but also the argument patterns, since

src/librustc/ich/impls_ty.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -847,16 +847,12 @@ impl_stable_hash_for!(struct ty::Destructor {
847847
did
848848
});
849849

850-
impl_stable_hash_for!(struct ty::CrateVariancesMap {
850+
impl_stable_hash_for!(struct ty::CrateVariancesMap<'tcx> {
851851
variances,
852-
// This is just an irrelevant helper value.
853-
empty_variance -> _,
854852
});
855853

856854
impl_stable_hash_for!(struct ty::CratePredicatesMap<'tcx> {
857855
predicates,
858-
// This is just an irrelevant helper value.
859-
empty_predicate -> _,
860856
});
861857

862858
impl_stable_hash_for!(struct ty::AssociatedItem {

src/librustc/infer/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
478478
pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
479479
InferCtxtBuilder {
480480
global_tcx: self,
481-
arena: SyncDroplessArena::default(),
481+
arena: SyncDroplessArena::new(),
482482
fresh_tables: None,
483483
}
484484
}

src/librustc/middle/expr_use_visitor.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ use middle::region;
2727
use ty::{self, TyCtxt, adjustment};
2828

2929
use hir::{self, PatKind};
30-
use rustc_data_structures::sync::Lrc;
3130
use std::rc::Rc;
3231
use syntax::ast;
3332
use syntax::ptr::P;
@@ -280,7 +279,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> {
280279
param_env: ty::ParamEnv<'tcx>,
281280
region_scope_tree: &'a region::ScopeTree,
282281
tables: &'a ty::TypeckTables<'tcx>,
283-
rvalue_promotable_map: Option<Lrc<ItemLocalSet>>)
282+
rvalue_promotable_map: Option<&'tcx ItemLocalSet>)
284283
-> Self
285284
{
286285
ExprUseVisitor {

src/librustc/middle/mem_categorization.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ use syntax_pos::Span;
8787
use std::borrow::Cow;
8888
use std::fmt;
8989
use std::hash::{Hash, Hasher};
90-
use rustc_data_structures::sync::Lrc;
9190
use rustc_data_structures::indexed_vec::Idx;
9291
use std::rc::Rc;
9392
use util::nodemap::ItemLocalSet;
@@ -300,7 +299,7 @@ pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
300299
pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
301300
pub region_scope_tree: &'a region::ScopeTree,
302301
pub tables: &'a ty::TypeckTables<'tcx>,
303-
rvalue_promotable_map: Option<Lrc<ItemLocalSet>>,
302+
rvalue_promotable_map: Option<&'tcx ItemLocalSet>,
304303
infcx: Option<&'a InferCtxt<'a, 'gcx, 'tcx>>,
305304
}
306305

@@ -410,7 +409,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> {
410409
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
411410
region_scope_tree: &'a region::ScopeTree,
412411
tables: &'a ty::TypeckTables<'tcx>,
413-
rvalue_promotable_map: Option<Lrc<ItemLocalSet>>)
412+
rvalue_promotable_map: Option<&'tcx ItemLocalSet>)
414413
-> MemCategorizationContext<'a, 'tcx, 'tcx> {
415414
MemCategorizationContext {
416415
tcx,

src/librustc/middle/region.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ use ty;
2222

2323
use std::mem;
2424
use std::fmt;
25-
use rustc_data_structures::sync::Lrc;
2625
use syntax::source_map;
2726
use syntax::ast;
2827
use syntax_pos::{Span, DUMMY_SP};
@@ -34,6 +33,7 @@ use hir::Node;
3433
use hir::def_id::DefId;
3534
use hir::intravisit::{self, Visitor, NestedVisitorMap};
3635
use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local};
36+
use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs};
3737
use rustc_data_structures::indexed_vec::Idx;
3838
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
3939
StableHasherResult};
@@ -106,6 +106,8 @@ pub struct Scope {
106106
pub data: ScopeData,
107107
}
108108

109+
impl_defer_dellocs_for_no_drop_type!([] Scope);
110+
109111
impl fmt::Debug for Scope {
110112
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
111113
match self.data {
@@ -349,6 +351,18 @@ pub struct ScopeTree {
349351
body_expr_count: FxHashMap<hir::BodyId, usize>,
350352
}
351353

354+
unsafe impl DeferDeallocs for ScopeTree {
355+
fn defer(&self, deferred: &mut DeferredDeallocs) {
356+
self.parent_map.defer(deferred);
357+
self.var_map.defer(deferred);
358+
self.destruction_scopes.defer(deferred);
359+
self.rvalue_scopes.defer(deferred);
360+
self.closure_tree.defer(deferred);
361+
self.yield_in_scope.defer(deferred);
362+
self.body_expr_count.defer(deferred);
363+
}
364+
}
365+
352366
#[derive(Debug, Copy, Clone)]
353367
pub struct Context {
354368
/// the root of the current region tree. This is typically the id
@@ -1329,7 +1343,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> {
13291343
}
13301344

13311345
fn region_scope_tree<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
1332-
-> Lrc<ScopeTree>
1346+
-> &'tcx ScopeTree
13331347
{
13341348
let closure_base_def_id = tcx.closure_base_def_id(def_id);
13351349
if closure_base_def_id != def_id {
@@ -1371,7 +1385,7 @@ fn region_scope_tree<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
13711385
ScopeTree::default()
13721386
};
13731387

1374-
Lrc::new(scope_tree)
1388+
tcx.promote(scope_tree)
13751389
}
13761390

13771391
pub fn provide(providers: &mut Providers<'_>) {

src/librustc/traits/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ use ty::fold::{TypeFolder, TypeFoldable, TypeVisitor};
3131
use infer::{InferCtxt};
3232
use util::common::ErrorReported;
3333

34-
use rustc_data_structures::sync::Lrc;
3534
use std::fmt::Debug;
3635
use std::rc::Rc;
3736
use syntax::ast;
@@ -959,11 +958,11 @@ fn substitute_normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
959958
fn vtable_methods<'a, 'tcx>(
960959
tcx: TyCtxt<'a, 'tcx, 'tcx>,
961960
trait_ref: ty::PolyTraitRef<'tcx>)
962-
-> Lrc<Vec<Option<(DefId, &'tcx Substs<'tcx>)>>>
961+
-> &'tcx [Option<(DefId, &'tcx Substs<'tcx>)>]
963962
{
964963
debug!("vtable_methods({:?})", trait_ref);
965964

966-
Lrc::new(
965+
tcx.promote_vec(
967966
supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
968967
let trait_methods = tcx.associated_items(trait_ref.def_id())
969968
.filter(|item| item.kind == ty::AssociatedKind::Method);

src/librustc/ty/context.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ use ty::CanonicalPolyFnSig;
5454
use util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap};
5555
use util::nodemap::{FxHashMap, FxHashSet};
5656
use smallvec::SmallVec;
57+
use rustc_data_structures::defer_deallocs::DeferDeallocs;
5758
use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
5859
StableHasher, StableHasherResult,
5960
StableVec};
@@ -91,7 +92,7 @@ impl<'tcx> AllArenas<'tcx> {
9192
pub fn new() -> Self {
9293
AllArenas {
9394
global: WorkerLocal::new(|_| GlobalArenas::default()),
94-
interner: SyncDroplessArena::default(),
95+
interner: SyncDroplessArena::new(),
9596
}
9697
}
9798
}
@@ -980,6 +981,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
980981
}
981982
}
982983

984+
#[inline(always)]
985+
pub fn promote<T: DeferDeallocs>(&self, object: T) -> &'gcx T {
986+
self.gcx.global_interners.arena.promote(object)
987+
}
988+
989+
#[inline(always)]
990+
pub fn promote_vec<T: DeferDeallocs>(&self, vec: Vec<T>) -> &'gcx [T] {
991+
self.gcx.global_interners.arena.promote_vec(vec)
992+
}
993+
983994
pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics {
984995
self.global_arenas.generics.alloc(generics)
985996
}

src/librustc/ty/mod.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ use syntax::symbol::{keywords, Symbol, LocalInternedString, InternedString};
5757
use syntax_pos::{DUMMY_SP, Span};
5858

5959
use smallvec;
60+
use rustc_data_structures::defer_deallocs::{DeferredDeallocs, DeferDeallocs};
6061
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
6162
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
6263
HashStable};
@@ -338,20 +339,19 @@ pub enum Variance {
338339
Bivariant, // T<A> <: T<B> -- e.g., unused type parameter
339340
}
340341

342+
impl_defer_dellocs_for_no_drop_type!([] Variance);
343+
341344
/// The crate variances map is computed during typeck and contains the
342345
/// variance of every item in the local crate. You should not use it
343346
/// directly, because to do so will make your pass dependent on the
344347
/// HIR of every item in the local crate. Instead, use
345348
/// `tcx.variances_of()` to get the variance for a *particular*
346349
/// item.
347-
pub struct CrateVariancesMap {
350+
pub struct CrateVariancesMap<'tcx> {
348351
/// For each item with generics, maps to a vector of the variance
349352
/// of its generics. If an item has no generics, it will have no
350353
/// entry.
351-
pub variances: FxHashMap<DefId, Lrc<Vec<ty::Variance>>>,
352-
353-
/// An empty vector, useful for cloning.
354-
pub empty_variance: Lrc<Vec<ty::Variance>>,
354+
pub variances: FxHashMap<DefId, &'tcx [ty::Variance]>,
355355
}
356356

357357
impl Variance {
@@ -1087,6 +1087,8 @@ pub enum Predicate<'tcx> {
10871087
ConstEvaluatable(DefId, &'tcx Substs<'tcx>),
10881088
}
10891089

1090+
impl_defer_dellocs_for_no_drop_type!([<'tcx>] Predicate<'tcx>);
1091+
10901092
/// The crate outlives map is computed during typeck and contains the
10911093
/// outlives of every item in the local crate. You should not use it
10921094
/// directly, because to do so will make your pass dependent on the
@@ -1097,10 +1099,7 @@ pub struct CratePredicatesMap<'tcx> {
10971099
/// For each struct with outlive bounds, maps to a vector of the
10981100
/// predicate of its outlive bounds. If an item has no outlives
10991101
/// bounds, it will have no entry.
1100-
pub predicates: FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
1101-
1102-
/// An empty vector, useful for cloning.
1103-
pub empty_predicate: Lrc<Vec<ty::Predicate<'tcx>>>,
1102+
pub predicates: FxHashMap<DefId, &'tcx [ty::Predicate<'tcx>]>,
11041103
}
11051104

11061105
impl<'tcx> AsRef<Predicate<'tcx>> for Predicate<'tcx> {
@@ -2957,7 +2956,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
29572956

29582957
pub struct AssociatedItemsIterator<'a, 'gcx: 'tcx, 'tcx: 'a> {
29592958
tcx: TyCtxt<'a, 'gcx, 'tcx>,
2960-
def_ids: Lrc<Vec<DefId>>,
2959+
def_ids: &'gcx [DefId],
29612960
next_index: usize,
29622961
}
29632962

@@ -3043,7 +3042,7 @@ fn adt_sized_constraint<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
30433042

30443043
fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
30453044
def_id: DefId)
3046-
-> Lrc<Vec<DefId>> {
3045+
-> &'tcx [DefId] {
30473046
let id = tcx.hir.as_local_node_id(def_id).unwrap();
30483047
let item = tcx.hir.expect_item(id);
30493048
let vec: Vec<_> = match item.node {
@@ -3062,7 +3061,7 @@ fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
30623061
hir::ItemKind::TraitAlias(..) => vec![],
30633062
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait")
30643063
};
3065-
Lrc::new(vec)
3064+
tcx.promote_vec(vec)
30663065
}
30673066

30683067
fn def_span<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Span {
@@ -3204,7 +3203,13 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
32043203
/// (constructing this map requires touching the entire crate).
32053204
#[derive(Clone, Debug, Default)]
32063205
pub struct CrateInherentImpls {
3207-
pub inherent_impls: DefIdMap<Lrc<Vec<DefId>>>,
3206+
pub inherent_impls: DefIdMap<Vec<DefId>>,
3207+
}
3208+
3209+
unsafe impl DeferDeallocs for CrateInherentImpls {
3210+
fn defer(&self, deferred: &mut DeferredDeallocs) {
3211+
self.inherent_impls.defer(deferred)
3212+
}
32083213
}
32093214

32103215
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]

0 commit comments

Comments
 (0)