@@ -703,6 +703,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
703
703
triple: tcx. sess. opts. target_triple. clone( ) ,
704
704
hash: tcx. crate_hash( LOCAL_CRATE ) ,
705
705
is_proc_macro_crate: proc_macro_data. is_some( ) ,
706
+ is_stub: false ,
706
707
} ,
707
708
extra_filename: tcx. sess. opts. cg. extra_filename. clone( ) ,
708
709
stable_crate_id: tcx. def_path_hash( LOCAL_CRATE . as_def_id( ) ) . stable_crate_id( ) ,
@@ -2235,54 +2236,75 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
2235
2236
// generated regardless of trailing bytes that end up in it.
2236
2237
2237
2238
pub struct EncodedMetadata {
2238
- // The declaration order matters because `mmap` should be dropped before `_temp_dir`.
2239
- mmap : Option < Mmap > ,
2239
+ // The declaration order matters because `full_metadata` should be dropped
2240
+ // before `_temp_dir`.
2241
+ full_metadata : Option < Mmap > ,
2242
+ // This is an optional stub metadata containing only the crate header.
2243
+ // The header should be very small, so we load it directly into memory.
2244
+ stub_metadata : Option < Vec < u8 > > ,
2240
2245
// We need to carry MaybeTempDir to avoid deleting the temporary
2241
2246
// directory while accessing the Mmap.
2242
2247
_temp_dir : Option < MaybeTempDir > ,
2243
2248
}
2244
2249
2245
2250
impl EncodedMetadata {
2246
2251
#[ inline]
2247
- pub fn from_path ( path : PathBuf , temp_dir : Option < MaybeTempDir > ) -> std:: io:: Result < Self > {
2252
+ pub fn from_path (
2253
+ path : PathBuf ,
2254
+ stub_path : Option < PathBuf > ,
2255
+ temp_dir : Option < MaybeTempDir > ,
2256
+ ) -> std:: io:: Result < Self > {
2248
2257
let file = std:: fs:: File :: open ( & path) ?;
2249
2258
let file_metadata = file. metadata ( ) ?;
2250
2259
if file_metadata. len ( ) == 0 {
2251
- return Ok ( Self { mmap : None , _temp_dir : None } ) ;
2260
+ return Ok ( Self { full_metadata : None , stub_metadata : None , _temp_dir : None } ) ;
2252
2261
}
2253
- let mmap = unsafe { Some ( Mmap :: map ( file) ?) } ;
2254
- Ok ( Self { mmap, _temp_dir : temp_dir } )
2262
+ let full_mmap = unsafe { Some ( Mmap :: map ( file) ?) } ;
2263
+
2264
+ let stub =
2265
+ if let Some ( stub_path) = stub_path { Some ( std:: fs:: read ( stub_path) ?) } else { None } ;
2266
+
2267
+ Ok ( Self { full_metadata : full_mmap, stub_metadata : stub, _temp_dir : temp_dir } )
2268
+ }
2269
+
2270
+ #[ inline]
2271
+ pub fn full ( & self ) -> & [ u8 ] {
2272
+ & self . full_metadata . as_deref ( ) . unwrap_or_default ( )
2255
2273
}
2256
2274
2257
2275
#[ inline]
2258
- pub fn raw_data ( & self ) -> & [ u8 ] {
2259
- self . mmap . as_deref ( ) . unwrap_or_default ( )
2276
+ pub fn stub_or_full ( & self ) -> & [ u8 ] {
2277
+ self . stub_metadata . as_deref ( ) . unwrap_or ( self . full ( ) )
2260
2278
}
2261
2279
}
2262
2280
2263
2281
impl < S : Encoder > Encodable < S > for EncodedMetadata {
2264
2282
fn encode ( & self , s : & mut S ) {
2265
- let slice = self . raw_data ( ) ;
2283
+ self . stub_metadata . encode ( s) ;
2284
+
2285
+ let slice = self . full ( ) ;
2266
2286
slice. encode ( s)
2267
2287
}
2268
2288
}
2269
2289
2270
2290
impl < D : Decoder > Decodable < D > for EncodedMetadata {
2271
2291
fn decode ( d : & mut D ) -> Self {
2292
+ let stub = <Option < Vec < u8 > > >:: decode ( d) ;
2293
+
2272
2294
let len = d. read_usize ( ) ;
2273
- let mmap = if len > 0 {
2295
+ let full_metadata = if len > 0 {
2274
2296
let mut mmap = MmapMut :: map_anon ( len) . unwrap ( ) ;
2275
2297
mmap. copy_from_slice ( d. read_raw_bytes ( len) ) ;
2276
2298
Some ( mmap. make_read_only ( ) . unwrap ( ) )
2277
2299
} else {
2278
2300
None
2279
2301
} ;
2280
2302
2281
- Self { mmap , _temp_dir : None }
2303
+ Self { full_metadata , stub_metadata : stub , _temp_dir : None }
2282
2304
}
2283
2305
}
2284
2306
2285
- pub fn encode_metadata ( tcx : TyCtxt < ' _ > , path : & Path ) {
2307
+ pub fn encode_metadata ( tcx : TyCtxt < ' _ > , path : & Path , ref_path : Option < & Path > ) {
2286
2308
let _prof_timer = tcx. prof . verbose_generic_activity ( "generate_crate_metadata" ) ;
2287
2309
2288
2310
// Since encoding metadata is not in a query, and nothing is cached,
@@ -2296,6 +2318,42 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2296
2318
join ( || prefetch_mir ( tcx) , || tcx. exported_symbols ( LOCAL_CRATE ) ) ;
2297
2319
}
2298
2320
2321
+ with_encode_metadata_header ( tcx, path, |ecx| {
2322
+ // Encode all the entries and extra information in the crate,
2323
+ // culminating in the `CrateRoot` which points to all of it.
2324
+ let root = ecx. encode_crate_root ( ) ;
2325
+
2326
+ // Flush buffer to ensure backing file has the correct size.
2327
+ ecx. opaque . flush ( ) ;
2328
+ // Record metadata size for self-profiling
2329
+ tcx. prof . artifact_size (
2330
+ "crate_metadata" ,
2331
+ "crate_metadata" ,
2332
+ ecx. opaque . file ( ) . metadata ( ) . unwrap ( ) . len ( ) ,
2333
+ ) ;
2334
+
2335
+ root. position . get ( )
2336
+ } ) ;
2337
+
2338
+ if let Some ( ref_path) = ref_path {
2339
+ with_encode_metadata_header ( tcx, ref_path, |ecx| {
2340
+ let header: LazyValue < CrateHeader > = ecx. lazy ( CrateHeader {
2341
+ name : tcx. crate_name ( LOCAL_CRATE ) ,
2342
+ triple : tcx. sess . opts . target_triple . clone ( ) ,
2343
+ hash : tcx. crate_hash ( LOCAL_CRATE ) ,
2344
+ is_proc_macro_crate : false ,
2345
+ is_stub : true ,
2346
+ } ) ;
2347
+ header. position . get ( )
2348
+ } ) ;
2349
+ }
2350
+ }
2351
+
2352
+ fn with_encode_metadata_header (
2353
+ tcx : TyCtxt < ' _ > ,
2354
+ path : & Path ,
2355
+ f : impl FnOnce ( & mut EncodeContext < ' _ , ' _ > ) -> usize ,
2356
+ ) {
2299
2357
let mut encoder = opaque:: FileEncoder :: new ( path)
2300
2358
. unwrap_or_else ( |err| tcx. dcx ( ) . emit_fatal ( FailCreateFileEncoder { err } ) ) ;
2301
2359
encoder. emit_raw_bytes ( METADATA_HEADER ) ;
@@ -2330,9 +2388,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2330
2388
// Encode the rustc version string in a predictable location.
2331
2389
rustc_version ( tcx. sess . cfg_version ) . encode ( & mut ecx) ;
2332
2390
2333
- // Encode all the entries and extra information in the crate,
2334
- // culminating in the `CrateRoot` which points to all of it.
2335
- let root = ecx. encode_crate_root ( ) ;
2391
+ let root_position = f ( & mut ecx) ;
2336
2392
2337
2393
// Make sure we report any errors from writing to the file.
2338
2394
// If we forget this, compilation can succeed with an incomplete rmeta file,
@@ -2342,12 +2398,9 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2342
2398
}
2343
2399
2344
2400
let file = ecx. opaque . file ( ) ;
2345
- if let Err ( err) = encode_root_position ( file, root . position . get ( ) ) {
2401
+ if let Err ( err) = encode_root_position ( file, root_position ) {
2346
2402
tcx. dcx ( ) . emit_fatal ( FailWriteFile { path : ecx. opaque . path ( ) , err } ) ;
2347
2403
}
2348
-
2349
- // Record metadata size for self-profiling
2350
- tcx. prof . artifact_size ( "crate_metadata" , "crate_metadata" , file. metadata ( ) . unwrap ( ) . len ( ) ) ;
2351
2404
}
2352
2405
2353
2406
fn encode_root_position ( mut file : & File , pos : usize ) -> Result < ( ) , std:: io:: Error > {
0 commit comments