Skip to content

Commit

Permalink
Concurrent rule tree, v1
Browse files Browse the repository at this point in the history
This patch introduces infrastructure for the rule tree, and constructs it.

We don't use it yet, nor have good heuristics for GC'ing it, but this should not
happen anymore once we store the rule node reference in the node.

I haven't messed up with memory orders because I want to do a try run with it,
then mess with them.

Take down the ApplicableDeclarationsCache, use the rule tree for doing the cascade.
  • Loading branch information
emilio authored and SimonSapin committed Nov 5, 2016
1 parent f7875da commit de4fe6e
Show file tree
Hide file tree
Showing 22 changed files with 1,068 additions and 553 deletions.
3 changes: 0 additions & 3 deletions components/layout/context.rs
Expand Up @@ -53,9 +53,6 @@ fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext)
LOCAL_CONTEXT_KEY.with(|r| { LOCAL_CONTEXT_KEY.with(|r| {
let mut r = r.borrow_mut(); let mut r = r.borrow_mut();
if let Some(context) = r.clone() { if let Some(context) = r.clone() {
if shared_layout_context.style_context.screen_size_changed {
context.style_context.applicable_declarations_cache.borrow_mut().evict_all();
}
context context
} else { } else {
let font_cache_thread = shared_layout_context.font_cache_thread.lock().unwrap().clone(); let font_cache_thread = shared_layout_context.font_cache_thread.lock().unwrap().clone();
Expand Down
10 changes: 10 additions & 0 deletions components/layout_thread/lib.rs
Expand Up @@ -1170,6 +1170,16 @@ impl LayoutThread {
node.dump_style(); node.dump_style();
} }


if opts::get().dump_rule_tree {
shared_layout_context.style_context.stylist.rule_tree.dump_stdout();
}

// GC The rule tree.
//
// FIXME(emilio): The whole point of the free list is not always freeing
// the list, find a good heuristic here for that.
unsafe { shared_layout_context.style_context.stylist.rule_tree.gc() }

// Perform post-style recalculation layout passes. // Perform post-style recalculation layout passes.
self.perform_post_style_recalc_layout_passes(&data.reflow_info, self.perform_post_style_recalc_layout_passes(&data.reflow_info,
Some(&data.query_type), Some(&data.query_type),
Expand Down
10 changes: 2 additions & 8 deletions components/script/dom/element.rs
Expand Up @@ -328,10 +328,10 @@ impl LayoutElementHelpers for LayoutJS<Element> {
where V: Push<ApplicableDeclarationBlock> where V: Push<ApplicableDeclarationBlock>
{ {
#[inline] #[inline]
fn from_declaration(rule: PropertyDeclaration) -> ApplicableDeclarationBlock { fn from_declaration(declaration: PropertyDeclaration) -> ApplicableDeclarationBlock {
ApplicableDeclarationBlock::from_declarations( ApplicableDeclarationBlock::from_declarations(
Arc::new(RwLock::new(PropertyDeclarationBlock { Arc::new(RwLock::new(PropertyDeclarationBlock {
declarations: vec![(rule, Importance::Normal)], declarations: vec![(declaration, Importance::Normal)],
important_count: 0, important_count: 0,
})), })),
Importance::Normal) Importance::Normal)
Expand Down Expand Up @@ -814,10 +814,7 @@ impl Element {
} }
None None
} }
}



impl Element {
pub fn is_focusable_area(&self) -> bool { pub fn is_focusable_area(&self) -> bool {
if self.is_actually_disabled() { if self.is_actually_disabled() {
return false; return false;
Expand Down Expand Up @@ -856,10 +853,7 @@ impl Element {
_ => false, _ => false,
} }
} }
}



impl Element {
pub fn push_new_attribute(&self, pub fn push_new_attribute(&self,
local_name: LocalName, local_name: LocalName,
value: AttrValue, value: AttrValue,
Expand Down
11 changes: 6 additions & 5 deletions components/script_layout_interface/wrapper_traits.rs
Expand Up @@ -375,13 +375,13 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
.borrow() .borrow()
.current_styles().pseudos.contains_key(&style_pseudo) { .current_styles().pseudos.contains_key(&style_pseudo) {
let mut data = self.get_style_data().unwrap().borrow_mut(); let mut data = self.get_style_data().unwrap().borrow_mut();
let new_style = let new_style_and_rule_node =
context.stylist.precomputed_values_for_pseudo( context.stylist.precomputed_values_for_pseudo(
&style_pseudo, &style_pseudo,
Some(&data.current_styles().primary), Some(&data.current_styles().primary),
false); false);
data.current_pseudos_mut() data.current_pseudos_mut()
.insert(style_pseudo.clone(), new_style.unwrap()); .insert(style_pseudo.clone(), new_style_and_rule_node.unwrap());
} }
} }
PseudoElementCascadeType::Lazy => { PseudoElementCascadeType::Lazy => {
Expand All @@ -404,7 +404,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +


self.get_style_data().unwrap().borrow() self.get_style_data().unwrap().borrow()
.current_styles().pseudos.get(&style_pseudo) .current_styles().pseudos.get(&style_pseudo)
.unwrap().clone() .unwrap().0.clone()
} }
} }
} }
Expand All @@ -413,7 +413,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
fn selected_style(&self) -> Arc<ServoComputedValues> { fn selected_style(&self) -> Arc<ServoComputedValues> {
let data = self.get_style_data().unwrap().borrow(); let data = self.get_style_data().unwrap().borrow();
data.current_styles().pseudos data.current_styles().pseudos
.get(&PseudoElement::Selection) .get(&PseudoElement::Selection).map(|s| &s.0)
.unwrap_or(&data.current_styles().primary) .unwrap_or(&data.current_styles().primary)
.clone() .clone()
} }
Expand All @@ -432,7 +432,8 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
PseudoElementType::Normal PseudoElementType::Normal
=> data.current_styles().primary.clone(), => data.current_styles().primary.clone(),
other other
=> data.current_styles().pseudos.get(&other.style_pseudo_element()).unwrap().clone(), => data.current_styles().pseudos
.get(&other.style_pseudo_element()).unwrap().0.clone(),
} }
} }


Expand Down
33 changes: 17 additions & 16 deletions components/style/animation.rs
Expand Up @@ -7,6 +7,7 @@
use Atom; use Atom;
use bezier::Bezier; use bezier::Bezier;
use context::SharedStyleContext; use context::SharedStyleContext;
use declarations_iterators::RawDeclarationsIterator;
use dom::{OpaqueNode, UnsafeNode}; use dom::{OpaqueNode, UnsafeNode};
use euclid::point::Point2D; use euclid::point::Point2D;
use keyframes::{KeyframesStep, KeyframesStepValue}; use keyframes::{KeyframesStep, KeyframesStepValue};
Expand All @@ -17,7 +18,6 @@ use properties::longhands::animation_iteration_count::computed_value::AnimationI
use properties::longhands::animation_play_state::computed_value::AnimationPlayState; use properties::longhands::animation_play_state::computed_value::AnimationPlayState;
use properties::longhands::transition_timing_function::computed_value::StartEnd; use properties::longhands::transition_timing_function::computed_value::StartEnd;
use properties::longhands::transition_timing_function::computed_value::TransitionTimingFunction; use properties::longhands::transition_timing_function::computed_value::TransitionTimingFunction;
use selector_matching::ApplicableDeclarationBlock;
use std::sync::Arc; use std::sync::Arc;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use timer::Timer; use timer::Timer;
Expand Down Expand Up @@ -385,23 +385,24 @@ fn compute_style_for_animation_step(context: &SharedStyleContext,
style_from_cascade: &ComputedValues) style_from_cascade: &ComputedValues)
-> ComputedValues { -> ComputedValues {
match step.value { match step.value {
// TODO: avoiding this spurious clone might involve having to create
// an Arc in the below (more common case).
KeyframesStepValue::ComputedValues => style_from_cascade.clone(), KeyframesStepValue::ComputedValues => style_from_cascade.clone(),
KeyframesStepValue::Declarations { block: ref declarations } => { KeyframesStepValue::Declarations { block: ref declarations } => {
let declaration_block = ApplicableDeclarationBlock { let guard = declarations.read();
mixed_declarations: declarations.clone(),
importance: Importance::Normal, // No !important in keyframes.
source_order: 0, debug_assert!(guard.declarations.iter()
specificity: ::std::u32::MAX, .all(|&(_, importance)| importance == Importance::Normal));
};
let (computed, _) = properties::cascade(context.viewport_size, let iter = RawDeclarationsIterator::new(&guard.declarations);
&[declaration_block],
Some(previous_style), let computed =
None, properties::apply_declarations(context.viewport_size,
None, /* is_root = */ false,
context.error_reporter.clone(), iter,
CascadeFlags::empty()); previous_style,
/* cascade_info = */ None,
context.error_reporter.clone(),
CascadeFlags::empty());
computed computed
} }
} }
Expand Down
4 changes: 1 addition & 3 deletions components/style/context.rs
Expand Up @@ -9,7 +9,7 @@ use app_units::Au;
use dom::OpaqueNode; use dom::OpaqueNode;
use error_reporting::ParseErrorReporter; use error_reporting::ParseErrorReporter;
use euclid::Size2D; use euclid::Size2D;
use matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache}; use matching::StyleSharingCandidateCache;
use parking_lot::RwLock; use parking_lot::RwLock;
use selector_matching::Stylist; use selector_matching::Stylist;
use std::cell::RefCell; use std::cell::RefCell;
Expand Down Expand Up @@ -66,7 +66,6 @@ pub struct SharedStyleContext {
} }


pub struct LocalStyleContext { pub struct LocalStyleContext {
pub applicable_declarations_cache: RefCell<ApplicableDeclarationsCache>,
pub style_sharing_candidate_cache: RefCell<StyleSharingCandidateCache>, pub style_sharing_candidate_cache: RefCell<StyleSharingCandidateCache>,
/// A channel on which new animations that have been triggered by style /// A channel on which new animations that have been triggered by style
/// recalculation can be sent. /// recalculation can be sent.
Expand All @@ -76,7 +75,6 @@ pub struct LocalStyleContext {
impl LocalStyleContext { impl LocalStyleContext {
pub fn new(local_context_creation_data: &LocalStyleContextCreationInfo) -> Self { pub fn new(local_context_creation_data: &LocalStyleContextCreationInfo) -> Self {
LocalStyleContext { LocalStyleContext {
applicable_declarations_cache: RefCell::new(ApplicableDeclarationsCache::new()),
style_sharing_candidate_cache: RefCell::new(StyleSharingCandidateCache::new()), style_sharing_candidate_cache: RefCell::new(StyleSharingCandidateCache::new()),
new_animations_sender: local_context_creation_data.new_animations_sender.clone(), new_animations_sender: local_context_creation_data.new_animations_sender.clone(),
} }
Expand Down
14 changes: 7 additions & 7 deletions components/style/data.rs
Expand Up @@ -5,14 +5,15 @@
//! Per-node data used in style calculation. //! Per-node data used in style calculation.


use properties::ComputedValues; use properties::ComputedValues;
use rule_tree::StrongRuleNode;
use selector_impl::PseudoElement; use selector_impl::PseudoElement;
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::BuildHasherDefault; use std::hash::BuildHasherDefault;
use std::mem; use std::mem;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::sync::Arc; use std::sync::Arc;


type PseudoStylesInner = HashMap<PseudoElement, Arc<ComputedValues>, type PseudoStylesInner = HashMap<PseudoElement, (Arc<ComputedValues>, StrongRuleNode),
BuildHasherDefault<::fnv::FnvHasher>>; BuildHasherDefault<::fnv::FnvHasher>>;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct PseudoStyles(PseudoStylesInner); pub struct PseudoStyles(PseudoStylesInner);
Expand All @@ -39,14 +40,18 @@ pub struct ElementStyles {
/// The results of CSS styling for this node. /// The results of CSS styling for this node.
pub primary: Arc<ComputedValues>, pub primary: Arc<ComputedValues>,


/// The rule node representing the last rule matched for this node.
pub rule_node: StrongRuleNode,

/// The results of CSS styling for each pseudo-element (if any). /// The results of CSS styling for each pseudo-element (if any).
pub pseudos: PseudoStyles, pub pseudos: PseudoStyles,
} }


impl ElementStyles { impl ElementStyles {
pub fn new(primary: Arc<ComputedValues>) -> Self { pub fn new(primary: Arc<ComputedValues>, rule_node: StrongRuleNode) -> Self {
ElementStyles { ElementStyles {
primary: primary, primary: primary,
rule_node: rule_node,
pseudos: PseudoStyles::empty(), pseudos: PseudoStyles::empty(),
} }
} }
Expand Down Expand Up @@ -185,11 +190,6 @@ impl ElementData {
} }
} }


pub fn style_text_node(&mut self, style: Arc<ComputedValues>) {
self.styles = ElementDataStyles::Current(ElementStyles::new(style));
self.restyle_data = None;
}

pub fn finish_styling(&mut self, styles: ElementStyles) { pub fn finish_styling(&mut self, styles: ElementStyles) {
debug_assert!(self.styles.is_previous()); debug_assert!(self.styles.is_previous());
self.styles = ElementDataStyles::Current(styles); self.styles = ElementDataStyles::Current(styles);
Expand Down
83 changes: 83 additions & 0 deletions components/style/declarations_iterators.rs
@@ -0,0 +1,83 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A set of simple iterators to be reused for doing the cascade.

use properties::{Importance, PropertyDeclaration};


/// An iterator that applies the declarations in a list that matches the given
/// importance.
#[derive(Clone)]
pub struct SimpleDeclarationsIterator<'a> {
declarations: &'a [(PropertyDeclaration, Importance)],
importance: Importance,
index: usize,
}

impl<'a> SimpleDeclarationsIterator<'a> {
pub fn new(declarations: &'a [(PropertyDeclaration, Importance)],
importance: Importance) -> Self {
SimpleDeclarationsIterator {
declarations: declarations,
importance: importance,
index: 0,
}
}
}

impl<'a> Iterator for SimpleDeclarationsIterator<'a> {
type Item = &'a PropertyDeclaration;

fn next(&mut self) -> Option<Self::Item> {
loop {
if self.index == self.declarations.len() {
return None;
}

let (ref decl, importance) =
self.declarations[self.declarations.len() - self.index - 1];

self.index += 1;

if importance == self.importance {
return Some(decl)
}
}
}
}

/// An iterator that applies the declarations in a list without checking any
/// order.
#[derive(Clone)]
pub struct RawDeclarationsIterator<'a> {
declarations: &'a [(PropertyDeclaration, Importance)],
index: usize,
}

impl<'a> RawDeclarationsIterator<'a> {
pub fn new(declarations: &'a [(PropertyDeclaration, Importance)]) -> Self {
RawDeclarationsIterator {
declarations: declarations,
index: 0,
}
}
}

impl<'a> Iterator for RawDeclarationsIterator<'a> {
type Item = &'a PropertyDeclaration;

fn next(&mut self) -> Option<Self::Item> {
if self.index == self.declarations.len() {
return None;
}

let (ref decl, _) =
self.declarations[self.declarations.len() - self.index - 1];

self.index += 1;

return Some(decl)
}
}
3 changes: 0 additions & 3 deletions components/style/gecko/context.rs
Expand Up @@ -13,9 +13,6 @@ fn create_or_get_local_context(shared: &SharedStyleContext) -> Rc<LocalStyleCont
LOCAL_CONTEXT_KEY.with(|r| { LOCAL_CONTEXT_KEY.with(|r| {
let mut r = r.borrow_mut(); let mut r = r.borrow_mut();
if let Some(context) = r.clone() { if let Some(context) = r.clone() {
if shared.screen_size_changed {
context.applicable_declarations_cache.borrow_mut().evict_all();
}
context context
} else { } else {
let context = Rc::new(LocalStyleContext::new(&shared.local_context_creation_data.lock().unwrap())); let context = Rc::new(LocalStyleContext::new(&shared.local_context_creation_data.lock().unwrap()));
Expand Down
2 changes: 1 addition & 1 deletion components/style/gecko/wrapper.rs
Expand Up @@ -334,7 +334,7 @@ impl<'le> GeckoElement<'le> {


pub fn get_pseudo_style(&self, pseudo: &PseudoElement) -> Option<Arc<ComputedValues>> { pub fn get_pseudo_style(&self, pseudo: &PseudoElement) -> Option<Arc<ComputedValues>> {
self.borrow_data().and_then(|data| data.current_styles().pseudos self.borrow_data().and_then(|data| data.current_styles().pseudos
.get(pseudo).map(|c| c.clone())) .get(pseudo).map(|c| c.0.clone()))
} }


pub fn ensure_data(&self) -> &AtomicRefCell<ElementData> { pub fn ensure_data(&self) -> &AtomicRefCell<ElementData> {
Expand Down
2 changes: 2 additions & 0 deletions components/style/lib.rs
Expand Up @@ -99,6 +99,7 @@ pub mod cascade_info;
pub mod context; pub mod context;
pub mod custom_properties; pub mod custom_properties;
pub mod data; pub mod data;
pub mod declarations_iterators;
pub mod dom; pub mod dom;
pub mod element_state; pub mod element_state;
pub mod error_reporting; pub mod error_reporting;
Expand All @@ -114,6 +115,7 @@ pub mod parallel;
pub mod parser; pub mod parser;
pub mod refcell; pub mod refcell;
pub mod restyle_hints; pub mod restyle_hints;
pub mod rule_tree;
pub mod selector_impl; pub mod selector_impl;
pub mod selector_matching; pub mod selector_matching;
pub mod sequential; pub mod sequential;
Expand Down

0 comments on commit de4fe6e

Please sign in to comment.