const alloc interning: only check for references for arrays/slices

Checking the size/alignment of an mplace may be costly, so we only do it
on the types where the walk we want to avoid could be expensive: the larger types
like arrays and slices, rather than on all aggregates being interned.
This commit is contained in:
Rémy Rakic 2022-06-13 17:35:00 +02:00
parent 18cbc19de2
commit c9772d7619

View File

@ -179,22 +179,26 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
return Ok(false);
}
// Now, check whether this alloc contains reference types (as relocations).
// FIXME(lqd): checking the size and alignment could be expensive here, only do the
// following for the potentially bigger aggregates like arrays and slices.
// Now, check whether this allocation contains reference types (as relocations).
//
// Note, this check may sometimes not be cheap, so we only do it when the walk we'd like
// to avoid could be expensive: on the potentially larger types, arrays and slices,
// rather than on all aggregates unconditionally.
if matches!(mplace.layout.ty.kind(), ty::Array(..) | ty::Slice(..)) {
let Some((size, align)) = self.ecx.size_and_align_of_mplace(&mplace)? else {
// We do the walk if we can't determine the size of the mplace: we may be dealing
// with extern types here in the future.
// We do the walk if we can't determine the size of the mplace: we may be
// dealing with extern types here in the future.
return Ok(true);
};
// If there are no refs or relocations in this allocation, we can avoid the interning
// walk.
if let Some(alloc) = self.ecx.get_ptr_alloc(mplace.ptr, size, align)?
&& !alloc.has_relocations() {
// If there are no refs or relocations in this allocation, we can avoid the
// interning walk.
if let Some(alloc) = self.ecx.get_ptr_alloc(mplace.ptr, size, align)? {
if !alloc.has_relocations() {
return Ok(false);
}
}
}
// In the general case, we do the walk.
Ok(true)