diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2023-03-03 19:04:10 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-03 19:04:10 +0530 |
commit | 38555a6a0fe9a7235776afe0ebfb2a24dc518391 (patch) | |
tree | ef9506c500451e5f2ef4ae5b70eda85c7147a25e /ext | |
parent | 64503fabd81e38c58d44d23ae94f5b87a384b86e (diff) |
feat(ops): reland fast zero copy string arguments (#17996)
Reland https://github.com/denoland/deno/pull/16777
The codegen is disabled in async ops and when fallback to slow call is
possible (return type is a Result) to avoid hitting this V8 bug:
https://github.com/denoland/deno/issues/17159
Diffstat (limited to 'ext')
-rw-r--r-- | ext/url/00_url.js | 6 | ||||
-rw-r--r-- | ext/url/lib.rs | 19 | ||||
-rw-r--r-- | ext/web/blob.rs | 6 | ||||
-rw-r--r-- | ext/web/compression.rs | 4 | ||||
-rw-r--r-- | ext/web/lib.rs | 52 | ||||
-rw-r--r-- | ext/webstorage/lib.rs | 6 |
6 files changed, 55 insertions, 38 deletions
diff --git a/ext/url/00_url.js b/ext/url/00_url.js index da5849d43..3c3f2b1d0 100644 --- a/ext/url/00_url.js +++ b/ext/url/00_url.js @@ -46,7 +46,7 @@ function opUrlReparse(href, setter, value) { href, setter, value, - componentsBuf.buffer, + componentsBuf, ); return getSerialization(status, href); } @@ -54,12 +54,12 @@ function opUrlReparse(href, setter, value) { function opUrlParse(href, maybeBase) { let status; if (maybeBase === undefined) { - status = ops.op_url_parse(href, componentsBuf.buffer); + status = ops.op_url_parse(href, componentsBuf); } else { status = ops.op_url_parse_with_base( href, maybeBase, - componentsBuf.buffer, + componentsBuf, ); } return getSerialization(status, href, maybeBase); diff --git a/ext/url/lib.rs b/ext/url/lib.rs index 087ccbfe7..4f15cb924 100644 --- a/ext/url/lib.rs +++ b/ext/url/lib.rs @@ -38,11 +38,11 @@ pub fn init() -> Extension { #[op] pub fn op_url_parse_with_base( state: &mut OpState, - href: String, - base_href: String, - buf: &mut [u8], + href: &str, + base_href: &str, + buf: &mut [u32], ) -> u32 { - let base_url = match Url::parse(&base_href) { + let base_url = match Url::parse(base_href) { Ok(url) => url, Err(_) => return ParseStatus::Err as u32, }; @@ -64,8 +64,8 @@ pub fn op_url_get_serialization(state: &mut OpState) -> String { } /// Parse `href` without a `base_url`. Fills the out `buf` with URL components. -#[op] -pub fn op_url_parse(state: &mut OpState, href: String, buf: &mut [u8]) -> u32 { +#[op(fast)] +pub fn op_url_parse(state: &mut OpState, href: &str, buf: &mut [u32]) -> u32 { parse_url(state, href, None, buf) } @@ -96,15 +96,14 @@ pub fn op_url_parse(state: &mut OpState, href: String, buf: &mut [u8]) -> u32 { #[inline] fn parse_url( state: &mut OpState, - href: String, + href: &str, base_href: Option<&Url>, - buf: &mut [u8], + buf: &mut [u32], ) -> u32 { - match Url::options().base_url(base_href).parse(&href) { + match Url::options().base_url(base_href).parse(href) { Ok(url) => { let inner_url = quirks::internal_components(&url); - let buf: &mut [u32] = as_u32_slice(buf); buf[0] = inner_url.scheme_end; buf[1] = inner_url.username_end; buf[2] = inner_url.host_start; diff --git a/ext/web/blob.rs b/ext/web/blob.rs index 44c8f0ace..7796c18af 100644 --- a/ext/web/blob.rs +++ b/ext/web/blob.rs @@ -248,10 +248,10 @@ pub fn op_blob_create_object_url( #[op] pub fn op_blob_revoke_object_url( - state: &mut OpState, - url: String, + state: &mut deno_core::OpState, + url: &str, ) -> Result<(), AnyError> { - let url = Url::parse(&url)?; + let url = Url::parse(url)?; let blob_store = state.borrow::<BlobStore>(); blob_store.remove_object_url(&url); Ok(()) diff --git a/ext/web/compression.rs b/ext/web/compression.rs index ee129fe5a..11ea9196a 100644 --- a/ext/web/compression.rs +++ b/ext/web/compression.rs @@ -41,11 +41,11 @@ impl Resource for CompressionResource { #[op] pub fn op_compression_new( state: &mut OpState, - format: String, + format: &str, is_decoder: bool, ) -> ResourceId { let w = Vec::new(); - let inner = match (format.as_str(), is_decoder) { + let inner = match (format, is_decoder) { ("deflate", true) => Inner::DeflateDecoder(ZlibDecoder::new(w)), ("deflate", false) => { Inner::DeflateEncoder(ZlibEncoder::new(w, Compression::default())) diff --git a/ext/web/lib.rs b/ext/web/lib.rs index c1d2c6703..2f59636fe 100644 --- a/ext/web/lib.rs +++ b/ext/web/lib.rs @@ -269,7 +269,7 @@ fn op_encoding_decode_single( #[op] fn op_encoding_new_decoder( state: &mut OpState, - label: String, + label: &str, fatal: bool, ignore_bom: bool, ) -> Result<ResourceId, AnyError> { @@ -350,25 +350,43 @@ impl Resource for TextDecoderResource { } } -#[op(v8)] +#[op] fn op_encoding_encode_into( - scope: &mut v8::HandleScope, - input: serde_v8::Value, + input: Cow<'_, str>, 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(()) +) { + // Since `input` is already UTF-8, we can simply find the last UTF-8 code + // point boundary from input that fits in `buffer`, and copy the bytes up to + // that point. + let boundary = if buffer.len() >= input.len() { + input.len() + } else { + let mut boundary = buffer.len(); + + // The maximum length of a UTF-8 code point is 4 bytes. + for _ in 0..4 { + if input.is_char_boundary(boundary) { + break; + } + debug_assert!(boundary > 0); + boundary -= 1; + } + + debug_assert!(input.is_char_boundary(boundary)); + boundary + }; + + buffer[..boundary].copy_from_slice(input[..boundary].as_bytes()); + + // The `read` output parameter is measured in UTF-16 code units. + out_buf[0] = match input { + // Borrowed Cow strings are zero-copy views into the V8 heap. + // Thus, they are guarantee to be SeqOneByteString. + Cow::Borrowed(v) => v[..boundary].len() as u32, + Cow::Owned(v) => v[..boundary].encode_utf16().count() as u32, + }; + out_buf[1] = boundary as u32; } #[op(v8)] diff --git a/ext/webstorage/lib.rs b/ext/webstorage/lib.rs index 852ce229e..5e534a122 100644 --- a/ext/webstorage/lib.rs +++ b/ext/webstorage/lib.rs @@ -138,8 +138,8 @@ pub fn op_webstorage_key( #[op] pub fn op_webstorage_set( state: &mut OpState, - key: String, - value: String, + key: &str, + value: &str, persistent: bool, ) -> Result<(), AnyError> { let conn = get_webstorage(state, persistent)?; @@ -183,7 +183,7 @@ pub fn op_webstorage_get( #[op] pub fn op_webstorage_remove( state: &mut OpState, - key_name: String, + key_name: &str, persistent: bool, ) -> Result<(), AnyError> { let conn = get_webstorage(state, persistent)?; |