@@ -43,77 +43,72 @@ pub const COMMON_VTABLE_ENTRIES_DROPINPLACE: usize = 0;
4343pub const COMMON_VTABLE_ENTRIES_SIZE : usize = 1 ;
4444pub const COMMON_VTABLE_ENTRIES_ALIGN : usize = 2 ;
4545
46- impl < ' tcx > TyCtxt < ' tcx > {
47- /// Retrieves an allocation that represents the contents of a vtable.
48- /// There's a cache within `TyCtxt` so it will be deduplicated.
49- pub fn vtable_allocation (
50- self ,
51- ty : Ty < ' tcx > ,
52- poly_trait_ref : Option < ty:: PolyExistentialTraitRef < ' tcx > > ,
53- ) -> AllocId {
54- let tcx = self ;
46+ /// Retrieves an allocation that represents the contents of a vtable.
47+ /// Since this is a query, allocations are cached and not duplicated.
48+ pub ( super ) fn vtable_allocation_provider < ' tcx > (
49+ tcx : TyCtxt < ' tcx > ,
50+ key : ( Ty < ' tcx > , Option < ty:: PolyExistentialTraitRef < ' tcx > > ) ,
51+ ) -> AllocId {
52+ let ( ty, poly_trait_ref) = key;
5553
56- let vtable_entries = if let Some ( poly_trait_ref) = poly_trait_ref {
57- let trait_ref = poly_trait_ref. with_self_ty ( tcx, ty) ;
58- let trait_ref = tcx. erase_regions ( trait_ref) ;
54+ let vtable_entries = if let Some ( poly_trait_ref) = poly_trait_ref {
55+ let trait_ref = poly_trait_ref. with_self_ty ( tcx, ty) ;
56+ let trait_ref = tcx. erase_regions ( trait_ref) ;
5957
60- tcx. vtable_entries ( trait_ref)
61- } else {
62- COMMON_VTABLE_ENTRIES
63- } ;
64-
65- let layout = tcx
66- . layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( ty) )
67- . expect ( "failed to build vtable representation" ) ;
68- assert ! ( !layout. is_unsized( ) , "can't create a vtable for an unsized type" ) ;
69- let size = layout. size . bytes ( ) ;
70- let align = layout. align . abi . bytes ( ) ;
58+ tcx. vtable_entries ( trait_ref)
59+ } else {
60+ COMMON_VTABLE_ENTRIES
61+ } ;
7162
72- let ptr_size = tcx. data_layout . pointer_size ;
73- let ptr_align = tcx. data_layout . pointer_align . abi ;
63+ let layout = tcx
64+ . layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( ty) )
65+ . expect ( "failed to build vtable representation" ) ;
66+ assert ! ( !layout. is_unsized( ) , "can't create a vtable for an unsized type" ) ;
67+ let size = layout. size . bytes ( ) ;
68+ let align = layout. align . abi . bytes ( ) ;
7469
75- let vtable_size = ptr_size * u64:: try_from ( vtable_entries. len ( ) ) . unwrap ( ) ;
76- let mut vtable =
77- Allocation :: uninit ( vtable_size, ptr_align, /* panic_on_fail */ true ) . unwrap ( ) ;
70+ let ptr_size = tcx. data_layout . pointer_size ;
71+ let ptr_align = tcx. data_layout . pointer_align . abi ;
7872
79- // No need to do any alignment checks on the memory accesses below, because we know the
80- // allocation is correctly aligned as we created it above. Also we're only offsetting by
81- // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`.
73+ let vtable_size = ptr_size * u64:: try_from ( vtable_entries. len ( ) ) . unwrap ( ) ;
74+ let mut vtable = Allocation :: uninit ( vtable_size, ptr_align, /* panic_on_fail */ true ) . unwrap ( ) ;
8275
83- for ( idx, entry) in vtable_entries. iter ( ) . enumerate ( ) {
84- let idx: u64 = u64:: try_from ( idx) . unwrap ( ) ;
85- let scalar = match entry {
86- VtblEntry :: MetadataDropInPlace => {
87- let instance = ty:: Instance :: resolve_drop_in_place ( tcx, ty) ;
88- let fn_alloc_id = tcx. create_fn_alloc ( instance) ;
89- let fn_ptr = Pointer :: from ( fn_alloc_id) ;
90- ScalarMaybeUninit :: from_pointer ( fn_ptr, & tcx)
91- }
92- VtblEntry :: MetadataSize => Scalar :: from_uint ( size, ptr_size) . into ( ) ,
93- VtblEntry :: MetadataAlign => Scalar :: from_uint ( align, ptr_size) . into ( ) ,
94- VtblEntry :: Vacant => continue ,
95- VtblEntry :: Method ( instance) => {
96- // Prepare the fn ptr we write into the vtable.
97- let instance = instance. polymorphize ( tcx) ;
98- let fn_alloc_id = tcx. create_fn_alloc ( instance) ;
99- let fn_ptr = Pointer :: from ( fn_alloc_id) ;
100- ScalarMaybeUninit :: from_pointer ( fn_ptr, & tcx)
101- }
102- VtblEntry :: TraitVPtr ( trait_ref) => {
103- let super_trait_ref = trait_ref. map_bound ( |trait_ref| {
104- ty:: ExistentialTraitRef :: erase_self_ty ( tcx, trait_ref)
105- } ) ;
106- let supertrait_alloc_id = self . vtable_allocation ( ty, Some ( super_trait_ref) ) ;
107- let vptr = Pointer :: from ( supertrait_alloc_id) ;
108- ScalarMaybeUninit :: from_pointer ( vptr, & tcx)
109- }
110- } ;
111- vtable
112- . write_scalar ( & tcx, alloc_range ( ptr_size * idx, ptr_size) , scalar)
113- . expect ( "failed to build vtable representation" ) ;
114- }
76+ // No need to do any alignment checks on the memory accesses below, because we know the
77+ // allocation is correctly aligned as we created it above. Also we're only offsetting by
78+ // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`.
11579
116- vtable. mutability = Mutability :: Not ;
117- tcx. create_memory_alloc ( tcx. intern_const_alloc ( vtable) )
80+ for ( idx, entry) in vtable_entries. iter ( ) . enumerate ( ) {
81+ let idx: u64 = u64:: try_from ( idx) . unwrap ( ) ;
82+ let scalar = match entry {
83+ VtblEntry :: MetadataDropInPlace => {
84+ let instance = ty:: Instance :: resolve_drop_in_place ( tcx, ty) ;
85+ let fn_alloc_id = tcx. create_fn_alloc ( instance) ;
86+ let fn_ptr = Pointer :: from ( fn_alloc_id) ;
87+ ScalarMaybeUninit :: from_pointer ( fn_ptr, & tcx)
88+ }
89+ VtblEntry :: MetadataSize => Scalar :: from_uint ( size, ptr_size) . into ( ) ,
90+ VtblEntry :: MetadataAlign => Scalar :: from_uint ( align, ptr_size) . into ( ) ,
91+ VtblEntry :: Vacant => continue ,
92+ VtblEntry :: Method ( instance) => {
93+ // Prepare the fn ptr we write into the vtable.
94+ let instance = instance. polymorphize ( tcx) ;
95+ let fn_alloc_id = tcx. create_fn_alloc ( instance) ;
96+ let fn_ptr = Pointer :: from ( fn_alloc_id) ;
97+ ScalarMaybeUninit :: from_pointer ( fn_ptr, & tcx)
98+ }
99+ VtblEntry :: TraitVPtr ( trait_ref) => {
100+ let super_trait_ref = trait_ref
101+ . map_bound ( |trait_ref| ty:: ExistentialTraitRef :: erase_self_ty ( tcx, trait_ref) ) ;
102+ let supertrait_alloc_id = tcx. vtable_allocation ( ( ty, Some ( super_trait_ref) ) ) ;
103+ let vptr = Pointer :: from ( supertrait_alloc_id) ;
104+ ScalarMaybeUninit :: from_pointer ( vptr, & tcx)
105+ }
106+ } ;
107+ vtable
108+ . write_scalar ( & tcx, alloc_range ( ptr_size * idx, ptr_size) , scalar)
109+ . expect ( "failed to build vtable representation" ) ;
118110 }
111+
112+ vtable. mutability = Mutability :: Not ;
113+ tcx. create_memory_alloc ( tcx. intern_const_alloc ( vtable) )
119114}
0 commit comments