Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "feat(ops): Fast zero copy string arguments (#16777)" #17063

Merged
merged 1 commit into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Revert "feat(ops): Fast zero copy string arguments (#16777)"
This reverts commit 9b2b8df.
  • Loading branch information
bartlomieju committed Dec 15, 2022
commit ee9d78c32c73c4f29a07947b6e2dfb23c03734b8
5 changes: 5 additions & 0 deletions cli/bench/console.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
const count = 100000;

const start = Date.now();
for (let i = 0; i < count; i++) console.log("Hello World");
const elapsed = Date.now() - start;
const rate = Math.floor(count / (elapsed / 1000));
console.log(`time ${elapsed} ms rate ${rate}`);
5 changes: 3 additions & 2 deletions cli/bench/encode_into.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
let [total, count] = typeof Deno !== "undefined"
? Deno.args
: [process.argv[2], process.argv[3]];

total = total ? parseInt(total, 0) : 50;
count = count ? parseInt(count, 10) : 10000000;
count = count ? parseInt(count, 10) : 1000000;

function bench(fun) {
const start = Date.now();
for (let i = 0; i < count; i++) fun();
const elapsed = Date.now() - start;
const rate = Math.floor(count / (elapsed / 1000));
console.log(`time ${elapsed} ms rate ${rate}`);
if (--total) bench(fun);
if (--total) queueMicrotask(() => bench(fun));
}

const encoder = new TextEncoder();
Expand Down
21 changes: 0 additions & 21 deletions cli/bench/webstorage.js

This file was deleted.

4 changes: 2 additions & 2 deletions cli/tsc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -710,9 +710,9 @@ pub fn resolve_npm_package_reference_types(
}

#[op]
fn op_is_node_file(state: &mut OpState, path: &str) -> bool {
fn op_is_node_file(state: &mut OpState, path: String) -> bool {
let state = state.borrow::<State>();
match ModuleSpecifier::parse(path) {
match ModuleSpecifier::parse(&path) {
Ok(specifier) => state
.maybe_npm_resolver
.as_ref()
Expand Down
6 changes: 3 additions & 3 deletions core/ops_builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ pub fn op_metrics(state: &mut OpState) -> (OpMetrics, Vec<OpMetrics>) {

/// Builtin utility to print to stdout/stderr
#[op]
pub fn op_print(msg: &str, is_err: bool) -> Result<(), Error> {
pub fn op_print(msg: String, is_err: bool) -> Result<(), Error> {
if is_err {
stderr().write_all(msg.as_bytes())?;
stderr().flush().unwrap();
Expand Down Expand Up @@ -152,12 +152,12 @@ pub fn op_wasm_streaming_feed(
pub fn op_wasm_streaming_set_url(
state: &mut OpState,
rid: ResourceId,
url: &str,
url: String,
) -> Result<(), Error> {
let wasm_streaming =
state.resource_table.get::<WasmStreamingResource>(rid)?;

wasm_streaming.0.borrow_mut().set_url(url);
wasm_streaming.0.borrow_mut().set_url(&url);

Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion ext/node/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ fn op_require_proxy_path(filename: String) -> String {
}

#[op]
fn op_require_is_request_relative(request: &str) -> bool {
fn op_require_is_request_relative(request: String) -> bool {
if request.starts_with("./") || request.starts_with("../") || request == ".."
{
return true;
Expand Down
8 changes: 4 additions & 4 deletions ext/url/00_url.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@
function opUrlParse(href, maybeBase) {
let status;
if (maybeBase === undefined) {
status = ops.op_url_parse(href, componentsBuf);
status = ops.op_url_parse(href, componentsBuf.buffer);
} else {
status = ops.op_url_parse_with_base(
status = core.ops.op_url_parse_with_base(
href,
maybeBase,
componentsBuf,
componentsBuf.buffer,
);
}
return getSerialization(status, href);
Expand All @@ -71,7 +71,7 @@
if (status === 0) {
return href;
} else if (status === 1) {
return ops.op_url_get_serialization();
return core.ops.op_url_get_serialization();
} else {
throw new TypeError("Invalid URL");
}
Expand Down
19 changes: 10 additions & 9 deletions ext/url/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ pub fn init() -> Extension {
#[op]
pub fn op_url_parse_with_base(
state: &mut OpState,
href: &str,
base_href: &str,
buf: &mut [u32],
href: String,
base_href: String,
buf: &mut [u8],
) -> 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,
};
Expand All @@ -67,8 +67,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(fast)]
pub fn op_url_parse(state: &mut OpState, href: &str, buf: &mut [u32]) -> u32 {
#[op]
pub fn op_url_parse(state: &mut OpState, href: String, buf: &mut [u8]) -> u32 {
parse_url(state, href, None, buf)
}

Expand Down Expand Up @@ -99,14 +99,15 @@ pub fn op_url_parse(state: &mut OpState, href: &str, buf: &mut [u32]) -> u32 {
#[inline]
fn parse_url(
state: &mut OpState,
href: &str,
href: String,
base_href: Option<&Url>,
buf: &mut [u32],
buf: &mut [u8],
) -> 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;
Expand Down
4 changes: 2 additions & 2 deletions ext/web/blob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,9 @@ pub fn op_blob_create_object_url(
#[op]
pub fn op_blob_revoke_object_url(
state: &mut deno_core::OpState,
url: &str,
url: String,
) -> 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(())
Expand Down
4 changes: 2 additions & 2 deletions ext/web/compression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ impl Resource for CompressionResource {
#[op]
pub fn op_compression_new(
state: &mut OpState,
format: &str,
format: String,
is_decoder: bool,
) -> ResourceId {
let w = Vec::new();
let inner = match (format, is_decoder) {
let inner = match (format.as_str(), is_decoder) {
("deflate", true) => Inner::DeflateDecoder(ZlibDecoder::new(w)),
("deflate", false) => {
Inner::DeflateEncoder(ZlibEncoder::new(w, Compression::default()))
Expand Down
52 changes: 17 additions & 35 deletions ext/web/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ fn op_encoding_decode_single(
#[op]
fn op_encoding_new_decoder(
state: &mut OpState,
label: &str,
label: String,
fatal: bool,
ignore_bom: bool,
) -> Result<ResourceId, AnyError> {
Expand Down Expand Up @@ -352,43 +352,25 @@ impl Resource for TextDecoderResource {
}
}

#[op]
#[op(v8)]
fn op_encoding_encode_into(
input: Cow<'_, str>,
scope: &mut v8::HandleScope,
input: serde_v8::Value,
buffer: &mut [u8],
out_buf: &mut [u32],
) {
// 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;
) -> 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(v8)]
Expand Down
6 changes: 3 additions & 3 deletions ext/webstorage/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ pub fn op_webstorage_key(
#[op]
pub fn op_webstorage_set(
state: &mut OpState,
key: &str,
value: &str,
key: String,
value: String,
persistent: bool,
) -> Result<(), AnyError> {
let conn = get_webstorage(state, persistent)?;
Expand Down Expand Up @@ -184,7 +184,7 @@ pub fn op_webstorage_get(
#[op]
pub fn op_webstorage_remove(
state: &mut OpState,
key_name: &str,
key_name: String,
persistent: bool,
) -> Result<(), AnyError> {
let conn = get_webstorage(state, persistent)?;
Expand Down
5 changes: 1 addition & 4 deletions ops/fast_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,9 +403,7 @@ fn q_fast_ty(v: &FastValue) -> Quote {
FastValue::F64 => q!({ f64 }),
FastValue::Bool => q!({ bool }),
FastValue::V8Value => q!({ v8::Local<v8::Value> }),
FastValue::Uint8Array
| FastValue::Uint32Array
| FastValue::SeqOneByteString => unreachable!(),
FastValue::Uint8Array | FastValue::Uint32Array => unreachable!(),
}
}

Expand All @@ -423,7 +421,6 @@ fn q_fast_ty_variant(v: &FastValue) -> Quote {
FastValue::V8Value => q!({ V8Value }),
FastValue::Uint8Array => q!({ TypedArray(CType::Uint8) }),
FastValue::Uint32Array => q!({ TypedArray(CType::Uint32) }),
FastValue::SeqOneByteString => q!({ SeqOneByteString }),
}
}

Expand Down
34 changes: 3 additions & 31 deletions ops/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,31 +411,14 @@ fn codegen_arg(
return quote! { let #ident = (); };
}
// Fast path for `String`
if let Some(is_ref) = is_string(&**ty) {
let ref_block = if is_ref {
quote! { let #ident = #ident.as_ref(); }
} else {
quote! {}
};
if is_string(&**ty) {
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),
Err(_) => {
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>`
Expand Down Expand Up @@ -646,25 +629,14 @@ fn is_result(ty: impl ToTokens) -> bool {
}
}

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_string(ty: impl ToTokens) -> bool {
tokens(ty) == "String"
}

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,
Expand Down
Loading