feat(compress): move match index reduction orchestration to Rust

ZSTD_reduceIndex previously selected and reduced each match table through
separate C helpers, even though the 16-cell reduction leaf already lived in
Rust. Keep C responsible for match-state access, table allocation policy,
nullable table selection, btlazy2 strategy selection, and the surrounding
workspace/window/dictionary state transition. Add one narrow Rust ABI that
receives only the validated hash, chain, and hash3 table slices and delegates
to the existing reducer, preserving chain markers only when requested and
keeping threshold and U32 wrapping arithmetic unchanged. Focused tests cover
zero-sized optional tables, marker routing, and threshold behavior.

Test Plan:
- `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression zstd_compress::tests::reduce_` -- 5 passed.
- `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression` -- 344 passed.
- `make -C lib -j2 lib-mt` and `make -C lib -j2 lib-nomt` -- passed.
- `make -C tests -j2 test-zstream` -- 84 named, 6,814 standard
  randomized, and 8,955 new-API randomized cases passed.
- Required compression clippy library/benches/tests, nightly fmt, and the repeated three clippy checks -- passed.
This commit is contained in:
2026-07-18 15:21:04 +02:00
parent a9b11394ce
commit 841806dcce
2 changed files with 108 additions and 30 deletions
+19 -28
View File
@@ -67,8 +67,10 @@ size_t ZSTD_compressStream2_c(ZSTD_CCtx* cctx,
ZSTD_EndDirective endOp);
int ZSTD_rust_simpleCompress2Level(const void* cctx);
int ZSTD_rust_simpleCompressStream2Level(const void* cctx);
void ZSTD_rust_reduceTable(U32* table, U32 size, U32 reducerValue,
int preserveMark);
void ZSTD_rust_reduceIndex(U32* hashTable, U32 hashSize,
U32* chainTable, U32 chainSize,
U32* hashTable3, U32 hashSize3,
U32 reducerValue, int preserveChainMark);
void ZSTD_rust_copyCDictTableIntoCCtx(U32* dst, U32 const* src,
size_t tableSize, int tagged);
U64 ZSTD_rust_advanceHashSalt(U64 hashSalt, U64 hashSaltEntropy);
@@ -2116,42 +2118,31 @@ size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long
}
/*! ZSTD_reduceTable() :
* reduce table indexes by `reducerValue`, or squash to zero.
* PreserveMark preserves "unsorted mark" for btlazy2 strategy.
* It must be set to a clear 0/1 value, to remove branch during inlining.
* Presume table size is a multiple of 16 cells
* to help auto-vectorization */
static void ZSTD_reduceTable(U32* const table, U32 const size, U32 const reducerValue)
{
ZSTD_rust_reduceTable(table, size, reducerValue, 0);
}
static void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const reducerValue)
{
ZSTD_rust_reduceTable(table, size, reducerValue, 1);
}
/*! ZSTD_reduceIndex() :
* rescale all indexes to avoid future overflow (indexes are U32) */
static void ZSTD_reduceIndex (ZSTD_MatchState_t* ms, ZSTD_CCtx_params const* params, const U32 reducerValue)
{
{ U32 const hSize = (U32)1 << params->cParams.hashLog;
ZSTD_reduceTable(ms->hashTable, hSize, reducerValue);
}
U32 const hSize = (U32)1 << params->cParams.hashLog;
U32* chainTable = NULL;
U32 chainSize = 0;
U32* hashTable3 = NULL;
U32 hashSize3 = 0;
if (ZSTD_allocateChainTable(params->cParams.strategy, params->useRowMatchFinder, (U32)ms->dedicatedDictSearch)) {
U32 const chainSize = (U32)1 << params->cParams.chainLog;
if (params->cParams.strategy == ZSTD_btlazy2)
ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue);
else
ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue);
chainTable = ms->chainTable;
chainSize = (U32)1 << params->cParams.chainLog;
}
if (ms->hashLog3) {
U32 const h3Size = (U32)1 << ms->hashLog3;
ZSTD_reduceTable(ms->hashTable3, h3Size, reducerValue);
hashTable3 = ms->hashTable3;
hashSize3 = (U32)1 << ms->hashLog3;
}
ZSTD_rust_reduceIndex(ms->hashTable, hSize,
chainTable, chainSize,
hashTable3, hashSize3,
reducerValue,
params->cParams.strategy == ZSTD_btlazy2);
}