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| {
let mut r = r.borrow_mut();
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
} else {
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();
}

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.
self.perform_post_style_recalc_layout_passes(&data.reflow_info,
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>
{
#[inline]
fn from_declaration(rule: PropertyDeclaration) -> ApplicableDeclarationBlock {
fn from_declaration(declaration: PropertyDeclaration) -> ApplicableDeclarationBlock {
ApplicableDeclarationBlock::from_declarations(
Arc::new(RwLock::new(PropertyDeclarationBlock {
declarations: vec![(rule, Importance::Normal)],
declarations: vec![(declaration, Importance::Normal)],
important_count: 0,
})),
Importance::Normal)
Expand Down Expand Up @@ -814,10 +814,7 @@ impl Element {
}
None
}
}


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


impl Element {
pub fn push_new_attribute(&self,
local_name: LocalName,
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()
.current_styles().pseudos.contains_key(&style_pseudo) {
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(
&style_pseudo,
Some(&data.current_styles().primary),
false);
data.current_pseudos_mut()
.insert(style_pseudo.clone(), new_style.unwrap());
.insert(style_pseudo.clone(), new_style_and_rule_node.unwrap());
}
}
PseudoElementCascadeType::Lazy => {
Expand All @@ -404,7 +404,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +

self.get_style_data().unwrap().borrow()
.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> {
let data = self.get_style_data().unwrap().borrow();
data.current_styles().pseudos
.get(&PseudoElement::Selection)
.get(&PseudoElement::Selection).map(|s| &s.0)
.unwrap_or(&data.current_styles().primary)
.clone()
}
Expand All @@ -432,7 +432,8 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
PseudoElementType::Normal
=> data.current_styles().primary.clone(),
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 bezier::Bezier;
use context::SharedStyleContext;
use declarations_iterators::RawDeclarationsIterator;
use dom::{OpaqueNode, UnsafeNode};
use euclid::point::Point2D;
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::transition_timing_function::computed_value::StartEnd;
use properties::longhands::transition_timing_function::computed_value::TransitionTimingFunction;
use selector_matching::ApplicableDeclarationBlock;
use std::sync::Arc;
use std::sync::mpsc::Sender;
use timer::Timer;
Expand Down Expand Up @@ -385,23 +385,24 @@ fn compute_style_for_animation_step(context: &SharedStyleContext,
style_from_cascade: &ComputedValues)
-> ComputedValues {
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::Declarations { block: ref declarations } => {
let declaration_block = ApplicableDeclarationBlock {
mixed_declarations: declarations.clone(),
importance: Importance::Normal,
source_order: 0,
specificity: ::std::u32::MAX,
};
let (computed, _) = properties::cascade(context.viewport_size,
&[declaration_block],
Some(previous_style),
None,
None,
context.error_reporter.clone(),
CascadeFlags::empty());
let guard = declarations.read();

// No !important in keyframes.
debug_assert!(guard.declarations.iter()
.all(|&(_, importance)| importance == Importance::Normal));

let iter = RawDeclarationsIterator::new(&guard.declarations);

let computed =
properties::apply_declarations(context.viewport_size,
/* is_root = */ false,
iter,
previous_style,
/* cascade_info = */ None,
context.error_reporter.clone(),
CascadeFlags::empty());
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 error_reporting::ParseErrorReporter;
use euclid::Size2D;
use matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};
use matching::StyleSharingCandidateCache;
use parking_lot::RwLock;
use selector_matching::Stylist;
use std::cell::RefCell;
Expand Down Expand Up @@ -66,7 +66,6 @@ pub struct SharedStyleContext {
}

pub struct LocalStyleContext {
pub applicable_declarations_cache: RefCell<ApplicableDeclarationsCache>,
pub style_sharing_candidate_cache: RefCell<StyleSharingCandidateCache>,
/// A channel on which new animations that have been triggered by style
/// recalculation can be sent.
Expand All @@ -76,7 +75,6 @@ pub struct LocalStyleContext {
impl LocalStyleContext {
pub fn new(local_context_creation_data: &LocalStyleContextCreationInfo) -> 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(),
}
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.

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

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

impl ElementStyles {
pub fn new(primary: Arc<ComputedValues>) -> Self {
pub fn new(primary: Arc<ComputedValues>, rule_node: StrongRuleNode) -> Self {
ElementStyles {
primary: primary,
rule_node: rule_node,
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) {
debug_assert!(self.styles.is_previous());
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| {
let mut r = r.borrow_mut();
if let Some(context) = r.clone() {
if shared.screen_size_changed {
context.applicable_declarations_cache.borrow_mut().evict_all();
}
context
} else {
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>> {
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> {
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 custom_properties;
pub mod data;
pub mod declarations_iterators;
pub mod dom;
pub mod element_state;
pub mod error_reporting;
Expand All @@ -114,6 +115,7 @@ pub mod parallel;
pub mod parser;
pub mod refcell;
pub mod restyle_hints;
pub mod rule_tree;
pub mod selector_impl;
pub mod selector_matching;
pub mod sequential;
Expand Down

0 comments on commit de4fe6e

Please sign in to comment.