Skip to content

Commit

Permalink
YJIT: A64: Remove assert that trips when OOM at page boundary
Browse files Browse the repository at this point in the history
With a well-timed OOM around a page switch in the backend, it can return
RetryOnNextPage twice and crash due to the assert. (More places can
signal OOM now since VirtualMem tracks Rust malloc heap size for
--yjit-mem-size.)

Return error in these cases instead of crashing.

Fixes: #566
  • Loading branch information
XrXr committed Jan 30, 2025
1 parent de45755 commit 5a7089f
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 11 deletions.
5 changes: 3 additions & 2 deletions yjit/src/asm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ impl CodeBlock {

/// Move the CodeBlock to the next page. If it's on the furthest page,
/// move the other CodeBlock to the next page as well.
#[must_use]
pub fn next_page<F: Fn(&mut CodeBlock, CodePtr)>(&mut self, base_ptr: CodePtr, jmp_ptr: F) -> bool {
let old_write_ptr = self.get_write_ptr();
self.set_write_ptr(base_ptr);
Expand Down Expand Up @@ -823,7 +824,7 @@ mod tests
assert_eq!(cb.code_size(), 4);

// Moving to the next page should not increase code_size
cb.next_page(cb.get_write_ptr(), |_, _| {});
assert!(cb.next_page(cb.get_write_ptr(), |_, _| {}));
assert_eq!(cb.code_size(), 4);

// Write 4 bytes in the second page
Expand All @@ -836,7 +837,7 @@ mod tests
cb.write_bytes(&[1, 1, 1, 1]);

// Moving from an old page to the next page should not increase code_size
cb.next_page(cb.get_write_ptr(), |_, _| {});
assert!(cb.next_page(cb.get_write_ptr(), |_, _| {}));
cb.set_pos(old_write_pos);
assert_eq!(cb.code_size(), 8);
}
Expand Down
15 changes: 6 additions & 9 deletions yjit/src/backend/arm64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1341,16 +1341,13 @@ impl Assembler
Err(EmitError::RetryOnNextPage) => {
// we want to lower jumps to labels to b.cond instructions, which have a 1 MiB
// range limit. We can easily exceed the limit in case the jump straddles two pages.
// In this case, we retry with a fresh page.
// In this case, we retry with a fresh page once.
cb.set_label_state(starting_label_state);
cb.next_page(start_ptr, emit_jmp_ptr_with_invalidation);
let result = asm.arm64_emit(cb, &mut ocb);
assert_ne!(
Err(EmitError::RetryOnNextPage),
result,
"should not fail when writing to a fresh code page"
);
result
if cb.next_page(start_ptr, emit_jmp_ptr_with_invalidation) {
asm.arm64_emit(cb, &mut ocb)
} else {
Err(EmitError::OutOfMemory)
}
}
result => result
};
Expand Down

0 comments on commit 5a7089f

Please sign in to comment.