Skip to content

Commit fd56196

Browse files
committed
Auto merge of #138705 - oli-obk:hir-split, r=<try>
[perf] Decouple directly accessing a HIR owner from ast lowering r? `@ghost` cc #95004
2 parents c360e21 + 0ddb721 commit fd56196

File tree

12 files changed

+119
-50
lines changed

12 files changed

+119
-50
lines changed

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
5454
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
5555
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
5656
use rustc_hir::{
57-
self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem,
58-
LifetimeSource, LifetimeSyntax, ParamName, TraitCandidate,
57+
self as hir, AngleBrackets, AttributeMap, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem,
58+
LifetimeSource, LifetimeSyntax, MaybeOwner, OwnerId, ParamName, TraitCandidate,
5959
};
6060
use rustc_index::{Idx, IndexSlice, IndexVec};
6161
use rustc_macros::extension;
@@ -429,7 +429,7 @@ fn compute_hir_hash(
429429
})
430430
}
431431

432-
pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
432+
pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate {
433433
let sess = tcx.sess;
434434
// Queries that borrow `resolver_for_lowering`.
435435
tcx.ensure_done().output_filenames(());
@@ -466,7 +466,27 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
466466
// Don't hash unless necessary, because it's expensive.
467467
let opt_hir_hash =
468468
if tcx.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None };
469-
hir::Crate { owners, opt_hir_hash }
469+
470+
for (def_id, owner) in owners.drain_enumerated(..) {
471+
let feed = tcx.super_duper_perf_hack_experiment(def_id);
472+
feed.hir_owner(owner);
473+
tcx.super_duper_perf_hack_experiment2(OwnerId { def_id }).hir_attr_map(
474+
match owner.as_owner() {
475+
Some(o) => &o.attrs,
476+
None => AttributeMap::EMPTY,
477+
},
478+
);
479+
feed.opt_hir_owner_nodes(owner.as_owner().map(|i| &i.nodes));
480+
match owner {
481+
MaybeOwner::Owner(_) => feed.local_def_id_to_hir_id(HirId::make_owner(def_id)),
482+
MaybeOwner::NonOwner(hir_id) => feed.local_def_id_to_hir_id(hir_id),
483+
MaybeOwner::Phantom => {}
484+
}
485+
tcx.super_duper_perf_hack_experiment2(OwnerId { def_id })
486+
.in_scope_traits_map(owner.as_owner().map(|owner_info| &owner_info.trait_map));
487+
}
488+
489+
hir::Crate { opt_hir_hash }
470490
}
471491

472492
#[derive(Copy, Clone, PartialEq, Debug)]

compiler/rustc_driver_impl/src/pretty.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,11 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
292292
}
293293
HirTree => {
294294
debug!("pretty printing HIR tree");
295-
format!("{:#?}", ex.tcx().hir_crate(()))
295+
let mut s = String::new();
296+
for id in ex.tcx().hir_crate_items(()).owners() {
297+
writeln!(&mut s, "{:#?}", ex.tcx().opt_hir_owner_nodes(id.def_id)).unwrap();
298+
}
299+
s
296300
}
297301
Mir => {
298302
let mut out = Vec::new();

compiler/rustc_hir/src/definitions.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ impl DefPathTable {
8888
DefPathHash::new(self.stable_crate_id, hash)
8989
}
9090

91+
pub fn def_keys(&self) -> impl Iterator<Item = DefIndex> + ExactSizeIterator {
92+
self.index_to_key.iter_enumerated().map(|(index, _)| index)
93+
}
94+
9195
pub fn enumerated_keys_and_path_hashes(
9296
&self,
9397
) -> impl Iterator<Item = (DefIndex, &DefKey, DefPathHash)> + ExactSizeIterator {

compiler/rustc_hir/src/hir.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,11 +1462,15 @@ pub struct AttributeMap<'tcx> {
14621462
}
14631463

14641464
impl<'tcx> AttributeMap<'tcx> {
1465-
pub const EMPTY: &'static AttributeMap<'static> = &AttributeMap {
1466-
map: SortedMap::new(),
1467-
opt_hash: Some(Fingerprint::ZERO),
1468-
define_opaque: None,
1469-
};
1465+
pub const EMPTY: &'static AttributeMap<'static> = &Self::empty();
1466+
1467+
pub const fn empty() -> AttributeMap<'static> {
1468+
AttributeMap {
1469+
map: SortedMap::new(),
1470+
opt_hash: Some(Fingerprint::ZERO),
1471+
define_opaque: None,
1472+
}
1473+
}
14701474

14711475
#[inline]
14721476
pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] {
@@ -1567,8 +1571,7 @@ impl<'tcx> MaybeOwner<'tcx> {
15671571
///
15681572
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
15691573
#[derive(Debug)]
1570-
pub struct Crate<'hir> {
1571-
pub owners: IndexVec<LocalDefId, MaybeOwner<'hir>>,
1574+
pub struct Crate {
15721575
// Only present when incr. comp. is enabled.
15731576
pub opt_hir_hash: Option<Fingerprint>,
15741577
}

compiler/rustc_hir/src/stable_hash_impls.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable<HirCtx> for AttributeMap
111111
}
112112
}
113113

114-
impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Crate<'_> {
114+
impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Crate {
115115
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
116-
let Crate { owners: _, opt_hir_hash } = self;
116+
let Crate { opt_hir_hash } = self;
117117
opt_hir_hash.unwrap().hash_stable(hcx, hasher)
118118
}
119119
}

compiler/rustc_interface/src/passes.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -928,16 +928,16 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
928928
if tcx.sess.opts.unstable_opts.input_stats {
929929
rustc_passes::input_stats::print_hir_stats(tcx);
930930
}
931+
932+
// Prefetch this to prevent multiple threads from blocking on it later.
933+
// This also feeds all the queries that normally depend on hir_crate having been run.
934+
tcx.ensure_done().hir_crate(());
935+
931936
// When using rustdoc's "jump to def" feature, it enters this code and `check_crate`
932937
// is not defined. So we need to cfg it out.
933938
#[cfg(all(not(doc), debug_assertions))]
934939
rustc_passes::hir_id_validator::check_crate(tcx);
935940

936-
// Prefetch this to prevent multiple threads from blocking on it later.
937-
// This is needed since the `hir_id_validator::check_crate` call above is not guaranteed
938-
// to use `hir_crate`.
939-
tcx.ensure_done().hir_crate(());
940-
941941
let sess = tcx.sess;
942942
sess.time("misc_checking_1", || {
943943
parallel!(

compiler/rustc_middle/src/arena.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ macro_rules! arena_types {
118118
[decode] specialization_graph: rustc_middle::traits::specialization_graph::Graph,
119119
[] crate_inherent_impls: rustc_middle::ty::CrateInherentImpls,
120120
[] hir_owner_nodes: rustc_hir::OwnerNodes<'tcx>,
121+
[] owner_info: rustc_hir::OwnerInfo<'tcx>,
121122
]);
122123
)
123124
}

compiler/rustc_middle/src/hir/map.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -396,12 +396,9 @@ impl<'tcx> TyCtxt<'tcx> {
396396
where
397397
V: Visitor<'tcx>,
398398
{
399-
let krate = self.hir_crate(());
400-
for info in krate.owners.iter() {
401-
if let MaybeOwner::Owner(info) = info {
402-
for attrs in info.attrs.map.values() {
403-
walk_list!(visitor, visit_attribute, *attrs);
404-
}
399+
for owner in self.hir_crate_items(()).owners().chain(Some(CRATE_OWNER_ID)) {
400+
for attrs in self.hir_attr_map(owner).map.values() {
401+
walk_list!(visitor, visit_attribute, *attrs);
405402
}
406403
}
407404
V::Result::output()

compiler/rustc_middle/src/hir/mod.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -181,19 +181,25 @@ pub fn provide(providers: &mut Providers) {
181181
providers.hir_crate_items = map::hir_crate_items;
182182
providers.crate_hash = map::crate_hash;
183183
providers.hir_module_items = map::hir_module_items;
184-
providers.local_def_id_to_hir_id = |tcx, def_id| match tcx.hir_crate(()).owners[def_id] {
185-
MaybeOwner::Owner(_) => HirId::make_owner(def_id),
186-
MaybeOwner::NonOwner(hir_id) => hir_id,
187-
MaybeOwner::Phantom => bug!("No HirId for {:?}", def_id),
184+
providers.local_def_id_to_hir_id = |tcx, def_id| {
185+
tcx.ensure_ok().hir_crate(());
186+
match tcx.hir_owner(def_id) {
187+
MaybeOwner::Owner(_) => HirId::make_owner(def_id),
188+
MaybeOwner::NonOwner(hir_id) => hir_id,
189+
MaybeOwner::Phantom => bug!("No HirId for {:?}", def_id),
190+
}
191+
};
192+
providers.opt_hir_owner_nodes = |tcx, id| {
193+
tcx.ensure_ok().hir_crate(());
194+
tcx.hir_owner(id).as_owner().map(|i| &i.nodes)
188195
};
189-
providers.opt_hir_owner_nodes =
190-
|tcx, id| tcx.hir_crate(()).owners.get(id)?.as_owner().map(|i| &i.nodes);
191196
providers.hir_owner_parent = |tcx, owner_id| {
192197
tcx.opt_local_parent(owner_id.def_id).map_or(CRATE_HIR_ID, |parent_def_id| {
193198
let parent_owner_id = tcx.local_def_id_to_hir_id(parent_def_id).owner;
194199
HirId {
195200
owner: parent_owner_id,
196-
local_id: tcx.hir_crate(()).owners[parent_owner_id.def_id]
201+
local_id: tcx
202+
.hir_owner(parent_owner_id.def_id)
197203
.unwrap()
198204
.parenting
199205
.get(&owner_id.def_id)
@@ -203,7 +209,8 @@ pub fn provide(providers: &mut Providers) {
203209
})
204210
};
205211
providers.hir_attr_map = |tcx, id| {
206-
tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
212+
tcx.ensure_ok().hir_crate(());
213+
tcx.hir_owner(id.def_id).as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
207214
};
208215
providers.def_span = |tcx, def_id| tcx.hir_span(tcx.local_def_id_to_hir_id(def_id));
209216
providers.def_ident_span = |tcx, def_id| {
@@ -236,7 +243,6 @@ pub fn provide(providers: &mut Providers) {
236243
|tcx, trait_id| tcx.resolutions(()).trait_impls.get(&trait_id).map_or(&[], |xs| &xs[..]);
237244
providers.expn_that_defined =
238245
|tcx, id| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root());
239-
providers.in_scope_traits_map = |tcx, id| {
240-
tcx.hir_crate(()).owners[id.def_id].as_owner().map(|owner_info| &owner_info.trait_map)
241-
};
246+
providers.in_scope_traits_map =
247+
|tcx, id| tcx.hir_owner(id.def_id).as_owner().map(|owner_info| &owner_info.trait_map);
242248
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,12 +166,19 @@ rustc_queries! {
166166
/// query gives you access to all other items. To avoid this fate, do not
167167
/// call `tcx.hir_crate(())`; instead, prefer wrappers like
168168
/// [`TyCtxt::hir_visit_all_item_likes_in_crate`].
169-
query hir_crate(key: ()) -> &'tcx Crate<'tcx> {
169+
query hir_crate(key: ()) -> &'tcx Crate {
170170
arena_cache
171171
eval_always
172172
desc { "getting the crate HIR" }
173173
}
174174

175+
/// A query decoupling the `hir_crate` query from everything else
176+
query hir_owner(key: LocalDefId) -> rustc_hir::MaybeOwner<'tcx> {
177+
no_hash
178+
desc { |tcx| "getting HIR of `{}`", tcx.def_path_str(key) }
179+
feedable
180+
}
181+
175182
/// All items in the crate.
176183
query hir_crate_items(_: ()) -> &'tcx rustc_middle::hir::ModuleItems {
177184
arena_cache
@@ -201,6 +208,7 @@ rustc_queries! {
201208
/// Avoid calling this query directly.
202209
query hir_owner_parent(key: hir::OwnerId) -> hir::HirId {
203210
desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key) }
211+
feedable
204212
}
205213

206214
/// Gives access to the HIR nodes and bodies inside `key` if it's a HIR owner.
@@ -1790,6 +1798,7 @@ rustc_queries! {
17901798
query in_scope_traits_map(_: hir::OwnerId)
17911799
-> Option<&'tcx ItemLocalMap<Box<[TraitCandidate]>>> {
17921800
desc { "getting traits in scope at a block" }
1801+
feedable
17931802
}
17941803

17951804
/// Returns whether the impl or associated function has the `default` keyword.

compiler/rustc_middle/src/ty/context.rs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
3737
use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState};
3838
use rustc_hir::intravisit::VisitorExt;
3939
use rustc_hir::lang_items::LangItem;
40-
use rustc_hir::{self as hir, Attribute, HirId, Node, TraitCandidate};
40+
use rustc_hir::{
41+
self as hir, Attribute, HirId, MaybeOwner, Node, OwnerId, OwnerInfo, TraitCandidate,
42+
};
4143
use rustc_index::IndexVec;
4244
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
4345
use rustc_query_system::cache::WithDepNode;
@@ -1275,6 +1277,16 @@ impl<'tcx> TyCtxt<'tcx> {
12751277
TyCtxtFeed { tcx: self, key: () }
12761278
}
12771279

1280+
pub fn super_duper_perf_hack_experiment(self, key: LocalDefId) -> TyCtxtFeed<'tcx, LocalDefId> {
1281+
self.dep_graph.assert_eval_always();
1282+
TyCtxtFeed { tcx: self, key }
1283+
}
1284+
1285+
pub fn super_duper_perf_hack_experiment2(self, key: OwnerId) -> TyCtxtFeed<'tcx, OwnerId> {
1286+
self.dep_graph.assert_eval_always();
1287+
TyCtxtFeed { tcx: self, key }
1288+
}
1289+
12781290
/// Only used in the resolver to register the `CRATE_DEF_ID` `DefId` and feed
12791291
/// some queries for it. It will panic if used twice.
12801292
pub fn create_local_crate_def_id(self, span: Span) -> TyCtxtFeed<'tcx, LocalDefId> {
@@ -1329,24 +1341,25 @@ impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
13291341

13301342
// Fills in all the important parts needed by HIR queries
13311343
pub fn feed_hir(&self) {
1332-
self.local_def_id_to_hir_id(HirId::make_owner(self.def_id()));
1333-
13341344
let node = hir::OwnerNode::Synthetic;
13351345
let bodies = Default::default();
1336-
let attrs = hir::AttributeMap::EMPTY;
1337-
1346+
let attrs = hir::AttributeMap::empty();
13381347
let (opt_hash_including_bodies, _) =
13391348
self.tcx.hash_owner_nodes(node, &bodies, &attrs.map, attrs.define_opaque);
13401349
let node = node.into();
1341-
self.opt_hir_owner_nodes(Some(self.tcx.arena.alloc(hir::OwnerNodes {
1342-
opt_hash_including_bodies,
1343-
nodes: IndexVec::from_elem_n(
1344-
hir::ParentedNode { parent: hir::ItemLocalId::INVALID, node },
1345-
1,
1346-
),
1347-
bodies,
1350+
self.hir_owner(MaybeOwner::Owner(self.tcx.arena.alloc(OwnerInfo {
1351+
nodes: hir::OwnerNodes {
1352+
opt_hash_including_bodies,
1353+
nodes: IndexVec::from_elem_n(
1354+
hir::ParentedNode { parent: hir::ItemLocalId::INVALID, node },
1355+
1,
1356+
),
1357+
bodies,
1358+
},
1359+
parenting: Default::default(),
1360+
attrs,
1361+
trait_map: Default::default(),
13481362
})));
1349-
self.feed_owner_id().hir_attr_map(attrs);
13501363
}
13511364
}
13521365

compiler/rustc_query_system/src/dep_graph/graph.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,18 @@ impl<D: Deps> DepGraph<D> {
200200
}
201201
}
202202

203+
pub fn assert_eval_always(&self) {
204+
if let Some(..) = self.data {
205+
D::read_deps(|task_deps| {
206+
assert_matches!(
207+
task_deps,
208+
TaskDepsRef::EvalAlways,
209+
"expected no task dependency tracking"
210+
);
211+
})
212+
}
213+
}
214+
203215
pub fn with_ignore<OP, R>(&self, op: OP) -> R
204216
where
205217
OP: FnOnce() -> R,

0 commit comments

Comments
 (0)