-
Notifications
You must be signed in to change notification settings - Fork 116
perf: optimize overflow check in RTS alloc_words
, fix and update tests
#3085
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ebf3483
381fb3a
e26eb7e
f6d70fb
620f2de
02e277b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,29 +72,29 @@ impl Memory for IcMemory { | |
unsafe fn alloc_words(&mut self, n: Words<u32>) -> Value { | ||
let bytes = n.to_bytes(); | ||
// Update ALLOCATED | ||
ALLOCATED += Bytes(u64::from(bytes.as_u32())); | ||
let delta = u64::from(bytes.as_u32()); | ||
ALLOCATED += Bytes(delta); | ||
|
||
// Update heap pointer | ||
let old_hp = HP; | ||
let (new_hp, overflow) = old_hp.overflowing_add(bytes.as_u32()); | ||
// Check for overflow | ||
if overflow { | ||
rts_trap_with("Out of memory"); | ||
} | ||
HP = new_hp; | ||
let old_hp = u64::from(HP); | ||
let new_hp = old_hp + delta; | ||
|
||
// Grow memory if needed | ||
grow_memory(new_hp as usize); | ||
grow_memory(new_hp); | ||
|
||
debug_assert!(new_hp <= u64::from(core::u32::MAX)); | ||
HP = new_hp as u32; | ||
|
||
Value::from_ptr(old_hp as usize) | ||
} | ||
} | ||
|
||
/// Page allocation. Ensures that the memory up to, but excluding, the given pointer is allocated. | ||
#[inline(never)] | ||
unsafe fn grow_memory(ptr: usize) { | ||
unsafe fn grow_memory(ptr: u64) { | ||
debug_assert!(ptr <= 2 * u64::from(core::u32::MAX)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can use the same condition as in the assert in line 85: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I'm deliberately comparing against 8GB because I want to test the overflow detection later on (otherwise we will get different faults on debug and release builds). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, got it. Sounds good! |
||
let page_size = u64::from(WASM_PAGE_SIZE.as_u32()); | ||
let total_pages_needed = (((ptr as u64) + page_size - 1) / page_size) as usize; | ||
let total_pages_needed = ((ptr + page_size - 1) / page_size) as usize; | ||
let current_pages = wasm32::memory_size(0); | ||
if total_pages_needed > current_pages { | ||
if wasm32::memory_grow(0, total_pages_needed - current_pages) == core::usize::MAX { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 | ||
ingress Completed: Reply: 0x4449444c0000 | ||
Err: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: RTS error: Out of memory | ||
Err: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: RTS error: Cannot grow memory |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 | ||
ingress Completed: Reply: 0x4449444c0000 | ||
Err: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: RTS error: Out of memory | ||
ingress Err: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: RTS error: Cannot grow memory |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
RTS error: Out of memory | ||
RTS error: Cannot grow memory |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ulan commenting remark in the meeting just now. The fast path should be predicated on the fact that the allocation remains on the last page, i.e.
old_hp >> 16 == new_hp >> 16
.And that condition could even be made faster by
(old_hp ^ new_hp) >> 16
. See #3090.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, but I'll leave that to #3090.