diff options
author | Bobby Holley <bobbyholley@gmail.com> | 2017-06-12 11:13:04 -0700 |
---|---|---|
committer | Bobby Holley <bobbyholley@gmail.com> | 2017-06-12 12:13:21 -0700 |
commit | a98fff1af85f377787cff046bce07c1a93e79f9e (patch) | |
tree | 1776f4c41faa932e657a3396f3a778294e0a7f46 | |
parent | 0caad2ffdc0879c12474a500d41f87697e8cfa5c (diff) | |
download | servo-a98fff1af85f377787cff046bce07c1a93e79f9e.tar.gz servo-a98fff1af85f377787cff046bce07c1a93e79f9e.zip |
Hoist ApplicableDeclaration{Block,List} into a separate file.
MozReview-Commit-ID: EXnAzfyoZ1e
-rw-r--r-- | components/script/dom/element.rs | 2 | ||||
-rw-r--r-- | components/script/layout_wrapper.rs | 2 | ||||
-rw-r--r-- | components/style/applicable_declarations.rs | 137 | ||||
-rw-r--r-- | components/style/dom.rs | 2 | ||||
-rw-r--r-- | components/style/gecko/wrapper.rs | 2 | ||||
-rw-r--r-- | components/style/lib.rs | 1 | ||||
-rw-r--r-- | components/style/matching.rs | 3 | ||||
-rw-r--r-- | components/style/rule_tree/mod.rs | 4 | ||||
-rw-r--r-- | components/style/selector_map.rs | 3 | ||||
-rw-r--r-- | components/style/sharing/mod.rs | 3 | ||||
-rw-r--r-- | components/style/stylist.rs | 130 | ||||
-rw-r--r-- | tests/unit/stylo/size_of.rs | 2 |
12 files changed, 161 insertions, 130 deletions
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 3d7b0676fb8..957eadb53e4 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -97,6 +97,7 @@ use std::convert::TryFrom; use std::default::Default; use std::fmt; use std::rc::Rc; +use style::applicable_declarations::ApplicableDeclarationBlock; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; use style::context::{QuirksMode, ReflowGoal}; use style::element_state::*; @@ -109,7 +110,6 @@ use style::selector_parser::extended_filtering; use style::shared_lock::{SharedRwLock, Locked}; use style::sink::Push; use style::stylearc::Arc; -use style::stylist::ApplicableDeclarationBlock; use style::thread_state; use style::values::{CSSFloat, Either}; use style::values::specified; diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs index 15589619e17..916b9f5a329 100644 --- a/components/script/layout_wrapper.rs +++ b/components/script/layout_wrapper.rs @@ -61,6 +61,7 @@ use std::marker::PhantomData; use std::mem::transmute; use std::sync::atomic::Ordering; use style; +use style::applicable_declarations::ApplicableDeclarationBlock; use style::attr::AttrValue; use style::computed_values::display; use style::context::{QuirksMode, SharedStyleContext}; @@ -76,7 +77,6 @@ use style::shared_lock::{SharedRwLock as StyleSharedRwLock, Locked as StyleLocke use style::sink::Push; use style::str::is_whitespace; use style::stylearc::Arc; -use style::stylist::ApplicableDeclarationBlock; #[derive(Copy, Clone)] pub struct ServoLayoutNode<'a> { diff --git a/components/style/applicable_declarations.rs b/components/style/applicable_declarations.rs new file mode 100644 index 00000000000..17cf13f7f4d --- /dev/null +++ b/components/style/applicable_declarations.rs @@ -0,0 +1,137 @@ +/* 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/. */ + +//! Applicable declarations management. + +use properties::PropertyDeclarationBlock; +use rule_tree::{CascadeLevel, StyleSource}; +use shared_lock::Locked; +use smallvec::SmallVec; +use std::fmt::{Debug, self}; +use std::mem; +use stylearc::Arc; + +/// List of applicable declarations. This is a transient structure that shuttles +/// declarations between selector matching and inserting into the rule tree, and +/// therefore we want to avoid heap-allocation where possible. +/// +/// In measurements on wikipedia, we pretty much never have more than 8 applicable +/// declarations, so we could consider making this 8 entries instead of 16. +/// However, it may depend a lot on workload, and stack space is cheap. +pub type ApplicableDeclarationList = SmallVec<[ApplicableDeclarationBlock; 16]>; + +/// Blink uses 18 bits to store source order, and does not check overflow [1]. +/// That's a limit that could be reached in realistic webpages, so we use +/// 24 bits and enforce defined behavior in the overflow case. +/// +/// Note that the value of 24 is also hard-coded into the level() accessor, +/// which does a byte-aligned load of the 4th byte. If you change this value +/// you'll need to change that as well. +/// +/// [1] https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/css/ +/// RuleSet.h?l=128&rcl=90140ab80b84d0f889abc253410f44ed54ae04f3 +const SOURCE_ORDER_BITS: usize = 24; +const SOURCE_ORDER_MASK: u32 = (1 << SOURCE_ORDER_BITS) - 1; +const SOURCE_ORDER_MAX: u32 = SOURCE_ORDER_MASK; + +/// Stores the source order of a block and the cascade level it belongs to. +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[derive(Copy, Clone, Eq, PartialEq)] +struct SourceOrderAndCascadeLevel(u32); + +impl SourceOrderAndCascadeLevel { + fn new(source_order: u32, cascade_level: CascadeLevel) -> SourceOrderAndCascadeLevel { + let mut bits = ::std::cmp::min(source_order, SOURCE_ORDER_MAX); + bits |= (cascade_level as u8 as u32) << SOURCE_ORDER_BITS; + SourceOrderAndCascadeLevel(bits) + } + + fn order(&self) -> u32 { + self.0 & SOURCE_ORDER_MASK + } + + fn level(&self) -> CascadeLevel { + unsafe { + // Transmute rather than shifting so that we're sure the compiler + // emits a simple byte-aligned load. + let as_bytes: [u8; 4] = mem::transmute(self.0); + CascadeLevel::from_byte(as_bytes[3]) + } + } +} + +impl Debug for SourceOrderAndCascadeLevel { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("SourceOrderAndCascadeLevel") + .field("order", &self.order()) + .field("level", &self.level()) + .finish() + } +} + +/// A property declaration together with its precedence among rules of equal +/// specificity so that we can sort them. +/// +/// This represents the declarations in a given declaration block for a given +/// importance. +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[derive(Debug, Clone, PartialEq)] +pub struct ApplicableDeclarationBlock { + /// The style source, either a style rule, or a property declaration block. + #[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")] + pub source: StyleSource, + /// The source order of the block, and the cascade level it belongs to. + order_and_level: SourceOrderAndCascadeLevel, + /// The specificity of the selector this block is represented by. + pub specificity: u32, +} + +impl ApplicableDeclarationBlock { + /// Constructs an applicable declaration block from a given property + /// declaration block and importance. + #[inline] + pub fn from_declarations(declarations: Arc<Locked<PropertyDeclarationBlock>>, + level: CascadeLevel) + -> Self { + ApplicableDeclarationBlock { + source: StyleSource::Declarations(declarations), + order_and_level: SourceOrderAndCascadeLevel::new(0, level), + specificity: 0, + } + } + + /// Constructs an applicable declaration block from the given components + #[inline] + pub fn new(source: StyleSource, + order: u32, + level: CascadeLevel, + specificity: u32) -> Self { + ApplicableDeclarationBlock { + source: source, + order_and_level: SourceOrderAndCascadeLevel::new(order, level), + specificity: specificity, + } + + } + + /// Returns the source order of the block. + #[inline] + pub fn source_order(&self) -> u32 { + self.order_and_level.order() + } + + /// Returns the cascade level of the block. + #[inline] + pub fn level(&self) -> CascadeLevel { + self.order_and_level.level() + } + + /// Convenience method to consume self and return the source alongside the + /// level. + #[inline] + pub fn order_and_level(self) -> (StyleSource, CascadeLevel) { + let level = self.level(); + (self.source, level) + } +} diff --git a/components/style/dom.rs b/components/style/dom.rs index aef401dc43e..bbb4b279bf3 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -8,6 +8,7 @@ #![deny(missing_docs)] use {Atom, Namespace, LocalName}; +use applicable_declarations::ApplicableDeclarationBlock; use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; #[cfg(feature = "gecko")] use context::UpdateAnimationsTasks; use data::ElementData; @@ -29,7 +30,6 @@ use std::fmt::Debug; use std::hash::Hash; use std::ops::Deref; use stylearc::Arc; -use stylist::ApplicableDeclarationBlock; use thread_state; pub use style_traits::UnsafeNode; diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 0ceb2c82a1b..64068a875f6 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -15,6 +15,7 @@ //! the separation between the style system implementation and everything else. use app_units::Au; +use applicable_declarations::ApplicableDeclarationBlock; use atomic_refcell::AtomicRefCell; use context::{QuirksMode, SharedStyleContext, UpdateAnimationsTasks}; use data::ElementData; @@ -87,7 +88,6 @@ use std::ptr; use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; use stylearc::Arc; use stylesheets::UrlExtraData; -use stylist::ApplicableDeclarationBlock; /// A simple wrapper over a non-null Gecko node (`nsINode`) pointer. /// diff --git a/components/style/lib.rs b/components/style/lib.rs index 0cde26b37f0..66cde1211d3 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -91,6 +91,7 @@ extern crate unicode_segmentation; mod macros; pub mod animation; +pub mod applicable_declarations; #[allow(missing_docs)] // TODO. #[cfg(feature = "servo")] pub mod attr; pub mod bezier; diff --git a/components/style/matching.rs b/components/style/matching.rs index 00eaba9b63e..d93eec27026 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -7,6 +7,7 @@ #![allow(unsafe_code)] #![deny(missing_docs)] +use applicable_declarations::ApplicableDeclarationList; use cascade_info::CascadeInfo; use context::{SelectorFlagsMap, SharedStyleContext, StyleContext}; use data::{ComputedStyle, ElementData, RestyleData}; @@ -25,7 +26,7 @@ use selectors::matching::{ElementSelectorFlags, MatchingContext, MatchingMode, S use selectors::matching::{VisitedHandlingMode, AFFECTED_BY_PSEUDO_ELEMENTS}; use sharing::StyleSharingBehavior; use stylearc::Arc; -use stylist::{ApplicableDeclarationList, RuleInclusion}; +use stylist::RuleInclusion; /// The way a style should be inherited. enum InheritMode { diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs index 66e5bd214f0..c1a3b2b69d5 100644 --- a/components/style/rule_tree/mod.rs +++ b/components/style/rule_tree/mod.rs @@ -6,6 +6,7 @@ //! The rule tree. +use applicable_declarations::ApplicableDeclarationList; #[cfg(feature = "servo")] use heapsize::HeapSizeOf; use properties::{AnimationRules, Importance, LonghandIdSet, PropertyDeclarationBlock}; @@ -17,7 +18,6 @@ use std::ptr; use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; use stylearc::{Arc, NonZeroPtrMut}; use stylesheets::StyleRule; -use stylist::ApplicableDeclarationList; use thread_state; /// The rule tree, the structure servo uses to preserve the results of selector @@ -230,7 +230,7 @@ impl RuleTree { guards: &StylesheetGuards) -> StrongRuleNode { - let rules = applicable_declarations.drain().map(|d| d.source_and_level()); + let rules = applicable_declarations.drain().map(|d| d.order_and_level()); let rule_node = self.insert_ordered_rules_with_important(rules, guards); rule_node } diff --git a/components/style/selector_map.rs b/components/style/selector_map.rs index 8bb9eeb8e31..6a5733877a2 100644 --- a/components/style/selector_map.rs +++ b/components/style/selector_map.rs @@ -6,6 +6,7 @@ //! name, ids and hash. use {Atom, LocalName}; +use applicable_declarations::ApplicableDeclarationBlock; use dom::TElement; use fnv::FnvHashMap; use pdqsort::sort_by; @@ -18,7 +19,7 @@ use smallvec::VecLike; use std::borrow::Borrow; use std::collections::HashMap; use std::hash::Hash; -use stylist::{ApplicableDeclarationBlock, Rule}; +use stylist::Rule; /// A trait to abstract over a given selector map entry. pub trait SelectorMapEntry : Sized + Clone { diff --git a/components/style/sharing/mod.rs b/components/style/sharing/mod.rs index 3c17f576156..5971eb34367 100644 --- a/components/style/sharing/mod.rs +++ b/components/style/sharing/mod.rs @@ -65,6 +65,7 @@ //! elements makes sense. use Atom; +use applicable_declarations::ApplicableDeclarationBlock; use bit_vec::BitVec; use bloom::StyleBloom; use cache::{LRUCache, LRUCacheMutIterator}; @@ -78,7 +79,7 @@ use selectors::matching::{ElementSelectorFlags, VisitedHandlingMode, StyleRelati use smallvec::SmallVec; use std::mem; use std::ops::Deref; -use stylist::{ApplicableDeclarationBlock, Stylist}; +use stylist::Stylist; mod checks; diff --git a/components/style/stylist.rs b/components/style/stylist.rs index ecda82f269e..321e417a428 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -5,6 +5,7 @@ //! Selector matching. use {Atom, LocalName, Namespace}; +use applicable_declarations::{ApplicableDeclarationBlock, ApplicableDeclarationList}; use bit_vec::BitVec; use context::{QuirksMode, SharedStyleContext}; use data::ComputedStyle; @@ -33,11 +34,10 @@ use selectors::parser::{SelectorIter, SelectorMethods}; use selectors::visitor::SelectorVisitor; use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards}; use sink::Push; -use smallvec::{SmallVec, VecLike}; -use std::fmt::{Debug, self}; +use smallvec::VecLike; +use std::fmt::Debug; #[cfg(feature = "servo")] use std::marker::PhantomData; -use std::mem; use style_traits::viewport::ViewportConstraints; use stylearc::Arc; #[cfg(feature = "gecko")] @@ -50,15 +50,6 @@ use thread_state; pub use ::fnv::FnvHashMap; -/// List of applicable declaration. This is a transient structure that shuttles -/// declarations between selector matching and inserting into the rule tree, and -/// therefore we want to avoid heap-allocation where possible. -/// -/// In measurements on wikipedia, we pretty much never have more than 8 applicable -/// declarations, so we could consider making this 8 entries instead of 16. -/// However, it may depend a lot on workload, and stack space is cheap. -pub type ApplicableDeclarationList = SmallVec<[ApplicableDeclarationBlock; 16]>; - /// This structure holds all the selectors and device characteristics /// for a given document. The selectors are converted into `Rule`s /// (defined in rust-selectors), and introduced in a `SelectorMap` @@ -756,7 +747,7 @@ impl Stylist { let rule_node = self.rule_tree.insert_ordered_rules_with_important( - declarations.into_iter().map(|a| a.source_and_level()), + declarations.into_iter().map(|a| a.order_and_level()), guards); if rule_node == self.rule_tree.root() { None @@ -1208,7 +1199,7 @@ impl Stylist { CascadeLevel::StyleAttributeNormal) ]; let rule_node = - self.rule_tree.insert_ordered_rules(v.into_iter().map(|a| a.source_and_level())); + self.rule_tree.insert_ordered_rules(v.into_iter().map(|a| a.order_and_level())); // This currently ignores visited styles. It appears to be used for // font styles in <canvas> via Servo_StyleSet_ResolveForDeclarations. @@ -1529,11 +1520,11 @@ impl Rule { pub fn to_applicable_declaration_block(&self, level: CascadeLevel) -> ApplicableDeclarationBlock { - ApplicableDeclarationBlock { - source: StyleSource::Style(self.style_rule.clone()), - source_and_level: SourceOrderAndCascadeLevel::new(self.source_order, level), - specificity: self.specificity(), - } + let source = StyleSource::Style(self.style_rule.clone()); + ApplicableDeclarationBlock::new(source, + self.source_order, + level, + self.specificity()) } /// Creates a new Rule. @@ -1551,104 +1542,3 @@ impl Rule { } } } - -/// Blink uses 18 bits to store source order, and does not check overflow [1]. -/// That's a limit that could be reached in realistic webpages, so we use -/// 24 bits and enforce defined behavior in the overflow case. -/// -/// Note that the value of 24 is also hard-coded into the level() accessor, -/// which does a byte-aligned load of the 4th byte. If you change this value -/// you'll need to change that as well. -/// -/// [1] https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/css/ -/// RuleSet.h?l=128&rcl=90140ab80b84d0f889abc253410f44ed54ae04f3 -const SOURCE_ORDER_BITS: usize = 24; -const SOURCE_ORDER_MASK: u32 = (1 << SOURCE_ORDER_BITS) - 1; -const SOURCE_ORDER_MAX: u32 = SOURCE_ORDER_MASK; - -/// Stores the source order of a block and the cascade level it belongs to. -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Copy, Clone, Eq, PartialEq)] -struct SourceOrderAndCascadeLevel(u32); - -impl SourceOrderAndCascadeLevel { - fn new(source_order: u32, cascade_level: CascadeLevel) -> SourceOrderAndCascadeLevel { - let mut bits = ::std::cmp::min(source_order, SOURCE_ORDER_MAX); - bits |= (cascade_level as u8 as u32) << SOURCE_ORDER_BITS; - SourceOrderAndCascadeLevel(bits) - } - - fn order(&self) -> u32 { - self.0 & SOURCE_ORDER_MASK - } - - fn level(&self) -> CascadeLevel { - unsafe { - // Transmute rather than shifting so that we're sure the compiler - // emits a simple byte-aligned load. - let as_bytes: [u8; 4] = mem::transmute(self.0); - CascadeLevel::from_byte(as_bytes[3]) - } - } -} - -impl Debug for SourceOrderAndCascadeLevel { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("SourceOrderAndCascadeLevel") - .field("order", &self.order()) - .field("level", &self.level()) - .finish() - } -} - -/// A property declaration together with its precedence among rules of equal -/// specificity so that we can sort them. -/// -/// This represents the declarations in a given declaration block for a given -/// importance. -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Debug, Clone, PartialEq)] -pub struct ApplicableDeclarationBlock { - /// The style source, either a style rule, or a property declaration block. - #[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")] - pub source: StyleSource, - /// The source order of the block, and the cascade level it belongs to. - source_and_level: SourceOrderAndCascadeLevel, - /// The specificity of the selector this block is represented by. - pub specificity: u32, -} - -impl ApplicableDeclarationBlock { - /// Constructs an applicable declaration block from a given property - /// declaration block and importance. - #[inline] - pub fn from_declarations(declarations: Arc<Locked<PropertyDeclarationBlock>>, - level: CascadeLevel) - -> Self { - ApplicableDeclarationBlock { - source: StyleSource::Declarations(declarations), - source_and_level: SourceOrderAndCascadeLevel::new(0, level), - specificity: 0, - } - } - - /// Returns the source order of the block. - #[inline] - pub fn source_order(&self) -> u32 { - self.source_and_level.order() - } - - /// Returns the cascade level of the block. - #[inline] - pub fn level(&self) -> CascadeLevel { - self.source_and_level.level() - } - - /// Convenience method to consume self and return the source alongside the - /// level. - #[inline] - pub fn source_and_level(self) -> (StyleSource, CascadeLevel) { - let level = self.level(); - (self.source, level) - } -} diff --git a/tests/unit/stylo/size_of.rs b/tests/unit/stylo/size_of.rs index 6c90f53ffe6..72acb2c2d5f 100644 --- a/tests/unit/stylo/size_of.rs +++ b/tests/unit/stylo/size_of.rs @@ -6,11 +6,11 @@ use selectors::gecko_like_types as dummies; use servo_arc::Arc; use std::mem::{size_of, align_of}; use style; +use style::applicable_declarations::ApplicableDeclarationBlock; use style::data::{ComputedStyle, ElementData, ElementStyles}; use style::gecko::selector_parser as real; use style::properties::ComputedValues; use style::rule_tree::StrongRuleNode; -use style::stylist::ApplicableDeclarationBlock; #[test] fn size_of_selectors_dummy_types() { |