mirror of
https://github.com/denoland/rusty_v8.git
synced 2025-03-08 20:16:41 -05:00
feat: Add v8::Isolate::request_garbage_collection_for_testing (#1148)
This commit is contained in:
parent
0f43fc0b58
commit
3e8a572ceb
4 changed files with 75 additions and 38 deletions
|
@ -317,6 +317,11 @@ bool v8__Isolate__HasPendingBackgroundTasks(v8::Isolate* isolate) {
|
|||
return isolate->HasPendingBackgroundTasks();
|
||||
}
|
||||
|
||||
void v8__Isolate__RequestGarbageCollectionForTesting(
|
||||
v8::Isolate* isolate, v8::Isolate::GarbageCollectionType type) {
|
||||
isolate->RequestGarbageCollectionForTesting(type);
|
||||
}
|
||||
|
||||
void v8__Isolate__CreateParams__CONSTRUCT(
|
||||
uninit_t<v8::Isolate::CreateParams>* buf) {
|
||||
construct_in_place<v8::Isolate::CreateParams>(buf);
|
||||
|
|
|
@ -107,6 +107,15 @@ pub enum PromiseHookType {
|
|||
After,
|
||||
}
|
||||
|
||||
/// Types of garbage collections that can be requested via
|
||||
/// [`Isolate::request_garbage_collection_for_testing`].
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(C)]
|
||||
pub enum GarbageCollectionType {
|
||||
Full,
|
||||
Minor,
|
||||
}
|
||||
|
||||
pub type MessageCallback = extern "C" fn(Local<Message>, Local<Value>);
|
||||
|
||||
pub type PromiseHook =
|
||||
|
@ -471,6 +480,10 @@ extern "C" {
|
|||
callback: extern "C" fn(*const FunctionCallbackInfo),
|
||||
);
|
||||
fn v8__Isolate__HasPendingBackgroundTasks(isolate: *const Isolate) -> bool;
|
||||
fn v8__Isolate__RequestGarbageCollectionForTesting(
|
||||
isolate: *mut Isolate,
|
||||
r#type: usize,
|
||||
);
|
||||
|
||||
fn v8__HeapProfiler__TakeHeapSnapshot(
|
||||
isolate: *mut Isolate,
|
||||
|
@ -1140,6 +1153,31 @@ impl Isolate {
|
|||
unsafe { v8__Isolate__HasPendingBackgroundTasks(self) }
|
||||
}
|
||||
|
||||
/// Request garbage collection with a specific embedderstack state in this
|
||||
/// Isolate. It is only valid to call this function if --expose_gc was
|
||||
/// specified.
|
||||
///
|
||||
/// This should only be used for testing purposes and not to enforce a garbage
|
||||
/// collection schedule. It has strong negative impact on the garbage
|
||||
/// collection performance. Use IdleNotificationDeadline() or
|
||||
/// LowMemoryNotification() instead to influence the garbage collection
|
||||
/// schedule.
|
||||
#[inline(always)]
|
||||
pub fn request_garbage_collection_for_testing(
|
||||
&mut self,
|
||||
r#type: GarbageCollectionType,
|
||||
) {
|
||||
unsafe {
|
||||
v8__Isolate__RequestGarbageCollectionForTesting(
|
||||
self,
|
||||
match r#type {
|
||||
GarbageCollectionType::Full => 0,
|
||||
GarbageCollectionType::Minor => 1,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn clear_scope_and_annex(&mut self) {
|
||||
// Drop the scope stack.
|
||||
ScopeData::drop_root(self);
|
||||
|
|
|
@ -97,6 +97,7 @@ pub use handle::Global;
|
|||
pub use handle::Handle;
|
||||
pub use handle::Local;
|
||||
pub use handle::Weak;
|
||||
pub use isolate::GarbageCollectionType;
|
||||
pub use isolate::HeapStatistics;
|
||||
pub use isolate::HostCreateShadowRealmContextCallback;
|
||||
pub use isolate::HostImportModuleDynamicallyCallback;
|
||||
|
|
|
@ -161,8 +161,7 @@ fn global_from_into_raw() {
|
|||
(raw, weak)
|
||||
};
|
||||
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
assert!(!weak.is_empty());
|
||||
|
||||
{
|
||||
|
@ -172,8 +171,7 @@ fn global_from_into_raw() {
|
|||
assert_eq!(global_from_weak, reconstructed);
|
||||
}
|
||||
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
assert!(weak.is_empty());
|
||||
}
|
||||
|
||||
|
@ -6379,23 +6377,24 @@ fn clear_kept_objects() {
|
|||
let context = v8::Context::new(scope);
|
||||
let scope = &mut v8::ContextScope::new(scope, context);
|
||||
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
let step1 = r#"
|
||||
var weakrefs = [];
|
||||
for (let i = 0; i < 424242; i++) weakrefs.push(new WeakRef({ i }));
|
||||
gc();
|
||||
"#;
|
||||
let step2 = r#"
|
||||
if (weakrefs.some(w => !w.deref())) throw "fail";
|
||||
"#;
|
||||
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
let step2 = r#"
|
||||
gc();
|
||||
let step3 = r#"
|
||||
if (weakrefs.every(w => w.deref())) throw "fail";
|
||||
"#;
|
||||
|
||||
eval(scope, step1).unwrap();
|
||||
scope.clear_kept_objects();
|
||||
scope.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
eval(scope, step2).unwrap();
|
||||
scope.clear_kept_objects();
|
||||
scope.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
eval(scope, step3).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -7420,8 +7419,7 @@ fn weak_handle() {
|
|||
|
||||
let scope = &mut v8::HandleScope::new(scope);
|
||||
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
|
||||
assert!(weak.is_empty());
|
||||
assert_eq!(weak.to_local(scope), None);
|
||||
|
@ -7450,8 +7448,8 @@ fn finalizers() {
|
|||
}
|
||||
|
||||
let scope = &mut v8::HandleScope::new(scope);
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope
|
||||
.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
}
|
||||
|
||||
let finalizer_called = Rc::new(Cell::new(false));
|
||||
|
@ -7486,8 +7484,7 @@ fn finalizers() {
|
|||
};
|
||||
|
||||
let scope = &mut v8::HandleScope::new(scope);
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
assert!(weak.is_empty());
|
||||
assert!(finalizer_called.get());
|
||||
}
|
||||
|
@ -7521,8 +7518,8 @@ fn guaranteed_finalizers() {
|
|||
}
|
||||
|
||||
let scope = &mut v8::HandleScope::new(scope);
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope
|
||||
.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
}
|
||||
|
||||
let finalizer_called = Rc::new(Cell::new(false));
|
||||
|
@ -7557,8 +7554,7 @@ fn guaranteed_finalizers() {
|
|||
};
|
||||
|
||||
let scope = &mut v8::HandleScope::new(scope);
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
assert!(weak.is_empty());
|
||||
assert!(finalizer_called.get());
|
||||
}
|
||||
|
@ -7583,8 +7579,7 @@ fn weak_from_global() {
|
|||
assert_eq!(weak.to_global(scope).unwrap(), global);
|
||||
|
||||
drop(global);
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
assert!(weak.is_empty());
|
||||
}
|
||||
|
||||
|
@ -7633,8 +7628,8 @@ fn weak_from_into_raw() {
|
|||
assert!(!finalizer_called.get());
|
||||
(weak1, weak2)
|
||||
};
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope
|
||||
.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
assert!(weak1.is_empty());
|
||||
assert!(weak2.is_empty());
|
||||
assert!(finalizer_called.get());
|
||||
|
@ -7648,8 +7643,8 @@ fn weak_from_into_raw() {
|
|||
v8::Weak::new(scope, local)
|
||||
};
|
||||
assert!(!weak.is_empty());
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope
|
||||
.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
assert!(weak.is_empty());
|
||||
assert_eq!(weak.into_raw(), None);
|
||||
}
|
||||
|
@ -7680,8 +7675,8 @@ fn weak_from_into_raw() {
|
|||
let raw2 = weak_with_finalizer.into_raw();
|
||||
assert!(raw1.is_some());
|
||||
assert!(raw2.is_some());
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope
|
||||
.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
assert!(finalizer_called.get());
|
||||
let weak1 = unsafe { v8::Weak::from_raw(scope, raw1) };
|
||||
let weak2 = unsafe { v8::Weak::from_raw(scope, raw2) };
|
||||
|
@ -7695,11 +7690,10 @@ fn weak_from_into_raw() {
|
|||
let local = v8::Object::new(scope);
|
||||
v8::Weak::new(scope, local).into_raw();
|
||||
v8::Weak::with_finalizer(scope, local, Box::new(|_| {})).into_raw();
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope
|
||||
.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
}
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -7739,8 +7733,7 @@ fn drop_weak_from_raw_in_finalizer() {
|
|||
}
|
||||
|
||||
assert!(!finalized.get());
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
assert!(finalized.get());
|
||||
}
|
||||
|
||||
|
@ -8747,8 +8740,8 @@ fn gc_callbacks() {
|
|||
let context = v8::Context::new(scope);
|
||||
let scope = &mut v8::ContextScope::new(scope, context);
|
||||
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope
|
||||
.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
assert_eq!(state.mark_sweep_calls, 1);
|
||||
assert_eq!(state.incremental_marking_calls, 0);
|
||||
}
|
||||
|
@ -8760,8 +8753,8 @@ fn gc_callbacks() {
|
|||
let context = v8::Context::new(scope);
|
||||
let scope = &mut v8::ContextScope::new(scope, context);
|
||||
|
||||
// TODO use binding to Isolate::RequestGarbageCollectionForTesting instead of gc()
|
||||
eval(scope, "gc()").unwrap();
|
||||
scope
|
||||
.request_garbage_collection_for_testing(v8::GarbageCollectionType::Full);
|
||||
// Assert callback was removed and not called again.
|
||||
assert_eq!(state.mark_sweep_calls, 1);
|
||||
assert_eq!(state.incremental_marking_calls, 0);
|
||||
|
|
Loading…
Add table
Reference in a new issue