summaryrefslogtreecommitdiff
path: root/ops/op2
diff options
context:
space:
mode:
Diffstat (limited to 'ops/op2')
-rw-r--r--ops/op2/dispatch_fast.rs293
-rw-r--r--ops/op2/dispatch_slow.rs100
-rw-r--r--ops/op2/generator_state.rs4
-rw-r--r--ops/op2/mod.rs11
-rw-r--r--ops/op2/test_cases/sync/add.out7
-rw-r--r--ops/op2/test_cases/sync/doc_comment.out5
-rw-r--r--ops/op2/test_cases/sync/result_primitive.out59
-rw-r--r--ops/op2/test_cases/sync/result_primitive.rs2
-rw-r--r--ops/op2/test_cases/sync/result_void.out59
-rw-r--r--ops/op2/test_cases/sync/result_void.rs2
-rw-r--r--ops/op2/test_cases/sync/smi.out7
11 files changed, 392 insertions, 157 deletions
diff --git a/ops/op2/dispatch_fast.rs b/ops/op2/dispatch_fast.rs
index 94140dbf6..5262196f4 100644
--- a/ops/op2/dispatch_fast.rs
+++ b/ops/op2/dispatch_fast.rs
@@ -11,7 +11,7 @@ use quote::quote;
#[allow(unused)]
#[derive(Debug, Default, PartialEq, Clone)]
-pub(crate) enum FastValue {
+pub(crate) enum V8FastCallType {
#[default]
Void,
Bool,
@@ -27,66 +27,74 @@ pub(crate) enum FastValue {
Uint32Array,
Float64Array,
SeqOneByteString,
+ CallbackOptions,
}
-impl FastValue {
+impl V8FastCallType {
/// Quote fast value type.
- fn quote_rust_type(&self) -> TokenStream {
+ fn quote_rust_type(&self, deno_core: &TokenStream) -> TokenStream {
match self {
- FastValue::Void => quote!(()),
- FastValue::Bool => quote!(bool),
- FastValue::U32 => quote!(u32),
- FastValue::I32 => quote!(i32),
- FastValue::U64 => quote!(u64),
- FastValue::I64 => quote!(i64),
- FastValue::F32 => quote!(f32),
- FastValue::F64 => quote!(f64),
- FastValue::Pointer => quote!(*mut ::std::ffi::c_void),
- FastValue::V8Value => unimplemented!("v8::Local<v8::Value>"),
- FastValue::Uint8Array
- | FastValue::Uint32Array
- | FastValue::Float64Array
- | FastValue::SeqOneByteString => unreachable!(),
+ V8FastCallType::Void => quote!(()),
+ V8FastCallType::Bool => quote!(bool),
+ V8FastCallType::U32 => quote!(u32),
+ V8FastCallType::I32 => quote!(i32),
+ V8FastCallType::U64 => quote!(u64),
+ V8FastCallType::I64 => quote!(i64),
+ V8FastCallType::F32 => quote!(f32),
+ V8FastCallType::F64 => quote!(f64),
+ V8FastCallType::Pointer => quote!(*mut ::std::ffi::c_void),
+ V8FastCallType::V8Value => {
+ quote!(#deno_core::v8::Local<#deno_core::v8::Value>)
+ }
+ V8FastCallType::CallbackOptions => {
+ quote!(*mut #deno_core::v8::fast_api::FastApiCallbackOptions)
+ }
+ V8FastCallType::Uint8Array
+ | V8FastCallType::Uint32Array
+ | V8FastCallType::Float64Array
+ | V8FastCallType::SeqOneByteString => unreachable!(),
}
}
/// Quote fast value type's variant.
fn quote_ctype(&self) -> TokenStream {
match &self {
- FastValue::Void => quote!(CType::Void),
- FastValue::Bool => quote!(CType::Bool),
- FastValue::U32 => quote!(CType::Uint32),
- FastValue::I32 => quote!(CType::Int32),
- FastValue::U64 => quote!(CType::Uint64),
- FastValue::I64 => quote!(CType::Int64),
- FastValue::F32 => quote!(CType::Float32),
- FastValue::F64 => quote!(CType::Float64),
- FastValue::Pointer => quote!(CType::Pointer),
- FastValue::V8Value => quote!(CType::V8Value),
- FastValue::Uint8Array => unreachable!(),
- FastValue::Uint32Array => unreachable!(),
- FastValue::Float64Array => unreachable!(),
- FastValue::SeqOneByteString => quote!(CType::SeqOneByteString),
+ V8FastCallType::Void => quote!(CType::Void),
+ V8FastCallType::Bool => quote!(CType::Bool),
+ V8FastCallType::U32 => quote!(CType::Uint32),
+ V8FastCallType::I32 => quote!(CType::Int32),
+ V8FastCallType::U64 => quote!(CType::Uint64),
+ V8FastCallType::I64 => quote!(CType::Int64),
+ V8FastCallType::F32 => quote!(CType::Float32),
+ V8FastCallType::F64 => quote!(CType::Float64),
+ V8FastCallType::Pointer => quote!(CType::Pointer),
+ V8FastCallType::V8Value => quote!(CType::V8Value),
+ V8FastCallType::CallbackOptions => quote!(CType::CallbackOptions),
+ V8FastCallType::Uint8Array => unreachable!(),
+ V8FastCallType::Uint32Array => unreachable!(),
+ V8FastCallType::Float64Array => unreachable!(),
+ V8FastCallType::SeqOneByteString => quote!(CType::SeqOneByteString),
}
}
/// Quote fast value type's variant.
fn quote_type(&self) -> TokenStream {
match &self {
- FastValue::Void => quote!(Type::Void),
- FastValue::Bool => quote!(Type::Bool),
- FastValue::U32 => quote!(Type::Uint32),
- FastValue::I32 => quote!(Type::Int32),
- FastValue::U64 => quote!(Type::Uint64),
- FastValue::I64 => quote!(Type::Int64),
- FastValue::F32 => quote!(Type::Float32),
- FastValue::F64 => quote!(Type::Float64),
- FastValue::Pointer => quote!(Type::Pointer),
- FastValue::V8Value => quote!(Type::V8Value),
- FastValue::Uint8Array => quote!(Type::TypedArray(CType::Uint8)),
- FastValue::Uint32Array => quote!(Type::TypedArray(CType::Uint32)),
- FastValue::Float64Array => quote!(Type::TypedArray(CType::Float64)),
- FastValue::SeqOneByteString => quote!(Type::SeqOneByteString),
+ V8FastCallType::Void => quote!(Type::Void),
+ V8FastCallType::Bool => quote!(Type::Bool),
+ V8FastCallType::U32 => quote!(Type::Uint32),
+ V8FastCallType::I32 => quote!(Type::Int32),
+ V8FastCallType::U64 => quote!(Type::Uint64),
+ V8FastCallType::I64 => quote!(Type::Int64),
+ V8FastCallType::F32 => quote!(Type::Float32),
+ V8FastCallType::F64 => quote!(Type::Float64),
+ V8FastCallType::Pointer => quote!(Type::Pointer),
+ V8FastCallType::V8Value => quote!(Type::V8Value),
+ V8FastCallType::CallbackOptions => quote!(Type::CallbackOptions),
+ V8FastCallType::Uint8Array => quote!(Type::TypedArray(CType::Uint8)),
+ V8FastCallType::Uint32Array => quote!(Type::TypedArray(CType::Uint32)),
+ V8FastCallType::Float64Array => quote!(Type::TypedArray(CType::Float64)),
+ V8FastCallType::SeqOneByteString => quote!(Type::SeqOneByteString),
}
}
}
@@ -95,104 +103,181 @@ pub fn generate_dispatch_fast(
generator_state: &mut GeneratorState,
signature: &ParsedSignature,
) -> Result<Option<(TokenStream, TokenStream)>, V8MappingError> {
- // Result not fast-call compatible (yet)
- if matches!(signature.ret_val, RetVal::Result(..)) {
- return Ok(None);
- }
-
let mut inputs = vec![];
for arg in &signature.args {
- let fv = match arg {
- Arg::OptionNumeric(_) | Arg::SerdeV8(_) => return Ok(None),
- Arg::Numeric(NumericArg::bool) => FastValue::Bool,
- Arg::Numeric(NumericArg::u32)
- | Arg::Numeric(NumericArg::u16)
- | Arg::Numeric(NumericArg::u8) => FastValue::U32,
- Arg::Numeric(NumericArg::i32)
- | Arg::Numeric(NumericArg::i16)
- | Arg::Numeric(NumericArg::i8)
- | Arg::Numeric(NumericArg::__SMI__) => FastValue::I32,
- Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => {
- FastValue::U64
- }
- Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => {
- FastValue::I64
- }
- _ => {
- return Err(V8MappingError::NoMapping("a fast argument", arg.clone()))
- }
+ let Some(fv) = map_arg_to_v8_fastcall_type(arg)? else {
+ return Ok(None);
};
inputs.push(fv);
}
+ let mut names = inputs
+ .iter()
+ .enumerate()
+ .map(|(i, _)| format_ident!("arg{i}"))
+ .collect::<Vec<_>>();
let ret_val = match &signature.ret_val {
RetVal::Infallible(arg) => arg,
RetVal::Result(arg) => arg,
};
- let output = match ret_val {
- Arg::OptionNumeric(_) | Arg::SerdeV8(_) => return Ok(None),
- Arg::Void => FastValue::Void,
- Arg::Numeric(NumericArg::bool) => FastValue::Bool,
- Arg::Numeric(NumericArg::u32)
- | Arg::Numeric(NumericArg::u16)
- | Arg::Numeric(NumericArg::u8) => FastValue::U32,
- Arg::Numeric(NumericArg::i32)
- | Arg::Numeric(NumericArg::i16)
- | Arg::Numeric(NumericArg::i8) => FastValue::I32,
- Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => {
- FastValue::U64
- }
- Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => {
- FastValue::I64
- }
- Arg::Special(_) => return Ok(None),
- _ => {
- return Err(V8MappingError::NoMapping(
- "a fast return value",
- ret_val.clone(),
- ))
- }
+ let output = match map_retval_to_v8_fastcall_type(ret_val)? {
+ None => return Ok(None),
+ Some(rv) => rv,
};
let GeneratorState {
fast_function,
deno_core,
+ result,
+ opctx,
+ fast_api_callback_options,
+ needs_fast_api_callback_options,
+ needs_fast_opctx,
..
- } = &generator_state;
+ } = generator_state;
+
+ let handle_error = match signature.ret_val {
+ RetVal::Infallible(_) => quote!(),
+ RetVal::Result(_) => {
+ *needs_fast_api_callback_options = true;
+ *needs_fast_opctx = true;
+ inputs.push(V8FastCallType::CallbackOptions);
+ quote! {
+ let #result = match #result {
+ Ok(#result) => #result,
+ Err(err) => {
+ // FASTCALL FALLBACK: This is where we set the errors for the slow-call error pickup path. There
+ // is no code running between this and the other FASTCALL FALLBACK comment, except some V8 code
+ // required to perform the fallback process. This is why the below call is safe.
- let input_types = inputs.iter().map(|fv| fv.quote_type());
+ // The reason we need to do this is because V8 does not allow exceptions to be thrown from the
+ // fast call. Instead, you are required to set the fallback flag, which indicates to V8 that it
+ // should re-call the slow version of the function. Technically the slow call should perform the
+ // same operation and then throw the same error (because it should be idempotent), but in our
+ // case we stash the error and pick it up on the slow path before doing any work.
+
+ // TODO(mmastrac): We should allow an #[op] flag to re-perform slow calls without the error path when
+ // the method is performance sensitive.
+
+ // SAFETY: We guarantee that OpCtx has no mutable references once ops are live and being called,
+ // allowing us to perform this one little bit of mutable magic.
+ unsafe { #opctx.unsafely_set_last_error_for_ops_only(err); }
+ #fast_api_callback_options.fallback = true;
+ return ::std::default::Default::default();
+ }
+ };
+ }
+ }
+ };
+
+ let input_types = inputs.iter().map(|fv| fv.quote_type()).collect::<Vec<_>>();
let output_type = output.quote_ctype();
let fast_definition = quote! {
use #deno_core::v8::fast_api::Type;
use #deno_core::v8::fast_api::CType;
#deno_core::v8::fast_api::FastFunction::new(
- &[ #( #input_types ),* ],
+ &[ Type::V8Value, #( #input_types ),* ],
#output_type,
Self::#fast_function as *const ::std::ffi::c_void
)
};
- let output_type = output.quote_rust_type();
- let names = &inputs
+ let output_type = output.quote_rust_type(deno_core);
+ let mut types = inputs
.iter()
- .enumerate()
- .map(|(i, _)| format_ident!("arg{i}"))
+ .map(|rv| rv.quote_rust_type(deno_core))
.collect::<Vec<_>>();
- let types = inputs.iter().map(|rv| rv.quote_rust_type());
+
+ let call_args = names.clone();
+
+ let with_fast_api_callback_options = if *needs_fast_api_callback_options {
+ types.push(V8FastCallType::CallbackOptions.quote_rust_type(deno_core));
+ names.push(fast_api_callback_options.clone());
+ quote! {
+ let #fast_api_callback_options = unsafe { &mut *#fast_api_callback_options };
+ }
+ } else {
+ quote!()
+ };
+ let with_opctx = if *needs_fast_opctx {
+ quote!(
+ let #opctx = unsafe {
+ &*(#deno_core::v8::Local::<v8::External>::cast(unsafe { #fast_api_callback_options.data.data }).value()
+ as *const #deno_core::_ops::OpCtx)
+ };
+ )
+ } else {
+ quote!()
+ };
let fast_fn = quote!(
fn #fast_function(
_: #deno_core::v8::Local<#deno_core::v8::Object>,
#( #names: #types, )*
) -> #output_type {
- #(
- let #names = #names as _;
- )*
- Self::call(#(#names),*)
+ #with_fast_api_callback_options
+ #with_opctx
+ let #result = Self::call(#(#call_args as _),*);
+ #handle_error
+ #result
}
);
Ok(Some((fast_definition, fast_fn)))
}
+
+fn map_arg_to_v8_fastcall_type(
+ arg: &Arg,
+) -> Result<Option<V8FastCallType>, V8MappingError> {
+ let rv = match arg {
+ Arg::OptionNumeric(_) | Arg::SerdeV8(_) => return Ok(None),
+ Arg::Numeric(NumericArg::bool) => V8FastCallType::Bool,
+ Arg::Numeric(NumericArg::u32)
+ | Arg::Numeric(NumericArg::u16)
+ | Arg::Numeric(NumericArg::u8) => V8FastCallType::U32,
+ Arg::Numeric(NumericArg::i32)
+ | Arg::Numeric(NumericArg::i16)
+ | Arg::Numeric(NumericArg::i8)
+ | Arg::Numeric(NumericArg::__SMI__) => V8FastCallType::I32,
+ Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => {
+ V8FastCallType::U64
+ }
+ Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => {
+ V8FastCallType::I64
+ }
+ _ => return Err(V8MappingError::NoMapping("a fast argument", arg.clone())),
+ };
+ Ok(Some(rv))
+}
+
+fn map_retval_to_v8_fastcall_type(
+ arg: &Arg,
+) -> Result<Option<V8FastCallType>, V8MappingError> {
+ let rv = match arg {
+ Arg::OptionNumeric(_) | Arg::SerdeV8(_) => return Ok(None),
+ Arg::Void => V8FastCallType::Void,
+ Arg::Numeric(NumericArg::bool) => V8FastCallType::Bool,
+ Arg::Numeric(NumericArg::u32)
+ | Arg::Numeric(NumericArg::u16)
+ | Arg::Numeric(NumericArg::u8) => V8FastCallType::U32,
+ Arg::Numeric(NumericArg::i32)
+ | Arg::Numeric(NumericArg::i16)
+ | Arg::Numeric(NumericArg::i8) => V8FastCallType::I32,
+ Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => {
+ V8FastCallType::U64
+ }
+ Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => {
+ V8FastCallType::I64
+ }
+ Arg::Special(_) => return Ok(None),
+ _ => {
+ return Err(V8MappingError::NoMapping(
+ "a fast return value",
+ arg.clone(),
+ ))
+ }
+ };
+ Ok(Some(rv))
+}
diff --git a/ops/op2/dispatch_slow.rs b/ops/op2/dispatch_slow.rs
index f54a28f1c..f10217a2d 100644
--- a/ops/op2/dispatch_slow.rs
+++ b/ops/op2/dispatch_slow.rs
@@ -1,3 +1,4 @@
+use super::MacroConfig;
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use super::generator_state::GeneratorState;
use super::signature::Arg;
@@ -9,11 +10,31 @@ use super::V8MappingError;
use proc_macro2::TokenStream;
use quote::quote;
-pub fn generate_dispatch_slow(
+pub(crate) fn generate_dispatch_slow(
+ config: &MacroConfig,
generator_state: &mut GeneratorState,
signature: &ParsedSignature,
) -> Result<TokenStream, V8MappingError> {
let mut output = TokenStream::new();
+
+ // Fast ops require the slow op to check op_ctx for the last error
+ if config.fast && matches!(signature.ret_val, RetVal::Result(_)) {
+ generator_state.needs_opctx = true;
+ let throw_exception = throw_exception(generator_state)?;
+ // If the fast op returned an error, we must throw it rather than doing work.
+ output.extend(quote!{
+ // FASTCALL FALLBACK: This is where we pick up the errors for the slow-call error pickup
+ // path. There is no code running between this and the other FASTCALL FALLBACK comment,
+ // except some V8 code required to perform the fallback process. This is why the below call is safe.
+
+ // SAFETY: We guarantee that OpCtx has no mutable references once ops are live and being called,
+ // allowing us to perform this one little bit of mutable magic.
+ if let Some(err) = unsafe { opctx.unsafely_take_last_error_for_ops_only() } {
+ #throw_exception
+ }
+ });
+ }
+
for (index, arg) in signature.args.iter().enumerate() {
output.extend(extract_arg(generator_state, index)?);
output.extend(from_arg(generator_state, index, arg)?);
@@ -27,6 +48,12 @@ pub fn generate_dispatch_slow(
quote!()
};
+ let with_opctx = if generator_state.needs_opctx {
+ with_opctx(generator_state)
+ } else {
+ quote!()
+ };
+
let with_retval = if generator_state.needs_retval {
with_retval(generator_state)
} else {
@@ -51,6 +78,7 @@ pub fn generate_dispatch_slow(
#with_scope
#with_retval
#with_args
+ #with_opctx
#output
}})
@@ -94,9 +122,11 @@ fn with_opctx(generator_state: &mut GeneratorState) -> TokenStream {
deno_core,
opctx,
fn_args,
+ needs_args,
..
- } = &generator_state;
+ } = generator_state;
+ *needs_args = true;
quote!(let #opctx = unsafe {
&*(#deno_core::v8::Local::<#deno_core::v8::External>::cast(#fn_args.data()).value()
as *const #deno_core::_ops::OpCtx)
@@ -246,56 +276,68 @@ pub fn return_value_infallible(
Ok(res)
}
-pub fn return_value_result(
+fn return_value_result(
generator_state: &mut GeneratorState,
ret_type: &Arg,
) -> Result<TokenStream, V8MappingError> {
let infallible = return_value_infallible(generator_state, ret_type)?;
+ let exception = throw_exception(generator_state)?;
+
+ let GeneratorState { result, .. } = &generator_state;
+
+ let tokens = quote!(
+ match #result {
+ Ok(#result) => {
+ #infallible
+ }
+ Err(err) => {
+ #exception
+ }
+ };
+ );
+ Ok(tokens)
+}
+
+/// Generates code to throw an exception, adding required additional dependencies as needed.
+fn throw_exception(
+ generator_state: &mut GeneratorState,
+) -> Result<TokenStream, V8MappingError> {
let maybe_scope = if generator_state.needs_scope {
quote!()
} else {
with_scope(generator_state)
};
- let maybe_args = if generator_state.needs_args {
+ let maybe_opctx = if generator_state.needs_opctx {
quote!()
} else {
- with_fn_args(generator_state)
+ with_opctx(generator_state)
};
- let maybe_opctx = if generator_state.needs_opctx {
+ let maybe_args = if generator_state.needs_args {
quote!()
} else {
- with_opctx(generator_state)
+ with_fn_args(generator_state)
};
let GeneratorState {
deno_core,
- result,
scope,
opctx,
..
} = &generator_state;
- let tokens = quote!(
- match #result {
- Ok(#result) => {
- #infallible
- }
- Err(err) => {
- #maybe_scope
- #maybe_args
- #maybe_opctx
- let opstate = ::std::cell::RefCell::borrow(&*#opctx.state);
- let exception = #deno_core::error::to_v8_error(
- #scope,
- opstate.get_error_class_fn,
- &err,
- );
- scope.throw_exception(exception);
- return;
- }
- };
- );
- Ok(tokens)
+ Ok(quote! {
+ #maybe_scope
+ #maybe_args
+ #maybe_opctx
+ let opstate = ::std::cell::RefCell::borrow(&*#opctx.state);
+ let exception = #deno_core::error::to_v8_error(
+ #scope,
+ opstate.get_error_class_fn,
+ &err,
+ );
+ scope.throw_exception(exception);
+ return;
+ })
}
diff --git a/ops/op2/generator_state.rs b/ops/op2/generator_state.rs
index 16249c217..e437ea47c 100644
--- a/ops/op2/generator_state.rs
+++ b/ops/op2/generator_state.rs
@@ -21,6 +21,8 @@ pub struct GeneratorState {
pub fn_args: Ident,
/// The `OpCtx` used for various information required for some ops.
pub opctx: Ident,
+ /// The `FastApiCallbackOptions` used in fast calls for fallback returns.
+ pub fast_api_callback_options: Ident,
/// The `v8::ReturnValue` used in the slow function
pub retval: Ident,
/// The "slow" function (ie: the one that isn't a fastcall)
@@ -33,4 +35,6 @@ pub struct GeneratorState {
pub needs_scope: bool,
pub needs_opstate: bool,
pub needs_opctx: bool,
+ pub needs_fast_opctx: bool,
+ pub needs_fast_api_callback_options: bool,
}
diff --git a/ops/op2/mod.rs b/ops/op2/mod.rs
index 558d7c7dc..67a92d450 100644
--- a/ops/op2/mod.rs
+++ b/ops/op2/mod.rs
@@ -50,7 +50,7 @@ pub enum V8MappingError {
}
#[derive(Default)]
-struct MacroConfig {
+pub(crate) struct MacroConfig {
pub core: bool,
pub fast: bool,
}
@@ -135,6 +135,8 @@ fn generate_op2(
let opctx = Ident::new("opctx", Span::call_site());
let slow_function = Ident::new("slow_function", Span::call_site());
let fast_function = Ident::new("fast_function", Span::call_site());
+ let fast_api_callback_options =
+ Ident::new("fast_api_callback_options", Span::call_site());
let deno_core = if config.core {
syn2::parse_str::<Path>("crate")
@@ -151,6 +153,7 @@ fn generate_op2(
scope,
info,
opctx,
+ fast_api_callback_options,
deno_core,
result,
retval,
@@ -161,10 +164,14 @@ fn generate_op2(
needs_scope: false,
needs_opctx: false,
needs_opstate: false,
+ needs_fast_opctx: false,
+ needs_fast_api_callback_options: false,
};
let name = func.sig.ident;
- let slow_fn = generate_dispatch_slow(&mut generator_state, &signature)?;
+
+ let slow_fn =
+ generate_dispatch_slow(&config, &mut generator_state, &signature)?;
let (fast_definition, fast_fn) =
match generate_dispatch_fast(&mut generator_state, &signature)? {
Some((fast_definition, fast_fn)) => {
diff --git a/ops/op2/test_cases/sync/add.out b/ops/op2/test_cases/sync/add.out
index a7269c5cf..7d97a7161 100644
--- a/ops/op2/test_cases/sync/add.out
+++ b/ops/op2/test_cases/sync/add.out
@@ -13,7 +13,7 @@ impl op_add {
use deno_core::v8::fast_api::Type;
use deno_core::v8::fast_api::CType;
deno_core::v8::fast_api::FastFunction::new(
- &[Type::Uint32, Type::Uint32],
+ &[Type::V8Value, Type::Uint32, Type::Uint32],
CType::Uint32,
Self::fast_function as *const ::std::ffi::c_void,
)
@@ -43,9 +43,8 @@ impl op_add {
arg0: u32,
arg1: u32,
) -> u32 {
- let arg0 = arg0 as _;
- let arg1 = arg1 as _;
- Self::call(arg0, arg1)
+ let result = Self::call(arg0 as _, arg1 as _);
+ result
}
#[inline(always)]
fn call(a: u32, b: u32) -> u32 {
diff --git a/ops/op2/test_cases/sync/doc_comment.out b/ops/op2/test_cases/sync/doc_comment.out
index bd0d0b21f..e9f063102 100644
--- a/ops/op2/test_cases/sync/doc_comment.out
+++ b/ops/op2/test_cases/sync/doc_comment.out
@@ -13,7 +13,7 @@ impl op_has_doc_comment {
use deno_core::v8::fast_api::Type;
use deno_core::v8::fast_api::CType;
deno_core::v8::fast_api::FastFunction::new(
- &[],
+ &[Type::V8Value],
CType::Void,
Self::fast_function as *const ::std::ffi::c_void,
)
@@ -28,7 +28,8 @@ impl op_has_doc_comment {
let result = Self::call();
}
fn fast_function(_: deno_core::v8::Local<deno_core::v8::Object>) -> () {
- Self::call()
+ let result = Self::call();
+ result
}
#[inline(always)]
pub fn call() -> () {}
diff --git a/ops/op2/test_cases/sync/result_primitive.out b/ops/op2/test_cases/sync/result_primitive.out
index a8ac50174..151e8e730 100644
--- a/ops/op2/test_cases/sync/result_primitive.out
+++ b/ops/op2/test_cases/sync/result_primitive.out
@@ -9,7 +9,15 @@ impl op_u32_with_result {
name: stringify!(op_u32_with_result),
v8_fn_ptr: Self::slow_function as _,
enabled: true,
- fast_fn: None,
+ fast_fn: Some({
+ use deno_core::v8::fast_api::Type;
+ use deno_core::v8::fast_api::CType;
+ deno_core::v8::fast_api::FastFunction::new(
+ &[Type::V8Value, Type::CallbackOptions],
+ CType::Uint32,
+ Self::fast_function as *const ::std::ffi::c_void,
+ )
+ }),
is_async: false,
is_unstable: false,
is_v8: false,
@@ -20,6 +28,27 @@ impl op_u32_with_result {
let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
&*info
});
+ let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe {
+ &*info
+ });
+ let opctx = unsafe {
+ &*(deno_core::v8::Local::<deno_core::v8::External>::cast(args.data()).value()
+ as *const deno_core::_ops::OpCtx)
+ };
+ if let Some(err) = unsafe { opctx.unsafely_take_last_error_for_ops_only() } {
+ let scope = &mut unsafe { deno_core::v8::CallbackScope::new(&*info) };
+ let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe {
+ &*info
+ });
+ let opstate = ::std::cell::RefCell::borrow(&*opctx.state);
+ let exception = deno_core::error::to_v8_error(
+ scope,
+ opstate.get_error_class_fn,
+ &err,
+ );
+ scope.throw_exception(exception);
+ return;
+ }
let result = Self::call();
match result {
Ok(result) => {
@@ -30,10 +59,6 @@ impl op_u32_with_result {
let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe {
&*info
});
- let opctx = unsafe {
- &*(deno_core::v8::Local::<deno_core::v8::External>::cast(args.data())
- .value() as *const deno_core::_ops::OpCtx)
- };
let opstate = ::std::cell::RefCell::borrow(&*opctx.state);
let exception = deno_core::error::to_v8_error(
scope,
@@ -45,6 +70,30 @@ impl op_u32_with_result {
}
};
}
+ fn fast_function(
+ _: deno_core::v8::Local<deno_core::v8::Object>,
+ fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
+ ) -> u32 {
+ let fast_api_callback_options = unsafe { &mut *fast_api_callback_options };
+ let opctx = unsafe {
+ &*(deno_core::v8::Local::<
+ v8::External,
+ >::cast(unsafe { fast_api_callback_options.data.data })
+ .value() as *const deno_core::_ops::OpCtx)
+ };
+ let result = Self::call();
+ let result = match result {
+ Ok(result) => result,
+ Err(err) => {
+ unsafe {
+ opctx.unsafely_set_last_error_for_ops_only(err);
+ }
+ fast_api_callback_options.fallback = true;
+ return ::std::default::Default::default();
+ }
+ };
+ result
+ }
#[inline(always)]
pub fn call() -> Result<u32, AnyError> {}
}
diff --git a/ops/op2/test_cases/sync/result_primitive.rs b/ops/op2/test_cases/sync/result_primitive.rs
index 6f68fa228..df89c2432 100644
--- a/ops/op2/test_cases/sync/result_primitive.rs
+++ b/ops/op2/test_cases/sync/result_primitive.rs
@@ -1,4 +1,4 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-#[op2]
+#[op2(fast)]
pub fn op_u32_with_result() -> Result<u32, AnyError> {}
diff --git a/ops/op2/test_cases/sync/result_void.out b/ops/op2/test_cases/sync/result_void.out
index 74c0c66a6..afc10582b 100644
--- a/ops/op2/test_cases/sync/result_void.out
+++ b/ops/op2/test_cases/sync/result_void.out
@@ -9,7 +9,15 @@ impl op_void_with_result {
name: stringify!(op_void_with_result),
v8_fn_ptr: Self::slow_function as _,
enabled: true,
- fast_fn: None,
+ fast_fn: Some({
+ use deno_core::v8::fast_api::Type;
+ use deno_core::v8::fast_api::CType;
+ deno_core::v8::fast_api::FastFunction::new(
+ &[Type::V8Value, Type::CallbackOptions],
+ CType::Void,
+ Self::fast_function as *const ::std::ffi::c_void,
+ )
+ }),
is_async: false,
is_unstable: false,
is_v8: false,
@@ -17,6 +25,27 @@ impl op_void_with_result {
}
}
pub extern "C" fn slow_function(info: *const deno_core::v8::FunctionCallbackInfo) {
+ let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe {
+ &*info
+ });
+ let opctx = unsafe {
+ &*(deno_core::v8::Local::<deno_core::v8::External>::cast(args.data()).value()
+ as *const deno_core::_ops::OpCtx)
+ };
+ if let Some(err) = unsafe { opctx.unsafely_take_last_error_for_ops_only() } {
+ let scope = &mut unsafe { deno_core::v8::CallbackScope::new(&*info) };
+ let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe {
+ &*info
+ });
+ let opstate = ::std::cell::RefCell::borrow(&*opctx.state);
+ let exception = deno_core::error::to_v8_error(
+ scope,
+ opstate.get_error_class_fn,
+ &err,
+ );
+ scope.throw_exception(exception);
+ return;
+ }
let result = Self::call();
match result {
Ok(result) => {}
@@ -25,10 +54,6 @@ impl op_void_with_result {
let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe {
&*info
});
- let opctx = unsafe {
- &*(deno_core::v8::Local::<deno_core::v8::External>::cast(args.data())
- .value() as *const deno_core::_ops::OpCtx)
- };
let opstate = ::std::cell::RefCell::borrow(&*opctx.state);
let exception = deno_core::error::to_v8_error(
scope,
@@ -40,6 +65,30 @@ impl op_void_with_result {
}
};
}
+ fn fast_function(
+ _: deno_core::v8::Local<deno_core::v8::Object>,
+ fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
+ ) -> () {
+ let fast_api_callback_options = unsafe { &mut *fast_api_callback_options };
+ let opctx = unsafe {
+ &*(deno_core::v8::Local::<
+ v8::External,
+ >::cast(unsafe { fast_api_callback_options.data.data })
+ .value() as *const deno_core::_ops::OpCtx)
+ };
+ let result = Self::call();
+ let result = match result {
+ Ok(result) => result,
+ Err(err) => {
+ unsafe {
+ opctx.unsafely_set_last_error_for_ops_only(err);
+ }
+ fast_api_callback_options.fallback = true;
+ return ::std::default::Default::default();
+ }
+ };
+ result
+ }
#[inline(always)]
pub fn call() -> Result<(), AnyError> {}
}
diff --git a/ops/op2/test_cases/sync/result_void.rs b/ops/op2/test_cases/sync/result_void.rs
index 41256e8c4..ef3aa7b32 100644
--- a/ops/op2/test_cases/sync/result_void.rs
+++ b/ops/op2/test_cases/sync/result_void.rs
@@ -1,4 +1,4 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-#[op2]
+#[op2(fast)]
pub fn op_void_with_result() -> Result<(), AnyError> {}
diff --git a/ops/op2/test_cases/sync/smi.out b/ops/op2/test_cases/sync/smi.out
index e6c1bc1e3..7210e0572 100644
--- a/ops/op2/test_cases/sync/smi.out
+++ b/ops/op2/test_cases/sync/smi.out
@@ -13,7 +13,7 @@ impl op_add {
use deno_core::v8::fast_api::Type;
use deno_core::v8::fast_api::CType;
deno_core::v8::fast_api::FastFunction::new(
- &[Type::Int32, Type::Uint32],
+ &[Type::V8Value, Type::Int32, Type::Uint32],
CType::Uint32,
Self::fast_function as *const ::std::ffi::c_void,
)
@@ -43,9 +43,8 @@ impl op_add {
arg0: i32,
arg1: u32,
) -> u32 {
- let arg0 = arg0 as _;
- let arg1 = arg1 as _;
- Self::call(arg0, arg1)
+ let result = Self::call(arg0 as _, arg1 as _);
+ result
}
#[inline(always)]
fn call(id: ResourceId, extra: u16) -> u32 {}