From cb07d4f91408fb032e10cb01cfa4c5916ee23218 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Thu, 19 Aug 2021 14:05:48 +0200 Subject: [PATCH] feat: implement counter_lookup_callback (#756) --- src/isolate_create_params.rs | 17 +++++++++++- tests/test_api.rs | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/isolate_create_params.rs b/src/isolate_create_params.rs index c45525ee..c2408382 100644 --- a/src/isolate_create_params.rs +++ b/src/isolate_create_params.rs @@ -13,8 +13,13 @@ use std::convert::TryFrom; use std::iter::once; use std::mem::size_of; use std::mem::MaybeUninit; +use std::os::raw::c_char; use std::ptr::null; +/// Should return a pointer to memory that persists for the lifetime of the +/// isolate. +pub type CounterLookupCallback = extern "C" fn(name: *const c_char) -> *mut i32; + /// Initial configuration parameters for a new Isolate. #[must_use] #[derive(Debug, Default)] @@ -24,6 +29,16 @@ pub struct CreateParams { } impl CreateParams { + /// Enables the host application to provide a mechanism for recording + /// statistics counters. + pub fn counter_lookup_callback( + mut self, + callback: CounterLookupCallback, + ) -> Self { + self.raw.counter_lookup_callback = Some(callback); + self + } + /// Explicitly specify a startup snapshot blob. pub fn snapshot_blob(mut self, data: impl Allocated<[u8]>) -> Self { let data = Allocation::of(data); @@ -181,7 +196,7 @@ pub(crate) mod raw { pub code_event_handler: *const Opaque, // JitCodeEventHandler pub constraints: ResourceConstraints, pub snapshot_blob: *const StartupData, - pub counter_lookup_callback: *const Opaque, // CounterLookupCallback + pub counter_lookup_callback: Option, pub create_histogram_callback: *const Opaque, // CreateHistogramCallback pub add_histogram_sample_callback: *const Opaque, // AddHistogramSampleCallback pub array_buffer_allocator: *mut ArrayBufferAllocator, diff --git a/tests/test_api.rs b/tests/test_api.rs index 424189c7..01dba2a0 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -3,11 +3,16 @@ use lazy_static::lazy_static; use std::any::type_name; use std::cell::RefCell; use std::collections::hash_map::DefaultHasher; +use std::collections::HashMap; use std::convert::{Into, TryFrom, TryInto}; use std::ffi::c_void; +use std::ffi::CStr; use std::hash::Hash; +use std::os::raw::c_char; use std::ptr::NonNull; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; +use std::sync::Mutex; use rusty_v8 as v8; // TODO(piscisaureus): Ideally there would be no need to import this trait. @@ -5354,3 +5359,52 @@ fn external_strings() { assert!(!gradients.is_onebyte()); assert!(!gradients.contains_only_onebyte()); } + +#[test] +fn counter_lookup_callback() { + #[derive(Eq, PartialEq, Hash)] + struct Name(*const c_char); + struct Count(*mut i32); + + unsafe impl Send for Name {} + unsafe impl Send for Count {} + + lazy_static! { + static ref MAP: Arc>> = Arc::default(); + } + + // |name| points to a static zero-terminated C string. + extern "C" fn callback(name: *const c_char) -> *mut i32 { + MAP + .lock() + .unwrap() + .entry(Name(name)) + .or_insert_with(|| Count(Box::leak(Box::new(0)))) + .0 + } + + let _setup_guard = setup(); + let params = v8::CreateParams::default().counter_lookup_callback(callback); + let isolate = &mut v8::Isolate::new(params); + let scope = &mut v8::HandleScope::new(isolate); + let context = v8::Context::new(scope); + let scope = &mut v8::ContextScope::new(scope, context); + let _ = eval(scope, "console.log(42);").unwrap(); + + let count = MAP + .lock() + .unwrap() + .iter() + .find_map(|(name, count)| { + let name = unsafe { CStr::from_ptr(name.0) }; + // Note: counter names start with a "c:" prefix. + if "c:V8.TotalParseSize" == name.to_string_lossy() { + Some(unsafe { *count.0 }) + } else { + None + } + }) + .unwrap(); + + assert_ne!(count, 0); +}