Skip to content

Commit d9ac0c6

Browse files
committed
Rewrite get_size_and_align so it doesn't duplicate work
1 parent b75dfa8 commit d9ac0c6

File tree

1 file changed

+35
-34
lines changed

1 file changed

+35
-34
lines changed

src/librustc_mir/interpret/memory.rs

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -535,40 +535,41 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
535535
id: AllocId,
536536
liveness: AllocCheck,
537537
) -> InterpResult<'static, (Size, Align)> {
538-
// Allocations of `static` items
539-
// Can't do this in the match argument, we may get cycle errors since the lock would
540-
// be held throughout the match.
541-
let alloc = self.tcx.alloc_map.lock().get(id);
542-
match alloc {
543-
Some(GlobalAlloc::Static(did)) => {
544-
// Use size and align of the type
545-
let ty = self.tcx.type_of(did);
546-
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
547-
return Ok((layout.size, layout.align.abi));
548-
}
549-
_ => {}
550-
}
551-
// Regular allocations.
552-
if let Ok(alloc) = self.get(id) {
553-
return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align));
554-
}
555-
// Function pointers.
556-
if let Ok(_) = self.get_fn_alloc(id) {
557-
return if let AllocCheck::Dereferencable = liveness {
558-
// The caller requested no function pointers.
559-
err!(DerefFunctionPointer)
560-
} else {
561-
Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
562-
};
563-
}
564-
// The rest must be dead.
565-
if let AllocCheck::MaybeDead = liveness {
566-
// Deallocated pointers are allowed, we should be able to find
567-
// them in the map.
568-
Ok(*self.dead_alloc_map.get(&id)
569-
.expect("deallocated pointers should all be recorded in `dead_alloc_map`"))
570-
} else {
571-
err!(DanglingPointerDeref)
538+
let alloc_or_size_align = self.alloc_map.get_or(id, || -> Result<_, InterpResult<'static, (Size, Align)>> {
539+
// Can't do this in the match argument, we may get cycle errors since the lock would
540+
// be held throughout the match.
541+
let alloc = self.tcx.alloc_map.lock().get(id);
542+
Err(match alloc {
543+
Some(GlobalAlloc::Static(did)) => {
544+
// Use size and align of the type
545+
let ty = self.tcx.type_of(did);
546+
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
547+
Ok((layout.size, layout.align.abi))
548+
},
549+
Some(GlobalAlloc::Memory(alloc)) =>
550+
// this duplicates the logic on the `match alloc_or_size_align`, but due to the
551+
// API of `get_or` there's no way around that.
552+
Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
553+
Some(GlobalAlloc::Function(_)) => if let AllocCheck::Dereferencable = liveness {
554+
// The caller requested no function pointers.
555+
err!(DerefFunctionPointer)
556+
} else {
557+
Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
558+
},
559+
// The rest must be dead.
560+
None => if let AllocCheck::MaybeDead = liveness {
561+
// Deallocated pointers are allowed, we should be able to find
562+
// them in the map.
563+
Ok(*self.dead_alloc_map.get(&id)
564+
.expect("deallocated pointers should all be recorded in `dead_alloc_map`"))
565+
} else {
566+
err!(DanglingPointerDeref)
567+
},
568+
})
569+
});
570+
match alloc_or_size_align {
571+
Ok((_, alloc)) => Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
572+
Err(done) => done,
572573
}
573574
}
574575

0 commit comments

Comments
 (0)