summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2023-03-05 13:30:22 +0530
committerGitHub <noreply@github.com>2023-03-05 13:30:22 +0530
commit0910be4d64272be6774b8b3d44852737e8c53ad4 (patch)
treeef8dcbf2e5cf0c8940512923dec016dd2a30c762
parent888ceac7fdc6e9b96d860f183dd2f31df3f3d601 (diff)
feat(ops): relational ops (#18023)
Join two independent ops into one. A fast impl of one + a slow callback of another. Here's an example showing optimized paths for latin-1 via fast call and the next-best fallback using V8 apis. ```rust #[op(v8)] fn op_encoding_encode_into_fallback( scope: &mut v8::HandleScope, input: serde_v8::Value, // ... #[op(fast, slow = op_encoding_encode_into_fallback)] fn op_encoding_encode_into( input: Cow<'_, str>, // ... ``` Benchmark results of the fallback path: ``` time target/release/deno run -A --unstable ./cli/tests/testdata/benches/text_encoder_into_perf.js ________________________________________________________ Executed in 70.90 millis fish external usr time 57.76 millis 0.23 millis 57.53 millis sys time 17.02 millis 1.28 millis 15.74 millis target/release/deno_main run -A --unstable ./cli/tests/testdata/benches/text_encoder_into_perf.js ________________________________________________________ Executed in 154.00 millis fish external usr time 67.14 millis 0.26 millis 66.88 millis sys time 38.82 millis 1.47 millis 37.35 millis ```
-rw-r--r--ext/web/lib.rs23
-rw-r--r--ops/attrs.rs52
-rw-r--r--ops/lib.rs54
3 files changed, 102 insertions, 27 deletions
diff --git a/ext/web/lib.rs b/ext/web/lib.rs
index 2f59636fe..76095810e 100644
--- a/ext/web/lib.rs
+++ b/ext/web/lib.rs
@@ -350,7 +350,28 @@ impl Resource for TextDecoderResource {
}
}
-#[op]
+#[op(v8)]
+fn op_encoding_encode_into_fallback(
+ scope: &mut v8::HandleScope,
+ input: serde_v8::Value,
+ buffer: &mut [u8],
+ out_buf: &mut [u32],
+) -> Result<(), AnyError> {
+ let s = v8::Local::<v8::String>::try_from(input.v8_value)?;
+
+ let mut nchars = 0;
+ out_buf[1] = s.write_utf8(
+ scope,
+ buffer,
+ Some(&mut nchars),
+ v8::WriteOptions::NO_NULL_TERMINATION
+ | v8::WriteOptions::REPLACE_INVALID_UTF8,
+ ) as u32;
+ out_buf[0] = nchars as u32;
+ Ok(())
+}
+
+#[op(fast, slow = op_encoding_encode_into_fallback)]
fn op_encoding_encode_into(
input: Cow<'_, str>,
buffer: &mut [u8],
diff --git a/ops/attrs.rs b/ops/attrs.rs
index a76cfddf6..d0182fc69 100644
--- a/ops/attrs.rs
+++ b/ops/attrs.rs
@@ -1,44 +1,54 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use syn::parse::Parse;
use syn::parse::ParseStream;
-use syn::punctuated::Punctuated;
use syn::Error;
use syn::Ident;
use syn::Result;
use syn::Token;
-#[derive(Copy, Clone, Debug, Default)]
+#[derive(Clone, Debug, Default)]
pub struct Attributes {
pub is_unstable: bool,
pub is_v8: bool,
pub must_be_fast: bool,
pub deferred: bool,
pub is_wasm: bool,
+ pub relation: Option<Ident>,
}
impl Parse for Attributes {
fn parse(input: ParseStream) -> Result<Self> {
- let vars = Punctuated::<Ident, Token![,]>::parse_terminated(input)?;
-
- let vars: Vec<_> = vars.iter().map(Ident::to_string).collect();
- let vars: Vec<_> = vars.iter().map(String::as_str).collect();
- for var in vars.iter() {
- if !["unstable", "v8", "fast", "deferred", "wasm"].contains(var) {
- return Err(Error::new(
- input.span(),
- "invalid attribute, expected one of: unstable, v8, fast, deferred, wasm",
- ));
- }
+ let mut self_ = Self::default();
+ let mut fast = false;
+ while let Ok(v) = input.parse::<Ident>() {
+ match v.to_string().as_str() {
+ "unstable" => self_.is_unstable = true,
+ "v8" => self_.is_v8 = true,
+ "fast" => fast = true,
+ "deferred" => self_.deferred = true,
+ "wasm" => self_.is_wasm = true,
+ "slow" => {
+ if !fast {
+ return Err(Error::new(
+ input.span(),
+ "relational attributes can only be used with fast attribute",
+ ));
+ }
+ input.parse::<Token![=]>()?;
+ self_.relation = Some(input.parse()?);
+ }
+ _ => {
+ return Err(Error::new(
+ input.span(),
+ "invalid attribute, expected one of: unstable, v8, fast, deferred, wasm",
+ ));
+ }
+ };
+ let _ = input.parse::<Token![,]>();
}
- let is_wasm = vars.contains(&"wasm");
+ self_.must_be_fast = self_.is_wasm || fast;
- Ok(Self {
- is_unstable: vars.contains(&"unstable"),
- is_v8: vars.contains(&"v8"),
- deferred: vars.contains(&"deferred"),
- must_be_fast: is_wasm || vars.contains(&"fast"),
- is_wasm,
- })
+ Ok(self_)
}
}
diff --git a/ops/lib.rs b/ops/lib.rs
index 19667ab45..21812f605 100644
--- a/ops/lib.rs
+++ b/ops/lib.rs
@@ -111,24 +111,68 @@ impl Op {
active,
} = fast_call::generate(&core, &mut optimizer, &item);
+ let docline = format!("Use `{name}::decl()` to get an op-declaration");
+
+ let is_v8 = attrs.is_v8;
+ let is_unstable = attrs.is_unstable;
+
+ if let Some(v8_fn) = attrs.relation {
+ return quote! {
+ #[allow(non_camel_case_types)]
+ #[doc="Auto-generated by `deno_ops`, i.e: `#[op]`"]
+ #[doc=""]
+ #[doc=#docline]
+ #[doc="you can include in a `deno_core::Extension`."]
+ pub struct #name;
+
+ #[doc(hidden)]
+ impl #name {
+ pub fn name() -> &'static str {
+ stringify!(#name)
+ }
+
+ pub fn v8_fn_ptr #generics () -> #core::v8::FunctionCallback #where_clause {
+ use #core::v8::MapFnTo;
+ #v8_fn::v8_func::<#type_params>.map_fn_to()
+ }
+
+ pub fn decl #generics () -> #core::OpDecl #where_clause {
+ #core::OpDecl {
+ name: Self::name(),
+ v8_fn_ptr: Self::v8_fn_ptr::<#type_params>(),
+ enabled: true,
+ fast_fn: #decl,
+ is_async: #is_async,
+ is_unstable: #is_unstable,
+ is_v8: #is_v8,
+ argc: 0,
+ }
+ }
+
+ #[inline]
+ #[allow(clippy::too_many_arguments)]
+ #orig
+ }
+
+ #impl_and_fn
+ };
+ }
+
let has_fallible_fast_call = active && optimizer.returns_result;
let (v8_body, argc) = if is_async {
+ let deferred = attrs.deferred;
codegen_v8_async(
&core,
&item,
attrs,
item.sig.asyncness.is_some(),
- attrs.deferred,
+ deferred,
)
} else {
codegen_v8_sync(&core, &item, attrs, has_fallible_fast_call)
};
- let is_v8 = attrs.is_v8;
- let is_unstable = attrs.is_unstable;
-
- let docline = format!("Use `{name}::decl()` to get an op-declaration");
// Generate wrapper
quote! {
#[allow(non_camel_case_types)]