-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Use proxy objects for MEMORY64 HEAP access over 4Gb #19737
Conversation
Thanks for working on this! I've been meaning to do something very similar myself but you have likely saved me a bunch of work here! |
Sure! I will fix all the failing tests soon |
…GB is set This extends the use automatically-generated JS wrappers to handle conversion of incoming i32 pointer to u32 JS numbers. This is only needed when CAN_ADDRESS_2GB is set. See #19737
…GB is set This extends the use automatically-generated JS wrappers to handle conversion of incoming i32 pointer to u32 JS numbers. This is only needed when CAN_ADDRESS_2GB is set. See #19737
…GB is set This extends the use automatically-generated JS wrappers to handle conversion of incoming i32 pointer to u32 JS numbers. This is only needed when CAN_ADDRESS_2GB is set. See #19737
…GB is set This extends the use automatically-generated JS wrappers to handle conversion of incoming i32 pointer to u32 JS numbers. This is only needed when CAN_ADDRESS_2GB is set. See #19737
…GB is set This extends the use automatically-generated JS wrappers to handle conversion of incoming i32 pointer to u32 JS numbers. This is only needed when CAN_ADDRESS_2GB is set. See #19737
…GB is set This extends the use automatically-generated JS wrappers to handle conversion of incoming i32 pointer to u32 JS numbers. This is only needed when CAN_ADDRESS_2GB is set. See #19737
…GB is set This extends the use automatically-generated JS wrappers to handle conversion of incoming i32 pointer to u32 JS numbers. This is only needed when CAN_ADDRESS_2GB is set. See #19737
…GB is set This extends the use automatically-generated JS wrappers to handle conversion of incoming i32 pointer to u32 JS numbers. This is only needed when CAN_ADDRESS_2GB is set. See #19737
…GB is set This extends the use automatically-generated JS wrappers to handle conversion of incoming i32 pointer to u32 JS numbers. This is only needed when CAN_ADDRESS_2GB is set. See #19737
…GB is set This extends the use automatically-generated JS wrappers to handle conversion of incoming i32 pointer to u32 JS numbers. This is only needed when CAN_ADDRESS_2GB is set. See #19737
…GB is set This extends the use automatically-generated JS wrappers to handle conversion of incoming i32 pointer to u32 JS numbers. This is only needed when CAN_ADDRESS_2GB is set. See #19737
I've fixed tests and now proxies are created only if allocated memory is > 4gb Also, memory growth does not work even if initial memory is >4gb, looks like chrome issue. Now going to try make it working with ASYNCIFY=2 and threads. First one throws bigint to number error somewhere, and second gives linker error. Guess the latter would require some deep digging |
…GB is set This extends the use automatically-generated JS wrappers to handle conversion of incoming i32 pointer to u32 JS numbers. This is only needed when CAN_ADDRESS_2GB is set. See #19737
…GB is set This extends the use automatically-generated JS wrappers to handle conversion of incoming i32 pointer to u32 JS numbers. This is only needed when CAN_ADDRESS_2GB is set. See #19737
…GB is set This extends the use automatically-generated JS wrappers to handle conversion of incoming i32 pointer to u32 JS numbers. This is only needed when CAN_ADDRESS_2GB is set. See #19737
Isn't this something that browsers will need to fix as part of adding support for wasm64? |
Yes. But who knows when that would happen. The workaround allows using >4gb now and can be removed without modifying any other code once full 64bit support is rolled out in browsers. It does not affect anything when <=4gb memory is used |
emcc.py
Outdated
@@ -3728,7 +3728,8 @@ def phase_binaryen(target, options, wasm_target): | |||
# >=2GB heap support requires pointers in JS to be unsigned. rather than | |||
# require all pointers to be unsigned by default, which increases code size | |||
# a little, keep them signed, and just unsign them here if we need that. | |||
if settings.CAN_ADDRESS_2GB: |
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.
This line can now be reverted since CAN_ADDRESS_2GB is never set when MEMORY64 is set: See #19755
src/preamble.js
Outdated
var maxArraySize = Math.min(b.byteLength, 4 * 1024 * 1024 * 1024 - 8); | ||
var proxyHandler = (type, heapBlock) => ({ | ||
heapBlock, | ||
copyWithin (target, start, end) { |
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.
Our JS style has no space between function names and their arguments
src/preamble.js
Outdated
copyWithin (target, start, end) { | ||
target = fixPointer(target) | ||
start = fixPointer(start) | ||
end = fixPointer(end) |
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.
I'm hoping you can simply remove fixPointer
since all incoming pointers should already i53 (and unsigned). See #19740.
Can you add a comment to this new code and include a link to the upstream bug: https://bugs.chromium.org/p/v8/issues/detail?id=4153 |
Sure. I've made a fix for ASYNCIFY=1 and MEMORY64=1. Should I include it into this PR or open a separate one? |
lgtm I re-titled this PR for clarity. |
# test that growth doesn't go beyond 2GB without the max being set for that, | ||
# and that we can catch an allocation failure exception for that | ||
self.emcc_args += ['-O2', '-sALLOW_MEMORY_GROWTH', '-sMAXIMUM_MEMORY=2GB'] | ||
self.do_run_in_out_file_test('browser', 'test_2GB_fail.cpp') | ||
|
||
@no_firefox('no 4GB support yet') | ||
@also_with_wasm64 | ||
@requires_v8 |
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.
Why this? In general if we can test on the command line I think we should prefer to do that. Browser tests tend to be more flaky and difficult to work with (for example we don't get to see the stdout in CI).
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.
It fails with a weird assertion error which i cannot reproduce locally. Neither in command line, nor in the browser. Maybe because of actual out of memory issue?
Will dig a bit more once this test run finishes
I have disabled test_zzz_zzz_4gb_fail_wasm64 because it fails during stack overflow check
in I can add
|
Interesting... |
I've fixed tests from main branch here. LLVM update changed something in output size |
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.
lgtm if tests pass!
test/test_browser.py
Outdated
# means we don't compete for memory with anything else (and run it | ||
# at the very very end, to reduce the risk of it OOM-killing the | ||
# browser). | ||
|
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.
Restore this comment?
test/test_browser.py
Outdated
@@ -5371,14 +5371,7 @@ def test_wasm_worker_proxied_function(self): | |||
self.btest(test_file('wasm_worker/proxied_function.c'), expected='0', args=['--js-library', test_file('wasm_worker/proxied_function.js'), '-sWASM_WORKERS', '-sASSERTIONS=0']) | |||
|
|||
@no_firefox('no 4GB support yet') | |||
@requires_v8 |
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.
Is this needed?
test/test_other.py
Outdated
def test_quick_exit(self): | ||
self.do_other_test('test_quick_exit.c') | ||
|
||
|
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.
Just one newline between methods in python
test/test_other.py
Outdated
'-Wno-experimental', | ||
'--extern-post-js', 'post.js']) | ||
self.run_js('a.out.js') | ||
|
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.
Remove extra newline
test/test_other.py
Outdated
@requires_node_canary | ||
def test_memory64_proxies(self): | ||
create_file('post.js', r''' | ||
addOnPostRun(() => { |
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.
Maybe put this in its own file? (test/other/test_memory64_proxies.js
?)
@sbc100 All done. Can you please also guide me on this one? WebAssembly/memory64#39 I've created a same proposal in WebAssembly/threads but the team has closed it as it should be part of the Memory64 spec. Currently it's not possible to create WebAssembly.Memory from JS with 64bit limits. And it's easy to fix in V8 source (just a couple of |
Can you try reverting all the test/code_size changes? I think that should help with a bunch of the current failures. |
Yup. Should be good now |
Thanks! I's been a long way |
This PR only added polyfills for HEAP8 and HEAP16, but not HEAP32 or HEAP64. I don't see that being discussed in above, and wonder why that was the case? |
The reason is that the chromium issue/limit is on the number of elements in the view not the byte length. So even without this fix we can create HEAP32 views that can address 16gb. I seem to remember there are other implementation limits in chrome that will get hit before we get to 16gb. I'm hoping that by the we want to allow for >16gb memories this polyfill will no longer be needed. |
Currently HEAP arrays fail to create when memory size is > 4gb so proxy objets for HEAP(U)8 are created when allocated memory is >4gb and for HEAP(U)16 when >8gb.
Solution overrides TypedArray set, subarray, fill, copyWithin, and slice methods. As well as direct property access using memory pointers. It creates N TypedArray views with maximum of 4 * 1024 * 1024 * 1024 - 2 elements for each heap view.
Also, test_memory64_proxies test added to check correctness of the implementation.
See https://bugs.chromium.org/p/v8/issues/detail?id=4153