mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
style: Ensure sequential tasks run after the bloom filter is dropped.
MozReview-Commit-ID: 3LjiPP7THg7
This commit is contained in:
parent
1c85c55d02
commit
af36ce2ae1
1 changed files with 48 additions and 12 deletions
|
@ -23,7 +23,7 @@ use selectors::matching::ElementSelectorFlags;
|
||||||
use shared_lock::StylesheetGuards;
|
use shared_lock::StylesheetGuards;
|
||||||
use sharing::StyleSharingCandidateCache;
|
use sharing::StyleSharingCandidateCache;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Add;
|
use std::ops;
|
||||||
#[cfg(feature = "servo")] use std::sync::Mutex;
|
#[cfg(feature = "servo")] use std::sync::Mutex;
|
||||||
#[cfg(feature = "servo")] use std::sync::mpsc::Sender;
|
#[cfg(feature = "servo")] use std::sync::mpsc::Sender;
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
|
@ -306,7 +306,7 @@ pub struct TraversalStatistics {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of Add to aggregate statistics across different threads.
|
/// Implementation of Add to aggregate statistics across different threads.
|
||||||
impl<'a> Add for &'a TraversalStatistics {
|
impl<'a> ops::Add for &'a TraversalStatistics {
|
||||||
type Output = TraversalStatistics;
|
type Output = TraversalStatistics;
|
||||||
fn add(self, other: Self) -> TraversalStatistics {
|
fn add(self, other: Self) -> TraversalStatistics {
|
||||||
debug_assert!(self.traversal_time_ms == 0.0 && other.traversal_time_ms == 0.0,
|
debug_assert!(self.traversal_time_ms == 0.0 && other.traversal_time_ms == 0.0,
|
||||||
|
@ -505,6 +505,43 @@ impl<E: TElement> SelectorFlagsMap<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A list of SequentialTasks that get executed on Drop.
|
||||||
|
pub struct SequentialTaskList<E>(Vec<SequentialTask<E>>)
|
||||||
|
where
|
||||||
|
E: TElement;
|
||||||
|
|
||||||
|
impl<E> ops::Deref for SequentialTaskList<E>
|
||||||
|
where
|
||||||
|
E: TElement,
|
||||||
|
{
|
||||||
|
type Target = Vec<SequentialTask<E>>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E> ops::DerefMut for SequentialTaskList<E>
|
||||||
|
where
|
||||||
|
E: TElement,
|
||||||
|
{
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E> Drop for SequentialTaskList<E>
|
||||||
|
where
|
||||||
|
E: TElement,
|
||||||
|
{
|
||||||
|
fn drop(&mut self) {
|
||||||
|
debug_assert!(thread_state::get() == thread_state::LAYOUT);
|
||||||
|
for task in self.0.drain(..) {
|
||||||
|
task.execute()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A thread-local style context.
|
/// A thread-local style context.
|
||||||
///
|
///
|
||||||
/// This context contains data that needs to be used during restyling, but is
|
/// This context contains data that needs to be used during restyling, but is
|
||||||
|
@ -520,9 +557,13 @@ pub struct ThreadLocalStyleContext<E: TElement> {
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
pub new_animations_sender: Sender<Animation>,
|
pub new_animations_sender: Sender<Animation>,
|
||||||
/// A set of tasks to be run (on the parent thread) in sequential mode after
|
/// A set of tasks to be run (on the parent thread) in sequential mode after
|
||||||
/// the rest of the styling is complete. This is useful for infrequently-needed
|
/// the rest of the styling is complete. This is useful for
|
||||||
/// non-threadsafe operations.
|
/// infrequently-needed non-threadsafe operations.
|
||||||
pub tasks: Vec<SequentialTask<E>>,
|
///
|
||||||
|
/// It's important that goes after the style sharing cache and the bloom
|
||||||
|
/// filter, to ensure they're dropped before we execute the tasks, which
|
||||||
|
/// could create another ThreadLocalStyleContext for style computation.
|
||||||
|
pub tasks: SequentialTaskList<E>,
|
||||||
/// ElementSelectorFlags that need to be applied after the traversal is
|
/// ElementSelectorFlags that need to be applied after the traversal is
|
||||||
/// complete. This map is used in cases where the matching algorithm needs
|
/// complete. This map is used in cases where the matching algorithm needs
|
||||||
/// to set flags on elements it doesn't have exclusive access to (i.e. other
|
/// to set flags on elements it doesn't have exclusive access to (i.e. other
|
||||||
|
@ -545,7 +586,7 @@ impl<E: TElement> ThreadLocalStyleContext<E> {
|
||||||
style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
|
style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
|
||||||
bloom_filter: StyleBloom::new(),
|
bloom_filter: StyleBloom::new(),
|
||||||
new_animations_sender: shared.local_context_creation_data.lock().unwrap().new_animations_sender.clone(),
|
new_animations_sender: shared.local_context_creation_data.lock().unwrap().new_animations_sender.clone(),
|
||||||
tasks: Vec::new(),
|
tasks: SequentialTaskList(Vec::new()),
|
||||||
selector_flags: SelectorFlagsMap::new(),
|
selector_flags: SelectorFlagsMap::new(),
|
||||||
statistics: TraversalStatistics::default(),
|
statistics: TraversalStatistics::default(),
|
||||||
current_element_info: None,
|
current_element_info: None,
|
||||||
|
@ -559,7 +600,7 @@ impl<E: TElement> ThreadLocalStyleContext<E> {
|
||||||
ThreadLocalStyleContext {
|
ThreadLocalStyleContext {
|
||||||
style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
|
style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
|
||||||
bloom_filter: StyleBloom::new(),
|
bloom_filter: StyleBloom::new(),
|
||||||
tasks: Vec::new(),
|
tasks: SequentialTaskList(Vec::new()),
|
||||||
selector_flags: SelectorFlagsMap::new(),
|
selector_flags: SelectorFlagsMap::new(),
|
||||||
statistics: TraversalStatistics::default(),
|
statistics: TraversalStatistics::default(),
|
||||||
current_element_info: None,
|
current_element_info: None,
|
||||||
|
@ -601,11 +642,6 @@ impl<E: TElement> Drop for ThreadLocalStyleContext<E> {
|
||||||
|
|
||||||
// Apply any slow selector flags that need to be set on parents.
|
// Apply any slow selector flags that need to be set on parents.
|
||||||
self.selector_flags.apply_flags();
|
self.selector_flags.apply_flags();
|
||||||
|
|
||||||
// Execute any enqueued sequential tasks.
|
|
||||||
for task in self.tasks.drain(..) {
|
|
||||||
task.execute();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue