feat(compress): move overflow correction policy into Rust
Move the overflow-correction branch and ordering into the Rust rewrite while keeping the C-owned window correction, workspace table markers, index reducer, and dictionary fields behind callbacks. Rust now preserves the original need-correction fast path, dirty/reduce/clean ordering, saturating nextToUpdate adjustment, and dictionary invalidation. Add focused callback ordering and safe-window tests. Test Plan: - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo fmt --manifest-path rust/Cargo.toml -- --check - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml overflow_correction -- --nocapture - 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 -B -C programs -j1 zstd - ulimit -v 41943040 make -C tests -j1 test-zstream ZSTREAM_TESTTIME=-T1s
This commit is contained in:
+108
-16
@@ -609,6 +609,36 @@ void ZSTD_rust_reduceIndex(U32* hashTable, U32 hashSize,
|
||||
U32* chainTable, U32 chainSize,
|
||||
U32* hashTable3, U32 hashSize3,
|
||||
U32 reducerValue, int preserveChainMark);
|
||||
typedef int (*ZSTD_rust_overflowNeedCorrection_f)(
|
||||
void* context, const void* src, const void* srcEnd);
|
||||
typedef U32 (*ZSTD_rust_overflowCorrect_f)(
|
||||
void* context, const void* src);
|
||||
typedef void (*ZSTD_rust_overflowCallback_f)(void* context);
|
||||
typedef void (*ZSTD_rust_overflowReduceIndex_f)(void* context, U32 correction);
|
||||
typedef struct {
|
||||
void* callbackContext;
|
||||
U32* nextToUpdate;
|
||||
ZSTD_rust_overflowNeedCorrection_f needCorrection;
|
||||
ZSTD_rust_overflowCorrect_f correctOverflow;
|
||||
ZSTD_rust_overflowCallback_f markTablesDirty;
|
||||
ZSTD_rust_overflowReduceIndex_f reduceIndex;
|
||||
ZSTD_rust_overflowCallback_f markTablesClean;
|
||||
ZSTD_rust_overflowCallback_f invalidateDictionary;
|
||||
} ZSTD_rust_overflowCorrectState;
|
||||
void ZSTD_rust_overflowCorrectIfNeeded(
|
||||
const ZSTD_rust_overflowCorrectState* state,
|
||||
const void* src, const void* srcEnd);
|
||||
typedef char ZSTD_rust_overflow_correct_state_layout[
|
||||
(offsetof(ZSTD_rust_overflowCorrectState, callbackContext) == 0
|
||||
&& offsetof(ZSTD_rust_overflowCorrectState, nextToUpdate) == sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_overflowCorrectState, needCorrection) == 2 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_overflowCorrectState, correctOverflow) == 3 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_overflowCorrectState, markTablesDirty) == 4 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_overflowCorrectState, reduceIndex) == 5 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_overflowCorrectState, markTablesClean) == 6 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_overflowCorrectState, invalidateDictionary) == 7 * sizeof(void*)
|
||||
&& sizeof(ZSTD_rust_overflowCorrectState) == 8 * sizeof(void*))
|
||||
? 1 : -1];
|
||||
void ZSTD_rust_copyCDictTableIntoCCtx(U32* dst, U32 const* src,
|
||||
size_t tableSize, int tagged);
|
||||
U64 ZSTD_rust_advanceHashSalt(U64 hashSalt, U64 hashSaltEntropy);
|
||||
@@ -5053,28 +5083,90 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc,
|
||||
return cSize;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ZSTD_MatchState_t* matchState;
|
||||
ZSTD_cwksp* workspace;
|
||||
const ZSTD_CCtx_params* params;
|
||||
} ZSTD_rust_overflowCorrectContext;
|
||||
|
||||
static int ZSTD_rust_overflowCorrect_need(
|
||||
void* context, const void* src, const void* srcEnd)
|
||||
{
|
||||
ZSTD_rust_overflowCorrectContext const* const state =
|
||||
(const ZSTD_rust_overflowCorrectContext*)context;
|
||||
U32 const cycleLog = ZSTD_cycleLog(
|
||||
state->params->cParams.chainLog,
|
||||
state->params->cParams.strategy);
|
||||
U32 const maxDist = (U32)1 << state->params->cParams.windowLog;
|
||||
return (int)ZSTD_window_needOverflowCorrection(
|
||||
state->matchState->window, cycleLog, maxDist,
|
||||
state->matchState->loadedDictEnd, src, srcEnd);
|
||||
}
|
||||
|
||||
static U32 ZSTD_rust_overflowCorrect_correct(void* context, const void* src)
|
||||
{
|
||||
ZSTD_rust_overflowCorrectContext const* const state =
|
||||
(const ZSTD_rust_overflowCorrectContext*)context;
|
||||
U32 const cycleLog = ZSTD_cycleLog(
|
||||
state->params->cParams.chainLog,
|
||||
state->params->cParams.strategy);
|
||||
U32 const maxDist = (U32)1 << state->params->cParams.windowLog;
|
||||
return ZSTD_window_correctOverflow(
|
||||
&state->matchState->window, cycleLog, maxDist, src);
|
||||
}
|
||||
|
||||
static void ZSTD_rust_overflowCorrect_markTablesDirty(void* context)
|
||||
{
|
||||
ZSTD_rust_overflowCorrectContext const* const state =
|
||||
(const ZSTD_rust_overflowCorrectContext*)context;
|
||||
ZSTD_cwksp_mark_tables_dirty(state->workspace);
|
||||
}
|
||||
|
||||
static void ZSTD_rust_overflowCorrect_reduceIndex(void* context, U32 correction)
|
||||
{
|
||||
ZSTD_rust_overflowCorrectContext const* const state =
|
||||
(const ZSTD_rust_overflowCorrectContext*)context;
|
||||
ZSTD_reduceIndex(state->matchState, state->params, correction);
|
||||
}
|
||||
|
||||
static void ZSTD_rust_overflowCorrect_markTablesClean(void* context)
|
||||
{
|
||||
ZSTD_rust_overflowCorrectContext const* const state =
|
||||
(const ZSTD_rust_overflowCorrectContext*)context;
|
||||
ZSTD_cwksp_mark_tables_clean(state->workspace);
|
||||
}
|
||||
|
||||
static void ZSTD_rust_overflowCorrect_invalidateDictionary(void* context)
|
||||
{
|
||||
ZSTD_rust_overflowCorrectContext const* const state =
|
||||
(const ZSTD_rust_overflowCorrectContext*)context;
|
||||
state->matchState->loadedDictEnd = 0;
|
||||
state->matchState->dictMatchState = NULL;
|
||||
}
|
||||
|
||||
static void ZSTD_overflowCorrectIfNeeded(ZSTD_MatchState_t* ms,
|
||||
ZSTD_cwksp* ws,
|
||||
ZSTD_CCtx_params const* params,
|
||||
void const* ip,
|
||||
void const* iend)
|
||||
{
|
||||
U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy);
|
||||
U32 const maxDist = (U32)1 << params->cParams.windowLog;
|
||||
if (ZSTD_window_needOverflowCorrection(ms->window, cycleLog, maxDist, ms->loadedDictEnd, ip, iend)) {
|
||||
U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
|
||||
ZSTD_cwksp_mark_tables_dirty(ws);
|
||||
ZSTD_reduceIndex(ms, params, correction);
|
||||
ZSTD_cwksp_mark_tables_clean(ws);
|
||||
if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
|
||||
else ms->nextToUpdate -= correction;
|
||||
/* invalidate dictionaries on overflow correction */
|
||||
ms->loadedDictEnd = 0;
|
||||
ms->dictMatchState = NULL;
|
||||
}
|
||||
ZSTD_rust_overflowCorrectContext context;
|
||||
ZSTD_rust_overflowCorrectState state;
|
||||
ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
|
||||
context.matchState = ms;
|
||||
context.workspace = ws;
|
||||
context.params = params;
|
||||
state.callbackContext = &context;
|
||||
state.nextToUpdate = &ms->nextToUpdate;
|
||||
state.needCorrection = ZSTD_rust_overflowCorrect_need;
|
||||
state.correctOverflow = ZSTD_rust_overflowCorrect_correct;
|
||||
state.markTablesDirty = ZSTD_rust_overflowCorrect_markTablesDirty;
|
||||
state.reduceIndex = ZSTD_rust_overflowCorrect_reduceIndex;
|
||||
state.markTablesClean = ZSTD_rust_overflowCorrect_markTablesClean;
|
||||
state.invalidateDictionary = ZSTD_rust_overflowCorrect_invalidateDictionary;
|
||||
ZSTD_rust_overflowCorrectIfNeeded(&state, ip, iend);
|
||||
}
|
||||
|
||||
#include "zstd_preSplit.h"
|
||||
|
||||
Reference in New Issue
Block a user