feat(ldm): move limit-table scalar leaf to Rust
Keep the LDM limit-table update on the Rust compression path while leaving match-state ownership in C. Previously, the C block wrapper combined pointer subtraction, match-state access, and the bounded scalar update. The wrapper now computes `curr` from `anchor - window.base`, passes `curr` and `nextToUpdate` through the narrow U32 ABI, and stores Rust's result before the existing fast-table dispatch. The Rust leaf uses explicit wrapping arithmetic to preserve the C U32 behavior: the strict `curr > nextToUpdate + 1024` threshold and the `MIN(512, ...)` clamp. Focused tests cover the threshold, one-step update, clamp, nonzero starting point, and arithmetic wraparound. Test Plan: - `cargo test zstd_ldm` -- default-feature test-binary link failed because existing dict-builder C symbols are not linked. - `cargo test --no-default-features --features compression zstd_ldm` -- passed (7 tests). - `make lib-nomt` -- passed. - `make lib-mt` -- passed. - `make -C tests test-zstream` -- passed; it emitted the existing `tests/zstreamtest.c` unterminated-string warning. - `cargo clippy`, `cargo clippy --benches`, `cargo clippy --tests`, `cargo +nightly fmt`, then the same clippy sequence -- passed.
This commit is contained in:
@@ -185,6 +185,7 @@ void ZSTD_rust_ldm_skipRawSeqStoreBytes(void* rawSeqStore, size_t nbBytes);
|
||||
size_t ZSTD_rust_ldm_blockCompress(
|
||||
void* rawSeqStore, void* blockContext, void* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
const void* src, size_t srcSize, U32 minMatch, int useOptimalParser);
|
||||
U32 ZSTD_rust_ldm_limitTableUpdate(U32 curr, U32 nextToUpdate);
|
||||
|
||||
const U64* ZSTD_ldm_rust_gearTable(void);
|
||||
void ZSTD_ldm_rust_prepareBlock(void* blockContext, const void* anchor);
|
||||
@@ -206,14 +207,6 @@ typedef struct {
|
||||
ZSTD_BlockCompressor_f blockCompressor;
|
||||
} ZSTD_rust_ldm_block_context;
|
||||
|
||||
static void ZSTD_rust_ldm_limitTableUpdate(ZSTD_MatchState_t* ms, const BYTE* anchor)
|
||||
{
|
||||
U32 const curr = (U32)(anchor - ms->window.base);
|
||||
if (curr > ms->nextToUpdate + 1024) {
|
||||
ms->nextToUpdate = curr - MIN(512, curr - ms->nextToUpdate - 1024);
|
||||
}
|
||||
}
|
||||
|
||||
static void ZSTD_rust_ldm_fillFastTables(ZSTD_MatchState_t* ms, const BYTE* end)
|
||||
{
|
||||
switch (ms->cParams.strategy) {
|
||||
@@ -243,7 +236,9 @@ static void ZSTD_rust_ldm_fillFastTables(ZSTD_MatchState_t* ms, const BYTE* end)
|
||||
void ZSTD_ldm_rust_prepareBlock(void* blockContext, const void* anchor)
|
||||
{
|
||||
ZSTD_rust_ldm_block_context* const context = (ZSTD_rust_ldm_block_context*)blockContext;
|
||||
ZSTD_rust_ldm_limitTableUpdate(context->ms, (const BYTE*)anchor);
|
||||
U32 const curr = (U32)((const BYTE*)anchor - context->ms->window.base);
|
||||
context->ms->nextToUpdate = ZSTD_rust_ldm_limitTableUpdate(
|
||||
curr, context->ms->nextToUpdate);
|
||||
ZSTD_rust_ldm_fillFastTables(context->ms, (const BYTE*)anchor);
|
||||
}
|
||||
|
||||
|
||||
@@ -187,6 +187,16 @@ fn bounded(lower: u32, value: u32, upper: u32) -> u32 {
|
||||
value.max(lower).min(upper)
|
||||
}
|
||||
|
||||
/// Return the next match-table update point using the C scalar rule.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ZSTD_rust_ldm_limitTableUpdate(curr: u32, next_to_update: u32) -> u32 {
|
||||
if curr > next_to_update.wrapping_add(1024) {
|
||||
curr.wrapping_sub(512u32.min(curr.wrapping_sub(next_to_update).wrapping_sub(1024)))
|
||||
} else {
|
||||
next_to_update
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn ldm_bucket(hash_table: *mut LdmEntry, hash: u32, bucket_size_log: u32) -> *mut LdmEntry {
|
||||
unsafe { hash_table.add((hash as usize) << bucket_size_log) }
|
||||
@@ -1007,6 +1017,31 @@ pub unsafe extern "C" fn ZSTD_rust_ldm_blockCompress(
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn limit_table_update_keeps_threshold_strict() {
|
||||
assert_eq!(ZSTD_rust_ldm_limitTableUpdate(1024, 0), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn limit_table_update_moves_one_step_past_threshold() {
|
||||
assert_eq!(ZSTD_rust_ldm_limitTableUpdate(1025, 0), 1024);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn limit_table_update_clamps_to_512() {
|
||||
assert_eq!(ZSTD_rust_ldm_limitTableUpdate(2048, 0), 1536);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn limit_table_update_preserves_nonzero_next_to_update() {
|
||||
assert_eq!(ZSTD_rust_ldm_limitTableUpdate(2000, 500), 1524);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn limit_table_update_wraps_u32_arithmetic() {
|
||||
assert_eq!(ZSTD_rust_ldm_limitTableUpdate(1000, u32::MAX - 511), 512);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parameter_defaults_follow_the_c_rules() {
|
||||
let mut params = LdmParams {
|
||||
|
||||
Reference in New Issue
Block a user