Rollup merge of #129751 - RalfJung:interpret-visit-field-order, r=compiler-errors
interpret/visitor: make memory order iteration slightly more efficient Finally I know enough about RPIT to write this iterator signature correctly. :D This means memory-order iteration now needs an allocation, but it avoids quadratic complexity (where it has to do a linear scan n times to find the n-th field in memory order), so that seems like a win overall. The changed code only affects Miri; the rustc changes are NOPs.
This commit is contained in:
commit
a59c1a4291
@ -25,14 +25,15 @@ fn read_discriminant(&mut self, v: &Self::V) -> InterpResult<'tcx, VariantIdx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This function provides the chance to reorder the order in which fields are visited for
|
/// This function provides the chance to reorder the order in which fields are visited for
|
||||||
/// `FieldsShape::Aggregate`: The order of fields will be
|
/// `FieldsShape::Aggregate`.
|
||||||
/// `(0..num_fields).map(aggregate_field_order)`.
|
|
||||||
///
|
///
|
||||||
/// The default means we iterate in source declaration order; alternative this can do an inverse
|
/// The default means we iterate in source declaration order; alternatively this can do some
|
||||||
/// lookup in `memory_index` to use memory field order instead.
|
/// work with `memory_index` to iterate in memory order.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn aggregate_field_order(_memory_index: &IndexVec<FieldIdx, u32>, idx: usize) -> usize {
|
fn aggregate_field_iter(
|
||||||
idx
|
memory_index: &IndexVec<FieldIdx, u32>,
|
||||||
|
) -> impl Iterator<Item = FieldIdx> + 'static {
|
||||||
|
memory_index.indices()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursive actions, ready to be overloaded.
|
// Recursive actions, ready to be overloaded.
|
||||||
@ -172,9 +173,9 @@ fn walk_value(&mut self, v: &Self::V) -> InterpResult<'tcx> {
|
|||||||
&FieldsShape::Union(fields) => {
|
&FieldsShape::Union(fields) => {
|
||||||
self.visit_union(v, fields)?;
|
self.visit_union(v, fields)?;
|
||||||
}
|
}
|
||||||
FieldsShape::Arbitrary { offsets, memory_index } => {
|
FieldsShape::Arbitrary { memory_index, .. } => {
|
||||||
for idx in 0..offsets.len() {
|
for idx in Self::aggregate_field_iter(memory_index) {
|
||||||
let idx = Self::aggregate_field_order(memory_index, idx);
|
let idx = idx.as_usize();
|
||||||
let field = self.ecx().project_field(v, idx)?;
|
let field = self.ecx().project_field(v, idx)?;
|
||||||
self.visit_field(v, idx, &field)?;
|
self.visit_field(v, idx, &field)?;
|
||||||
}
|
}
|
||||||
|
@ -630,14 +630,11 @@ fn ecx(&self) -> &MiriInterpCx<'tcx> {
|
|||||||
self.ecx
|
self.ecx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn aggregate_field_order(memory_index: &IndexVec<FieldIdx, u32>, idx: usize) -> usize {
|
fn aggregate_field_iter(
|
||||||
// We need to do an *inverse* lookup: find the field that has position `idx` in memory order.
|
memory_index: &IndexVec<FieldIdx, u32>,
|
||||||
for (src_field, &mem_pos) in memory_index.iter_enumerated() {
|
) -> impl Iterator<Item = FieldIdx> + 'static {
|
||||||
if mem_pos as usize == idx {
|
let inverse_memory_index = memory_index.invert_bijective_mapping();
|
||||||
return src_field.as_usize();
|
inverse_memory_index.into_iter()
|
||||||
}
|
|
||||||
}
|
|
||||||
panic!("invalid `memory_index`, could not find {}-th field in memory order", idx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook to detect `UnsafeCell`.
|
// Hook to detect `UnsafeCell`.
|
||||||
|
Loading…
Reference in New Issue
Block a user