feat(compress): project continue overflow correction into Rust
Pass the existing overflow-correction projection directly through the compressContinue ABI so Rust owns the correction decision and ordering while C retains only the table/workspace callbacks. Remove the redundant C forwarding adapter and keep the stack projection valid for synchronous dispatch. Test Plan: - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo fmt --all -- --check - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --lib zstd_compress::tests::compress_continue -- --nocapture - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --all-targets -- -D warnings - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test - ulimit -v 41943040; make -j1 - ulimit -v 41943040; make -j1 -C tests test-zstream ZSTREAM_TESTTIME=-T2s - ulimit -v 41943040; make -j1 -C tests test-fuzzer FUZZERTEST=-T3s FUZZER_FLAGS=--no-big-tests
This commit is contained in:
@@ -888,9 +888,6 @@ typedef struct {
|
|||||||
} ZSTD_rust_compressContinueWindowState;
|
} ZSTD_rust_compressContinueWindowState;
|
||||||
typedef char ZSTD_rust_compress_continue_window_state_layout[
|
typedef char ZSTD_rust_compress_continue_window_state_layout[
|
||||||
(sizeof(ZSTD_rust_compressContinueWindowState) == 7 * sizeof(void*)) ? 1 : -1];
|
(sizeof(ZSTD_rust_compressContinueWindowState) == 7 * sizeof(void*)) ? 1 : -1];
|
||||||
typedef void (*ZSTD_rust_compressContinueWindow_f)(void* context,
|
|
||||||
const void* src,
|
|
||||||
size_t srcSize);
|
|
||||||
typedef size_t (*ZSTD_rust_compressContinueBlock_f)(void* context,
|
typedef size_t (*ZSTD_rust_compressContinueBlock_f)(void* context,
|
||||||
void* dst,
|
void* dst,
|
||||||
size_t dstCapacity,
|
size_t dstCapacity,
|
||||||
@@ -901,7 +898,7 @@ typedef struct {
|
|||||||
void* callbackContext;
|
void* callbackContext;
|
||||||
ZSTD_rust_compressContinueWindowState* windowState;
|
ZSTD_rust_compressContinueWindowState* windowState;
|
||||||
ZSTD_rust_compressContinueWindowState* ldmWindowState;
|
ZSTD_rust_compressContinueWindowState* ldmWindowState;
|
||||||
ZSTD_rust_compressContinueWindow_f correctOverflow;
|
const ZSTD_rust_overflowCorrectState* overflowState;
|
||||||
ZSTD_rust_compressContinueBlock_f compressFrameChunk;
|
ZSTD_rust_compressContinueBlock_f compressFrameChunk;
|
||||||
ZSTD_rust_compressContinueBlock_f compressBlock;
|
ZSTD_rust_compressContinueBlock_f compressBlock;
|
||||||
ZSTD_compressionStage_e* stage;
|
ZSTD_compressionStage_e* stage;
|
||||||
@@ -927,7 +924,7 @@ typedef char ZSTD_rust_compress_continue_state_layout[
|
|||||||
(offsetof(ZSTD_rust_compressContinueState, callbackContext) == 0
|
(offsetof(ZSTD_rust_compressContinueState, callbackContext) == 0
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, windowState) == sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, windowState) == sizeof(void*)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, ldmWindowState) == 2 * sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, ldmWindowState) == 2 * sizeof(void*)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, correctOverflow) == 3 * sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, overflowState) == 3 * sizeof(void*)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, compressFrameChunk) == 4 * sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, compressFrameChunk) == 4 * sizeof(void*)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, compressBlock) == 5 * sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, compressBlock) == 5 * sizeof(void*)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, stage) == 6 * sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, stage) == 6 * sizeof(void*)
|
||||||
@@ -5618,17 +5615,6 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ZSTD_rust_compressContinue_correctOverflow(
|
|
||||||
void* context, const void* src, size_t srcSize)
|
|
||||||
{
|
|
||||||
ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context;
|
|
||||||
ZSTD_MatchState_t* const ms = &cctx->blockState.matchState;
|
|
||||||
|
|
||||||
ZSTD_overflowCorrectIfNeeded(
|
|
||||||
ms, &cctx->workspace, &cctx->appliedParams,
|
|
||||||
src, (const BYTE*)src + srcSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t ZSTD_rust_compressContinue_frameChunk(
|
static size_t ZSTD_rust_compressContinue_frameChunk(
|
||||||
void* context, void* dst, size_t dstCapacity,
|
void* context, void* dst, size_t dstCapacity,
|
||||||
const void* src, size_t srcSize, U32 lastFrameChunk)
|
const void* src, size_t srcSize, U32 lastFrameChunk)
|
||||||
@@ -5657,6 +5643,8 @@ static size_t ZSTD_compressContinue_dispatch(
|
|||||||
ZSTD_rust_compressContinueState state;
|
ZSTD_rust_compressContinueState state;
|
||||||
ZSTD_rust_compressContinueWindowState windowState;
|
ZSTD_rust_compressContinueWindowState windowState;
|
||||||
ZSTD_rust_compressContinueWindowState ldmWindowState;
|
ZSTD_rust_compressContinueWindowState ldmWindowState;
|
||||||
|
ZSTD_rust_overflowCorrectContext overflowContext;
|
||||||
|
ZSTD_rust_overflowCorrectState overflowState;
|
||||||
ZSTD_MatchState_t* const ms = &cctx->blockState.matchState;
|
ZSTD_MatchState_t* const ms = &cctx->blockState.matchState;
|
||||||
ZSTD_window_t* const window = &ms->window;
|
ZSTD_window_t* const window = &ms->window;
|
||||||
ZSTD_window_t* const ldmWindow = &cctx->ldmState.window;
|
ZSTD_window_t* const ldmWindow = &cctx->ldmState.window;
|
||||||
@@ -5676,10 +5664,23 @@ static size_t ZSTD_compressContinue_dispatch(
|
|||||||
ldmWindowState.forceNonContiguous = NULL;
|
ldmWindowState.forceNonContiguous = NULL;
|
||||||
ldmWindowState.nextToUpdate = NULL;
|
ldmWindowState.nextToUpdate = NULL;
|
||||||
|
|
||||||
|
overflowContext.matchState = ms;
|
||||||
|
overflowContext.workspace = &cctx->workspace;
|
||||||
|
overflowContext.params = &cctx->appliedParams;
|
||||||
|
overflowState.callbackContext = &overflowContext;
|
||||||
|
overflowState.nextToUpdate = &ms->nextToUpdate;
|
||||||
|
overflowState.needCorrection = ZSTD_rust_overflowCorrect_need;
|
||||||
|
overflowState.correctOverflow = ZSTD_rust_overflowCorrect_correct;
|
||||||
|
overflowState.markTablesDirty = ZSTD_rust_overflowCorrect_markTablesDirty;
|
||||||
|
overflowState.reduceIndex = ZSTD_rust_overflowCorrect_reduceIndex;
|
||||||
|
overflowState.markTablesClean = ZSTD_rust_overflowCorrect_markTablesClean;
|
||||||
|
overflowState.loadedDictEnd = &ms->loadedDictEnd;
|
||||||
|
overflowState.dictMatchState = &ms->dictMatchState;
|
||||||
|
|
||||||
state.callbackContext = cctx;
|
state.callbackContext = cctx;
|
||||||
state.windowState = &windowState;
|
state.windowState = &windowState;
|
||||||
state.ldmWindowState = &ldmWindowState;
|
state.ldmWindowState = &ldmWindowState;
|
||||||
state.correctOverflow = ZSTD_rust_compressContinue_correctOverflow;
|
state.overflowState = &overflowState;
|
||||||
state.compressFrameChunk = ZSTD_rust_compressContinue_frameChunk;
|
state.compressFrameChunk = ZSTD_rust_compressContinue_frameChunk;
|
||||||
state.compressBlock = ZSTD_rust_compressContinue_block;
|
state.compressBlock = ZSTD_rust_compressContinue_block;
|
||||||
state.stage = &cctx->stage;
|
state.stage = &cctx->stage;
|
||||||
|
|||||||
+51
-13
@@ -793,7 +793,6 @@ pub unsafe extern "C" fn ZSTD_rust_compressFrameChunk(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type CompressContinueWindowFn = unsafe extern "C" fn(*mut c_void, *const c_void, usize);
|
|
||||||
type CompressContinueBlockFn =
|
type CompressContinueBlockFn =
|
||||||
unsafe extern "C" fn(*mut c_void, *mut c_void, usize, *const c_void, usize, c_uint) -> usize;
|
unsafe extern "C" fn(*mut c_void, *mut c_void, usize, *const c_void, usize, c_uint) -> usize;
|
||||||
|
|
||||||
@@ -843,14 +842,14 @@ const _: () = {
|
|||||||
/// Rust owns stage transitions, frame-header sequencing, input progression,
|
/// Rust owns stage transitions, frame-header sequencing, input progression,
|
||||||
/// and dispatch between the already-migrated frame-chunk/block bodies. The
|
/// and dispatch between the already-migrated frame-chunk/block bodies. The
|
||||||
/// frame-header parameters are projected as scalars. The opaque callback
|
/// frame-header parameters are projected as scalars. The opaque callback
|
||||||
/// context remains in C for overflow correction and context-sensitive block
|
/// context remains in C for overflow-correction callbacks and context-sensitive
|
||||||
/// operations; window advancement is projected directly into Rust.
|
/// block operations; window advancement is projected directly into Rust.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct ZSTD_rust_compressContinueState {
|
pub struct ZSTD_rust_compressContinueState {
|
||||||
callback_context: *mut c_void,
|
callback_context: *mut c_void,
|
||||||
window_state: *const ZSTD_rust_compressContinueWindowProjection,
|
window_state: *const ZSTD_rust_compressContinueWindowProjection,
|
||||||
ldm_window_state: *const ZSTD_rust_compressContinueWindowProjection,
|
ldm_window_state: *const ZSTD_rust_compressContinueWindowProjection,
|
||||||
correct_overflow: CompressContinueWindowFn,
|
overflow_state: *const ZSTD_rust_overflowCorrectState,
|
||||||
compress_frame_chunk: CompressContinueBlockFn,
|
compress_frame_chunk: CompressContinueBlockFn,
|
||||||
compress_block: CompressContinueBlockFn,
|
compress_block: CompressContinueBlockFn,
|
||||||
stage: *mut c_int,
|
stage: *mut c_int,
|
||||||
@@ -877,9 +876,7 @@ const _: () = {
|
|||||||
assert!(
|
assert!(
|
||||||
offset_of!(ZSTD_rust_compressContinueState, ldm_window_state) == 2 * size_of::<usize>()
|
offset_of!(ZSTD_rust_compressContinueState, ldm_window_state) == 2 * size_of::<usize>()
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(offset_of!(ZSTD_rust_compressContinueState, overflow_state) == 3 * size_of::<usize>());
|
||||||
offset_of!(ZSTD_rust_compressContinueState, correct_overflow) == 3 * size_of::<usize>()
|
|
||||||
);
|
|
||||||
assert!(
|
assert!(
|
||||||
offset_of!(ZSTD_rust_compressContinueState, compress_frame_chunk) == 4 * size_of::<usize>()
|
offset_of!(ZSTD_rust_compressContinueState, compress_frame_chunk) == 4 * size_of::<usize>()
|
||||||
);
|
);
|
||||||
@@ -1076,7 +1073,11 @@ unsafe fn compress_continue_body_with(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if frame == 0 {
|
if frame == 0 {
|
||||||
unsafe { (state.correct_overflow)(state.callback_context, src, src_size) };
|
if state.overflow_state.is_null() {
|
||||||
|
return ERROR(ZstdErrorCode::Generic);
|
||||||
|
}
|
||||||
|
let src_end = src.cast::<u8>().wrapping_add(src_size).cast();
|
||||||
|
unsafe { ZSTD_rust_overflowCorrectIfNeeded(state.overflow_state, src, src_end) };
|
||||||
}
|
}
|
||||||
|
|
||||||
let compressed_size = if frame != 0 {
|
let compressed_size = if frame != 0 {
|
||||||
@@ -11168,8 +11169,11 @@ mod tests {
|
|||||||
ldm_window: ZSTD_rust_windowUpdateState,
|
ldm_window: ZSTD_rust_windowUpdateState,
|
||||||
force_non_contiguous: c_int,
|
force_non_contiguous: c_int,
|
||||||
next_to_update: c_uint,
|
next_to_update: c_uint,
|
||||||
|
loaded_dict_end: c_uint,
|
||||||
|
dict_match_state: *const c_void,
|
||||||
window_projection: ZSTD_rust_compressContinueWindowProjection,
|
window_projection: ZSTD_rust_compressContinueWindowProjection,
|
||||||
ldm_window_projection: ZSTD_rust_compressContinueWindowProjection,
|
ldm_window_projection: ZSTD_rust_compressContinueWindowProjection,
|
||||||
|
overflow_state: Option<ZSTD_rust_overflowCorrectState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn compress_continue_test_context(
|
unsafe fn compress_continue_test_context(
|
||||||
@@ -11178,13 +11182,29 @@ mod tests {
|
|||||||
unsafe { &mut *context.cast::<CompressContinueTestContext>() }
|
unsafe { &mut *context.cast::<CompressContinueTestContext>() }
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn compress_continue_test_overflow(
|
unsafe extern "C" fn compress_continue_test_overflow_need(
|
||||||
context: *mut c_void,
|
context: *mut c_void,
|
||||||
_src: *const c_void,
|
_src: *const c_void,
|
||||||
_src_size: usize,
|
_src_end: *const c_void,
|
||||||
) {
|
) -> c_int {
|
||||||
let context = unsafe { compress_continue_test_context(context) };
|
let context = unsafe { compress_continue_test_context(context) };
|
||||||
context.overflow_calls += 1;
|
context.overflow_calls += 1;
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn compress_continue_test_overflow_correct(
|
||||||
|
_context: *mut c_void,
|
||||||
|
_src: *const c_void,
|
||||||
|
) -> c_uint {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn compress_continue_test_overflow_callback(_context: *mut c_void) {}
|
||||||
|
|
||||||
|
unsafe extern "C" fn compress_continue_test_overflow_reduce(
|
||||||
|
_context: *mut c_void,
|
||||||
|
_correction: c_uint,
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn compress_continue_test_frame(
|
unsafe extern "C" fn compress_continue_test_frame(
|
||||||
@@ -11235,6 +11255,8 @@ mod tests {
|
|||||||
context.ldm_window = context.window;
|
context.ldm_window = context.window;
|
||||||
context.force_non_contiguous = 0;
|
context.force_non_contiguous = 0;
|
||||||
context.next_to_update = ZSTD_WINDOW_START_INDEX;
|
context.next_to_update = ZSTD_WINDOW_START_INDEX;
|
||||||
|
context.loaded_dict_end = 0;
|
||||||
|
context.dict_match_state = ptr::null();
|
||||||
context.window_projection = ZSTD_rust_compressContinueWindowProjection {
|
context.window_projection = ZSTD_rust_compressContinueWindowProjection {
|
||||||
next_src: ptr::addr_of_mut!(context.window.nextSrc),
|
next_src: ptr::addr_of_mut!(context.window.nextSrc),
|
||||||
base: ptr::addr_of_mut!(context.window.base),
|
base: ptr::addr_of_mut!(context.window.base),
|
||||||
@@ -11253,11 +11275,27 @@ mod tests {
|
|||||||
force_non_contiguous: ptr::null_mut(),
|
force_non_contiguous: ptr::null_mut(),
|
||||||
next_to_update: ptr::null_mut(),
|
next_to_update: ptr::null_mut(),
|
||||||
};
|
};
|
||||||
|
let callback_context = (context as *mut CompressContinueTestContext).cast();
|
||||||
|
context.overflow_state = Some(ZSTD_rust_overflowCorrectState {
|
||||||
|
callback_context,
|
||||||
|
next_to_update: ptr::addr_of_mut!(context.next_to_update),
|
||||||
|
need_correction: Some(compress_continue_test_overflow_need),
|
||||||
|
correct_overflow: Some(compress_continue_test_overflow_correct),
|
||||||
|
mark_tables_dirty: Some(compress_continue_test_overflow_callback),
|
||||||
|
reduce_index: Some(compress_continue_test_overflow_reduce),
|
||||||
|
mark_tables_clean: Some(compress_continue_test_overflow_callback),
|
||||||
|
loaded_dict_end: ptr::addr_of_mut!(context.loaded_dict_end),
|
||||||
|
dict_match_state: ptr::addr_of_mut!(context.dict_match_state),
|
||||||
|
});
|
||||||
|
let overflow_state = context
|
||||||
|
.overflow_state
|
||||||
|
.as_ref()
|
||||||
|
.map_or(ptr::null(), |state| state as *const _);
|
||||||
ZSTD_rust_compressContinueState {
|
ZSTD_rust_compressContinueState {
|
||||||
callback_context: (context as *mut CompressContinueTestContext).cast(),
|
callback_context,
|
||||||
window_state: &context.window_projection,
|
window_state: &context.window_projection,
|
||||||
ldm_window_state: &context.ldm_window_projection,
|
ldm_window_state: &context.ldm_window_projection,
|
||||||
correct_overflow: compress_continue_test_overflow,
|
overflow_state,
|
||||||
compress_frame_chunk: compress_continue_test_frame,
|
compress_frame_chunk: compress_continue_test_frame,
|
||||||
compress_block: compress_continue_test_block,
|
compress_block: compress_continue_test_block,
|
||||||
stage,
|
stage,
|
||||||
|
|||||||
Reference in New Issue
Block a user