Hoist ApplicableDeclaration{Block,List} into a separate file.

MozReview-Commit-ID: EXnAzfyoZ1e
This commit is contained in:
Bobby Holley 2017-06-12 11:13:04 -07:00
parent 0caad2ffdc
commit a98fff1af8
12 changed files with 161 additions and 130 deletions

View file

@ -97,6 +97,7 @@ use std::convert::TryFrom;
use std::default::Default; use std::default::Default;
use std::fmt; use std::fmt;
use std::rc::Rc; use std::rc::Rc;
use style::applicable_declarations::ApplicableDeclarationBlock;
use style::attr::{AttrValue, LengthOrPercentageOrAuto}; use style::attr::{AttrValue, LengthOrPercentageOrAuto};
use style::context::{QuirksMode, ReflowGoal}; use style::context::{QuirksMode, ReflowGoal};
use style::element_state::*; use style::element_state::*;
@ -109,7 +110,6 @@ use style::selector_parser::extended_filtering;
use style::shared_lock::{SharedRwLock, Locked}; use style::shared_lock::{SharedRwLock, Locked};
use style::sink::Push; use style::sink::Push;
use style::stylearc::Arc; use style::stylearc::Arc;
use style::stylist::ApplicableDeclarationBlock;
use style::thread_state; use style::thread_state;
use style::values::{CSSFloat, Either}; use style::values::{CSSFloat, Either};
use style::values::specified; use style::values::specified;

View file

@ -61,6 +61,7 @@ use std::marker::PhantomData;
use std::mem::transmute; use std::mem::transmute;
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
use style; use style;
use style::applicable_declarations::ApplicableDeclarationBlock;
use style::attr::AttrValue; use style::attr::AttrValue;
use style::computed_values::display; use style::computed_values::display;
use style::context::{QuirksMode, SharedStyleContext}; 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::sink::Push;
use style::str::is_whitespace; use style::str::is_whitespace;
use style::stylearc::Arc; use style::stylearc::Arc;
use style::stylist::ApplicableDeclarationBlock;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct ServoLayoutNode<'a> { pub struct ServoLayoutNode<'a> {

View file

@ -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)
}
}

View file

@ -8,6 +8,7 @@
#![deny(missing_docs)] #![deny(missing_docs)]
use {Atom, Namespace, LocalName}; use {Atom, Namespace, LocalName};
use applicable_declarations::ApplicableDeclarationBlock;
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
#[cfg(feature = "gecko")] use context::UpdateAnimationsTasks; #[cfg(feature = "gecko")] use context::UpdateAnimationsTasks;
use data::ElementData; use data::ElementData;
@ -29,7 +30,6 @@ use std::fmt::Debug;
use std::hash::Hash; use std::hash::Hash;
use std::ops::Deref; use std::ops::Deref;
use stylearc::Arc; use stylearc::Arc;
use stylist::ApplicableDeclarationBlock;
use thread_state; use thread_state;
pub use style_traits::UnsafeNode; pub use style_traits::UnsafeNode;

View file

@ -15,6 +15,7 @@
//! the separation between the style system implementation and everything else. //! the separation between the style system implementation and everything else.
use app_units::Au; use app_units::Au;
use applicable_declarations::ApplicableDeclarationBlock;
use atomic_refcell::AtomicRefCell; use atomic_refcell::AtomicRefCell;
use context::{QuirksMode, SharedStyleContext, UpdateAnimationsTasks}; use context::{QuirksMode, SharedStyleContext, UpdateAnimationsTasks};
use data::ElementData; use data::ElementData;
@ -87,7 +88,6 @@ use std::ptr;
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
use stylearc::Arc; use stylearc::Arc;
use stylesheets::UrlExtraData; use stylesheets::UrlExtraData;
use stylist::ApplicableDeclarationBlock;
/// A simple wrapper over a non-null Gecko node (`nsINode`) pointer. /// A simple wrapper over a non-null Gecko node (`nsINode`) pointer.
/// ///

View file

@ -91,6 +91,7 @@ extern crate unicode_segmentation;
mod macros; mod macros;
pub mod animation; pub mod animation;
pub mod applicable_declarations;
#[allow(missing_docs)] // TODO. #[allow(missing_docs)] // TODO.
#[cfg(feature = "servo")] pub mod attr; #[cfg(feature = "servo")] pub mod attr;
pub mod bezier; pub mod bezier;

View file

@ -7,6 +7,7 @@
#![allow(unsafe_code)] #![allow(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
use applicable_declarations::ApplicableDeclarationList;
use cascade_info::CascadeInfo; use cascade_info::CascadeInfo;
use context::{SelectorFlagsMap, SharedStyleContext, StyleContext}; use context::{SelectorFlagsMap, SharedStyleContext, StyleContext};
use data::{ComputedStyle, ElementData, RestyleData}; 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 selectors::matching::{VisitedHandlingMode, AFFECTED_BY_PSEUDO_ELEMENTS};
use sharing::StyleSharingBehavior; use sharing::StyleSharingBehavior;
use stylearc::Arc; use stylearc::Arc;
use stylist::{ApplicableDeclarationList, RuleInclusion}; use stylist::RuleInclusion;
/// The way a style should be inherited. /// The way a style should be inherited.
enum InheritMode { enum InheritMode {

View file

@ -6,6 +6,7 @@
//! The rule tree. //! The rule tree.
use applicable_declarations::ApplicableDeclarationList;
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
use heapsize::HeapSizeOf; use heapsize::HeapSizeOf;
use properties::{AnimationRules, Importance, LonghandIdSet, PropertyDeclarationBlock}; use properties::{AnimationRules, Importance, LonghandIdSet, PropertyDeclarationBlock};
@ -17,7 +18,6 @@ use std::ptr;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
use stylearc::{Arc, NonZeroPtrMut}; use stylearc::{Arc, NonZeroPtrMut};
use stylesheets::StyleRule; use stylesheets::StyleRule;
use stylist::ApplicableDeclarationList;
use thread_state; use thread_state;
/// The rule tree, the structure servo uses to preserve the results of selector /// The rule tree, the structure servo uses to preserve the results of selector
@ -230,7 +230,7 @@ impl RuleTree {
guards: &StylesheetGuards) guards: &StylesheetGuards)
-> StrongRuleNode -> 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); let rule_node = self.insert_ordered_rules_with_important(rules, guards);
rule_node rule_node
} }

View file

@ -6,6 +6,7 @@
//! name, ids and hash. //! name, ids and hash.
use {Atom, LocalName}; use {Atom, LocalName};
use applicable_declarations::ApplicableDeclarationBlock;
use dom::TElement; use dom::TElement;
use fnv::FnvHashMap; use fnv::FnvHashMap;
use pdqsort::sort_by; use pdqsort::sort_by;
@ -18,7 +19,7 @@ use smallvec::VecLike;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::Hash; use std::hash::Hash;
use stylist::{ApplicableDeclarationBlock, Rule}; use stylist::Rule;
/// A trait to abstract over a given selector map entry. /// A trait to abstract over a given selector map entry.
pub trait SelectorMapEntry : Sized + Clone { pub trait SelectorMapEntry : Sized + Clone {

View file

@ -65,6 +65,7 @@
//! elements makes sense. //! elements makes sense.
use Atom; use Atom;
use applicable_declarations::ApplicableDeclarationBlock;
use bit_vec::BitVec; use bit_vec::BitVec;
use bloom::StyleBloom; use bloom::StyleBloom;
use cache::{LRUCache, LRUCacheMutIterator}; use cache::{LRUCache, LRUCacheMutIterator};
@ -78,7 +79,7 @@ use selectors::matching::{ElementSelectorFlags, VisitedHandlingMode, StyleRelati
use smallvec::SmallVec; use smallvec::SmallVec;
use std::mem; use std::mem;
use std::ops::Deref; use std::ops::Deref;
use stylist::{ApplicableDeclarationBlock, Stylist}; use stylist::Stylist;
mod checks; mod checks;

View file

@ -5,6 +5,7 @@
//! Selector matching. //! Selector matching.
use {Atom, LocalName, Namespace}; use {Atom, LocalName, Namespace};
use applicable_declarations::{ApplicableDeclarationBlock, ApplicableDeclarationList};
use bit_vec::BitVec; use bit_vec::BitVec;
use context::{QuirksMode, SharedStyleContext}; use context::{QuirksMode, SharedStyleContext};
use data::ComputedStyle; use data::ComputedStyle;
@ -33,11 +34,10 @@ use selectors::parser::{SelectorIter, SelectorMethods};
use selectors::visitor::SelectorVisitor; use selectors::visitor::SelectorVisitor;
use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards}; use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
use sink::Push; use sink::Push;
use smallvec::{SmallVec, VecLike}; use smallvec::VecLike;
use std::fmt::{Debug, self}; use std::fmt::Debug;
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem;
use style_traits::viewport::ViewportConstraints; use style_traits::viewport::ViewportConstraints;
use stylearc::Arc; use stylearc::Arc;
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
@ -50,15 +50,6 @@ use thread_state;
pub use ::fnv::FnvHashMap; 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 /// This structure holds all the selectors and device characteristics
/// for a given document. The selectors are converted into `Rule`s /// for a given document. The selectors are converted into `Rule`s
/// (defined in rust-selectors), and introduced in a `SelectorMap` /// (defined in rust-selectors), and introduced in a `SelectorMap`
@ -756,7 +747,7 @@ impl Stylist {
let rule_node = let rule_node =
self.rule_tree.insert_ordered_rules_with_important( 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); guards);
if rule_node == self.rule_tree.root() { if rule_node == self.rule_tree.root() {
None None
@ -1208,7 +1199,7 @@ impl Stylist {
CascadeLevel::StyleAttributeNormal) CascadeLevel::StyleAttributeNormal)
]; ];
let rule_node = 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 // This currently ignores visited styles. It appears to be used for
// font styles in <canvas> via Servo_StyleSet_ResolveForDeclarations. // font styles in <canvas> via Servo_StyleSet_ResolveForDeclarations.
@ -1529,11 +1520,11 @@ impl Rule {
pub fn to_applicable_declaration_block(&self, pub fn to_applicable_declaration_block(&self,
level: CascadeLevel) level: CascadeLevel)
-> ApplicableDeclarationBlock { -> ApplicableDeclarationBlock {
ApplicableDeclarationBlock { let source = StyleSource::Style(self.style_rule.clone());
source: StyleSource::Style(self.style_rule.clone()), ApplicableDeclarationBlock::new(source,
source_and_level: SourceOrderAndCascadeLevel::new(self.source_order, level), self.source_order,
specificity: self.specificity(), level,
} self.specificity())
} }
/// Creates a new Rule. /// 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)
}
}

View file

@ -6,11 +6,11 @@ use selectors::gecko_like_types as dummies;
use servo_arc::Arc; use servo_arc::Arc;
use std::mem::{size_of, align_of}; use std::mem::{size_of, align_of};
use style; use style;
use style::applicable_declarations::ApplicableDeclarationBlock;
use style::data::{ComputedStyle, ElementData, ElementStyles}; use style::data::{ComputedStyle, ElementData, ElementStyles};
use style::gecko::selector_parser as real; use style::gecko::selector_parser as real;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::rule_tree::StrongRuleNode; use style::rule_tree::StrongRuleNode;
use style::stylist::ApplicableDeclarationBlock;
#[test] #[test]
fn size_of_selectors_dummy_types() { fn size_of_selectors_dummy_types() {