Skip to content

Commit

Permalink
feat(core,ops): add *mut v8::Isolate as a dangerous but fast arg (d…
Browse files Browse the repository at this point in the history
  • Loading branch information
mmastrac authored Oct 17, 2023
1 parent 134ebaa commit c9d2e99
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 71 deletions.
26 changes: 26 additions & 0 deletions core/benches/ops/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ deno_core::extension!(
op_local_nofast,
op_global,
op_global_scope,
op_scope,
op_isolate_nofast,
op_make_external,
op_bigint,
op_bigint_return,
Expand Down Expand Up @@ -94,6 +96,12 @@ pub fn op_global_scope(
) {
}

#[op2]
pub fn op_scope(_scope: &mut v8::HandleScope) {}

#[op2(nofast)]
pub fn op_isolate_nofast(_isolate: *mut v8::Isolate) {}

#[op2(fast)]
pub fn op_make_external() -> *const c_void {
std::ptr::null()
Expand Down Expand Up @@ -405,6 +413,22 @@ fn bench_op_bigint_return(b: &mut Bencher) {
);
}

/// A function that takes only a scope
fn bench_op_v8_scope(b: &mut Bencher) {
bench_op(b, BENCH_COUNT, "op_scope", 1, "op_scope();");
}

/// A function that takes only an isolate
fn bench_op_v8_isolate_nofast(b: &mut Bencher) {
bench_op(
b,
BENCH_COUNT,
"op_isolate_nofast",
1,
"op_isolate_nofast();",
);
}

fn bench_op_external(b: &mut Bencher) {
bench_op(b, BENCH_COUNT, "op_external", 1, "op_external(EXTERNAL)");
}
Expand Down Expand Up @@ -471,6 +495,8 @@ benchmark_group!(
bench_op_v8_global_scope,
bench_op_bigint,
bench_op_bigint_return,
bench_op_v8_scope,
bench_op_v8_isolate_nofast,
bench_op_external,
bench_op_external_nofast,
bench_op_buffer,
Expand Down
48 changes: 29 additions & 19 deletions core/ops_builtin_v8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,40 @@ pub fn op_set_promise_reject_callback<'a>(
old.map(|v| v8::Local::new(scope, &*v))
}

#[op2(core)]
pub fn op_run_microtasks(scope: &mut v8::HandleScope) {
scope.perform_microtask_checkpoint();
// We run in a `nofast` op here so we don't get put into a `DisallowJavascriptExecutionScope` and we're
// allowed to touch JS heap.
#[op2(core, nofast)]
pub fn op_queue_microtask(
isolate: *mut v8::Isolate,
cb: v8::Local<v8::Function>,
) {
// SAFETY: we know v8 provides us a valid, non-null isolate pointer
unsafe {
isolate.as_mut().unwrap_unchecked().enqueue_microtask(cb);
}
}

#[op2(core)]
pub fn op_has_tick_scheduled(scope: &mut v8::HandleScope) -> bool {
let state_rc = JsRuntime::state_from(scope);
let state = state_rc.borrow();
// We run in a `nofast` op here so we don't get put into a `DisallowJavascriptExecutionScope` and we're
// allowed to touch JS heap.
#[op2(core, nofast)]
pub fn op_run_microtasks(isolate: *mut v8::Isolate) {
// SAFETY: we know v8 provides us with a valid, non-null isolate
unsafe {
isolate
.as_mut()
.unwrap_unchecked()
.perform_microtask_checkpoint()
};
}

#[op2(core, fast)]
pub fn op_has_tick_scheduled(state: &JsRuntimeState) -> bool {
state.has_tick_scheduled
}

#[op2(core)]
pub fn op_set_has_tick_scheduled(scope: &mut v8::HandleScope, v: bool) {
let state_rc = JsRuntime::state_from(scope);
state_rc.borrow_mut().has_tick_scheduled = v;
#[op2(core, fast)]
pub fn op_set_has_tick_scheduled(state: &mut JsRuntimeState, v: bool) {
state.has_tick_scheduled = v;
}

#[derive(Serialize)]
Expand Down Expand Up @@ -126,14 +144,6 @@ pub fn op_eval_context<'a>(
}
}

#[op2(core)]
pub fn op_queue_microtask(
scope: &mut v8::HandleScope,
cb: v8::Local<v8::Function>,
) {
scope.enqueue_microtask(cb);
}

#[op2(core)]
pub fn op_create_host_object<'a>(
scope: &mut v8::HandleScope<'a>,
Expand Down
27 changes: 27 additions & 0 deletions core/runtime/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,8 @@ mod tests {
op_external_process,
op_external_make_ptr,
op_external_process_ptr,
op_isolate_queue_microtask,
op_isolate_run_microtasks,

op_async_void,
op_async_number,
Expand Down Expand Up @@ -2094,6 +2096,31 @@ mod tests {
Ok(())
}

#[op2(core, nofast)]
fn op_isolate_run_microtasks(isolate: *mut v8::Isolate) {
// SAFETY: testing
unsafe { isolate.as_mut().unwrap().perform_microtask_checkpoint() };
}

#[op2(core, nofast)]
fn op_isolate_queue_microtask(
isolate: *mut v8::Isolate,
cb: v8::Local<v8::Function>,
) {
// SAFETY: testing
unsafe { isolate.as_mut().unwrap().enqueue_microtask(cb) };
}

#[tokio::test]
pub async fn test_isolate() -> Result<(), Box<dyn std::error::Error>> {
run_test2(
10000,
"op_isolate_queue_microtask,op_isolate_run_microtasks",
"op_isolate_queue_microtask(() => {}); op_isolate_run_microtasks();",
)?;
Ok(())
}

#[op2(async, core)]
async fn op_async_void() {}

Expand Down
14 changes: 14 additions & 0 deletions ops/op2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,20 @@ Rc<RefCell<JsRuntimeState>>
</td><td>
Only usable in `deno_core`.
</td></tr>
<tr>
<td>

```text
*mut v8::Isolate
```

</td><td>
</td><td>

</td><td>
⚠️ Extremely dangerous, may crash if you don't use `nofast` depending on what you do.
</td></tr>
</table>

<!-- END ARGS -->
Expand Down
5 changes: 5 additions & 0 deletions ops/op2/dispatch_fast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,10 @@ fn map_v8_fastcall_arg_to_arg(
Arg::Buffer(buffer, _, BufferSource::TypedArray) => {
fast_api_typed_array_to_buffer(deno_core, arg_ident, arg_ident, *buffer)?
}
Arg::Special(Special::Isolate) => {
*needs_opctx = true;
quote!(let #arg_ident = #opctx.isolate;)
}
Arg::Ref(RefType::Ref, Special::OpState) => {
*needs_opctx = true;
quote!(let #arg_ident = &::std::cell::RefCell::borrow(&#opctx.state);)
Expand Down Expand Up @@ -590,6 +594,7 @@ fn map_arg_to_v8_fastcall_type(
| Arg::RcRefCell(Special::JsRuntimeState)
| Arg::Ref(_, Special::JsRuntimeState)
| Arg::State(..)
| Arg::Special(Special::Isolate)
| Arg::OptionState(..) => V8FastCallType::Virtual,
// Other types + ref types are not handled
Arg::OptionNumeric(..)
Expand Down
6 changes: 6 additions & 0 deletions ops/op2/dispatch_slow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,12 @@ pub fn from_arg(
args,
scope,
opstate,
opctx,
js_runtime_state,
needs_scope,
needs_isolate,
needs_opstate,
needs_opctx,
needs_js_runtime_state,
..
} = &mut generator_state;
Expand Down Expand Up @@ -381,6 +383,10 @@ pub fn from_arg(
Arg::External(External::Ptr(_)) => {
from_arg_option(generator_state, &arg_ident, "external")?
}
Arg::Special(Special::Isolate) => {
*needs_opctx = true;
quote!(let #arg_ident = #opctx.isolate;)
}
Arg::Ref(_, Special::HandleScope) => {
*needs_scope = true;
quote!(let #arg_ident = &mut #scope;)
Expand Down
Loading

0 comments on commit c9d2e99

Please sign in to comment.