summaryrefslogtreecommitdiff
path: root/ops/lib.rs
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2022-12-01 21:29:15 -0800
committerGitHub <noreply@github.com>2022-12-02 05:29:15 +0000
commit9b2b8df927ac23cfa99016a684179f2a3198ba2e (patch)
tree1d13b575bc7c4f7279b2ff3fdde175a7522d643a /ops/lib.rs
parent075854e5162c3d9f4fd7061d19acbe2c5855536e (diff)
feat(ops): Fast zero copy string arguments (#16777)
Uses SeqOneByteString optimization to do zero-copy `&str` arguments in fast calls. - [x] Depends on https://github.com/denoland/rusty_v8/pull/1129 - [x] Depends on https://chromium-review.googlesource.com/c/v8/v8/+/4036884 - [x] Disable in async ops - [x] Make it work with owned `String` with an extra alloc in fast path. - [x] Support `Cow<'_, str>`. Owned for slow case, Borrowed for fast case ```rust #[op] fn op_string_len(s: &str) -> u32 { str.len() as u32 } ```
Diffstat (limited to 'ops/lib.rs')
-rw-r--r--ops/lib.rs34
1 files changed, 31 insertions, 3 deletions
diff --git a/ops/lib.rs b/ops/lib.rs
index 598350167..26fcb2a78 100644
--- a/ops/lib.rs
+++ b/ops/lib.rs
@@ -400,7 +400,12 @@ fn codegen_arg(
return quote! { let #ident = (); };
}
// Fast path for `String`
- if is_string(&**ty) {
+ if let Some(is_ref) = is_string(&**ty) {
+ let ref_block = if is_ref {
+ quote! { let #ident = #ident.as_ref(); }
+ } else {
+ quote! {}
+ };
return quote! {
let #ident = match #core::v8::Local::<#core::v8::String>::try_from(args.get(#idx as i32)) {
Ok(v8_string) => #core::serde_v8::to_utf8(v8_string, scope),
@@ -408,6 +413,18 @@ fn codegen_arg(
return #core::_ops::throw_type_error(scope, format!("Expected string at position {}", #idx));
}
};
+ #ref_block
+ };
+ }
+ // Fast path for `Cow<'_, str>`
+ if is_cow_str(&**ty) {
+ return quote! {
+ let #ident = match #core::v8::Local::<#core::v8::String>::try_from(args.get(#idx as i32)) {
+ Ok(v8_string) => ::std::borrow::Cow::Owned(#core::serde_v8::to_utf8(v8_string, scope)),
+ Err(_) => {
+ return #core::_ops::throw_type_error(scope, format!("Expected string at position {}", #idx));
+ }
+ };
};
}
// Fast path for `Option<String>`
@@ -618,14 +635,25 @@ fn is_result(ty: impl ToTokens) -> bool {
}
}
-fn is_string(ty: impl ToTokens) -> bool {
- tokens(ty) == "String"
+fn is_string(ty: impl ToTokens) -> Option<bool> {
+ let toks = tokens(ty);
+ if toks == "String" {
+ return Some(false);
+ }
+ if toks == "& str" {
+ return Some(true);
+ }
+ None
}
fn is_option_string(ty: impl ToTokens) -> bool {
tokens(ty) == "Option < String >"
}
+fn is_cow_str(ty: impl ToTokens) -> bool {
+ tokens(&ty).starts_with("Cow <") && tokens(&ty).ends_with("str >")
+}
+
enum SliceType {
U8,
U8Mut,