1
Fork 0

Omit non-needs_drop drop_in_place in vtables

This replaces the drop_in_place reference with null in vtables. On
librustc_driver.so, this drops about ~17k dynamic relocations from the
output, since many vtables can now be placed in read-only memory, rather
than having a relocated pointer included.

This makes a tradeoff by adding a null check at vtable call sites.
That's hard to avoid without changing the vtable format (e.g., to use a
pc-relative relocation instead of an absolute address, and avoid the
dynamic relocation that way). But it seems likely that the check is
cheap at runtime.
This commit is contained in:
Mark Rousskov 2024-03-17 17:42:37 -04:00
parent b0f8618938
commit 4c002fce9d
7 changed files with 203 additions and 116 deletions

View file

@ -15,12 +15,13 @@ impl<'a, 'tcx> VirtualIndex {
VirtualIndex(index as u64)
}
pub fn get_fn<Bx: BuilderMethods<'a, 'tcx>>(
fn get_fn_inner<Bx: BuilderMethods<'a, 'tcx>>(
self,
bx: &mut Bx,
llvtable: Bx::Value,
ty: Ty<'tcx>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
nonnull: bool,
) -> Bx::Value {
// Load the function pointer from the object.
debug!("get_fn({llvtable:?}, {ty:?}, {self:?})");
@ -41,13 +42,35 @@ impl<'a, 'tcx> VirtualIndex {
} else {
let gep = bx.inbounds_ptradd(llvtable, bx.const_usize(vtable_byte_offset));
let ptr = bx.load(llty, gep, ptr_align);
bx.nonnull_metadata(ptr);
// VTable loads are invariant.
bx.set_invariant_load(ptr);
if nonnull {
bx.nonnull_metadata(ptr);
}
ptr
}
}
pub fn get_optional_fn<Bx: BuilderMethods<'a, 'tcx>>(
self,
bx: &mut Bx,
llvtable: Bx::Value,
ty: Ty<'tcx>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
) -> Bx::Value {
self.get_fn_inner(bx, llvtable, ty, fn_abi, false)
}
pub fn get_fn<Bx: BuilderMethods<'a, 'tcx>>(
self,
bx: &mut Bx,
llvtable: Bx::Value,
ty: Ty<'tcx>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
) -> Bx::Value {
self.get_fn_inner(bx, llvtable, ty, fn_abi, true)
}
pub fn get_usize<Bx: BuilderMethods<'a, 'tcx>>(
self,
bx: &mut Bx,