feat(compress): move CDict table copy leaf to Rust
ZSTD_copyCDictTableIntoCCtx only transformed tagged CDict match-table entries or copied untagged entries; context-owned table selection remains in C. Keep that policy and both call sites in C, forwarding the selected flag through a narrow ABI. Rust removes the frozen eight-bit short-cache tag or uses copy_nonoverlapping for C memcpy-equivalent copying without adding validation. Test Plan: - Focused and full compression Rust tests passed (2 and 267 tests). - `make -B -C lib -j2 lib` passed. - `make -C tests -j2 fuzzer` passed. - `./tests/fuzzer -s4560 -t47 -i48 -v` passed. - Clippy normal/benches/tests before and after `cargo +nightly fmt` passed. - `git diff --check` and `git diff --cached --check` passed.
This commit is contained in:
@@ -66,6 +66,8 @@ int ZSTD_rust_simpleCompress2Level(const void* cctx);
|
|||||||
int ZSTD_rust_simpleCompressStream2Level(const void* cctx);
|
int ZSTD_rust_simpleCompressStream2Level(const void* cctx);
|
||||||
void ZSTD_rust_reduceTable(U32* table, U32 size, U32 reducerValue,
|
void ZSTD_rust_reduceTable(U32* table, U32 size, U32 reducerValue,
|
||||||
int preserveMark);
|
int preserveMark);
|
||||||
|
void ZSTD_rust_copyCDictTableIntoCCtx(U32* dst, U32 const* src,
|
||||||
|
size_t tableSize, int tagged);
|
||||||
U64 ZSTD_rust_advanceHashSalt(U64 hashSalt, U64 hashSaltEntropy);
|
U64 ZSTD_rust_advanceHashSalt(U64 hashSalt, U64 hashSaltEntropy);
|
||||||
int ZSTD_rust_indexTooCloseToMax(size_t nextSrcBaseOffset);
|
int ZSTD_rust_indexTooCloseToMax(size_t nextSrcBaseOffset);
|
||||||
int ZSTD_rust_dictTooBig(size_t loadedDictSize);
|
int ZSTD_rust_dictTooBig(size_t loadedDictSize);
|
||||||
@@ -1877,18 +1879,9 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx,
|
|||||||
|
|
||||||
static void ZSTD_copyCDictTableIntoCCtx(U32* dst, U32 const* src, size_t tableSize,
|
static void ZSTD_copyCDictTableIntoCCtx(U32* dst, U32 const* src, size_t tableSize,
|
||||||
ZSTD_compressionParameters const* cParams) {
|
ZSTD_compressionParameters const* cParams) {
|
||||||
if (ZSTD_CDictIndicesAreTagged(cParams)){
|
ZSTD_STATIC_ASSERT(ZSTD_SHORT_CACHE_TAG_BITS == 8);
|
||||||
/* Remove tags from the CDict table if they are present.
|
ZSTD_rust_copyCDictTableIntoCCtx(dst, src, tableSize,
|
||||||
* See docs on "short cache" in zstd_compress_internal.h for context. */
|
ZSTD_CDictIndicesAreTagged(cParams));
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < tableSize; i++) {
|
|
||||||
U32 const taggedIndex = src[i];
|
|
||||||
U32 const index = taggedIndex >> ZSTD_SHORT_CACHE_TAG_BITS;
|
|
||||||
dst[i] = index;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ZSTD_memcpy(dst, src, tableSize * sizeof(U32));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
|
static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ const ZSTD_ROWSIZE: usize = 16;
|
|||||||
const ZSTD_WINDOW_START_INDEX: u32 = 2;
|
const ZSTD_WINDOW_START_INDEX: u32 = 2;
|
||||||
const ZSTD_DUBT_UNSORTED_MARK: u32 = 1;
|
const ZSTD_DUBT_UNSORTED_MARK: u32 = 1;
|
||||||
const ZSTD_INDEXOVERFLOW_MARGIN: usize = 16usize << 20;
|
const ZSTD_INDEXOVERFLOW_MARGIN: usize = 16usize << 20;
|
||||||
|
const ZSTD_SHORT_CACHE_TAG_BITS: u32 = 8;
|
||||||
const ZSTD_CURRENT_MAX: usize = if size_of::<usize>() == 8 {
|
const ZSTD_CURRENT_MAX: usize = if size_of::<usize>() == 8 {
|
||||||
3500usize << 20
|
3500usize << 20
|
||||||
} else {
|
} else {
|
||||||
@@ -345,6 +346,25 @@ pub unsafe extern "C" fn ZSTD_rust_reduceTable(
|
|||||||
reduce_table_internal(table, reducer_value, preserve_mark != 0);
|
reduce_table_internal(table, reducer_value, preserve_mark != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Copies a CDict match table into a CCtx, removing short-cache tags when the
|
||||||
|
/// C-owned compression parameters say the source table is tagged.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn ZSTD_rust_copyCDictTableIntoCCtx(
|
||||||
|
dst: *mut u32,
|
||||||
|
src: *const u32,
|
||||||
|
table_size: usize,
|
||||||
|
tagged: c_int,
|
||||||
|
) {
|
||||||
|
if tagged != 0 {
|
||||||
|
for i in 0..table_size {
|
||||||
|
let index = unsafe { *src.add(i) } >> ZSTD_SHORT_CACHE_TAG_BITS;
|
||||||
|
unsafe { *dst.add(i) = index };
|
||||||
|
}
|
||||||
|
} else if table_size != 0 {
|
||||||
|
unsafe { ptr::copy_nonoverlapping(src, dst, table_size) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn zeroed_state() -> ZSTD_compressedBlockState_t {
|
fn zeroed_state() -> ZSTD_compressedBlockState_t {
|
||||||
/* The state contains only integer arrays and enum fields. */
|
/* The state contains only integer arrays and enum fields. */
|
||||||
@@ -856,6 +876,40 @@ mod tests {
|
|||||||
assert_eq!(table[ZSTD_ROWSIZE * 2 - 1], u32::MAX - 4);
|
assert_eq!(table[ZSTD_ROWSIZE * 2 - 1], u32::MAX - 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn copy_cdict_table_removes_short_cache_tags() {
|
||||||
|
let source = [0x1234_56ff, 0xdead_beef, 0x0000_0100, u32::MAX];
|
||||||
|
let mut destination = [0u32; 4];
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ZSTD_rust_copyCDictTableIntoCCtx(
|
||||||
|
destination.as_mut_ptr(),
|
||||||
|
source.as_ptr(),
|
||||||
|
source.len(),
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(destination, [0x0012_3456, 0x00de_adbe, 1, 0x00ff_ffff]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn copy_cdict_table_preserves_untagged_entries() {
|
||||||
|
let source = [0, 2, 0x1234_5678, u32::MAX];
|
||||||
|
let mut destination = [0xa5a5_a5a5; 4];
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ZSTD_rust_copyCDictTableIntoCCtx(
|
||||||
|
destination.as_mut_ptr(),
|
||||||
|
source.as_ptr(),
|
||||||
|
source.len(),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(destination, source);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bitmix_and_hash_salt_match_the_c_arithmetic() {
|
fn bitmix_and_hash_salt_match_the_c_arithmetic() {
|
||||||
assert_eq!(bitmix(0x0123_4567_89ab_cdef, 8), 0xd498_d855_4e8d_d8cb);
|
assert_eq!(bitmix(0x0123_4567_89ab_cdef, 8), 0xd498_d855_4e8d_d8cb);
|
||||||
|
|||||||
Reference in New Issue
Block a user