Skip to content

Commit 7120ef3

Browse files
committed
Introduce an arena type which may be used to allocate a list of types with destructors
1 parent 0ddf7ac commit 7120ef3

File tree

11 files changed

+167
-21
lines changed

11 files changed

+167
-21
lines changed

src/librustc/arena.rs

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use arena::{TypedArena, DroplessArena};
2+
3+
#[macro_export]
4+
macro_rules! arena_types {
5+
($macro:path, $args:tt, $tcx:lifetime) => (
6+
$macro!($args, [
7+
[] vtable_method: Option<(
8+
rustc::hir::def_id::DefId,
9+
rustc::ty::subst::SubstsRef<$tcx>
10+
)>,
11+
[decode] specialization_graph: rustc::traits::specialization_graph::Graph,
12+
], $tcx);
13+
)
14+
}
15+
16+
macro_rules! declare_arena {
17+
([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
18+
#[derive(Default)]
19+
pub struct Arena<$tcx> {
20+
dropless: DroplessArena,
21+
$($name: TypedArena<$ty>,)*
22+
}
23+
}
24+
}
25+
26+
macro_rules! impl_specialized_decodable {
27+
([decode] $ty:ty, $tcx:lifetime) => {
28+
impl<$tcx> serialize::UseSpecializedDecodable for &$tcx $ty {}
29+
};
30+
([] $ty:ty, $tcx:lifetime) => {};
31+
}
32+
33+
macro_rules! impl_arena_allocatable {
34+
([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
35+
$(
36+
impl_specialized_decodable!($a $ty, $tcx);
37+
38+
impl<$tcx> ArenaAllocatable<$tcx> for $ty {
39+
#[inline]
40+
fn arena<'a>(arena: &'a Arena<$tcx>) -> Option<&'a TypedArena<Self>> {
41+
Some(&arena.$name)
42+
}
43+
}
44+
)*
45+
}
46+
}
47+
48+
arena_types!(declare_arena, [], 'tcx);
49+
50+
arena_types!(impl_arena_allocatable, [], 'tcx);
51+
52+
pub trait ArenaAllocatable<'tcx>: Sized {
53+
/// Returns a specific arena to allocate from if the type requires destructors.
54+
/// Otherwise it will return `None` to be allocated from the dropless arena.
55+
fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a TypedArena<Self>>;
56+
}
57+
58+
impl<'tcx, T: Copy> ArenaAllocatable<'tcx> for T {
59+
#[inline]
60+
default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a TypedArena<Self>> {
61+
None
62+
}
63+
}
64+
65+
impl<'tcx> Arena<'tcx> {
66+
#[inline]
67+
pub fn alloc<T: ArenaAllocatable<'tcx>>(&self, value: T) -> &mut T {
68+
match T::arena(self) {
69+
Some(arena) => {
70+
arena.alloc(value)
71+
}
72+
None => {
73+
self.dropless.alloc(value)
74+
}
75+
}
76+
}
77+
78+
pub fn alloc_from_iter<
79+
T: ArenaAllocatable<'tcx>,
80+
I: IntoIterator<Item = T>
81+
>(
82+
&self,
83+
iter: I
84+
) -> &mut [T] {
85+
match T::arena(self) {
86+
Some(arena) => {
87+
arena.alloc_from_iter(iter)
88+
}
89+
None => {
90+
self.dropless.alloc_from_iter(iter)
91+
}
92+
}
93+
}
94+
}

src/librustc/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ pub mod diagnostics;
103103
#[macro_use]
104104
pub mod query;
105105

106+
#[macro_use]
107+
pub mod arena;
106108
pub mod cfg;
107109
pub mod dep_graph;
108110
pub mod hir;

src/librustc/query/mod.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ rustc_queries! {
516516

517517
Other {
518518
query vtable_methods(key: ty::PolyTraitRef<'tcx>)
519-
-> Lrc<Vec<Option<(DefId, SubstsRef<'tcx>)>>> {
519+
-> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] {
520520
no_force
521521
desc { |tcx| "finding all methods for trait {}", tcx.def_path_str(key.def_id()) }
522522
}
@@ -539,8 +539,7 @@ rustc_queries! {
539539
query trait_impls_of(key: DefId) -> Lrc<ty::trait_def::TraitImpls> {
540540
desc { |tcx| "trait impls of `{}`", tcx.def_path_str(key) }
541541
}
542-
query specialization_graph_of(_: DefId)
543-
-> Lrc<specialization_graph::Graph> {}
542+
query specialization_graph_of(_: DefId) -> &'tcx specialization_graph::Graph {}
544543
query is_object_safe(key: DefId) -> bool {
545544
desc { |tcx| "determine object safety of trait `{}`", tcx.def_path_str(key) }
546545
}

src/librustc/traits/mod.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ use crate::infer::{InferCtxt, SuppressRegionErrors};
2626
use crate::infer::outlives::env::OutlivesEnvironment;
2727
use crate::middle::region;
2828
use crate::mir::interpret::ErrorHandled;
29-
use rustc_data_structures::sync::Lrc;
3029
use rustc_macros::HashStable;
3130
use syntax::ast;
3231
use syntax_pos::{Span, DUMMY_SP};
@@ -984,11 +983,11 @@ fn substitute_normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
984983
fn vtable_methods<'a, 'tcx>(
985984
tcx: TyCtxt<'a, 'tcx, 'tcx>,
986985
trait_ref: ty::PolyTraitRef<'tcx>)
987-
-> Lrc<Vec<Option<(DefId, SubstsRef<'tcx>)>>>
986+
-> &'tcx [Option<(DefId, SubstsRef<'tcx>)>]
988987
{
989988
debug!("vtable_methods({:?})", trait_ref);
990989

991-
Lrc::new(
990+
tcx.arena.alloc_from_iter(
992991
supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
993992
let trait_methods = tcx.associated_items(trait_ref.def_id())
994993
.filter(|item| item.kind == ty::AssociatedKind::Method);
@@ -1039,7 +1038,7 @@ fn vtable_methods<'a, 'tcx>(
10391038

10401039
Some((def_id, substs))
10411040
})
1042-
}).collect()
1041+
})
10431042
)
10441043
}
10451044

src/librustc/traits/specialize/mod.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use crate::infer::{InferCtxt, InferOk};
1616
use crate::lint;
1717
use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
1818
use rustc_data_structures::fx::FxHashSet;
19-
use rustc_data_structures::sync::Lrc;
2019
use syntax_pos::DUMMY_SP;
2120
use crate::traits::select::IntercrateAmbiguityCause;
2221
use crate::ty::{self, TyCtxt, TypeFoldable};
@@ -289,7 +288,7 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
289288
pub(super) fn specialization_graph_provider<'a, 'tcx>(
290289
tcx: TyCtxt<'a, 'tcx, 'tcx>,
291290
trait_id: DefId,
292-
) -> Lrc<specialization_graph::Graph> {
291+
) -> &'tcx specialization_graph::Graph {
293292
let mut sg = specialization_graph::Graph::new();
294293

295294
let mut trait_impls = tcx.all_impls(trait_id);
@@ -383,7 +382,7 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(
383382
}
384383
}
385384

386-
Lrc::new(sg)
385+
tcx.arena.alloc(sg)
387386
}
388387

389388
/// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a

src/librustc/traits/specialize/specialization_graph.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
77
use crate::traits;
88
use crate::ty::{self, TyCtxt, TypeFoldable};
99
use crate::ty::fast_reject::{self, SimplifiedType};
10-
use rustc_data_structures::sync::Lrc;
1110
use syntax::ast::Ident;
1211
use crate::util::captures::Captures;
1312
use crate::util::nodemap::{DefIdMap, FxHashMap};
@@ -439,13 +438,13 @@ impl<'a, 'gcx, 'tcx> Node {
439438
}
440439
}
441440

442-
pub struct Ancestors {
441+
pub struct Ancestors<'tcx> {
443442
trait_def_id: DefId,
444-
specialization_graph: Lrc<Graph>,
443+
specialization_graph: &'tcx Graph,
445444
current_source: Option<Node>,
446445
}
447446

448-
impl Iterator for Ancestors {
447+
impl Iterator for Ancestors<'_> {
449448
type Item = Node;
450449
fn next(&mut self) -> Option<Node> {
451450
let cur = self.current_source.take();
@@ -476,7 +475,7 @@ impl<T> NodeItem<T> {
476475
}
477476
}
478477

479-
impl<'a, 'gcx, 'tcx> Ancestors {
478+
impl<'a, 'gcx, 'tcx> Ancestors<'gcx> {
480479
/// Search the items from the given ancestors, returning each definition
481480
/// with the given name and the given kind.
482481
// FIXME(#35870): avoid closures being unexported due to `impl Trait`.
@@ -509,10 +508,10 @@ impl<'a, 'gcx, 'tcx> Ancestors {
509508

510509
/// Walk up the specialization ancestors of a given impl, starting with that
511510
/// impl itself.
512-
pub fn ancestors(tcx: TyCtxt<'_, '_, '_>,
511+
pub fn ancestors(tcx: TyCtxt<'_, 'tcx, '_>,
513512
trait_def_id: DefId,
514513
start_from_impl: DefId)
515-
-> Ancestors {
514+
-> Ancestors<'tcx> {
516515
let specialization_graph = tcx.specialization_graph_of(trait_def_id);
517516
Ancestors {
518517
trait_def_id,

src/librustc/ty/codec.rs

+52
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// The functionality in here is shared between persisting to crate metadata and
77
// persisting to incr. comp. caches.
88

9+
use crate::arena::ArenaAllocatable;
910
use crate::hir::def_id::{DefId, CrateNum};
1011
use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
1112
use rustc_data_structures::fx::FxHashMap;
@@ -130,6 +131,26 @@ pub trait TyDecoder<'a, 'tcx: 'a>: Decoder {
130131
}
131132
}
132133

134+
#[inline]
135+
pub fn decode_arena_allocable<'a, 'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
136+
decoder: &mut D
137+
) -> Result<&'tcx T, D::Error>
138+
where D: TyDecoder<'a, 'tcx>,
139+
'tcx: 'a,
140+
{
141+
Ok(decoder.tcx().arena.alloc(Decodable::decode(decoder)?))
142+
}
143+
144+
#[inline]
145+
pub fn decode_arena_allocable_slice<'a, 'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
146+
decoder: &mut D
147+
) -> Result<&'tcx [T], D::Error>
148+
where D: TyDecoder<'a, 'tcx>,
149+
'tcx: 'a,
150+
{
151+
Ok(decoder.tcx().arena.alloc_from_iter(<Vec<T> as Decodable>::decode(decoder)?))
152+
}
153+
133154
#[inline]
134155
pub fn decode_cnum<'a, 'tcx, D>(decoder: &mut D) -> Result<CrateNum, D::Error>
135156
where D: TyDecoder<'a, 'tcx>,
@@ -273,6 +294,35 @@ macro_rules! __impl_decoder_methods {
273294
}
274295
}
275296

297+
#[macro_export]
298+
macro_rules! impl_arena_allocatable_decoder {
299+
([$DecoderName:ident [$($typaram:tt),*]], [[decode] $name:ident: $ty:ty], $tcx:lifetime) => {
300+
impl<$($typaram),*> SpecializedDecoder<&$tcx $ty> for $DecoderName<$($typaram),*> {
301+
#[inline]
302+
fn specialized_decode(&mut self) -> Result<&$tcx $ty, Self::Error> {
303+
decode_arena_allocable(self)
304+
}
305+
}
306+
307+
impl<$($typaram),*> SpecializedDecoder<&$tcx [$ty]> for $DecoderName<$($typaram),*> {
308+
#[inline]
309+
fn specialized_decode(&mut self) -> Result<&$tcx [$ty], Self::Error> {
310+
decode_arena_allocable_slice(self)
311+
}
312+
}
313+
};
314+
([$DecoderName:ident [$($typaram:tt),*]], [[] $name:ident: $ty:ty], $tcx:lifetime) => {};
315+
}
316+
317+
#[macro_export]
318+
macro_rules! impl_arena_allocatable_decoders {
319+
($args:tt, [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
320+
$(
321+
impl_arena_allocatable_decoder!($args, [$a $name: $ty], $tcx);
322+
)*
323+
}
324+
}
325+
276326
#[macro_export]
277327
macro_rules! implement_ty_decoder {
278328
($DecoderName:ident <$($typaram:tt),*>) => {
@@ -322,6 +372,8 @@ macro_rules! implement_ty_decoder {
322372
// the caller to pick any lifetime for 'tcx, including 'static,
323373
// by using the unspecialized proxies to them.
324374

375+
arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
376+
325377
impl<$($typaram),*> SpecializedDecoder<CrateNum>
326378
for $DecoderName<$($typaram),*> {
327379
fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {

src/librustc/ty/context.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Type context book-keeping.
22
3+
use crate::arena::Arena;
34
use crate::dep_graph::DepGraph;
45
use crate::dep_graph::{self, DepNode, DepConstructor};
56
use crate::session::Session;
@@ -996,6 +997,7 @@ impl<'gcx> Deref for TyCtxt<'_, 'gcx, '_> {
996997
}
997998

998999
pub struct GlobalCtxt<'tcx> {
1000+
pub arena: WorkerLocal<Arena<'tcx>>,
9991001
global_arenas: &'tcx WorkerLocal<GlobalArenas<'tcx>>,
10001002
global_interners: CtxtInterners<'tcx>,
10011003

@@ -1255,6 +1257,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
12551257
GlobalCtxt {
12561258
sess: s,
12571259
cstore,
1260+
arena: WorkerLocal::new(|_| Arena::default()),
12581261
global_arenas: &arenas.global,
12591262
global_interners: interners,
12601263
dep_graph,

src/librustc/ty/trait_def.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl<'a, 'gcx, 'tcx> TraitDef {
6767

6868
pub fn ancestors(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
6969
of_impl: DefId)
70-
-> specialization_graph::Ancestors {
70+
-> specialization_graph::Ancestors<'gcx> {
7171
specialization_graph::ancestors(tcx, self.def_id, of_impl)
7272
}
7373
}

src/librustc_mir/interpret/traits.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use rustc_data_structures::sync::Lrc;
21
use rustc::ty::{self, Ty};
32
use rustc::ty::layout::{Size, Align, LayoutOf};
43
use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic};
@@ -35,7 +34,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
3534

3635
self.tcx.vtable_methods(trait_ref)
3736
} else {
38-
Lrc::new(Vec::new())
37+
&[]
3938
};
4039

4140
let layout = self.layout_of(ty)?;

src/libserialize/serialize.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -911,4 +911,4 @@ impl<T: UseSpecializedDecodable> Decodable for T {
911911
impl<'a, T: ?Sized + Encodable> UseSpecializedEncodable for &'a T {}
912912
impl<T: ?Sized + Encodable> UseSpecializedEncodable for Box<T> {}
913913
impl<T: Decodable> UseSpecializedDecodable for Box<T> {}
914-
914+
impl<'a, T: ?Sized + Decodable> UseSpecializedDecodable for &'a [T] {}

0 commit comments

Comments
 (0)