zstd-ruby 1.4.5.0 → 1.4.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +35 -0
- data/README.md +2 -2
- data/ext/zstdruby/libzstd/Makefile +237 -138
- data/ext/zstdruby/libzstd/README.md +28 -0
- data/ext/zstdruby/libzstd/common/bitstream.h +25 -16
- data/ext/zstdruby/libzstd/common/compiler.h +118 -4
- data/ext/zstdruby/libzstd/common/cpu.h +1 -3
- data/ext/zstdruby/libzstd/common/debug.c +1 -1
- data/ext/zstdruby/libzstd/common/debug.h +12 -19
- data/ext/zstdruby/libzstd/common/entropy_common.c +189 -43
- data/ext/zstdruby/libzstd/common/error_private.c +2 -1
- data/ext/zstdruby/libzstd/common/error_private.h +2 -2
- data/ext/zstdruby/libzstd/common/fse.h +40 -12
- data/ext/zstdruby/libzstd/common/fse_decompress.c +124 -17
- data/ext/zstdruby/libzstd/common/huf.h +27 -6
- data/ext/zstdruby/libzstd/common/mem.h +67 -94
- data/ext/zstdruby/libzstd/common/pool.c +23 -17
- data/ext/zstdruby/libzstd/common/pool.h +2 -2
- data/ext/zstdruby/libzstd/common/threading.c +6 -5
- data/ext/zstdruby/libzstd/common/xxhash.c +19 -57
- data/ext/zstdruby/libzstd/common/xxhash.h +2 -2
- data/ext/zstdruby/libzstd/common/zstd_common.c +10 -10
- data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
- data/ext/zstdruby/libzstd/common/zstd_errors.h +2 -1
- data/ext/zstdruby/libzstd/common/zstd_internal.h +90 -59
- data/ext/zstdruby/libzstd/common/zstd_trace.c +42 -0
- data/ext/zstdruby/libzstd/common/zstd_trace.h +152 -0
- data/ext/zstdruby/libzstd/compress/fse_compress.c +31 -24
- data/ext/zstdruby/libzstd/compress/hist.c +27 -29
- data/ext/zstdruby/libzstd/compress/hist.h +2 -2
- data/ext/zstdruby/libzstd/compress/huf_compress.c +217 -101
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +1495 -478
- data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +143 -44
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +7 -7
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +18 -4
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +25 -21
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +62 -26
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +23 -23
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +21 -21
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +352 -78
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +21 -1
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +276 -209
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +8 -2
- data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +103 -0
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +191 -46
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +79 -410
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +27 -109
- data/ext/zstdruby/libzstd/decompress/huf_decompress.c +303 -201
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +9 -9
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +2 -2
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +370 -87
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +153 -45
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +6 -3
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +28 -11
- data/ext/zstdruby/libzstd/deprecated/zbuff.h +1 -1
- data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +1 -1
- data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
- data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +40 -31
- data/ext/zstdruby/libzstd/dictBuilder/cover.h +2 -2
- data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +1 -1
- data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +26 -25
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +22 -24
- data/ext/zstdruby/libzstd/dictBuilder/zdict.h +5 -4
- data/ext/zstdruby/libzstd/dll/example/Makefile +1 -1
- data/ext/zstdruby/libzstd/dll/example/README.md +16 -22
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +6 -2
- data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +6 -2
- data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +6 -2
- data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +7 -3
- data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +10 -6
- data/ext/zstdruby/libzstd/legacy/zstd_v05.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +10 -6
- data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +10 -6
- data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -1
- data/ext/zstdruby/libzstd/libzstd.pc.in +3 -3
- data/ext/zstdruby/libzstd/zstd.h +414 -54
- data/lib/zstd-ruby/version.rb +1 -1
- metadata +7 -3
- data/.travis.yml +0 -14
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (c) 2016-
|
2
|
+
* Copyright (c) 2016-2021, Yann Collet, Facebook, Inc.
|
3
3
|
* All rights reserved.
|
4
4
|
*
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
@@ -50,6 +50,19 @@ static unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) {
|
|
50
50
|
return maxSymbolValue;
|
51
51
|
}
|
52
52
|
|
53
|
+
/**
|
54
|
+
* Returns true if we should use ncount=-1 else we should
|
55
|
+
* use ncount=1 for low probability symbols instead.
|
56
|
+
*/
|
57
|
+
static unsigned ZSTD_useLowProbCount(size_t const nbSeq)
|
58
|
+
{
|
59
|
+
/* Heuristic: This should cover most blocks <= 16K and
|
60
|
+
* start to fade out after 16K to about 32K depending on
|
61
|
+
* comprssibility.
|
62
|
+
*/
|
63
|
+
return nbSeq >= 2048;
|
64
|
+
}
|
65
|
+
|
53
66
|
/**
|
54
67
|
* Returns the cost in bytes of encoding the normalized count header.
|
55
68
|
* Returns an error if any of the helper functions return an error.
|
@@ -60,7 +73,7 @@ static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,
|
|
60
73
|
BYTE wksp[FSE_NCOUNTBOUND];
|
61
74
|
S16 norm[MaxSeq + 1];
|
62
75
|
const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
|
63
|
-
FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max), "");
|
76
|
+
FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max, ZSTD_useLowProbCount(nbSeq)), "");
|
64
77
|
return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);
|
65
78
|
}
|
66
79
|
|
@@ -239,7 +252,7 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity,
|
|
239
252
|
*op = codeTable[0];
|
240
253
|
return 1;
|
241
254
|
case set_repeat:
|
242
|
-
|
255
|
+
ZSTD_memcpy(nextCTable, prevCTable, prevCTableSize);
|
243
256
|
return 0;
|
244
257
|
case set_basic:
|
245
258
|
FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, entropyWorkspace, entropyWorkspaceSize), ""); /* note : could be pre-calculated */
|
@@ -253,7 +266,8 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity,
|
|
253
266
|
nbSeq_1--;
|
254
267
|
}
|
255
268
|
assert(nbSeq_1 > 1);
|
256
|
-
|
269
|
+
assert(entropyWorkspaceSize >= FSE_BUILD_CTABLE_WORKSPACE_SIZE(MaxSeq, MaxFSELog));
|
270
|
+
FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max, ZSTD_useLowProbCount(nbSeq_1)), "");
|
257
271
|
{ size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
|
258
272
|
FORWARD_IF_ERROR(NCountSize, "FSE_writeNCount failed");
|
259
273
|
FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, entropyWorkspace, entropyWorkspaceSize), "");
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (c) 2016-
|
2
|
+
* Copyright (c) 2016-2021, Yann Collet, Facebook, Inc.
|
3
3
|
* All rights reserved.
|
4
4
|
*
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
@@ -29,7 +29,7 @@
|
|
29
29
|
* This metadata is populated in ZSTD_buildSuperBlockEntropy_literal() */
|
30
30
|
typedef struct {
|
31
31
|
symbolEncodingType_e hType;
|
32
|
-
BYTE hufDesBuffer[
|
32
|
+
BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE];
|
33
33
|
size_t hufDesSize;
|
34
34
|
} ZSTD_hufCTablesMetadata_t;
|
35
35
|
|
@@ -42,7 +42,7 @@ typedef struct {
|
|
42
42
|
symbolEncodingType_e llType;
|
43
43
|
symbolEncodingType_e ofType;
|
44
44
|
symbolEncodingType_e mlType;
|
45
|
-
BYTE fseTablesBuffer[
|
45
|
+
BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE];
|
46
46
|
size_t fseTablesSize;
|
47
47
|
size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_compressSubBlock_sequences() */
|
48
48
|
} ZSTD_fseCTablesMetadata_t;
|
@@ -79,7 +79,7 @@ static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSiz
|
|
79
79
|
DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_literal (srcSize=%zu)", srcSize);
|
80
80
|
|
81
81
|
/* Prepare nextEntropy assuming reusing the existing table */
|
82
|
-
|
82
|
+
ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
83
83
|
|
84
84
|
if (disableLiteralsCompression) {
|
85
85
|
DEBUGLOG(5, "set_basic - disabled");
|
@@ -118,7 +118,7 @@ static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSiz
|
|
118
118
|
}
|
119
119
|
|
120
120
|
/* Build Huffman Tree */
|
121
|
-
|
121
|
+
ZSTD_memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable));
|
122
122
|
huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
|
123
123
|
{ size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp,
|
124
124
|
maxSymbolValue, huffLog,
|
@@ -137,14 +137,14 @@ static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSiz
|
|
137
137
|
(HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue);
|
138
138
|
if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) {
|
139
139
|
DEBUGLOG(5, "set_repeat - smaller");
|
140
|
-
|
140
|
+
ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
141
141
|
hufMetadata->hType = set_repeat;
|
142
142
|
return 0;
|
143
143
|
}
|
144
144
|
}
|
145
145
|
if (newCSize + hSize >= srcSize) {
|
146
146
|
DEBUGLOG(5, "set_basic - no gains");
|
147
|
-
|
147
|
+
ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
148
148
|
hufMetadata->hType = set_basic;
|
149
149
|
return 0;
|
150
150
|
}
|
@@ -188,7 +188,7 @@ static size_t ZSTD_buildSuperBlockEntropy_sequences(seqStore_t* seqStorePtr,
|
|
188
188
|
|
189
189
|
assert(cTableWkspSize >= (1 << MaxFSELog) * sizeof(FSE_FUNCTION_TYPE));
|
190
190
|
DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_sequences (nbSeq=%zu)", nbSeq);
|
191
|
-
|
191
|
+
ZSTD_memset(workspace, 0, wkspSize);
|
192
192
|
|
193
193
|
fseMetadata->lastCountSize = 0;
|
194
194
|
/* convert length/distances into codes */
|
@@ -304,7 +304,7 @@ ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr,
|
|
304
304
|
* before we know the table size + compressed size, so we have a bound on the
|
305
305
|
* table size. If we guessed incorrectly, we fall back to uncompressed literals.
|
306
306
|
*
|
307
|
-
* We write the header when writeEntropy=1 and set
|
307
|
+
* We write the header when writeEntropy=1 and set entropyWritten=1 when we succeeded
|
308
308
|
* in writing the header, otherwise it is set to 0.
|
309
309
|
*
|
310
310
|
* hufMetadata->hType has literals block type info.
|
@@ -348,7 +348,7 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
|
|
348
348
|
assert(hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat);
|
349
349
|
|
350
350
|
if (writeEntropy && hufMetadata->hType == set_compressed) {
|
351
|
-
|
351
|
+
ZSTD_memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize);
|
352
352
|
op += hufMetadata->hufDesSize;
|
353
353
|
cLitSize += hufMetadata->hufDesSize;
|
354
354
|
DEBUGLOG(5, "ZSTD_compressSubBlock_literal (hSize=%zu)", hufMetadata->hufDesSize);
|
@@ -474,7 +474,7 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables
|
|
474
474
|
const U32 MLtype = fseMetadata->mlType;
|
475
475
|
DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (fseTablesSize=%zu)", fseMetadata->fseTablesSize);
|
476
476
|
*seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
|
477
|
-
|
477
|
+
ZSTD_memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize);
|
478
478
|
op += fseMetadata->fseTablesSize;
|
479
479
|
} else {
|
480
480
|
const U32 repeat = set_repeat;
|
@@ -603,7 +603,7 @@ static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type,
|
|
603
603
|
const BYTE* codeTable, unsigned maxCode,
|
604
604
|
size_t nbSeq, const FSE_CTable* fseCTable,
|
605
605
|
const U32* additionalBits,
|
606
|
-
short const* defaultNorm, U32 defaultNormLog,
|
606
|
+
short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
|
607
607
|
void* workspace, size_t wkspSize)
|
608
608
|
{
|
609
609
|
unsigned* const countWksp = (unsigned*)workspace;
|
@@ -615,7 +615,11 @@ static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type,
|
|
615
615
|
|
616
616
|
HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize); /* can't fail */
|
617
617
|
if (type == set_basic) {
|
618
|
-
|
618
|
+
/* We selected this encoding type, so it must be valid. */
|
619
|
+
assert(max <= defaultMax);
|
620
|
+
cSymbolTypeSizeEstimateInBits = max <= defaultMax
|
621
|
+
? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max)
|
622
|
+
: ERROR(GENERIC);
|
619
623
|
} else if (type == set_rle) {
|
620
624
|
cSymbolTypeSizeEstimateInBits = 0;
|
621
625
|
} else if (type == set_compressed || type == set_repeat) {
|
@@ -643,15 +647,15 @@ static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable,
|
|
643
647
|
size_t cSeqSizeEstimate = 0;
|
644
648
|
cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff,
|
645
649
|
nbSeq, fseTables->offcodeCTable, NULL,
|
646
|
-
OF_defaultNorm, OF_defaultNormLog,
|
650
|
+
OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
|
647
651
|
workspace, wkspSize);
|
648
652
|
cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->llType, llCodeTable, MaxLL,
|
649
653
|
nbSeq, fseTables->litlengthCTable, LL_bits,
|
650
|
-
LL_defaultNorm, LL_defaultNormLog,
|
654
|
+
LL_defaultNorm, LL_defaultNormLog, MaxLL,
|
651
655
|
workspace, wkspSize);
|
652
656
|
cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, MaxML,
|
653
657
|
nbSeq, fseTables->matchlengthCTable, ML_bits,
|
654
|
-
ML_defaultNorm, ML_defaultNormLog,
|
658
|
+
ML_defaultNorm, ML_defaultNormLog, MaxML,
|
655
659
|
workspace, wkspSize);
|
656
660
|
if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize;
|
657
661
|
return cSeqSizeEstimate + sequencesSectionHeaderSize;
|
@@ -790,7 +794,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
|
|
790
794
|
} while (!lastSequence);
|
791
795
|
if (writeLitEntropy) {
|
792
796
|
DEBUGLOG(5, "ZSTD_compressSubBlock_multi has literal entropy tables unwritten");
|
793
|
-
|
797
|
+
ZSTD_memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf));
|
794
798
|
}
|
795
799
|
if (writeSeqEntropy && ZSTD_needSequenceEntropyTables(&entropyMetadata->fseMetadata)) {
|
796
800
|
/* If we haven't written our entropy tables, then we've violated our contract and
|
@@ -809,11 +813,11 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
|
|
809
813
|
if (sp < send) {
|
810
814
|
seqDef const* seq;
|
811
815
|
repcodes_t rep;
|
812
|
-
|
816
|
+
ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep));
|
813
817
|
for (seq = sstart; seq < sp; ++seq) {
|
814
818
|
rep = ZSTD_updateRep(rep.rep, seq->offset - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
|
815
819
|
}
|
816
|
-
|
820
|
+
ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep));
|
817
821
|
}
|
818
822
|
}
|
819
823
|
DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed");
|
@@ -831,7 +835,7 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,
|
|
831
835
|
&zc->blockState.nextCBlock->entropy,
|
832
836
|
&zc->appliedParams,
|
833
837
|
&entropyMetadata,
|
834
|
-
zc->entropyWorkspace,
|
838
|
+
zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */), "");
|
835
839
|
|
836
840
|
return ZSTD_compressSubBlock_multi(&zc->seqStore,
|
837
841
|
zc->blockState.prevCBlock,
|
@@ -841,5 +845,5 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,
|
|
841
845
|
dst, dstCapacity,
|
842
846
|
src, srcSize,
|
843
847
|
zc->bmi2, lastBlock,
|
844
|
-
zc->entropyWorkspace,
|
848
|
+
zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */);
|
845
849
|
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (c) 2016-
|
2
|
+
* Copyright (c) 2016-2021, Yann Collet, Facebook, Inc.
|
3
3
|
* All rights reserved.
|
4
4
|
*
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
@@ -44,6 +44,16 @@ typedef enum {
|
|
44
44
|
ZSTD_cwksp_alloc_aligned
|
45
45
|
} ZSTD_cwksp_alloc_phase_e;
|
46
46
|
|
47
|
+
/**
|
48
|
+
* Used to describe whether the workspace is statically allocated (and will not
|
49
|
+
* necessarily ever be freed), or if it's dynamically allocated and we can
|
50
|
+
* expect a well-formed caller to free this.
|
51
|
+
*/
|
52
|
+
typedef enum {
|
53
|
+
ZSTD_cwksp_dynamic_alloc,
|
54
|
+
ZSTD_cwksp_static_alloc
|
55
|
+
} ZSTD_cwksp_static_alloc_e;
|
56
|
+
|
47
57
|
/**
|
48
58
|
* Zstd fits all its internal datastructures into a single continuous buffer,
|
49
59
|
* so that it only needs to perform a single OS allocation (or so that a buffer
|
@@ -92,7 +102,7 @@ typedef enum {
|
|
92
102
|
*
|
93
103
|
* - Static objects: this is optionally the enclosing ZSTD_CCtx or ZSTD_CDict,
|
94
104
|
* so that literally everything fits in a single buffer. Note: if present,
|
95
|
-
* this must be the first object in the workspace, since
|
105
|
+
* this must be the first object in the workspace, since ZSTD_customFree{CCtx,
|
96
106
|
* CDict}() rely on a pointer comparison to see whether one or two frees are
|
97
107
|
* required.
|
98
108
|
*
|
@@ -137,9 +147,10 @@ typedef struct {
|
|
137
147
|
void* tableValidEnd;
|
138
148
|
void* allocStart;
|
139
149
|
|
140
|
-
|
150
|
+
BYTE allocFailed;
|
141
151
|
int workspaceOversizedDuration;
|
142
152
|
ZSTD_cwksp_alloc_phase_e phase;
|
153
|
+
ZSTD_cwksp_static_alloc_e isStatic;
|
143
154
|
} ZSTD_cwksp;
|
144
155
|
|
145
156
|
/*-*************************************
|
@@ -178,7 +189,9 @@ MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) {
|
|
178
189
|
* else is though.
|
179
190
|
*/
|
180
191
|
MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) {
|
181
|
-
|
192
|
+
if (size == 0)
|
193
|
+
return 0;
|
194
|
+
#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
|
182
195
|
return size + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
|
183
196
|
#else
|
184
197
|
return size;
|
@@ -228,7 +241,10 @@ MEM_STATIC void* ZSTD_cwksp_reserve_internal(
|
|
228
241
|
ZSTD_cwksp_internal_advance_phase(ws, phase);
|
229
242
|
alloc = (BYTE *)ws->allocStart - bytes;
|
230
243
|
|
231
|
-
|
244
|
+
if (bytes == 0)
|
245
|
+
return NULL;
|
246
|
+
|
247
|
+
#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
|
232
248
|
/* over-reserve space */
|
233
249
|
alloc = (BYTE *)alloc - 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
|
234
250
|
#endif
|
@@ -247,11 +263,13 @@ MEM_STATIC void* ZSTD_cwksp_reserve_internal(
|
|
247
263
|
}
|
248
264
|
ws->allocStart = alloc;
|
249
265
|
|
250
|
-
#if
|
266
|
+
#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
|
251
267
|
/* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on
|
252
268
|
* either size. */
|
253
269
|
alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
|
254
|
-
|
270
|
+
if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
|
271
|
+
__asan_unpoison_memory_region(alloc, bytes);
|
272
|
+
}
|
255
273
|
#endif
|
256
274
|
|
257
275
|
return alloc;
|
@@ -296,8 +314,10 @@ MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) {
|
|
296
314
|
}
|
297
315
|
ws->tableEnd = end;
|
298
316
|
|
299
|
-
#if
|
300
|
-
|
317
|
+
#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
|
318
|
+
if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
|
319
|
+
__asan_unpoison_memory_region(alloc, bytes);
|
320
|
+
}
|
301
321
|
#endif
|
302
322
|
|
303
323
|
return alloc;
|
@@ -311,7 +331,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
|
|
311
331
|
void* alloc = ws->objectEnd;
|
312
332
|
void* end = (BYTE*)alloc + roundedBytes;
|
313
333
|
|
314
|
-
#if
|
334
|
+
#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
|
315
335
|
/* over-reserve space */
|
316
336
|
end = (BYTE *)end + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
|
317
337
|
#endif
|
@@ -332,11 +352,13 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
|
|
332
352
|
ws->tableEnd = end;
|
333
353
|
ws->tableValidEnd = end;
|
334
354
|
|
335
|
-
#if
|
355
|
+
#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
|
336
356
|
/* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on
|
337
357
|
* either size. */
|
338
358
|
alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
|
339
|
-
|
359
|
+
if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
|
360
|
+
__asan_unpoison_memory_region(alloc, bytes);
|
361
|
+
}
|
340
362
|
#endif
|
341
363
|
|
342
364
|
return alloc;
|
@@ -345,7 +367,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
|
|
345
367
|
MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws) {
|
346
368
|
DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_dirty");
|
347
369
|
|
348
|
-
#if
|
370
|
+
#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
|
349
371
|
/* To validate that the table re-use logic is sound, and that we don't
|
350
372
|
* access table space that we haven't cleaned, we re-"poison" the table
|
351
373
|
* space every time we mark it dirty. */
|
@@ -380,7 +402,7 @@ MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) {
|
|
380
402
|
assert(ws->tableValidEnd >= ws->objectEnd);
|
381
403
|
assert(ws->tableValidEnd <= ws->allocStart);
|
382
404
|
if (ws->tableValidEnd < ws->tableEnd) {
|
383
|
-
|
405
|
+
ZSTD_memset(ws->tableValidEnd, 0, (BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd);
|
384
406
|
}
|
385
407
|
ZSTD_cwksp_mark_tables_clean(ws);
|
386
408
|
}
|
@@ -392,8 +414,12 @@ MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) {
|
|
392
414
|
MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) {
|
393
415
|
DEBUGLOG(4, "cwksp: clearing tables!");
|
394
416
|
|
395
|
-
#if
|
396
|
-
|
417
|
+
#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
|
418
|
+
/* We don't do this when the workspace is statically allocated, because
|
419
|
+
* when that is the case, we have no capability to hook into the end of the
|
420
|
+
* workspace's lifecycle to unpoison the memory.
|
421
|
+
*/
|
422
|
+
if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
|
397
423
|
size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd;
|
398
424
|
__asan_poison_memory_region(ws->objectEnd, size);
|
399
425
|
}
|
@@ -410,7 +436,7 @@ MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) {
|
|
410
436
|
MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {
|
411
437
|
DEBUGLOG(4, "cwksp: clearing!");
|
412
438
|
|
413
|
-
#if
|
439
|
+
#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
|
414
440
|
/* To validate that the context re-use logic is sound, and that we don't
|
415
441
|
* access stuff that this compression hasn't initialized, we re-"poison"
|
416
442
|
* the workspace (or at least the non-static, non-table parts of it)
|
@@ -421,8 +447,12 @@ MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {
|
|
421
447
|
}
|
422
448
|
#endif
|
423
449
|
|
424
|
-
#if
|
425
|
-
|
450
|
+
#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
|
451
|
+
/* We don't do this when the workspace is statically allocated, because
|
452
|
+
* when that is the case, we have no capability to hook into the end of the
|
453
|
+
* workspace's lifecycle to unpoison the memory.
|
454
|
+
*/
|
455
|
+
if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
|
426
456
|
size_t size = (BYTE*)ws->workspaceEnd - (BYTE*)ws->objectEnd;
|
427
457
|
__asan_poison_memory_region(ws->objectEnd, size);
|
428
458
|
}
|
@@ -442,7 +472,7 @@ MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {
|
|
442
472
|
* Any existing values in the workspace are ignored (the previously managed
|
443
473
|
* buffer, if present, must be separately freed).
|
444
474
|
*/
|
445
|
-
MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size) {
|
475
|
+
MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size, ZSTD_cwksp_static_alloc_e isStatic) {
|
446
476
|
DEBUGLOG(4, "cwksp: init'ing workspace with %zd bytes", size);
|
447
477
|
assert(((size_t)start & (sizeof(void*)-1)) == 0); /* ensure correct alignment */
|
448
478
|
ws->workspace = start;
|
@@ -450,39 +480,45 @@ MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size) {
|
|
450
480
|
ws->objectEnd = ws->workspace;
|
451
481
|
ws->tableValidEnd = ws->objectEnd;
|
452
482
|
ws->phase = ZSTD_cwksp_alloc_objects;
|
483
|
+
ws->isStatic = isStatic;
|
453
484
|
ZSTD_cwksp_clear(ws);
|
454
485
|
ws->workspaceOversizedDuration = 0;
|
455
486
|
ZSTD_cwksp_assert_internal_consistency(ws);
|
456
487
|
}
|
457
488
|
|
458
489
|
MEM_STATIC size_t ZSTD_cwksp_create(ZSTD_cwksp* ws, size_t size, ZSTD_customMem customMem) {
|
459
|
-
void* workspace =
|
490
|
+
void* workspace = ZSTD_customMalloc(size, customMem);
|
460
491
|
DEBUGLOG(4, "cwksp: creating new workspace with %zd bytes", size);
|
461
492
|
RETURN_ERROR_IF(workspace == NULL, memory_allocation, "NULL pointer!");
|
462
|
-
ZSTD_cwksp_init(ws, workspace, size);
|
493
|
+
ZSTD_cwksp_init(ws, workspace, size, ZSTD_cwksp_dynamic_alloc);
|
463
494
|
return 0;
|
464
495
|
}
|
465
496
|
|
466
497
|
MEM_STATIC void ZSTD_cwksp_free(ZSTD_cwksp* ws, ZSTD_customMem customMem) {
|
467
498
|
void *ptr = ws->workspace;
|
468
499
|
DEBUGLOG(4, "cwksp: freeing workspace");
|
469
|
-
|
470
|
-
|
500
|
+
ZSTD_memset(ws, 0, sizeof(ZSTD_cwksp));
|
501
|
+
ZSTD_customFree(ptr, customMem);
|
471
502
|
}
|
472
503
|
|
473
504
|
/**
|
474
505
|
* Moves the management of a workspace from one cwksp to another. The src cwksp
|
475
|
-
* is left in an invalid state (src must be re-init()'ed before
|
506
|
+
* is left in an invalid state (src must be re-init()'ed before it's used again).
|
476
507
|
*/
|
477
508
|
MEM_STATIC void ZSTD_cwksp_move(ZSTD_cwksp* dst, ZSTD_cwksp* src) {
|
478
509
|
*dst = *src;
|
479
|
-
|
510
|
+
ZSTD_memset(src, 0, sizeof(ZSTD_cwksp));
|
480
511
|
}
|
481
512
|
|
482
513
|
MEM_STATIC size_t ZSTD_cwksp_sizeof(const ZSTD_cwksp* ws) {
|
483
514
|
return (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->workspace);
|
484
515
|
}
|
485
516
|
|
517
|
+
MEM_STATIC size_t ZSTD_cwksp_used(const ZSTD_cwksp* ws) {
|
518
|
+
return (size_t)((BYTE*)ws->tableEnd - (BYTE*)ws->workspace)
|
519
|
+
+ (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->allocStart);
|
520
|
+
}
|
521
|
+
|
486
522
|
MEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) {
|
487
523
|
return ws->allocFailed;
|
488
524
|
}
|