mirror of
https://github.com/denoland/deno.git
synced 2025-08-04 10:59:13 +00:00
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
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
}
```
This commit is contained in:
parent
075854e516
commit
9b2b8df927
34 changed files with 804 additions and 97 deletions
34
ops/lib.rs
34
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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue