Skip to content

Commit

Permalink
style: Remove the Mutex from new_animations_sender by moving it to th…
Browse files Browse the repository at this point in the history
…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 203d2a6
Show file tree
Hide file tree
Showing 15 changed files with 166 additions and 134 deletions.
14 changes: 6 additions & 8 deletions components/layout/context.rs
Expand Up @@ -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>,
}

Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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
}
}
Expand Down
6 changes: 4 additions & 2 deletions components/layout_thread/lib.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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()),
Expand Down
31 changes: 15 additions & 16 deletions components/style/animation.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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>)
Expand All @@ -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,
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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;
}
}
Expand Down
42 changes: 33 additions & 9 deletions components/style/context.rs
Expand Up @@ -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>,
Expand All @@ -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,

Expand All @@ -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.
Expand Down
56 changes: 31 additions & 25 deletions components/style/matching.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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;
Expand All @@ -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
}
Expand All @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -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.
Expand All @@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion components/style/parallel.rs
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion components/style/selector_impl.rs
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions components/style/servo.rs
Expand Up @@ -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>;
3 changes: 1 addition & 2 deletions components/style/traversal.rs
Expand Up @@ -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);
}
Expand Down

0 comments on commit 203d2a6

Please sign in to comment.