Skip to content

Commit 3f30d8a

Browse files
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.
2 parents a8c5950 + de34a91 commit 3f30d8a

File tree

2 files changed

+15
-17
lines changed

2 files changed

+15
-17
lines changed

compiler/rustc_const_eval/src/interpret/visitor.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,15 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
2525
}
2626

2727
/// This function provides the chance to reorder the order in which fields are visited for
28-
/// `FieldsShape::Aggregate`: The order of fields will be
29-
/// `(0..num_fields).map(aggregate_field_order)`.
28+
/// `FieldsShape::Aggregate`.
3029
///
31-
/// The default means we iterate in source declaration order; alternative this can do an inverse
32-
/// lookup in `memory_index` to use memory field order instead.
30+
/// The default means we iterate in source declaration order; alternatively this can do some
31+
/// work with `memory_index` to iterate in memory order.
3332
#[inline(always)]
34-
fn aggregate_field_order(_memory_index: &IndexVec<FieldIdx, u32>, idx: usize) -> usize {
35-
idx
33+
fn aggregate_field_iter(
34+
memory_index: &IndexVec<FieldIdx, u32>,
35+
) -> impl Iterator<Item = FieldIdx> + 'static {
36+
memory_index.indices()
3637
}
3738

3839
// Recursive actions, ready to be overloaded.
@@ -172,9 +173,9 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
172173
&FieldsShape::Union(fields) => {
173174
self.visit_union(v, fields)?;
174175
}
175-
FieldsShape::Arbitrary { offsets, memory_index } => {
176-
for idx in 0..offsets.len() {
177-
let idx = Self::aggregate_field_order(memory_index, idx);
176+
FieldsShape::Arbitrary { memory_index, .. } => {
177+
for idx in Self::aggregate_field_iter(memory_index) {
178+
let idx = idx.as_usize();
178179
let field = self.ecx().project_field(v, idx)?;
179180
self.visit_field(v, idx, &field)?;
180181
}

src/tools/miri/src/helpers.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -630,14 +630,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
630630
self.ecx
631631
}
632632

633-
fn aggregate_field_order(memory_index: &IndexVec<FieldIdx, u32>, idx: usize) -> usize {
634-
// We need to do an *inverse* lookup: find the field that has position `idx` in memory order.
635-
for (src_field, &mem_pos) in memory_index.iter_enumerated() {
636-
if mem_pos as usize == idx {
637-
return src_field.as_usize();
638-
}
639-
}
640-
panic!("invalid `memory_index`, could not find {}-th field in memory order", idx);
633+
fn aggregate_field_iter(
634+
memory_index: &IndexVec<FieldIdx, u32>,
635+
) -> impl Iterator<Item = FieldIdx> + 'static {
636+
let inverse_memory_index = memory_index.invert_bijective_mapping();
637+
inverse_memory_index.into_iter()
641638
}
642639

643640
// Hook to detect `UnsafeCell`.

0 commit comments

Comments
 (0)