@@ -173,17 +173,41 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
173173 //
174174 // As an optimization, however, if the allocation does not contain any pointers: we don't
175175 // need to do the walk. It can be costly for big arrays for example (e.g. issue #93215).
176+ let is_walk_needed = |mplace : & MPlaceTy < ' tcx > | -> InterpResult < ' tcx , bool > {
177+ // ZSTs cannot contain pointers, we can avoid the interning walk.
178+ if mplace. layout . is_zst ( ) {
179+ return Ok ( false ) ;
180+ }
181+
182+ // Now, check whether this alloc contains reference types (as relocations).
183+
184+ // FIXME(lqd): checking the size and alignment could be expensive here, only do the
185+ // following for the potentially bigger aggregates like arrays and slices.
186+ let Some ( ( size, align) ) = self . ecx . size_and_align_of_mplace ( & mplace) ? else {
187+ // We do the walk if we can't determine the size of the mplace: we may be dealing
188+ // with extern types here in the future.
189+ return Ok ( true ) ;
190+ } ;
176191
177- let Some ( ( size, align) ) = self . ecx . size_and_align_of_mplace ( & mplace) ? else {
178- // We could be dealing with an extern type here in the future, so we do the regular
192+ // If there are no refs or relocations in this allocation, we can avoid the interning
179193 // walk.
180- return self . walk_aggregate ( mplace, fields) ;
194+ if let Some ( alloc) = self . ecx . get_ptr_alloc ( mplace. ptr , size, align) ?
195+ && !alloc. has_relocations ( ) {
196+ return Ok ( false ) ;
197+ }
198+
199+ // In the general case, we do the walk.
200+ Ok ( true )
181201 } ;
182202
183- let Some ( alloc) = self . ecx . get_ptr_alloc ( mplace. ptr , size, align) ? else {
184- // ZSTs cannot contain pointers, so we can skip them.
203+ // If this allocation contains no references to intern, we avoid the potentially costly
204+ // walk.
205+ //
206+ // We can do this before the checks for interior mutability below, because only references
207+ // are relevant in that situation, and we're checking if there are any here.
208+ if !is_walk_needed ( mplace) ? {
185209 return Ok ( ( ) ) ;
186- } ;
210+ }
187211
188212 if let Some ( def) = mplace. layout . ty . ty_adt_def ( ) {
189213 if Some ( def. did ( ) ) == self . ecx . tcx . lang_items ( ) . unsafe_cell_type ( ) {
@@ -198,11 +222,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
198222 }
199223 }
200224
201- if !alloc. has_relocations ( ) {
202- // There are no refs or relocations in this allocation, we can skip the interning walk.
203- return Ok ( ( ) ) ;
204- }
205-
206225 self . walk_aggregate ( mplace, fields)
207226 }
208227
0 commit comments