-
Notifications
You must be signed in to change notification settings - Fork 3.5k
[embind] Use a single invoker mechanism #24577
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
Conversation
sbc100
left a comment
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 can't say I understand all of this but look like a good direction. I leave @brendandahl to do a full review.
| #if !DYNAMIC_EXECUTION | ||
| var argN = new Array(argCount); | ||
| var invokerFunction = (obj, func, destructorsRef, args) => { | ||
| var invokerFunction = (handle, methodName, destructorsRef, args) => { |
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.
Would it make more sense to call the first argument receiver? Or is handle (the type of the receiver I guess?) more descriptive here?
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.
handle as in generally EM_VAL. If the invoker kind is "method" then it's a handle of the receiver, if it's a "function" or a "constructor" then it's a handle of the function itself, and if it's a cast, then it's just null... A handle seemed like the most generic name.
|
The wasm2js failure looks a bit suspicious:
I guess it comes from |
|
Yes, If you build with However this only handles native->JS dependencies, but what we have here is a case of the JS compiler itself generating calls to a JS function (effectively a JS->JS dependency), but I guess its being injected somehow too late (and the native link has already been done). If you can share a repro case I can take a look. |
I don't have a smaller one, I've only guessed what's happening by searching for keywords from the error message for now. |
|
Does it fix the issue if you make the condition on line 536 of jsifier.js match the one on 314. It looks like they should be the same condition but they are not. |
|
No, still the same. I even tried making that dep unconditional just in case, but nothing:
Worth noting that Looks like that one is implemented in assembly, maybe it needs to be somehow exposed to wasm2js conversion? |
|
It's all the weirder that Aren't those digits at the end just optimisation levels? |
|
yes, you can see the setTempRet0 dependency is supposed to be added on line 530 ( |
|
Sorry, I still don't understand.
But then why even making it unconditional doesn't fix the issue? And why is I don't understand the mechanism here at all, so I have more questions than answers 😅 |
Answering just this part: We process the JS libraries files twice. Once in I think this issue is that while The code for this is here: Lines 3104 to 3128 in 542dc42
Specifically I think we are missing a call to
I imagine this is because at O0 getTempRet0 and/or its dependencies are exported for other reasons. |
That would make sense, but then why does O2 pass? Shouldn't it be more restrictive than O1 basically always? Could you help me fix this one please? I still don't understand what the fix should look like. |
|
Wait it passed after a rebase, wat? Nothing relevant changed upstream that I can see. |
|
The CI failure |
|
@brendandahl Can you please fix CI? I don't think I can merge until then (unless someone with force-merge rights wants to do it). |
For #24550 I mean. |
This is the next step in refactorings I started back in emscripten-core#20383 to merge all Embind generic method callers into a single mechanism. I never got around to landing this PR because I kept trying to split it into even smaller changes / steps, never found a good way to do so due to how entangled they were, got frustrated and left it alone. However, aside from being a nice-to-have optimisation or cleanup refactoring, it's also an easy way to deal with issues like emscripten-core#24547 which makes it a bit more pressing. Without this PR, we'd have to duplicate the `emval_as`+`emval_as_int64`+`emval_as_uint64` fix from emscripten-core#13889 for `emval_call` and `emval_call_method` as well, but after this PR everything goes through the same centralised implementation where we can deal with all Embind types in a consistent manner. There are some more things that I'd like to clean up here (including some of the complexity added by this very own PR), but in order to try and keep review scope smaller, I'm going to submit them separately. Fixes emscripten-core#24547.
Given how often it flakes lately, it really should use a local server instead of relying on httpbin.org... @sbc100 can you merge manually please? I already did rerun and it takes forever only to run into another flake. |
Agreed. Would you open a bug for that? |
|
Thanks, and done: #24597 |
I'm having real trouble reproducing this UB in isolation, but I ran into issues with garbage values in test_i64_val while making other innocent-looking changes. I think it might explain the really weird bug from emscripten-core#24577 (comment) that magically went away after a rebase despite no related changes being made. Essentially, because I stupidly used `T&&` in a template, and because it's [waves around] C++, it got inferred as `unsigned long long &` instead of the desired `unsigned long long`, so in `.as<T>()` we were quietly returning `unsigned long long&` references to a temporary `unsigned long long` value on function stack. Most of the time it somehow still works and, because it's templated, it's not caught by Clang's "non-const lvalue reference to type" diagnostic, but under unrelated changes and optimisations it can break badly.
I'm having trouble reproducing this UB in isolation, but I ran into issues with garbage values in test_i64_val while making other innocent-looking changes. I think it might even explain the really weird bug from #24577 (comment) that magically went away after a rebase despite no related changes being made upstream. Essentially, because I stupidly used `T&&` in a template, and because it's [waves around] C++, it got inferred as `unsigned long long &` instead of the desired `unsigned long long`, so in `.as<T>()` we were quietly returning an `unsigned long long&` reference to a temporary `unsigned long long` value on function stack. Most of the time it somehow still works and, because it's templated, it's not caught by Clang's "non-const lvalue reference to type" diagnostic, but under unrelated changes and optimisations it can break badly.
This is the next step in refactorings I started back in #20383 to merge all Embind generic method callers into a single mechanism. I never got around to landing this PR because I kept trying to split it into even smaller changes / steps, never found a good way to do so due to how entangled they were, got frustrated and left it alone.
However, aside from being a nice-to-have optimisation or cleanup refactoring, it's also an easy way to deal with issues like #24547 which makes it a bit more pressing. Without this PR, we'd have to duplicate the
emval_as+emval_as_int64+emval_as_uint64fix from #13889 foremval_callandemval_call_methodas well, but after this PR everything goes through the same centralised implementation where we can deal with all Embind types in a consistent manner.There are some more things that I'd like to clean up here (including some of the complexity added by this very own PR), but in order to try and keep review scope smaller, I'm going to submit them separately.
Fixes #24547.