@@ -37,8 +37,8 @@ mod tests;
37
37
mod test_db;
38
38
39
39
use std:: {
40
- collections:: { hash_map:: Entry , HashMap } ,
41
- hash:: Hash ,
40
+ collections:: hash_map:: Entry ,
41
+ hash:: { BuildHasherDefault , Hash } ,
42
42
} ;
43
43
44
44
use chalk_ir:: {
@@ -52,7 +52,7 @@ use hir_def::{hir::ExprId, type_ref::Rawness, GeneralConstId, TypeOrConstParamId
52
52
use hir_expand:: name;
53
53
use la_arena:: { Arena , Idx } ;
54
54
use mir:: { MirEvalError , VTableMap } ;
55
- use rustc_hash:: FxHashSet ;
55
+ use rustc_hash:: { FxHashMap , FxHashSet } ;
56
56
use syntax:: ast:: { make, ConstArg } ;
57
57
use traits:: FnTrait ;
58
58
use triomphe:: Arc ;
@@ -171,47 +171,79 @@ pub type Variances = chalk_ir::Variances<Interner>;
171
171
/// the necessary bits of memory of the const eval session to keep the constant
172
172
/// meaningful.
173
173
#[ 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 > ) ,
177
179
}
178
180
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 ] > ) {
181
189
match self . memory . entry ( addr) {
182
190
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 ) ;
185
193
}
186
194
}
187
195
Entry :: Vacant ( e) => {
188
- e. insert ( x ) ;
196
+ e. insert ( val ) ;
189
197
}
190
198
}
191
199
}
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
+ }
192
213
193
214
/// This functions convert each address by a function `f` which gets the byte intervals and assign an address
194
215
/// to them. It is useful when you want to load a constant with a memory map in a new memory. You can pass an
195
216
/// allocator function as `f` and it will return a mapping of old addresses to new addresses.
196
217
fn transform_addresses (
197
218
& self ,
198
219
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
+ }
208
235
}
209
236
210
- fn get < ' a > ( & ' a self , addr : usize , size : usize ) -> Option < & ' a [ u8 ] > {
237
+ fn get ( & self , addr : usize , size : usize ) -> Option < & [ u8 ] > {
211
238
if size == 0 {
212
239
Some ( & [ ] )
213
240
} 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
+ }
215
247
}
216
248
}
217
249
}
0 commit comments