From 4e87a68ced1ab0cb52d8ef2521f023e224c5fc5e Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sun, 19 Mar 2017 18:22:23 -0700 Subject: [PATCH] servo: Merge #16033 - Per-document shared lock for author-origin stylesheets (from servo:per-document-locks); r=emilio Fix #16027 Source-Repo: https://github.com/servo/servo Source-Revision: 8d25dcb8b5f83728987171fe7a5b4905df741e58 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : a490cb0bdb298cfd4580da1e32427beb28e7cefd --- servo/components/layout_thread/lib.rs | 222 +++++++++++++----------- servo/components/script/dom/document.rs | 3 +- servo/components/style/servo/mod.rs | 10 -- 3 files changed, 117 insertions(+), 118 deletions(-) diff --git a/servo/components/layout_thread/lib.rs b/servo/components/layout_thread/lib.rs index 1ebee7b5ead2..31500461fa4f 100644 --- a/servo/components/layout_thread/lib.rs +++ b/servo/components/layout_thread/lib.rs @@ -114,7 +114,6 @@ use style::error_reporting::StdoutErrorReporter; use style::logical_geometry::LogicalPoint; use style::media_queries::{Device, MediaType}; use style::parser::ParserContextExtraData; -use style::servo::AUTHOR_SHARED_LOCK; use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION, STORE_OVERFLOW}; use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards}; use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets}; @@ -190,6 +189,9 @@ pub struct LayoutThread { /// The root of the flow tree. root_flow: Option, + /// The document-specific shared lock used for author-origin stylesheets + document_shared_lock: Option, + /// The list of currently-running animations. running_animations: Arc>>>, @@ -442,6 +444,7 @@ impl LayoutThread { new_animations_receiver: new_animations_receiver, outstanding_web_fonts: outstanding_web_fonts_counter, root_flow: None, + document_shared_lock: None, running_animations: Arc::new(RwLock::new(HashMap::new())), expired_animations: Arc::new(RwLock::new(HashMap::new())), epoch: Epoch(0), @@ -1020,7 +1023,9 @@ impl LayoutThread { // Calculate the actual viewport as per DEVICE-ADAPT ยง 6 - let author_guard = document.style_shared_lock().read(); + let document_shared_lock = document.style_shared_lock(); + self.document_shared_lock = Some(document_shared_lock.clone()); + let author_guard = document_shared_lock.read(); let device = Device::new(MediaType::Screen, initial_viewport); Arc::get_mut(&mut rw_data.stylist).unwrap() .set_device(device, &author_guard, &data.document_stylesheets); @@ -1189,11 +1194,14 @@ impl LayoutThread { unsafe { layout_context.style_context.stylist.rule_tree.maybe_gc(); } // Perform post-style recalculation layout passes. - self.perform_post_style_recalc_layout_passes(&data.reflow_info, - Some(&data.query_type), - Some(&document), - &mut rw_data, - &mut layout_context); + if let Some(mut root_flow) = self.root_flow.clone() { + self.perform_post_style_recalc_layout_passes(&mut root_flow, + &data.reflow_info, + Some(&data.query_type), + Some(&document), + &mut rw_data, + &mut layout_context); + } self.respond_to_query_if_necessary(&data.query_type, &mut *rw_data, @@ -1346,123 +1354,125 @@ impl LayoutThread { println!("**** pipeline={}\tForDisplay\tSpecial\tAnimationTick", self.id); } - let reflow_info = Reflow { - goal: ReflowGoal::ForDisplay, - page_clip_rect: max_rect(), - }; - - let author_guard = AUTHOR_SHARED_LOCK.read(); - let ua_or_user_guard = UA_STYLESHEETS.shared_lock.read(); - let guards = StylesheetGuards { - author: &author_guard, - ua_or_user: &ua_or_user_guard, - }; - let mut layout_context = self.build_layout_context(guards, &*rw_data, false); - if let Some(mut root_flow) = self.root_flow.clone() { - // Perform an abbreviated style recalc that operates without access to the DOM. - let animations = self.running_animations.read(); - profile(time::ProfilerCategory::LayoutStyleRecalc, - self.profiler_metadata(), - self.time_profiler_chan.clone(), - || { - animation::recalc_style_for_animations(&layout_context, - FlowRef::deref_mut(&mut root_flow), - &animations) - }); + let reflow_info = Reflow { + goal: ReflowGoal::ForDisplay, + page_clip_rect: max_rect(), + }; + + // Unwrap here should not panic since self.root_flow is only ever set to Some(_) + // in handle_reflow() where self.document_shared_lock is as well. + let author_shared_lock = self.document_shared_lock.clone().unwrap(); + let author_guard = author_shared_lock.read(); + let ua_or_user_guard = UA_STYLESHEETS.shared_lock.read(); + let guards = StylesheetGuards { + author: &author_guard, + ua_or_user: &ua_or_user_guard, + }; + let mut layout_context = self.build_layout_context(guards, &*rw_data, false); + + { + // Perform an abbreviated style recalc that operates without access to the DOM. + let animations = self.running_animations.read(); + profile(time::ProfilerCategory::LayoutStyleRecalc, + self.profiler_metadata(), + self.time_profiler_chan.clone(), + || { + animation::recalc_style_for_animations( + &layout_context, FlowRef::deref_mut(&mut root_flow), &animations) + }); + } + self.perform_post_style_recalc_layout_passes(&mut root_flow, + &reflow_info, + None, + None, + &mut *rw_data, + &mut layout_context); + assert!(layout_context.pending_images.is_none()); } - - self.perform_post_style_recalc_layout_passes(&reflow_info, - None, - None, - &mut *rw_data, - &mut layout_context); - - assert!(layout_context.pending_images.is_none()); } fn perform_post_style_recalc_layout_passes(&mut self, + root_flow: &mut FlowRef, data: &Reflow, query_type: Option<&ReflowQueryType>, document: Option<&ServoLayoutDocument>, rw_data: &mut LayoutThreadData, context: &mut LayoutContext) { - if let Some(mut root_flow) = self.root_flow.clone() { - // Kick off animations if any were triggered, expire completed ones. - animation::update_animation_state(&self.constellation_chan, - &self.script_chan, - &mut *self.running_animations.write(), - &mut *self.expired_animations.write(), - &self.new_animations_receiver, - self.id, - &self.timer); + // Kick off animations if any were triggered, expire completed ones. + animation::update_animation_state(&self.constellation_chan, + &self.script_chan, + &mut *self.running_animations.write(), + &mut *self.expired_animations.write(), + &self.new_animations_receiver, + self.id, + &self.timer); - profile(time::ProfilerCategory::LayoutRestyleDamagePropagation, + profile(time::ProfilerCategory::LayoutRestyleDamagePropagation, + self.profiler_metadata(), + self.time_profiler_chan.clone(), + || { + // Call `compute_layout_damage` even in non-incremental mode, because it sets flags + // that are needed in both incremental and non-incremental traversals. + let damage = FlowRef::deref_mut(root_flow).compute_layout_damage(); + + if opts::get().nonincremental_layout || damage.contains(REFLOW_ENTIRE_DOCUMENT) { + FlowRef::deref_mut(root_flow).reflow_entire_document() + } + }); + + if opts::get().trace_layout { + layout_debug::begin_trace(root_flow.clone()); + } + + // Resolve generated content. + profile(time::ProfilerCategory::LayoutGeneratedContent, + self.profiler_metadata(), + self.time_profiler_chan.clone(), + || sequential::resolve_generated_content(FlowRef::deref_mut(root_flow), &context)); + + // Guess float placement. + profile(time::ProfilerCategory::LayoutFloatPlacementSpeculation, + self.profiler_metadata(), + self.time_profiler_chan.clone(), + || sequential::guess_float_placement(FlowRef::deref_mut(root_flow))); + + // Perform the primary layout passes over the flow tree to compute the locations of all + // the boxes. + if flow::base(&**root_flow).restyle_damage.intersects(REFLOW | REFLOW_OUT_OF_FLOW) { + profile(time::ProfilerCategory::LayoutMain, self.profiler_metadata(), self.time_profiler_chan.clone(), || { - // Call `compute_layout_damage` even in non-incremental mode, because it sets flags - // that are needed in both incremental and non-incremental traversals. - let damage = FlowRef::deref_mut(&mut root_flow).compute_layout_damage(); + let profiler_metadata = self.profiler_metadata(); - if opts::get().nonincremental_layout || damage.contains(REFLOW_ENTIRE_DOCUMENT) { - FlowRef::deref_mut(&mut root_flow).reflow_entire_document() + if let (true, Some(traversal)) = (self.parallel_flag, self.parallel_traversal.as_mut()) { + // Parallel mode. + LayoutThread::solve_constraints_parallel(traversal, + FlowRef::deref_mut(root_flow), + profiler_metadata, + self.time_profiler_chan.clone(), + &*context); + } else { + //Sequential mode + LayoutThread::solve_constraints(FlowRef::deref_mut(root_flow), &context) } }); - - if opts::get().trace_layout { - layout_debug::begin_trace(root_flow.clone()); - } - - // Resolve generated content. - profile(time::ProfilerCategory::LayoutGeneratedContent, - self.profiler_metadata(), - self.time_profiler_chan.clone(), - || sequential::resolve_generated_content(FlowRef::deref_mut(&mut root_flow), &context)); - - // Guess float placement. - profile(time::ProfilerCategory::LayoutFloatPlacementSpeculation, - self.profiler_metadata(), - self.time_profiler_chan.clone(), - || sequential::guess_float_placement(FlowRef::deref_mut(&mut root_flow))); - - // Perform the primary layout passes over the flow tree to compute the locations of all - // the boxes. - if flow::base(&*root_flow).restyle_damage.intersects(REFLOW | REFLOW_OUT_OF_FLOW) { - profile(time::ProfilerCategory::LayoutMain, - self.profiler_metadata(), - self.time_profiler_chan.clone(), - || { - let profiler_metadata = self.profiler_metadata(); - - if let (true, Some(traversal)) = (self.parallel_flag, self.parallel_traversal.as_mut()) { - // Parallel mode. - LayoutThread::solve_constraints_parallel(traversal, - FlowRef::deref_mut(&mut root_flow), - profiler_metadata, - self.time_profiler_chan.clone(), - &*context); - } else { - //Sequential mode - LayoutThread::solve_constraints(FlowRef::deref_mut(&mut root_flow), &context) - } - }); - } - - profile(time::ProfilerCategory::LayoutStoreOverflow, - self.profiler_metadata(), - self.time_profiler_chan.clone(), - || { - sequential::store_overflow(context, - FlowRef::deref_mut(&mut root_flow) as &mut Flow); - }); - - self.perform_post_main_layout_passes(data, - query_type, - document, - rw_data, - context); } + + profile(time::ProfilerCategory::LayoutStoreOverflow, + self.profiler_metadata(), + self.time_profiler_chan.clone(), + || { + sequential::store_overflow(context, + FlowRef::deref_mut(root_flow) as &mut Flow); + }); + + self.perform_post_main_layout_passes(data, + query_type, + document, + rw_data, + context); } fn perform_post_main_layout_passes(&mut self, diff --git a/servo/components/script/dom/document.rs b/servo/components/script/dom/document.rs index b875c75d8371..7a50fe5cf6c0 100644 --- a/servo/components/script/dom/document.rs +++ b/servo/components/script/dom/document.rs @@ -134,7 +134,6 @@ use style::attr::AttrValue; use style::context::{QuirksMode, ReflowGoal}; use style::restyle_hints::{RestyleHint, RESTYLE_STYLE_ATTRIBUTE}; use style::selector_parser::{RestyleDamage, Snapshot}; -use style::servo::AUTHOR_SHARED_LOCK; use style::shared_lock::SharedRwLock as StyleSharedRwLock; use style::str::{HTML_SPACE_CHARACTERS, split_html_space_chars, str_join}; use style::stylesheets::Stylesheet; @@ -2132,7 +2131,7 @@ impl Document { scripts: Default::default(), anchors: Default::default(), applets: Default::default(), - style_shared_lock: AUTHOR_SHARED_LOCK.clone(), + style_shared_lock: StyleSharedRwLock::new(), stylesheets: DOMRefCell::new(None), stylesheets_changed_since_reflow: Cell::new(false), stylesheet_list: MutNullableJS::new(None), diff --git a/servo/components/style/servo/mod.rs b/servo/components/style/servo/mod.rs index ff6890658d38..ad741616eeb7 100644 --- a/servo/components/style/servo/mod.rs +++ b/servo/components/style/servo/mod.rs @@ -9,13 +9,3 @@ pub mod media_queries; pub mod restyle_damage; pub mod selector_parser; - -use shared_lock::SharedRwLock; - -lazy_static! { - /// Per-process shared lock for author-origin stylesheets - /// - /// FIXME: make it per-document or per-pipeline instead: - /// https://github.com/servo/servo/issues/16027 - pub static ref AUTHOR_SHARED_LOCK: SharedRwLock = SharedRwLock::new(); -}