1
1
use crate :: QueryCtxt ;
2
2
use 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 } ;
4
5
use rustc_data_structures:: unhash:: UnhashMap ;
5
6
use rustc_hir:: def_id:: { CrateNum , DefId , DefIndex , LocalDefId , StableCrateId , LOCAL_CRATE } ;
6
7
use rustc_hir:: definitions:: DefPathHash ;
@@ -42,7 +43,7 @@ const TAG_EXPN_DATA: u8 = 1;
42
43
/// any side effects that have been emitted during a query.
43
44
pub struct OnDiskCache < ' sess > {
44
45
// The complete cache data in serialized form.
45
- serialized_data : Vec < u8 > ,
46
+ serialized_data : RwLock < Option < Mmap > > ,
46
47
47
48
// Collects all `QuerySideEffects` created during the current compilation
48
49
// session.
@@ -182,7 +183,8 @@ impl EncodedSourceFileId {
182
183
}
183
184
184
185
impl < ' 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 {
186
188
debug_assert ! ( sess. opts. incremental. is_some( ) ) ;
187
189
188
190
// Wrap in a scope so we can borrow `data`.
@@ -204,7 +206,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
204
206
} ;
205
207
206
208
Self {
207
- serialized_data : data,
209
+ serialized_data : RwLock :: new ( Some ( data) ) ,
208
210
file_index_to_stable_id : footer. file_index_to_stable_id ,
209
211
file_index_to_file : Default :: default ( ) ,
210
212
cnum_map : OnceCell :: new ( ) ,
@@ -225,7 +227,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
225
227
226
228
fn new_empty ( source_map : & ' sess SourceMap ) -> Self {
227
229
Self {
228
- serialized_data : Vec :: new ( ) ,
230
+ serialized_data : RwLock :: new ( None ) ,
229
231
file_index_to_stable_id : Default :: default ( ) ,
230
232
file_index_to_file : Default :: default ( ) ,
231
233
cnum_map : OnceCell :: new ( ) ,
@@ -244,7 +246,31 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
244
246
}
245
247
}
246
248
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 {
248
274
// Serializing the `DepGraph` should not modify it.
249
275
tcx. dep_graph . with_ignore ( || {
250
276
// Allocate `SourceFileIndex`es.
@@ -266,21 +292,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
266
292
( file_to_file_index, file_index_to_stable_id)
267
293
} ;
268
294
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
-
284
295
let latest_foreign_def_path_hashes = self . latest_foreign_def_path_hashes . lock ( ) . clone ( ) ;
285
296
let hygiene_encode_context = HygieneEncodeContext :: default ( ) ;
286
297
@@ -564,7 +575,7 @@ impl<'sess> OnDiskCache<'sess> {
564
575
} )
565
576
}
566
577
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 > (
568
579
& ' sess self ,
569
580
tcx : TyCtxt < ' tcx > ,
570
581
pos : AbsoluteBytePos ,
@@ -575,9 +586,10 @@ impl<'sess> OnDiskCache<'sess> {
575
586
{
576
587
let cnum_map = self . cnum_map . get_or_init ( || Self :: compute_cnum_map ( tcx) ) ;
577
588
589
+ let serialized_data = self . serialized_data . read ( ) ;
578
590
let mut decoder = CacheDecoder {
579
591
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 ( ) ) ,
581
593
source_map : self . source_map ,
582
594
cnum_map,
583
595
file_index_to_file : & self . file_index_to_file ,
0 commit comments