summaryrefslogtreecommitdiff
path: root/ops/op2/dispatch_slow.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ops/op2/dispatch_slow.rs')
-rw-r--r--ops/op2/dispatch_slow.rs401
1 files changed, 0 insertions, 401 deletions
diff --git a/ops/op2/dispatch_slow.rs b/ops/op2/dispatch_slow.rs
deleted file mode 100644
index 2ec67cc76..000000000
--- a/ops/op2/dispatch_slow.rs
+++ /dev/null
@@ -1,401 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-use super::generator_state::GeneratorState;
-use super::signature::Arg;
-use super::signature::NumericArg;
-use super::signature::ParsedSignature;
-use super::signature::RetVal;
-use super::signature::Special;
-use super::MacroConfig;
-use super::V8MappingError;
-use proc_macro2::TokenStream;
-use quote::format_ident;
-use quote::quote;
-
-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)?);
- }
- output.extend(call(generator_state)?);
- output.extend(return_value(generator_state, &signature.ret_val)?);
-
- let with_scope = if generator_state.needs_scope {
- with_scope(generator_state)
- } else {
- 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 {
- quote!()
- };
-
- let with_args = if generator_state.needs_args {
- with_fn_args(generator_state)
- } else {
- quote!()
- };
-
- let GeneratorState {
- deno_core,
- info,
- slow_function,
- ..
- } = &generator_state;
-
- Ok(quote! {
- extern "C" fn #slow_function(#info: *const #deno_core::v8::FunctionCallbackInfo) {
- #with_scope
- #with_retval
- #with_args
- #with_opctx
-
- #output
- }})
-}
-
-fn with_scope(generator_state: &mut GeneratorState) -> TokenStream {
- let GeneratorState {
- deno_core,
- scope,
- info,
- ..
- } = &generator_state;
-
- quote!(let #scope = &mut unsafe { #deno_core::v8::CallbackScope::new(&*#info) };)
-}
-
-fn with_retval(generator_state: &mut GeneratorState) -> TokenStream {
- let GeneratorState {
- deno_core,
- retval,
- info,
- ..
- } = &generator_state;
-
- quote!(let mut #retval = #deno_core::v8::ReturnValue::from_function_callback_info(unsafe { &*#info });)
-}
-
-fn with_fn_args(generator_state: &mut GeneratorState) -> TokenStream {
- let GeneratorState {
- deno_core,
- fn_args,
- info,
- ..
- } = &generator_state;
-
- quote!(let #fn_args = #deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { &*#info });)
-}
-
-fn with_opctx(generator_state: &mut GeneratorState) -> TokenStream {
- let GeneratorState {
- deno_core,
- opctx,
- fn_args,
- needs_args,
- ..
- } = 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)
- };)
-}
-
-pub fn extract_arg(
- generator_state: &mut GeneratorState,
- index: usize,
-) -> Result<TokenStream, V8MappingError> {
- let GeneratorState { fn_args, .. } = &generator_state;
- let arg_ident = generator_state.args.get(index);
-
- Ok(quote!(
- let #arg_ident = #fn_args.get(#index as i32);
- ))
-}
-
-pub fn from_arg(
- mut generator_state: &mut GeneratorState,
- index: usize,
- arg: &Arg,
-) -> Result<TokenStream, V8MappingError> {
- let GeneratorState {
- deno_core,
- args,
- scope,
- needs_scope,
- ..
- } = &mut generator_state;
- let arg_ident = args.get_mut(index).expect("Argument at index was missing");
- let arg_temp = format_ident!("{}_temp", arg_ident);
- let res = match arg {
- Arg::Numeric(NumericArg::bool) => quote! {
- let #arg_ident = #arg_ident.is_true();
- },
- Arg::Numeric(NumericArg::u8)
- | Arg::Numeric(NumericArg::u16)
- | Arg::Numeric(NumericArg::u32) => {
- quote! {
- let #arg_ident = #deno_core::_ops::to_u32(&#arg_ident) as _;
- }
- }
- Arg::Numeric(NumericArg::i8)
- | Arg::Numeric(NumericArg::i16)
- | Arg::Numeric(NumericArg::i32)
- | Arg::Numeric(NumericArg::__SMI__) => {
- quote! {
- let #arg_ident = #deno_core::_ops::to_i32(&#arg_ident) as _;
- }
- }
- Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => {
- quote! {
- let #arg_ident = #deno_core::_ops::to_u64(&#arg_ident) as _;
- }
- }
- Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => {
- quote! {
- let #arg_ident = #deno_core::_ops::to_i64(&#arg_ident) as _;
- }
- }
- Arg::OptionNumeric(numeric) => {
- // Ends the borrow of generator_state
- let arg_ident = arg_ident.clone();
- let some = from_arg(generator_state, index, &Arg::Numeric(*numeric))?;
- quote! {
- let #arg_ident = if #arg_ident.is_null_or_undefined() {
- None
- } else {
- #some
- Some(#arg_ident)
- };
- }
- }
- Arg::Option(Special::String) => {
- *needs_scope = true;
- quote! {
- let #arg_ident = #arg_ident.to_rust_string_lossy(#scope);
- }
- }
- Arg::Special(Special::String) => {
- *needs_scope = true;
- quote! {
- let #arg_ident = #arg_ident.to_rust_string_lossy(#scope);
- }
- }
- Arg::Special(Special::RefStr) => {
- *needs_scope = true;
- quote! {
- // Trade 1024 bytes of stack space for potentially non-allocating strings
- let mut #arg_temp: [::std::mem::MaybeUninit<u8>; 1024] = [::std::mem::MaybeUninit::uninit(); 1024];
- let #arg_ident = &#deno_core::_ops::to_str(#scope, &#arg_ident, &mut #arg_temp);
- }
- }
- Arg::Special(Special::CowStr) => {
- *needs_scope = true;
- quote! {
- // Trade 1024 bytes of stack space for potentially non-allocating strings
- let mut #arg_temp: [::std::mem::MaybeUninit<u8>; 1024] = [::std::mem::MaybeUninit::uninit(); 1024];
- let #arg_ident = #deno_core::_ops::to_str(#scope, &#arg_ident, &mut #arg_temp);
- }
- }
- _ => return Err(V8MappingError::NoMapping("a slow argument", arg.clone())),
- };
- Ok(res)
-}
-
-pub fn call(
- generator_state: &mut GeneratorState,
-) -> Result<TokenStream, V8MappingError> {
- let GeneratorState { result, .. } = &generator_state;
-
- let mut tokens = TokenStream::new();
- for arg in &generator_state.args {
- tokens.extend(quote!( #arg , ));
- }
- Ok(quote! {
- let #result = Self::call( #tokens );
- })
-}
-
-pub fn return_value(
- generator_state: &mut GeneratorState,
- ret_type: &RetVal,
-) -> Result<TokenStream, V8MappingError> {
- match ret_type {
- RetVal::Infallible(ret_type) => {
- return_value_infallible(generator_state, ret_type)
- }
- RetVal::Result(ret_type) => return_value_result(generator_state, ret_type),
- }
-}
-
-pub fn return_value_infallible(
- generator_state: &mut GeneratorState,
- ret_type: &Arg,
-) -> Result<TokenStream, V8MappingError> {
- let GeneratorState {
- deno_core,
- scope,
- result,
- retval,
- needs_retval,
- needs_scope,
- ..
- } = generator_state;
-
- let res = match ret_type {
- Arg::Void => {
- quote! {/* void */}
- }
- Arg::Numeric(NumericArg::u8)
- | Arg::Numeric(NumericArg::u16)
- | Arg::Numeric(NumericArg::u32) => {
- *needs_retval = true;
- quote!(#retval.set_uint32(#result as u32);)
- }
- Arg::Numeric(NumericArg::i8)
- | Arg::Numeric(NumericArg::i16)
- | Arg::Numeric(NumericArg::i32) => {
- *needs_retval = true;
- quote!(#retval.set_int32(#result as i32);)
- }
- Arg::Special(Special::String) => {
- *needs_retval = true;
- *needs_scope = true;
- quote! {
- if #result.is_empty() {
- #retval.set_empty_string();
- } else {
- // This should not fail in normal cases
- // TODO(mmastrac): This has extra allocations that we need to get rid of, especially if the string
- // is ASCII. We could make an "external Rust String" string in V8 from these and re-use the allocation.
- let temp = #deno_core::v8::String::new(#scope, &#result).unwrap();
- #retval.set(temp.into());
- }
- }
- }
- Arg::Option(Special::String) => {
- *needs_retval = true;
- *needs_scope = true;
- // End the generator_state borrow
- let (result, retval) = (result.clone(), retval.clone());
- let some = return_value_infallible(
- generator_state,
- &Arg::Special(Special::String),
- )?;
- quote! {
- if let Some(#result) = #result {
- #some
- } else {
- #retval.set_null();
- }
- }
- }
- _ => {
- return Err(V8MappingError::NoMapping(
- "a slow return value",
- ret_type.clone(),
- ))
- }
- };
-
- Ok(res)
-}
-
-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_opctx = if generator_state.needs_opctx {
- quote!()
- } else {
- with_opctx(generator_state)
- };
-
- let maybe_args = if generator_state.needs_args {
- quote!()
- } else {
- with_fn_args(generator_state)
- };
-
- let GeneratorState {
- deno_core,
- scope,
- opctx,
- ..
- } = &generator_state;
-
- 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;
- })
-}