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); ZSTD_rust_simpleCompress2Level_f simpleCompress2Level);
int ZSTD_rust_simpleCompressStream2Level(const void* cctx, size_t srcSize); int ZSTD_rust_simpleCompressStream2Level(const void* cctx, size_t srcSize);
U32 ZSTD_rust_limitNextToUpdate(U32 curr, U32 nextToUpdate); U32 ZSTD_rust_limitNextToUpdate(U32 curr, U32 nextToUpdate);
void ZSTD_rust_advanceHashSaltInPlace(U64* hashSalt, U64 hashSaltEntropy);
void ZSTD_rust_reduceIndex(U32* hashTable, U32 hashSize, void ZSTD_rust_reduceIndex(U32* hashTable, U32 hashSize,
U32* chainTable, U32 chainSize, U32* chainTable, U32 chainSize,
U32* hashTable3, U32 hashSize3, U32* hashTable3, U32 hashSize3,
@@ -1286,7 +1285,6 @@ typedef char ZSTD_rust_overflow_correct_state_layout[
? 1 : -1]; ? 1 : -1];
void ZSTD_rust_copyCDictTableIntoCCtx(U32* dst, U32 const* src, void ZSTD_rust_copyCDictTableIntoCCtx(U32* dst, U32 const* src,
size_t tableSize, int tagged); size_t tableSize, int tagged);
U64 ZSTD_rust_advanceHashSalt(U64 hashSalt, U64 hashSaltEntropy);
int ZSTD_indexTooCloseToMax(size_t nextSrcBaseOffset); int ZSTD_indexTooCloseToMax(size_t nextSrcBaseOffset);
int ZSTD_dictTooBig(size_t loadedDictSize); int ZSTD_dictTooBig(size_t loadedDictSize);
@@ -1327,7 +1325,7 @@ typedef struct {
ZSTD_rust_resetMatchStateCallback_f invalidateMatchState; ZSTD_rust_resetMatchStateCallback_f invalidateMatchState;
ZSTD_rust_resetMatchStateCallback_f clearTables; ZSTD_rust_resetMatchStateCallback_f clearTables;
ZSTD_rust_resetMatchStateCallback_f cleanTables; ZSTD_rust_resetMatchStateCallback_f cleanTables;
ZSTD_rust_resetMatchStateCallback_f advanceHashSalt; unsigned hashSaltEntropy;
ZSTD_rust_resetMatchStateReserve_f reserve; ZSTD_rust_resetMatchStateReserve_f reserve;
ZSTD_rust_resetMatchStateReserveFailed_f reserveFailed; ZSTD_rust_resetMatchStateReserveFailed_f reserveFailed;
ZSTD_rust_resetMatchStateZero_f zero; 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, hashLog3)
== offsetof(ZSTD_rust_resetMatchStateState, optimalSize) == offsetof(ZSTD_rust_resetMatchStateState, optimalSize)
+ sizeof(size_t) + 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, setPointer)
== offsetof(ZSTD_rust_resetMatchStateState, cParamsOut) == offsetof(ZSTD_rust_resetMatchStateState, cParamsOut)
+ sizeof(void*) + sizeof(void*)
@@ -4994,14 +4998,6 @@ static void ZSTD_rust_resetMatchState_cleanTables(void* opaque)
ZSTD_cwksp_clean_tables(context->ws); 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( static void* ZSTD_rust_resetMatchState_reserve(
void* opaque, int reserveKind, size_t size) 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.invalidateMatchState = ZSTD_rust_resetMatchState_invalidate;
state.clearTables = ZSTD_rust_resetMatchState_clearTables; state.clearTables = ZSTD_rust_resetMatchState_clearTables;
state.cleanTables = ZSTD_rust_resetMatchState_cleanTables; state.cleanTables = ZSTD_rust_resetMatchState_cleanTables;
state.advanceHashSalt = ZSTD_rust_resetMatchState_advanceHashSalt; state.hashSaltEntropy = ms->hashSaltEntropy;
state.reserve = ZSTD_rust_resetMatchState_reserve; state.reserve = ZSTD_rust_resetMatchState_reserve;
state.reserveFailed = ZSTD_rust_resetMatchState_reserveFailed; state.reserveFailed = ZSTD_rust_resetMatchState_reserveFailed;
state.zero = ZSTD_rust_resetMatchState_zero; state.zero = ZSTD_rust_resetMatchState_zero;
+22 -14
View File
@@ -8843,7 +8843,7 @@ pub struct ZSTD_rust_resetMatchStateState {
invalidate_match_state: Option<ResetMatchStateCallback>, invalidate_match_state: Option<ResetMatchStateCallback>,
clear_tables: Option<ResetMatchStateCallback>, clear_tables: Option<ResetMatchStateCallback>,
clean_tables: Option<ResetMatchStateCallback>, clean_tables: Option<ResetMatchStateCallback>,
advance_hash_salt: Option<ResetMatchStateCallback>, hash_salt_entropy: c_uint,
reserve: Option<ResetMatchStateReserve>, reserve: Option<ResetMatchStateReserve>,
reserve_failed: Option<ResetMatchStateReserveFailed>, reserve_failed: Option<ResetMatchStateReserveFailed>,
zero: Option<ResetMatchStateZero>, zero: Option<ResetMatchStateZero>,
@@ -8865,6 +8865,15 @@ const _: () = {
offset_of!(ZSTD_rust_resetMatchStateState, hash_log3) offset_of!(ZSTD_rust_resetMatchStateState, hash_log3)
== offset_of!(ZSTD_rust_resetMatchStateState, optimal_size) + size_of::<usize>() == 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!( assert!(
offset_of!(ZSTD_rust_resetMatchStateState, set_pointer) offset_of!(ZSTD_rust_resetMatchStateState, set_pointer)
== offset_of!(ZSTD_rust_resetMatchStateState, c_params_out) + size_of::<usize>() == 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 { let Some(clean_tables) = state.clean_tables else {
return ERROR(ZstdErrorCode::Generic); return ERROR(ZstdErrorCode::Generic);
}; };
let Some(advance_hash_salt) = state.advance_hash_salt else {
return ERROR(ZstdErrorCode::Generic);
};
let Some(reserve) = state.reserve else { let Some(reserve) = state.reserve else {
return ERROR(ZstdErrorCode::Generic); return ERROR(ZstdErrorCode::Generic);
}; };
@@ -9038,7 +9044,10 @@ pub unsafe extern "C" fn ZSTD_rust_resetMatchState(
RESET_MATCH_POINTER_TAG_TABLE, RESET_MATCH_POINTER_TAG_TABLE,
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 { } else {
let tag_table = unsafe { let tag_table = unsafe {
@@ -13051,6 +13060,7 @@ mod tests {
zeroed: Vec<(usize, usize)>, zeroed: Vec<(usize, usize)>,
storage: [usize; 32], storage: [usize; 32],
fail_after: usize, fail_after: usize,
hash_salt_entropy: c_uint,
} }
unsafe fn reset_match_state_test_context( unsafe fn reset_match_state_test_context(
@@ -13084,11 +13094,6 @@ mod tests {
context.events.push(5); 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( unsafe extern "C" fn reset_match_state_test_reserve(
context: *mut c_void, context: *mut c_void,
reserve_kind: c_int, reserve_kind: c_int,
@@ -13171,7 +13176,7 @@ mod tests {
invalidate_match_state: Some(reset_match_state_test_invalidate), invalidate_match_state: Some(reset_match_state_test_invalidate),
clear_tables: Some(reset_match_state_test_clear), clear_tables: Some(reset_match_state_test_clear),
clean_tables: Some(reset_match_state_test_clean), 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: Some(reset_match_state_test_reserve),
reserve_failed: Some(reset_match_state_test_reserve_failed), reserve_failed: Some(reset_match_state_test_reserve_failed),
zero: Some(reset_match_state_test_zero), zero: Some(reset_match_state_test_zero),
@@ -13254,7 +13259,10 @@ mod tests {
#[test] #[test]
fn reset_match_state_salts_cctx_row_tables_without_zeroing() { fn reset_match_state_salts_cctx_row_tables_without_zeroing() {
let c_params = reset_match_state_test_params(ZSTD_GREEDY, 6, 4); 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 hash_log3 = 99;
let mut row_hash_log = 99; let mut row_hash_log = 99;
let mut hash_salt = 7; let mut hash_salt = 7;
@@ -13280,11 +13288,11 @@ mod tests {
assert_eq!(result, 0); assert_eq!(result, 0);
assert_eq!(hash_log3, 0); assert_eq!(hash_log3, 0);
assert_eq!(row_hash_log, 6); 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!(c_params_out, c_params);
assert_eq!( assert_eq!(
context.events, 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!( assert_eq!(
context.reserves, context.reserves,