aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/script_task.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/script_task.rs')
-rw-r--r--components/script/script_task.rs83
1 files changed, 63 insertions, 20 deletions
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index 6214b289731..efbad39dc86 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -73,11 +73,12 @@ use net_traits::LoadData as NetLoadData;
use net_traits::{AsyncResponseTarget, ResourceTask, LoadConsumer, ControlMsg, Metadata};
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageCacheResult};
use net_traits::storage_task::StorageTask;
-use profile_traits::mem::{self, Report, Reporter, ReporterRequest, ReportKind, ReportsChan};
+use profile_traits::mem::{self, Report, ReportKind, ReportsChan, OpaqueSender};
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};
@@ -216,6 +219,12 @@ pub trait ScriptChan {
fn clone(&self) -> Box<ScriptChan+Send>;
}
+impl OpaqueSender<ScriptMsg> for Box<ScriptChan+Send> {
+ fn send(&self, msg: ScriptMsg) {
+ ScriptChan::send(&**self, msg).unwrap();
+ }
+}
+
/// An interface for receiving ScriptMsg values in an event loop. Used for synchronous DOM
/// APIs that need to abstract over multiple kinds of event loops (worker/main thread) with
/// different Receiver interfaces.
@@ -437,24 +446,10 @@ impl ScriptTaskFactory for ScriptTask {
load_data.url.clone());
script_task.start_page_load(new_load, load_data);
- // Register this task as a memory reporter.
let reporter_name = format!("script-reporter-{}", id.0);
- let (reporter_sender, reporter_receiver) = ipc::channel().unwrap();
- ROUTER.add_route(reporter_receiver.to_opaque(), box move |reporter_request| {
- // Just injects an appropriate event into the worker task's queue.
- let reporter_request: ReporterRequest = reporter_request.to().unwrap();
- channel_for_reporter.send(ScriptMsg::CollectReports(
- reporter_request.reports_channel)).unwrap()
- });
- let reporter = Reporter(reporter_sender);
- let msg = mem::ProfilerMsg::RegisterReporter(reporter_name.clone(), reporter);
- mem_profiler_chan.send(msg);
-
- script_task.start();
-
- // Unregister this task as a memory reporter.
- let msg = mem::ProfilerMsg::UnregisterReporter(reporter_name);
- mem_profiler_chan.send(msg);
+ mem_profiler_chan.run_with_memory_reporting(|| {
+ script_task.start();
+ }, reporter_name, channel_for_reporter, ScriptMsg::CollectReports);
// This must always be the very last operation performed before the task completes
failsafe.neuter();
@@ -462,6 +457,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 +613,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));
@@ -1329,7 +1372,7 @@ impl ScriptTask {
fn handle_tick_all_animations(&self, id: PipelineId) {
let page = get_page(&self.root_page(), id);
let document = page.document();
- document.r().invoke_animation_callbacks();
+ document.r().run_the_animation_frame_callbacks();
}
/// The entry point to document loading. Defines bindings, sets up the window and document