Bug 1477628 - Convert FnvHash{Set,Map} instances to FxHash{Set,Map}. r=heycam
☠☠ backed out by 75ec3f923e76 ☠ ☠
authorNicholas Nethercote <nnethercote@mozilla.com>
Fri, 27 Jul 2018 09:01:15 +1000
changeset 428675 72b855b514f912ddd458272348b3849361ed4deb
parent 428674 2f7364bad51af4d5d0c5873a65bfdf5e7f909394
child 428676 06b8093ddc6a341b8be4ef2c4dca2188ada74296
push id34339
push userdluca@mozilla.com
push dateFri, 27 Jul 2018 10:20:10 +0000
treeherdermozilla-central@87bcafe428a4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1477628
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1477628 - Convert FnvHash{Set,Map} instances to FxHash{Set,Map}. r=heycam It doesn't appear to make much difference to performance, but it does let us remove the `fnv` crate from the repo.
Cargo.lock
servo/components/selectors/Cargo.toml
servo/components/selectors/bloom.rs
servo/components/selectors/lib.rs
servo/components/selectors/nth_index_cache.rs
servo/components/style/Cargo.toml
servo/components/style/context.rs
servo/components/style/gecko/wrapper.rs
servo/components/style/hash.rs
servo/components/style/invalidation/media_queries.rs
servo/components/style/invalidation/stylesheets.rs
servo/components/style/lib.rs
servo/components/style/properties/helpers/animated_properties.mako.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/rule_cache.rs
servo/components/style/rule_tree/mod.rs
servo/components/style/servo/selector_parser.rs
servo/components/style/stylesheets/stylesheet.rs
servo/components/style/values/specified/position.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1799,17 +1799,17 @@ version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "selectors"
 version = "0.19.0"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_arc 0.1.1",
  "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1947,17 +1947,17 @@ dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fallible 0.0.1",
- "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.0.1",
--- a/servo/components/selectors/Cargo.toml
+++ b/servo/components/selectors/Cargo.toml
@@ -19,16 +19,16 @@ path = "lib.rs"
 [features]
 bench = []
 
 [dependencies]
 bitflags = "1.0"
 matches = "0.1"
 cssparser = "0.24.0"
 log = "0.4"
-fnv = "1.0"
+fxhash = "0.2"
 phf = "0.7.18"
 precomputed-hash = "0.1"
 servo_arc = { version = "0.1", path = "../servo_arc" }
 smallvec = "0.6"
 
 [build-dependencies]
 phf_codegen = "0.7.18"
--- a/servo/components/selectors/bloom.rs
+++ b/servo/components/selectors/bloom.rs
@@ -1,16 +1,16 @@
 /* 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/. */
 
 //! Counting and non-counting Bloom filters tuned for use as ancestor filters
 //! for selector matching.
 
-use fnv::FnvHasher;
+use fxhash::FxHasher;
 use std::fmt::{self, Debug};
 use std::hash::{Hash, Hasher};
 
 // The top 8 bits of the 32-bit hash value are not used by the bloom filter.
 // Consumers may rely on this to pack hashes more efficiently.
 pub const BLOOM_HASH_MASK: u32 = 0x00ffffff;
 const KEY_SIZE: usize = 12;
 
@@ -292,17 +292,17 @@ impl Clone for BloomStorageBool {
     fn clone(&self) -> Self {
         BloomStorageBool {
             counters: self.counters,
         }
     }
 }
 
 fn hash<T: Hash>(elem: &T) -> u32 {
-    let mut hasher = FnvHasher::default();
+    let mut hasher = FxHasher::default();
     elem.hash(&mut hasher);
     let hash: u64 = hasher.finish();
     (hash >> 32) as u32 ^ (hash as u32)
 }
 
 #[inline]
 fn hash1(hash: u32) -> u32 {
     hash & KEY_MASK
--- a/servo/components/selectors/lib.rs
+++ b/servo/components/selectors/lib.rs
@@ -4,17 +4,17 @@
 
 // Make |cargo bench| work.
 #![cfg_attr(feature = "bench", feature(test))]
 
 #[macro_use]
 extern crate bitflags;
 #[macro_use]
 extern crate cssparser;
-extern crate fnv;
+extern crate fxhash;
 #[macro_use]
 extern crate log;
 #[macro_use]
 extern crate matches;
 extern crate phf;
 extern crate precomputed_hash;
 extern crate servo_arc;
 extern crate smallvec;
--- a/servo/components/selectors/nth_index_cache.rs
+++ b/servo/components/selectors/nth_index_cache.rs
@@ -1,13 +1,13 @@
 /* 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 fnv::FnvHashMap;
+use fxhash::FxHashMap;
 use tree::OpaqueElement;
 
 /// A cache to speed up matching of nth-index-like selectors.
 ///
 /// See [1] for some discussion around the design tradeoffs.
 ///
 /// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1401855#c3
 #[derive(Default)]
@@ -27,17 +27,17 @@ impl NthIndexCache {
             (true, false) => &mut self.nth_of_type,
             (true, true) => &mut self.nth_last_of_type,
         }
     }
 }
 
 /// The concrete per-pseudo-class cache.
 #[derive(Default)]
-pub struct NthIndexCacheInner(FnvHashMap<OpaqueElement, i32>);
+pub struct NthIndexCacheInner(FxHashMap<OpaqueElement, i32>);
 
 impl NthIndexCacheInner {
     /// Does a lookup for a given element in the cache.
     pub fn lookup(&mut self, el: OpaqueElement) -> Option<i32> {
         self.0.get(&el).map(|x| *x)
     }
 
     /// Inserts an entry into the cache.
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -31,17 +31,17 @@ atomic_refcell = "0.1"
 bitflags = "1.0"
 byteorder = "1.0"
 cfg-if = "0.1.0"
 cssparser = "0.24.0"
 new_debug_unreachable = "1.0"
 encoding_rs = {version = "0.7", optional = true}
 euclid = "0.18"
 fallible = { path = "../fallible" }
-fnv = "1.0"
+fxhash = "0.2"
 hashglobe = { path = "../hashglobe" }
 html5ever = {version = "0.22", optional = true}
 itertools = "0.7.6"
 itoa = "0.4"
 lazy_static = "1"
 log = "0.4"
 malloc_size_of = { path = "../malloc_size_of" }
 malloc_size_of_derive = { path = "../malloc_size_of_derive" }
--- a/servo/components/style/context.rs
+++ b/servo/components/style/context.rs
@@ -9,17 +9,17 @@ use animation::Animation;
 use app_units::Au;
 use bloom::StyleBloom;
 use data::{EagerPseudoStyles, ElementData};
 use dom::{SendElement, TElement};
 #[cfg(feature = "servo")]
 use dom::OpaqueNode;
 use euclid::Size2D;
 use euclid::TypedScale;
-use fnv::FnvHashMap;
+use fxhash::FxHashMap;
 use font_metrics::FontMetricsProvider;
 #[cfg(feature = "gecko")]
 use gecko_bindings::structs;
 use parallel::{STACK_SAFETY_MARGIN_KB, STYLE_THREAD_STACK_SIZE_KB};
 #[cfg(feature = "servo")]
 use parking_lot::RwLock;
 use properties::ComputedValues;
 #[cfg(feature = "servo")]
@@ -168,21 +168,21 @@ pub struct SharedStyleContext<'a> {
     /// Flags controlling how we traverse the tree.
     pub traversal_flags: TraversalFlags,
 
     /// A map with our snapshots in order to handle restyle hints.
     pub snapshot_map: &'a SnapshotMap,
 
     /// The animations that are currently running.
     #[cfg(feature = "servo")]
-    pub running_animations: Arc<RwLock<FnvHashMap<OpaqueNode, Vec<Animation>>>>,
+    pub running_animations: Arc<RwLock<FxHashMap<OpaqueNode, Vec<Animation>>>>,
 
     /// The list of animations that have expired since the last style recalculation.
     #[cfg(feature = "servo")]
-    pub expired_animations: Arc<RwLock<FnvHashMap<OpaqueNode, Vec<Animation>>>>,
+    pub expired_animations: Arc<RwLock<FxHashMap<OpaqueNode, Vec<Animation>>>>,
 
     /// Paint worklets
     #[cfg(feature = "servo")]
     pub registered_speculative_painters: &'a RegisteredSpeculativePainters,
 
     /// Data needed to create the thread-local style context from the shared one.
     #[cfg(feature = "servo")]
     pub local_context_creation_data: Mutex<ThreadLocalStyleContextCreationInfo>,
@@ -565,34 +565,34 @@ impl<E: TElement> SequentialTask<E> {
 }
 
 type CacheItem<E> = (SendElement<E>, ElementSelectorFlags);
 
 /// Map from Elements to ElementSelectorFlags. Used to defer applying selector
 /// flags until after the traversal.
 pub struct SelectorFlagsMap<E: TElement> {
     /// The hashmap storing the flags to apply.
-    map: FnvHashMap<SendElement<E>, ElementSelectorFlags>,
+    map: FxHashMap<SendElement<E>, ElementSelectorFlags>,
     /// An LRU cache to avoid hashmap lookups, which can be slow if the map
     /// gets big.
     cache: LRUCache<[Entry<CacheItem<E>>; 4 + 1]>,
 }
 
 #[cfg(debug_assertions)]
 impl<E: TElement> Drop for SelectorFlagsMap<E> {
     fn drop(&mut self) {
         debug_assert!(self.map.is_empty());
     }
 }
 
 impl<E: TElement> SelectorFlagsMap<E> {
     /// Creates a new empty SelectorFlagsMap.
     pub fn new() -> Self {
         SelectorFlagsMap {
-            map: FnvHashMap::default(),
+            map: FxHashMap::default(),
             cache: LRUCache::default(),
         }
     }
 
     /// Inserts some flags into the map for a given element.
     pub fn insert_flags(&mut self, element: E, flags: ElementSelectorFlags) {
         let el = unsafe { SendElement::new(element) };
         // Check the cache. If the flags have already been noted, we're done.
@@ -828,17 +828,17 @@ pub struct StyleContext<'a, E: TElement 
 }
 
 /// A registered painter
 #[cfg(feature = "servo")]
 pub trait RegisteredSpeculativePainter: SpeculativePainter {
     /// The name it was registered with
     fn name(&self) -> Atom;
     /// The properties it was registered with
-    fn properties(&self) -> &FnvHashMap<Atom, PropertyId>;
+    fn properties(&self) -> &FxHashMap<Atom, PropertyId>;
 }
 
 /// A set of registered painters
 #[cfg(feature = "servo")]
 pub trait RegisteredSpeculativePainters: Sync {
     /// Look up a speculative painter
     fn get(&self, name: &Atom) -> Option<&RegisteredSpeculativePainter>;
 }
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -57,17 +57,17 @@ use gecko_bindings::structs::ELEMENT_HAS
 use gecko_bindings::structs::ELEMENT_HAS_SNAPSHOT;
 use gecko_bindings::structs::EffectCompositor_CascadeLevel as CascadeLevel;
 use gecko_bindings::structs::NODE_DESCENDANTS_NEED_FRAMES;
 use gecko_bindings::structs::NODE_NEEDS_FRAME;
 use gecko_bindings::structs::nsChangeHint;
 use gecko_bindings::structs::nsIDocument_DocumentTheme as DocumentTheme;
 use gecko_bindings::structs::nsRestyleHint;
 use gecko_bindings::sugar::ownership::{HasArcFFI, HasSimpleFFI};
-use hash::FnvHashMap;
+use hash::FxHashMap;
 use logical_geometry::WritingMode;
 use media_queries::Device;
 use properties::{ComputedValues, LonghandId};
 use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
 use properties::animated_properties::{AnimationValue, AnimationValueMap};
 use properties::style_structs::Font;
 use rule_tree::CascadeLevel as ServoCascadeLevel;
 use selector_parser::{AttrValue, Direction, PseudoClassStringArg};
@@ -862,22 +862,22 @@ impl<'le> GeckoElement<'le> {
         match self.containing_shadow_host() {
             Some(e) => {
                 e.is_svg_element() && e.local_name() == &*local_name!("use")
             },
             None => false,
         }
     }
 
-    fn css_transitions_info(&self) -> FnvHashMap<LonghandId, Arc<AnimationValue>> {
+    fn css_transitions_info(&self) -> FxHashMap<LonghandId, Arc<AnimationValue>> {
         use gecko_bindings::bindings::Gecko_ElementTransitions_EndValueAt;
         use gecko_bindings::bindings::Gecko_ElementTransitions_Length;
 
         let collection_length = unsafe { Gecko_ElementTransitions_Length(self.0) } as usize;
-        let mut map = FnvHashMap::with_capacity_and_hasher(collection_length, Default::default());
+        let mut map = FxHashMap::with_capacity_and_hasher(collection_length, Default::default());
 
         for i in 0..collection_length {
             let raw_end_value = unsafe { Gecko_ElementTransitions_EndValueAt(self.0, i) };
 
             let end_value = AnimationValue::arc_from_borrowed(&raw_end_value)
                 .expect("AnimationValue not found in ElementTransitions");
 
             let property = end_value.id();
@@ -888,17 +888,17 @@ impl<'le> GeckoElement<'le> {
     }
 
     fn needs_transitions_update_per_property(
         &self,
         longhand_id: LonghandId,
         combined_duration: f32,
         before_change_style: &ComputedValues,
         after_change_style: &ComputedValues,
-        existing_transitions: &FnvHashMap<LonghandId, Arc<AnimationValue>>,
+        existing_transitions: &FxHashMap<LonghandId, Arc<AnimationValue>>,
     ) -> bool {
         use values::animated::{Animate, Procedure};
         debug_assert!(!longhand_id.is_logical());
 
         // If there is an existing transition, update only if the end value
         // differs.
         //
         // If the end value has not changed, we should leave the currently
--- a/servo/components/style/hash.rs
+++ b/servo/components/style/hash.rs
@@ -2,17 +2,17 @@
  * 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/. */
 
 //! Reexports of hashglobe types in Gecko mode, and stdlib hashmap shims in Servo mode
 //!
 //! Can go away when the stdlib gets fallible collections
 //! https://github.com/rust-lang/rfcs/pull/2116
 
-use fnv;
+use fxhash;
 
 #[cfg(feature = "gecko")]
 pub use hashglobe::hash_map::HashMap;
 #[cfg(feature = "gecko")]
 pub use hashglobe::hash_set::HashSet;
 
 #[cfg(feature = "servo")]
 pub use hashglobe::fake::{HashMap, HashSet};
@@ -20,12 +20,12 @@ pub use hashglobe::fake::{HashMap, HashS
 /// Appropriate reexports of hash_map types
 pub mod map {
     #[cfg(feature = "gecko")]
     pub use hashglobe::hash_map::{Entry, Iter};
     #[cfg(feature = "servo")]
     pub use std::collections::hash_map::{Entry, Iter};
 }
 
-/// Hash map that uses the FNV hasher
-pub type FnvHashMap<K, V> = HashMap<K, V, fnv::FnvBuildHasher>;
-/// Hash set that uses the FNV hasher
-pub type FnvHashSet<T> = HashSet<T, fnv::FnvBuildHasher>;
+/// Hash map that uses the Fx hasher
+pub type FxHashMap<K, V> = HashMap<K, V, fxhash::FxBuildHasher>;
+/// Hash set that uses the Fx hasher
+pub type FxHashSet<T> = HashSet<T, fxhash::FxBuildHasher>;
--- a/servo/components/style/invalidation/media_queries.rs
+++ b/servo/components/style/invalidation/media_queries.rs
@@ -1,16 +1,16 @@
 /* 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/. */
 
 //! Code related to the invalidation of media-query-affected rules.
 
 use context::QuirksMode;
-use fnv::FnvHashSet;
+use fxhash::FxHashSet;
 use media_queries::Device;
 use shared_lock::SharedRwLockReadGuard;
 use stylesheets::{DocumentRule, ImportRule, MediaRule};
 use stylesheets::{NestedRuleIterationCondition, Stylesheet, SupportsRule};
 
 /// A key for a given media query result.
 ///
 /// NOTE: It happens to be the case that all the media lists we care about
@@ -49,24 +49,24 @@ impl ToMediaListKey for Stylesheet {}
 impl ToMediaListKey for ImportRule {}
 impl ToMediaListKey for MediaRule {}
 
 /// A struct that holds the result of a media query evaluation pass for the
 /// media queries that evaluated successfully.
 #[derive(Debug, MallocSizeOf, PartialEq)]
 pub struct EffectiveMediaQueryResults {
     /// The set of media lists that matched last time.
-    set: FnvHashSet<MediaListKey>,
+    set: FxHashSet<MediaListKey>,
 }
 
 impl EffectiveMediaQueryResults {
     /// Trivially constructs an empty `EffectiveMediaQueryResults`.
     pub fn new() -> Self {
         Self {
-            set: FnvHashSet::default(),
+            set: FxHashSet::default(),
         }
     }
 
     /// Resets the results, using an empty key.
     pub fn clear(&mut self) {
         self.set.clear()
     }
 
--- a/servo/components/style/invalidation/stylesheets.rs
+++ b/servo/components/style/invalidation/stylesheets.rs
@@ -6,17 +6,17 @@
 //! document.
 
 #![deny(unsafe_code)]
 
 use Atom;
 use CaseSensitivityExt;
 use LocalName as SelectorLocalName;
 use dom::{TDocument, TElement, TNode};
-use fnv::FnvHashSet;
+use fxhash::FxHashSet;
 use invalidation::element::element_wrapper::{ElementSnapshot, ElementWrapper};
 use invalidation::element::restyle_hints::RestyleHint;
 use media_queries::Device;
 use selector_parser::{SelectorImpl, Snapshot, SnapshotMap};
 use selectors::attr::CaseSensitivity;
 use selectors::parser::{Component, LocalName, Selector};
 use shared_lock::SharedRwLockReadGuard;
 use stylesheets::{CssRule, StylesheetInDocument};
@@ -101,29 +101,29 @@ impl Invalidation {
 
 /// A set of invalidations due to stylesheet additions.
 ///
 /// TODO(emilio): We might be able to do the same analysis for media query
 /// changes too (or even selector changes?).
 #[derive(MallocSizeOf)]
 pub struct StylesheetInvalidationSet {
     /// The subtrees we know we have to restyle so far.
-    invalid_scopes: FnvHashSet<Invalidation>,
+    invalid_scopes: FxHashSet<Invalidation>,
     /// The elements we know we have to restyle so far.
-    invalid_elements: FnvHashSet<Invalidation>,
+    invalid_elements: FxHashSet<Invalidation>,
     /// Whether the whole document should be restyled.
     fully_invalid: bool,
 }
 
 impl StylesheetInvalidationSet {
     /// Create an empty `StylesheetInvalidationSet`.
     pub fn new() -> Self {
         Self {
-            invalid_scopes: FnvHashSet::default(),
-            invalid_elements: FnvHashSet::default(),
+            invalid_scopes: FxHashSet::default(),
+            invalid_elements: FxHashSet::default(),
             fully_invalid: false,
         }
     }
 
     /// Mark the DOM tree styles' as fully invalid.
     pub fn invalidate_fully(&mut self) {
         debug!("StylesheetInvalidationSet::invalidate_fully");
         self.invalid_scopes.clear();
--- a/servo/components/style/lib.rs
+++ b/servo/components/style/lib.rs
@@ -37,17 +37,17 @@ extern crate byteorder;
 #[no_link]
 extern crate cfg_if;
 #[macro_use]
 extern crate cssparser;
 #[macro_use]
 extern crate debug_unreachable;
 extern crate euclid;
 extern crate fallible;
-extern crate fnv;
+extern crate fxhash;
 #[cfg(feature = "gecko")]
 #[macro_use]
 pub mod gecko_string_cache;
 extern crate hashglobe;
 #[cfg(feature = "servo")]
 #[macro_use]
 extern crate html5ever;
 extern crate itertools;
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -20,17 +20,17 @@ use properties::longhands;
 use properties::longhands::font_weight::computed_value::T as FontWeight;
 use properties::longhands::visibility::computed_value::T as Visibility;
 use properties::PropertyId;
 use properties::{LonghandId, ShorthandId};
 use servo_arc::Arc;
 use smallvec::SmallVec;
 use std::{cmp, ptr};
 use std::mem::{self, ManuallyDrop};
-use hash::FnvHashMap;
+use hash::FxHashMap;
 use super::ComputedValues;
 use values::CSSFloat;
 use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
 use values::animated::color::Color as AnimatedColor;
 use values::animated::effects::Filter as AnimatedFilter;
 #[cfg(feature = "gecko")] use values::computed::TransitionProperty;
 use values::computed::{Angle, CalcLengthOrPercentage};
 use values::computed::{ClipRect, Context};
@@ -227,17 +227,17 @@ impl AnimatedProperty {
             _ => return None,
         })
     }
 }
 
 /// A collection of AnimationValue that were composed on an element.
 /// This HashMap stores the values that are the last AnimationValue to be
 /// composed for each TransitionProperty.
-pub type AnimationValueMap = FnvHashMap<LonghandId, AnimationValue>;
+pub type AnimationValueMap = FxHashMap<LonghandId, AnimationValue>;
 
 #[cfg(feature = "gecko")]
 unsafe impl HasFFI for AnimationValueMap {
     type FFIType = RawServoAnimationValueMap;
 }
 #[cfg(feature = "gecko")]
 unsafe impl HasSimpleFFI for AnimationValueMap {}
 
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -2382,17 +2382,17 @@ impl<'a> Iterator for AllShorthandDeclar
 }
 
 #[cfg(feature = "gecko")]
 pub use gecko_properties::style_structs;
 
 /// The module where all the style structs are defined.
 #[cfg(feature = "servo")]
 pub mod style_structs {
-    use fnv::FnvHasher;
+    use fx::FxHasher;
     use super::longhands;
     use std::hash::{Hash, Hasher};
     use logical_geometry::WritingMode;
     use media_queries::Device;
     use values::computed::NonNegativeLength;
 
     % for style_struct in data.active_style_structs():
         % if style_struct.name == "Font":
@@ -2529,17 +2529,17 @@ pub mod style_structs {
                     }
                 % endfor
             % elif style_struct.name == "Font":
                 /// Computes a font hash in order to be able to cache fonts
                 /// effectively in GFX and layout.
                 pub fn compute_font_hash(&mut self) {
                     // Corresponds to the fields in
                     // `gfx::font_template::FontTemplateDescriptor`.
-                    let mut hasher: FnvHasher = Default::default();
+                    let mut hasher: FxHasher = Default::default();
                     self.font_weight.hash(&mut hasher);
                     self.font_stretch.hash(&mut hasher);
                     self.font_style.hash(&mut hasher);
                     self.font_family.hash(&mut hasher);
                     self.hash = hasher.finish()
                 }
 
                 /// (Servo does not handle MathML, so this just calls copy_font_size_from)
--- a/servo/components/style/rule_cache.rs
+++ b/servo/components/style/rule_cache.rs
@@ -1,16 +1,16 @@
 /* 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 cache from rule node to computed values, in order to cache reset
 //! properties.
 
-use fnv::FnvHashMap;
+use fxhash::FxHashMap;
 use logical_geometry::WritingMode;
 use properties::{ComputedValues, StyleBuilder};
 use rule_tree::StrongRuleNode;
 use selector_parser::PseudoElement;
 use servo_arc::Arc;
 use shared_lock::StylesheetGuards;
 use smallvec::SmallVec;
 use values::computed::NonNegativeLength;
@@ -66,24 +66,24 @@ impl RuleCacheConditions {
 
         true
     }
 }
 
 /// A TLS cache from rules matched to computed values.
 pub struct RuleCache {
     // FIXME(emilio): Consider using LRUCache or something like that?
-    map: FnvHashMap<StrongRuleNode, SmallVec<[(RuleCacheConditions, Arc<ComputedValues>); 1]>>,
+    map: FxHashMap<StrongRuleNode, SmallVec<[(RuleCacheConditions, Arc<ComputedValues>); 1]>>,
 }
 
 impl RuleCache {
     /// Creates an empty `RuleCache`.
     pub fn new() -> Self {
         Self {
-            map: FnvHashMap::default(),
+            map: FxHashMap::default(),
         }
     }
 
     /// Walk the rule tree and return a rule node for using as the key
     /// for rule cache.
     ///
     /// It currently skips a rule node when it is neither from a style
     /// rule, nor containing any declaration of reset property. We don't
--- a/servo/components/style/rule_tree/mod.rs
+++ b/servo/components/style/rule_tree/mod.rs
@@ -1141,23 +1141,23 @@ impl StrongRuleNode {
             current, next
         );
 
         Some(WeakRuleNode::from_ptr(current))
     }
 
     unsafe fn assert_free_list_has_no_duplicates_or_null(&self) {
         assert!(cfg!(debug_assertions), "This is an expensive check!");
-        use hash::FnvHashSet;
+        use hash::FxHashSet;
 
         let me = &*self.ptr();
         assert!(me.is_root());
 
         let mut current = self.ptr();
-        let mut seen = FnvHashSet::default();
+        let mut seen = FxHashSet::default();
         while current != FREE_LIST_SENTINEL {
             let next = (*current).next_free.load(Ordering::Relaxed);
             assert!(!next.is_null());
             assert!(!seen.contains(&next));
             seen.insert(next);
 
             current = next;
         }
--- a/servo/components/style/servo/selector_parser.rs
+++ b/servo/components/style/servo/selector_parser.rs
@@ -6,17 +6,17 @@
 
 //! Servo's selector parser.
 
 use {Atom, CaseSensitivityExt, LocalName, Namespace, Prefix};
 use attr::{AttrIdentifier, AttrValue};
 use cssparser::{serialize_identifier, CowRcStr, Parser as CssParser, SourceLocation, ToCss};
 use dom::{OpaqueNode, TElement, TNode};
 use element_state::{DocumentState, ElementState};
-use fnv::FnvHashMap;
+use fxhash::FxHashMap;
 use invalidation::element::document_state::InvalidationMatchingData;
 use invalidation::element::element_wrapper::ElementSnapshot;
 use properties::{ComputedValues, PropertyFlags};
 use properties::longhands::display::computed_value::T as Display;
 use selector_parser::{AttrValue as SelectorAttrValue, PseudoElementCascadeType, SelectorParser};
 use selectors::attr::{AttrSelectorOperation, CaseSensitivity, NamespaceConstraint};
 use selectors::parser::{SelectorParseErrorKind, Visit};
 use selectors::visitor::SelectorVisitor;
@@ -612,32 +612,32 @@ impl SelectorImpl {
         for i in 0..EAGER_PSEUDO_COUNT {
             fun(PseudoElement::from_eager_index(i));
         }
     }
 }
 
 /// A map from elements to snapshots for the Servo style back-end.
 #[derive(Debug)]
-pub struct SnapshotMap(FnvHashMap<OpaqueNode, ServoElementSnapshot>);
+pub struct SnapshotMap(FxHashMap<OpaqueNode, ServoElementSnapshot>);
 
 impl SnapshotMap {
     /// Create a new empty `SnapshotMap`.
     pub fn new() -> Self {
-        SnapshotMap(FnvHashMap::default())
+        SnapshotMap(FxHashMap::default())
     }
 
     /// Get a snapshot given an element.
     pub fn get<T: TElement>(&self, el: &T) -> Option<&ServoElementSnapshot> {
         self.0.get(&el.as_node().opaque())
     }
 }
 
 impl Deref for SnapshotMap {
-    type Target = FnvHashMap<OpaqueNode, ServoElementSnapshot>;
+    type Target = FxHashMap<OpaqueNode, ServoElementSnapshot>;
 
     fn deref(&self) -> &Self::Target {
         &self.0
     }
 }
 
 impl DerefMut for SnapshotMap {
     fn deref_mut(&mut self) -> &mut Self::Target {
--- a/servo/components/style/stylesheets/stylesheet.rs
+++ b/servo/components/style/stylesheets/stylesheet.rs
@@ -2,17 +2,17 @@
  * 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 {Namespace, Prefix};
 use context::QuirksMode;
 use cssparser::{Parser, ParserInput, RuleListParser};
 use error_reporting::{ContextualParseError, ParseErrorReporter};
 use fallible::FallibleVec;
-use fnv::FnvHashMap;
+use fxhash::FxHashMap;
 use invalidation::media_queries::{MediaListKey, ToMediaListKey};
 #[cfg(feature = "gecko")]
 use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
 use media_queries::{Device, MediaList};
 use parking_lot::RwLock;
 use parser::ParserContext;
 use servo_arc::Arc;
 use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard};
@@ -37,17 +37,17 @@ pub struct UserAgentStylesheets {
 
 /// A set of namespaces applying to a given stylesheet.
 ///
 /// The namespace id is used in gecko
 #[derive(Clone, Debug, Default, MallocSizeOf)]
 #[allow(missing_docs)]
 pub struct Namespaces {
     pub default: Option<Namespace>,
-    pub prefixes: FnvHashMap<Prefix, Namespace>,
+    pub prefixes: FxHashMap<Prefix, Namespace>,
 }
 
 /// The contents of a given stylesheet. This effectively maps to a
 /// StyleSheetInner in Gecko.
 #[derive(Debug)]
 pub struct StylesheetContents {
     /// List of rules in the order they were found (important for
     /// cascading order)
--- a/servo/components/style/values/specified/position.rs
+++ b/servo/components/style/values/specified/position.rs
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! CSS handling for the specified value of
 //! [`position`][position]s
 //!
 //! [position]: https://drafts.csswg.org/css-backgrounds-3/#position
 
 use cssparser::Parser;
-use hash::FnvHashMap;
+use hash::FxHashMap;
 use parser::{Parse, ParserContext};
 use selectors::parser::SelectorParseErrorKind;
 use servo_arc::Arc;
 use std::fmt::{self, Write};
 use std::ops::Range;
 use str::HTML_SPACE_CHARACTERS;
 use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
 use values::{Either, None_};
@@ -543,17 +543,17 @@ impl TemplateAreas {
     pub fn from_vec(strings: Vec<Box<str>>) -> Result<TemplateAreas, ()> {
         if strings.is_empty() {
             return Err(());
         }
         let mut areas: Vec<NamedArea> = vec![];
         let mut width = 0;
         {
             let mut row = 0u32;
-            let mut area_indices = FnvHashMap::<&str, usize>::default();
+            let mut area_indices = FxHashMap::<&str, usize>::default();
             for string in &strings {
                 let mut current_area_index: Option<usize> = None;
                 row += 1;
                 let mut column = 0u32;
                 for token in TemplateAreasTokenizer(string) {
                     column += 1;
                     let token = if let Some(token) = token? {
                         token