@@ -37,8 +37,8 @@ mod tests;
3737mod test_db;
3838
3939use std:: {
40- collections:: { hash_map:: Entry , HashMap } ,
41- hash:: Hash ,
40+ collections:: hash_map:: Entry ,
41+ hash:: { BuildHasherDefault , Hash } ,
4242} ;
4343
4444use chalk_ir:: {
@@ -52,7 +52,7 @@ use hir_def::{hir::ExprId, type_ref::Rawness, GeneralConstId, TypeOrConstParamId
5252use hir_expand:: name;
5353use la_arena:: { Arena , Idx } ;
5454use mir:: { MirEvalError , VTableMap } ;
55- use rustc_hash:: FxHashSet ;
55+ use rustc_hash:: { FxHashMap , FxHashSet } ;
5656use syntax:: ast:: { make, ConstArg } ;
5757use traits:: FnTrait ;
5858use triomphe:: Arc ;
@@ -171,47 +171,79 @@ pub type Variances = chalk_ir::Variances<Interner>;
171171/// the necessary bits of memory of the const eval session to keep the constant
172172/// meaningful.
173173#[ derive( Debug , Default , Clone , PartialEq , Eq ) ]
174- pub struct MemoryMap {
175- pub memory : HashMap < usize , Vec < u8 > > ,
176- pub vtable : VTableMap ,
174+ pub enum MemoryMap {
175+ #[ default]
176+ Empty ,
177+ Simple ( Box < [ u8 ] > ) ,
178+ Complex ( Box < ComplexMemoryMap > ) ,
177179}
178180
179- impl MemoryMap {
180- fn insert ( & mut self , addr : usize , x : Vec < u8 > ) {
181+ #[ derive( Debug , Default , Clone , PartialEq , Eq ) ]
182+ pub struct ComplexMemoryMap {
183+ memory : FxHashMap < usize , Box < [ u8 ] > > ,
184+ vtable : VTableMap ,
185+ }
186+
187+ impl ComplexMemoryMap {
188+ fn insert ( & mut self , addr : usize , val : Box < [ u8 ] > ) {
181189 match self . memory . entry ( addr) {
182190 Entry :: Occupied ( mut e) => {
183- if e. get ( ) . len ( ) < x . len ( ) {
184- e. insert ( x ) ;
191+ if e. get ( ) . len ( ) < val . len ( ) {
192+ e. insert ( val ) ;
185193 }
186194 }
187195 Entry :: Vacant ( e) => {
188- e. insert ( x ) ;
196+ e. insert ( val ) ;
189197 }
190198 }
191199 }
200+ }
201+
202+ impl MemoryMap {
203+ pub fn vtable_ty ( & self , id : usize ) -> Result < & Ty , MirEvalError > {
204+ match self {
205+ MemoryMap :: Empty | MemoryMap :: Simple ( _) => Err ( MirEvalError :: InvalidVTableId ( id) ) ,
206+ MemoryMap :: Complex ( cm) => cm. vtable . ty ( id) ,
207+ }
208+ }
209+
210+ fn simple ( v : Box < [ u8 ] > ) -> Self {
211+ MemoryMap :: Simple ( v)
212+ }
192213
193214 /// This functions convert each address by a function `f` which gets the byte intervals and assign an address
194215 /// to them. It is useful when you want to load a constant with a memory map in a new memory. You can pass an
195216 /// allocator function as `f` and it will return a mapping of old addresses to new addresses.
196217 fn transform_addresses (
197218 & self ,
198219 mut f : impl FnMut ( & [ u8 ] , usize ) -> Result < usize , MirEvalError > ,
199- ) -> Result < HashMap < usize , usize > , MirEvalError > {
200- self . memory
201- . iter ( )
202- . map ( |x| {
203- let addr = * x. 0 ;
204- let align = if addr == 0 { 64 } else { ( addr - ( addr & ( addr - 1 ) ) ) . min ( 64 ) } ;
205- Ok ( ( addr, f ( x. 1 , align) ?) )
206- } )
207- . collect ( )
220+ ) -> Result < FxHashMap < usize , usize > , MirEvalError > {
221+ let mut transform = |( addr, val) : ( & usize , & Box < [ u8 ] > ) | {
222+ let addr = * addr;
223+ let align = if addr == 0 { 64 } else { ( addr - ( addr & ( addr - 1 ) ) ) . min ( 64 ) } ;
224+ f ( val, align) . and_then ( |it| Ok ( ( addr, it) ) )
225+ } ;
226+ match self {
227+ MemoryMap :: Empty => Ok ( Default :: default ( ) ) ,
228+ MemoryMap :: Simple ( m) => transform ( ( & 0 , m) ) . map ( |( addr, val) | {
229+ let mut map = FxHashMap :: with_capacity_and_hasher ( 1 , BuildHasherDefault :: default ( ) ) ;
230+ map. insert ( addr, val) ;
231+ map
232+ } ) ,
233+ MemoryMap :: Complex ( cm) => cm. memory . iter ( ) . map ( transform) . collect ( ) ,
234+ }
208235 }
209236
210- fn get < ' a > ( & ' a self , addr : usize , size : usize ) -> Option < & ' a [ u8 ] > {
237+ fn get ( & self , addr : usize , size : usize ) -> Option < & [ u8 ] > {
211238 if size == 0 {
212239 Some ( & [ ] )
213240 } else {
214- self . memory . get ( & addr) ?. get ( 0 ..size)
241+ match self {
242+ MemoryMap :: Empty => Some ( & [ ] ) ,
243+ MemoryMap :: Simple ( m) if addr == 0 => m. get ( 0 ..size) ,
244+ MemoryMap :: Simple ( _) => None ,
245+ MemoryMap :: Complex ( cm) => cm. memory . get ( & addr) ?. get ( 0 ..size) ,
246+ }
215247 }
216248 }
217249}
0 commit comments