Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move HashMap to liballoc #51846

Closed
wants to merge 3 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Use a weak lang item for hashmap_random_keys
Amanieu committed Jul 2, 2018
commit 1edfa6c88d99b8cbd72f219da6eb94a05930060e
2 changes: 2 additions & 0 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
@@ -355,6 +355,8 @@ language_item_table! {
AlignOffsetLangItem, "align_offset", align_offset_fn;

TerminationTraitLangItem, "termination", termination;

HashMapRandomKeysLangItem, "hashmap_random_keys", hashmap_random_keys;
}

impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> {
1 change: 1 addition & 0 deletions src/librustc/middle/weak_lang_items.rs
Original file line number Diff line number Diff line change
@@ -166,4 +166,5 @@ weak_lang_items! {
eh_personality, EhPersonalityLangItem, rust_eh_personality;
eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume;
oom, OomLangItem, rust_oom;
hashmap_random_keys,HashMapRandomKeysLangItem, rust_hashmap_random_keys;
}
35 changes: 13 additions & 22 deletions src/libstd/collections/hash/map.rs
Original file line number Diff line number Diff line change
@@ -12,7 +12,6 @@ use self::Entry::*;
use self::VacantEntryState::*;

use collections::CollectionAllocErr;
use cell::Cell;
use borrow::Borrow;
use cmp::max;
use fmt::{self, Debug};
@@ -21,7 +20,6 @@ use hash::{Hash, Hasher, BuildHasher, SipHasher13};
use iter::{FromIterator, FusedIterator};
use mem::{self, replace};
use ops::{Deref, Index};
use sys;

use super::table::{self, Bucket, EmptyBucket, Fallibility, FullBucket, FullBucketMut, RawTable,
SafeHash};
@@ -2592,29 +2590,22 @@ impl RandomState {
/// ```
#[inline]
#[allow(deprecated)]
// rand
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
pub fn new() -> RandomState {
// Historically this function did not cache keys from the OS and instead
// simply always called `rand::thread_rng().gen()` twice. In #31356 it
// was discovered, however, that because we re-seed the thread-local RNG
// from the OS periodically that this can cause excessive slowdown when
// many hash maps are created on a thread. To solve this performance
// trap we cache the first set of randomly generated keys per-thread.
//
// Later in #36481 it was discovered that exposing a deterministic
// iteration order allows a form of DOS attack. To counter that we
// increment one of the seeds on every RandomState creation, giving
// every corresponding HashMap a different iteration order.
thread_local!(static KEYS: Cell<(u64, u64)> = {
Cell::new(sys::hashmap_random_keys())
});
// Use a weak lang item to get random keys without a hard dependency
// on libstd.
#[cfg(not(stage0))]
#[allow(improper_ctypes)]
extern {
#[lang = "hashmap_random_keys"]
#[unwind(allowed)]
fn hashmap_random_keys() -> (u64, u64);
}
#[cfg(stage0)]
unsafe fn hashmap_random_keys() -> (u64, u64) { (0, 0) }

KEYS.with(|keys| {
let (k0, k1) = keys.get();
keys.set((k0.wrapping_add(1), k1));
RandomState { k0: k0, k1: k1 }
})
let (k0, k1) = unsafe { hashmap_random_keys() };
RandomState { k0: k0, k1: k1 }
}
}

29 changes: 29 additions & 0 deletions src/libstd/collections/mod.rs
Original file line number Diff line number Diff line change
@@ -455,3 +455,32 @@ pub mod hash_set {
#[stable(feature = "rust1", since = "1.0.0")]
pub use super::hash::set::*;
}

#[cfg(not(stage0))]
#[cfg_attr(not(test), lang = "hashmap_random_keys")]
#[cfg_attr(test, allow(dead_code))]
fn hashmap_random_keys() -> (u64, u64) {
use sys;
use cell::Cell;

// Historically this function did not cache keys from the OS and instead
// simply always called `rand::thread_rng().gen()` twice. In #31356 it
// was discovered, however, that because we re-seed the thread-local RNG
// from the OS periodically that this can cause excessive slowdown when
// many hash maps are created on a thread. To solve this performance
// trap we cache the first set of randomly generated keys per-thread.
//
// Later in #36481 it was discovered that exposing a deterministic
// iteration order allows a form of DOS attack. To counter that we
// increment one of the seeds on every RandomState creation, giving
// every corresponding HashMap a different iteration order.
thread_local!(static KEYS: Cell<(u64, u64)> = {
Cell::new(sys::hashmap_random_keys())
});

KEYS.with(|keys| {
let (k0, k1) = keys.get();
keys.set((k0.wrapping_add(1), k1));
(k0, k1)
})
}