mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-03 07:01:19 +00:00
Bug 1631721 - Use hashbrown instead of hashglobe r=manishearth
Differential Revision: https://phabricator.services.mozilla.com/D71741
This commit is contained in:
parent
cbe24024bb
commit
67ea7f6752
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1271,6 +1271,7 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
name = "fallible"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"hashbrown",
|
||||
"hashglobe",
|
||||
"smallvec",
|
||||
]
|
||||
@ -2534,6 +2535,7 @@ dependencies = [
|
||||
"app_units",
|
||||
"cssparser",
|
||||
"euclid",
|
||||
"hashbrown",
|
||||
"hashglobe",
|
||||
"selectors",
|
||||
"servo_arc",
|
||||
|
@ -11,6 +11,7 @@ path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
smallvec = "1.0"
|
||||
hashbrown = "0.7"
|
||||
hashglobe = { path = "../hashglobe" }
|
||||
|
||||
# This crate effectively does nothing except if the `known_system_malloc`
|
||||
|
@ -2,20 +2,62 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
extern crate hashbrown;
|
||||
extern crate hashglobe;
|
||||
extern crate smallvec;
|
||||
|
||||
use hashbrown::hash_map::Entry;
|
||||
use hashbrown::CollectionAllocErr;
|
||||
#[cfg(feature = "known_system_malloc")]
|
||||
use hashglobe::alloc;
|
||||
use hashglobe::FailedAllocationError;
|
||||
use smallvec::Array;
|
||||
use smallvec::SmallVec;
|
||||
use std::alloc::Layout;
|
||||
use std::vec::Vec;
|
||||
|
||||
pub trait FallibleVec<T> {
|
||||
/// Append |val| to the end of |vec|. Returns Ok(()) on success,
|
||||
/// Err(reason) if it fails, with |reason| describing the failure.
|
||||
fn try_push(&mut self, value: T) -> Result<(), FailedAllocationError>;
|
||||
fn try_push(&mut self, value: T) -> Result<(), CollectionAllocErr>;
|
||||
}
|
||||
|
||||
pub trait FallibleHashMap<K, V, H> {
|
||||
fn try_insert(&mut self, k: K, v: V) -> Result<Option<V>, CollectionAllocErr>;
|
||||
fn try_entry(&mut self, k: K) -> Result<Entry<K, V, H>, CollectionAllocErr>;
|
||||
}
|
||||
|
||||
pub trait FallibleHashSet<T, H> {
|
||||
fn try_insert(&mut self, x: T) -> Result<bool, CollectionAllocErr>;
|
||||
}
|
||||
|
||||
impl<K, V, H> FallibleHashMap<K, V, H> for hashbrown::HashMap<K, V, H>
|
||||
where
|
||||
K: Eq + std::hash::Hash,
|
||||
H: std::hash::BuildHasher,
|
||||
{
|
||||
#[inline]
|
||||
fn try_insert(&mut self, k: K, v: V) -> Result<Option<V>, CollectionAllocErr> {
|
||||
self.try_reserve(1)?;
|
||||
Ok(self.insert(k, v))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_entry(&mut self, k: K) -> Result<Entry<K, V, H>, CollectionAllocErr> {
|
||||
self.try_reserve(1)?;
|
||||
Ok(self.entry(k))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, H> FallibleHashSet<T, H> for hashbrown::HashSet<T, H>
|
||||
where
|
||||
T: Eq + std::hash::Hash,
|
||||
H: std::hash::BuildHasher,
|
||||
{
|
||||
#[inline]
|
||||
fn try_insert(&mut self, x: T) -> Result<bool, CollectionAllocErr> {
|
||||
self.try_reserve(1)?;
|
||||
Ok(self.insert(x))
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
@ -23,7 +65,7 @@ pub trait FallibleVec<T> {
|
||||
|
||||
impl<T> FallibleVec<T> for Vec<T> {
|
||||
#[inline(always)]
|
||||
fn try_push(&mut self, val: T) -> Result<(), FailedAllocationError> {
|
||||
fn try_push(&mut self, val: T) -> Result<(), CollectionAllocErr> {
|
||||
#[cfg(feature = "known_system_malloc")]
|
||||
{
|
||||
if self.capacity() == self.len() {
|
||||
@ -41,7 +83,7 @@ impl<T> FallibleVec<T> for Vec<T> {
|
||||
#[cfg(feature = "known_system_malloc")]
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
fn try_double_vec<T>(vec: &mut Vec<T>) -> Result<(), FailedAllocationError> {
|
||||
fn try_double_vec<T>(vec: &mut Vec<T>) -> Result<(), CollectionAllocErr> {
|
||||
use std::mem;
|
||||
|
||||
let old_ptr = vec.as_mut_ptr();
|
||||
@ -53,12 +95,15 @@ fn try_double_vec<T>(vec: &mut Vec<T>) -> Result<(), FailedAllocationError> {
|
||||
} else {
|
||||
old_cap
|
||||
.checked_mul(2)
|
||||
.ok_or(FailedAllocationError::new("capacity overflow for Vec"))?
|
||||
.ok_or(CollectionAllocErr::CapacityOverflow)?
|
||||
};
|
||||
|
||||
let new_size_bytes = new_cap
|
||||
.checked_mul(mem::size_of::<T>())
|
||||
.ok_or(FailedAllocationError::new("capacity overflow for Vec"))?;
|
||||
.ok_or(CollectionAllocErr::CapacityOverflow)?;
|
||||
|
||||
let layout = Layout::from_size_align(new_size_bytes, std::mem::align_of::<T>())
|
||||
.map_err(|_| CollectionAllocErr::CapacityOverflow)?;
|
||||
|
||||
let new_ptr = unsafe {
|
||||
if old_cap == 0 {
|
||||
@ -69,9 +114,7 @@ fn try_double_vec<T>(vec: &mut Vec<T>) -> Result<(), FailedAllocationError> {
|
||||
};
|
||||
|
||||
if new_ptr.is_null() {
|
||||
return Err(FailedAllocationError::new(
|
||||
"out of memory when allocating Vec",
|
||||
));
|
||||
return Err(CollectionAllocErr::AllocErr { layout });
|
||||
}
|
||||
|
||||
let new_vec = unsafe { Vec::from_raw_parts(new_ptr as *mut T, old_len, new_cap) };
|
||||
@ -85,7 +128,7 @@ fn try_double_vec<T>(vec: &mut Vec<T>) -> Result<(), FailedAllocationError> {
|
||||
|
||||
impl<T: Array> FallibleVec<T::Item> for SmallVec<T> {
|
||||
#[inline(always)]
|
||||
fn try_push(&mut self, val: T::Item) -> Result<(), FailedAllocationError> {
|
||||
fn try_push(&mut self, val: T::Item) -> Result<(), CollectionAllocErr> {
|
||||
#[cfg(feature = "known_system_malloc")]
|
||||
{
|
||||
if self.capacity() == self.len() {
|
||||
@ -103,7 +146,7 @@ impl<T: Array> FallibleVec<T::Item> for SmallVec<T> {
|
||||
#[cfg(feature = "known_system_malloc")]
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
fn try_double_small_vec<T>(svec: &mut SmallVec<T>) -> Result<(), FailedAllocationError>
|
||||
fn try_double_small_vec<T>(svec: &mut SmallVec<T>) -> Result<(), CollectionAllocErr>
|
||||
where
|
||||
T: Array,
|
||||
{
|
||||
@ -119,18 +162,21 @@ where
|
||||
} else {
|
||||
old_cap
|
||||
.checked_mul(2)
|
||||
.ok_or(FailedAllocationError::new("capacity overflow for SmallVec"))?
|
||||
.ok_or(CollectionAllocErr::CapacityOverflow)?
|
||||
};
|
||||
|
||||
// This surely shouldn't fail, if |old_cap| was previously accepted as a
|
||||
// valid value. But err on the side of caution.
|
||||
let old_size_bytes = old_cap
|
||||
.checked_mul(mem::size_of::<T>())
|
||||
.ok_or(FailedAllocationError::new("capacity overflow for SmallVec"))?;
|
||||
.ok_or(CollectionAllocErr::CapacityOverflow)?;
|
||||
|
||||
let new_size_bytes = new_cap
|
||||
.checked_mul(mem::size_of::<T>())
|
||||
.ok_or(FailedAllocationError::new("capacity overflow for SmallVec"))?;
|
||||
.ok_or(CollectionAllocErr::CapacityOverflow)?;
|
||||
|
||||
let layout = Layout::from_size_align(new_size_bytes, std::mem::align_of::<T>())
|
||||
.map_err(|_| CollectionAllocErr::CapacityOverflow)?;
|
||||
|
||||
let new_ptr;
|
||||
if svec.spilled() {
|
||||
@ -150,9 +196,7 @@ where
|
||||
}
|
||||
|
||||
if new_ptr.is_null() {
|
||||
return Err(FailedAllocationError::new(
|
||||
"out of memory when allocating SmallVec",
|
||||
));
|
||||
return Err(CollectionAllocErr::AllocErr { layout });
|
||||
}
|
||||
|
||||
let new_vec = unsafe { Vec::from_raw_parts(new_ptr as *mut T::Item, old_len, new_cap) };
|
||||
|
@ -33,6 +33,7 @@ content-security-policy = {version = "0.3.0", features = ["serde"], optional = t
|
||||
crossbeam-channel = { version = "0.3", optional = true }
|
||||
cssparser = "0.27"
|
||||
euclid = "0.20"
|
||||
hashbrown = "0.7"
|
||||
hashglobe = { path = "../hashglobe" }
|
||||
hyper = { version = "0.12", optional = true }
|
||||
hyper_serde = { version = "0.11", optional = true }
|
||||
|
@ -55,6 +55,7 @@ extern crate content_security_policy;
|
||||
extern crate crossbeam_channel;
|
||||
extern crate cssparser;
|
||||
extern crate euclid;
|
||||
extern crate hashbrown;
|
||||
extern crate hashglobe;
|
||||
#[cfg(feature = "servo")]
|
||||
extern crate hyper;
|
||||
@ -487,6 +488,7 @@ macro_rules! malloc_size_of_hash_set {
|
||||
}
|
||||
|
||||
malloc_size_of_hash_set!(std::collections::HashSet<T, S>);
|
||||
malloc_size_of_hash_set!(hashbrown::HashSet<T, S>);
|
||||
malloc_size_of_hash_set!(hashglobe::hash_set::HashSet<T, S>);
|
||||
malloc_size_of_hash_set!(hashglobe::fake::HashSet<T, S>);
|
||||
|
||||
@ -528,6 +530,7 @@ macro_rules! malloc_size_of_hash_map {
|
||||
}
|
||||
|
||||
malloc_size_of_hash_map!(std::collections::HashMap<K, V, S>);
|
||||
malloc_size_of_hash_map!(hashbrown::HashMap<K, V, S>);
|
||||
malloc_size_of_hash_map!(hashglobe::hash_map::HashMap<K, V, S>);
|
||||
malloc_size_of_hash_map!(hashglobe::fake::HashMap<K, V, S>);
|
||||
|
||||
|
@ -2,28 +2,11 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://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
|
||||
//! Reexports of hashbrown, without and with FxHash
|
||||
|
||||
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};
|
||||
|
||||
/// 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};
|
||||
}
|
||||
pub use hashbrown::{hash_map as map, HashMap, HashSet};
|
||||
|
||||
/// Hash map that uses the Fx hasher
|
||||
pub type FxHashMap<K, V> = HashMap<K, V, fxhash::FxBuildHasher>;
|
||||
|
@ -10,7 +10,7 @@ use crate::selector_map::{MaybeCaseInsensitiveHashMap, SelectorMap, SelectorMapE
|
||||
use crate::selector_parser::SelectorImpl;
|
||||
use crate::{Atom, LocalName, Namespace};
|
||||
use fallible::FallibleVec;
|
||||
use hashglobe::FailedAllocationError;
|
||||
use hashbrown::CollectionAllocErr;
|
||||
use selectors::attr::NamespaceConstraint;
|
||||
use selectors::parser::{Combinator, Component};
|
||||
use selectors::parser::{Selector, SelectorIter};
|
||||
@ -224,7 +224,7 @@ impl InvalidationMap {
|
||||
&mut self,
|
||||
selector: &Selector<SelectorImpl>,
|
||||
quirks_mode: QuirksMode,
|
||||
) -> Result<(), FailedAllocationError> {
|
||||
) -> Result<(), CollectionAllocErr> {
|
||||
debug!("InvalidationMap::note_selector({:?})", selector);
|
||||
|
||||
let mut iter = selector.iter();
|
||||
|
@ -18,6 +18,7 @@ use crate::stylesheets::{CssRule, StylesheetInDocument};
|
||||
use crate::Atom;
|
||||
use crate::CaseSensitivityExt;
|
||||
use crate::LocalName as SelectorLocalName;
|
||||
use fallible::FallibleHashSet;
|
||||
use fxhash::FxHasher;
|
||||
use selectors::attr::CaseSensitivity;
|
||||
use selectors::parser::{Component, LocalName, Selector};
|
||||
|
@ -46,7 +46,7 @@ extern crate fxhash;
|
||||
#[cfg(feature = "gecko")]
|
||||
#[macro_use]
|
||||
pub mod gecko_string_cache;
|
||||
extern crate hashglobe;
|
||||
extern crate hashbrown;
|
||||
#[cfg(feature = "servo")]
|
||||
#[macro_use]
|
||||
extern crate html5ever;
|
||||
|
@ -14,8 +14,8 @@ use crate::rule_tree::CascadeLevel;
|
||||
use crate::selector_parser::SelectorImpl;
|
||||
use crate::stylist::Rule;
|
||||
use crate::{Atom, LocalName, Namespace, WeakAtom};
|
||||
use fallible::FallibleVec;
|
||||
use hashglobe::FailedAllocationError;
|
||||
use fallible::{FallibleHashMap, FallibleVec};
|
||||
use hashbrown::CollectionAllocErr;
|
||||
use precomputed_hash::PrecomputedHash;
|
||||
use selectors::matching::{matches_selector, ElementSelectorFlags, MatchingContext};
|
||||
use selectors::parser::{Combinator, Component, SelectorIter};
|
||||
@ -95,7 +95,7 @@ pub trait SelectorMapEntry: Sized + Clone {
|
||||
///
|
||||
/// TODO: Tune the initial capacity of the HashMap
|
||||
#[derive(Debug, MallocSizeOf)]
|
||||
pub struct SelectorMap<T: 'static> {
|
||||
pub struct SelectorMap<T> {
|
||||
/// Rules that have `:root` selectors.
|
||||
pub root: SmallVec<[T; 1]>,
|
||||
/// A hash from an ID to rules which contain that ID selector.
|
||||
@ -112,17 +112,14 @@ pub struct SelectorMap<T: 'static> {
|
||||
pub count: usize,
|
||||
}
|
||||
|
||||
impl<T: 'static> Default for SelectorMap<T> {
|
||||
impl<T> Default for SelectorMap<T> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(Manishearth) the 'static bound can be removed when
|
||||
// our HashMap fork (hashglobe) is able to use NonZero,
|
||||
// or when stdlib gets fallible collections
|
||||
impl<T: 'static> SelectorMap<T> {
|
||||
impl<T> SelectorMap<T> {
|
||||
/// Trivially constructs an empty `SelectorMap`.
|
||||
pub fn new() -> Self {
|
||||
SelectorMap {
|
||||
@ -280,11 +277,7 @@ impl SelectorMap<Rule> {
|
||||
impl<T: SelectorMapEntry> SelectorMap<T> {
|
||||
/// Inserts into the correct hash, trying id, class, localname and
|
||||
/// namespace.
|
||||
pub fn insert(
|
||||
&mut self,
|
||||
entry: T,
|
||||
quirks_mode: QuirksMode,
|
||||
) -> Result<(), FailedAllocationError> {
|
||||
pub fn insert(&mut self, entry: T, quirks_mode: QuirksMode) -> Result<(), CollectionAllocErr> {
|
||||
self.count += 1;
|
||||
|
||||
let vector = match find_bucket(entry.selector()) {
|
||||
@ -563,14 +556,11 @@ fn find_bucket<'a>(mut iter: SelectorIter<'a, SelectorImpl>) -> Bucket<'a> {
|
||||
|
||||
/// Wrapper for PrecomputedHashMap that does ASCII-case-insensitive lookup in quirks mode.
|
||||
#[derive(Debug, MallocSizeOf)]
|
||||
pub struct MaybeCaseInsensitiveHashMap<K: PrecomputedHash + Hash + Eq, V: 'static>(
|
||||
pub struct MaybeCaseInsensitiveHashMap<K: PrecomputedHash + Hash + Eq, V>(
|
||||
PrecomputedHashMap<K, V>,
|
||||
);
|
||||
|
||||
// FIXME(Manishearth) the 'static bound can be removed when
|
||||
// our HashMap fork (hashglobe) is able to use NonZero,
|
||||
// or when stdlib gets fallible collections
|
||||
impl<V: 'static> MaybeCaseInsensitiveHashMap<Atom, V> {
|
||||
impl<V> MaybeCaseInsensitiveHashMap<Atom, V> {
|
||||
/// Empty map
|
||||
pub fn new() -> Self {
|
||||
MaybeCaseInsensitiveHashMap(PrecomputedHashMap::default())
|
||||
@ -581,7 +571,8 @@ impl<V: 'static> MaybeCaseInsensitiveHashMap<Atom, V> {
|
||||
&mut self,
|
||||
mut key: Atom,
|
||||
quirks_mode: QuirksMode,
|
||||
) -> Result<hash_map::Entry<Atom, V>, FailedAllocationError> {
|
||||
) -> Result<hash_map::Entry<Atom, V, BuildHasherDefault<PrecomputedHasher>>, CollectionAllocErr>
|
||||
{
|
||||
if quirks_mode == QuirksMode::Quirks {
|
||||
key = key.to_ascii_lowercase()
|
||||
}
|
||||
|
@ -33,8 +33,8 @@ use crate::stylesheets::{CounterStyleRule, FontFaceRule, FontFeatureValuesRule,
|
||||
use crate::stylesheets::{CssRule, Origin, OriginSet, PerOrigin, PerOriginIter};
|
||||
use crate::thread_state::{self, ThreadState};
|
||||
use crate::{Atom, LocalName, Namespace, WeakAtom};
|
||||
use fallible::FallibleVec;
|
||||
use hashglobe::FailedAllocationError;
|
||||
use fallible::{FallibleHashMap, FallibleVec};
|
||||
use hashbrown::CollectionAllocErr;
|
||||
use malloc_size_of::MallocSizeOf;
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
|
||||
@ -88,7 +88,7 @@ impl UserAgentCascadeDataCache {
|
||||
device: &Device,
|
||||
quirks_mode: QuirksMode,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
) -> Result<Arc<UserAgentCascadeData>, FailedAllocationError>
|
||||
) -> Result<Arc<UserAgentCascadeData>, CollectionAllocErr>
|
||||
where
|
||||
I: Iterator<Item = &'a S> + Clone,
|
||||
S: StylesheetInDocument + ToMediaListKey + PartialEq + 'static,
|
||||
@ -260,7 +260,7 @@ impl DocumentCascadeData {
|
||||
quirks_mode: QuirksMode,
|
||||
mut flusher: DocumentStylesheetFlusher<'a, S>,
|
||||
guards: &StylesheetGuards,
|
||||
) -> Result<(), FailedAllocationError>
|
||||
) -> Result<(), CollectionAllocErr>
|
||||
where
|
||||
S: StylesheetInDocument + ToMediaListKey + PartialEq + 'static,
|
||||
{
|
||||
@ -1839,7 +1839,7 @@ impl CascadeData {
|
||||
quirks_mode: QuirksMode,
|
||||
collection: SheetCollectionFlusher<S>,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
) -> Result<(), FailedAllocationError>
|
||||
) -> Result<(), CollectionAllocErr>
|
||||
where
|
||||
S: StylesheetInDocument + ToMediaListKey + PartialEq + 'static,
|
||||
{
|
||||
@ -1976,7 +1976,7 @@ impl CascadeData {
|
||||
guard: &SharedRwLockReadGuard,
|
||||
rebuild_kind: SheetRebuildKind,
|
||||
mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
|
||||
) -> Result<(), FailedAllocationError>
|
||||
) -> Result<(), CollectionAllocErr>
|
||||
where
|
||||
S: StylesheetInDocument + ToMediaListKey + 'static,
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user