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 05b1415f18
commit 9ddcc59411
2 changed files with 17 additions and 4 deletions

View File

@ -593,6 +593,7 @@ pub(crate) fn codegen_drop<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>, fx: &mut FunctionCx<'_, '_, 'tcx>,
source_info: mir::SourceInfo, source_info: mir::SourceInfo,
drop_place: CPlace<'tcx>, drop_place: CPlace<'tcx>,
target: BasicBlock,
) { ) {
let ty = drop_place.layout().ty; let ty = drop_place.layout().ty;
let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty).polymorphize(fx.tcx); let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty).polymorphize(fx.tcx);
@ -620,6 +621,12 @@ pub(crate) fn codegen_drop<'tcx>(
let ptr = ptr.get_addr(fx); let ptr = ptr.get_addr(fx);
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable); let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable);
let is_null = fx.bcx.ins().icmp_imm(IntCC::Equal, drop_fn, 0);
let target_block = fx.get_block(target);
let continued = fx.bcx.create_block();
fx.bcx.ins().brif(is_null, target_block, &[], continued, &[]);
fx.bcx.switch_to_block(continued);
// FIXME(eddyb) perhaps move some of this logic into // FIXME(eddyb) perhaps move some of this logic into
// `Instance::resolve_drop_in_place`? // `Instance::resolve_drop_in_place`?
let virtual_drop = Instance { let virtual_drop = Instance {
@ -659,6 +666,12 @@ pub(crate) fn codegen_drop<'tcx>(
let (data, vtable) = drop_place.to_cvalue(fx).dyn_star_force_data_on_stack(fx); let (data, vtable) = drop_place.to_cvalue(fx).dyn_star_force_data_on_stack(fx);
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable); let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable);
let is_null = fx.bcx.ins().icmp_imm(IntCC::Equal, drop_fn, 0);
let target_block = fx.get_block(target);
let continued = fx.bcx.create_block();
fx.bcx.ins().brif(is_null, target_block, &[], continued, &[]);
fx.bcx.switch_to_block(continued);
let virtual_drop = Instance { let virtual_drop = Instance {
def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0), def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
args: drop_instance.args, args: drop_instance.args,
@ -697,4 +710,7 @@ pub(crate) fn codegen_drop<'tcx>(
} }
} }
} }
let target_block = fx.get_block(target);
fx.bcx.ins().jump(target_block, &[]);
} }

View File

@ -548,10 +548,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
} }
TerminatorKind::Drop { place, target, unwind: _, replace: _ } => { TerminatorKind::Drop { place, target, unwind: _, replace: _ } => {
let drop_place = codegen_place(fx, *place); let drop_place = codegen_place(fx, *place);
crate::abi::codegen_drop(fx, source_info, drop_place); crate::abi::codegen_drop(fx, source_info, drop_place, *target);
let target_block = fx.get_block(*target);
fx.bcx.ins().jump(target_block, &[]);
} }
}; };
} }