servo: Merge #13179 - Remove one level of nesting in `Stylist` (from servo:flatter-stylist); r=emilio
authorSimon Sapin <simon.sapin@exyr.org>
Tue, 06 Sep 2016 01:48:04 -0500
changeset 339647 246143c073980800f93e30517f4da5a70c4c9e9f
parent 339646 25e56d4816861f26b1008d7d49d3e3bbfcdd1bf9
child 339648 e50ba1d6c2e62e945a9c33f741219cbcac4ddecc
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
servo: Merge #13179 - Remove one level of nesting in `Stylist` (from servo:flatter-stylist); r=emilio <!-- Please describe your changes on the following line: --> Since #13134, the "normal" and "important" parts of `Stylist` are identical, so we don’t need to store them twice. r? @emilio --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [x] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 89126b44d74ac49e7e05d8a127020aa39de0d30e
servo/components/script/dom/element.rs
servo/components/script/layout_wrapper.rs
servo/components/style/animation.rs
servo/components/style/dom.rs
servo/components/style/keyframes.rs
servo/components/style/matching.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/selector_matching.rs
servo/ports/geckolib/wrapper.rs
servo/tests/unit/style/selector_matching.rs
--- a/servo/components/script/dom/element.rs
+++ b/servo/components/script/dom/element.rs
@@ -86,17 +86,17 @@ use style::attr::{AttrValue, LengthOrPer
 use style::element_state::*;
 use style::matching::{common_style_affecting_attributes, rare_style_affecting_attributes};
 use style::parser::ParserContextExtraData;
 use style::properties::longhands::{self, background_image, border_spacing, font_family, overflow_x, font_size};
 use style::properties::{DeclaredValue, Importance};
 use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
 use style::refcell::Ref;
 use style::selector_impl::{NonTSPseudoClass, ServoSelectorImpl};
-use style::selector_matching::DeclarationBlock;
+use style::selector_matching::ApplicableDeclarationBlock;
 use style::sink::Push;
 use style::values::CSSFloat;
 use style::values::specified::{self, CSSColor, CSSRGBA, LengthOrPercentage};
 
 // TODO: Update focus state when the top-level browsing context gains or loses system focus,
 // and when the element enters or leaves a browsing context container.
 // https://html.spec.whatwg.org/multipage/#selector-focus
 
@@ -286,17 +286,17 @@ impl RawLayoutElementHelpers for Element
 pub trait LayoutElementHelpers {
     #[allow(unsafe_code)]
     unsafe fn has_class_for_layout(&self, name: &Atom) -> bool;
     #[allow(unsafe_code)]
     unsafe fn get_classes_for_layout(&self) -> Option<&'static [Atom]>;
 
     #[allow(unsafe_code)]
     unsafe fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, &mut V)
-        where V: Push<DeclarationBlock>;
+        where V: Push<ApplicableDeclarationBlock>;
     #[allow(unsafe_code)]
     unsafe fn get_colspan(self) -> u32;
     #[allow(unsafe_code)]
     unsafe fn html_element_in_html_document_for_layout(&self) -> bool;
     fn id_attribute(&self) -> *const Option<Atom>;
     fn style_attribute(&self) -> *const Option<Arc<PropertyDeclarationBlock>>;
     fn local_name(&self) -> &Atom;
     fn namespace(&self) -> &Namespace;
@@ -319,21 +319,21 @@ impl LayoutElementHelpers for LayoutJS<E
     #[inline]
     unsafe fn get_classes_for_layout(&self) -> Option<&'static [Atom]> {
         get_attr_for_layout(&*self.unsafe_get(), &ns!(), &atom!("class"))
             .map(|attr| attr.value_tokens_forever().unwrap())
     }
 
     #[allow(unsafe_code)]
     unsafe fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
-        where V: Push<DeclarationBlock>
+        where V: Push<ApplicableDeclarationBlock>
     {
         #[inline]
-        fn from_declaration(rule: PropertyDeclaration) -> DeclarationBlock {
-            DeclarationBlock::from_declarations(
+        fn from_declaration(rule: PropertyDeclaration) -> ApplicableDeclarationBlock {
+            ApplicableDeclarationBlock::from_declarations(
                 Arc::new(PropertyDeclarationBlock {
                     declarations: vec![(rule, Importance::Normal)],
                     important_count: 0,
                 }),
                 Importance::Normal)
         }
 
         let bgcolor = if let Some(this) = self.downcast::<HTMLBodyElement>() {
--- a/servo/components/script/layout_wrapper.rs
+++ b/servo/components/script/layout_wrapper.rs
@@ -58,17 +58,17 @@ use style::attr::AttrValue;
 use style::computed_values::display;
 use style::context::SharedStyleContext;
 use style::data::PrivateStyleData;
 use style::dom::{PresentationalHintsSynthetizer, OpaqueNode, TDocument, TElement, TNode, UnsafeNode};
 use style::element_state::*;
 use style::properties::{ComputedValues, PropertyDeclarationBlock};
 use style::refcell::{Ref, RefCell, RefMut};
 use style::selector_impl::{ElementSnapshot, NonTSPseudoClass, PseudoElement, ServoSelectorImpl};
-use style::selector_matching::DeclarationBlock;
+use style::selector_matching::ApplicableDeclarationBlock;
 use style::sink::Push;
 use style::str::is_whitespace;
 use url::Url;
 
 #[derive(Copy, Clone)]
 pub struct ServoLayoutNode<'a> {
     /// The wrapped node.
     node: LayoutJS<Node>,
@@ -437,17 +437,17 @@ impl<'le> fmt::Debug for ServoLayoutElem
             try!(write!(f, " id={}", id));
         }
         write!(f, ">")
     }
 }
 
 impl<'le> PresentationalHintsSynthetizer for ServoLayoutElement<'le> {
     fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
-        where V: Push<DeclarationBlock>
+        where V: Push<ApplicableDeclarationBlock>
     {
         unsafe {
             self.element.synthesize_presentational_hints_for_legacy_attributes(hints);
         }
     }
 }
 
 impl<'le> TElement for ServoLayoutElement<'le> {
@@ -1089,10 +1089,10 @@ impl<'le> ::selectors::Element for Servo
     fn each_class<F>(&self, _callback: F)
         where F: FnMut(&Atom) {
         warn!("ServoThreadSafeLayoutElement::each_class called");
     }
 }
 
 impl<'le> PresentationalHintsSynthetizer for ServoThreadSafeLayoutElement<'le> {
     fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
-        where V: Push<DeclarationBlock> {}
+        where V: Push<ApplicableDeclarationBlock> {}
 }
--- a/servo/components/style/animation.rs
+++ b/servo/components/style/animation.rs
@@ -11,17 +11,17 @@ use euclid::point::Point2D;
 use keyframes::{KeyframesStep, KeyframesStepValue};
 use properties::animated_properties::{AnimatedProperty, TransitionProperty};
 use properties::longhands::animation_direction::computed_value::AnimationDirection;
 use properties::longhands::animation_iteration_count::computed_value::AnimationIterationCount;
 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 properties::{self, ComputedValues, Importance};
-use selector_matching::DeclarationBlock;
+use selector_matching::ApplicableDeclarationBlock;
 use std::sync::Arc;
 use std::sync::mpsc::Sender;
 use string_cache::Atom;
 use timer::Timer;
 use values::computed::Time;
 
 /// This structure represents a keyframes animation current iteration state.
 ///
@@ -379,17 +379,17 @@ fn compute_style_for_animation_step(cont
                                     previous_style: &ComputedValues,
                                     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(ref declarations) => {
-            let declaration_block = DeclarationBlock {
+            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],
                                                     false,
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -8,17 +8,17 @@
 
 use context::SharedStyleContext;
 use data::PrivateStyleData;
 use element_state::ElementState;
 use properties::{ComputedValues, PropertyDeclarationBlock};
 use refcell::{Ref, RefMut};
 use restyle_hints::{RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
 use selector_impl::{ElementExt, PseudoElement};
-use selector_matching::DeclarationBlock;
+use selector_matching::ApplicableDeclarationBlock;
 use sink::Push;
 use std::fmt::Debug;
 use std::ops::BitOr;
 use std::sync::Arc;
 use string_cache::{Atom, Namespace};
 
 /// Opaque type stored in type-unsafe work queues for parallel layout.
 /// Must be transmutable to and from TNode.
@@ -181,17 +181,17 @@ pub trait TDocument : Sized + Copy + Clo
                                               <Self::ConcreteElement as ElementExt>::Snapshot)>;
 
     fn needs_paint_from_layout(&self);
     fn will_paint(&self);
 }
 
 pub trait PresentationalHintsSynthetizer {
     fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
-        where V: Push<DeclarationBlock>;
+        where V: Push<ApplicableDeclarationBlock>;
 }
 
 pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + PresentationalHintsSynthetizer {
     type ConcreteNode: TNode<ConcreteElement = Self, ConcreteDocument = Self::ConcreteDocument>;
     type ConcreteDocument: TDocument<ConcreteNode = Self::ConcreteNode, ConcreteElement = Self>;
 
     fn as_node(&self) -> Self::ConcreteNode;
 
--- a/servo/components/style/keyframes.rs
+++ b/servo/components/style/keyframes.rs
@@ -70,17 +70,17 @@ impl KeyframeSelector {
 /// A keyframe.
 #[derive(Debug, Clone, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub struct Keyframe {
     pub selector: KeyframeSelector,
 
     /// `!important` is not allowed in keyframe declarations,
     /// so the second value of these tuples is always `Importance::Normal`.
-    /// But including them enables `compute_style_for_animation_step` to create a `DeclarationBlock`
+    /// But including them enables `compute_style_for_animation_step` to create a `ApplicableDeclarationBlock`
     /// by cloning an `Arc<_>` (incrementing a reference count) rather than re-creating a `Vec<_>`.
     pub block: Arc<PropertyDeclarationBlock>,
 }
 
 /// A keyframes step value. This can be a synthetised keyframes animation, that
 /// is, one autogenerated from the current computed values, or a list of
 /// declarations to apply.
 // TODO: Find a better name for this?
--- a/servo/components/style/matching.rs
+++ b/servo/components/style/matching.rs
@@ -11,17 +11,17 @@ use arc_ptr_eq;
 use cache::{LRUCache, SimpleHashCache};
 use cascade_info::CascadeInfo;
 use context::{StyleContext, SharedStyleContext};
 use data::PrivateStyleData;
 use dom::{TElement, TNode, TRestyleDamage, UnsafeNode};
 use properties::longhands::display::computed_value as display;
 use properties::{ComputedValues, cascade, PropertyDeclarationBlock};
 use selector_impl::{TheSelectorImpl, PseudoElement};
-use selector_matching::{DeclarationBlock, Stylist};
+use selector_matching::{ApplicableDeclarationBlock, Stylist};
 use selectors::bloom::BloomFilter;
 use selectors::matching::{MatchingReason, StyleRelations, AFFECTED_BY_PSEUDO_ELEMENTS};
 use selectors::{Element, MatchAttr};
 use sink::ForgetfulSink;
 use smallvec::SmallVec;
 use std::collections::HashMap;
 use std::hash::{BuildHasherDefault, Hash, Hasher};
 use std::slice::IterMut;
@@ -46,19 +46,19 @@ fn create_common_style_affecting_attribu
                 }
             }
         }
     }
     flags
 }
 
 pub struct ApplicableDeclarations {
-    pub normal: SmallVec<[DeclarationBlock; 16]>,
+    pub normal: SmallVec<[ApplicableDeclarationBlock; 16]>,
     pub per_pseudo: HashMap<PseudoElement,
-                            Vec<DeclarationBlock>,
+                            Vec<ApplicableDeclarationBlock>,
                             BuildHasherDefault<::fnv::FnvHasher>>,
 
     /// Whether the `normal` declarations are shareable with other nodes.
     pub normal_shareable: bool,
 }
 
 impl ApplicableDeclarations {
     pub fn new() -> Self {
@@ -73,21 +73,21 @@ impl ApplicableDeclarations {
         });
 
         applicable_declarations
     }
 }
 
 #[derive(Clone)]
 pub struct ApplicableDeclarationsCacheEntry {
-    pub declarations: Vec<DeclarationBlock>,
+    pub declarations: Vec<ApplicableDeclarationBlock>,
 }
 
 impl ApplicableDeclarationsCacheEntry {
-    fn new(declarations: Vec<DeclarationBlock>) -> ApplicableDeclarationsCacheEntry {
+    fn new(declarations: Vec<ApplicableDeclarationBlock>) -> ApplicableDeclarationsCacheEntry {
         ApplicableDeclarationsCacheEntry {
             declarations: declarations,
         }
     }
 }
 
 impl PartialEq for ApplicableDeclarationsCacheEntry {
     fn eq(&self, other: &ApplicableDeclarationsCacheEntry) -> bool {
@@ -100,21 +100,21 @@ impl Eq for ApplicableDeclarationsCacheE
 impl Hash for ApplicableDeclarationsCacheEntry {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let tmp = ApplicableDeclarationsCacheQuery::new(&*self.declarations);
         tmp.hash(state);
     }
 }
 
 struct ApplicableDeclarationsCacheQuery<'a> {
-    declarations: &'a [DeclarationBlock],
+    declarations: &'a [ApplicableDeclarationBlock],
 }
 
 impl<'a> ApplicableDeclarationsCacheQuery<'a> {
-    fn new(declarations: &'a [DeclarationBlock]) -> ApplicableDeclarationsCacheQuery<'a> {
+    fn new(declarations: &'a [ApplicableDeclarationBlock]) -> ApplicableDeclarationsCacheQuery<'a> {
         ApplicableDeclarationsCacheQuery {
             declarations: declarations,
         }
     }
 }
 
 impl<'a> PartialEq for ApplicableDeclarationsCacheQuery<'a> {
     fn eq(&self, other: &ApplicableDeclarationsCacheQuery<'a>) -> bool {
@@ -154,24 +154,24 @@ pub struct ApplicableDeclarationsCache {
 
 impl ApplicableDeclarationsCache {
     pub fn new() -> Self {
         ApplicableDeclarationsCache {
             cache: SimpleHashCache::new(APPLICABLE_DECLARATIONS_CACHE_SIZE),
         }
     }
 
-    pub fn find(&self, declarations: &[DeclarationBlock]) -> Option<Arc<ComputedValues>> {
+    pub fn find(&self, declarations: &[ApplicableDeclarationBlock]) -> Option<Arc<ComputedValues>> {
         match self.cache.find(&ApplicableDeclarationsCacheQuery::new(declarations)) {
             None => None,
             Some(ref values) => Some((*values).clone()),
         }
     }
 
-    pub fn insert(&mut self, declarations: Vec<DeclarationBlock>, style: Arc<ComputedValues>) {
+    pub fn insert(&mut self, declarations: Vec<ApplicableDeclarationBlock>, style: Arc<ComputedValues>) {
         self.cache.insert(ApplicableDeclarationsCacheEntry::new(declarations), style)
     }
 
     pub fn evict_all(&mut self) {
         self.cache.evict_all();
     }
 }
 
@@ -488,17 +488,17 @@ pub enum StyleSharingResult<ConcreteRest
 trait PrivateMatchMethods: TNode {
     /// Actually cascades style for a node or a pseudo-element of a node.
     ///
     /// Note that animations only apply to nodes or ::before or ::after
     /// pseudo-elements.
     fn cascade_node_pseudo_element<'a, Ctx>(&self,
                                             context: &Ctx,
                                             parent_style: Option<&Arc<ComputedValues>>,
-                                            applicable_declarations: &[DeclarationBlock],
+                                            applicable_declarations: &[ApplicableDeclarationBlock],
                                             mut old_style: Option<&mut Arc<ComputedValues>>,
                                             applicable_declarations_cache:
                                              &mut ApplicableDeclarationsCache,
                                             shareable: bool,
                                             animate_properties: bool)
                                             -> Arc<ComputedValues>
         where Ctx: StyleContext<'a>
     {
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -24,17 +24,17 @@ use error_reporting::ParseErrorReporter;
 use url::Url;
 #[cfg(feature = "servo")] use euclid::side_offsets::SideOffsets2D;
 use euclid::size::Size2D;
 use string_cache::Atom;
 use computed_values;
 #[cfg(feature = "servo")] use logical_geometry::{LogicalMargin, PhysicalSide};
 use logical_geometry::WritingMode;
 use parser::{ParserContext, ParserContextExtraData, log_css_error};
-use selector_matching::DeclarationBlock;
+use selector_matching::ApplicableDeclarationBlock;
 use stylesheets::Origin;
 use values::LocalToCss;
 use values::HasViewportPercentage;
 use values::computed::{self, ToComputedValue};
 use cascade_info::CascadeInfo;
 #[cfg(feature = "servo")] use values::specified::BorderStyle;
 
 use self::property_bit_field::PropertyBitField;
@@ -1713,17 +1713,17 @@ mod lazy_static_module {
         };
     }
 }
 
 /// Fast path for the function below. Only computes new inherited styles.
 #[allow(unused_mut, unused_imports)]
 fn cascade_with_cached_declarations(
         viewport_size: Size2D<Au>,
-        applicable_declarations: &[DeclarationBlock],
+        applicable_declarations: &[ApplicableDeclarationBlock],
         shareable: bool,
         parent_style: &ComputedValues,
         cached_style: &ComputedValues,
         custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
         mut cascade_info: Option<<&mut CascadeInfo>,
         mut error_reporter: StdBox<ParseErrorReporter + Send>)
         -> ComputedValues {
     let mut context = computed::Context {
@@ -1858,17 +1858,17 @@ static CASCADE_PROPERTY: [CascadePropert
 ///
 ///   * `cached_style`: If present, cascading is short-circuited for everything but inherited
 ///     values and these values are used instead. Obviously, you must be careful when supplying
 ///     this that it is safe to only provide inherited declarations. If `parent_style` is `None`,
 ///     this is ignored.
 ///
 /// Returns the computed values and a boolean indicating whether the result is cacheable.
 pub fn cascade(viewport_size: Size2D<Au>,
-               applicable_declarations: &[DeclarationBlock],
+               applicable_declarations: &[ApplicableDeclarationBlock],
                shareable: bool,
                parent_style: Option<<&ComputedValues>,
                cached_style: Option<<&ComputedValues>,
                mut cascade_info: Option<<&mut CascadeInfo>,
                mut error_reporter: StdBox<ParseErrorReporter + Send>)
                -> (ComputedValues, bool) {
     let initial_values = ComputedValues::initial_values();
     let (is_root_element, inherited_style) = match parent_style {
--- a/servo/components/style/selector_matching.rs
+++ b/servo/components/style/selector_matching.rs
@@ -33,18 +33,17 @@ use stylesheets::{CSSRule, CSSRuleIterat
 use viewport::{MaybeNew, ViewportRuleCascade};
 
 pub type FnvHashMap<K, V> = HashMap<K, V, BuildHasherDefault<::fnv::FnvHasher>>;
 
 /// 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`
 /// depending on the pseudo-element (see `PerPseudoElementSelectorMap`),
-/// stylesheet origin (see `PerOriginSelectorMap`), and priority
-/// (see the `normal` and `important` fields in `PerOriginSelectorMap`).
+/// and stylesheet origin (see the fields of `PerPseudoElementSelectorMap`).
 ///
 /// This structure is effectively created once per pipeline, in the
 /// LayoutThread corresponding to that pipeline.
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub struct Stylist {
     /// Device that the stylist is currently evaluating against.
     pub device: Device,
 
@@ -66,17 +65,17 @@ pub struct Stylist {
     pseudos_map: FnvHashMap<PseudoElement, PerPseudoElementSelectorMap>,
 
     /// A map with all the animations indexed by name.
     animations: FnvHashMap<Atom, KeyframesAnimation>,
 
     /// Applicable declarations for a given non-eagerly cascaded pseudo-element.
     /// These are eagerly computed once, and then used to resolve the new
     /// computed values on the fly on layout.
-    precomputed_pseudo_element_decls: FnvHashMap<PseudoElement, Vec<DeclarationBlock>>,
+    precomputed_pseudo_element_decls: FnvHashMap<PseudoElement, Vec<ApplicableDeclarationBlock>>,
 
     rules_source_order: usize,
 
     /// Selector dependencies used to compute restyle hints.
     state_deps: DependencySet,
 
     /// Selectors in the page affecting siblings
     sibling_affecting_selectors: Vec<Selector<TheSelectorImpl>>,
@@ -157,48 +156,36 @@ impl Stylist {
     }
 
     fn add_stylesheet(&mut self, stylesheet: &Stylesheet) {
         if !stylesheet.is_effective_for_device(&self.device) {
             return;
         }
         let mut rules_source_order = self.rules_source_order;
 
-        // Take apart the StyleRule into individual Rules and insert
-        // them into the SelectorMap of that priority.
-        macro_rules! append(
-            ($style_rule: ident, $priority: ident, $importance: expr) => {
-                for selector in &$style_rule.selectors {
-                    let map = if let Some(ref pseudo) = selector.pseudo_element {
-                        self.pseudos_map
-                            .entry(pseudo.clone())
-                            .or_insert_with(PerPseudoElementSelectorMap::new)
-                            .borrow_for_origin(&stylesheet.origin)
-                    } else {
-                        self.element_map.borrow_for_origin(&stylesheet.origin)
-                    };
-
-                    map.$priority.insert(Rule {
-                        selector: selector.complex_selector.clone(),
-                        declarations: DeclarationBlock {
-                            specificity: selector.specificity,
-                            mixed_declarations: $style_rule.declarations.clone(),
-                            importance: $importance,
-                            source_order: rules_source_order,
-                        },
-                    });
-                }
-            };
-        );
-
         for rule in stylesheet.effective_rules(&self.device) {
             match *rule {
                 CSSRule::Style(ref style_rule) => {
-                    append!(style_rule, normal, Importance::Normal);
-                    append!(style_rule, important, Importance::Important);
+                    for selector in &style_rule.selectors {
+                        let map = if let Some(ref pseudo) = selector.pseudo_element {
+                            self.pseudos_map
+                                .entry(pseudo.clone())
+                                .or_insert_with(PerPseudoElementSelectorMap::new)
+                                .borrow_for_origin(&stylesheet.origin)
+                        } else {
+                            self.element_map.borrow_for_origin(&stylesheet.origin)
+                        };
+
+                        map.insert(Rule {
+                            selector: selector.complex_selector.clone(),
+                            declarations: style_rule.declarations.clone(),
+                            specificity: selector.specificity,
+                            source_order: rules_source_order,
+                        });
+                    }
                     rules_source_order += 1;
 
                     for selector in &style_rule.selectors {
                         self.state_deps.note_selector(&selector.complex_selector);
                         if selector.affects_siblings() {
                             self.sibling_affecting_selectors.push(selector.clone());
                         }
 
@@ -237,18 +224,17 @@ impl Stylist {
 
         TheSelectorImpl::each_precomputed_pseudo_element(|pseudo| {
             // TODO: Consider not doing this and just getting the rules on the
             // fly. It should be a bit slower, but we'd take rid of the
             // extra field, and avoid this precomputation entirely.
             if let Some(map) = self.pseudos_map.remove(&pseudo) {
                 let mut declarations = vec![];
 
-                map.user_agent.normal.get_universal_rules(&mut declarations);
-                map.user_agent.important.get_universal_rules(&mut declarations);
+                map.user_agent.get_universal_rules(&mut declarations);
 
                 self.precomputed_pseudo_element_decls.insert(pseudo, declarations);
             }
         })
     }
 
     /// Computes the style for a given "precomputed" pseudo-element, taking the
     /// universal rules and applying them.
@@ -345,17 +331,17 @@ impl Stylist {
                                         parent_bf: Option<&BloomFilter>,
                                         style_attribute: Option<&Arc<PropertyDeclarationBlock>>,
                                         pseudo_element: Option<&PseudoElement>,
                                         applicable_declarations: &mut V,
                                         reason: MatchingReason) -> StyleRelations
         where E: Element<Impl=TheSelectorImpl> +
                  fmt::Debug +
                  PresentationalHintsSynthetizer,
-              V: Push<DeclarationBlock> + VecLike<DeclarationBlock>
+              V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock>
     {
         assert!(!self.is_device_dirty);
         assert!(style_attribute.is_none() || pseudo_element.is_none(),
                 "Style attributes do not apply to pseudo-elements");
         debug_assert!(pseudo_element.is_none() ||
                       !TheSelectorImpl::pseudo_element_cascade_type(pseudo_element.as_ref().unwrap())
                         .is_precomputed());
 
@@ -363,99 +349,99 @@ impl Stylist {
             Some(ref pseudo) => self.pseudos_map.get(pseudo).unwrap(),
             None => &self.element_map,
         };
 
         let mut relations = StyleRelations::empty();
 
         debug!("Determining if style is shareable: pseudo: {}", pseudo_element.is_some());
         // Step 1: Normal user-agent rules.
-        map.user_agent.normal.get_all_matching_rules(element,
-                                                     parent_bf,
-                                                     applicable_declarations,
-                                                     &mut relations,
-                                                     reason,
-                                                     Importance::Normal);
+        map.user_agent.get_all_matching_rules(element,
+                                              parent_bf,
+                                              applicable_declarations,
+                                              &mut relations,
+                                              reason,
+                                              Importance::Normal);
         debug!("UA normal: {:?}", relations);
 
         // Step 2: Presentational hints.
         let length = applicable_declarations.len();
         element.synthesize_presentational_hints_for_legacy_attributes(applicable_declarations);
         if applicable_declarations.len() != length {
             // Never share style for elements with preshints
             relations |= AFFECTED_BY_PRESENTATIONAL_HINTS;
         }
         debug!("preshints: {:?}", relations);
 
         // Step 3: User and author normal rules.
-        map.user.normal.get_all_matching_rules(element,
-                                               parent_bf,
-                                               applicable_declarations,
-                                               &mut relations,
-                                               reason,
-                                               Importance::Normal);
+        map.user.get_all_matching_rules(element,
+                                        parent_bf,
+                                        applicable_declarations,
+                                        &mut relations,
+                                        reason,
+                                        Importance::Normal);
         debug!("user normal: {:?}", relations);
-        map.author.normal.get_all_matching_rules(element,
-                                                 parent_bf,
-                                                 applicable_declarations,
-                                                 &mut relations,
-                                                 reason,
-                                                 Importance::Normal);
+        map.author.get_all_matching_rules(element,
+                                          parent_bf,
+                                          applicable_declarations,
+                                          &mut relations,
+                                          reason,
+                                          Importance::Normal);
         debug!("author normal: {:?}", relations);
 
         // Step 4: Normal style attributes.
         if let Some(sa)  = style_attribute {
             if sa.any_normal() {
                 relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
                 Push::push(
                     applicable_declarations,
-                    DeclarationBlock::from_declarations(sa.clone(), Importance::Normal));
+                    ApplicableDeclarationBlock::from_declarations(sa.clone(), Importance::Normal));
             }
         }
 
         debug!("style attr: {:?}", relations);
 
         // Step 5: Author-supplied `!important` rules.
-        map.author.important.get_all_matching_rules(element,
-                                                    parent_bf,
-                                                    applicable_declarations,
-                                                    &mut relations,
-                                                    reason,
-                                                    Importance::Important);
+        map.author.get_all_matching_rules(element,
+                                          parent_bf,
+                                          applicable_declarations,
+                                          &mut relations,
+                                          reason,
+                                          Importance::Important);
 
         debug!("author important: {:?}", relations);
 
         // Step 6: `!important` style attributes.
         if let Some(sa) = style_attribute {
             if sa.any_important() {
                 relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
                 Push::push(
                     applicable_declarations,
-                    DeclarationBlock::from_declarations(sa.clone(), Importance::Important));
+                    ApplicableDeclarationBlock::from_declarations(sa.clone(), Importance::Important));
             }
         }
 
         debug!("style attr important: {:?}", relations);
 
         // Step 7: User and UA `!important` rules.
-        map.user.important.get_all_matching_rules(element,
-                                                  parent_bf,
-                                                  applicable_declarations,
-                                                  &mut relations,
-                                                  reason,
-                                                  Importance::Important);
+        map.user.get_all_matching_rules(element,
+                                        parent_bf,
+                                        applicable_declarations,
+                                        &mut relations,
+                                        reason,
+                                        Importance::Important);
 
         debug!("user important: {:?}", relations);
 
-        map.user_agent.important.get_all_matching_rules(element,
-                                                        parent_bf,
-                                                        applicable_declarations,
-                                                        &mut relations,
-                                                        reason,
-                                                        Importance::Important);
+        map.user_agent.get_all_matching_rules(element,
+                                              parent_bf,
+                                              applicable_declarations,
+                                              &mut relations,
+                                              reason,
+                                              Importance::Important);
 
         debug!("UA important: {:?}", relations);
 
         debug!("push_applicable_declarations: shareable: {:?}", relations);
 
         relations
     }
 
@@ -544,61 +530,40 @@ impl Stylist {
                                    -> RestyleHint
         where E: ElementExt + Clone
     {
         self.state_deps.compute_hint(element, snapshot, current_state)
     }
 }
 
 
-/// Map that contains the CSS rules for a given origin.
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-struct PerOriginSelectorMap {
-    /// Rules that contains at least one property declaration with
-    /// normal importance.
-    normal: SelectorMap,
-    /// Rules that contains at least one property declaration with
-    /// !important.
-    important: SelectorMap,
-}
-
-impl PerOriginSelectorMap {
-    #[inline]
-    fn new() -> Self {
-        PerOriginSelectorMap {
-            normal: SelectorMap::new(),
-            important: SelectorMap::new(),
-        }
-    }
-}
-
 /// Map that contains the CSS rules for a specific PseudoElement
 /// (or lack of PseudoElement).
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 struct PerPseudoElementSelectorMap {
     /// Rules from user agent stylesheets
-    user_agent: PerOriginSelectorMap,
+    user_agent: SelectorMap,
     /// Rules from author stylesheets
-    author: PerOriginSelectorMap,
+    author: SelectorMap,
     /// Rules from user stylesheets
-    user: PerOriginSelectorMap,
+    user: SelectorMap,
 }
 
 impl PerPseudoElementSelectorMap {
     #[inline]
     fn new() -> Self {
         PerPseudoElementSelectorMap {
-            user_agent: PerOriginSelectorMap::new(),
-            author: PerOriginSelectorMap::new(),
-            user: PerOriginSelectorMap::new(),
+            user_agent: SelectorMap::new(),
+            author: SelectorMap::new(),
+            user: SelectorMap::new(),
         }
     }
 
     #[inline]
-    fn borrow_for_origin(&mut self, origin: &Origin) -> &mut PerOriginSelectorMap {
+    fn borrow_for_origin(&mut self, origin: &Origin) -> &mut SelectorMap {
         match *origin {
             Origin::UserAgent => &mut self.user_agent,
             Origin::Author => &mut self.author,
             Origin::User => &mut self.user,
         }
     }
 }
 
@@ -660,17 +625,17 @@ impl SelectorMap {
     pub fn get_all_matching_rules<E, V>(&self,
                                         element: &E,
                                         parent_bf: Option<&BloomFilter>,
                                         matching_rules_list: &mut V,
                                         relations: &mut StyleRelations,
                                         reason: MatchingReason,
                                         importance: Importance)
         where E: Element<Impl=TheSelectorImpl>,
-              V: VecLike<DeclarationBlock>
+              V: VecLike<ApplicableDeclarationBlock>
     {
         if self.empty {
             return
         }
 
         // At the end, we're going to sort the rules that we added, so remember where we began.
         let init_len = matching_rules_list.len();
         if let Some(id) = element.get_id() {
@@ -721,28 +686,35 @@ impl SelectorMap {
         sort_by_key(&mut matching_rules_list[init_len..],
                     |rule| (rule.specificity, rule.source_order));
     }
 
     /// Append to `rule_list` all universal Rules (rules with selector `*|*`) in
     /// `self` sorted by specifity and source order.
     pub fn get_universal_rules<V>(&self,
                                   matching_rules_list: &mut V)
-        where V: VecLike<DeclarationBlock>
+        where V: VecLike<ApplicableDeclarationBlock>
     {
         if self.empty {
             return
         }
 
         let init_len = matching_rules_list.len();
 
         for rule in self.other_rules.iter() {
             if rule.selector.compound_selector.is_empty() &&
                rule.selector.next.is_none() {
-                matching_rules_list.push(rule.declarations.clone());
+                if rule.declarations.any_normal() {
+                    matching_rules_list.push(
+                        rule.to_applicable_declaration_block(Importance::Normal));
+                }
+                if rule.declarations.any_important() {
+                    matching_rules_list.push(
+                        rule.to_applicable_declaration_block(Importance::Important));
+                }
             }
         }
 
         sort_by_key(&mut matching_rules_list[init_len..],
                     |rule| (rule.specificity, rule.source_order));
     }
 
     fn get_matching_rules_from_hash<E, Str, BorrowedStr: ?Sized, Vector>(
@@ -752,17 +724,17 @@ impl SelectorMap {
         key: &BorrowedStr,
         matching_rules: &mut Vector,
         relations: &mut StyleRelations,
         reason: MatchingReason,
         importance: Importance)
         where E: Element<Impl=TheSelectorImpl>,
               Str: Borrow<BorrowedStr> + Eq + Hash,
               BorrowedStr: Eq + Hash,
-              Vector: VecLike<DeclarationBlock>
+              Vector: VecLike<ApplicableDeclarationBlock>
     {
         if let Some(rules) = hash.get(key) {
             SelectorMap::get_matching_rules(element,
                                             parent_bf,
                                             rules,
                                             matching_rules,
                                             relations,
                                             reason,
@@ -774,29 +746,29 @@ impl SelectorMap {
     fn get_matching_rules<E, V>(element: &E,
                                 parent_bf: Option<&BloomFilter>,
                                 rules: &[Rule],
                                 matching_rules: &mut V,
                                 relations: &mut StyleRelations,
                                 reason: MatchingReason,
                                 importance: Importance)
         where E: Element<Impl=TheSelectorImpl>,
-              V: VecLike<DeclarationBlock>
+              V: VecLike<ApplicableDeclarationBlock>
     {
         for rule in rules.iter() {
-            let block = &rule.declarations.mixed_declarations;
+            let block = &rule.declarations;
             let any_declaration_for_importance = if importance.important() {
                 block.any_important()
             } else {
                 block.any_normal()
             };
             if any_declaration_for_importance &&
                matches_complex_selector(&*rule.selector, element, parent_bf,
                                         relations, reason) {
-                matching_rules.push(rule.declarations.clone());
+                matching_rules.push(rule.to_applicable_declaration_block(importance));
             }
         }
     }
 
     /// Insert rule into the correct hash.
     /// Order in which to try: id_hash, class_hash, local_name_hash, other_rules.
     pub fn insert(&mut self, rule: Rule) {
         self.empty = false;
@@ -863,73 +835,87 @@ impl SelectorMap {
 
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[derive(Clone)]
 pub struct Rule {
     // This is an Arc because Rule will essentially be cloned for every element
     // that it matches. Selector contains an owned vector (through
     // ComplexSelector) and we want to avoid the allocation.
     pub selector: Arc<ComplexSelector<TheSelectorImpl>>,
-    pub declarations: DeclarationBlock,
+    pub declarations: Arc<PropertyDeclarationBlock>,
+    pub source_order: usize,
+    pub specificity: u32,
+}
+
+impl Rule {
+    fn to_applicable_declaration_block(&self, importance: Importance)
+                                       -> ApplicableDeclarationBlock {
+        ApplicableDeclarationBlock {
+            mixed_declarations: self.declarations.clone(),
+            importance: importance,
+            source_order: self.source_order,
+            specificity: self.specificity,
+        }
+    }
 }
 
 /// A property declaration together with its precedence among rules of equal specificity so that
 /// we can sort them.
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[derive(Debug, Clone)]
-pub struct DeclarationBlock {
+pub struct ApplicableDeclarationBlock {
     /// Contains declarations of either importance, but only those of self.importance are relevant.
-    /// Use DeclarationBlock::iter
+    /// Use ApplicableDeclarationBlock::iter
     pub mixed_declarations: Arc<PropertyDeclarationBlock>,
     pub importance: Importance,
     pub source_order: usize,
     pub specificity: u32,
 }
 
-impl DeclarationBlock {
+impl ApplicableDeclarationBlock {
     #[inline]
     pub fn from_declarations(declarations: Arc<PropertyDeclarationBlock>,
                              importance: Importance)
                              -> Self {
-        DeclarationBlock {
+        ApplicableDeclarationBlock {
             mixed_declarations: declarations,
             importance: importance,
             source_order: 0,
             specificity: 0,
         }
     }
 
-    pub fn iter(&self) -> DeclarationBlockIter {
-        DeclarationBlockIter {
+    pub fn iter(&self) -> ApplicableDeclarationBlockIter {
+        ApplicableDeclarationBlockIter {
             iter: self.mixed_declarations.declarations.iter(),
             importance: self.importance,
         }
     }
 }
 
-pub struct DeclarationBlockIter<'a> {
+pub struct ApplicableDeclarationBlockIter<'a> {
     iter: slice::Iter<'a, (PropertyDeclaration, Importance)>,
     importance: Importance,
 }
 
-impl<'a> Iterator for DeclarationBlockIter<'a> {
+impl<'a> Iterator for ApplicableDeclarationBlockIter<'a> {
     type Item = &'a PropertyDeclaration;
 
     #[inline]
     fn next(&mut self) -> Option<Self::Item> {
         while let Some(&(ref declaration, importance)) = self.iter.next() {
             if importance == self.importance {
                 return Some(declaration)
             }
         }
         None
     }
 }
 
-impl<'a> DoubleEndedIterator for DeclarationBlockIter<'a> {
+impl<'a> DoubleEndedIterator for ApplicableDeclarationBlockIter<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<Self::Item> {
         while let Some(&(ref declaration, importance)) = self.iter.next_back() {
             if importance == self.importance {
                 return Some(declaration)
             }
         }
         None
--- a/servo/ports/geckolib/wrapper.rs
+++ b/servo/ports/geckolib/wrapper.rs
@@ -46,17 +46,17 @@ use style::dom::{TDocument, TElement, TN
 use style::element_state::ElementState;
 use style::error_reporting::StdoutErrorReporter;
 use style::gecko_selector_impl::{GeckoSelectorImpl, NonTSPseudoClass, PseudoElement};
 use style::parser::ParserContextExtraData;
 use style::properties::PropertyDeclarationBlock;
 use style::properties::{ComputedValues, parse_style_attribute};
 use style::refcell::{Ref, RefCell, RefMut};
 use style::selector_impl::ElementExt;
-use style::selector_matching::DeclarationBlock;
+use style::selector_matching::ApplicableDeclarationBlock;
 use style::sink::Push;
 use url::Url;
 
 pub struct NonOpaqueStyleData(RefCell<PrivateStyleData>);
 
 unsafe impl HasFFI for NonOpaqueStyleData {
     type FFIType = ServoNodeData;
 }
@@ -479,17 +479,17 @@ impl<'le> TElement for GeckoElement<'le>
 impl<'le> PartialEq for GeckoElement<'le> {
     fn eq(&self, other: &Self) -> bool {
         self.0 as *const _ == other.0 as *const _
     }
 }
 
 impl<'le> PresentationalHintsSynthetizer for GeckoElement<'le> {
     fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
-        where V: Push<DeclarationBlock>
+        where V: Push<ApplicableDeclarationBlock>
     {
         // FIXME(bholley) - Need to implement this.
     }
 }
 
 impl<'le> ::selectors::Element for GeckoElement<'le> {
     fn parent_element(&self) -> Option<Self> {
         unsafe {
--- a/servo/tests/unit/style/selector_matching.rs
+++ b/servo/tests/unit/style/selector_matching.rs
@@ -1,37 +1,39 @@
 /* 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/. */
 
 use cssparser::Parser;
 use selectors::parser::{LocalName, ParserContext, parse_selector_list};
 use std::sync::Arc;
 use string_cache::Atom;
-use style::properties::{Importance, PropertyDeclarationBlock};
-use style::selector_matching::{DeclarationBlock, Rule, SelectorMap};
+use style::properties::{PropertyDeclarationBlock, PropertyDeclaration, DeclaredValue};
+use style::properties::{longhands, Importance};
+use style::selector_matching::{Rule, SelectorMap};
 
 /// Helper method to get some Rules from selector strings.
 /// Each sublist of the result contains the Rules for one StyleRule.
 fn get_mock_rules(css_selectors: &[&str]) -> Vec<Vec<Rule>> {
     css_selectors.iter().enumerate().map(|(i, selectors)| {
         let context = ParserContext::new();
         parse_selector_list(&context, &mut Parser::new(*selectors))
         .unwrap().into_iter().map(|s| {
             Rule {
                 selector: s.complex_selector.clone(),
-                declarations: DeclarationBlock {
-                    mixed_declarations: Arc::new(PropertyDeclarationBlock {
-                        declarations: Vec::new(),
-                        important_count: 0,
-                    }),
-                    importance: Importance::Normal,
-                    specificity: s.specificity,
-                    source_order: i,
-                }
+                declarations: Arc::new(PropertyDeclarationBlock {
+                    declarations: vec![
+                        (PropertyDeclaration::Display(DeclaredValue::Value(
+                            longhands::display::SpecifiedValue::block)),
+                         Importance::Normal),
+                    ],
+                    important_count: 0,
+                }),
+                specificity: s.specificity,
+                source_order: i,
             }
         }).collect()
     }).collect()
 }
 
 fn get_mock_map(selectors: &[&str]) -> SelectorMap {
     let mut map = SelectorMap::new();
     let selector_rules = get_mock_rules(selectors);
@@ -43,18 +45,18 @@ fn get_mock_map(selectors: &[&str]) -> S
     }
 
     map
 }
 
 #[test]
 fn test_rule_ordering_same_specificity() {
     let rules_list = get_mock_rules(&["a.intro", "img.sidebar"]);
-    let a = &rules_list[0][0].declarations;
-    let b = &rules_list[1][0].declarations;
+    let a = &rules_list[0][0];
+    let b = &rules_list[1][0];
     assert!((a.specificity, a.source_order) < ((b.specificity, b.source_order)),
             "The rule that comes later should win.");
 }
 
 
 #[test]
 fn test_get_id_name() {
     let rules_list = get_mock_rules(&[".intro", "#top"]);
@@ -84,19 +86,19 @@ fn test_get_local_name() {
     check(3, Some(("ImG", "img")));
 }
 
 #[test]
 fn test_insert() {
     let rules_list = get_mock_rules(&[".intro.foo", "#top"]);
     let mut selector_map = SelectorMap::new();
     selector_map.insert(rules_list[1][0].clone());
-    assert_eq!(1, selector_map.id_hash.get(&atom!("top")).unwrap()[0].declarations.source_order);
+    assert_eq!(1, selector_map.id_hash.get(&atom!("top")).unwrap()[0].source_order);
     selector_map.insert(rules_list[0][0].clone());
-    assert_eq!(0, selector_map.class_hash.get(&Atom::from("intro")).unwrap()[0].declarations.source_order);
+    assert_eq!(0, selector_map.class_hash.get(&Atom::from("intro")).unwrap()[0].source_order);
     assert!(selector_map.class_hash.get(&Atom::from("foo")).is_none());
 }
 
 #[test]
 fn test_get_universal_rules() {
     let map = get_mock_map(&["*|*", "#foo > *|*", ".klass", "#id"]);
     let mut decls = vec![];