Created
January 18, 2017 22:49
-
-
Save jdm/b36d32d887e1fd6887b6d60c6cae218d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* This Source Code Form is subject to the terms of the Mozilla Public | |
* License, v. 2.0. If a copy of the MPL was not distributed with this file, | |
* You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
#[macro_use] | |
extern crate js; | |
extern crate libc; | |
use js::jsapi::{jsfriendapi_h_unnamed_12, DumpHeap}; | |
use js::glue::CallValueTracer; | |
use js::jsapi::JS_GC; | |
use js::jsapi::JSAutoCompartment; | |
use js::jsapi::CallArgs; | |
use js::jsapi::CompartmentOptions; | |
use js::jsapi::GCForReason; | |
use js::jsapi::GCTraceKindToAscii; | |
use js::jsapi::GCNurseryProgress; | |
use js::jsapi::HandleObject; | |
use js::jsapi::Heap; | |
use js::jsapi::IsPromiseObject; | |
use js::jsapi::JSContext; | |
use js::jsapi::JSGCInvocationKind; | |
use js::jsapi::JSGCStatus; | |
use js::jsapi::JSRuntime; | |
use js::jsapi::JSTracer; | |
use js::jsapi::JS_AddExtraGCRootsTracer; | |
use js::jsapi::JS_GetFunctionObject; | |
use js::jsapi::JS_NewFunction; | |
use js::jsapi::JS_NewGlobalObject; | |
use js::jsapi::JS_NewObject; | |
use js::jsapi::JS_SetGCCallback; | |
use js::jsapi::NewPromiseObject; | |
use js::jsapi::OnNewGlobalHookOption; | |
use js::jsapi::SetGCNurseryCollectionCallback; | |
use js::jsapi::Reason; | |
use js::jsval::{UndefinedValue, JSVal, ObjectValue}; | |
use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; | |
use std::cell::UnsafeCell; | |
use std::ptr; | |
use std::os::raw::c_void; | |
unsafe extern fn do_nothing_promise_executor(_cx: *mut JSContext, argc: u32, vp: *mut JSVal) -> bool { | |
let args = CallArgs::from_vp(vp, argc); | |
*args.rval() = UndefinedValue(); | |
true | |
} | |
unsafe extern fn gc_callback(_rt: *mut JSRuntime, _progress: GCNurseryProgress, _reason: Reason) { | |
//panic!("nursery gc callback") | |
} | |
unsafe extern fn gc_callback2(_rt: *mut JSRuntime, _status: JSGCStatus, _data: *mut c_void) { | |
//panic!("regular gc callback") | |
} | |
static mut PROMISE_ROOT: *mut Global = 0 as *mut Global; | |
struct Global { | |
v: Option<UnsafeCell<Heap<JSVal>>>, | |
} | |
unsafe extern "C" fn trace_promise_root(tr: *mut JSTracer, _data: *mut c_void) { | |
if PROMISE_ROOT.is_null() { | |
return; | |
} | |
if let Some(ref value) = (*PROMISE_ROOT).v { | |
let v: &Heap<JSVal> = &*value.get(); | |
if v.get().is_markable() { | |
CallValueTracer(tr, v.ptr.get() as *mut _, | |
GCTraceKindToAscii(v.get().trace_kind())); | |
} | |
} | |
} | |
#[test] | |
fn test() { | |
let rt = Runtime::new(); | |
let cx = rt.cx(); | |
let mut g = Global { | |
v: None, | |
}; | |
unsafe { | |
PROMISE_ROOT = &mut g; | |
//JS_AddExtraGCRootsTracer(rt.rt(), Some(trace_promise_root), ptr::null_mut()); | |
let _ = SetGCNurseryCollectionCallback(rt.rt(), Some(gc_callback)); | |
JS_SetGCCallback(rt.rt(), Some(gc_callback2), ptr::null_mut()); | |
rooted!(in(cx) let global = | |
JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(), | |
OnNewGlobalHookOption::FireOnNewGlobalHook, | |
&CompartmentOptions::default()) | |
); | |
let _ac = JSAutoCompartment::new(cx, global.get()); | |
let do_nothing_func = JS_NewFunction(cx, | |
Some(do_nothing_promise_executor), | |
/* nargs = */ 2, | |
/* flags = */ 0, | |
ptr::null()); | |
{ | |
assert!(!do_nothing_func.is_null()); | |
rooted!(in(cx) let do_nothing_obj = JS_GetFunctionObject(do_nothing_func)); | |
assert!(!do_nothing_obj.is_null()); | |
rooted!(in(cx) let promise = NewPromiseObject(cx, | |
do_nothing_obj.handle(), | |
HandleObject::null())); | |
g.v = Some(UnsafeCell::new(Heap::default())); | |
(*g.v.as_mut().unwrap().get()).set(ObjectValue(promise.get())); | |
} | |
//JS_GC(rt.rt()); | |
{ | |
//let mut v = vec![]; | |
//for _ in 1..1000 { | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
//GCForReason(rt.rt(), JSGCInvocationKind::GC_SHRINK, Reason::OUT_OF_NURSERY); | |
//} | |
//MinorGC(cx, false); | |
} | |
let fp = libc::fopen(b"/dev/null\0" as *const _ as *const _, b"w\0" as *const _ as *const _); | |
DumpHeap(rt.rt(), fp, jsfriendapi_h_unnamed_12::CollectNurseryBeforeDump); | |
libc::fclose(fp); | |
rooted!(in(cx) let promise = (*g.v.as_ref().unwrap().get()).get().to_object()); | |
assert!(IsPromiseObject(promise.handle())); | |
PROMISE_ROOT = ptr::null_mut(); | |
//JS_SetGCCallback(rt.rt(), None, ptr::null_mut()); | |
//let _ = SetGCNurseryCollectionCallback(rt.rt(), None); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment