feat(decompress): move platform BMI2 init to Rust
The decoder context remains allocated and laid out by C because optional members change with the active build configuration. Previously, the C adapter also owned the platform leaf: its DYNAMIC_BMI2 branch queried CPU features and assigned the private bmi2 member directly. That kept the policy in C and made the Rust boundary depend on the context layout. Move the leaf to Rust and give it an opaque scalar address plus the active configuration value. The C adapter now only extracts the optional address when that member exists and forwards it, while DYNAMIC_BMI2=0 passes NULL. Rust performs the dynamic decision, queries CPU support, and writes the scalar. The existing 68-word DCtx view is unchanged. Focused unit coverage verifies that disabled dynamic dispatch leaves the scalar untouched and enabled dispatch publishes the CPU feature result. Test Plan: - `cc -fsyntax-only -Werror -DDYNAMIC_BMI2=0 -Ilib -Ilib/common -Ilib/compress -Ilib/decompress -Ilib/dict -Ilib/legacy lib/decompress/zstd_decompress.c` -- passed - `cc -fsyntax-only -Werror -DDYNAMIC_BMI2=1 -Ilib -Ilib/common -Ilib/compress -Ilib/decompress -Ilib/dict -Ilib/legacy lib/decompress/zstd_decompress.c` -- passed - `rustfmt --edition 2021 --check rust/src/zstd_decompress.rs` -- passed - `git diff --check -- lib/decompress/zstd_decompress.c rust/src/zstd_decompress.rs` -- passed
This commit is contained in:
@@ -133,7 +133,8 @@ void ZSTD_rust_dctx_view(ZSTD_DCtx* dctx, ZSTD_rustDctxView* out);
|
|||||||
void ZSTD_rust_dctx_trace_view(ZSTD_DCtx* dctx,
|
void ZSTD_rust_dctx_trace_view(ZSTD_DCtx* dctx,
|
||||||
ZSTD_rustDctxTraceView* out);
|
ZSTD_rustDctxTraceView* out);
|
||||||
size_t ZSTD_rust_dctx_sizeof(void);
|
size_t ZSTD_rust_dctx_sizeof(void);
|
||||||
void ZSTD_rust_dctx_init_platform(ZSTD_DCtx* dctx);
|
void ZSTD_dctx_init_platform(ZSTD_DCtx* dctx);
|
||||||
|
void ZSTD_rust_dctx_init_platform(void* bmi2, int dynamic_bmi2);
|
||||||
size_t ZSTD_rust_dctx_default_max_window_size(void);
|
size_t ZSTD_rust_dctx_default_max_window_size(void);
|
||||||
int ZSTD_rust_no_forward_progress_max(void);
|
int ZSTD_rust_no_forward_progress_max(void);
|
||||||
int ZSTD_rust_heapmode(void);
|
int ZSTD_rust_heapmode(void);
|
||||||
@@ -245,12 +246,13 @@ size_t ZSTD_rust_dctx_sizeof(void)
|
|||||||
return sizeof(ZSTD_DCtx);
|
return sizeof(ZSTD_DCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZSTD_rust_dctx_init_platform(ZSTD_DCtx* dctx)
|
void ZSTD_dctx_init_platform(ZSTD_DCtx* dctx)
|
||||||
{
|
{
|
||||||
#if DYNAMIC_BMI2
|
#if DYNAMIC_BMI2
|
||||||
dctx->bmi2 = ZSTD_cpuSupportsBmi2();
|
ZSTD_rust_dctx_init_platform(&dctx->bmi2, DYNAMIC_BMI2);
|
||||||
#else
|
#else
|
||||||
(void)dctx;
|
(void)dctx;
|
||||||
|
ZSTD_rust_dctx_init_platform(NULL, DYNAMIC_BMI2);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ unsafe extern "C" {
|
|||||||
fn ZSTD_rust_dctx_view(dctx: *mut ZSTD_DCtx, out: *mut ZSTD_rustDctxView);
|
fn ZSTD_rust_dctx_view(dctx: *mut ZSTD_DCtx, out: *mut ZSTD_rustDctxView);
|
||||||
fn ZSTD_rust_dctx_trace_view(dctx: *mut ZSTD_DCtx, out: *mut ZSTD_rustDctxTraceView);
|
fn ZSTD_rust_dctx_trace_view(dctx: *mut ZSTD_DCtx, out: *mut ZSTD_rustDctxTraceView);
|
||||||
fn ZSTD_rust_dctx_sizeof() -> usize;
|
fn ZSTD_rust_dctx_sizeof() -> usize;
|
||||||
fn ZSTD_rust_dctx_init_platform(dctx: *mut ZSTD_DCtx);
|
fn ZSTD_dctx_init_platform(dctx: *mut ZSTD_DCtx);
|
||||||
fn ZSTD_rust_dctx_default_max_window_size() -> usize;
|
fn ZSTD_rust_dctx_default_max_window_size() -> usize;
|
||||||
fn ZSTD_rust_no_forward_progress_max() -> c_int;
|
fn ZSTD_rust_no_forward_progress_max() -> c_int;
|
||||||
fn ZSTD_rust_heapmode() -> c_int;
|
fn ZSTD_rust_heapmode() -> c_int;
|
||||||
@@ -378,6 +378,37 @@ unsafe extern "C" {
|
|||||||
fn ZSTD_checkContinuity(dctx: *mut ZSTD_DCtx, dst: *const c_void, dst_size: usize);
|
fn ZSTD_checkContinuity(dctx: *mut ZSTD_DCtx, dst: *const c_void, dst_size: usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn ZSTD_rust_dctx_init_platform(bmi2: *mut c_void, dynamic_bmi2: c_int) {
|
||||||
|
if dynamic_bmi2 != 0 && !bmi2.is_null() {
|
||||||
|
unsafe {
|
||||||
|
bmi2.cast::<c_int>()
|
||||||
|
.write(c_int::from(crate::cpu::ZSTD_cpuSupportsBmi2()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod dctx_platform_tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn initializes_bmi2_only_when_dynamic_support_is_enabled() {
|
||||||
|
let mut bmi2 = c_int::MAX;
|
||||||
|
unsafe {
|
||||||
|
ZSTD_rust_dctx_init_platform((&mut bmi2 as *mut c_int).cast(), 0);
|
||||||
|
}
|
||||||
|
assert_eq!(bmi2, c_int::MAX);
|
||||||
|
|
||||||
|
let expected = c_int::from(crate::cpu::ZSTD_cpuSupportsBmi2());
|
||||||
|
bmi2 = c_int::MAX;
|
||||||
|
unsafe {
|
||||||
|
ZSTD_rust_dctx_init_platform((&mut bmi2 as *mut c_int).cast(), 1);
|
||||||
|
}
|
||||||
|
assert_eq!(bmi2, expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type ZstdDecompressDCtxFn =
|
type ZstdDecompressDCtxFn =
|
||||||
unsafe extern "C" fn(*mut ZSTD_DCtx, *mut c_void, usize, *const c_void, usize) -> usize;
|
unsafe extern "C" fn(*mut ZSTD_DCtx, *mut c_void, usize, *const c_void, usize) -> usize;
|
||||||
|
|
||||||
@@ -2576,7 +2607,7 @@ unsafe fn init_dctx_internal(view: &ZSTD_rustDctxView) {
|
|||||||
if !view.fuzz_end.is_null() {
|
if !view.fuzz_end.is_null() {
|
||||||
set_pointer(view.fuzz_end, ptr::null());
|
set_pointer(view.fuzz_end, ptr::null());
|
||||||
}
|
}
|
||||||
ZSTD_rust_dctx_init_platform(view.dctx.cast());
|
ZSTD_dctx_init_platform(view.dctx.cast());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user