Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
Loading