-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
[emval] Reuse method calling optimisation in regular calls #20383
[emval] Reuse method calling optimisation in regular calls #20383
Conversation
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.
Looks good, minor nits.
@@ -509,16 +480,28 @@ class val { | |||
return internal::_emval_delete(as_handle(), val_ref(property).as_handle()); | |||
} | |||
|
|||
template<typename... 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.
Why was this moved?
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 to keep all variants / usages of internalCall
together, I found it makes it easier to iterate on it when you can see all places that need to be updated together on one screen.
Addressed the feedback. |
Reindent and change more concats to templates.
7ba7779
to
b4fef41
Compare
Before PR emscripten-core#20383 val's `call` and `operator()` had different behaviors where one would automatically destroy arguments after the call and the other didn't. After that PR, they both called destroy. The automatic destruction wasn't really documented anywhere and and led to some unexpected behavior. This changes it so neither automatically destroys the arguments which I think is more inline with the rest of embind where it's up to the user to handle object lifetimes. Fixes: emscripten-core#21016 and emscripten-core#20095
Before PR emscripten-core#20383 val's `call` and `operator()` had different behaviors where one would automatically destroy arguments after the call and the other didn't. After that PR, they both called destroy. The automatic destruction wasn't really documented anywhere and and led to some unexpected behavior. This changes it so neither automatically destroys the arguments which I think is more inline with the rest of embind where it's up to the user to handle object lifetimes. Fixes: emscripten-core#21016 and emscripten-core#20095
Before PR emscripten-core#20383 val's `call` and `operator()` had different behaviors where one would automatically destroy arguments after the call and the other didn't. After that PR, they both called destroy. The automatic destruction wasn't really documented anywhere and and led to some unexpected behavior. This changes it so neither automatically destroys the arguments which I think is more inline with the rest of embind where it's up to the user to handle object lifetimes. Fixes: emscripten-core#21016 and emscripten-core#20095
…21022) Before PR #20383 val's `call` and `operator()` had different behaviors where one would automatically destroy arguments after the call and the other didn't. After that PR, they both called destroy. The automatic destruction wasn't really documented anywhere and and led to some unexpected behavior. This changes it so neither automatically destroys the arguments which I think is more inline with the rest of embind where it's up to the user to handle object lifetimes. Fixes: #21016 and #20095
Method, function and constructor calls are very similar in nature but used different code paths: method calls have an optimisation where an optimised caller trampoline is generated once and reused for each function signature, whereas the other two serialized arguments and types every time.
There is no reason for them to diverge, so I made function calls and constructors reuse the same optimisation.
Results on a silly microbenchmark running a side-effect-ful JS function with 100 integer args in a loop:
Before
with dynamic execution:
as method: 224.504ns
as function: 5367.9ns
without dynamic execution:
as method: 845.044ns
as function: 5350.96ns
After
with dynamic execution:
as method: 262.74ns
as function: 246.593ns
without dynamic execution:
as method: 859.534ns
as function: 823.498ns
In real world the difference is unlikely to be perceptible, but at the very least this makes the code more consistent and deletes a bunch of duplication.