Skip to content

[emval] Reuse method calling optimisation in regular calls #20383

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

Merged
merged 11 commits into from
Oct 18, 2023

Conversation

RReverser
Copy link
Collaborator

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.

Copy link
Collaborator

@brendandahl brendandahl left a 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>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why was this moved?

Copy link
Collaborator Author

@RReverser RReverser Oct 17, 2023

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.

@RReverser
Copy link
Collaborator Author

Addressed the feedback.

@RReverser RReverser force-pushed the emval-optimised-call-new branch from 7ba7779 to b4fef41 Compare October 17, 2023 23:29
@RReverser RReverser merged commit 12777ca into emscripten-core:main Oct 18, 2023
@RReverser RReverser deleted the emval-optimised-call-new branch October 18, 2023 17:53
brendandahl added a commit to brendandahl/emscripten that referenced this pull request Jan 5, 2024
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
brendandahl added a commit to brendandahl/emscripten that referenced this pull request Jan 8, 2024
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
brendandahl added a commit to brendandahl/emscripten that referenced this pull request Jan 11, 2024
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
brendandahl added a commit that referenced this pull request Jan 11, 2024
…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
RReverser added a commit to RReverser/emscripten that referenced this pull request Jun 16, 2025
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.
RReverser added a commit to RReverser/emscripten that referenced this pull request Jun 16, 2025
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.
RReverser added a commit to RReverser/emscripten that referenced this pull request Jun 17, 2025
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.
RReverser added a commit to RReverser/emscripten that referenced this pull request Jun 17, 2025
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.
RReverser added a commit to RReverser/emscripten that referenced this pull request Jun 17, 2025
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.
sbc100 pushed a commit that referenced this pull request Jun 17, 2025
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_uint64` fix from #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 #24547.
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.

2 participants