feat(compress): project hash salt entropy into Rust

The row-matchfinder reset path only used its C callback to read the private
hashSaltEntropy scalar and invoke Rust. Replace that callback slot with the
existing 32-bit scalar, keep the ABI offsets pointer-sized on 32-bit and
64-bit targets, and update the salt directly in Rust at the row-table reset
point. Preserve the C workspace callbacks and verify the real salt transition
in the reset-policy test.

Test Plan:
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo check --manifest-path rust/Cargo.toml --tests
- ulimit -v 41943040; make -j1
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings
- ulimit -v 41943040; make -j1 -C tests test
This commit is contained in:
2026-07-21 19:45:07 +02:00
parent 5f965b7025
commit 8597c9c4aa
2 changed files with 30 additions and 26 deletions
+8 -12
View File
@@ -1241,7 +1241,6 @@ int ZSTD_rust_simpleCompressStream2Policy(
ZSTD_rust_simpleCompress2Level_f simpleCompress2Level);
int ZSTD_rust_simpleCompressStream2Level(const void* cctx, size_t srcSize);
U32 ZSTD_rust_limitNextToUpdate(U32 curr, U32 nextToUpdate);
void ZSTD_rust_advanceHashSaltInPlace(U64* hashSalt, U64 hashSaltEntropy);
void ZSTD_rust_reduceIndex(U32* hashTable, U32 hashSize,
U32* chainTable, U32 chainSize,
U32* hashTable3, U32 hashSize3,
@@ -1286,7 +1285,6 @@ typedef char ZSTD_rust_overflow_correct_state_layout[
? 1 : -1];
void ZSTD_rust_copyCDictTableIntoCCtx(U32* dst, U32 const* src,
size_t tableSize, int tagged);
U64 ZSTD_rust_advanceHashSalt(U64 hashSalt, U64 hashSaltEntropy);
int ZSTD_indexTooCloseToMax(size_t nextSrcBaseOffset);
int ZSTD_dictTooBig(size_t loadedDictSize);
@@ -1327,7 +1325,7 @@ typedef struct {
ZSTD_rust_resetMatchStateCallback_f invalidateMatchState;
ZSTD_rust_resetMatchStateCallback_f clearTables;
ZSTD_rust_resetMatchStateCallback_f cleanTables;
ZSTD_rust_resetMatchStateCallback_f advanceHashSalt;
unsigned hashSaltEntropy;
ZSTD_rust_resetMatchStateReserve_f reserve;
ZSTD_rust_resetMatchStateReserveFailed_f reserveFailed;
ZSTD_rust_resetMatchStateZero_f zero;
@@ -1341,6 +1339,12 @@ typedef char ZSTD_rust_reset_match_state_layout[
&& offsetof(ZSTD_rust_resetMatchStateState, hashLog3)
== offsetof(ZSTD_rust_resetMatchStateState, optimalSize)
+ sizeof(size_t)
&& offsetof(ZSTD_rust_resetMatchStateState, hashSaltEntropy)
== offsetof(ZSTD_rust_resetMatchStateState, cleanTables)
+ sizeof(void*)
&& offsetof(ZSTD_rust_resetMatchStateState, reserve)
== offsetof(ZSTD_rust_resetMatchStateState, hashSaltEntropy)
+ sizeof(void*)
&& offsetof(ZSTD_rust_resetMatchStateState, setPointer)
== offsetof(ZSTD_rust_resetMatchStateState, cParamsOut)
+ sizeof(void*)
@@ -4994,14 +4998,6 @@ static void ZSTD_rust_resetMatchState_cleanTables(void* opaque)
ZSTD_cwksp_clean_tables(context->ws);
}
static void ZSTD_rust_resetMatchState_advanceHashSalt(void* opaque)
{
ZSTD_rust_resetMatchStateContext* const context =
(ZSTD_rust_resetMatchStateContext*)opaque;
ZSTD_rust_advanceHashSaltInPlace(
&context->ms->hashSalt, (U64)context->ms->hashSaltEntropy);
}
static void* ZSTD_rust_resetMatchState_reserve(
void* opaque, int reserveKind, size_t size)
{
@@ -5115,7 +5111,7 @@ ZSTD_reset_matchState(ZSTD_MatchState_t* ms,
state.invalidateMatchState = ZSTD_rust_resetMatchState_invalidate;
state.clearTables = ZSTD_rust_resetMatchState_clearTables;
state.cleanTables = ZSTD_rust_resetMatchState_cleanTables;
state.advanceHashSalt = ZSTD_rust_resetMatchState_advanceHashSalt;
state.hashSaltEntropy = ms->hashSaltEntropy;
state.reserve = ZSTD_rust_resetMatchState_reserve;
state.reserveFailed = ZSTD_rust_resetMatchState_reserveFailed;
state.zero = ZSTD_rust_resetMatchState_zero;
+22 -14
View File
@@ -8843,7 +8843,7 @@ pub struct ZSTD_rust_resetMatchStateState {
invalidate_match_state: Option<ResetMatchStateCallback>,
clear_tables: Option<ResetMatchStateCallback>,
clean_tables: Option<ResetMatchStateCallback>,
advance_hash_salt: Option<ResetMatchStateCallback>,
hash_salt_entropy: c_uint,
reserve: Option<ResetMatchStateReserve>,
reserve_failed: Option<ResetMatchStateReserveFailed>,
zero: Option<ResetMatchStateZero>,
@@ -8865,6 +8865,15 @@ const _: () = {
offset_of!(ZSTD_rust_resetMatchStateState, hash_log3)
== offset_of!(ZSTD_rust_resetMatchStateState, optimal_size) + size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetMatchStateState, hash_salt_entropy)
== offset_of!(ZSTD_rust_resetMatchStateState, clean_tables) + size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetMatchStateState, reserve)
== offset_of!(ZSTD_rust_resetMatchStateState, hash_salt_entropy)
+ size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_resetMatchStateState, set_pointer)
== offset_of!(ZSTD_rust_resetMatchStateState, c_params_out) + size_of::<usize>()
@@ -8911,9 +8920,6 @@ pub unsafe extern "C" fn ZSTD_rust_resetMatchState(
let Some(clean_tables) = state.clean_tables else {
return ERROR(ZstdErrorCode::Generic);
};
let Some(advance_hash_salt) = state.advance_hash_salt else {
return ERROR(ZstdErrorCode::Generic);
};
let Some(reserve) = state.reserve else {
return ERROR(ZstdErrorCode::Generic);
};
@@ -9038,7 +9044,10 @@ pub unsafe extern "C" fn ZSTD_rust_resetMatchState(
RESET_MATCH_POINTER_TAG_TABLE,
tag_table,
);
advance_hash_salt(state.callback_context);
*state.hash_salt = advance_hash_salt(
*state.hash_salt,
state.hash_salt_entropy as u64,
);
}
} else {
let tag_table = unsafe {
@@ -13051,6 +13060,7 @@ mod tests {
zeroed: Vec<(usize, usize)>,
storage: [usize; 32],
fail_after: usize,
hash_salt_entropy: c_uint,
}
unsafe fn reset_match_state_test_context(
@@ -13084,11 +13094,6 @@ mod tests {
context.events.push(5);
}
unsafe extern "C" fn reset_match_state_test_advance(context: *mut c_void) {
let context = unsafe { reset_match_state_test_context(context) };
context.events.push(6);
}
unsafe extern "C" fn reset_match_state_test_reserve(
context: *mut c_void,
reserve_kind: c_int,
@@ -13171,7 +13176,7 @@ mod tests {
invalidate_match_state: Some(reset_match_state_test_invalidate),
clear_tables: Some(reset_match_state_test_clear),
clean_tables: Some(reset_match_state_test_clean),
advance_hash_salt: Some(reset_match_state_test_advance),
hash_salt_entropy: context.hash_salt_entropy,
reserve: Some(reset_match_state_test_reserve),
reserve_failed: Some(reset_match_state_test_reserve_failed),
zero: Some(reset_match_state_test_zero),
@@ -13254,7 +13259,10 @@ mod tests {
#[test]
fn reset_match_state_salts_cctx_row_tables_without_zeroing() {
let c_params = reset_match_state_test_params(ZSTD_GREEDY, 6, 4);
let mut context = ResetMatchStateTestContext::default();
let mut context = ResetMatchStateTestContext {
hash_salt_entropy: 11,
..ResetMatchStateTestContext::default()
};
let mut hash_log3 = 99;
let mut row_hash_log = 99;
let mut hash_salt = 7;
@@ -13280,11 +13288,11 @@ mod tests {
assert_eq!(result, 0);
assert_eq!(hash_log3, 0);
assert_eq!(row_hash_log, 6);
assert_eq!(hash_salt, 7);
assert_eq!(hash_salt, advance_hash_salt(7, 11));
assert_eq!(c_params_out, c_params);
assert_eq!(
context.events,
[3, 4, 100, 200, 100, 201, 100, 202, 5, 101, 203, 6]
[3, 4, 100, 200, 100, 201, 100, 202, 5, 101, 203]
);
assert_eq!(
context.reserves,