mirror of
https://github.com/servo/servo.git
synced 2025-08-01 19:50:30 +01:00
Time distribution across script event categories.
This commit is contained in:
parent
71b277d567
commit
1e6a2f08fc
11 changed files with 184 additions and 50 deletions
|
@ -17,9 +17,10 @@ use dom::bindings::structuredclone::StructuredCloneData;
|
||||||
use dom::bindings::utils::Reflectable;
|
use dom::bindings::utils::Reflectable;
|
||||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||||
use dom::messageevent::MessageEvent;
|
use dom::messageevent::MessageEvent;
|
||||||
use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler, WorkerEventHandler};
|
use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler, SimpleWorkerErrorHandler};
|
||||||
use dom::workerglobalscope::WorkerGlobalScope;
|
use dom::workerglobalscope::WorkerGlobalScope;
|
||||||
use dom::workerglobalscope::{WorkerGlobalScopeTypeId, WorkerGlobalScopeInit};
|
use dom::workerglobalscope::{WorkerGlobalScopeTypeId, WorkerGlobalScopeInit};
|
||||||
|
use script_task::ScriptTaskEventCategory::WorkerEvent;
|
||||||
use script_task::{ScriptTask, ScriptChan, TimerSource, ScriptPort, StackRootTLS, CommonScriptMsg};
|
use script_task::{ScriptTask, ScriptChan, TimerSource, ScriptPort, StackRootTLS, CommonScriptMsg};
|
||||||
|
|
||||||
use devtools_traits::DevtoolScriptControlMsg;
|
use devtools_traits::DevtoolScriptControlMsg;
|
||||||
|
@ -207,8 +208,8 @@ impl DedicatedWorkerGlobalScope {
|
||||||
let (url, source) = match load_whole_resource(&init.resource_task, worker_url) {
|
let (url, source) = match load_whole_resource(&init.resource_task, worker_url) {
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
println!("error loading script {}", serialized_worker_url);
|
println!("error loading script {}", serialized_worker_url);
|
||||||
parent_sender.send(CommonScriptMsg::RunnableMsg(
|
parent_sender.send(CommonScriptMsg::RunnableMsg(WorkerEvent,
|
||||||
box WorkerEventHandler::new(worker))).unwrap();
|
box SimpleWorkerErrorHandler::new(worker))).unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Ok((metadata, bytes)) => {
|
Ok((metadata, bytes)) => {
|
||||||
|
@ -308,7 +309,7 @@ impl DedicatedWorkerGlobalScope {
|
||||||
data.read(GlobalRef::Worker(scope), message.handle_mut());
|
data.read(GlobalRef::Worker(scope), message.handle_mut());
|
||||||
MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message.handle());
|
MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message.handle());
|
||||||
},
|
},
|
||||||
WorkerScriptMsg::Common(CommonScriptMsg::RunnableMsg(runnable)) => {
|
WorkerScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) => {
|
||||||
runnable.handler()
|
runnable.handler()
|
||||||
},
|
},
|
||||||
WorkerScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr)) => {
|
WorkerScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr)) => {
|
||||||
|
@ -359,7 +360,7 @@ impl DedicatedWorkerGlobalScopeMethods for DedicatedWorkerGlobalScope {
|
||||||
fn PostMessage(&self, cx: *mut JSContext, message: HandleValue) -> ErrorResult {
|
fn PostMessage(&self, cx: *mut JSContext, message: HandleValue) -> ErrorResult {
|
||||||
let data = try!(StructuredCloneData::write(cx, message));
|
let data = try!(StructuredCloneData::write(cx, message));
|
||||||
let worker = self.worker.borrow().as_ref().unwrap().clone();
|
let worker = self.worker.borrow().as_ref().unwrap().clone();
|
||||||
self.parent_sender.send(CommonScriptMsg::RunnableMsg(
|
self.parent_sender.send(CommonScriptMsg::RunnableMsg(WorkerEvent,
|
||||||
box WorkerMessageHandler::new(worker, data))).unwrap();
|
box WorkerMessageHandler::new(worker, data))).unwrap();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ use encoding::label::encoding_from_whatwg_label;
|
||||||
use encoding::types::{EncodingRef, DecoderTrap};
|
use encoding::types::{EncodingRef, DecoderTrap};
|
||||||
use hyper::mime::{Mime, Attr};
|
use hyper::mime::{Mime, Attr};
|
||||||
use rustc_serialize::base64::{Config, ToBase64, CharacterSet, Newline};
|
use rustc_serialize::base64::{Config, ToBase64, CharacterSet, Newline};
|
||||||
|
use script_task::ScriptTaskEventCategory::FileRead;
|
||||||
use script_task::{ScriptChan, Runnable, ScriptPort, CommonScriptMsg};
|
use script_task::{ScriptChan, Runnable, ScriptPort, CommonScriptMsg};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
@ -401,22 +402,22 @@ fn perform_annotated_read_operation(gen_id: GenerationId, data: ReadMetaData, bl
|
||||||
let chan = &script_chan;
|
let chan = &script_chan;
|
||||||
// Step 4
|
// Step 4
|
||||||
let task = box FileReaderEvent::ProcessRead(filereader.clone(), gen_id);
|
let task = box FileReaderEvent::ProcessRead(filereader.clone(), gen_id);
|
||||||
chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
|
chan.send(CommonScriptMsg::RunnableMsg(FileRead, task)).unwrap();
|
||||||
|
|
||||||
let task = box FileReaderEvent::ProcessReadData(filereader.clone(),
|
let task = box FileReaderEvent::ProcessReadData(filereader.clone(),
|
||||||
gen_id, DOMString::new());
|
gen_id, DOMString::new());
|
||||||
chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
|
chan.send(CommonScriptMsg::RunnableMsg(FileRead, task)).unwrap();
|
||||||
|
|
||||||
let bytes = match blob_contents.recv() {
|
let bytes = match blob_contents.recv() {
|
||||||
Ok(bytes) => bytes,
|
Ok(bytes) => bytes,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let task = box FileReaderEvent::ProcessReadError(filereader,
|
let task = box FileReaderEvent::ProcessReadError(filereader,
|
||||||
gen_id, DOMErrorName::NotFoundError);
|
gen_id, DOMErrorName::NotFoundError);
|
||||||
chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
|
chan.send(CommonScriptMsg::RunnableMsg(FileRead, task)).unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let task = box FileReaderEvent::ProcessReadEOF(filereader, gen_id, data, bytes);
|
let task = box FileReaderEvent::ProcessReadEOF(filereader, gen_id, data, bytes);
|
||||||
chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
|
chan.send(CommonScriptMsg::RunnableMsg(FileRead, task)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||||
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
||||||
use dom::node::{document_from_node, Node, NodeTypeId, NodeDamage, window_from_node};
|
use dom::node::{document_from_node, Node, NodeTypeId, NodeDamage, window_from_node};
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
|
use script_task::ScriptTaskEventCategory::UpdateReplacedElement;
|
||||||
use script_task::{Runnable, ScriptChan, CommonScriptMsg};
|
use script_task::{Runnable, ScriptChan, CommonScriptMsg};
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
@ -131,7 +132,7 @@ impl HTMLImageElement {
|
||||||
// Return the image via a message to the script task, which marks the element
|
// Return the image via a message to the script task, which marks the element
|
||||||
// as dirty and triggers a reflow.
|
// as dirty and triggers a reflow.
|
||||||
let image_response = message.to().unwrap();
|
let image_response = message.to().unwrap();
|
||||||
script_chan.send(CommonScriptMsg::RunnableMsg(
|
script_chan.send(CommonScriptMsg::RunnableMsg(UpdateReplacedElement,
|
||||||
box ImageResponseHandlerRunnable::new(
|
box ImageResponseHandlerRunnable::new(
|
||||||
trusted_node.clone(), image_response))).unwrap();
|
trusted_node.clone(), image_response))).unwrap();
|
||||||
});
|
});
|
||||||
|
|
|
@ -32,6 +32,7 @@ use dom::window::ScriptHelpers;
|
||||||
use js::jsapi::RootedValue;
|
use js::jsapi::RootedValue;
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use network_listener::{NetworkListener, PreInvoke};
|
use network_listener::{NetworkListener, PreInvoke};
|
||||||
|
use script_task::ScriptTaskEventCategory::ScriptEvent;
|
||||||
use script_task::{ScriptChan, Runnable, CommonScriptMsg};
|
use script_task::{ScriptChan, Runnable, CommonScriptMsg};
|
||||||
|
|
||||||
use encoding::all::UTF_8;
|
use encoding::all::UTF_8;
|
||||||
|
@ -426,7 +427,7 @@ impl HTMLScriptElement {
|
||||||
element: handler,
|
element: handler,
|
||||||
is_error: false,
|
is_error: false,
|
||||||
};
|
};
|
||||||
chan.send(CommonScriptMsg::RunnableMsg(dispatcher)).unwrap();
|
chan.send(CommonScriptMsg::RunnableMsg(ScriptEvent, dispatcher)).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,7 +440,7 @@ impl HTMLScriptElement {
|
||||||
element: handler,
|
element: handler,
|
||||||
is_error: true,
|
is_error: true,
|
||||||
};
|
};
|
||||||
chan.send(CommonScriptMsg::RunnableMsg(dispatcher)).unwrap();
|
chan.send(CommonScriptMsg::RunnableMsg(ScriptEvent, dispatcher)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dispatch_before_script_execute_event(&self) -> bool {
|
pub fn dispatch_before_script_execute_event(&self) -> bool {
|
||||||
|
|
|
@ -25,6 +25,7 @@ use dom::node::{ChildrenMutation, Node, NodeDamage};
|
||||||
use dom::node::{NodeTypeId, document_from_node, window_from_node};
|
use dom::node::{NodeTypeId, document_from_node, window_from_node};
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use msg::constellation_msg::ConstellationChan;
|
use msg::constellation_msg::ConstellationChan;
|
||||||
|
use script_task::ScriptTaskEventCategory::InputEvent;
|
||||||
use script_task::{Runnable, CommonScriptMsg};
|
use script_task::{Runnable, CommonScriptMsg};
|
||||||
use textinput::{TextInput, Lines, KeyReaction};
|
use textinput::{TextInput, Lines, KeyReaction};
|
||||||
|
|
||||||
|
@ -356,7 +357,7 @@ impl VirtualMethods for HTMLTextAreaElement {
|
||||||
let dispatcher = ChangeEventRunnable {
|
let dispatcher = ChangeEventRunnable {
|
||||||
element: handler,
|
element: handler,
|
||||||
};
|
};
|
||||||
let _ = chan.send(CommonScriptMsg::RunnableMsg(box dispatcher));
|
let _ = chan.send(CommonScriptMsg::RunnableMsg(InputEvent, box dispatcher));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.force_relayout();
|
self.force_relayout();
|
||||||
|
|
|
@ -22,6 +22,7 @@ use dom::closeevent::CloseEvent;
|
||||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||||
use dom::messageevent::MessageEvent;
|
use dom::messageevent::MessageEvent;
|
||||||
|
use script_task::ScriptTaskEventCategory::WebSocketEvent;
|
||||||
use script_task::{Runnable, CommonScriptMsg};
|
use script_task::{Runnable, CommonScriptMsg};
|
||||||
|
|
||||||
use net_traits::hosts::replace_hosts;
|
use net_traits::hosts::replace_hosts;
|
||||||
|
@ -182,7 +183,7 @@ impl WebSocket {
|
||||||
let task = box CloseTask {
|
let task = box CloseTask {
|
||||||
addr: address,
|
addr: address,
|
||||||
};
|
};
|
||||||
sender.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
|
sender.send(CommonScriptMsg::RunnableMsg(WebSocketEvent, task)).unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -192,7 +193,7 @@ impl WebSocket {
|
||||||
addr: address.clone(),
|
addr: address.clone(),
|
||||||
sender: ws_sender.clone(),
|
sender: ws_sender.clone(),
|
||||||
};
|
};
|
||||||
sender.send(CommonScriptMsg::RunnableMsg(open_task)).unwrap();
|
sender.send(CommonScriptMsg::RunnableMsg(WebSocketEvent, open_task)).unwrap();
|
||||||
|
|
||||||
for message in receiver.incoming_messages() {
|
for message in receiver.incoming_messages() {
|
||||||
let message = match message {
|
let message = match message {
|
||||||
|
@ -208,7 +209,7 @@ impl WebSocket {
|
||||||
let task = box CloseTask {
|
let task = box CloseTask {
|
||||||
addr: address,
|
addr: address,
|
||||||
};
|
};
|
||||||
sender.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
|
sender.send(CommonScriptMsg::RunnableMsg(WebSocketEvent, task)).unwrap();
|
||||||
break;
|
break;
|
||||||
},
|
},
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
|
@ -217,7 +218,7 @@ impl WebSocket {
|
||||||
address: address.clone(),
|
address: address.clone(),
|
||||||
message: message,
|
message: message,
|
||||||
};
|
};
|
||||||
sender.send(CommonScriptMsg::RunnableMsg(message_task)).unwrap();
|
sender.send(CommonScriptMsg::RunnableMsg(WebSocketEvent, message_task)).unwrap();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -186,20 +186,20 @@ impl Runnable for WorkerMessageHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WorkerEventHandler {
|
pub struct SimpleWorkerErrorHandler {
|
||||||
addr: TrustedWorkerAddress,
|
addr: TrustedWorkerAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorkerEventHandler {
|
impl SimpleWorkerErrorHandler {
|
||||||
pub fn new(addr: TrustedWorkerAddress) -> WorkerEventHandler {
|
pub fn new(addr: TrustedWorkerAddress) -> SimpleWorkerErrorHandler {
|
||||||
WorkerEventHandler {
|
SimpleWorkerErrorHandler {
|
||||||
addr: addr
|
addr: addr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Runnable for WorkerEventHandler {
|
impl Runnable for SimpleWorkerErrorHandler {
|
||||||
fn handler(self: Box<WorkerEventHandler>) {
|
fn handler(self: Box<SimpleWorkerErrorHandler>) {
|
||||||
let this = *self;
|
let this = *self;
|
||||||
Worker::dispatch_simple_error(this.addr);
|
Worker::dispatch_simple_error(this.addr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget;
|
||||||
use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTargetTypeId;
|
use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTargetTypeId;
|
||||||
use dom::xmlhttprequestupload::XMLHttpRequestUpload;
|
use dom::xmlhttprequestupload::XMLHttpRequestUpload;
|
||||||
use network_listener::{NetworkListener, PreInvoke};
|
use network_listener::{NetworkListener, PreInvoke};
|
||||||
|
use script_task::ScriptTaskEventCategory::XhrEvent;
|
||||||
use script_task::{ScriptChan, Runnable, ScriptPort, CommonScriptMsg};
|
use script_task::{ScriptChan, Runnable, ScriptPort, CommonScriptMsg};
|
||||||
|
|
||||||
use encoding::all::UTF_8;
|
use encoding::all::UTF_8;
|
||||||
|
@ -989,7 +990,7 @@ impl XMLHttpRequest {
|
||||||
sleep_ms(duration_ms);
|
sleep_ms(duration_ms);
|
||||||
match cancel_rx.try_recv() {
|
match cancel_rx.try_recv() {
|
||||||
Err(TryRecvError::Empty) => {
|
Err(TryRecvError::Empty) => {
|
||||||
timeout_target.send(CommonScriptMsg::RunnableMsg(box XHRTimeout {
|
timeout_target.send(CommonScriptMsg::RunnableMsg(XhrEvent, box XHRTimeout {
|
||||||
xhr: xhr,
|
xhr: xhr,
|
||||||
gen_id: gen_id,
|
gen_id: gen_id,
|
||||||
})).unwrap();
|
})).unwrap();
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use net_traits::{AsyncResponseListener, ResponseAction};
|
use net_traits::{AsyncResponseListener, ResponseAction};
|
||||||
|
use script_task::ScriptTaskEventCategory::NetworkEvent;
|
||||||
use script_task::{ScriptChan, Runnable, CommonScriptMsg};
|
use script_task::{ScriptChan, Runnable, CommonScriptMsg};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ pub struct NetworkListener<T: AsyncResponseListener + PreInvoke + Send + 'static
|
||||||
|
|
||||||
impl<T: AsyncResponseListener + PreInvoke + Send + 'static> NetworkListener<T> {
|
impl<T: AsyncResponseListener + PreInvoke + Send + 'static> NetworkListener<T> {
|
||||||
pub fn notify(&self, action: ResponseAction) {
|
pub fn notify(&self, action: ResponseAction) {
|
||||||
if let Err(err) = self.script_chan.send(CommonScriptMsg::RunnableMsg(box ListenerRunnable {
|
if let Err(err) = self.script_chan.send(CommonScriptMsg::RunnableMsg(NetworkEvent, box ListenerRunnable {
|
||||||
context: self.context.clone(),
|
context: self.context.clone(),
|
||||||
action: action,
|
action: action,
|
||||||
})) {
|
})) {
|
||||||
|
|
|
@ -94,11 +94,12 @@ use js::jsval::UndefinedValue;
|
||||||
use js::rust::Runtime;
|
use js::rust::Runtime;
|
||||||
use url::{Url, UrlParser};
|
use url::{Url, UrlParser};
|
||||||
|
|
||||||
|
use core::ops::Deref;
|
||||||
use libc;
|
use libc;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::io::{stdout, Write};
|
use std::io::{stdout, Write};
|
||||||
use std::mem as std_mem;
|
use std::mem as std_mem;
|
||||||
use std::option::Option;
|
use std::option::Option;
|
||||||
|
@ -178,6 +179,13 @@ pub trait MainThreadRunnable {
|
||||||
fn handler(self: Box<Self>, script_task: &ScriptTask);
|
fn handler(self: Box<Self>, script_task: &ScriptTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum MixedMessage {
|
||||||
|
FromConstellation(ConstellationControlMsg),
|
||||||
|
FromScript(MainThreadScriptMsg),
|
||||||
|
FromDevtools(DevtoolScriptControlMsg),
|
||||||
|
FromImageCache(ImageCacheResult),
|
||||||
|
}
|
||||||
|
|
||||||
/// Common messages used to control the event loops in both the script and the worker
|
/// Common messages used to control the event loops in both the script and the worker
|
||||||
pub enum CommonScriptMsg {
|
pub enum CommonScriptMsg {
|
||||||
/// Requests that the script task measure its memory usage. The results are sent back via the
|
/// Requests that the script task measure its memory usage. The results are sent back via the
|
||||||
|
@ -190,7 +198,27 @@ pub enum CommonScriptMsg {
|
||||||
/// A DOM object's last pinned reference was removed (dispatched to all tasks).
|
/// A DOM object's last pinned reference was removed (dispatched to all tasks).
|
||||||
RefcountCleanup(TrustedReference),
|
RefcountCleanup(TrustedReference),
|
||||||
/// Generic message that encapsulates event handling.
|
/// Generic message that encapsulates event handling.
|
||||||
RunnableMsg(Box<Runnable + Send>),
|
RunnableMsg(ScriptTaskEventCategory, Box<Runnable + Send>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, Hash, JSTraceable, PartialEq)]
|
||||||
|
pub enum ScriptTaskEventCategory {
|
||||||
|
AttachLayout,
|
||||||
|
ConstellationMsg,
|
||||||
|
DevtoolsMsg,
|
||||||
|
DocumentEvent,
|
||||||
|
DomEvent,
|
||||||
|
FileRead,
|
||||||
|
ImageCacheMsg,
|
||||||
|
InputEvent,
|
||||||
|
NetworkEvent,
|
||||||
|
Resize,
|
||||||
|
ScriptEvent,
|
||||||
|
UpdateReplacedElement,
|
||||||
|
SetViewport,
|
||||||
|
WebSocketEvent,
|
||||||
|
WorkerEvent,
|
||||||
|
XhrEvent,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Messages used to control the script event loop
|
/// Messages used to control the script event loop
|
||||||
|
@ -390,6 +418,11 @@ pub struct ScriptTask {
|
||||||
|
|
||||||
/// List of pipelines that have been owned and closed by this script task.
|
/// List of pipelines that have been owned and closed by this script task.
|
||||||
closed_pipelines: RefCell<HashSet<PipelineId>>,
|
closed_pipelines: RefCell<HashSet<PipelineId>>,
|
||||||
|
|
||||||
|
/// When profiling data should be written out to stdout.
|
||||||
|
perf_profiler_next_report: Cell<Option<u64>>,
|
||||||
|
/// How much time was spent on what since the last report.
|
||||||
|
perf_profiler_times: RefCell<HashMap<ScriptTaskEventCategory, u64>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In the event of task failure, all data on the stack runs its destructor. However, there
|
/// In the event of task failure, all data on the stack runs its destructor. However, there
|
||||||
|
@ -635,6 +668,9 @@ impl ScriptTask {
|
||||||
js_runtime: Rc::new(runtime),
|
js_runtime: Rc::new(runtime),
|
||||||
mouse_over_targets: DOMRefCell::new(vec!()),
|
mouse_over_targets: DOMRefCell::new(vec!()),
|
||||||
closed_pipelines: RefCell::new(HashSet::new()),
|
closed_pipelines: RefCell::new(HashSet::new()),
|
||||||
|
|
||||||
|
perf_profiler_next_report: Cell::new(None),
|
||||||
|
perf_profiler_times: RefCell::new(HashMap::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,13 +749,6 @@ impl ScriptTask {
|
||||||
self.handle_event(id, ResizeEvent(size));
|
self.handle_event(id, ResizeEvent(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MixedMessage {
|
|
||||||
FromConstellation(ConstellationControlMsg),
|
|
||||||
FromScript(MainThreadScriptMsg),
|
|
||||||
FromDevtools(DevtoolScriptControlMsg),
|
|
||||||
FromImageCache(ImageCacheResult),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store new resizes, and gather all other events.
|
// Store new resizes, and gather all other events.
|
||||||
let mut sequential = vec!();
|
let mut sequential = vec!();
|
||||||
|
|
||||||
|
@ -762,13 +791,19 @@ impl ScriptTask {
|
||||||
// child list yet, causing the find() to fail.
|
// child list yet, causing the find() to fail.
|
||||||
MixedMessage::FromConstellation(ConstellationControlMsg::AttachLayout(
|
MixedMessage::FromConstellation(ConstellationControlMsg::AttachLayout(
|
||||||
new_layout_info)) => {
|
new_layout_info)) => {
|
||||||
|
self.profile_event(ScriptTaskEventCategory::AttachLayout, || {
|
||||||
self.handle_new_layout(new_layout_info);
|
self.handle_new_layout(new_layout_info);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
MixedMessage::FromConstellation(ConstellationControlMsg::Resize(id, size)) => {
|
MixedMessage::FromConstellation(ConstellationControlMsg::Resize(id, size)) => {
|
||||||
|
self.profile_event(ScriptTaskEventCategory::Resize, || {
|
||||||
self.handle_resize(id, size);
|
self.handle_resize(id, size);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
MixedMessage::FromConstellation(ConstellationControlMsg::Viewport(id, rect)) => {
|
MixedMessage::FromConstellation(ConstellationControlMsg::Viewport(id, rect)) => {
|
||||||
|
self.profile_event(ScriptTaskEventCategory::SetViewport, || {
|
||||||
self.handle_viewport(id, rect);
|
self.handle_viewport(id, rect);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
MixedMessage::FromConstellation(ConstellationControlMsg::TickAllAnimations(
|
MixedMessage::FromConstellation(ConstellationControlMsg::TickAllAnimations(
|
||||||
pipeline_id)) => {
|
pipeline_id)) => {
|
||||||
|
@ -815,10 +850,13 @@ impl ScriptTask {
|
||||||
|
|
||||||
// Process the gathered events.
|
// Process the gathered events.
|
||||||
for msg in sequential {
|
for msg in sequential {
|
||||||
|
let category = self.categorize_msg(&msg);
|
||||||
|
|
||||||
|
let result = self.profile_event(category, move || {
|
||||||
match msg {
|
match msg {
|
||||||
MixedMessage::FromConstellation(ConstellationControlMsg::ExitPipeline(id, exit_type)) => {
|
MixedMessage::FromConstellation(ConstellationControlMsg::ExitPipeline(id, exit_type)) => {
|
||||||
if self.handle_exit_pipeline_msg(id, exit_type) {
|
if self.handle_exit_pipeline_msg(id, exit_type) {
|
||||||
return false
|
return Some(false)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MixedMessage::FromConstellation(inner_msg) => self.handle_msg_from_constellation(inner_msg),
|
MixedMessage::FromConstellation(inner_msg) => self.handle_msg_from_constellation(inner_msg),
|
||||||
|
@ -826,6 +864,13 @@ impl ScriptTask {
|
||||||
MixedMessage::FromDevtools(inner_msg) => self.handle_msg_from_devtools(inner_msg),
|
MixedMessage::FromDevtools(inner_msg) => self.handle_msg_from_devtools(inner_msg),
|
||||||
MixedMessage::FromImageCache(inner_msg) => self.handle_msg_from_image_cache(inner_msg),
|
MixedMessage::FromImageCache(inner_msg) => self.handle_msg_from_image_cache(inner_msg),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(retval) = result {
|
||||||
|
return retval
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue batched reflows on any pages that require it (e.g. if images loaded)
|
// Issue batched reflows on any pages that require it (e.g. if images loaded)
|
||||||
|
@ -847,6 +892,76 @@ impl ScriptTask {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn categorize_msg(&self, msg: &MixedMessage) -> ScriptTaskEventCategory {
|
||||||
|
match *msg {
|
||||||
|
MixedMessage::FromConstellation(ref inner_msg) => {
|
||||||
|
match *inner_msg {
|
||||||
|
ConstellationControlMsg::SendEvent(_, _) =>
|
||||||
|
ScriptTaskEventCategory::DomEvent,
|
||||||
|
_ => ScriptTaskEventCategory::ConstellationMsg
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MixedMessage::FromDevtools(_) => ScriptTaskEventCategory::DevtoolsMsg,
|
||||||
|
MixedMessage::FromImageCache(_) => ScriptTaskEventCategory::ImageCacheMsg,
|
||||||
|
MixedMessage::FromScript(ref inner_msg) => {
|
||||||
|
match *inner_msg {
|
||||||
|
MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(ref category, _)) =>
|
||||||
|
*category,
|
||||||
|
_ => ScriptTaskEventCategory::ScriptEvent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn profile_event<F, R>(&self, category: ScriptTaskEventCategory, f: F) -> R
|
||||||
|
where F: FnOnce() -> R {
|
||||||
|
|
||||||
|
if opts::get().profile_script_events {
|
||||||
|
let start = time::precise_time_ns();
|
||||||
|
let result = f();
|
||||||
|
let end = time::precise_time_ns();
|
||||||
|
|
||||||
|
let duration = end - start;
|
||||||
|
|
||||||
|
let aggregate = {
|
||||||
|
let zero = 0;
|
||||||
|
let perf_profiler_times = self.perf_profiler_times.borrow();
|
||||||
|
let so_far = perf_profiler_times.get(&category).unwrap_or(&zero);
|
||||||
|
|
||||||
|
so_far + duration
|
||||||
|
};
|
||||||
|
|
||||||
|
self.perf_profiler_times.borrow_mut().insert(category, aggregate);
|
||||||
|
|
||||||
|
const NANO: u64 = 1000 * 1000 * 1000;
|
||||||
|
const REPORT_INTERVAL: u64 = 10 * NANO;
|
||||||
|
|
||||||
|
match self.perf_profiler_next_report.get() {
|
||||||
|
None => self.perf_profiler_next_report.set(Some(start + REPORT_INTERVAL)),
|
||||||
|
Some(time) if time <= end => {
|
||||||
|
self.perf_profiler_next_report.set(Some(end + REPORT_INTERVAL));
|
||||||
|
|
||||||
|
let stdout = stdout();
|
||||||
|
let mut stdout = stdout.lock();
|
||||||
|
writeln!(&mut stdout, "Script task time distribution:").unwrap();
|
||||||
|
for (c, t) in self.perf_profiler_times.borrow().deref() {
|
||||||
|
let secs = t / NANO;
|
||||||
|
let nanos = t % NANO;
|
||||||
|
writeln!(&mut stdout, " {:?}: {}.{}s", c, secs, nanos).unwrap();
|
||||||
|
}
|
||||||
|
stdout.flush().unwrap();
|
||||||
|
|
||||||
|
self.perf_profiler_times.borrow_mut().clear();
|
||||||
|
},
|
||||||
|
Some(_) => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
} else {
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_msg_from_constellation(&self, msg: ConstellationControlMsg) {
|
fn handle_msg_from_constellation(&self, msg: ConstellationControlMsg) {
|
||||||
match msg {
|
match msg {
|
||||||
ConstellationControlMsg::AttachLayout(_) =>
|
ConstellationControlMsg::AttachLayout(_) =>
|
||||||
|
@ -914,7 +1029,9 @@ impl ScriptTask {
|
||||||
MainThreadScriptMsg::Common(
|
MainThreadScriptMsg::Common(
|
||||||
CommonScriptMsg::FireTimer(TimerSource::FromWorker, _)) =>
|
CommonScriptMsg::FireTimer(TimerSource::FromWorker, _)) =>
|
||||||
panic!("Worker timeouts must not be sent to script task"),
|
panic!("Worker timeouts must not be sent to script task"),
|
||||||
MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(runnable)) =>
|
MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) =>
|
||||||
|
// The category of the runnable is ignored by the pattern, however
|
||||||
|
// it is still respected by profiling (see categorize_msg).
|
||||||
runnable.handler(),
|
runnable.handler(),
|
||||||
MainThreadScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr)) =>
|
MainThreadScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr)) =>
|
||||||
LiveDOMReferences::cleanup(addr),
|
LiveDOMReferences::cleanup(addr),
|
||||||
|
@ -1128,7 +1245,7 @@ impl ScriptTask {
|
||||||
// https://html.spec.whatwg.org/multipage/#the-end step 7
|
// https://html.spec.whatwg.org/multipage/#the-end step 7
|
||||||
let addr: Trusted<Document> = Trusted::new(self.get_cx(), doc, self.chan.clone());
|
let addr: Trusted<Document> = Trusted::new(self.get_cx(), doc, self.chan.clone());
|
||||||
let handler = box DocumentProgressHandler::new(addr.clone(), DocumentProgressTask::Load);
|
let handler = box DocumentProgressHandler::new(addr.clone(), DocumentProgressTask::Load);
|
||||||
self.chan.send(CommonScriptMsg::RunnableMsg(handler)).unwrap();
|
self.chan.send(CommonScriptMsg::RunnableMsg(ScriptTaskEventCategory::DocumentEvent, handler)).unwrap();
|
||||||
|
|
||||||
let ConstellationChan(ref chan) = self.constellation_chan;
|
let ConstellationChan(ref chan) = self.constellation_chan;
|
||||||
chan.send(ConstellationMsg::LoadComplete(pipeline)).unwrap();
|
chan.send(ConstellationMsg::LoadComplete(pipeline)).unwrap();
|
||||||
|
@ -1881,7 +1998,7 @@ impl ScriptTask {
|
||||||
// https://html.spec.whatwg.org/multipage/#the-end step 4
|
// https://html.spec.whatwg.org/multipage/#the-end step 4
|
||||||
let addr: Trusted<Document> = Trusted::new(self.get_cx(), document.r(), self.chan.clone());
|
let addr: Trusted<Document> = Trusted::new(self.get_cx(), document.r(), self.chan.clone());
|
||||||
let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded);
|
let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded);
|
||||||
self.chan.send(CommonScriptMsg::RunnableMsg(handler)).unwrap();
|
self.chan.send(CommonScriptMsg::RunnableMsg(ScriptTaskEventCategory::DocumentEvent, handler)).unwrap();
|
||||||
|
|
||||||
window.r().set_fragment_name(final_url.fragment.clone());
|
window.r().set_fragment_name(final_url.fragment.clone());
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,9 @@ pub struct Opts {
|
||||||
/// profile viewer.
|
/// profile viewer.
|
||||||
pub profile_tasks: bool,
|
pub profile_tasks: bool,
|
||||||
|
|
||||||
|
/// Periodically print out on which events script tasks spend their processing time.
|
||||||
|
pub profile_script_events: bool,
|
||||||
|
|
||||||
/// `None` to disable devtools or `Some` with a port number to start a server to listen to
|
/// `None` to disable devtools or `Some` with a port number to start a server to listen to
|
||||||
/// remote Firefox devtools connections.
|
/// remote Firefox devtools connections.
|
||||||
pub devtools_port: Option<u16>,
|
pub devtools_port: Option<u16>,
|
||||||
|
@ -213,6 +216,9 @@ pub struct DebugOptions {
|
||||||
/// Instrument each task, writing the output to a file.
|
/// Instrument each task, writing the output to a file.
|
||||||
pub profile_tasks: bool,
|
pub profile_tasks: bool,
|
||||||
|
|
||||||
|
/// Profile which events script tasks spend their time on.
|
||||||
|
pub profile_script_events: bool,
|
||||||
|
|
||||||
/// Paint borders along layer and tile boundaries.
|
/// Paint borders along layer and tile boundaries.
|
||||||
pub show_compositor_borders: bool,
|
pub show_compositor_borders: bool,
|
||||||
|
|
||||||
|
@ -265,6 +271,7 @@ impl DebugOptions {
|
||||||
"dump-display-list-optimized" => debug_options.dump_display_list_optimized = true,
|
"dump-display-list-optimized" => debug_options.dump_display_list_optimized = true,
|
||||||
"relayout-event" => debug_options.relayout_event = true,
|
"relayout-event" => debug_options.relayout_event = true,
|
||||||
"profile-tasks" => debug_options.profile_tasks = true,
|
"profile-tasks" => debug_options.profile_tasks = true,
|
||||||
|
"profile-script-events" => debug_options.profile_script_events = true,
|
||||||
"show-compositor-borders" => debug_options.show_compositor_borders = true,
|
"show-compositor-borders" => debug_options.show_compositor_borders = true,
|
||||||
"show-fragment-borders" => debug_options.show_fragment_borders = true,
|
"show-fragment-borders" => debug_options.show_fragment_borders = true,
|
||||||
"show-parallel-paint" => debug_options.show_parallel_paint = true,
|
"show-parallel-paint" => debug_options.show_parallel_paint = true,
|
||||||
|
@ -409,6 +416,7 @@ pub fn default_opts() -> Opts {
|
||||||
relayout_event: false,
|
relayout_event: false,
|
||||||
validate_display_list_geometry: false,
|
validate_display_list_geometry: false,
|
||||||
profile_tasks: false,
|
profile_tasks: false,
|
||||||
|
profile_script_events: false,
|
||||||
resources_path: None,
|
resources_path: None,
|
||||||
sniff_mime_types: false,
|
sniff_mime_types: false,
|
||||||
disable_share_style_cache: false,
|
disable_share_style_cache: false,
|
||||||
|
@ -594,6 +602,7 @@ pub fn from_cmdline_args(args: &[String]) {
|
||||||
hard_fail: opt_match.opt_present("f"),
|
hard_fail: opt_match.opt_present("f"),
|
||||||
bubble_inline_sizes_separately: bubble_inline_sizes_separately,
|
bubble_inline_sizes_separately: bubble_inline_sizes_separately,
|
||||||
profile_tasks: debug_options.profile_tasks,
|
profile_tasks: debug_options.profile_tasks,
|
||||||
|
profile_script_events: debug_options.profile_script_events,
|
||||||
trace_layout: debug_options.trace_layout,
|
trace_layout: debug_options.trace_layout,
|
||||||
devtools_port: devtools_port,
|
devtools_port: devtools_port,
|
||||||
webdriver_port: webdriver_port,
|
webdriver_port: webdriver_port,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue