zstd-ruby 1.4.5.0 → 1.4.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
}
|