Skip to content

Make metadata a workproduct and reuse it #114669

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

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3995,6 +3995,7 @@ dependencies = [
"rustc_fs_util",
"rustc_hir",
"rustc_hir_pretty",
"rustc_incremental",
"rustc_index",
"rustc_macros",
"rustc_middle",
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_codegen_cranelift/src/driver/aot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ impl OngoingCodegen {
backend_config: &BackendConfig,
) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
let mut work_products = FxIndexMap::default();

if let Some(path) = self.metadata.path() {
if let Some((id, product)) =
rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(sess, "metadata", &[
("rmeta", path),
])
{
work_products.insert(id, product);
}
}

let mut modules = vec![];

for module_codegen in self.modules {
Expand Down
16 changes: 14 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(

fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
sess: &Session,
metadata: &EncodedMetadata,
compiled_modules: &CompiledModules,
) -> FxIndexMap<WorkProductId, WorkProduct> {
let mut work_products = FxIndexMap::default();
Expand All @@ -530,6 +531,14 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(

let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir");

if let Some(path) = metadata.path() {
if let Some((id, product)) =
copy_cgu_workproduct_to_incr_comp_cache_dir(sess, "metadata", &[("rmeta", path)])
{
work_products.insert(id, product);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

This should be done for all codegen backends. Maybe move it to rustc_incremental or rustc_interface? rustc_interface is responsible for ensuring that the .rmeta file is written in the first place.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

rustc_interface has the .rmeta file written by calling encode_and_write_metadata(tcx). This specific code path fetches the metadata to put into the rlib file.


for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) {
let mut files = Vec::new();
if let Some(object_file_path) = &module.object {
Expand Down Expand Up @@ -2059,8 +2068,11 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {

sess.dcx().abort_if_errors();

let work_products =
copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess, &compiled_modules);
let work_products = copy_all_cgu_workproducts_to_incr_comp_cache_dir(
sess,
&self.metadata,
&compiled_modules,
);
produce_final_output_artifacts(sess, &compiled_modules, &self.output_filenames);

// FIXME: time_llvm_passes support - does this use a global context or
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_metadata/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_fs_util = { path = "../rustc_fs_util" }
rustc_hir = { path = "../rustc_hir" }
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
rustc_incremental = { path = "../rustc_incremental" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
Expand Down
50 changes: 39 additions & 11 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1544,6 +1544,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let table = tcx.associated_types_for_impl_traits_in_associated_fn(def_id);
record_defaulted_array!(self.tables.associated_types_for_impl_traits_in_associated_fn[def_id] <- table);
}
if let DefKind::Mod = tcx.def_kind(def_id) {
record!(self.tables.doc_link_resolutions[def_id] <- tcx.doc_link_resolutions(def_id));
record_array!(self.tables.doc_link_traits_in_scope[def_id] <- tcx.doc_link_traits_in_scope(def_id));
}
}

for (def_id, impls) in &tcx.crate_inherent_impls(()).0.inherent_impls {
Expand All @@ -1552,14 +1556,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
def_id.index
}));
}

for (def_id, res_map) in &tcx.resolutions(()).doc_link_resolutions {
record!(self.tables.doc_link_resolutions[def_id.to_def_id()] <- res_map);
}

for (def_id, traits) in &tcx.resolutions(()).doc_link_traits_in_scope {
record_array!(self.tables.doc_link_traits_in_scope[def_id.to_def_id()] <- traits);
}
}

#[instrument(level = "trace", skip(self))]
Expand Down Expand Up @@ -2205,6 +2201,8 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
pub struct EncodedMetadata {
// The declaration order matters because `mmap` should be dropped before `_temp_dir`.
mmap: Option<Mmap>,
// The path containing the metadata, to record as work product.
path: Option<Box<Path>>,
// We need to carry MaybeTempDir to avoid deleting the temporary
// directory while accessing the Mmap.
_temp_dir: Option<MaybeTempDir>,
Expand All @@ -2216,16 +2214,21 @@ impl EncodedMetadata {
let file = std::fs::File::open(&path)?;
let file_metadata = file.metadata()?;
if file_metadata.len() == 0 {
return Ok(Self { mmap: None, _temp_dir: None });
return Ok(Self { mmap: None, path: None, _temp_dir: None });
}
let mmap = unsafe { Some(Mmap::map(file)?) };
Ok(Self { mmap, _temp_dir: temp_dir })
Ok(Self { mmap, path: Some(path.into()), _temp_dir: temp_dir })
}

#[inline]
pub fn raw_data(&self) -> &[u8] {
self.mmap.as_deref().unwrap_or_default()
}

#[inline]
pub fn path(&self) -> Option<&Path> {
self.path.as_deref()
}
}

impl<S: Encoder> Encodable<S> for EncodedMetadata {
Expand All @@ -2249,11 +2252,32 @@ impl<D: Decoder> Decodable<D> for EncodedMetadata {
None
};

Self { mmap, _temp_dir: None }
Self { mmap, path: None, _temp_dir: None }
}
}

#[instrument(level = "trace", skip(tcx))]
pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
let dep_node = tcx.metadata_dep_node();

if tcx.dep_graph.is_fully_enabled()
&& let work_product_id = &rustc_middle::dep_graph::WorkProductId::from_cgu_name("metadata")
&& let Some(work_product) = tcx.dep_graph.previous_work_product(work_product_id)
&& tcx.try_mark_green(&dep_node)
{
let saved_path = &work_product.saved_files["rmeta"];
let incr_comp_session_dir = tcx.sess.incr_comp_session_dir_opt().unwrap();
let source_file = rustc_incremental::in_incr_comp_dir(&incr_comp_session_dir, saved_path);
debug!("copying preexisting metadata from {source_file:?} to {path:?}");
match rustc_fs_util::link_or_copy(&source_file, path) {
Ok(_) => {}
Err(err) => {
tcx.dcx().emit_fatal(FailCreateFileEncoder { err });
}
};
return;
};

let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata");

// Since encoding metadata is not in a query, and nothing is cached,
Expand All @@ -2267,6 +2291,10 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE));
}

tcx.dep_graph.with_task(dep_node, tcx, path, encode_metadata_impl, None);
}

fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
let mut encoder = opaque::FileEncoder::new(path)
.unwrap_or_else(|err| tcx.dcx().emit_fatal(FailCreateFileEncoder { err }));
encoder.emit_raw_bytes(METADATA_HEADER);
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_middle/src/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ rustc_query_append!(define_dep_nodes![
[] fn TraitSelect() -> (),
[] fn CompileCodegenUnit() -> (),
[] fn CompileMonoItem() -> (),
[] fn Metadata() -> (),
]);

// WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys.
Expand All @@ -157,6 +158,12 @@ pub(crate) fn make_compile_mono_item<'tcx>(
DepNode::construct(tcx, dep_kinds::CompileMonoItem, mono_item)
}

// WARNING: `construct` is generic and does not know that `Metadata` takes `()`s as keys.
// Be very careful changing this type signature!
pub(crate) fn make_metadata(tcx: TyCtxt<'_>) -> DepNode {
DepNode::construct(tcx, dep_kinds::Metadata, &())
}

pub trait DepNodeExt: Sized {
/// Extracts the DefId corresponding to this DepNode. This will work
/// if two conditions are met:
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/dep_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::ty::{self, TyCtxt};
mod dep_node;

pub use dep_node::{DepKind, DepNode, DepNodeExt, dep_kinds, label_strs};
pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item};
pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item, make_metadata};
pub use rustc_query_system::dep_graph::debug::{DepNodeFilter, EdgeFilter};
pub use rustc_query_system::dep_graph::{
DepContext, DepGraphQuery, DepNodeIndex, Deps, SerializedDepGraph, SerializedDepNodeIndex,
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,16 @@ rustc_queries! {
desc { "getting the resolver for lowering" }
}

/// Named module children from all kinds of items, including imports.
/// In addition to regular items this list also includes struct and variant constructors, and
/// items inside `extern {}` blocks because all of them introduce names into parent module.
///
/// Module here is understood in name resolution sense - it can be a `mod` item,
/// or a crate root, or an enum, or a trait.
query module_children_local(key: LocalDefId) -> &'tcx [ModChild] {
desc { |tcx| "module exports for `{}`", tcx.def_path_str(key) }
}

/// Return the span for a definition.
/// Contrary to `def_span` below, this query returns the full absolute span of the definition.
/// This span is meant for dep-tracking rather than diagnostics. It should not be used outside
Expand Down
30 changes: 10 additions & 20 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ use crate::arena::Arena;
use crate::dep_graph::{DepGraph, DepKindStruct};
use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarInfo, CanonicalVarInfos};
use crate::lint::lint_level;
use crate::metadata::ModChild;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::{resolve_bound_vars, stability};
use crate::mir::interpret::{self, Allocation, ConstAllocation};
Expand Down Expand Up @@ -1863,9 +1862,8 @@ impl<'tcx> TyCtxt<'tcx> {
}

pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx {
// Create a dependency to the red node to be sure we re-execute this when the amount of
// definitions change.
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
// Depend on the `analysis` query to ensure compilation if finished.
self.ensure().analysis(());

let definitions = &self.untracked.definitions;
std::iter::from_coroutine(
Expand All @@ -1888,9 +1886,8 @@ impl<'tcx> TyCtxt<'tcx> {
}

pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
// Create a dependency to the crate to be sure we re-execute this when the amount of
// definitions change.
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
// Depend on the `analysis` query to ensure compilation if finished.
self.ensure().analysis(());

// Freeze definitions once we start iterating on them, to prevent adding new ones
// while iterating. If some query needs to add definitions, it should be `ensure`d above.
Expand Down Expand Up @@ -3154,23 +3151,14 @@ impl<'tcx> TyCtxt<'tcx> {
self.opt_rpitit_info(def_id).is_some()
}

/// Named module children from all kinds of items, including imports.
/// In addition to regular items this list also includes struct and variant constructors, and
/// items inside `extern {}` blocks because all of them introduce names into parent module.
///
/// Module here is understood in name resolution sense - it can be a `mod` item,
/// or a crate root, or an enum, or a trait.
///
/// This is not a query, making it a query causes perf regressions
/// (probably due to hashing spans in `ModChild`ren).
pub fn module_children_local(self, def_id: LocalDefId) -> &'tcx [ModChild] {
self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..])
}

pub fn resolver_for_lowering(self) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
self.resolver_for_lowering_raw(()).0
}

pub fn metadata_dep_node(self) -> crate::dep_graph::DepNode {
crate::dep_graph::make_metadata(self)
}

/// Given an `impl_id`, return the trait it implements.
/// Return `None` if this is an inherent impl.
pub fn impl_trait_ref(
Expand Down Expand Up @@ -3218,6 +3206,8 @@ pub struct DeducedParamAttrs {
}

pub fn provide(providers: &mut Providers) {
providers.module_children_local =
|tcx, def_id| tcx.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..]);
providers.maybe_unused_trait_imports =
|tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
providers.names_imported_by_glob_use = |tcx, id| {
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_query_impl/src/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,17 @@ macro_rules! define_queries {
}
}

pub(crate) fn Metadata<'tcx>() -> DepKindStruct<'tcx> {
DepKindStruct {
is_anon: false,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Unit,
force_from_dep_node: None,
try_load_from_on_disk_cache: None,
name: &"Metadata",
}
}

$(pub(crate) fn $name<'tcx>()-> DepKindStruct<'tcx> {
$crate::plumbing::query_callback::<query_impl::$name::QueryType<'tcx>>(
is_anon!([$($modifiers)*]),
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1473,13 +1473,16 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
}

fn with_scope<T>(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
if let Some(module) = self.r.get_module(self.r.local_def_id(id).to_def_id()) {
let def_id = self.r.local_def_id(id);
if let Some(module) = self.r.get_module(def_id.to_def_id()) {
// Move down in the graph.
let orig_module = replace(&mut self.parent_scope.module, module);
self.with_rib(ValueNS, RibKind::Module(module), |this| {
this.with_rib(TypeNS, RibKind::Module(module), |this| {
let ret = f(this);
this.parent_scope.module = orig_module;
this.r.doc_link_resolutions.entry(def_id).or_default();
this.r.doc_link_traits_in_scope.entry(def_id).or_default();
ret
})
})
Expand Down Expand Up @@ -5054,6 +5057,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
BuiltinLintDiag::UnusedLabel,
);
}
self.doc_link_resolutions.entry(CRATE_DEF_ID).or_default();
self.doc_link_traits_in_scope.entry(CRATE_DEF_ID).or_default();
}
}

Expand Down
Loading