Skip to content

Commit

Permalink
Use custom map types with custom hasher types
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcrichton committed Apr 12, 2024
1 parent 38b0549 commit 80e0f18
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 17 deletions.
1 change: 1 addition & 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ semver = { version = "1.0.0", default-features = false }
smallvec = "1.11.1"
libtest-mimic = "0.7.0"
hashbrown = { version = "0.14.3", default-features = false, features = ['ahash'] }
ahash = { version = "0.8.11", default-features = false }

wasm-compose = { version = "0.202.0", path = "crates/wasm-compose" }
wasm-encoder = { version = "0.202.0", path = "crates/wasm-encoder" }
Expand Down
4 changes: 2 additions & 2 deletions crates/wasm-compose/src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ impl<'a> TypeEncoder<'a> {
index
}

fn flags(encodable: &mut Encodable, names: &IndexSet<KebabString>) -> u32 {
fn flags(encodable: &mut Encodable, names: &wasmparser::map::IndexSet<KebabString>) -> u32 {
let index = encodable.type_count();
encodable
.ty()
Expand All @@ -739,7 +739,7 @@ impl<'a> TypeEncoder<'a> {
index
}

fn enum_type(encodable: &mut Encodable, cases: &IndexSet<KebabString>) -> u32 {
fn enum_type(encodable: &mut Encodable, cases: &wasmparser::map::IndexSet<KebabString>) -> u32 {
let index = encodable.type_count();
encodable
.ty()
Expand Down
1 change: 1 addition & 0 deletions crates/wasmparser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ bitflags = "2.4.1"
indexmap = { workspace = true }
semver = { workspace = true }
hashbrown = { workspace = true }
ahash = { workspace = true }

[dev-dependencies]
anyhow = { workspace = true }
Expand Down
11 changes: 3 additions & 8 deletions crates/wasmparser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,7 @@ mod prelude {
pub use alloc::vec;
pub use alloc::vec::Vec;

#[cfg(feature = "std")]
pub type IndexMap<K, V> = indexmap::IndexMap<K, V>;
#[cfg(feature = "std")]
pub type IndexSet<K> = indexmap::IndexSet<K>;
#[cfg(not(feature = "std"))]
pub type IndexMap<K, V> = indexmap::IndexMap<K, V, hashbrown::hash_map::DefaultHashBuilder>;
#[cfg(not(feature = "std"))]
pub type IndexSet<K> = indexmap::IndexSet<K, hashbrown::hash_map::DefaultHashBuilder>;
pub use crate::map::{HashMap, HashSet, IndexMap, IndexSet};
}

/// A helper macro to conveniently iterate over all opcodes recognized by this
Expand Down Expand Up @@ -787,3 +780,5 @@ mod parser;
mod readers;
mod resources;
mod validator;

pub mod map;
126 changes: 126 additions & 0 deletions crates/wasmparser/src/map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
//! Type aliases for maps used by `wasmparser`
//!
//! This module contains type aliases used for [`HashMap`], [`HashSet`],
//! [`IndexMap`], and [`IndexSet`]. Note that these differ from upstream types
//! in the `indexmap` crate and the standard library due to customization of the
//! hash algorithm type parameter.
use core::hash::{BuildHasher, Hasher};

/// Wasmparser-specific type alias for an ordered map.
pub type IndexMap<K, V> = indexmap::IndexMap<K, V, RandomState>;

/// Wasmparser-specific type alias for an ordered set.
pub type IndexSet<K> = indexmap::IndexSet<K, RandomState>;

/// Wasmparser-specific type alias for hash map.
pub type HashMap<K, V> = hashbrown::HashMap<K, V, RandomState>;

/// Wasmparser-specific type alias for hash set.
pub type HashSet<K> = hashbrown::HashSet<K, RandomState>;

/// Wasmparser's hashing state stored per-map.
///
/// This is DoS-resistant when the `std` feature is activated and still somewhat
/// resistant when it's not active but not as secure.
#[derive(Clone, Debug)]
pub struct RandomState(RandomStateImpl);

impl Default for RandomState {
#[inline]
fn default() -> RandomState {
RandomState(RandomStateImpl::default())
}
}

impl BuildHasher for RandomState {
type Hasher = RandomStateHasher;

#[inline]
fn build_hasher(&self) -> RandomStateHasher {
RandomStateHasher(self.0.build_hasher())
}
}

/// Wasmparser's hasher type used with [`RandomState`].
pub struct RandomStateHasher(<RandomStateImpl as BuildHasher>::Hasher);

impl Hasher for RandomStateHasher {
#[inline]
fn finish(&self) -> u64 {
self.0.finish()
}
#[inline]
fn write(&mut self, bytes: &[u8]) {
self.0.write(bytes)
}
#[inline]
fn write_u8(&mut self, i: u8) {
self.0.write_u8(i)
}
#[inline]
fn write_u16(&mut self, i: u16) {
self.0.write_u16(i)
}
#[inline]
fn write_u32(&mut self, i: u32) {
self.0.write_u32(i)
}
#[inline]
fn write_u64(&mut self, i: u64) {
self.0.write_u64(i)
}
#[inline]
fn write_u128(&mut self, i: u128) {
self.0.write_u128(i)
}
#[inline]
fn write_usize(&mut self, i: usize) {
self.0.write_usize(i)
}
#[inline]
fn write_i8(&mut self, i: i8) {
self.0.write_i8(i)
}
#[inline]
fn write_i16(&mut self, i: i16) {
self.0.write_i16(i)
}
#[inline]
fn write_i32(&mut self, i: i32) {
self.0.write_i32(i)
}
#[inline]
fn write_i64(&mut self, i: i64) {
self.0.write_i64(i)
}
#[inline]
fn write_i128(&mut self, i: i128) {
self.0.write_i128(i)
}
#[inline]
fn write_isize(&mut self, i: isize) {
self.0.write_isize(i)
}
}

// When the `std` feature is active reuse the standard library's implementation
// of hash state and hasher.
#[cfg(feature = "std")]
use std::collections::hash_map::RandomState as RandomStateImpl;

// When the `std` feature is NOT active then rely on `ahash::RandomState`. That
// relies on ASLR by default for randomness.
#[derive(Default, Clone, Debug)]
#[cfg(not(feature = "std"))]
struct RandomStateImpl;

#[cfg(not(feature = "std"))]
impl BuildHasher for RandomStateImpl {
type Hasher = ahash::AHasher;

#[inline]
fn build_hasher(&self) -> ahash::AHasher {
ahash::RandomState::new().build_hasher()
}
}
5 changes: 2 additions & 3 deletions crates/wasmparser/src/validator/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ use crate::{
WasmFeatures,
};
use core::mem;
use hashbrown::{HashMap, HashSet};
use indexmap::map::Entry;

fn to_kebab_str<'a>(s: &'a str, desc: &str, offset: usize) -> Result<&'a KebabStr> {
Expand Down Expand Up @@ -1657,8 +1656,8 @@ impl ComponentState {
) -> Result<ComponentFuncType> {
let mut info = TypeInfo::new();

let mut set =
HashSet::with_capacity(core::cmp::max(ty.params.len(), ty.results.type_count()));
let mut set = HashSet::default();
set.reserve(core::cmp::max(ty.params.len(), ty.results.type_count()));

let params = ty
.params
Expand Down
1 change: 0 additions & 1 deletion crates/wasmparser/src/validator/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use crate::{
};
use alloc::sync::Arc;
use core::mem;
use hashbrown::HashSet;

// Section order for WebAssembly modules.
//
Expand Down
3 changes: 1 addition & 2 deletions crates/wasmparser/src/validator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use core::{
mem,
};
use hashbrown::hash_map::Entry;
use hashbrown::{HashMap, HashSet};

/// The maximum number of parameters in the canonical ABI that can be passed by value.
///
Expand Down Expand Up @@ -2841,7 +2840,7 @@ impl TypeList {
});

TypeList {
alias_mappings: HashMap::new(),
alias_mappings: HashMap::default(),
alias_counter: self.alias_counter,
alias_snapshots: self.alias_snapshots.clone(),
core_types: self.core_types.commit(),
Expand Down
2 changes: 1 addition & 1 deletion crates/wit-parser/src/decoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ impl WitPackageDecoder<'_> {
fn decode_interface<'a>(
&mut self,
name: &str,
imports: &IndexMap<String, types::ComponentEntityType>,
imports: &wasmparser::map::IndexMap<String, types::ComponentEntityType>,
ty: &types::ComponentInstanceType,
fields: &mut PackageFields<'a>,
) -> Result<PackageName> {
Expand Down

0 comments on commit 80e0f18

Please sign in to comment.