diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2022-09-06 23:08:37 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-06 23:08:37 +0530 |
commit | d2a408f452db1157a1e6a14810bd1f03fc431d9d (patch) | |
tree | 66c45829a78cb3c6cd6e875cca65ce26384fe50d /core/runtime.rs | |
parent | c0a684c14ed70717e18b528bb8f366eb593636a7 (diff) |
perf(runtime): short-circuit `queue_async_op` for Poll::Ready (#15773)
Diffstat (limited to 'core/runtime.rs')
-rw-r--r-- | core/runtime.rs | 122 |
1 files changed, 81 insertions, 41 deletions
diff --git a/core/runtime.rs b/core/runtime.rs index 4aad2bd76..2c16ddeb8 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -2145,14 +2145,54 @@ impl JsRealm { #[inline] pub fn queue_async_op( - scope: &v8::Isolate, + state: Rc<RefCell<OpState>>, + scope: &mut v8::HandleScope, + deferred: bool, op: impl Future<Output = (v8::Global<v8::Context>, PromiseId, OpId, OpResult)> + 'static, ) { - let state_rc = JsRuntime::state(scope); - let mut state = state_rc.borrow_mut(); - state.pending_ops.push(OpCall::eager(op)); - state.have_unpolled_ops = true; + match OpCall::eager(op) { + // This calls promise.resolve() before the control goes back to userland JS. It works something + // along the lines of: + // + // function opresolve(promiseId, ...) { + // getPromise(promiseId).resolve(...); + // } + // const p = setPromise(); + // op.op_async(promiseId, ...); // Calls `opresolve` + // return p; + EagerPollResult::Ready((context, promise_id, op_id, mut resp)) + if !deferred => + { + let args = &[ + v8::Integer::new(scope, promise_id).into(), + resp.to_v8(scope).unwrap(), + ]; + + let realm = JsRealm::new(context); + let js_recv_cb_handle = + realm.state(scope).borrow().js_recv_cb.clone().unwrap(); + state.borrow().tracker.track_async_completed(op_id); + + let tc_scope = &mut v8::TryCatch::new(scope); + let js_recv_cb = js_recv_cb_handle.open(tc_scope); + let this = v8::undefined(tc_scope).into(); + js_recv_cb.call(tc_scope, this, args); + } + EagerPollResult::Ready(op) => { + let ready = OpCall::ready(op); + let state_rc = JsRuntime::state(scope); + let mut state = state_rc.borrow_mut(); + state.pending_ops.push(ready); + state.have_unpolled_ops = true; + } + EagerPollResult::Pending(op) => { + let state_rc = JsRuntime::state(scope); + let mut state = state_rc.borrow_mut(); + state.pending_ops.push(op); + state.have_unpolled_ops = true; + } + } } #[cfg(test)] @@ -2194,7 +2234,7 @@ pub mod tests { dispatch_count: Arc<AtomicUsize>, } - #[op] + #[op(deferred)] async fn op_test( rc_op_state: Rc<RefCell<OpState>>, control: u8, @@ -2256,41 +2296,6 @@ pub mod tests { } #[test] - fn test_dispatch() { - let (mut runtime, dispatch_count) = setup(Mode::Async); - runtime - .execute_script( - "filename.js", - r#" - let control = 42; - Deno.core.opAsync("op_test", control); - async function main() { - Deno.core.opAsync("op_test", control); - } - main(); - "#, - ) - .unwrap(); - assert_eq!(dispatch_count.load(Ordering::Relaxed), 2); - } - - #[test] - fn test_op_async_promise_id() { - let (mut runtime, _dispatch_count) = setup(Mode::Async); - runtime - .execute_script( - "filename.js", - r#" - const p = Deno.core.opAsync("op_test", 42); - if (p[Symbol.for("Deno.core.internalPromiseId")] == undefined) { - throw new Error("missing id on returned promise"); - } - "#, - ) - .unwrap(); - } - - #[test] fn test_ref_unref_ops() { let (mut runtime, _dispatch_count) = setup(Mode::Async); runtime @@ -2345,6 +2350,41 @@ pub mod tests { } #[test] + fn test_dispatch() { + let (mut runtime, dispatch_count) = setup(Mode::Async); + runtime + .execute_script( + "filename.js", + r#" + let control = 42; + Deno.core.opAsync("op_test", control); + async function main() { + Deno.core.opAsync("op_test", control); + } + main(); + "#, + ) + .unwrap(); + assert_eq!(dispatch_count.load(Ordering::Relaxed), 2); + } + + #[test] + fn test_op_async_promise_id() { + let (mut runtime, _dispatch_count) = setup(Mode::Async); + runtime + .execute_script( + "filename.js", + r#" + const p = Deno.core.opAsync("op_test", 42); + if (p[Symbol.for("Deno.core.internalPromiseId")] == undefined) { + throw new Error("missing id on returned promise"); + } + "#, + ) + .unwrap(); + } + + #[test] fn test_dispatch_no_zero_copy_buf() { let (mut runtime, dispatch_count) = setup(Mode::AsyncZeroCopy(false)); runtime |