Move the binary-tree optimal and ultra block parsers into Rust with a narrow C projection of match-state, sequence-store, and entropy-table fields. Keep the established C entry points as wrappers, and avoid reading uninitialized entropy costs during dictionary tree updates. Test Plan: - cargo test --manifest-path rust/Cargo.toml - cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings - cargo +nightly fmt --manifest-path rust/Cargo.toml --all -- --check - make -B -C tests test-zstream V=1 - git diff --check Refs: rust/src/zstd_opt.rs, lib/compress/zstd_opt.c
244 lines
8.7 KiB
C
244 lines
8.7 KiB
C
/*
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under both the BSD-style license (found in the
|
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
|
* in the COPYING file in the root directory of this source tree).
|
|
* You may select, at your option, one or both of these licenses.
|
|
*/
|
|
|
|
/* The optimal parser is implemented in rust/src/zstd_opt.rs. Keep the
|
|
* private ZSTD_MatchState_t and entropy-table layouts on the C side: this
|
|
* translation unit only projects the leaves Rust needs and preserves the
|
|
* established C entry points. */
|
|
#include "zstd_compress_internal.h"
|
|
#include "zstd_opt.h"
|
|
|
|
#if !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \
|
|
|| !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \
|
|
|| !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR)
|
|
|
|
typedef struct {
|
|
U32* hashTable;
|
|
U32* chainTable;
|
|
const BYTE* base;
|
|
const BYTE* dictBase;
|
|
U32 dictLimit;
|
|
U32 lowLimit;
|
|
U32 loadedDictEnd;
|
|
U32* nextToUpdate;
|
|
U32 hashLog;
|
|
U32 chainLog;
|
|
U32 searchLog;
|
|
U32 windowLog;
|
|
int useCPredict;
|
|
U32* hashTable3;
|
|
U32 hashLog3;
|
|
const BYTE* nextSrc;
|
|
U32 minMatch;
|
|
U32 targetLength;
|
|
optState_t* opt;
|
|
const void* dictMatchState;
|
|
const RawSeqStore_t* ldmSeqStore;
|
|
const BYTE** windowBase;
|
|
U32* windowDictLimit;
|
|
U32* windowLowLimit;
|
|
const size_t* hufCTable;
|
|
int hufRepeatValid;
|
|
const U32* fseLitLengthCTable;
|
|
const U32* fseMatchLengthCTable;
|
|
const U32* fseOffCodeCTable;
|
|
} ZSTD_RustOptState;
|
|
|
|
typedef char ZSTD_rust_opt_seqdef_layout[(sizeof(SeqDef) == 8) ? 1 : -1];
|
|
typedef char ZSTD_rust_opt_match_layout[(sizeof(ZSTD_match_t) == 8) ? 1 : -1];
|
|
typedef char ZSTD_rust_opt_rawseq_layout[(sizeof(rawSeq) == 12) ? 1 : -1];
|
|
typedef char ZSTD_rust_opt_seqstore_layout[
|
|
(offsetof(SeqStore_t, longLengthPos) == 9 * sizeof(size_t) + 4) ? 1 : -1];
|
|
typedef char ZSTD_rust_optimal_layout[
|
|
(sizeof(ZSTD_optimal_t) == 4 * sizeof(U32) + sizeof(U32) * ZSTD_REP_NUM) ? 1 : -1];
|
|
typedef char ZSTD_rust_opt_rep_count[(ZSTD_REP_NUM == 3) ? 1 : -1];
|
|
|
|
static void ZSTD_rustOptState_init(
|
|
ZSTD_RustOptState* const out,
|
|
ZSTD_MatchState_t* const ms,
|
|
const ZSTD_RustOptState* const dms)
|
|
{
|
|
out->hashTable = ms->hashTable;
|
|
out->chainTable = ms->chainTable;
|
|
out->base = ms->window.base;
|
|
out->dictBase = ms->window.dictBase;
|
|
out->dictLimit = ms->window.dictLimit;
|
|
out->lowLimit = ms->window.lowLimit;
|
|
out->loadedDictEnd = ms->loadedDictEnd;
|
|
out->nextToUpdate = &ms->nextToUpdate;
|
|
out->hashLog = ms->cParams.hashLog;
|
|
out->chainLog = ms->cParams.chainLog;
|
|
out->searchLog = ms->cParams.searchLog;
|
|
#ifdef ZSTD_C_PREDICT
|
|
out->useCPredict = 1;
|
|
#else
|
|
out->useCPredict = 0;
|
|
#endif
|
|
out->windowLog = ms->cParams.windowLog;
|
|
out->hashTable3 = ms->hashTable3;
|
|
out->hashLog3 = ms->hashLog3;
|
|
out->nextSrc = ms->window.nextSrc;
|
|
out->minMatch = ms->cParams.minMatch;
|
|
out->targetLength = ms->cParams.targetLength;
|
|
out->opt = &ms->opt;
|
|
out->dictMatchState = dms;
|
|
out->ldmSeqStore = ms->ldmSeqStore;
|
|
out->windowBase = &ms->window.base;
|
|
out->windowDictLimit = &ms->window.dictLimit;
|
|
out->windowLowLimit = &ms->window.lowLimit;
|
|
out->hufCTable = NULL;
|
|
out->hufRepeatValid = 0;
|
|
out->fseLitLengthCTable = NULL;
|
|
out->fseMatchLengthCTable = NULL;
|
|
out->fseOffCodeCTable = NULL;
|
|
}
|
|
|
|
static void ZSTD_rustOptState_projectCosts(
|
|
ZSTD_RustOptState* const out,
|
|
ZSTD_MatchState_t* const ms)
|
|
{
|
|
const ZSTD_entropyCTables_t* const costs = ms->opt.symbolCosts;
|
|
out->hufCTable = costs ? costs->huf.CTable : NULL;
|
|
out->hufRepeatValid = costs && costs->huf.repeatMode == HUF_repeat_valid;
|
|
out->fseLitLengthCTable = costs ? costs->fse.litlengthCTable : NULL;
|
|
out->fseMatchLengthCTable = costs ? costs->fse.matchlengthCTable : NULL;
|
|
out->fseOffCodeCTable = costs ? costs->fse.offcodeCTable : NULL;
|
|
}
|
|
|
|
static void ZSTD_rustOptState_init_with_dict(
|
|
ZSTD_RustOptState* const out,
|
|
ZSTD_MatchState_t* const ms)
|
|
{
|
|
ZSTD_rustOptState_init(out, ms, NULL);
|
|
}
|
|
|
|
static void ZSTD_rustOptState_init_with_costs(
|
|
ZSTD_RustOptState* const out,
|
|
ZSTD_MatchState_t* const ms,
|
|
const ZSTD_RustOptState* const dms)
|
|
{
|
|
ZSTD_rustOptState_init(out, ms, dms);
|
|
ZSTD_rustOptState_projectCosts(out, ms);
|
|
}
|
|
|
|
void ZSTD_rust_opt_updateTree(
|
|
ZSTD_RustOptState* state,
|
|
const void* ip, const void* iend,
|
|
U32 mls, int dictMode);
|
|
|
|
size_t ZSTD_rust_compressBlock_opt(
|
|
ZSTD_RustOptState* state, void* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
const void* src, size_t srcSize, int optLevel, int dictMode);
|
|
|
|
void ZSTD_rust_initStats_ultra(
|
|
ZSTD_RustOptState* state, void* seqStore, const U32 rep[ZSTD_REP_NUM],
|
|
const void* src, size_t srcSize);
|
|
|
|
size_t ZSTD_rust_compressBlock_btultra2(
|
|
ZSTD_RustOptState* state, void* seqStore, U32 rep[ZSTD_REP_NUM],
|
|
const void* src, size_t srcSize);
|
|
|
|
enum {
|
|
ZSTD_rust_dict_noDict = 0,
|
|
ZSTD_rust_dict_extDict = 1,
|
|
ZSTD_rust_dict_dictMatchState = 2,
|
|
};
|
|
|
|
void ZSTD_updateTree(ZSTD_MatchState_t* const ms, const BYTE* const ip,
|
|
const BYTE* const iend)
|
|
{
|
|
ZSTD_RustOptState state;
|
|
ZSTD_rustOptState_init_with_dict(&state, ms);
|
|
ZSTD_rust_opt_updateTree(&state, ip, iend, ms->cParams.minMatch,
|
|
ZSTD_rust_dict_noDict);
|
|
}
|
|
|
|
#ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR
|
|
size_t ZSTD_compressBlock_btopt(
|
|
ZSTD_MatchState_t* const ms, SeqStore_t* const seqStore,
|
|
U32 rep[ZSTD_REP_NUM], const void* const src, size_t const srcSize)
|
|
{
|
|
ZSTD_RustOptState state;
|
|
ZSTD_rustOptState_init_with_costs(&state, ms, NULL);
|
|
return ZSTD_rust_compressBlock_opt(&state, seqStore, rep, src, srcSize,
|
|
0, ZSTD_rust_dict_noDict);
|
|
}
|
|
|
|
size_t ZSTD_compressBlock_btopt_dictMatchState(
|
|
ZSTD_MatchState_t* const ms, SeqStore_t* const seqStore,
|
|
U32 rep[ZSTD_REP_NUM], const void* const src, size_t const srcSize)
|
|
{
|
|
ZSTD_RustOptState state;
|
|
ZSTD_RustOptState dictState;
|
|
ZSTD_MatchState_t dictCopy = *ms->dictMatchState;
|
|
ZSTD_rustOptState_init(&dictState, &dictCopy, NULL);
|
|
ZSTD_rustOptState_init_with_costs(&state, ms, &dictState);
|
|
return ZSTD_rust_compressBlock_opt(&state, seqStore, rep, src, srcSize,
|
|
0, ZSTD_rust_dict_dictMatchState);
|
|
}
|
|
|
|
size_t ZSTD_compressBlock_btopt_extDict(
|
|
ZSTD_MatchState_t* const ms, SeqStore_t* const seqStore,
|
|
U32 rep[ZSTD_REP_NUM], const void* const src, size_t const srcSize)
|
|
{
|
|
ZSTD_RustOptState state;
|
|
ZSTD_rustOptState_init_with_costs(&state, ms, NULL);
|
|
return ZSTD_rust_compressBlock_opt(&state, seqStore, rep, src, srcSize,
|
|
0, ZSTD_rust_dict_extDict);
|
|
}
|
|
#endif
|
|
|
|
#ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR
|
|
size_t ZSTD_compressBlock_btultra(
|
|
ZSTD_MatchState_t* const ms, SeqStore_t* const seqStore,
|
|
U32 rep[ZSTD_REP_NUM], const void* const src, size_t const srcSize)
|
|
{
|
|
ZSTD_RustOptState state;
|
|
ZSTD_rustOptState_init_with_costs(&state, ms, NULL);
|
|
return ZSTD_rust_compressBlock_opt(&state, seqStore, rep, src, srcSize,
|
|
2, ZSTD_rust_dict_noDict);
|
|
}
|
|
|
|
size_t ZSTD_compressBlock_btultra_dictMatchState(
|
|
ZSTD_MatchState_t* const ms, SeqStore_t* const seqStore,
|
|
U32 rep[ZSTD_REP_NUM], const void* const src, size_t const srcSize)
|
|
{
|
|
ZSTD_RustOptState state;
|
|
ZSTD_RustOptState dictState;
|
|
ZSTD_MatchState_t dictCopy = *ms->dictMatchState;
|
|
ZSTD_rustOptState_init(&dictState, &dictCopy, NULL);
|
|
ZSTD_rustOptState_init_with_costs(&state, ms, &dictState);
|
|
return ZSTD_rust_compressBlock_opt(&state, seqStore, rep, src, srcSize,
|
|
2, ZSTD_rust_dict_dictMatchState);
|
|
}
|
|
|
|
size_t ZSTD_compressBlock_btultra_extDict(
|
|
ZSTD_MatchState_t* const ms, SeqStore_t* const seqStore,
|
|
U32 rep[ZSTD_REP_NUM], const void* const src, size_t const srcSize)
|
|
{
|
|
ZSTD_RustOptState state;
|
|
ZSTD_rustOptState_init_with_costs(&state, ms, NULL);
|
|
return ZSTD_rust_compressBlock_opt(&state, seqStore, rep, src, srcSize,
|
|
2, ZSTD_rust_dict_extDict);
|
|
}
|
|
|
|
size_t ZSTD_compressBlock_btultra2(
|
|
ZSTD_MatchState_t* const ms, SeqStore_t* const seqStore,
|
|
U32 rep[ZSTD_REP_NUM], const void* const src, size_t const srcSize)
|
|
{
|
|
ZSTD_RustOptState state;
|
|
ZSTD_rustOptState_init_with_costs(&state, ms, NULL);
|
|
return ZSTD_rust_compressBlock_btultra2(&state, seqStore, rep, src,
|
|
srcSize);
|
|
}
|
|
#endif
|
|
|
|
#endif /* any optimal parser entry point is enabled */
|