Store microtask queues in their global (fixes #18467)

This commit is contained in:
Anthony Ramine 2017-09-13 10:48:39 +02:00
parent 7481ce177f
commit 24cf15a014
7 changed files with 29 additions and 78 deletions

View file

@ -247,7 +247,7 @@ impl DedicatedWorkerGlobalScope {
global.handle_event(event); global.handle_event(event);
// Step 6 // Step 6
let _ar = AutoWorkerReset::new(&global, worker.clone()); let _ar = AutoWorkerReset::new(&global, worker.clone());
global.upcast::<WorkerGlobalScope>().perform_a_microtask_checkpoint(); global.upcast::<GlobalScope>().perform_a_microtask_checkpoint();
} }
}, reporter_name, parent_sender, CommonScriptMsg::CollectReports); }, reporter_name, parent_sender, CommonScriptMsg::CollectReports);
}).expect("Thread spawning failed"); }).expect("Thread spawning failed");

View file

@ -63,6 +63,9 @@ impl DissimilarOriginWindow {
global_to_clone_from.resource_threads().clone(), global_to_clone_from.resource_threads().clone(),
timer_event_chan, timer_event_chan,
global_to_clone_from.origin().clone(), global_to_clone_from.origin().clone(),
// FIXME(nox): The microtask queue is probably not important
// here, but this whole DOM interface is a hack anyway.
global_to_clone_from.microtask_queue().clone(),
), ),
window_proxy: JS::from_ref(window_proxy), window_proxy: JS::from_ref(window_proxy),
location: Default::default(), location: Default::default(),

View file

@ -33,7 +33,7 @@ use js::jsapi::{JS_GetObjectRuntime, MutableHandleValue};
use js::panic::maybe_resume_unwind; use js::panic::maybe_resume_unwind;
use js::rust::{CompileOptionsWrapper, Runtime, get_object_class}; use js::rust::{CompileOptionsWrapper, Runtime, get_object_class};
use libc; use libc;
use microtask::Microtask; use microtask::{Microtask, MicrotaskQueue};
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use net_traits::{CoreResourceThread, ResourceThreads, IpcSend}; use net_traits::{CoreResourceThread, ResourceThreads, IpcSend};
use profile_traits::{mem, time}; use profile_traits::{mem, time};
@ -46,6 +46,7 @@ use std::cell::Cell;
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::ffi::CString; use std::ffi::CString;
use std::rc::Rc;
use task_source::file_reading::FileReadingTaskSource; use task_source::file_reading::FileReadingTaskSource;
use task_source::networking::NetworkingTaskSource; use task_source::networking::NetworkingTaskSource;
use task_source::performance_timeline::PerformanceTimelineTaskSource; use task_source::performance_timeline::PerformanceTimelineTaskSource;
@ -99,6 +100,15 @@ pub struct GlobalScope {
/// The origin of the globalscope /// The origin of the globalscope
origin: MutableOrigin, origin: MutableOrigin,
/// The microtask queue associated with this global.
///
/// It is refcounted because windows in the same script thread share the
/// same microtask queue.
///
/// https://html.spec.whatwg.org/multipage/#microtask-queue
#[ignore_heap_size_of = "Rc<T> is hard"]
microtask_queue: Rc<MicrotaskQueue>,
} }
impl GlobalScope { impl GlobalScope {
@ -112,6 +122,7 @@ impl GlobalScope {
resource_threads: ResourceThreads, resource_threads: ResourceThreads,
timer_event_chan: IpcSender<TimerEvent>, timer_event_chan: IpcSender<TimerEvent>,
origin: MutableOrigin, origin: MutableOrigin,
microtask_queue: Rc<MicrotaskQueue>,
) -> Self { ) -> Self {
Self { Self {
eventtarget: EventTarget::new_inherited(), eventtarget: EventTarget::new_inherited(),
@ -129,6 +140,7 @@ impl GlobalScope {
resource_threads, resource_threads,
timers: OneshotTimers::new(timer_event_chan, scheduler_chan), timers: OneshotTimers::new(timer_event_chan, scheduler_chan),
origin, origin,
microtask_queue,
} }
} }
@ -479,30 +491,12 @@ impl GlobalScope {
/// Perform a microtask checkpoint. /// Perform a microtask checkpoint.
pub fn perform_a_microtask_checkpoint(&self) { pub fn perform_a_microtask_checkpoint(&self) {
if let Some(window) = self.downcast::<Window>() { self.microtask_queue.checkpoint(|_| Some(Root::from_ref(self)));
return window.perform_a_microtask_checkpoint();
}
if let Some(worker) = self.downcast::<WorkerGlobalScope>() {
return worker.perform_a_microtask_checkpoint();
}
if let Some(worker) = self.downcast::<WorkletGlobalScope>() {
return worker.perform_a_microtask_checkpoint();
}
unreachable!();
} }
/// Enqueue a microtask for subsequent execution. /// Enqueue a microtask for subsequent execution.
pub fn enqueue_microtask(&self, job: Microtask) { pub fn enqueue_microtask(&self, job: Microtask) {
if let Some(window) = self.downcast::<Window>() { self.microtask_queue.enqueue(job);
return window.enqueue_microtask(job);
}
if let Some(worker) = self.downcast::<WorkerGlobalScope>() {
return worker.enqueue_microtask(job);
}
if let Some(worker) = self.downcast::<WorkletGlobalScope>() {
return worker.enqueue_microtask(job);
}
unreachable!();
} }
/// Create a new sender/receiver pair that can be used to implement an on-demand /// Create a new sender/receiver pair that can be used to implement an on-demand
@ -518,6 +512,11 @@ impl GlobalScope {
unreachable!(); unreachable!();
} }
/// Returns the microtask queue of this global.
pub fn microtask_queue(&self) -> &Rc<MicrotaskQueue> {
&self.microtask_queue
}
/// Process a single event as if it were the next event /// Process a single event as if it were the next event
/// in the thread queue for this global scope. /// in the thread queue for this global scope.
pub fn process_event(&self, msg: CommonScriptMsg) { pub fn process_event(&self, msg: CommonScriptMsg) {

View file

@ -219,7 +219,7 @@ impl ServiceWorkerGlobalScope {
break; break;
} }
// Step 6 // Step 6
global.upcast::<WorkerGlobalScope>().perform_a_microtask_checkpoint(); global.upcast::<GlobalScope>().perform_a_microtask_checkpoint();
} }
}, reporter_name, scope.script_chan(), CommonScriptMsg::CollectReports); }, reporter_name, scope.script_chan(), CommonScriptMsg::CollectReports);
}).expect("Thread spawning failed"); }).expect("Thread spawning failed");

View file

@ -59,7 +59,7 @@ use js::jsapi::{JS_GC, JS_GetRuntime};
use js::jsval::UndefinedValue; use js::jsval::UndefinedValue;
use js::rust::Runtime; use js::rust::Runtime;
use layout_image::fetch_image_for_layout; use layout_image::fetch_image_for_layout;
use microtask::{Microtask, MicrotaskQueue}; use microtask::MicrotaskQueue;
use msg::constellation_msg::{FrameType, PipelineId}; use msg::constellation_msg::{FrameType, PipelineId};
use net_traits::{ResourceThreads, ReferrerPolicy}; use net_traits::{ResourceThreads, ReferrerPolicy};
use net_traits::image_cache::{ImageCache, ImageResponder, ImageResponse}; use net_traits::image_cache::{ImageCache, ImageResponder, ImageResponse};
@ -288,10 +288,6 @@ pub struct Window {
test_worklet: MutNullableJS<Worklet>, test_worklet: MutNullableJS<Worklet>,
/// https://drafts.css-houdini.org/css-paint-api-1/#paint-worklet /// https://drafts.css-houdini.org/css-paint-api-1/#paint-worklet
paint_worklet: MutNullableJS<Worklet>, paint_worklet: MutNullableJS<Worklet>,
/// https://html.spec.whatwg.org/multipage/#microtask-queue
#[ignore_heap_size_of = "Rc<T> is hard"]
microtask_queue: Rc<MicrotaskQueue>,
} }
impl Window { impl Window {
@ -1790,16 +1786,6 @@ impl Window {
.send(msg) .send(msg)
.unwrap(); .unwrap();
} }
pub fn enqueue_microtask(&self, job: Microtask) {
self.microtask_queue.enqueue(job);
}
pub fn perform_a_microtask_checkpoint(&self) {
self.microtask_queue.checkpoint(|_| {
Some(Root::from_ref(self.upcast::<GlobalScope>()))
});
}
} }
impl Window { impl Window {
@ -1855,6 +1841,7 @@ impl Window {
resource_threads, resource_threads,
timer_event_chan, timer_event_chan,
origin, origin,
microtask_queue,
), ),
script_chan, script_chan,
dom_manipulation_task_source, dom_manipulation_task_source,
@ -1906,7 +1893,6 @@ impl Window {
unminified_js_dir: Default::default(), unminified_js_dir: Default::default(),
test_worklet: Default::default(), test_worklet: Default::default(),
paint_worklet: Default::default(), paint_worklet: Default::default(),
microtask_queue,
}; };
unsafe { unsafe {

View file

@ -30,7 +30,6 @@ use js::jsapi::{HandleValue, JSAutoCompartment, JSContext, JSRuntime};
use js::jsval::UndefinedValue; use js::jsval::UndefinedValue;
use js::panic::maybe_resume_unwind; use js::panic::maybe_resume_unwind;
use js::rust::Runtime; use js::rust::Runtime;
use microtask::{MicrotaskQueue, Microtask};
use net_traits::{IpcSend, load_whole_resource}; use net_traits::{IpcSend, load_whole_resource};
use net_traits::request::{CredentialsMode, Destination, RequestInit as NetRequestInit, Type as RequestType}; use net_traits::request::{CredentialsMode, Destination, RequestInit as NetRequestInit, Type as RequestType};
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
@ -91,10 +90,6 @@ pub struct WorkerGlobalScope {
/// `IpcSender` doesn't exist /// `IpcSender` doesn't exist
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>, from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
/// https://html.spec.whatwg.org/multipage/#microtask-queue
#[ignore_heap_size_of = "Rc<T> is hard"]
microtask_queue: Rc<MicrotaskQueue>,
navigation_start_precise: f64, navigation_start_precise: f64,
performance: MutNullableJS<Performance>, performance: MutNullableJS<Performance>,
} }
@ -119,6 +114,7 @@ impl WorkerGlobalScope {
init.resource_threads, init.resource_threads,
timer_event_chan, timer_event_chan,
MutableOrigin::new(init.origin), MutableOrigin::new(init.origin),
Default::default(),
), ),
worker_id: init.worker_id, worker_id: init.worker_id,
worker_url, worker_url,
@ -128,7 +124,6 @@ impl WorkerGlobalScope {
navigator: Default::default(), navigator: Default::default(),
from_devtools_sender: init.from_devtools_sender, from_devtools_sender: init.from_devtools_sender,
from_devtools_receiver, from_devtools_receiver,
microtask_queue: Default::default(),
navigation_start_precise: precise_time_ns() as f64, navigation_start_precise: precise_time_ns() as f64,
performance: Default::default(), performance: Default::default(),
} }
@ -171,18 +166,6 @@ impl WorkerGlobalScope {
cancelled: self.closing.clone(), cancelled: self.closing.clone(),
} }
} }
pub fn enqueue_microtask(&self, job: Microtask) {
self.microtask_queue.enqueue(job);
}
pub fn perform_a_microtask_checkpoint(&self) {
self.microtask_queue.checkpoint(|id| {
let global = self.upcast::<GlobalScope>();
assert_eq!(global.pipeline_id(), id);
Some(Root::from_ref(global))
});
}
} }
impl WorkerGlobalScopeMethods for WorkerGlobalScope { impl WorkerGlobalScopeMethods for WorkerGlobalScope {

View file

@ -17,8 +17,6 @@ use ipc_channel::ipc::IpcSender;
use js::jsapi::JSContext; use js::jsapi::JSContext;
use js::jsval::UndefinedValue; use js::jsval::UndefinedValue;
use js::rust::Runtime; use js::rust::Runtime;
use microtask::Microtask;
use microtask::MicrotaskQueue;
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use net_traits::ResourceThreads; use net_traits::ResourceThreads;
use net_traits::image_cache::ImageCache; use net_traits::image_cache::ImageCache;
@ -36,7 +34,6 @@ use script_traits::TimerSchedulerMsg;
use servo_url::ImmutableOrigin; use servo_url::ImmutableOrigin;
use servo_url::MutableOrigin; use servo_url::MutableOrigin;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
@ -47,9 +44,6 @@ pub struct WorkletGlobalScope {
globalscope: GlobalScope, globalscope: GlobalScope,
/// The base URL for this worklet. /// The base URL for this worklet.
base_url: ServoUrl, base_url: ServoUrl,
/// https://html.spec.whatwg.org/multipage/#microtask-queue
#[ignore_heap_size_of = "Rc<T> is hard"]
microtask_queue: Rc<MicrotaskQueue>,
/// Sender back to the script thread /// Sender back to the script thread
#[ignore_heap_size_of = "channels are hard"] #[ignore_heap_size_of = "channels are hard"]
to_script_thread_sender: Sender<MainThreadScriptMsg>, to_script_thread_sender: Sender<MainThreadScriptMsg>,
@ -82,9 +76,9 @@ impl WorkletGlobalScope {
init.resource_threads.clone(), init.resource_threads.clone(),
timer_event_chan, timer_event_chan,
MutableOrigin::new(ImmutableOrigin::new_opaque()), MutableOrigin::new(ImmutableOrigin::new_opaque()),
Default::default(),
), ),
base_url, base_url,
microtask_queue: Default::default(),
to_script_thread_sender: init.to_script_thread_sender.clone(), to_script_thread_sender: init.to_script_thread_sender.clone(),
executor, executor,
} }
@ -133,20 +127,6 @@ impl WorkletGlobalScope {
self.executor.clone() self.executor.clone()
} }
/// Queue up a microtask to be executed in this global.
pub fn enqueue_microtask(&self, job: Microtask) {
self.microtask_queue.enqueue(job);
}
/// Perform any queued microtasks.
pub fn perform_a_microtask_checkpoint(&self) {
self.microtask_queue.checkpoint(|id| {
let global = self.upcast::<GlobalScope>();
assert_eq!(global.pipeline_id(), id);
Some(Root::from_ref(global))
});
}
/// Perform a worklet task /// Perform a worklet task
pub fn perform_a_worklet_task(&self, task: WorkletTask) { pub fn perform_a_worklet_task(&self, task: WorkletTask) {
match task { match task {