This commit replaces GothamState's internal HashMap
with a BTreeMap to improve performance.
OpState/GothamState keys by TypeId which is essentially
an opaque u64. For small sets of integer keys BTreeMap
outperforms HashMap mainly since it removes the hashing
overhead and Eq/Comp on integer-like types is very cheap,
it should also have a smaller memory footprint.
We only use ~30 unique types and thus ~30 unique keys to
access OpState, so the keyset is small and immutable
throughout the life of a JsRuntime, there's no meaningful
churn in keys added/removed.
This is another optimization to help improve the baseline overhead
of async ops. It shaves off ~55ns/op or ~7% of the current total
async op overhead.
It achieves these gains by taking advantage of the sequential
nature of promise IDs and optimistically stores them sequentially
in a pre-allocated circular buffer and fallbacks to the promise Map
for slow to resolve promises.
- Improves op performance.
- Handle op-metadata (errors, promise IDs) explicitly in the op-layer vs
per op-encoding (aka: out-of-payload).
- Remove shared queue & custom "asyncHandlers", all async values are
returned in batches via js_recv_cb.
- The op-layer should be thought of as simple function calls with little
indirection or translation besides the conceptually straightforward
serde_v8 bijections.
- Preserve concepts of json/bin/min as semantic groups of their
inputs/outputs instead of their op-encoding strategy, preserving these
groups will also facilitate partial transitions over to v8 Fast API for the
"min" and "bin" groups
This commit moves implementation of bin ops to "deno_core" crates
as well as unifying logic between bin ops and json ops to reuse
as much code as possible (both in Rust and JavaScript).
This commit rewrites "dispatch_minimal" into "dispatch_buffer".
It's part of an effort to unify JS interface for ops for both json
and minimal (buffer) ops.
Before this commit "minimal ops" could be either sync or async
depending on the return type from the op, but this commit changes
it to have separate signatures for sync and async ops (just like
in case of json ops).
In case JavaScript throws an unhandled error, part of the "shared_queue" could
be still unprocessed.
If this is the case; throw the js runtime error instead of asserting on the
queue size not being 0.
This commit rewrites implementation of "JsRuntime::mod_evaluate".
Event loop is no longer polled automatically and users must manually
drive event loop forward after calling "mod_evaluate".
Co-authored-by: Nayeem Rahman <nayeemrmn99@gmail.com>
Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit rewrites "JsRuntime::poll" function to fix a corner case that
might caused "overflown_response" to be overwritten by other overflown response.
The logic has been changed to allow returning multiple overflown response
alongside responses from shared queue.
This commit adds two new "Deno.core" APIs:
- "Deno.core.serialize"
- "Deno.core.deserialize"
These APIs are used to provide structured cloning of values
and will be used for further web worker implementation.
Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This PR makes json_op_sync/async generic to all Deserialize/Serialize types
instead of the loosely-typed serde_json::Value. Since serde_json::Value
implements Deserialize/Serialize, very little existing code needs to be updated,
however as json_op_sync/async are now generic, type inference is broken in some
cases (see cli/build.rs:146). I've found this reduces a good bit of boilerplate,
as seen in the updated deno_core examples.
This change may also reduce serialization and deserialization overhead as serde
has a better idea of what types it is working with. I am currently working on
benchmarks to confirm this and I will update this PR with my findings.
This commit rewrites initialisation of the "shared queue" and
in effect prevents from double execution of "core/core.js" and
"core/error.js".
Previously both of these files were executed every time a "JsRuntime"
was created. That lead to a situation where one copy of each script
was included in the snapshot and then another copy would be
executed after loading the snapshot.
Effectively "JsRuntime::shared_init" was removed; instead execution
of those scripts and actual initialisation of shared queue
was split into two helper functions: "JsRuntime::js_init" and
"JsRuntime::share_queue_init".
Additionally stale TODO comments were removed.
Fixes the following runtime error for me when benchmarking:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err`
value: Error: Unregistered error class: "Error"
Connection reset by peer (os error 104)
Classes of errors returned from ops should be registered via
Deno.core.registerErrorClass().
at processResponse (deno:core/core.js:219:13)
at Object.jsonOpAsync (deno:core/core.js:240:12)
at async read (http_bench_json_ops.js:29:21)
at async serve (http_bench_json_ops.js:45:19)',
core/examples/http_bench_json_ops.rs:260:28
Implementors of `deno_core::JsRuntime` might want to do additional actions
during each turn of event loop, eg. `deno_runtime::Worker` polls inspector,
`deno_runtime::WebWorker` receives/dispatches messages from/to worker host.
Previously `JsRuntime::mod_evaluate` was implemented in such fashion that it
only polled `JsRuntime`'s event loop. This behavior turned out to be wrong
in the example of `WebWorker` which couldn't receive/dispatch messages because
its implementation of event loop was never called.
This commit rewrites "mod_evaluate" to return a handle to receiver that resolves
when module's promise resolves. It is now implementors responsibility to poll
event loop after calling `mod_evaluate`.
This commit migrates all ops to use new resource table
and "AsyncRefCell".
Old implementation of resource table was completely
removed and all code referencing it was updated to use
new system.
This commit moves Deno JS runtime, ops, permissions and
inspector implementation to new "deno_runtime" crate located
in "runtime/" directory.
Details in "runtime/README.md".
Co-authored-by: Ryan Dahl <ry@tinyclouds.org>
This commit does major refactor of "Worker" and "WebWorker",
in order to decouple them from "ProgramState" and "Flags".
The main points of interest are "create_main_worker()" and
"create_web_worker_callback()" functions which are responsible
for creating "Worker" and "WebWorker" in CLI context.
As a result it is now possible to factor out common "runtime"
functionality into a separate crate.
This commit adds "Deno.core.createPrepareStackTrace". This function
was moved from "cli/rt/40_error_stack.js" to unify handling of stack frames in core
(before this PR there was implicit dependency on logic in "core/error.rs::JsError").
Unfortunately formatting logic must still be duplicated in "cli/error.js::PrettyJsError"
to provide coloring, but currently there's no solution to this problem.
"createPrepareStackTrace" can accept a single argument; a function that takes
a location and provides source mapped location back.
This commit disables source mapping of errors
for standalone binaries. Since applying source
maps relies on using file fetcher infrastructure
it's not feasible to use it for standalone binaries
that are not supposed to use that infrastructure.
This commit adds `FsModuleLoader` to `deno_core`, which implements
`ModuleLoader` trait. It is used when creating a runtime that supports
module loading from filesystem.
Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
Fixes panic occurring in worker when "self.close()" is called
at the top level, ie. worker shuts down while
module evaluation promise hasn't yet resolved.
This commit refactors "deno_core::Modules" structure to not depend on
"get_identity_hash" function to identify modules, but instead use default
hash implementation.
Make JSRuntime::new() accept a custom v8::CreateParams object to tune
the v8::Isolate it creates.
Subsumes the functionality of HeapLimits, which I therefore removed.
This commit changes implementation of top-level-await in "deno_core".
Previously promise returned from module evaluation was not awaited,
leading to out-of-order execution of modules that have TLA. It's been
fixed by changing "JsRuntime::mod_evaluate" to be an async function
that resolves when the promise returned from module evaluation also
resolves. When waiting for promise resolution event loop is polled
repeatedly, until there are no more dynamic imports or pending
ops.
* Revert "refactor: Worker is not a Future (#7895)"
This reverts commit f4357f0ff9.
* Revert "refactor(core): JsRuntime is not a Future (#7855)"
This reverts commit d8879feb8c.
* Revert "fix(core): module execution with top level await (#7672)"
This reverts commit c7c7677825.
This commit rewrites deno_core::JsRuntime to not implement Future
trait.
Instead there are two separate methods:
- JsRuntime::poll_event_loop() - does single tick of event loop
- JsRuntime::run_event_loop() - runs event loop to completion
This commit renames occurrences of "isolate" variable name
to "js_runtime". This was outstanding debt after renaming
deno_core::CoreIsolate to JsRuntime.
This commit fixes implementation of top level await in "deno_core".
Previously promise returned from module execution was ignored causing to execute
modules out-of-order.
With this commit promise returned from module execution is stored on "JsRuntime"
and event loop is polled until the promise resolves.