Skip to content
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
5 changes: 5 additions & 0 deletions src/binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,11 @@ bool v8__Isolate__GetHeapSpaceStatistics(
return isolate->GetHeapSpaceStatistics(space_statistics, index);
}

bool v8__Isolate__GetHeapCodeAndMetadataStatistics(v8::Isolate* isolate,
v8::HeapCodeStatistics* s) {
return isolate->GetHeapCodeAndMetadataStatistics(s);
}

void v8__Isolate__RemoveNearHeapLimitCallback(
v8::Isolate* isolate, v8::NearHeapLimitCallback callback,
size_t heap_limit) {
Expand Down
1 change: 1 addition & 0 deletions src/binding.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ using v8__String__WriteFlags = v8::String::WriteFlags;
using v8__ModuleImportPhase = v8::ModuleImportPhase;
using v8__HeapStatistics = v8::HeapStatistics;
using v8__HeapSpaceStatistics = v8::HeapSpaceStatistics;
using v8__HeapCodeStatistics = v8::HeapCodeStatistics;
using v8__GCType = v8::GCType;
using v8__GCCallbackFlags = v8::GCCallbackFlags;
using v8__Intercepted = v8::Intercepted;
Expand Down
45 changes: 45 additions & 0 deletions src/isolate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::StartupData;
use crate::String;
use crate::V8::get_current_platform;
use crate::Value;
use crate::binding::v8__HeapCodeStatistics;
use crate::binding::v8__HeapSpaceStatistics;
use crate::binding::v8__HeapStatistics;
use crate::binding::v8__Isolate__UseCounterFeature;
Expand Down Expand Up @@ -666,6 +667,10 @@ unsafe extern "C" {
space_statistics: *mut v8__HeapSpaceStatistics,
index: size_t,
) -> bool;
fn v8__Isolate__GetHeapCodeAndMetadataStatistics(
isolate: *mut RealIsolate,
code_statistics: *mut v8__HeapCodeStatistics,
) -> bool;
fn v8__Isolate__AddNearHeapLimitCallback(
isolate: *mut RealIsolate,
callback: NearHeapLimitCallback,
Expand Down Expand Up @@ -1269,6 +1274,26 @@ impl Isolate {
Some(HeapSpaceStatistics(inner))
}

/// Get code and metadata statistics for the heap.
///
/// \returns true on success.
#[inline(always)]
pub fn get_heap_code_and_metadata_statistics(
&mut self,
) -> Option<HeapCodeStatistics> {
let inner = unsafe {
let mut s = MaybeUninit::zeroed();
if !v8__Isolate__GetHeapCodeAndMetadataStatistics(
self.as_real_ptr(),
s.as_mut_ptr(),
) {
return None;
}
s.assume_init()
};
Some(HeapCodeStatistics(inner))
}

/// Tells V8 to capture current stack trace when uncaught exception occurs
/// and report it to the message listeners. The option is off by default.
#[inline(always)]
Expand Down Expand Up @@ -2234,6 +2259,26 @@ impl HeapSpaceStatistics {
}
}

pub struct HeapCodeStatistics(v8__HeapCodeStatistics);

impl HeapCodeStatistics {
pub fn code_and_metadata_size(&self) -> usize {
self.0.code_and_metadata_size_
}

pub fn bytecode_and_metadata_size(&self) -> usize {
self.0.bytecode_and_metadata_size_
}

pub fn external_script_source_size(&self) -> usize {
self.0.external_script_source_size_
}

pub fn cpu_profiler_metadata_size(&self) -> usize {
self.0.cpu_profiler_metadata_size_
}
}

impl<'s, F> MapFnFrom<F> for PrepareStackTraceCallback<'s>
where
F: UnitType
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ pub use handle::SealedLocal;
pub use handle::TracedReference;
pub use handle::Weak;
pub use isolate::GarbageCollectionType;
pub use isolate::HeapCodeStatistics;
pub use isolate::HeapSpaceStatistics;
pub use isolate::HeapStatistics;
pub use isolate::HostCreateShadowRealmContextCallback;
Expand Down
36 changes: 36 additions & 0 deletions tests/test_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7792,6 +7792,42 @@ fn heap_statistics() {
assert_ne!(s.number_of_native_contexts(), 0);
}

#[test]
fn heap_code_statistics() {
let _setup_guard = setup::parallel_test();

let isolate = &mut v8::Isolate::new(Default::default());

// Before running any code, statistics should still be available.
let s = isolate
.get_heap_code_and_metadata_statistics()
.expect("get_heap_code_and_metadata_statistics should succeed");

// Before running any code, code_and_metadata_size may or may not be > 0
// depending on the platform and V8 version.
// external_script_source_size and cpu_profiler_metadata_size start at 0.
assert_eq!(s.external_script_source_size(), 0);
assert_eq!(s.cpu_profiler_metadata_size(), 0);

// Run some JS to generate bytecode.
{
v8::scope!(let scope, isolate);
let context = v8::Context::new(scope, Default::default());
let scope = &mut v8::ContextScope::new(scope, context);
eval(scope, "function foo() { return 1 + 2; } foo();").unwrap();
}

let s2 = isolate
.get_heap_code_and_metadata_statistics()
.expect("get_heap_code_and_metadata_statistics should succeed");

// After compiling code, bytecode_and_metadata_size should increase.
assert!(s2.bytecode_and_metadata_size() > 0);
// code_and_metadata_size tracks JIT-compiled code, which may be 0 if V8
// only uses the interpreter for simple scripts.
assert!(s2.code_and_metadata_size() >= s.code_and_metadata_size());
}

#[test]
fn low_memory_notification() {
let _setup_guard = setup::parallel_test();
Expand Down