From 15ca122d106a5d05fe5cdbbaebb024143743e199 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Fri, 18 Oct 2024 15:02:35 +0200 Subject: [PATCH] wip --- ops/op2/dispatch_fast.rs | 11 +++++++--- test.ts | 31 ++++++++++++++++++++++++++++ testing/checkin/runner/extensions.rs | 1 + testing/checkin/runner/ops.rs | 13 ++++++++++++ testing/checkin/runtime/error.ts | 3 +++ 5 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 test.ts diff --git a/ops/op2/dispatch_fast.rs b/ops/op2/dispatch_fast.rs index 26e8d575e..a9af67707 100644 --- a/ops/op2/dispatch_fast.rs +++ b/ops/op2/dispatch_fast.rs @@ -716,7 +716,10 @@ fn map_v8_fastcall_arg_to_arg( } } Arg::String(Strings::String) => { - quote!(let #arg_ident = deno_core::_ops::to_string_ptr(unsafe { &mut *#arg_ident });) + *needs_scope = true; + quote!( + let #arg_ident = deno_core::_ops::to_string(&mut #scope, &*#arg_ident); + ) } Arg::String(Strings::CowStr) => { quote! { @@ -877,12 +880,14 @@ fn map_arg_to_v8_fastcall_type( // Ref strings that are one byte internally may be passed as a SeqOneByteString, // which gives us a FastApiOneByteString. Arg::String(Strings::RefStr) => V8FastCallType::SeqOneByteString, - // Owned strings can be fast, but we'll have to copy them. - Arg::String(Strings::String) => V8FastCallType::SeqOneByteString, // Cow strings can be fast, but may require copying Arg::String(Strings::CowStr) => V8FastCallType::SeqOneByteString, // Cow byte strings can be fast and don't require copying Arg::String(Strings::CowByte) => V8FastCallType::SeqOneByteString, + // Strings are passed to fast calls as V8String, and are then extracted + // using v8::ValueView. For one byte ASCII strings we can avoid copying. For + // other strings we always have to copy / rewrite. + Arg::String(Strings::String) => V8FastCallType::V8Value, Arg::External(..) => V8FastCallType::Pointer, Arg::CppGcResource(..) => V8FastCallType::V8Value, Arg::OptionCppGcResource(..) => V8FastCallType::V8Value, diff --git a/test.ts b/test.ts new file mode 100644 index 000000000..558784136 --- /dev/null +++ b/test.ts @@ -0,0 +1,31 @@ + +const hexSliceLookupTable = (function () { + const alphabet = "0123456789abcdef"; + const table = new Array(256); + for (let i = 0; i < 16; ++i) { + const i16 = i * 16; + for (let j = 0; j < 16; ++j) { + table[i16 + j] = alphabet[i] + alphabet[j]; + } + } + return table; +})(); + +function generateId(size: number) { + let out = ""; + for (let i = 0; i < size / 4; i += 1) { + const r32 = (Math.random() * 2 ** 32) >>> 0; + out += hexSliceLookupTable[(r32 >> 24) & 0xff]; + out += hexSliceLookupTable[(r32 >> 16) & 0xff]; + out += hexSliceLookupTable[(r32 >> 8) & 0xff]; + out += hexSliceLookupTable[r32 & 0xff]; + } + return out; +} + + +const start = Date.now(); +while (start + 1000 > Date.now()) { + const id = generateId(16); + op_fast(id); +} diff --git a/testing/checkin/runner/extensions.rs b/testing/checkin/runner/extensions.rs index bdabaa56d..5d4ef8d34 100644 --- a/testing/checkin/runner/extensions.rs +++ b/testing/checkin/runner/extensions.rs @@ -23,6 +23,7 @@ deno_core::extension!( ops::op_stats_dump, ops::op_stats_delete, ops::op_nop_generic

, + ops::op_fast, ops_io::op_pipe_create, ops_io::op_file_open, ops_async::op_task_submit, diff --git a/testing/checkin/runner/ops.rs b/testing/checkin/runner/ops.rs index 24eb3fe4c..32ea8f3ea 100644 --- a/testing/checkin/runner/ops.rs +++ b/testing/checkin/runner/ops.rs @@ -1,3 +1,4 @@ +use core::str; // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use std::cell::RefCell; use std::rc::Rc; @@ -8,6 +9,7 @@ use deno_core::stats::RuntimeActivitySnapshot; use deno_core::stats::RuntimeActivityStats; use deno_core::stats::RuntimeActivityStatsFactory; use deno_core::stats::RuntimeActivityStatsFilter; +use deno_core::v8; use deno_core::GarbageCollected; use deno_core::OpDecl; use deno_core::OpState; @@ -21,6 +23,17 @@ pub fn op_log_debug(#[string] s: &str) { println!("{s}"); } +#[op2(fast)] +pub fn op_fast(scope: &mut v8::HandleScope<'_>, s: v8::Local<'_, v8::Value>) { + let x = v8::ValueView::new(scope, s.cast()); + match x.data() { + v8::ValueViewData::OneByte(s) => { + let str = str::from_utf8(s).unwrap(); + } + v8::ValueViewData::TwoByte(_) => {} + }; +} + #[op2(fast)] pub fn op_log_info(#[state] output: &mut Output, #[string] s: String) { println!("{s}"); diff --git a/testing/checkin/runtime/error.ts b/testing/checkin/runtime/error.ts index 4dca78fe8..9d076e584 100644 --- a/testing/checkin/runtime/error.ts +++ b/testing/checkin/runtime/error.ts @@ -6,8 +6,11 @@ import { op_error_context_async, op_error_context_sync, op_error_custom_sync, + op_fast, } from "ext:core/ops"; +globalThis.op_fast = op_fast; + export async function asyncThrow(kind: "lazy" | "eager" | "deferred") { const op = { lazy: op_async_throw_error_lazy,