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(
|
size_t ZSTD_rust_ldm_blockCompress(
|
||||||
void* rawSeqStore, void* blockContext, void* seqStore, U32 rep[ZSTD_REP_NUM],
|
void* rawSeqStore, void* blockContext, void* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
const void* src, size_t srcSize, U32 minMatch, int useOptimalParser);
|
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);
|
const U64* ZSTD_ldm_rust_gearTable(void);
|
||||||
void ZSTD_ldm_rust_prepareBlock(void* blockContext, const void* anchor);
|
void ZSTD_ldm_rust_prepareBlock(void* blockContext, const void* anchor);
|
||||||
@@ -206,14 +207,6 @@ typedef struct {
|
|||||||
ZSTD_BlockCompressor_f blockCompressor;
|
ZSTD_BlockCompressor_f blockCompressor;
|
||||||
} ZSTD_rust_ldm_block_context;
|
} 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)
|
static void ZSTD_rust_ldm_fillFastTables(ZSTD_MatchState_t* ms, const BYTE* end)
|
||||||
{
|
{
|
||||||
switch (ms->cParams.strategy) {
|
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)
|
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_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);
|
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)
|
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]
|
#[inline]
|
||||||
unsafe fn ldm_bucket(hash_table: *mut LdmEntry, hash: u32, bucket_size_log: u32) -> *mut LdmEntry {
|
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) }
|
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 {
|
mod tests {
|
||||||
use super::*;
|
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]
|
#[test]
|
||||||
fn parameter_defaults_follow_the_c_rules() {
|
fn parameter_defaults_follow_the_c_rules() {
|
||||||
let mut params = LdmParams {
|
let mut params = LdmParams {
|
||||||
|
|||||||
Reference in New Issue
Block a user