Stop doing fuzzy search for stack maps

The new backends will not emit a stack map for a safepoint if there are zero
live references. Our fuzzy search for stack maps, which was necessary for the
old backend, caused us to use the wrong stack map for some PCs which would in
turn cause us to treat arbitrary stack slots as reference types pointers.
This commit is contained in:
Nick Fitzgerald
2021-09-01 15:40:18 -07:00
parent 4b256ab968
commit ec4e48d4cb

View File

@@ -122,13 +122,29 @@ impl ModuleInfo for RegisteredModule {
let info = self.module.func_info(index); let info = self.module.func_info(index);
// Do a binary search to find the stack map for the given offset. // Do a binary search to find the stack map for the given offset.
let index = match info
.stack_maps
.binary_search_by_key(&func_offset, |i| i.code_offset)
{
// Found it.
Ok(i) => i,
// No stack map associated with this PC.
// //
// Because GC safepoints are technically only associated with a single // Because we know we are in Wasm code, and we must be at some kind
// PC, we should ideally only care about `Ok(index)` values returned // of call/safepoint, then the Cranelift backend must have avoided
// from the binary search. However, safepoints are inserted right before // emitting a stack map for this location because no refs were live.
// calls, and there are two things that can disturb the PC/offset #[cfg(not(feature = "old-x86-backend"))]
// associated with the safepoint versus the PC we actually use to query Err(_) => return None,
// for the stack map:
// ### Old x86_64 backend specific code.
//
// Because GC safepoints are technically only associated with a
// single PC, we should ideally only care about `Ok(index)` values
// returned from the binary search. However, safepoints are inserted
// right before calls, and there are two things that can disturb the
// PC/offset associated with the safepoint versus the PC we actually
// use to query for the stack map:
// //
// 1. The `backtrace` crate gives us the PC in a frame that will be // 1. The `backtrace` crate gives us the PC in a frame that will be
// *returned to*, and where execution will continue from, rather than // *returned to*, and where execution will continue from, rather than
@@ -162,21 +178,9 @@ impl ModuleInfo for RegisteredModule {
// (which would not have been updated to point to the moved objects) // (which would not have been updated to point to the moved objects)
// or reload from the stack slots (which would have been updated to // or reload from the stack slots (which would have been updated to
// point to the moved objects). // point to the moved objects).
#[cfg(feature = "old-x86-backend")]
let index = match info
.stack_maps
.binary_search_by_key(&func_offset, |i| i.code_offset)
{
// Exact hit.
Ok(i) => i,
// `Err(0)` means that the associated stack map would have been the
// first element in the array if this pc had an associated stack
// map, but this pc does not have an associated stack map. This can
// only happen inside a Wasm frame if there are no live refs at this
// pc.
Err(0) => return None, Err(0) => return None,
#[cfg(feature = "old-x86-backend")]
Err(i) => i - 1, Err(i) => i - 1,
}; };