@@ -189,6 +189,22 @@ impl<'tcx> OpTy<'tcx> {
189
189
}
190
190
}
191
191
192
+ // Use the existing layout if given (but sanity check in debug mode),
193
+ // or compute the layout.
194
+ #[ inline( always) ]
195
+ fn from_known_layout < ' tcx > (
196
+ layout : Option < TyLayout < ' tcx > > ,
197
+ compute : impl FnOnce ( ) -> EvalResult < ' tcx , TyLayout < ' tcx > >
198
+ ) -> EvalResult < ' tcx , TyLayout < ' tcx > > {
199
+ match layout {
200
+ None => compute ( ) ,
201
+ Some ( layout) => {
202
+ debug_assert_eq ! ( layout. ty, compute( ) ?. ty) ;
203
+ Ok ( layout)
204
+ }
205
+ }
206
+ }
207
+
192
208
impl < ' a , ' mir , ' tcx , M : Machine < ' mir , ' tcx > > EvalContext < ' a , ' mir , ' tcx , M > {
193
209
/// Try reading a value in memory; this is interesting particularily for ScalarPair.
194
210
/// Return None if the layout does not permit loading this as a value.
@@ -377,21 +393,25 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
377
393
}
378
394
379
395
// Evaluate a place with the goal of reading from it. This lets us sometimes
380
- // avoid allocations.
396
+ // avoid allocations. If you already know the layout, you can pass it in
397
+ // to avoid looking it up again.
381
398
fn eval_place_to_op (
382
399
& mut self ,
383
400
mir_place : & mir:: Place < ' tcx > ,
401
+ layout : Option < TyLayout < ' tcx > > ,
384
402
) -> EvalResult < ' tcx , OpTy < ' tcx > > {
385
403
use rustc:: mir:: Place :: * ;
386
404
Ok ( match * mir_place {
387
405
Local ( mir:: RETURN_PLACE ) => return err ! ( ReadFromReturnPointer ) ,
388
406
Local ( local) => {
389
407
let op = * self . frame ( ) . locals [ local] . access ( ) ?;
390
- OpTy { op, layout : self . layout_of_local ( self . cur_frame ( ) , local) ? }
408
+ let layout = from_known_layout ( layout,
409
+ || self . layout_of_local ( self . cur_frame ( ) , local) ) ?;
410
+ OpTy { op, layout }
391
411
} ,
392
412
393
413
Projection ( ref proj) => {
394
- let op = self . eval_place_to_op ( & proj. base ) ?;
414
+ let op = self . eval_place_to_op ( & proj. base , None ) ?;
395
415
self . operand_projection ( op, & proj. elem ) ?
396
416
}
397
417
@@ -406,17 +426,25 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
406
426
}
407
427
408
428
/// Evaluate the operand, returning a place where you can then find the data.
409
- pub fn eval_operand ( & mut self , mir_op : & mir:: Operand < ' tcx > ) -> EvalResult < ' tcx , OpTy < ' tcx > > {
429
+ /// if you already know the layout, you can save two some table lookups
430
+ /// by passing it in here.
431
+ pub fn eval_operand (
432
+ & mut self ,
433
+ mir_op : & mir:: Operand < ' tcx > ,
434
+ layout : Option < TyLayout < ' tcx > > ,
435
+ ) -> EvalResult < ' tcx , OpTy < ' tcx > > {
410
436
use rustc:: mir:: Operand :: * ;
411
437
let op = match * mir_op {
412
438
// FIXME: do some more logic on `move` to invalidate the old location
413
439
Copy ( ref place) |
414
440
Move ( ref place) =>
415
- self . eval_place_to_op ( place) ?,
441
+ self . eval_place_to_op ( place, layout ) ?,
416
442
417
443
Constant ( ref constant) => {
418
- let ty = self . monomorphize ( mir_op. ty ( self . mir ( ) , * self . tcx ) , self . substs ( ) ) ;
419
- let layout = self . layout_of ( ty) ?;
444
+ let layout = from_known_layout ( layout, || {
445
+ let ty = self . monomorphize ( mir_op. ty ( self . mir ( ) , * self . tcx ) , self . substs ( ) ) ;
446
+ self . layout_of ( ty)
447
+ } ) ?;
420
448
let op = self . const_value_to_op ( constant. literal . val ) ?;
421
449
OpTy { op, layout }
422
450
}
@@ -431,7 +459,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
431
459
ops : & [ mir:: Operand < ' tcx > ] ,
432
460
) -> EvalResult < ' tcx , Vec < OpTy < ' tcx > > > {
433
461
ops. into_iter ( )
434
- . map ( |op| self . eval_operand ( op) )
462
+ . map ( |op| self . eval_operand ( op, None ) )
435
463
. collect ( )
436
464
}
437
465
@@ -473,7 +501,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
473
501
& mut self ,
474
502
op : & mir:: Operand < ' tcx > ,
475
503
) -> EvalResult < ' tcx , ValTy < ' tcx > > {
476
- let op = self . eval_operand ( op) ?;
504
+ let op = self . eval_operand ( op, None ) ?;
477
505
self . read_value ( op)
478
506
}
479
507
pub fn eval_operand_and_read_scalar (
0 commit comments