aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlice Ryhl <aliceryhl@google.com>2023-10-24 14:58:03 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-10-24 14:58:03 +0000
commitfa5d7d3c3990f9002707e072fc87550ca868c85a (patch)
treed4f09d781d9cddc8da2e810e614f5aeb8947bf09
parentaf5a95a9d2962d34d17767649bf1b9b018afdefc (diff)
parent88740a120673cb4c7af8295116f398b9536f0f10 (diff)
downloadahash-fa5d7d3c3990f9002707e072fc87550ca868c85a.tar.gz
Upgrade ahash to 0.8.5 am: 88740a1206
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/ahash/+/2801334 Change-Id: I80c202f26f50902e31f1695a409ac22f5ec5d851 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--.github/workflows/rust.yml15
-rw-r--r--Android.bp5
-rw-r--r--Cargo.toml13
-rw-r--r--Cargo.toml.orig3
-rw-r--r--METADATA10
-rw-r--r--src/aes_hash.rs13
-rw-r--r--src/convert.rs7
-rw-r--r--src/hash_quality_test.rs44
-rw-r--r--src/operations.rs35
10 files changed, 94 insertions, 53 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 5f20ebf..a2a6019 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
{
"git": {
- "sha1": "f9acd508bd89e7c5b2877a9510098100f9018d64"
+ "sha1": "7bbbd833cb48c6f8e64bd94c196a700c09bb97e4"
},
"path_in_vcs": ""
} \ No newline at end of file
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index c551724..f09853c 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -51,7 +51,7 @@ jobs:
env:
RUSTFLAGS: -C target-cpu=native
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v2
- name: Install latest nightly
uses: actions-rs/toolchain@v1
with:
@@ -89,6 +89,19 @@ jobs:
with:
command: check
args: --target armv7-unknown-linux-gnueabihf
+ aarch64-apple-darwin:
+ name: Aarch64 Apple Darwin
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions-rs/toolchain@v1
+ with:
+ toolchain: stable
+ target: aarch64-apple-darwin
+ - uses: actions-rs/cargo@v1
+ with:
+ command: check
+ args: --target aarch64-apple-darwin
i686-unknown-linux-gnu:
name: Linux i686
runs-on: ubuntu-latest
diff --git a/Android.bp b/Android.bp
index dcefb1c..3b13fa6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -42,7 +42,7 @@ rust_library {
host_supported: true,
crate_name: "ahash",
cargo_env_compat: true,
- cargo_pkg_version: "0.8.3",
+ cargo_pkg_version: "0.8.5",
srcs: ["src/lib.rs"],
edition: "2018",
arch: {
@@ -57,14 +57,13 @@ rust_library {
"default",
"getrandom",
"runtime-rng",
- "specialize",
"std",
- "stdsimd",
],
rustlibs: [
"libcfg_if",
"libgetrandom",
"libonce_cell",
+ "libzerocopy",
],
apex_available: [
"//apex_available:platform",
diff --git a/Cargo.toml b/Cargo.toml
index a027c55..e87124f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "ahash"
-version = "0.8.3"
+version = "0.8.5"
authors = ["Tom Kaitchuck <Tom.Kaitchuck@gmail.com>"]
build = "./build.rs"
exclude = [
@@ -38,6 +38,7 @@ license = "MIT OR Apache-2.0"
repository = "https://github.com/tkaitchuck/ahash"
[package.metadata.docs.rs]
+features = ["std"]
rustc-args = [
"-C",
"target-feature=+aes",
@@ -46,20 +47,19 @@ rustdoc-args = [
"-C",
"target-feature=+aes",
]
-features = ["std"]
[profile.bench]
opt-level = 3
lto = "fat"
codegen-units = 1
-debug = false
+debug = 0
debug-assertions = false
[profile.release]
opt-level = 3
lto = "fat"
codegen-units = 1
-debug = false
+debug = 0
debug-assertions = false
[profile.test]
@@ -103,6 +103,11 @@ optional = true
version = "1.0.117"
optional = true
+[dependencies.zerocopy]
+version = "0.7.0"
+features = ["simd"]
+default-features = false
+
[dev-dependencies.criterion]
version = "0.3.2"
features = ["html_reports"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 9b19105..b340522 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "ahash"
-version = "0.8.3"
+version = "0.8.5"
authors = ["Tom Kaitchuck <Tom.Kaitchuck@gmail.com>"]
license = "MIT OR Apache-2.0"
description = "A non-cryptographic hash function using AES-NI for high performance"
@@ -80,6 +80,7 @@ serde = { version = "1.0.117", optional = true }
cfg-if = "1.0"
atomic-polyfill = { version="1.0.1", optional=true}
getrandom = { version = "0.2.7", optional = true }
+zerocopy = { version = "0.7.0", default-features = false, features = ["simd"] }
[target.'cfg(not(all(target_arch = "arm", target_os = "none")))'.dependencies]
once_cell = { version = "1.13.1", default-features = false, features = ["unstable", "alloc"] }
diff --git a/METADATA b/METADATA
index 18aa68c..5d390c2 100644
--- a/METADATA
+++ b/METADATA
@@ -1,6 +1,6 @@
# This project was upgraded with external_updater.
# Usage: tools/external_updater/updater.sh update rust/crates/ahash
-# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
name: "ahash"
description: "A non-cryptographic hash function using AES-NI for high performance"
@@ -11,13 +11,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/ahash/ahash-0.8.3.crate"
+ value: "https://static.crates.io/crates/ahash/ahash-0.8.5.crate"
}
- version: "0.8.3"
+ version: "0.8.5"
license_type: NOTICE
last_upgrade_date {
year: 2023
- month: 2
- day: 15
+ month: 10
+ day: 24
}
}
diff --git a/src/aes_hash.rs b/src/aes_hash.rs
index 702044e..d3b673f 100644
--- a/src/aes_hash.rs
+++ b/src/aes_hash.rs
@@ -164,10 +164,10 @@ impl Hasher for AHasher {
let tail = data.read_last_u128x4();
let mut current: [u128; 4] = [self.key; 4];
current[0] = aesenc(current[0], tail[0]);
- current[1] = aesenc(current[1], tail[1]);
+ current[1] = aesdec(current[1], tail[1]);
current[2] = aesenc(current[2], tail[2]);
- current[3] = aesenc(current[3], tail[3]);
- let mut sum: [u128; 2] = [self.key, self.key];
+ current[3] = aesdec(current[3], tail[3]);
+ let mut sum: [u128; 2] = [self.key, !self.key];
sum[0] = add_by_64s(sum[0].convert(), tail[0].convert()).convert();
sum[1] = add_by_64s(sum[1].convert(), tail[1].convert()).convert();
sum[0] = shuffle_and_add(sum[0], tail[2]);
@@ -184,8 +184,9 @@ impl Hasher for AHasher {
sum[1] = shuffle_and_add(sum[1], blocks[3]);
data = rest;
}
- self.hash_in_2(aesenc(current[0], current[1]), aesenc(current[2], current[3]));
- self.hash_in(add_by_64s(sum[0].convert(), sum[1].convert()).convert());
+ self.hash_in_2(current[0], current[1]);
+ self.hash_in_2(current[2], current[3]);
+ self.hash_in_2(sum[0], sum[1]);
} else {
//len 33-64
let (head, _) = data.read_u128x2();
@@ -209,7 +210,7 @@ impl Hasher for AHasher {
fn finish(&self) -> u64 {
let combined = aesdec(self.sum, self.enc);
let result: [u64; 2] = aesenc(aesenc(combined, self.key), combined).convert();
- result[0]
+ result[1]
}
}
diff --git a/src/convert.rs b/src/convert.rs
index fc47baa..712eae1 100644
--- a/src/convert.rs
+++ b/src/convert.rs
@@ -7,13 +7,13 @@ macro_rules! convert {
impl Convert<$b> for $a {
#[inline(always)]
fn convert(self) -> $b {
- unsafe { core::mem::transmute::<$a, $b>(self) }
+ zerocopy::transmute!(self)
}
}
impl Convert<$a> for $b {
#[inline(always)]
fn convert(self) -> $a {
- unsafe { core::mem::transmute::<$b, $a>(self) }
+ zerocopy::transmute!(self)
}
}
};
@@ -65,8 +65,7 @@ macro_rules! as_array {
{
#[inline(always)]
fn as_array<T>(slice: &[T]) -> &[T; $len] {
- assert_eq!(slice.len(), $len);
- unsafe { &*(slice.as_ptr() as *const [_; $len]) }
+ core::convert::TryFrom::try_from(slice).unwrap()
}
as_array($input)
}
diff --git a/src/hash_quality_test.rs b/src/hash_quality_test.rs
index 8f13d24..25356e4 100644
--- a/src/hash_quality_test.rs
+++ b/src/hash_quality_test.rs
@@ -1,5 +1,5 @@
use core::hash::{Hash, Hasher};
-use std::collections::HashMap;
+use std::collections::{HashMap};
fn assert_sufficiently_different(a: u64, b: u64, tolerance: i32) {
let (same_byte_count, same_nibble_count) = count_same_bytes_and_nibbles(a, b);
@@ -71,12 +71,8 @@ fn test_no_full_collisions<T: Hasher>(gen_hash: impl Fn() -> T) {
gen_combinations(&options, 7, Vec::new(), &mut combinations);
let mut map: HashMap<u64, Vec<u8>> = HashMap::new();
for combination in combinations {
- let array = unsafe {
- let (begin, middle, end) = combination.align_to::<u8>();
- assert_eq!(0, begin.len());
- assert_eq!(0, end.len());
- middle.to_vec()
- };
+ use zerocopy::AsBytes;
+ let array = combination.as_slice().as_bytes().to_vec();
let mut hasher = gen_hash();
hasher.write(&array);
let hash = hasher.finish();
@@ -342,6 +338,28 @@ fn test_length_extension<T: Hasher>(hasher: impl Fn(u128, u128) -> T) {
}
}
+fn test_sparse<T: Hasher>(hasher: impl Fn() -> T) {
+ let mut buf = [0u8; 256];
+ let mut hashes = HashMap::new();
+ for idx_1 in 0..256 {
+ for idx_2 in idx_1+1..256 {
+ for value_1 in [1, 2, 4, 8, 16, 32, 64, 128] {
+ for value_2 in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 16, 17, 18, 20, 24, 31, 32, 33, 48, 64, 96, 127, 128, 129, 192, 254, 255] {
+ buf[idx_1] = value_1;
+ buf[idx_2] = value_2;
+ let hash_value = hash_with(&buf, &mut hasher());
+ let keys = hashes.entry(hash_value).or_insert(Vec::new());
+ keys.push((idx_1, value_1, idx_2, value_2));
+ buf[idx_1] = 0;
+ buf[idx_2] = 0;
+ }
+ }
+ }
+ }
+ hashes.retain(|_key, value| value.len() != 1);
+ assert_eq!(0, hashes.len(), "Collision with: {:?}", hashes);
+}
+
#[cfg(test)]
mod fallback_tests {
use crate::fallback_hash::*;
@@ -408,6 +426,12 @@ mod fallback_tests {
fn fallback_length_extension() {
test_length_extension(|a, b| AHasher::new_with_keys(a, b));
}
+
+ #[test]
+ fn test_no_sparse_collisions() {
+ test_sparse(|| AHasher::new_with_keys(0, 0));
+ test_sparse(|| AHasher::new_with_keys(1, 2));
+ }
}
///Basic sanity tests of the cypto properties of aHash.
@@ -501,4 +525,10 @@ mod aes_tests {
fn aes_length_extension() {
test_length_extension(|a, b| AHasher::test_with_keys(a, b));
}
+
+ #[test]
+ fn aes_no_sparse_collisions() {
+ test_sparse(|| AHasher::test_with_keys(0, 0));
+ test_sparse(|| AHasher::test_with_keys(1, 2));
+ }
}
diff --git a/src/operations.rs b/src/operations.rs
index ffd3b1a..23d4e22 100644
--- a/src/operations.rs
+++ b/src/operations.rs
@@ -1,4 +1,5 @@
use crate::convert::*;
+use zerocopy::transmute;
///This constant comes from Kunth's prng (Empirically it works better than those from splitmix32).
pub(crate) const MULTIPLE: u64 = 6364136223846793005;
@@ -55,8 +56,7 @@ pub(crate) fn shuffle(a: u128) -> u128 {
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
- use core::mem::transmute;
- unsafe { transmute(_mm_shuffle_epi8(transmute(a), transmute(SHUFFLE_MASK))) }
+ unsafe { transmute!(_mm_shuffle_epi8(transmute!(a), transmute!(SHUFFLE_MASK))) }
}
#[cfg(not(all(target_feature = "ssse3", not(miri))))]
{
@@ -81,13 +81,12 @@ pub(crate) fn shuffle_and_add(base: u128, to_add: u128) -> u128 {
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2", not(miri)))]
#[inline(always)]
pub(crate) fn add_by_64s(a: [u64; 2], b: [u64; 2]) -> [u64; 2] {
- use core::mem::transmute;
unsafe {
#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
- transmute(_mm_add_epi64(transmute(a), transmute(b)))
+ transmute!(_mm_add_epi64(transmute!(a), transmute!(b)))
}
}
@@ -105,10 +104,9 @@ pub(crate) fn aesenc(value: u128, xor: u128) -> u128 {
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
- use core::mem::transmute;
unsafe {
- let value = transmute(value);
- transmute(_mm_aesenc_si128(value, transmute(xor)))
+ let value = transmute!(value);
+ transmute!(_mm_aesenc_si128(value, transmute!(xor)))
}
}
@@ -125,11 +123,9 @@ pub(crate) fn aesenc(value: u128, xor: u128) -> u128 {
use core::arch::aarch64::*;
#[cfg(target_arch = "arm")]
use core::arch::arm::*;
- use core::mem::transmute;
- unsafe {
- let value = transmute(value);
- transmute(vaesmcq_u8(vaeseq_u8(value, transmute(xor))))
- }
+ let res = unsafe { vaesmcq_u8(vaeseq_u8(transmute!(value), transmute!(0u128))) };
+ let value: u128 = transmute!(res);
+ xor ^ value
}
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)))]
@@ -140,10 +136,9 @@ pub(crate) fn aesdec(value: u128, xor: u128) -> u128 {
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
- use core::mem::transmute;
unsafe {
- let value = transmute(value);
- transmute(_mm_aesdec_si128(value, transmute(xor)))
+ let value = transmute!(value);
+ transmute!(_mm_aesdec_si128(value, transmute!(xor)))
}
}
@@ -160,11 +155,9 @@ pub(crate) fn aesdec(value: u128, xor: u128) -> u128 {
use core::arch::aarch64::*;
#[cfg(target_arch = "arm")]
use core::arch::arm::*;
- use core::mem::transmute;
- unsafe {
- let value = transmute(value);
- transmute(vaesimcq_u8(vaesdq_u8(value, transmute(xor))))
- }
+ let res = unsafe { vaesimcq_u8(vaesdq_u8(transmute!(value), transmute!(0u128))) };
+ let value: u128 = transmute!(res);
+ xor ^ value
}
#[allow(unused)]
@@ -207,7 +200,7 @@ mod test {
// #[cfg(target_arch = "x86_64")]
// use core::arch::x86_64::*;
// MASK.with(|mask| {
- // unsafe { transmute(_mm_shuffle_epi8(transmute(a), transmute(mask.get()))) }
+ // unsafe { transmute!(_mm_shuffle_epi8(transmute!(a), transmute!(mask.get()))) }
// })
// }
//