Skip to content

Commit

Permalink
Auto merge of #19912 - emilio:ordermap, r=Manishearth
Browse files Browse the repository at this point in the history
style: Temporarily use OrderMap on Gecko.

This will allow us to discard std hash map as a source of crashes.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19912)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Feb 1, 2018
2 parents 1bd3f0e + 4d9ce6b commit e6d9c25
Show file tree
Hide file tree
Showing 9 changed files with 383 additions and 10 deletions.
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions components/hashglobe/Cargo.toml
Expand Up @@ -11,6 +11,7 @@ readme = "README.md"

[dependencies]
libc = "0.2"
ordermap = "0.3"

[dev-dependencies]
rand = "0.3"
3 changes: 3 additions & 0 deletions components/hashglobe/src/lib.rs
Expand Up @@ -8,13 +8,16 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate ordermap;

pub mod alloc;
pub mod hash_map;
pub mod hash_set;
mod shim;
mod table;

pub mod fake;
pub mod order;

use std::{error, fmt};

Expand Down
246 changes: 246 additions & 0 deletions components/hashglobe/src/order.rs
@@ -0,0 +1,246 @@
/* 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/. */

//! This module contains shims around the ordermap crate that add fallible
//! methods.
//!
//! These methods are a lie. They are not actually fallible. This is just to
//! make it smooth to switch between hashmap impls the codebase.

use ordermap::{OrderMap, OrderSet};
use std::fmt;
use std::hash::{BuildHasher, Hash};
use std::ops::{Deref, DerefMut};

pub use std::collections::hash_map::RandomState;
pub use ordermap::{Entry, Iter as MapIter, IterMut as MapIterMut};
pub use ordermap::set::{Iter as SetIter, IntoIter as SetIntoIter};

#[derive(Clone)]
pub struct HashMap<K, V, S = RandomState>(OrderMap<K, V, S>);


use FailedAllocationError;

impl<K, V, S> Deref for HashMap<K, V, S> {
type Target = OrderMap<K, V, S>;
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<K, V, S> DerefMut for HashMap<K, V, S> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl<K, V, S> HashMap<K, V, S>
where K: Eq + Hash,
S: BuildHasher
{
#[inline]
pub fn try_with_hasher(hash_builder: S) -> Result<HashMap<K, V, S>, FailedAllocationError> {
Ok(HashMap(OrderMap::with_hasher(hash_builder)))
}

#[inline]
pub fn try_with_capacity_and_hasher(capacity: usize,
hash_builder: S)
-> Result<HashMap<K, V, S>, FailedAllocationError> {
Ok(HashMap(OrderMap::with_capacity_and_hasher(capacity, hash_builder)))
}

pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap<K, V, S> {
HashMap(OrderMap::with_capacity_and_hasher(capacity, hash_builder))
}


#[inline]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), FailedAllocationError> {
Ok(self.reserve(additional))
}

#[inline]
pub fn try_entry(&mut self, key: K) -> Result<Entry<K, V, S>, FailedAllocationError> {
Ok(self.entry(key))
}

#[inline]
pub fn try_insert(&mut self, k: K, v: V) -> Result<Option<V>, FailedAllocationError> {
Ok(self.insert(k, v))
}
}

#[derive(Clone)]
pub struct HashSet<T, S = RandomState>(OrderSet<T, S>);


impl<T, S> Deref for HashSet<T, S> {
type Target = OrderSet<T, S>;
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<T, S> DerefMut for HashSet<T, S> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl<T: Hash + Eq> HashSet<T, RandomState> {
#[inline]
pub fn new() -> HashSet<T, RandomState> {
HashSet(OrderSet::new())
}

#[inline]
pub fn with_capacity(capacity: usize) -> HashSet<T, RandomState> {
HashSet(OrderSet::with_capacity(capacity))
}
}


impl<T, S> HashSet<T, S>
where T: Eq + Hash,
S: BuildHasher
{
#[inline]
pub fn with_hasher(hasher: S) -> HashSet<T, S> {
HashSet(OrderSet::with_hasher(hasher))
}


#[inline]
pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashSet<T, S> {
HashSet(OrderSet::with_capacity_and_hasher(capacity, hasher))
}

#[inline]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), FailedAllocationError> {
Ok(self.reserve(additional))
}

#[inline]
pub fn try_insert(&mut self, value: T) -> Result<bool, FailedAllocationError> {
Ok(self.insert(value))
}
}

// Pass through trait impls
// We can't derive these since the bounds are not obvious to the derive macro

impl<K: Hash + Eq, V, S: BuildHasher + Default> Default for HashMap<K, V, S> {
fn default() -> Self {
HashMap(Default::default())
}
}

impl<K, V, S> fmt::Debug for HashMap<K, V, S>
where K: Eq + Hash + fmt::Debug,
V: fmt::Debug,
S: BuildHasher {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}

impl<K, V, S> PartialEq for HashMap<K, V, S>
where K: Eq + Hash,
V: PartialEq,
S: BuildHasher
{
fn eq(&self, other: &HashMap<K, V, S>) -> bool {
self.0.eq(&other.0)
}
}

impl<K, V, S> Eq for HashMap<K, V, S>
where K: Eq + Hash,
V: Eq,
S: BuildHasher
{
}

impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S>
where K: Eq + Hash,
S: BuildHasher
{
type Item = (&'a K, &'a V);
type IntoIter = MapIter<'a, K, V>;

fn into_iter(self) -> MapIter<'a, K, V> {
self.0.iter()
}
}

impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S>
where K: Eq + Hash,
S: BuildHasher
{
type Item = (&'a K, &'a mut V);
type IntoIter = MapIterMut<'a, K, V>;

fn into_iter(self) -> MapIterMut<'a, K, V> {
self.0.iter_mut()
}
}

impl<T: Eq + Hash, S: BuildHasher + Default> Default for HashSet<T, S> {
fn default() -> Self {
HashSet(Default::default())
}
}

impl<T, S> fmt::Debug for HashSet<T, S>
where T: Eq + Hash + fmt::Debug,
S: BuildHasher
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}

impl<T, S> PartialEq for HashSet<T, S>
where T: Eq + Hash,
S: BuildHasher
{
fn eq(&self, other: &HashSet<T, S>) -> bool {
self.0.eq(&other.0)
}
}

impl<T, S> Eq for HashSet<T, S>
where T: Eq + Hash,
S: BuildHasher
{
}

impl<'a, T, S> IntoIterator for &'a HashSet<T, S>
where T: Eq + Hash,
S: BuildHasher
{
type Item = &'a T;
type IntoIter = SetIter<'a, T>;

fn into_iter(self) -> SetIter<'a, T> {
self.0.iter()
}
}

impl<T, S> IntoIterator for HashSet<T, S>
where T: Eq + Hash,
S: BuildHasher
{
type Item = T;
type IntoIter = SetIntoIter<T>;


fn into_iter(self) -> SetIntoIter<T> {
self.0.into_iter()
}
}


1 change: 1 addition & 0 deletions components/malloc_size_of/Cargo.toml
Expand Up @@ -17,6 +17,7 @@ cssparser = "0.23.0"
euclid = "0.16"
hashglobe = { path = "../hashglobe" }
mozjs = { version = "0.1.8", features = ["promises"], optional = true }
ordermap = "0.3"
selectors = { path = "../selectors" }
servo_arc = { path = "../servo_arc" }
smallbitvec = "1.0.3"
Expand Down

0 comments on commit e6d9c25

Please sign in to comment.