diff --git a/bench_util/benches/op_baseline.rs b/bench_util/benches/op_baseline.rs index 317be79829..14d04f60d0 100644 --- a/bench_util/benches/op_baseline.rs +++ b/bench_util/benches/op_baseline.rs @@ -41,16 +41,6 @@ fn bench_op_async(b: &mut Bencher) { bench_js_async(b, r#"Deno.core.opAsync("op_pi_async");"#, setup); } -fn bench_is_proxy(b: &mut Bencher) { - bench_js_sync(b, r#"Deno.core.isProxy(42);"#, setup); -} - -benchmark_group!( - benches, - bench_op_pi_json, - bench_op_nop, - bench_op_async, - bench_is_proxy -); +benchmark_group!(benches, bench_op_pi_json, bench_op_nop, bench_op_async,); bench_or_profile!(benches); diff --git a/core/01_core.js b/core/01_core.js index e1ac275ebf..c7ced9b82e 100644 --- a/core/01_core.js +++ b/core/01_core.js @@ -306,7 +306,7 @@ deserialize: (buffer, options) => ops.op_deserialize(buffer, options), getPromiseDetails: (promise) => ops.op_get_promise_details(promise), getProxyDetails: (proxy) => ops.op_get_proxy_details(proxy), - isProxy: (value) => ops.op_is_proxy(value), + isProxy: (value) => ops.op_is_proxy.fast(value), memoryUsage: () => ops.op_memory_usage(), setWasmStreamingCallback: (fn) => ops.op_set_wasm_streaming_callback(fn), abortWasmStreaming: ( diff --git a/core/ops_builtin.rs b/core/ops_builtin.rs index 2e911e4150..bd19b74f6b 100644 --- a/core/ops_builtin.rs +++ b/core/ops_builtin.rs @@ -191,7 +191,7 @@ fn op_format_file_name(file_name: String) -> String { format_file_name(&file_name) } -#[op] +#[op(fast)] fn op_is_proxy(value: serde_v8::Value) -> bool { value.v8_value.is_proxy() } diff --git a/core/runtime.rs b/core/runtime.rs index 50c108f33f..366e834a26 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -3121,6 +3121,7 @@ assertEquals(1, notify_return_value); runtime.execute_script("", "").unwrap(); } + #[ignore] // TODO(@littledivy): Fast API ops when snapshot is not loaded. #[test] fn test_is_proxy() { let mut runtime = JsRuntime::new(RuntimeOptions::default()); diff --git a/ops/lib.rs b/ops/lib.rs index 0b0689356b..7d291d1da5 100644 --- a/ops/lib.rs +++ b/ops/lib.rs @@ -304,6 +304,7 @@ fn codegen_fast_impl( args, ret, use_recv, + v8_values, }) = fast_info { let inputs = &f @@ -311,17 +312,42 @@ fn codegen_fast_impl( .inputs .iter() .skip(if use_recv { 1 } else { 0 }) + .enumerate() + .map(|(idx, arg)| { + if v8_values.contains(&idx) { + let ident = match arg { + FnArg::Receiver(_) => unreachable!(), + FnArg::Typed(t) => match &*t.pat { + syn::Pat::Ident(i) => format_ident!("{}", i.ident), + _ => unreachable!(), + }, + }; + return quote! { #ident: #core::v8::Local < #core::v8::Value > }; + } + quote!(#arg) + }) .collect::>(); let input_idents = f .sig .inputs .iter() - .map(|a| match a { - FnArg::Receiver(_) => unreachable!(), - FnArg::Typed(t) => match &*t.pat { - syn::Pat::Ident(i) => format_ident!("{}", i.ident), - _ => unreachable!(), - }, + .enumerate() + .map(|(idx, a)| { + let ident = match a { + FnArg::Receiver(_) => unreachable!(), + FnArg::Typed(t) => match &*t.pat { + syn::Pat::Ident(i) => format_ident!("{}", i.ident), + _ => unreachable!(), + }, + }; + if v8_values.contains(&idx) { + return quote! { + #core::serde_v8::Value { + v8_value: #ident, + } + }; + } + quote! { #ident } }) .collect::>(); let generics = &f.sig.generics; @@ -453,6 +479,7 @@ struct FastApiSyn { args: TokenStream2, ret: TokenStream2, use_recv: bool, + v8_values: Vec, } fn can_be_fast_api(core: &TokenStream2, f: &syn::ItemFn) -> Option { @@ -466,6 +493,7 @@ fn can_be_fast_api(core: &TokenStream2, f: &syn::ItemFn) -> Option { }; let mut use_recv = false; + let mut v8_values = Vec::new(); let mut args = vec![quote! { #core::v8::fast_api::Type::V8Value }]; for (pos, input) in inputs.iter().enumerate() { if pos == 0 && is_mut_ref_opstate(input) { @@ -478,16 +506,21 @@ fn can_be_fast_api(core: &TokenStream2, f: &syn::ItemFn) -> Option { _ => unreachable!(), }; - match is_fast_scalar(core, ty, false) { - None => match is_fast_arg_sequence(core, ty) { + if let Some(arg) = is_fast_v8_value(core, ty) { + args.push(arg); + v8_values.push(pos); + } else { + match is_fast_scalar(core, ty, false) { + None => match is_fast_arg_sequence(core, ty) { + Some(arg) => { + args.push(arg); + } + // early return, this function cannot be a fast call. + None => return None, + }, Some(arg) => { args.push(arg); } - // early return, this function cannot be a fast call. - None => return None, - }, - Some(arg) => { - args.push(arg); } } } @@ -501,6 +534,7 @@ fn can_be_fast_api(core: &TokenStream2, f: &syn::ItemFn) -> Option { args: args.parse().unwrap(), ret, use_recv, + v8_values, }) } @@ -523,6 +557,16 @@ fn is_fast_arg_sequence( None } +fn is_fast_v8_value( + core: &TokenStream2, + arg: impl ToTokens, +) -> Option { + if tokens(&arg).contains("serde_v8 :: Value") { + return Some(quote! { #core::v8::fast_api::Type::V8Value }); + } + None +} + fn is_local_array(arg: impl ToTokens) -> bool { static RE: Lazy = Lazy::new(|| Regex::new(r"^v8::Local$").unwrap()); @@ -558,6 +602,7 @@ fn is_fast_scalar( "i32" => Some(quote! { #core::v8::fast_api::#cty::Int32 }), "f32" => Some(quote! { #core::v8::fast_api::#cty::Float32 }), "f64" => Some(quote! { #core::v8::fast_api::#cty::Float64 }), + "bool" => Some(quote! { #core::v8::fast_api::#cty::Bool }), _ => None, } }