Skip to content

Commit 5a7089f

Browse files
committed
YJIT: A64: Remove assert that trips when OOM at page boundary
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: Shopify#566
1 parent de45755 commit 5a7089f

File tree

2 files changed

+9
-11
lines changed

2 files changed

+9
-11
lines changed

yjit/src/asm/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ impl CodeBlock {
145145

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

825826
// Moving to the next page should not increase code_size
826-
cb.next_page(cb.get_write_ptr(), |_, _| {});
827+
assert!(cb.next_page(cb.get_write_ptr(), |_, _| {}));
827828
assert_eq!(cb.code_size(), 4);
828829

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

838839
// Moving from an old page to the next page should not increase code_size
839-
cb.next_page(cb.get_write_ptr(), |_, _| {});
840+
assert!(cb.next_page(cb.get_write_ptr(), |_, _| {}));
840841
cb.set_pos(old_write_pos);
841842
assert_eq!(cb.code_size(), 8);
842843
}

yjit/src/backend/arm64/mod.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,16 +1341,13 @@ impl Assembler
13411341
Err(EmitError::RetryOnNextPage) => {
13421342
// we want to lower jumps to labels to b.cond instructions, which have a 1 MiB
13431343
// range limit. We can easily exceed the limit in case the jump straddles two pages.
1344-
// In this case, we retry with a fresh page.
1344+
// In this case, we retry with a fresh page once.
13451345
cb.set_label_state(starting_label_state);
1346-
cb.next_page(start_ptr, emit_jmp_ptr_with_invalidation);
1347-
let result = asm.arm64_emit(cb, &mut ocb);
1348-
assert_ne!(
1349-
Err(EmitError::RetryOnNextPage),
1350-
result,
1351-
"should not fail when writing to a fresh code page"
1352-
);
1353-
result
1346+
if cb.next_page(start_ptr, emit_jmp_ptr_with_invalidation) {
1347+
asm.arm64_emit(cb, &mut ocb)
1348+
} else {
1349+
Err(EmitError::OutOfMemory)
1350+
}
13541351
}
13551352
result => result
13561353
};

0 commit comments

Comments
 (0)