feat(compress): call reset storage policy directly from Rust
The CCtx reset tail already delegated storage reservation and ordering policy to Rust, but crossed back into C through a redundant callback trampoline. Project the storage state directly through the existing pointer-sized ABI slot and invoke the Rust storage operation without the extra C hop. Keep private workspace/layout callbacks and match-state reset in C, preserve hash -> match -> storage ordering, and retain allocation-error propagation in Rust tests. Test Plan: - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo check --manifest-path rust/Cargo.toml --tests - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings - ulimit -v 41943040; make -j1 - ulimit -v 41943040; make -j1 -C tests test
This commit is contained in:
@@ -2304,7 +2304,7 @@ typedef struct {
|
||||
ZSTD_rust_resetCCtxStorageCallback_f resetHash;
|
||||
void* compressedBlockState;
|
||||
ZSTD_rust_resetCCtxTailCallback_f resetMatchState;
|
||||
ZSTD_rust_resetCCtxTailCallback_f resetStorage;
|
||||
const ZSTD_rust_resetCCtxStorageState* storageState;
|
||||
ZSTD_compressionParameters* matchStateCParams;
|
||||
int* matchStatePrefetchCDictTables;
|
||||
unsigned long long* pledgedSrcSizePlusOne;
|
||||
@@ -2327,7 +2327,7 @@ typedef char ZSTD_rust_reset_cctx_tail_state_layout[
|
||||
== 2 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_resetCCtxTailState, resetMatchState)
|
||||
== 3 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_resetCCtxTailState, resetStorage)
|
||||
&& offsetof(ZSTD_rust_resetCCtxTailState, storageState)
|
||||
== 4 * sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_resetCCtxTailState, matchStateCParams)
|
||||
== 5 * sizeof(void*)
|
||||
@@ -5389,13 +5389,6 @@ static size_t ZSTD_rust_resetCCtxTail_resetMatchState(void* opaque)
|
||||
ZSTD_resetTarget_CCtx);
|
||||
}
|
||||
|
||||
static size_t ZSTD_rust_resetCCtxTail_resetStorage(void* opaque)
|
||||
{
|
||||
ZSTD_rust_resetCCtxTailContext* const context =
|
||||
(ZSTD_rust_resetCCtxTailContext*)opaque;
|
||||
return ZSTD_rust_resetCCtxStorage(context->storageState);
|
||||
}
|
||||
|
||||
/*! ZSTD_resetCCtx_internal() :
|
||||
* @param loadedDictSize The size of the dictionary to be loaded
|
||||
* into the context, if any. If no dictionary is used, or the
|
||||
@@ -5534,7 +5527,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
tailState.resetHash = ZSTD_rust_resetCCtxTail_resetHash;
|
||||
tailState.compressedBlockState = NULL;
|
||||
tailState.resetMatchState = ZSTD_rust_resetCCtxTail_resetMatchState;
|
||||
tailState.resetStorage = ZSTD_rust_resetCCtxTail_resetStorage;
|
||||
tailState.storageState = &storageState;
|
||||
tailState.matchStateCParams = &zc->blockState.matchState.cParams;
|
||||
tailState.matchStatePrefetchCDictTables =
|
||||
&zc->blockState.matchState.prefetchCDictTables;
|
||||
|
||||
+108
-14
@@ -9930,15 +9930,15 @@ const _: () = {
|
||||
/// C-owned operations used by the post-workspace CCtx reset tail.
|
||||
///
|
||||
/// Rust owns the operation order, compressed-block reset, and error
|
||||
/// propagation. C retains the private context initialization, match-state
|
||||
/// reset, and storage publication operations.
|
||||
/// propagation. C retains the private context initialization and match-state
|
||||
/// reset; the storage policy is called directly through its projected state.
|
||||
#[repr(C)]
|
||||
pub struct ZSTD_rust_resetCCtxTailState {
|
||||
callbackContext: *mut c_void,
|
||||
resetHash: Option<ResetCCtxStorageCallback>,
|
||||
compressedBlockState: *mut ZSTD_compressedBlockState_t,
|
||||
resetMatchState: Option<ResetCCtxTailCallback>,
|
||||
resetStorage: Option<ResetCCtxTailCallback>,
|
||||
storageState: *const ZSTD_rust_resetCCtxStorageState,
|
||||
matchStateCParams: *mut ZSTD_compressionParameters,
|
||||
matchStatePrefetchCDictTables: *mut c_int,
|
||||
pledgedSrcSizePlusOne: *mut u64,
|
||||
@@ -9962,7 +9962,7 @@ const _: () = {
|
||||
offset_of!(ZSTD_rust_resetCCtxTailState, compressedBlockState) == 2 * size_of::<usize>()
|
||||
);
|
||||
assert!(offset_of!(ZSTD_rust_resetCCtxTailState, resetMatchState) == 3 * size_of::<usize>());
|
||||
assert!(offset_of!(ZSTD_rust_resetCCtxTailState, resetStorage) == 4 * size_of::<usize>());
|
||||
assert!(offset_of!(ZSTD_rust_resetCCtxTailState, storageState) == 4 * size_of::<usize>());
|
||||
assert!(
|
||||
offset_of!(ZSTD_rust_resetCCtxTailState, matchStateCParams) == 5 * size_of::<usize>()
|
||||
);
|
||||
@@ -10462,9 +10462,9 @@ pub unsafe extern "C" fn ZSTD_rust_resetCCtxTail(
|
||||
let Some(reset_match_state) = state.resetMatchState else {
|
||||
return ERROR(ZstdErrorCode::Generic);
|
||||
};
|
||||
let Some(reset_storage) = state.resetStorage else {
|
||||
if state.storageState.is_null() {
|
||||
return ERROR(ZstdErrorCode::Generic);
|
||||
};
|
||||
}
|
||||
if state.compressedBlockState.is_null() {
|
||||
return ERROR(ZstdErrorCode::Generic);
|
||||
}
|
||||
@@ -10502,7 +10502,7 @@ pub unsafe extern "C" fn ZSTD_rust_resetCCtxTail(
|
||||
if ERR_isError(result) {
|
||||
return result;
|
||||
}
|
||||
let result = reset_storage(state.callbackContext);
|
||||
let result = ZSTD_rust_resetCCtxStorage(state.storageState);
|
||||
if ERR_isError(result) {
|
||||
return result;
|
||||
}
|
||||
@@ -23436,6 +23436,8 @@ mod tests {
|
||||
#[derive(Default)]
|
||||
struct ResetCCtxTailTestContext {
|
||||
events: Vec<&'static str>,
|
||||
storage_allocations: Vec<Box<[u8]>>,
|
||||
storage_error_armed: bool,
|
||||
match_result: usize,
|
||||
storage_result: usize,
|
||||
c_params: ZSTD_compressionParameters,
|
||||
@@ -23471,22 +23473,110 @@ mod tests {
|
||||
context.match_result
|
||||
}
|
||||
|
||||
unsafe extern "C" fn reset_cctx_tail_test_reset_storage(context: *mut c_void) -> usize {
|
||||
unsafe extern "C" fn reset_cctx_tail_storage_set_pointer(
|
||||
_context: *mut c_void,
|
||||
_pointer_kind: c_int,
|
||||
_pointer: *mut c_void,
|
||||
) {
|
||||
}
|
||||
|
||||
unsafe extern "C" fn reset_cctx_tail_storage_set_size(
|
||||
_context: *mut c_void,
|
||||
_size_kind: c_int,
|
||||
_value: usize,
|
||||
) {
|
||||
}
|
||||
|
||||
unsafe extern "C" fn reset_cctx_tail_storage_set_int(
|
||||
_context: *mut c_void,
|
||||
_int_kind: c_int,
|
||||
_value: c_int,
|
||||
) {
|
||||
}
|
||||
|
||||
unsafe extern "C" fn reset_cctx_tail_storage_reserve(
|
||||
context: *mut c_void,
|
||||
_reserve_kind: c_int,
|
||||
size: usize,
|
||||
) -> *mut c_void {
|
||||
let context = unsafe { reset_cctx_tail_test_context(context) };
|
||||
let allocation = vec![0u8; size.max(1)].into_boxed_slice();
|
||||
let pointer = allocation.as_ptr() as *mut c_void;
|
||||
context.storage_allocations.push(allocation);
|
||||
pointer
|
||||
}
|
||||
|
||||
unsafe extern "C" fn reset_cctx_tail_storage_reserve_failed(
|
||||
context: *mut c_void,
|
||||
) -> c_int {
|
||||
let context = unsafe { reset_cctx_tail_test_context(context) };
|
||||
c_int::from(context.storage_error_armed)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn reset_cctx_tail_storage_zero(
|
||||
_context: *mut c_void,
|
||||
pointer: *mut c_void,
|
||||
size: usize,
|
||||
) {
|
||||
if !pointer.is_null() {
|
||||
unsafe { ptr::write_bytes(pointer.cast::<u8>(), 0, size) };
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn reset_cctx_tail_storage_window_init(_context: *mut c_void) {}
|
||||
|
||||
unsafe extern "C" fn reset_cctx_tail_storage_reset_external_sequences(
|
||||
context: *mut c_void,
|
||||
) {
|
||||
let context = unsafe { reset_cctx_tail_test_context(context) };
|
||||
context.events.push("reset-storage");
|
||||
context.storage_result
|
||||
context.storage_error_armed = context.storage_result != 0;
|
||||
}
|
||||
|
||||
fn reset_cctx_tail_test_storage_state(
|
||||
context: &mut ResetCCtxTailTestContext,
|
||||
) -> ZSTD_rust_resetCCtxStorageState {
|
||||
ZSTD_rust_resetCCtxStorageState {
|
||||
callbackContext: (context as *mut ResetCCtxTailTestContext).cast(),
|
||||
ldmEnable: ZSTD_RUST_PS_DISABLE,
|
||||
hasExtSeqProd: 0,
|
||||
hashLog: 0,
|
||||
bucketSizeLog: 0,
|
||||
blockSize: 1,
|
||||
maxNbSeq: 1,
|
||||
maxNbLdmSeq: 0,
|
||||
maxNbExternalSeq: 0,
|
||||
buffInSize: 0,
|
||||
buffOutSize: 0,
|
||||
seqDefSize: 1,
|
||||
ldmEntrySize: 1,
|
||||
rawSeqSize: 1,
|
||||
externalSequenceSize: 1,
|
||||
byteSize: 1,
|
||||
wildcopyOverlength: 0,
|
||||
bufferedPolicy: 0,
|
||||
setPointer: Some(reset_cctx_tail_storage_set_pointer),
|
||||
setSize: Some(reset_cctx_tail_storage_set_size),
|
||||
setInt: Some(reset_cctx_tail_storage_set_int),
|
||||
reserve: Some(reset_cctx_tail_storage_reserve),
|
||||
reserveFailed: Some(reset_cctx_tail_storage_reserve_failed),
|
||||
zero: Some(reset_cctx_tail_storage_zero),
|
||||
windowInit: Some(reset_cctx_tail_storage_window_init),
|
||||
resetExternalSequences: Some(reset_cctx_tail_storage_reset_external_sequences),
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_cctx_tail_test_state(
|
||||
context: &mut ResetCCtxTailTestContext,
|
||||
compressed_block_state: *mut ZSTD_compressedBlockState_t,
|
||||
storage_state: &mut ZSTD_rust_resetCCtxStorageState,
|
||||
) -> ZSTD_rust_resetCCtxTailState {
|
||||
ZSTD_rust_resetCCtxTailState {
|
||||
callbackContext: (context as *mut ResetCCtxTailTestContext).cast(),
|
||||
resetHash: Some(reset_cctx_tail_test_reset_hash),
|
||||
compressedBlockState: compressed_block_state,
|
||||
resetMatchState: Some(reset_cctx_tail_test_reset_match_state),
|
||||
resetStorage: Some(reset_cctx_tail_test_reset_storage),
|
||||
storageState: storage_state,
|
||||
matchStateCParams: ptr::addr_of_mut!(context.match_state_cparams),
|
||||
matchStatePrefetchCDictTables: ptr::addr_of_mut!(
|
||||
context.match_state_prefetch_cdict_tables
|
||||
@@ -23511,7 +23601,8 @@ mod tests {
|
||||
let mut context = ResetCCtxTailTestContext::default();
|
||||
let mut block_state =
|
||||
unsafe { MaybeUninit::<ZSTD_compressedBlockState_t>::zeroed().assume_init() };
|
||||
let state = reset_cctx_tail_test_state(&mut context, &mut block_state);
|
||||
let mut storage_state = reset_cctx_tail_test_storage_state(&mut context);
|
||||
let state = reset_cctx_tail_test_state(&mut context, &mut block_state, &mut storage_state);
|
||||
|
||||
assert_eq!(unsafe { ZSTD_rust_resetCCtxTail(&state) }, 0);
|
||||
assert_eq!(
|
||||
@@ -23551,7 +23642,8 @@ mod tests {
|
||||
};
|
||||
let mut block_state =
|
||||
unsafe { MaybeUninit::<ZSTD_compressedBlockState_t>::zeroed().assume_init() };
|
||||
let state = reset_cctx_tail_test_state(&mut context, &mut block_state);
|
||||
let mut storage_state = reset_cctx_tail_test_storage_state(&mut context);
|
||||
let state = reset_cctx_tail_test_state(&mut context, &mut block_state, &mut storage_state);
|
||||
|
||||
assert_eq!(unsafe { ZSTD_rust_resetCCtxTail(&state) }, 0);
|
||||
assert_eq!(context.match_state_cparams, c_params);
|
||||
@@ -23574,7 +23666,8 @@ mod tests {
|
||||
};
|
||||
let mut block_state =
|
||||
unsafe { MaybeUninit::<ZSTD_compressedBlockState_t>::zeroed().assume_init() };
|
||||
let state = reset_cctx_tail_test_state(&mut context, &mut block_state);
|
||||
let mut storage_state = reset_cctx_tail_test_storage_state(&mut context);
|
||||
let state = reset_cctx_tail_test_state(&mut context, &mut block_state, &mut storage_state);
|
||||
|
||||
assert_eq!(
|
||||
unsafe { ZSTD_rust_resetCCtxTail(&state) },
|
||||
@@ -23591,7 +23684,8 @@ mod tests {
|
||||
};
|
||||
let mut block_state =
|
||||
unsafe { MaybeUninit::<ZSTD_compressedBlockState_t>::zeroed().assume_init() };
|
||||
let state = reset_cctx_tail_test_state(&mut context, &mut block_state);
|
||||
let mut storage_state = reset_cctx_tail_test_storage_state(&mut context);
|
||||
let state = reset_cctx_tail_test_state(&mut context, &mut block_state, &mut storage_state);
|
||||
|
||||
assert_eq!(
|
||||
unsafe { ZSTD_rust_resetCCtxTail(&state) },
|
||||
|
||||
Reference in New Issue
Block a user