feat(compress): zero CDict hash table3 in Rust

Move the final CDict-copy hashTable3 clearing operation into the Rust reset
orchestration. The C bridge now projects the post-reset destination table
and hash log while retaining only the private reset, workspace dirty/clean,
and metadata operations on the C side.

Preserve C's zero-log contract: hashLog3 == 0 means no table bytes are
cleared and a null hashTable3 is valid. Nonzero logs are bounds-checked before
Rust zeroes the table, keeping the operation between the dirty and clean
transitions.

Test Plan:
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
- ulimit -v 41943040; make -j1
- ulimit -v 41943040; make -j1 -C tests test-zstream ZSTREAM_TESTTIME=-T2s
- ulimit -v 41943040; make -j1 -C tests test-fuzzer FUZZERTEST=-T3s FUZZER_FLAGS=--no-big-tests
This commit is contained in:
2026-07-19 23:40:39 +02:00
parent 13ccc6a859
commit f758c41c5d
2 changed files with 52 additions and 37 deletions
+8 -18
View File
@@ -2501,8 +2501,6 @@ typedef char ZSTD_rust_reset_cctx_using_cdict_state_layout[
typedef size_t (*ZSTD_rust_resetCCtxByCopyingCDictReset_f)(
void* context, const void* cdict, const void* params,
U64 pledgedSrcSize, int zbuff);
typedef void (*ZSTD_rust_resetCCtxByCopyingCDictState_f)(
void* context, const void* cdict);
typedef void (*ZSTD_rust_resetCCtxByCopyingCDictMarkTables_f)(void* context);
typedef struct {
void* callbackContext;
@@ -2511,7 +2509,6 @@ typedef struct {
U64 pledgedSrcSize;
ZSTD_rust_resetCCtxByCopyingCDictReset_f reset;
ZSTD_rust_resetCCtxByCopyingCDictMarkTables_f markTablesDirty;
ZSTD_rust_resetCCtxByCopyingCDictState_f zeroHashTable3;
ZSTD_rust_resetCCtxByCopyingCDictMarkTables_f markTablesClean;
U32** destinationHashTable;
const U32* sourceHashTable;
@@ -2528,6 +2525,8 @@ typedef struct {
const BYTE* sourceTagTable;
U64* destinationHashSalt;
const U64* sourceHashSalt;
U32** destinationHashTable3;
const U32* destinationHashLog3;
void* destinationWindow;
const void* sourceWindow;
U32* destinationNextToUpdate;
@@ -2555,7 +2554,7 @@ typedef char ZSTD_rust_reset_cctx_by_copying_cdict_state_layout[
&& offsetof(ZSTD_rust_resetCCtxByCopyingCDictState, reset)
== 3 * sizeof(void*) + sizeof(U64)
&& offsetof(ZSTD_rust_resetCCtxByCopyingCDictState, zbuff)
== 3 * sizeof(void*) + sizeof(U64) + 31 * sizeof(void*)
== 3 * sizeof(void*) + sizeof(U64) + 32 * sizeof(void*)
&& sizeof(ZSTD_rust_resetCCtxByCopyingCDictState)
== ((offsetof(ZSTD_rust_resetCCtxByCopyingCDictState, zbuff)
+ sizeof(int) + sizeof(void*) - 1) / sizeof(void*))
@@ -4600,18 +4599,6 @@ static void ZSTD_rust_resetCCtx_byCopyingCDict_mark_tables_dirty(void* context)
ZSTD_cwksp_mark_tables_dirty(&cctx->workspace);
}
static void ZSTD_rust_resetCCtx_byCopyingCDict_zero_hash_table3(
void* context, const void* cdictOpaque)
{
ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context;
const ZSTD_CDict* const cdict = (const ZSTD_CDict*)cdictOpaque;
U32 const h3log = cctx->blockState.matchState.hashLog3;
assert(h3log <= 31);
assert(cdict->matchState.hashLog3 == 0);
ZSTD_memset(cctx->blockState.matchState.hashTable3, 0,
(h3log ? ((size_t)1 << h3log) : 0) * sizeof(U32));
}
static void ZSTD_rust_resetCCtx_byCopyingCDict_mark_tables_clean(void* context)
{
ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context;
@@ -4640,10 +4627,9 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
state.reset = ZSTD_rust_resetCCtx_byCopyingCDict_reset;
state.markTablesDirty =
ZSTD_rust_resetCCtx_byCopyingCDict_mark_tables_dirty;
state.zeroHashTable3 =
ZSTD_rust_resetCCtx_byCopyingCDict_zero_hash_table3;
state.markTablesClean =
ZSTD_rust_resetCCtx_byCopyingCDict_mark_tables_clean;
assert(cdict->matchState.hashLog3 == 0);
state.destinationHashTable =
&cctx->blockState.matchState.hashTable;
state.sourceHashTable = cdict->matchState.hashTable;
@@ -4665,6 +4651,10 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
state.destinationHashSalt =
&cctx->blockState.matchState.hashSalt;
state.sourceHashSalt = &cdict->matchState.hashSalt;
state.destinationHashTable3 =
&cctx->blockState.matchState.hashTable3;
state.destinationHashLog3 =
&cctx->blockState.matchState.hashLog3;
state.destinationWindow = &cctx->blockState.matchState.window;
state.sourceWindow = &cdict->matchState.window;
state.destinationNextToUpdate = &cctx->blockState.matchState.nextToUpdate;