aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/script_task.rs
diff options
context:
space:
mode:
authorMichael Howell <michael@notriddle.com>2015-08-04 15:01:55 -0700
committerMichael Howell <michael@notriddle.com>2015-08-06 09:45:11 -0700
commit7cb4d77c74f502c8d7bf1080c9c6b34ee7e21475 (patch)
tree5de22e3d8951e7207821cb9afcb8a88f1e8ece95 /components/script/script_task.rs
parentd2ba81ead2daa059a9ee889fe643d00c3d6fb8c8 (diff)
downloadservo-7cb4d77c74f502c8d7bf1080c9c6b34ee7e21475.tar.gz
servo-7cb4d77c74f502c8d7bf1080c9c6b34ee7e21475.zip
GC profiling.
* Closes #6968. * Test case for GC profiling thanks to @jdm!
Diffstat (limited to 'components/script/script_task.rs')
-rw-r--r--components/script/script_task.rs53
1 files changed, 52 insertions, 1 deletions
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index 832024a1c03..c8aea249a95 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -78,6 +78,7 @@ use string_cache::Atom;
use util::str::DOMString;
use util::task::spawn_named_with_send_on_failure;
use util::task_state;
+use util::opts;
use euclid::Rect;
use euclid::point::Point2D;
@@ -89,6 +90,7 @@ use js::jsapi::{JS_SetWrapObjectCallbacks, JS_AddExtraGCRootsTracer, DisableIncr
use js::jsapi::{JSContext, JSRuntime, JSTracer};
use js::jsapi::{JS_GetRuntime, JS_SetGCCallback, JSGCStatus, JSAutoRequest, SetDOMCallbacks};
use js::jsapi::{SetDOMProxyInformation, DOMProxyShadowsResult, HandleObject, HandleId, RootedValue};
+use js::jsapi::{JSGCInvocationKind, GCDescription, SetGCSliceCallback, GCProgress};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use url::{Url, UrlParser};
@@ -98,6 +100,7 @@ use std::any::Any;
use std::borrow::ToOwned;
use std::cell::{Cell, RefCell};
use std::collections::HashSet;
+use std::io::{stdout, Write};
use std::mem as std_mem;
use std::option::Option;
use std::ptr;
@@ -105,7 +108,7 @@ use std::rc::Rc;
use std::result::Result;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver, Select};
-use time::Tm;
+use time::{self, Tm};
use hyper::header::{ContentType, HttpDate};
use hyper::mime::{Mime, TopLevel, SubLevel};
@@ -462,6 +465,49 @@ impl ScriptTaskFactory for ScriptTask {
}
}
+thread_local!(static GC_CYCLE_START: Cell<Option<Tm>> = Cell::new(None));
+thread_local!(static GC_SLICE_START: Cell<Option<Tm>> = Cell::new(None));
+
+unsafe extern "C" fn gc_slice_callback(_rt: *mut JSRuntime, progress: GCProgress, desc: *const GCDescription) {
+ match progress {
+ GCProgress::GC_CYCLE_BEGIN => {
+ GC_CYCLE_START.with(|start| {
+ start.set(Some(time::now()));
+ println!("GC cycle began");
+ })
+ },
+ GCProgress::GC_SLICE_BEGIN => {
+ GC_SLICE_START.with(|start| {
+ start.set(Some(time::now()));
+ println!("GC slice began");
+ })
+ },
+ GCProgress::GC_SLICE_END => {
+ GC_SLICE_START.with(|start| {
+ let dur = time::now() - start.get().unwrap();
+ start.set(None);
+ println!("GC slice ended: duration={}", dur);
+ })
+ },
+ GCProgress::GC_CYCLE_END => {
+ GC_CYCLE_START.with(|start| {
+ let dur = time::now() - start.get().unwrap();
+ start.set(None);
+ println!("GC cycle ended: duration={}", dur);
+ })
+ },
+ };
+ if !desc.is_null() {
+ let desc: &GCDescription = &*desc;
+ let invocationKind = match desc.invocationKind_ {
+ JSGCInvocationKind::GC_NORMAL => "GC_NORMAL",
+ JSGCInvocationKind::GC_SHRINK => "GC_SHRINK",
+ };
+ println!(" isCompartment={}, invocationKind={}", desc.isCompartment_, invocationKind);
+ }
+ let _ = stdout().flush();
+}
+
unsafe extern "C" fn debug_gc_callback(_rt: *mut JSRuntime, status: JSGCStatus, _data: *mut libc::c_void) {
match status {
JSGCStatus::JSGC_BEGIN => task_state::enter(task_state::IN_GC),
@@ -575,6 +621,11 @@ impl ScriptTask {
JS_SetGCCallback(runtime.rt(), Some(debug_gc_callback), ptr::null_mut());
}
}
+ if opts::get().gc_profile {
+ unsafe {
+ SetGCSliceCallback(runtime.rt(), Some(gc_slice_callback));
+ }
+ }
unsafe {
SetDOMProxyInformation(ptr::null(), 0, Some(shadow_check_callback));