Skip to content
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

Fix dyncall and dynamic linking with -sMAIN_MODULE=1 #16693

Closed
wants to merge 1 commit into from

Conversation

hoodmane
Copy link
Collaborator

Sometimes side modules need dyncalls with 64 bit types that are missing the dynCall wrappers from the main module. In this case, we can fall back to trying to use BigInt. I don't want to compile with -sWASM_BIGINT BigInt64Array has under a year of support in Safari. BigInt has been supported in Safari since v14.0 so I'm not as worried about this. In any case, this works in strictly more cases than it would before.

We don't compile with WASM_BIGINT so if there is a 64 bit integer
in the dynamic call, Emscripten tries to call a legalizer wrapper.
These legalizer wrappers are only generated in the main module so
sometimes a side module tries to call a wrapper that doesn't exist.
This adds an extra handler in that case.
@hoodmane hoodmane changed the title Fix dyncall and dynamic linking Fix dyncall and dynamic linking with -sMAIN_MODULE=1 Apr 11, 2022
@@ -3139,7 +3139,29 @@ LibraryManager.library = {
// part of thier signature, so we rely the dynCall functions generated by
// wasm-emscripten-finalize
if (sig.includes('j')) {
#if MAIN_MODULE
if(Module["dynCall_" + sig]){
return dynCallLegacy(sig, ptr, args);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, reading this I'm confused as to why dynCall_* would only sometimes exist when DYNCALLS. That is, we should have returned from line 3135 above, I think? Is this related to this issue from the description:

"Sometimes side modules need dyncalls with 64 bit types that are missing the dynCall wrappers from the main module."

If so, could we include dyncalls in side modules? cc @sbc100

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will try to come up with a MWE soon. It occurred on this branch:
pyodide/pyodide#2378
with the signature viij but I have seen it before.

could we include dyncalls in side modules? cc @sbc100

Yeah I suspect you can do that, perhaps it's a better solution? BigInt support is much broader than BigInt64Array so I don't mind this. But yeah it would be harder for me to come up with this.

@sbc100
Copy link
Collaborator

sbc100 commented Apr 12, 2022

Can you explain why you don't want to do use -sWASM_BIGINT? It seems like the right solution here.. and if it isn't then perhaps we would want an different option for this limited use of BigInt?

@sbc100
Copy link
Collaborator

sbc100 commented Apr 12, 2022

Can you share the backtrace of there the failing call to dynCall is coming from? Am I correct in assuming its coming from a function generated by createInvokeFunction in response of an invoke_xx import? here:

$createInvokeFunction: function(sig) {
return function() {
var sp = stackSave();
try {
return dynCall(sig, arguments[0], Array.prototype.slice.call(arguments, 1));

@hoodmane
Copy link
Collaborator Author

hoodmane commented Apr 12, 2022 via email

@sbc100
Copy link
Collaborator

sbc100 commented Apr 12, 2022

Yeah: we don't want -sWASM_BIGINT because it doesn't work on Safari 14 and we haven't made up our mind that we are officially not supporting Safari 14.

Sorry, can you explain a little more. I'm confused because this patch seems to rely on wasm/BigInt integration (you are passing BigInts as arguments and receiving them as return values to/from wasm functions) which is what I thought that the WASM_BIGINT assumed. Or is WASM_BIGINT assuming something more that just this?

@hoodmane
Copy link
Collaborator Author

hoodmane commented Apr 12, 2022 via email

@sbc100
Copy link
Collaborator

sbc100 commented Apr 12, 2022

According to caniuse, Safari 14.0 has BigInt but not BigInt64Array. So we are happy to assume the former is present. -sWASM_BIGINT assumes both.

In that case can we fix this by making WASM_BIGINT not assume BigInt64Array? or at least making it optional? I seems like BigInt64Array support is unrelated to wasm/bigint integration which is what that setting is designed for.

@hoodmane
Copy link
Collaborator Author

In that case can we fix this by making WASM_BIGINT not assume BigInt64Array?

That would be great! Yeah if you just checked if typeof BigInt64Array !== "undefined" and skipped making HEAP64 and HEAPU64 if not I think it would fix the problem for us. Though I haven't grepped the code base just now maybe there are other spots you use it?

@kripken
Copy link
Member

kripken commented Apr 13, 2022

Grepping for HEAP64 / HEAPU64, it is used in a few places, like embind's extra i64/u64 integration support. That might be optional if the user avoids it. The other place is pthread proxying, where I'm not sure it is as simple to avoid - we use i64s in more places and need to proxy them properly. But in general, we may start to use HEAP64 in more places, so working around it in each of them seems less good.

I think we could do this, though, with a little work. We could add a "BigInt but without BigInt[U]64Array" mode in which a custom acorn optimizer pass is run that rewrites HEAP[U]64 to operations on a smaller size. We have similar things like littleEndianHeap(), asanify(), safeHeap() which rewrite all accesses (over here).

@sbc100
Copy link
Collaborator

sbc100 commented Apr 13, 2022

Grepping for HEAP64 / HEAPU64, it is used in a few places, like embind's extra i64/u64 integration support. That might be optional if the user avoids it. The other place is pthread proxying, where I'm not sure it is as simple to avoid - we use i64s in more places and need to proxy them properly. But in general, we may start to use HEAP64 in more places, so working around it in each of them seems less good.

I think we could do this, though, with a little work. We could add a "BigInt but without BigInt[U]64Array" mode in which a custom acorn optimizer pass is run that rewrites HEAP[U]64 to operations on a smaller size. We have similar things like littleEndianHeap(), asanify(), safeHeap() which rewrite all accesses (over here).

Could we write a BigInt64Array polyfill that kicks in only when targeting older safari versions?

@hoodmane
Copy link
Collaborator Author

Could we write a BigInt64Array polyfill that kicks in only when targeting older safari versions?

Yeah that sounds like the best idea. It should be quite simple.

@sbc100
Copy link
Collaborator

sbc100 commented Apr 13, 2022

Could we write a BigInt64Array polyfill that kicks in only when targeting older safari versions?

Yeah that sounds like the best idea. It should be quite simple.

We would probably also want to bump the default safari version to 15 (perhaps at least when bitint is enabled).. so that folks have to explicitly opt into the polyfil.

@kripken
Copy link
Member

kripken commented Apr 14, 2022

Maybe there is JS magic that I am unaware of, but I'm not sure a polyfill can work. We need to replace HEAP64[x] with a function call. Can a Proxy object do it perhaps? Anyhow, if it's possible then a polyfill sounds best!

@sbc100
Copy link
Collaborator

sbc100 commented Apr 14, 2022

Maybe there is JS magic that I am unaware of, but I'm not sure a polyfill can work. We need to replace HEAP64[x] with a function call. Can a Proxy object do it perhaps? Anyhow, if it's possible then a polyfill sounds best!

Apparently that is possible yes: https://stackoverflow.com/questions/1711357/how-would-you-overload-the-operator-in-javascript

@hoodmane
Copy link
Collaborator Author

Closed in favor of #17103.

@hoodmane hoodmane closed this Jun 14, 2022
kripken pushed a commit that referenced this pull request Jun 27, 2022
As discussed in #16693, -s WASM_BIGINT requires both BigInt (present since
Safari 14.0) and BigInt64Array (present since Safari 15.0). Thus, users that want
to target Safari 14.0 need a polyfill for BigInt64Array, which this adds.
@hoodmane
Copy link
Collaborator Author

hoodmane commented Oct 11, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants