Skip to content

Commit b3150f3

Browse files
committed
Adds RmetaLinkCache a per-link cache that uses path as the key of decoded lib.rmeta-link archive members, and routes add_archive read through it so each rlib link metadata is decoded at most once per link. This is a demand that originated from the discussion in #156735 and we split it out as its own PR. It gives that PR a decode once path tp read instead of reparsing each rlib per crate once native_lib_filenames moves to a link time read.
1 parent f7da3c0 commit b3150f3

3 files changed

Lines changed: 49 additions & 11 deletions

File tree

compiler/rustc_codegen_ssa/src/back/archive.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustc_target::spec::Arch;
2222
use tracing::trace;
2323

2424
use super::metadata::{create_compressed_metadata_file, search_for_section};
25-
use super::rmeta_link;
25+
use super::rmeta_link::{self, RmetaLinkCache};
2626
use super::symbol_edit::{apply_edits, collect_internal_names};
2727
use crate::common;
2828
// Public for ArchiveBuilderBuilder::extract_bundled_libs
@@ -311,7 +311,7 @@ fn find_binutils_dlltool(sess: &Session) -> OsString {
311311
}
312312

313313
pub enum AddArchiveKind<'a> {
314-
Rlib(/*skip*/ &'a dyn Fn(&str, ArchiveEntryKind) -> bool),
314+
Rlib(&'a mut RmetaLinkCache, /*skip*/ &'a dyn Fn(&str, ArchiveEntryKind) -> bool),
315315
Other,
316316
}
317317

@@ -466,7 +466,11 @@ pub fn try_extract_macho_fat_archive(
466466
}
467467

468468
impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
469-
fn add_archive(&mut self, archive_path: &Path, ar_kind: AddArchiveKind<'_>) -> io::Result<()> {
469+
fn add_archive(
470+
&mut self,
471+
archive_path: &Path,
472+
mut ar_kind: AddArchiveKind<'_>,
473+
) -> io::Result<()> {
470474
let mut archive_path = archive_path.to_path_buf();
471475
if self.sess.target.llvm_target.contains("-apple-macosx")
472476
&& let Some(new_archive_path) = try_extract_macho_fat_archive(self.sess, &archive_path)?
@@ -481,8 +485,14 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
481485
let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
482486
let archive = ArchiveFile::parse(&*archive_map)
483487
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
484-
let metadata_link = match ar_kind {
485-
AddArchiveKind::Rlib(..) => rmeta_link::read(&archive, &archive_map, &archive_path),
488+
let skip = match &ar_kind {
489+
AddArchiveKind::Rlib(_, skip) => Some(*skip),
490+
AddArchiveKind::Other => None,
491+
};
492+
let metadata_link = match &mut ar_kind {
493+
AddArchiveKind::Rlib(cache, _) => cache.get_or_insert_with(&archive_path, || {
494+
rmeta_link::read(&archive, &archive_map, &archive_path)
495+
}),
486496
AddArchiveKind::Other => None,
487497
};
488498
let archive_index = self.src_archives.len();
@@ -512,9 +522,9 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
512522
} else {
513523
ArchiveEntryKind::Other
514524
};
515-
let drop = match ar_kind {
516-
AddArchiveKind::Rlib(skip) => skip(&file_name, kind),
517-
AddArchiveKind::Other => false,
525+
let drop = match skip {
526+
Some(skip) => skip(&file_name, kind),
527+
None => false,
518528
};
519529
if !drop {
520530
let source = if entry.is_thin() {

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ use super::archive::{
5959
use super::command::Command;
6060
use super::linker::{self, Linker};
6161
use super::metadata::{MetadataPosition, create_wrapper_file};
62+
use super::rmeta_link::RmetaLinkCache;
6263
use super::rpath::{self, RPathConfig};
6364
use super::{apple, rmeta_link, versioned_llvm_target};
6465
use crate::base::needs_allocator_shim_for_linking;
@@ -86,6 +87,7 @@ pub fn link_binary(
8687
let _timer = sess.timer("link_binary");
8788
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
8889
let mut tempfiles_for_stdout_output: Vec<PathBuf> = Vec::new();
90+
let mut rmeta_link_cache = RmetaLinkCache::default();
8991
for &crate_type in &crate_info.crate_types {
9092
// Ignore executable crates if we have -Z no-codegen, as they will error.
9193
if (sess.opts.unstable_opts.no_codegen || !sess.opts.output_types.should_codegen())
@@ -139,6 +141,7 @@ pub fn link_binary(
139141
link_staticlib(
140142
sess,
141143
archive_builder_builder,
144+
&mut rmeta_link_cache,
142145
&compiled_modules,
143146
&crate_info,
144147
&metadata,
@@ -150,6 +153,7 @@ pub fn link_binary(
150153
link_natively(
151154
sess,
152155
archive_builder_builder,
156+
&mut rmeta_link_cache,
153157
crate_type,
154158
&out_filename,
155159
&compiled_modules,
@@ -502,6 +506,7 @@ fn link_rlib<'a>(
502506
fn link_staticlib(
503507
sess: &Session,
504508
archive_builder_builder: &dyn ArchiveBuilderBuilder,
509+
rmeta_link_cache: &mut RmetaLinkCache,
505510
compiled_modules: &CompiledModules,
506511
crate_info: &CrateInfo,
507512
metadata: &EncodedMetadata,
@@ -531,7 +536,7 @@ fn link_staticlib(
531536
let bundled_libs: FxIndexSet<_> = native_libs.filter_map(|lib| lib.filename).collect();
532537
ab.add_archive(
533538
path,
534-
AddArchiveKind::Rlib(&|fname: &str, entry_kind| {
539+
AddArchiveKind::Rlib(rmeta_link_cache, &|fname: &str, entry_kind| {
535540
// Ignore metadata and rmeta-link files.
536541
if fname == METADATA_FILENAME || fname == rmeta_link::FILENAME {
537542
return true;
@@ -939,6 +944,7 @@ fn report_linker_output(
939944
fn link_natively(
940945
sess: &Session,
941946
archive_builder_builder: &dyn ArchiveBuilderBuilder,
947+
rmeta_link_cache: &mut RmetaLinkCache,
942948
crate_type: CrateType,
943949
out_filename: &Path,
944950
compiled_modules: &CompiledModules,
@@ -965,6 +971,7 @@ fn link_natively(
965971
flavor,
966972
sess,
967973
archive_builder_builder,
974+
rmeta_link_cache,
968975
crate_type,
969976
tmpdir,
970977
temp_filename,
@@ -2491,6 +2498,7 @@ fn linker_with_args(
24912498
flavor: LinkerFlavor,
24922499
sess: &Session,
24932500
archive_builder_builder: &dyn ArchiveBuilderBuilder,
2501+
rmeta_link_cache: &mut RmetaLinkCache,
24942502
crate_type: CrateType,
24952503
tmpdir: &Path,
24962504
out_filename: &Path,
@@ -2619,6 +2627,7 @@ fn linker_with_args(
26192627
cmd,
26202628
sess,
26212629
archive_builder_builder,
2630+
rmeta_link_cache,
26222631
crate_info,
26232632
crate_type,
26242633
tmpdir,
@@ -3055,6 +3064,7 @@ fn add_upstream_rust_crates(
30553064
cmd: &mut dyn Linker,
30563065
sess: &Session,
30573066
archive_builder_builder: &dyn ArchiveBuilderBuilder,
3067+
rmeta_link_cache: &mut RmetaLinkCache,
30583068
crate_info: &CrateInfo,
30593069
crate_type: CrateType,
30603070
tmpdir: &Path,
@@ -3107,6 +3117,7 @@ fn add_upstream_rust_crates(
31073117
cmd,
31083118
sess,
31093119
archive_builder_builder,
3120+
rmeta_link_cache,
31103121
crate_info,
31113122
tmpdir,
31123123
cnum,
@@ -3238,6 +3249,7 @@ fn add_static_crate(
32383249
cmd: &mut dyn Linker,
32393250
sess: &Session,
32403251
archive_builder_builder: &dyn ArchiveBuilderBuilder,
3252+
rmeta_link_cache: &mut RmetaLinkCache,
32413253
crate_info: &CrateInfo,
32423254
tmpdir: &Path,
32433255
cnum: CrateNum,
@@ -3268,7 +3280,7 @@ fn add_static_crate(
32683280
let mut archive = archive_builder_builder.new_archive_builder(sess);
32693281
if let Err(error) = archive.add_archive(
32703282
cratepath,
3271-
AddArchiveKind::Rlib(&|f, entry_kind| {
3283+
AddArchiveKind::Rlib(rmeta_link_cache, &|f, entry_kind| {
32723284
if f == METADATA_FILENAME || f == rmeta_link::FILENAME {
32733285
return true;
32743286
}

compiler/rustc_codegen_ssa/src/back/rmeta_link.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
//! and potentially other data collected and used when building or linking a rlib.
33
//! See <https://github.com/rust-lang/rust/issues/138243>.
44
5-
use std::path::Path;
5+
use std::path::{Path, PathBuf};
66

77
use object::read::archive::ArchiveFile;
8+
use rustc_data_structures::fx::FxHashMap;
89
use rustc_serialize::opaque::mem_encoder::MemEncoder;
910
use rustc_serialize::opaque::{MAGIC_END_BYTES, MemDecoder};
1011
use rustc_serialize::{Decodable, Encodable};
@@ -54,3 +55,18 @@ pub fn read_from_data(archive_data: &[u8], rlib_path: &Path) -> Option<RmetaLink
5455
let archive = ArchiveFile::parse(archive_data).ok()?;
5556
read(&archive, archive_data, rlib_path)
5657
}
58+
59+
#[derive(Default)]
60+
pub struct RmetaLinkCache {
61+
cache: FxHashMap<PathBuf, Option<RmetaLink>>,
62+
}
63+
64+
impl RmetaLinkCache {
65+
pub fn get_or_insert_with(
66+
&mut self,
67+
rlib_path: &Path,
68+
load: impl FnOnce() -> Option<RmetaLink>,
69+
) -> Option<&RmetaLink> {
70+
self.cache.entry(rlib_path.to_path_buf()).or_insert_with(load).as_ref()
71+
}
72+
}

0 commit comments

Comments
 (0)