11use crate :: QueryCtxt ;
22use rustc_data_structures:: fx:: { FxHashMap , FxHashSet , FxIndexSet } ;
3- use rustc_data_structures:: sync:: { HashMapExt , Lock , Lrc , OnceCell } ;
3+ use rustc_data_structures:: memmap:: Mmap ;
4+ use rustc_data_structures:: sync:: { HashMapExt , Lock , Lrc , OnceCell , RwLock } ;
45use rustc_data_structures:: unhash:: UnhashMap ;
56use rustc_hir:: def_id:: { CrateNum , DefId , DefIndex , LocalDefId , StableCrateId , LOCAL_CRATE } ;
67use rustc_hir:: definitions:: DefPathHash ;
@@ -42,7 +43,7 @@ const TAG_EXPN_DATA: u8 = 1;
4243/// any side effects that have been emitted during a query.
4344pub struct OnDiskCache < ' sess > {
4445 // The complete cache data in serialized form.
45- serialized_data : Vec < u8 > ,
46+ serialized_data : RwLock < Option < Mmap > > ,
4647
4748 // Collects all `QuerySideEffects` created during the current compilation
4849 // session.
@@ -182,7 +183,8 @@ impl EncodedSourceFileId {
182183}
183184
184185impl < ' sess > rustc_middle:: ty:: OnDiskCache < ' sess > for OnDiskCache < ' sess > {
185- fn new ( sess : & ' sess Session , data : Vec < u8 > , start_pos : usize ) -> Self {
186+ /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
187+ fn new ( sess : & ' sess Session , data : Mmap , start_pos : usize ) -> Self {
186188 debug_assert ! ( sess. opts. incremental. is_some( ) ) ;
187189
188190 // Wrap in a scope so we can borrow `data`.
@@ -204,7 +206,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
204206 } ;
205207
206208 Self {
207- serialized_data : data,
209+ serialized_data : RwLock :: new ( Some ( data) ) ,
208210 file_index_to_stable_id : footer. file_index_to_stable_id ,
209211 file_index_to_file : Default :: default ( ) ,
210212 cnum_map : OnceCell :: new ( ) ,
@@ -225,7 +227,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
225227
226228 fn new_empty ( source_map : & ' sess SourceMap ) -> Self {
227229 Self {
228- serialized_data : Vec :: new ( ) ,
230+ serialized_data : RwLock :: new ( None ) ,
229231 file_index_to_stable_id : Default :: default ( ) ,
230232 file_index_to_file : Default :: default ( ) ,
231233 cnum_map : OnceCell :: new ( ) ,
@@ -244,7 +246,31 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
244246 }
245247 }
246248
247- fn serialize ( & self , tcx : TyCtxt < ' sess > , encoder : & mut FileEncoder ) -> FileEncodeResult {
249+ /// Execute all cache promotions and release the serialized backing Mmap.
250+ ///
251+ /// Cache promotions require invoking queries, which needs to read the serialized data.
252+ /// In order to serialize the new on-disk cache, the former on-disk cache file needs to be
253+ /// deleted, hence we won't be able to refer to its memmapped data.
254+ fn drop_serialized_data ( & self , tcx : TyCtxt < ' tcx > ) {
255+ // Register any dep nodes that we reused from the previous session,
256+ // but didn't `DepNode::construct` in this session. This ensures
257+ // that their `DefPathHash` to `RawDefId` mappings are registered
258+ // in 'latest_foreign_def_path_hashes' if necessary, since that
259+ // normally happens in `DepNode::construct`.
260+ tcx. dep_graph . register_reused_dep_nodes ( tcx) ;
261+
262+ // Load everything into memory so we can write it out to the on-disk
263+ // cache. The vast majority of cacheable query results should already
264+ // be in memory, so this should be a cheap operation.
265+ // Do this *before* we clone 'latest_foreign_def_path_hashes', since
266+ // loading existing queries may cause us to create new DepNodes, which
267+ // may in turn end up invoking `store_foreign_def_id_hash`
268+ tcx. dep_graph . exec_cache_promotions ( QueryCtxt :: from_tcx ( tcx) ) ;
269+
270+ * self . serialized_data . write ( ) = None ;
271+ }
272+
273+ fn serialize < ' tcx > ( & self , tcx : TyCtxt < ' tcx > , encoder : & mut FileEncoder ) -> FileEncodeResult {
248274 // Serializing the `DepGraph` should not modify it.
249275 tcx. dep_graph . with_ignore ( || {
250276 // Allocate `SourceFileIndex`es.
@@ -266,21 +292,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
266292 ( file_to_file_index, file_index_to_stable_id)
267293 } ;
268294
269- // Register any dep nodes that we reused from the previous session,
270- // but didn't `DepNode::construct` in this session. This ensures
271- // that their `DefPathHash` to `RawDefId` mappings are registered
272- // in 'latest_foreign_def_path_hashes' if necessary, since that
273- // normally happens in `DepNode::construct`.
274- tcx. dep_graph . register_reused_dep_nodes ( tcx) ;
275-
276- // Load everything into memory so we can write it out to the on-disk
277- // cache. The vast majority of cacheable query results should already
278- // be in memory, so this should be a cheap operation.
279- // Do this *before* we clone 'latest_foreign_def_path_hashes', since
280- // loading existing queries may cause us to create new DepNodes, which
281- // may in turn end up invoking `store_foreign_def_id_hash`
282- tcx. dep_graph . exec_cache_promotions ( QueryCtxt :: from_tcx ( tcx) ) ;
283-
284295 let latest_foreign_def_path_hashes = self . latest_foreign_def_path_hashes . lock ( ) . clone ( ) ;
285296 let hygiene_encode_context = HygieneEncodeContext :: default ( ) ;
286297
@@ -564,7 +575,7 @@ impl<'sess> OnDiskCache<'sess> {
564575 } )
565576 }
566577
567- fn with_decoder < ' a , ' tcx , T , F : FnOnce ( & mut CacheDecoder < ' sess , ' tcx > ) -> T > (
578+ fn with_decoder < ' a , ' tcx , T , F : for < ' s > FnOnce ( & mut CacheDecoder < ' s , ' tcx > ) -> T > (
568579 & ' sess self ,
569580 tcx : TyCtxt < ' tcx > ,
570581 pos : AbsoluteBytePos ,
@@ -575,9 +586,10 @@ impl<'sess> OnDiskCache<'sess> {
575586 {
576587 let cnum_map = self . cnum_map . get_or_init ( || Self :: compute_cnum_map ( tcx) ) ;
577588
589+ let serialized_data = self . serialized_data . read ( ) ;
578590 let mut decoder = CacheDecoder {
579591 tcx,
580- opaque : opaque:: Decoder :: new ( & self . serialized_data [ .. ] , pos. to_usize ( ) ) ,
592+ opaque : opaque:: Decoder :: new ( serialized_data. as_deref ( ) . unwrap_or ( & [ ] ) , pos. to_usize ( ) ) ,
581593 source_map : self . source_map ,
582594 cnum_map,
583595 file_index_to_file : & self . file_index_to_file ,
0 commit comments