@@ -24,22 +24,36 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
2424 pub fn get_vtable (
2525 & mut self ,
2626 ty : Ty < ' tcx > ,
27- trait_ref : ty:: PolyTraitRef < ' tcx > ,
27+ poly_trait_ref : Option < ty:: PolyExistentialTraitRef < ' tcx > > ,
2828 ) -> EvalResult < ' tcx , Pointer < M :: PointerTag > > {
29- debug ! ( "get_vtable(trait_ref={:?})" , trait_ref ) ;
29+ debug ! ( "get_vtable(trait_ref={:?})" , poly_trait_ref ) ;
3030
31- // FIXME: Cache this!
31+ let ( ty , poly_trait_ref ) = self . tcx . erase_regions ( & ( ty , poly_trait_ref ) ) ;
3232
33- let layout = self . layout_of ( trait_ref. self_ty ( ) ) ?;
33+ if let Some ( & vtable) = self . vtables . get ( & ( ty, poly_trait_ref) ) {
34+ return Ok ( Pointer :: from ( vtable) . with_default_tag ( ) ) ;
35+ }
36+
37+ let trait_ref = poly_trait_ref. map ( |trait_ref| {
38+ let trait_ref = trait_ref. with_self_ty ( * self . tcx , ty) ;
39+ self . tcx . erase_regions ( & trait_ref)
40+ } ) ;
41+
42+ let methods = trait_ref. map ( |trait_ref| self . tcx . vtable_methods ( trait_ref) ) ;
43+
44+ let layout = self . layout_of ( ty) ?;
3445 assert ! ( !layout. is_unsized( ) , "can't create a vtable for an unsized type" ) ;
3546 let size = layout. size . bytes ( ) ;
3647 let align = layout. align . abi ( ) ;
3748
3849 let ptr_size = self . pointer_size ( ) ;
3950 let ptr_align = self . tcx . data_layout . pointer_align ;
40- let methods = self . tcx . vtable_methods ( trait_ref) ;
51+ // /////////////////////////////////////////////////////////////////////////////////////////
52+ // If you touch this code, be sure to also make the corresponding changes to
53+ // `get_vtable` in rust_codegen_llvm/meth.rs
54+ // /////////////////////////////////////////////////////////////////////////////////////////
4155 let vtable = self . memory . allocate (
42- ptr_size * ( 3 + methods. len ( ) as u64 ) ,
56+ ptr_size * ( 3 + methods. as_ref ( ) . map_or ( 0 , |m| m . len ( ) as u64 ) ) ,
4357 ptr_align,
4458 MemoryKind :: Vtable ,
4559 ) ?;
@@ -54,16 +68,19 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
5468 self . memory . write_ptr_sized ( align_ptr, ptr_align,
5569 Scalar :: from_uint ( align, ptr_size) . into ( ) ) ?;
5670
57- for ( i, method) in methods. iter ( ) . enumerate ( ) {
58- if let Some ( ( def_id, substs) ) = * method {
59- let instance = self . resolve ( def_id, substs) ?;
60- let fn_ptr = self . memory . create_fn_alloc ( instance) ;
61- let method_ptr = vtable. offset ( ptr_size * ( 3 + i as u64 ) , & self ) ?;
62- self . memory . write_ptr_sized ( method_ptr, ptr_align, Scalar :: Ptr ( fn_ptr) . into ( ) ) ?;
71+ if let Some ( methods) = methods {
72+ for ( i, method) in methods. iter ( ) . enumerate ( ) {
73+ if let Some ( ( def_id, substs) ) = * method {
74+ let instance = self . resolve ( def_id, substs) ?;
75+ let fn_ptr = self . memory . create_fn_alloc ( instance) ;
76+ let method_ptr = vtable. offset ( ptr_size * ( 3 + i as u64 ) , & self ) ?;
77+ self . memory . write_ptr_sized ( method_ptr, ptr_align, Scalar :: Ptr ( fn_ptr) . into ( ) ) ?;
78+ }
6379 }
6480 }
6581
6682 self . memory . mark_immutable ( vtable. alloc_id ) ?;
83+ assert ! ( self . vtables. insert( ( ty, poly_trait_ref) , vtable. alloc_id) . is_none( ) ) ;
6784
6885 Ok ( vtable)
6986 }
0 commit comments