1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-24 16:19:12 -05:00
denoland-deno/ops/op2/dispatch_fast.rs
Matt Mastracci 65d9bfb533
refactor(ops): Adding op2 macro and implementing in a couple of places (#19534)
This is a new op system that will eventually replace `#[op]`. 

Features
 - More maintainable, generally less-coupled code
 - More modern Rust proc-macro libraries
- Enforces correct `fast` labelling for fast ops, allowing for visual
scanning of fast ops
 - Explicit marking of `#[string]`, `#[serde]` and `#[smi]` parameters.

This first version of op2 supports integer and Option<integer>
parameters only, and allows us to start working on converting ops and
adding features.
2023-06-24 13:54:10 +02:00

193 lines
5.8 KiB
Rust

// 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::V8MappingError;
use proc_macro2::TokenStream;
use quote::format_ident;
use quote::quote;
#[allow(unused)]
#[derive(Debug, Default, PartialEq, Clone)]
pub(crate) enum FastValue {
#[default]
Void,
Bool,
U32,
I32,
U64,
I64,
F32,
F64,
Pointer,
V8Value,
Uint8Array,
Uint32Array,
Float64Array,
SeqOneByteString,
}
impl FastValue {
/// Quote fast value type.
fn quote_rust_type(&self) -> 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!(),
}
}
/// 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),
}
}
/// 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),
}
}
}
pub fn generate_dispatch_fast(
generator_state: &mut GeneratorState,
signature: &ParsedSignature,
) -> Result<Option<(TokenStream, TokenStream)>, V8MappingError> {
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()))
}
};
inputs.push(fv);
}
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 GeneratorState {
fast_function,
deno_core,
..
} = &generator_state;
let input_types = inputs.iter().map(|fv| fv.quote_type());
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 ),* ],
#output_type,
Self::#fast_function as *const ::std::ffi::c_void
)
};
let output_type = output.quote_rust_type();
let names = &inputs
.iter()
.enumerate()
.map(|(i, _)| format_ident!("arg{i}"))
.collect::<Vec<_>>();
let types = inputs.iter().map(|rv| rv.quote_rust_type());
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),*)
}
);
Ok(Some((fast_definition, fast_fn)))
}