@@ -75,6 +75,13 @@ pub struct OnDiskCache<'sess> {
7575 // A map from dep-node to the position of any associated diagnostics in
7676 // `serialized_data`.
7777 prev_diagnostics_index : FxHashMap < SerializedDepNodeIndex , AbsoluteBytePos > ,
78+
79+ // A cache to ensure we don't read allocations twice
80+ interpret_alloc_cache : RefCell < FxHashMap < usize , interpret:: AllocId > > ,
81+
82+ // A map from positions to size of the serialized allocation
83+ // so we can skip over already processed allocations
84+ interpret_alloc_size : RefCell < FxHashMap < usize , usize > > ,
7885}
7986
8087// This type is used only for (de-)serialization.
@@ -140,6 +147,8 @@ impl<'sess> OnDiskCache<'sess> {
140147 query_result_index : footer. query_result_index . into_iter ( ) . collect ( ) ,
141148 prev_diagnostics_index : footer. diagnostics_index . into_iter ( ) . collect ( ) ,
142149 synthetic_expansion_infos : RefCell :: new ( FxHashMap ( ) ) ,
150+ interpret_alloc_cache : RefCell :: new ( FxHashMap :: default ( ) ) ,
151+ interpret_alloc_size : RefCell :: new ( FxHashMap :: default ( ) ) ,
143152 }
144153 }
145154
@@ -155,6 +164,8 @@ impl<'sess> OnDiskCache<'sess> {
155164 query_result_index : FxHashMap ( ) ,
156165 prev_diagnostics_index : FxHashMap ( ) ,
157166 synthetic_expansion_infos : RefCell :: new ( FxHashMap ( ) ) ,
167+ interpret_alloc_cache : RefCell :: new ( FxHashMap :: default ( ) ) ,
168+ interpret_alloc_size : RefCell :: new ( FxHashMap :: default ( ) ) ,
158169 }
159170 }
160171
@@ -381,7 +392,8 @@ impl<'sess> OnDiskCache<'sess> {
381392 file_index_to_file : & self . file_index_to_file ,
382393 file_index_to_stable_id : & self . file_index_to_stable_id ,
383394 synthetic_expansion_infos : & self . synthetic_expansion_infos ,
384- interpret_alloc_cache : FxHashMap :: default ( ) ,
395+ interpret_alloc_cache : & self . interpret_alloc_cache ,
396+ interpret_alloc_size : & self . interpret_alloc_size ,
385397 } ;
386398
387399 match decode_tagged ( & mut decoder, dep_node_index) {
@@ -443,7 +455,8 @@ struct CacheDecoder<'a, 'tcx: 'a, 'x> {
443455 synthetic_expansion_infos : & ' x RefCell < FxHashMap < AbsoluteBytePos , SyntaxContext > > ,
444456 file_index_to_file : & ' x RefCell < FxHashMap < FileMapIndex , Lrc < FileMap > > > ,
445457 file_index_to_stable_id : & ' x FxHashMap < FileMapIndex , StableFilemapId > ,
446- interpret_alloc_cache : FxHashMap < usize , interpret:: AllocId > ,
458+ interpret_alloc_cache : & ' x RefCell < FxHashMap < usize , interpret:: AllocId > > ,
459+ interpret_alloc_size : & ' x RefCell < FxHashMap < usize , usize > > ,
447460}
448461
449462impl < ' a , ' tcx , ' x > CacheDecoder < ' a , ' tcx , ' x > {
@@ -565,47 +578,37 @@ implement_ty_decoder!( CacheDecoder<'a, 'tcx, 'x> );
565578
566579impl < ' a , ' tcx , ' x > SpecializedDecoder < interpret:: AllocId > for CacheDecoder < ' a , ' tcx , ' x > {
567580 fn specialized_decode ( & mut self ) -> Result < interpret:: AllocId , Self :: Error > {
568- const MAX1 : usize = usize:: max_value ( ) - 1 ;
569581 let tcx = self . tcx ;
570582 let pos = TyDecoder :: position ( self ) ;
571- match usize:: decode ( self ) ? {
572- :: std:: usize:: MAX => {
573- let alloc_id = tcx. interpret_interner . reserve ( ) ;
574- trace ! ( "creating alloc id {:?} at {}" , alloc_id, pos) ;
575- // insert early to allow recursive allocs
576- self . interpret_alloc_cache . insert ( pos, alloc_id) ;
577-
578- let allocation = interpret:: Allocation :: decode ( self ) ?;
579- trace ! ( "decoded alloc {:?} {:#?}" , alloc_id, allocation) ;
580- let allocation = self . tcx . intern_const_alloc ( allocation) ;
581- tcx. interpret_interner . intern_at_reserved ( alloc_id, allocation) ;
582-
583- if let Some ( glob) = Option :: < DefId > :: decode ( self ) ? {
584- trace ! ( "connecting alloc {:?} with {:?}" , alloc_id, glob) ;
585- tcx. interpret_interner . cache ( glob, alloc_id) ;
586- }
587-
588- Ok ( alloc_id)
589- } ,
590- MAX1 => {
591- trace ! ( "creating fn alloc id at {}" , pos) ;
592- let instance = ty:: Instance :: decode ( self ) ?;
593- trace ! ( "decoded fn alloc instance: {:?}" , instance) ;
594- let id = tcx. interpret_interner . create_fn_alloc ( instance) ;
595- trace ! ( "created fn alloc id: {:?}" , id) ;
596- self . interpret_alloc_cache . insert ( pos, id) ;
597- Ok ( id)
583+ trace ! ( "specialized_decode_alloc_id: {:?}" , pos) ;
584+ if let Some ( cached) = self . interpret_alloc_cache . borrow ( ) . get ( & pos) . cloned ( ) {
585+ // if there's no end position we are currently deserializing a recursive
586+ // allocation
587+ if let Some ( end) = self . interpret_alloc_size . borrow ( ) . get ( & pos) . cloned ( ) {
588+ trace ! ( "{} already cached as {:?}" , pos, cached) ;
589+ // skip ahead
590+ self . opaque . set_position ( end) ;
591+ return Ok ( cached)
592+ }
593+ }
594+ let id = interpret:: specialized_decode_alloc_id (
595+ self ,
596+ tcx,
597+ pos,
598+ |this, pos, alloc_id| {
599+ assert ! ( this. interpret_alloc_cache. borrow_mut( ) . insert( pos, alloc_id) . is_none( ) ) ;
598600 } ,
599- shorthand => {
600- trace ! ( "loading shorthand {}" , shorthand) ;
601- if let Some ( & alloc_id) = self . interpret_alloc_cache . get ( & shorthand) {
602- return Ok ( alloc_id) ;
603- }
604- trace ! ( "shorthand {} not cached, loading entire allocation" , shorthand) ;
601+ |this, shorthand| {
605602 // need to load allocation
606- self . with_position ( shorthand, |this| interpret:: AllocId :: decode ( this) )
607- } ,
608- }
603+ this. with_position ( shorthand, |this| interpret:: AllocId :: decode ( this) )
604+ }
605+ ) ?;
606+ assert ! ( self
607+ . interpret_alloc_size
608+ . borrow_mut( )
609+ . insert( pos, TyDecoder :: position( self ) )
610+ . is_none( ) ) ;
611+ Ok ( id)
609612 }
610613}
611614impl < ' a , ' tcx , ' x > SpecializedDecoder < Span > for CacheDecoder < ' a , ' tcx , ' x > {
@@ -806,30 +809,27 @@ impl<'enc, 'a, 'tcx, E> SpecializedEncoder<interpret::AllocId> for CacheEncoder<
806809 where E : ' enc + ty_codec:: TyEncoder
807810{
808811 fn specialized_encode ( & mut self , alloc_id : & interpret:: AllocId ) -> Result < ( ) , Self :: Error > {
809- trace ! ( "encoding {:?} at {}" , alloc_id, self . position( ) ) ;
810- if let Some ( shorthand) = self . interpret_alloc_shorthands . get ( alloc_id) . cloned ( ) {
811- trace ! ( "encoding {:?} as shorthand to {}" , alloc_id, shorthand) ;
812- return shorthand. encode ( self ) ;
813- }
814- let start = self . position ( ) ;
815- // cache the allocation shorthand now, because the allocation itself might recursively
816- // point to itself.
817- self . interpret_alloc_shorthands . insert ( * alloc_id, start) ;
818- if let Some ( alloc) = self . tcx . interpret_interner . get_alloc ( * alloc_id) {
819- trace ! ( "encoding {:?} with {:#?}" , alloc_id, alloc) ;
820- usize:: max_value ( ) . encode ( self ) ?;
821- alloc. encode ( self ) ?;
822- self . tcx . interpret_interner
823- . get_corresponding_static_def_id ( * alloc_id)
824- . encode ( self ) ?;
825- } else if let Some ( fn_instance) = self . tcx . interpret_interner . get_fn ( * alloc_id) {
826- trace ! ( "encoding {:?} with {:#?}" , alloc_id, fn_instance) ;
827- ( usize:: max_value ( ) - 1 ) . encode ( self ) ?;
828- fn_instance. encode ( self ) ?;
829- } else {
830- bug ! ( "alloc id without corresponding allocation: {}" , alloc_id) ;
831- }
832- Ok ( ( ) )
812+ use std:: collections:: hash_map:: Entry ;
813+ let tcx = self . tcx ;
814+ let pos = self . position ( ) ;
815+ let shorthand = match self . interpret_alloc_shorthands . entry ( * alloc_id) {
816+ Entry :: Occupied ( entry) => Some ( entry. get ( ) . clone ( ) ) ,
817+ Entry :: Vacant ( entry) => {
818+ // ensure that we don't place any AllocIds at the very beginning
819+ // of the metadata file, because that would end up making our indices
820+ // not special. It is essentially impossible for that to happen,
821+ // but let's make sure
822+ assert ! ( pos != interpret:: ALLOC_DISCRIMINANT && pos != interpret:: FN_DISCRIMINANT ) ;
823+ entry. insert ( pos) ;
824+ None
825+ } ,
826+ } ;
827+ interpret:: specialized_encode_alloc_id (
828+ self ,
829+ tcx,
830+ * alloc_id,
831+ shorthand,
832+ )
833833 }
834834}
835835
0 commit comments