Skip to content
Permalink
Browse files

style: Remove the Mutex from new_animations_sender by moving it to th…

…e local StyleContext.

As a follow-up, we could move all the data living under a mutex in the
SharedLayoutContext only in order to create the local context to the same place.

This should increase animation performance when there are multiple animations in
one page that happen to be on different threads.
  • Loading branch information
emilio committed Jul 1, 2016
1 parent 5478e60 commit 203d2a62c24ca3d8b07e4ec492fc53bb30bbeedc
@@ -25,15 +25,14 @@ use std::hash::BuildHasherDefault;
use std::rc::Rc;
use std::sync::{Arc, Mutex, RwLock};
use style::context::{LocalStyleContext, StyleContext};
use style::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};
use style::properties::ServoComputedValues;
use style::selector_impl::ServoSelectorImpl;
use style::servo::SharedStyleContext;
use url::Url;
use util::opts;

struct LocalLayoutContext {
style_context: LocalStyleContext<ServoComputedValues>,
style_context: LocalStyleContext<ServoSelectorImpl>,

font_context: RefCell<FontContext>,
}

@@ -64,11 +63,10 @@ fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext)
context
} else {
let font_cache_thread = shared_layout_context.font_cache_thread.lock().unwrap().clone();
let local_style_data = shared_layout_context.style_context.local_context_creation_data.lock().unwrap();

let context = Rc::new(LocalLayoutContext {
style_context: LocalStyleContext {
applicable_declarations_cache: RefCell::new(ApplicableDeclarationsCache::new()),
style_sharing_candidate_cache: RefCell::new(StyleSharingCandidateCache::new()),
},
style_context: LocalStyleContext::new(&local_style_data),
font_context: RefCell::new(FontContext::new(font_cache_thread)),
});
*r = Some(context.clone());
@@ -110,7 +108,7 @@ impl<'a> StyleContext<'a, ServoSelectorImpl> for LayoutContext<'a> {
&self.shared.style_context
}

fn local_context(&self) -> &LocalStyleContext<ServoComputedValues> {
fn local_context(&self) -> &LocalStyleContext<ServoSelectorImpl> {
&self.cached_local_layout_context.style_context
}
}
@@ -108,7 +108,7 @@ use style::parallel::WorkQueueData;
use style::properties::ComputedValues;
use style::refcell::RefCell;
use style::selector_matching::USER_OR_USER_AGENT_STYLESHEETS;
use style::servo::{Animation, SharedStyleContext, Stylesheet, Stylist};
use style::servo::{Animation, LocalStyleContextCreationInfo, SharedStyleContext, Stylesheet, Stylist};
use style::stylesheets::CSSRuleIteratorExt;
use url::Url;
use util::geometry::MAX_RECT;
@@ -488,17 +488,19 @@ impl LayoutThread {
screen_size_changed: bool,
goal: ReflowGoal)
-> SharedLayoutContext {
let local_style_context_creation_data = LocalStyleContextCreationInfo::new(self.new_animations_sender.clone());

SharedLayoutContext {
style_context: SharedStyleContext {
viewport_size: self.viewport_size.clone(),
screen_size_changed: screen_size_changed,
stylist: rw_data.stylist.clone(),
generation: self.generation,
goal: goal,
new_animations_sender: Mutex::new(self.new_animations_sender.clone()),
running_animations: self.running_animations.clone(),
expired_animations: self.expired_animations.clone(),
error_reporter: self.error_reporter.clone(),
local_context_creation_data: Mutex::new(local_style_context_creation_data),
},
image_cache_thread: self.image_cache_thread.clone(),
image_cache_sender: Mutex::new(self.image_cache_sender.clone()),
@@ -19,8 +19,8 @@ use properties::style_struct_traits::Box;
use properties::{self, ComputedValues};
use selector_impl::SelectorImplExt;
use selectors::matching::DeclarationBlock;
use std::sync::Arc;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use string_cache::Atom;
use time;
use values::computed::Time;
@@ -356,7 +356,7 @@ impl<T> GetMod for Vec<T> {
//
// TODO(emilio): Take rid of this mutex splitting SharedLayoutContex into a
// cloneable part and a non-cloneable part..
pub fn start_transitions_if_applicable<Impl: SelectorImplExt>(new_animations_sender: &Mutex<Sender<Animation<Impl>>>,
pub fn start_transitions_if_applicable<Impl: SelectorImplExt>(new_animations_sender: &Sender<Animation<Impl>>,
node: OpaqueNode,
old_style: &Impl::ComputedValues,
new_style: &mut Arc<Impl::ComputedValues>)
@@ -377,7 +377,6 @@ pub fn start_transitions_if_applicable<Impl: SelectorImplExt>(new_animations_sen
let start_time =
now + (box_style.transition_delay.0.get_mod(i).seconds() as f64);
new_animations_sender
.lock().unwrap()
.send(Animation::Transition(node, start_time, AnimationFrame {
duration: box_style.transition_duration.0.get_mod(i).seconds() as f64,
property_animation: property_animation,
@@ -417,6 +416,7 @@ fn compute_style_for_animation_step<Impl: SelectorImplExt>(context: &SharedStyle
}

pub fn maybe_start_animations<Impl: SelectorImplExt>(context: &SharedStyleContext<Impl>,
new_animations_sender: &Sender<Animation<Impl>>,
node: OpaqueNode,
new_style: &Arc<Impl::ComputedValues>) -> bool
{
@@ -465,19 +465,18 @@ pub fn maybe_start_animations<Impl: SelectorImplExt>(context: &SharedStyleContex
};


context.new_animations_sender
.lock().unwrap()
.send(Animation::Keyframes(node, name.clone(), KeyframesAnimationState {
started_at: animation_start,
duration: duration as f64,
delay: delay as f64,
iteration_state: iteration_state,
running_state: running_state,
direction: animation_direction,
current_direction: initial_direction,
expired: false,
cascade_style: new_style.clone(),
})).unwrap();
new_animations_sender
.send(Animation::Keyframes(node, name.clone(), KeyframesAnimationState {
started_at: animation_start,
duration: duration as f64,
delay: delay as f64,
iteration_state: iteration_state,
running_state: running_state,
direction: animation_direction,
current_direction: initial_direction,
expired: false,
cascade_style: new_style.clone(),
})).unwrap();
had_animations = true;
}
}
@@ -10,14 +10,26 @@ use dom::OpaqueNode;
use error_reporting::ParseErrorReporter;
use euclid::Size2D;
use matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};
use properties::ComputedValues;
use selector_impl::SelectorImplExt;
use selector_matching::Stylist;
use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex, RwLock};

/// This structure is used to create a local style context from a shared one.
pub struct LocalStyleContextCreationInfo<Impl: SelectorImplExt> {
new_animations_sender: Sender<Animation<Impl>>,
}

impl<Impl: SelectorImplExt> LocalStyleContextCreationInfo<Impl> {
pub fn new(animations_sender: Sender<Animation<Impl>>) -> Self {
LocalStyleContextCreationInfo {
new_animations_sender: animations_sender,
}
}
}

pub struct SharedStyleContext<Impl: SelectorImplExt> {
/// The current viewport size.
pub viewport_size: Size2D<Au>,
@@ -32,10 +44,6 @@ pub struct SharedStyleContext<Impl: SelectorImplExt> {
/// This can be used to easily check for invalid stale data.
pub generation: u32,

/// A channel on which new animations that have been triggered by style recalculation can be
/// sent.
pub new_animations_sender: Mutex<Sender<Animation<Impl>>>,

/// Why is this reflow occurring
pub goal: ReflowGoal,

@@ -47,16 +55,32 @@ pub struct SharedStyleContext<Impl: SelectorImplExt> {

///The CSS error reporter for all CSS loaded in this layout thread
pub error_reporter: Box<ParseErrorReporter + Sync>,

/// Data needed to create the local style context from the shared one.
pub local_context_creation_data: Mutex<LocalStyleContextCreationInfo<Impl>>,
}

pub struct LocalStyleContext<Impl: SelectorImplExt> {
pub applicable_declarations_cache: RefCell<ApplicableDeclarationsCache<Impl::ComputedValues>>,
pub style_sharing_candidate_cache: RefCell<StyleSharingCandidateCache<Impl::ComputedValues>>,
/// A channel on which new animations that have been triggered by style
/// recalculation can be sent.
pub new_animations_sender: Sender<Animation<Impl>>,
}

pub struct LocalStyleContext<C: ComputedValues> {
pub applicable_declarations_cache: RefCell<ApplicableDeclarationsCache<C>>,
pub style_sharing_candidate_cache: RefCell<StyleSharingCandidateCache<C>>,
impl<Impl: SelectorImplExt> LocalStyleContext<Impl> {
pub fn new(local_context_creation_data: &LocalStyleContextCreationInfo<Impl>) -> Self {
LocalStyleContext {
applicable_declarations_cache: RefCell::new(ApplicableDeclarationsCache::new()),
style_sharing_candidate_cache: RefCell::new(StyleSharingCandidateCache::new()),
new_animations_sender: local_context_creation_data.new_animations_sender.clone(),
}
}
}

pub trait StyleContext<'a, Impl: SelectorImplExt> {
fn shared_context(&self) -> &'a SharedStyleContext<Impl>;
fn local_context(&self) -> &LocalStyleContext<Impl::ComputedValues>;
fn local_context(&self) -> &LocalStyleContext<Impl>;
}

/// Why we're doing reflow.
@@ -7,7 +7,7 @@
#![allow(unsafe_code)]

use animation::{self, Animation};
use context::{SharedStyleContext, LocalStyleContext};
use context::{StyleContext, SharedStyleContext};
use data::PrivateStyleData;
use dom::{TElement, TNode, TRestyleDamage};
use properties::{ComputedValues, PropertyDeclaration, cascade};
@@ -371,19 +371,22 @@ trait PrivateMatchMethods: TNode
///
/// Note that animations only apply to nodes or ::before or ::after
/// pseudo-elements.
fn cascade_node_pseudo_element(&self,
context: &SharedStyleContext<<Self::ConcreteElement as Element>::Impl>,
parent_style: Option<&Arc<Self::ConcreteComputedValues>>,
applicable_declarations: &[DeclarationBlock],
mut style: Option<&mut Arc<Self::ConcreteComputedValues>>,
applicable_declarations_cache:
&mut ApplicableDeclarationsCache<Self::ConcreteComputedValues>,
shareable: bool,
animate_properties: bool)
-> (Self::ConcreteRestyleDamage, Arc<Self::ConcreteComputedValues>) {
fn cascade_node_pseudo_element<'a, Ctx>(&self,
context: &Ctx,
parent_style: Option<&Arc<Self::ConcreteComputedValues>>,
applicable_declarations: &[DeclarationBlock],
mut style: Option<&mut Arc<Self::ConcreteComputedValues>>,
applicable_declarations_cache:
&mut ApplicableDeclarationsCache<Self::ConcreteComputedValues>,
shareable: bool,
animate_properties: bool)
-> (Self::ConcreteRestyleDamage, Arc<Self::ConcreteComputedValues>)
where Ctx: StyleContext<'a, <Self::ConcreteElement as Element>::Impl> {
let mut cacheable = true;
let shared_context = context.shared_context();
if animate_properties {
cacheable = !self.update_animations_for_cascade(context, &mut style) && cacheable;
cacheable = !self.update_animations_for_cascade(shared_context,
&mut style) && cacheable;
}

let this_style;
@@ -395,22 +398,22 @@ trait PrivateMatchMethods: TNode
None => None,
};

let (the_style, is_cacheable) = cascade(context.viewport_size,
let (the_style, is_cacheable) = cascade(shared_context.viewport_size,
applicable_declarations,
shareable,
Some(&***parent_style),
cached_computed_values,
context.error_reporter.clone());
shared_context.error_reporter.clone());
cacheable = cacheable && is_cacheable;
this_style = the_style
}
None => {
let (the_style, is_cacheable) = cascade(context.viewport_size,
let (the_style, is_cacheable) = cascade(shared_context.viewport_size,
applicable_declarations,
shareable,
None,
None,
context.error_reporter.clone());
shared_context.error_reporter.clone());
cacheable = cacheable && is_cacheable;
this_style = the_style
}
@@ -419,10 +422,12 @@ trait PrivateMatchMethods: TNode
let mut this_style = Arc::new(this_style);

if animate_properties {
let new_animations_sender = &context.local_context().new_animations_sender;
let this_opaque = self.opaque();
// Trigger any present animations if necessary.
let mut animations_started = animation::maybe_start_animations::<<Self::ConcreteElement as Element>::Impl>(
&context,
&shared_context,
new_animations_sender,
this_opaque,
&this_style);

@@ -431,7 +436,7 @@ trait PrivateMatchMethods: TNode
if let Some(ref style) = style {
animations_started |=
animation::start_transitions_if_applicable::<<Self::ConcreteElement as Element>::Impl>(
&context.new_animations_sender,
new_animations_sender,
this_opaque,
&**style,
&mut this_style);
@@ -658,12 +663,13 @@ pub trait MatchMethods : TNode {
}
}

unsafe fn cascade_node(&self,
context: &SharedStyleContext<<Self::ConcreteElement as Element>::Impl>,
local_context: &LocalStyleContext<Self::ConcreteComputedValues>,
parent: Option<Self>,
applicable_declarations: &ApplicableDeclarations<<Self::ConcreteElement as Element>::Impl>)
where <Self::ConcreteElement as Element>::Impl: SelectorImplExt<ComputedValues = Self::ConcreteComputedValues>
unsafe fn cascade_node<'a, Ctx>(&self,
context: &Ctx,
parent: Option<Self>,
applicable_declarations:
&ApplicableDeclarations<<Self::ConcreteElement as Element>::Impl>)
where <Self::ConcreteElement as Element>::Impl: SelectorImplExt<ComputedValues = Self::ConcreteComputedValues>,
Ctx: StyleContext<'a, <Self::ConcreteElement as Element>::Impl>
{
// Get our parent's style. This must be unsafe so that we don't touch the parent's
// borrow flags.
@@ -679,7 +685,7 @@ pub trait MatchMethods : TNode {
};

let mut applicable_declarations_cache =
local_context.applicable_declarations_cache.borrow_mut();
context.local_context().applicable_declarations_cache.borrow_mut();

let damage;
if self.is_text_node() {
@@ -45,7 +45,7 @@ pub fn traverse_dom<N, C>(root: N,
where N: TNode, C: DomTraversalContext<N> {
run_queue_with_custom_work_data_type(queue, |queue| {
queue.push(WorkUnit {
fun: top_down_dom::<N, C>,
fun: top_down_dom::<N, C>,
data: (Box::new(vec![root.to_unsafe()]), root.opaque()),
});
}, queue_data);
@@ -65,7 +65,7 @@ pub trait ElementExt: Element {

// NB: The `Clone` trait is here for convenience due to:
// https://github.com/rust-lang/rust/issues/26925
pub trait SelectorImplExt : SelectorImpl + Clone + Debug + Sized {
pub trait SelectorImplExt : SelectorImpl + Clone + Debug + Sized + 'static {
type ComputedValues: properties::ComputedValues;

fn pseudo_element_cascade_type(pseudo: &Self::PseudoElement) -> PseudoElementCascadeType;
@@ -15,4 +15,5 @@ pub type Stylesheet = stylesheets::Stylesheet<ServoSelectorImpl>;
pub type PrivateStyleData = data::PrivateStyleData<ServoSelectorImpl, ServoComputedValues>;
pub type Stylist = selector_matching::Stylist<ServoSelectorImpl>;
pub type SharedStyleContext = context::SharedStyleContext<ServoSelectorImpl>;
pub type LocalStyleContextCreationInfo = context::LocalStyleContextCreationInfo<ServoSelectorImpl>;
pub type Animation = animation::Animation<ServoSelectorImpl>;
@@ -218,8 +218,7 @@ pub fn recalc_style_at<'a, N, C>(context: &'a C,

// Perform the CSS cascade.
unsafe {
node.cascade_node(&context.shared_context(),
&context.local_context(),
node.cascade_node(context,
parent_opt,
&applicable_declarations);
}

0 comments on commit 203d2a6

Please sign in to comment.
You can’t perform that action at this time.