-
Notifications
You must be signed in to change notification settings - Fork 5.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
feat(core): Reland support for async ops in realms #17204
feat(core): Reland support for async ops in realms #17204
Conversation
Currently realms are supported on `deno_core`, but there was no support for async ops anywhere other than the main realm. The main issue is that the `js_recv_cb` callback, which resolves promises corresponding to async ops, was only set for the main realm, so async ops in other realms would never resolve. Furthermore, promise ID's are specific to each realm, which meant that async ops from other realms would result in a wrong promise from the main realm being resolved. This change takes the `ContextState` struct added in denoland#17050, and adds to it a `js_recv_cb` callback for each realm. Combined with the fact that that same PR also added a list of known realms to `JsRuntimeState`, and that denoland#17174 made `OpCtx` instances realm-specific and had them include an index into that list of known realms, this makes it possible to know the current realm in the `queue_async_op` and `queue_fast_async_op` methods, and therefore to send the results of promises for each realm to that realm, and prevent the ID's from getting mixed up. Additionally, since promise ID's are no longer unique to the isolate, having a single set of unrefed ops doesn't work. This change therefore also moves `unrefed_ops` from `JsRuntimeState` to `ContextState`, and adds the lengths of the unrefed op sets for all known realms to get the total number of unrefed ops to compare in the event loop. This PR is a reland of denoland#14734 after it was reverted in denoland#16366, except that `ContextState` and `JsRuntimeState::known_realms` were previously relanded in denoland#17050. Another significant difference with the original PR is passing around an index into `JsRuntimeState::known_realms` instead of a `v8::Global<v8::Context>` to identify the realm, because async op queuing in fast calls cannot call into V8, and therefore cannot have access to V8 globals. This also simplified the implementation of `resolve_async_ops`. Co-authored-by: Luis Malheiro <[email protected]>
main:
this PR:
There seems to be a clear decrease in performance in this benchmark. Now, |
I got rid of a
|
PTAL @bartlomieju @littledivy |
@littledivy this looks good to me now - I think having a separate code path for non-default realm is a good idea. |
Oooops, looks like #17301 causes the tests to fail, could you update them @andreubotella? |
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!
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 too, thanks Andreu
Currently realms are supported on `deno_core`, but there was no support for async ops anywhere other than the main realm. The main issue is that the `js_recv_cb` callback, which resolves promises corresponding to async ops, was only set for the main realm, so async ops in other realms would never resolve. Furthermore, promise ID's are specific to each realm, which meant that async ops from other realms would result in a wrong promise from the main realm being resolved. This change takes the `ContextState` struct added in #17050, and adds to it a `js_recv_cb` callback for each realm. Combined with the fact that that same PR also added a list of known realms to `JsRuntimeState`, and that #17174 made `OpCtx` instances realm-specific and had them include an index into that list of known realms, this makes it possible to know the current realm in the `queue_async_op` and `queue_fast_async_op` methods, and therefore to send the results of promises for each realm to that realm, and prevent the ID's from getting mixed up. Additionally, since promise ID's are no longer unique to the isolate, having a single set of unrefed ops doesn't work. This change therefore also moves `unrefed_ops` from `JsRuntimeState` to `ContextState`, and adds the lengths of the unrefed op sets for all known realms to get the total number of unrefed ops to compare in the event loop. This PR is a reland of #14734 after it was reverted in #16366, except that `ContextState` and `JsRuntimeState::known_realms` were previously relanded in #17050. Another significant difference with the original PR is passing around an index into `JsRuntimeState::known_realms` instead of a `v8::Global<v8::Context>` to identify the realm, because async op queuing in fast calls cannot call into V8, and therefore cannot have access to V8 globals. This also simplified the implementation of `resolve_async_ops`. Co-authored-by: Luis Malheiro <[email protected]>
Currently realms are supported on
deno_core
, but there was no support for async ops anywhere other than the main realm. The main issue is that thejs_recv_cb
callback, which resolves promises corresponding to async ops, was only set for the main realm, so async ops in other realms would never resolve. Furthermore, promise ID's are specific to each realm, which meant that async ops from other realms would result in a wrong promise from the main realm being resolved.This change takes the
ContextState
struct added in #17050, and adds to it ajs_recv_cb
callback for each realm. Combined with the fact that that same PR also added a list of known realms toJsRuntimeState
, and that #17174 madeOpCtx
instances realm-specific and had them include an index into that list of known realms, this makes it possible to know the current realm in thequeue_async_op
andqueue_fast_async_op
methods, and therefore to send the results of promises for each realm to that realm, and prevent the ID's from getting mixed up.Additionally, since promise ID's are no longer unique to the isolate, having a single set of unrefed ops doesn't work. This change therefore also moves
unrefed_ops
fromJsRuntimeState
toContextState
, and adds the lengths of the unrefed op sets for all known realms to get the total number of unrefed ops to compare in the event loop.This PR is a reland of #14734 after it was reverted in #16366, except that
ContextState
andJsRuntimeState::known_realms
were previously relanded in #17050. Another significant difference with the original PR is passing around an index intoJsRuntimeState::known_realms
instead of av8::Global<v8::Context>
to identify the realm, because async op queuing in fast calls cannot call into V8, and therefore cannot have access to V8 globals. This also simplified the implementation ofresolve_async_ops
.cc @lmalheiro, since the this reland includes a test they provided for the original PR.