extzstd 0.3.2 → 0.4

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.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -3
  3. data/contrib/zstd/CHANGELOG +225 -1
  4. data/contrib/zstd/CONTRIBUTING.md +158 -75
  5. data/contrib/zstd/LICENSE +4 -4
  6. data/contrib/zstd/Makefile +106 -69
  7. data/contrib/zstd/Package.swift +36 -0
  8. data/contrib/zstd/README.md +64 -36
  9. data/contrib/zstd/SECURITY.md +15 -0
  10. data/contrib/zstd/TESTING.md +2 -3
  11. data/contrib/zstd/lib/BUCK +5 -7
  12. data/contrib/zstd/lib/Makefile +117 -199
  13. data/contrib/zstd/lib/README.md +37 -7
  14. data/contrib/zstd/lib/common/allocations.h +55 -0
  15. data/contrib/zstd/lib/common/bits.h +200 -0
  16. data/contrib/zstd/lib/common/bitstream.h +80 -86
  17. data/contrib/zstd/lib/common/compiler.h +225 -63
  18. data/contrib/zstd/lib/common/cpu.h +37 -1
  19. data/contrib/zstd/lib/common/debug.c +7 -1
  20. data/contrib/zstd/lib/common/debug.h +21 -12
  21. data/contrib/zstd/lib/common/entropy_common.c +15 -37
  22. data/contrib/zstd/lib/common/error_private.c +9 -2
  23. data/contrib/zstd/lib/common/error_private.h +93 -5
  24. data/contrib/zstd/lib/common/fse.h +12 -87
  25. data/contrib/zstd/lib/common/fse_decompress.c +37 -117
  26. data/contrib/zstd/lib/common/huf.h +97 -172
  27. data/contrib/zstd/lib/common/mem.h +58 -58
  28. data/contrib/zstd/lib/common/pool.c +38 -17
  29. data/contrib/zstd/lib/common/pool.h +10 -4
  30. data/contrib/zstd/lib/common/portability_macros.h +158 -0
  31. data/contrib/zstd/lib/common/threading.c +74 -14
  32. data/contrib/zstd/lib/common/threading.h +5 -10
  33. data/contrib/zstd/lib/common/xxhash.c +6 -814
  34. data/contrib/zstd/lib/common/xxhash.h +6930 -195
  35. data/contrib/zstd/lib/common/zstd_common.c +1 -36
  36. data/contrib/zstd/lib/common/zstd_deps.h +1 -1
  37. data/contrib/zstd/lib/common/zstd_internal.h +68 -154
  38. data/contrib/zstd/lib/common/zstd_trace.h +163 -0
  39. data/contrib/zstd/lib/compress/clevels.h +134 -0
  40. data/contrib/zstd/lib/compress/fse_compress.c +75 -155
  41. data/contrib/zstd/lib/compress/hist.c +1 -1
  42. data/contrib/zstd/lib/compress/hist.h +1 -1
  43. data/contrib/zstd/lib/compress/huf_compress.c +810 -259
  44. data/contrib/zstd/lib/compress/zstd_compress.c +2864 -919
  45. data/contrib/zstd/lib/compress/zstd_compress_internal.h +523 -192
  46. data/contrib/zstd/lib/compress/zstd_compress_literals.c +117 -40
  47. data/contrib/zstd/lib/compress/zstd_compress_literals.h +16 -6
  48. data/contrib/zstd/lib/compress/zstd_compress_sequences.c +28 -19
  49. data/contrib/zstd/lib/compress/zstd_compress_sequences.h +1 -1
  50. data/contrib/zstd/lib/compress/zstd_compress_superblock.c +251 -412
  51. data/contrib/zstd/lib/compress/zstd_compress_superblock.h +1 -1
  52. data/contrib/zstd/lib/compress/zstd_cwksp.h +284 -97
  53. data/contrib/zstd/lib/compress/zstd_double_fast.c +382 -133
  54. data/contrib/zstd/lib/compress/zstd_double_fast.h +14 -2
  55. data/contrib/zstd/lib/compress/zstd_fast.c +732 -260
  56. data/contrib/zstd/lib/compress/zstd_fast.h +3 -2
  57. data/contrib/zstd/lib/compress/zstd_lazy.c +1177 -390
  58. data/contrib/zstd/lib/compress/zstd_lazy.h +129 -14
  59. data/contrib/zstd/lib/compress/zstd_ldm.c +280 -210
  60. data/contrib/zstd/lib/compress/zstd_ldm.h +3 -2
  61. data/contrib/zstd/lib/compress/zstd_ldm_geartab.h +106 -0
  62. data/contrib/zstd/lib/compress/zstd_opt.c +516 -285
  63. data/contrib/zstd/lib/compress/zstd_opt.h +32 -8
  64. data/contrib/zstd/lib/compress/zstdmt_compress.c +202 -131
  65. data/contrib/zstd/lib/compress/zstdmt_compress.h +9 -6
  66. data/contrib/zstd/lib/decompress/huf_decompress.c +1149 -555
  67. data/contrib/zstd/lib/decompress/huf_decompress_amd64.S +595 -0
  68. data/contrib/zstd/lib/decompress/zstd_ddict.c +4 -4
  69. data/contrib/zstd/lib/decompress/zstd_ddict.h +1 -1
  70. data/contrib/zstd/lib/decompress/zstd_decompress.c +583 -106
  71. data/contrib/zstd/lib/decompress/zstd_decompress_block.c +1054 -379
  72. data/contrib/zstd/lib/decompress/zstd_decompress_block.h +14 -3
  73. data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +56 -6
  74. data/contrib/zstd/lib/deprecated/zbuff.h +1 -1
  75. data/contrib/zstd/lib/deprecated/zbuff_common.c +1 -1
  76. data/contrib/zstd/lib/deprecated/zbuff_compress.c +24 -4
  77. data/contrib/zstd/lib/deprecated/zbuff_decompress.c +3 -1
  78. data/contrib/zstd/lib/dictBuilder/cover.c +60 -44
  79. data/contrib/zstd/lib/dictBuilder/cover.h +6 -11
  80. data/contrib/zstd/lib/dictBuilder/divsufsort.c +1 -1
  81. data/contrib/zstd/lib/dictBuilder/fastcover.c +26 -18
  82. data/contrib/zstd/lib/dictBuilder/zdict.c +100 -101
  83. data/contrib/zstd/lib/legacy/zstd_legacy.h +38 -1
  84. data/contrib/zstd/lib/legacy/zstd_v01.c +18 -53
  85. data/contrib/zstd/lib/legacy/zstd_v01.h +1 -1
  86. data/contrib/zstd/lib/legacy/zstd_v02.c +28 -85
  87. data/contrib/zstd/lib/legacy/zstd_v02.h +1 -1
  88. data/contrib/zstd/lib/legacy/zstd_v03.c +29 -88
  89. data/contrib/zstd/lib/legacy/zstd_v03.h +1 -1
  90. data/contrib/zstd/lib/legacy/zstd_v04.c +27 -80
  91. data/contrib/zstd/lib/legacy/zstd_v04.h +1 -1
  92. data/contrib/zstd/lib/legacy/zstd_v05.c +36 -85
  93. data/contrib/zstd/lib/legacy/zstd_v05.h +1 -1
  94. data/contrib/zstd/lib/legacy/zstd_v06.c +44 -96
  95. data/contrib/zstd/lib/legacy/zstd_v06.h +1 -1
  96. data/contrib/zstd/lib/legacy/zstd_v07.c +37 -92
  97. data/contrib/zstd/lib/legacy/zstd_v07.h +1 -1
  98. data/contrib/zstd/lib/libzstd.mk +237 -0
  99. data/contrib/zstd/lib/libzstd.pc.in +4 -3
  100. data/contrib/zstd/lib/module.modulemap +35 -0
  101. data/contrib/zstd/lib/{dictBuilder/zdict.h → zdict.h} +202 -33
  102. data/contrib/zstd/lib/zstd.h +1030 -332
  103. data/contrib/zstd/lib/{common/zstd_errors.h → zstd_errors.h} +27 -8
  104. data/ext/extconf.rb +26 -7
  105. data/ext/extzstd.c +51 -24
  106. data/ext/extzstd.h +33 -6
  107. data/ext/extzstd_stream.c +74 -31
  108. data/ext/libzstd_conf.h +0 -1
  109. data/ext/zstd_decompress_asm.S +1 -0
  110. metadata +17 -7
  111. data/contrib/zstd/appveyor.yml +0 -292
  112. data/ext/depend +0 -2
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -11,8 +11,49 @@
11
11
  #include "zstd_compress_internal.h"
12
12
  #include "zstd_double_fast.h"
13
13
 
14
+ #ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR
14
15
 
15
- void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
16
+ static
17
+ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
18
+ void ZSTD_fillDoubleHashTableForCDict(ZSTD_matchState_t* ms,
19
+ void const* end, ZSTD_dictTableLoadMethod_e dtlm)
20
+ {
21
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
22
+ U32* const hashLarge = ms->hashTable;
23
+ U32 const hBitsL = cParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS;
24
+ U32 const mls = cParams->minMatch;
25
+ U32* const hashSmall = ms->chainTable;
26
+ U32 const hBitsS = cParams->chainLog + ZSTD_SHORT_CACHE_TAG_BITS;
27
+ const BYTE* const base = ms->window.base;
28
+ const BYTE* ip = base + ms->nextToUpdate;
29
+ const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
30
+ const U32 fastHashFillStep = 3;
31
+
32
+ /* Always insert every fastHashFillStep position into the hash tables.
33
+ * Insert the other positions into the large hash table if their entry
34
+ * is empty.
35
+ */
36
+ for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) {
37
+ U32 const curr = (U32)(ip - base);
38
+ U32 i;
39
+ for (i = 0; i < fastHashFillStep; ++i) {
40
+ size_t const smHashAndTag = ZSTD_hashPtr(ip + i, hBitsS, mls);
41
+ size_t const lgHashAndTag = ZSTD_hashPtr(ip + i, hBitsL, 8);
42
+ if (i == 0) {
43
+ ZSTD_writeTaggedIndex(hashSmall, smHashAndTag, curr + i);
44
+ }
45
+ if (i == 0 || hashLarge[lgHashAndTag >> ZSTD_SHORT_CACHE_TAG_BITS] == 0) {
46
+ ZSTD_writeTaggedIndex(hashLarge, lgHashAndTag, curr + i);
47
+ }
48
+ /* Only load extra positions for ZSTD_dtlm_full */
49
+ if (dtlm == ZSTD_dtlm_fast)
50
+ break;
51
+ } }
52
+ }
53
+
54
+ static
55
+ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
56
+ void ZSTD_fillDoubleHashTableForCCtx(ZSTD_matchState_t* ms,
16
57
  void const* end, ZSTD_dictTableLoadMethod_e dtlm)
17
58
  {
18
59
  const ZSTD_compressionParameters* const cParams = &ms->cParams;
@@ -43,15 +84,239 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
43
84
  /* Only load extra positions for ZSTD_dtlm_full */
44
85
  if (dtlm == ZSTD_dtlm_fast)
45
86
  break;
46
- } }
87
+ } }
88
+ }
89
+
90
+ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
91
+ const void* const end,
92
+ ZSTD_dictTableLoadMethod_e dtlm,
93
+ ZSTD_tableFillPurpose_e tfp)
94
+ {
95
+ if (tfp == ZSTD_tfp_forCDict) {
96
+ ZSTD_fillDoubleHashTableForCDict(ms, end, dtlm);
97
+ } else {
98
+ ZSTD_fillDoubleHashTableForCCtx(ms, end, dtlm);
99
+ }
100
+ }
101
+
102
+
103
+ FORCE_INLINE_TEMPLATE
104
+ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
105
+ size_t ZSTD_compressBlock_doubleFast_noDict_generic(
106
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
107
+ void const* src, size_t srcSize, U32 const mls /* template */)
108
+ {
109
+ ZSTD_compressionParameters const* cParams = &ms->cParams;
110
+ U32* const hashLong = ms->hashTable;
111
+ const U32 hBitsL = cParams->hashLog;
112
+ U32* const hashSmall = ms->chainTable;
113
+ const U32 hBitsS = cParams->chainLog;
114
+ const BYTE* const base = ms->window.base;
115
+ const BYTE* const istart = (const BYTE*)src;
116
+ const BYTE* anchor = istart;
117
+ const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);
118
+ /* presumes that, if there is a dictionary, it must be using Attach mode */
119
+ const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog);
120
+ const BYTE* const prefixLowest = base + prefixLowestIndex;
121
+ const BYTE* const iend = istart + srcSize;
122
+ const BYTE* const ilimit = iend - HASH_READ_SIZE;
123
+ U32 offset_1=rep[0], offset_2=rep[1];
124
+ U32 offsetSaved1 = 0, offsetSaved2 = 0;
125
+
126
+ size_t mLength;
127
+ U32 offset;
128
+ U32 curr;
129
+
130
+ /* how many positions to search before increasing step size */
131
+ const size_t kStepIncr = 1 << kSearchStrength;
132
+ /* the position at which to increment the step size if no match is found */
133
+ const BYTE* nextStep;
134
+ size_t step; /* the current step size */
135
+
136
+ size_t hl0; /* the long hash at ip */
137
+ size_t hl1; /* the long hash at ip1 */
138
+
139
+ U32 idxl0; /* the long match index for ip */
140
+ U32 idxl1; /* the long match index for ip1 */
141
+
142
+ const BYTE* matchl0; /* the long match for ip */
143
+ const BYTE* matchs0; /* the short match for ip */
144
+ const BYTE* matchl1; /* the long match for ip1 */
145
+
146
+ const BYTE* ip = istart; /* the current position */
147
+ const BYTE* ip1; /* the next position */
148
+
149
+ DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_noDict_generic");
150
+
151
+ /* init */
152
+ ip += ((ip - prefixLowest) == 0);
153
+ {
154
+ U32 const current = (U32)(ip - base);
155
+ U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog);
156
+ U32 const maxRep = current - windowLow;
157
+ if (offset_2 > maxRep) offsetSaved2 = offset_2, offset_2 = 0;
158
+ if (offset_1 > maxRep) offsetSaved1 = offset_1, offset_1 = 0;
159
+ }
160
+
161
+ /* Outer Loop: one iteration per match found and stored */
162
+ while (1) {
163
+ step = 1;
164
+ nextStep = ip + kStepIncr;
165
+ ip1 = ip + step;
166
+
167
+ if (ip1 > ilimit) {
168
+ goto _cleanup;
169
+ }
170
+
171
+ hl0 = ZSTD_hashPtr(ip, hBitsL, 8);
172
+ idxl0 = hashLong[hl0];
173
+ matchl0 = base + idxl0;
174
+
175
+ /* Inner Loop: one iteration per search / position */
176
+ do {
177
+ const size_t hs0 = ZSTD_hashPtr(ip, hBitsS, mls);
178
+ const U32 idxs0 = hashSmall[hs0];
179
+ curr = (U32)(ip-base);
180
+ matchs0 = base + idxs0;
181
+
182
+ hashLong[hl0] = hashSmall[hs0] = curr; /* update hash tables */
183
+
184
+ /* check noDict repcode */
185
+ if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
186
+ mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
187
+ ip++;
188
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength);
189
+ goto _match_stored;
190
+ }
191
+
192
+ hl1 = ZSTD_hashPtr(ip1, hBitsL, 8);
193
+
194
+ if (idxl0 > prefixLowestIndex) {
195
+ /* check prefix long match */
196
+ if (MEM_read64(matchl0) == MEM_read64(ip)) {
197
+ mLength = ZSTD_count(ip+8, matchl0+8, iend) + 8;
198
+ offset = (U32)(ip-matchl0);
199
+ while (((ip>anchor) & (matchl0>prefixLowest)) && (ip[-1] == matchl0[-1])) { ip--; matchl0--; mLength++; } /* catch up */
200
+ goto _match_found;
201
+ }
202
+ }
203
+
204
+ idxl1 = hashLong[hl1];
205
+ matchl1 = base + idxl1;
206
+
207
+ if (idxs0 > prefixLowestIndex) {
208
+ /* check prefix short match */
209
+ if (MEM_read32(matchs0) == MEM_read32(ip)) {
210
+ goto _search_next_long;
211
+ }
212
+ }
213
+
214
+ if (ip1 >= nextStep) {
215
+ PREFETCH_L1(ip1 + 64);
216
+ PREFETCH_L1(ip1 + 128);
217
+ step++;
218
+ nextStep += kStepIncr;
219
+ }
220
+ ip = ip1;
221
+ ip1 += step;
222
+
223
+ hl0 = hl1;
224
+ idxl0 = idxl1;
225
+ matchl0 = matchl1;
226
+ #if defined(__aarch64__)
227
+ PREFETCH_L1(ip+256);
228
+ #endif
229
+ } while (ip1 <= ilimit);
230
+
231
+ _cleanup:
232
+ /* If offset_1 started invalid (offsetSaved1 != 0) and became valid (offset_1 != 0),
233
+ * rotate saved offsets. See comment in ZSTD_compressBlock_fast_noDict for more context. */
234
+ offsetSaved2 = ((offsetSaved1 != 0) && (offset_1 != 0)) ? offsetSaved1 : offsetSaved2;
235
+
236
+ /* save reps for next block */
237
+ rep[0] = offset_1 ? offset_1 : offsetSaved1;
238
+ rep[1] = offset_2 ? offset_2 : offsetSaved2;
239
+
240
+ /* Return the last literals size */
241
+ return (size_t)(iend - anchor);
242
+
243
+ _search_next_long:
244
+
245
+ /* check prefix long +1 match */
246
+ if (idxl1 > prefixLowestIndex) {
247
+ if (MEM_read64(matchl1) == MEM_read64(ip1)) {
248
+ ip = ip1;
249
+ mLength = ZSTD_count(ip+8, matchl1+8, iend) + 8;
250
+ offset = (U32)(ip-matchl1);
251
+ while (((ip>anchor) & (matchl1>prefixLowest)) && (ip[-1] == matchl1[-1])) { ip--; matchl1--; mLength++; } /* catch up */
252
+ goto _match_found;
253
+ }
254
+ }
255
+
256
+ /* if no long +1 match, explore the short match we found */
257
+ mLength = ZSTD_count(ip+4, matchs0+4, iend) + 4;
258
+ offset = (U32)(ip - matchs0);
259
+ while (((ip>anchor) & (matchs0>prefixLowest)) && (ip[-1] == matchs0[-1])) { ip--; matchs0--; mLength++; } /* catch up */
260
+
261
+ /* fall-through */
262
+
263
+ _match_found: /* requires ip, offset, mLength */
264
+ offset_2 = offset_1;
265
+ offset_1 = offset;
266
+
267
+ if (step < 4) {
268
+ /* It is unsafe to write this value back to the hashtable when ip1 is
269
+ * greater than or equal to the new ip we will have after we're done
270
+ * processing this match. Rather than perform that test directly
271
+ * (ip1 >= ip + mLength), which costs speed in practice, we do a simpler
272
+ * more predictable test. The minmatch even if we take a short match is
273
+ * 4 bytes, so as long as step, the distance between ip and ip1
274
+ * (initially) is less than 4, we know ip1 < new ip. */
275
+ hashLong[hl1] = (U32)(ip1 - base);
276
+ }
277
+
278
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);
279
+
280
+ _match_stored:
281
+ /* match found */
282
+ ip += mLength;
283
+ anchor = ip;
284
+
285
+ if (ip <= ilimit) {
286
+ /* Complementary insertion */
287
+ /* done after iLimit test, as candidates could be > iend-8 */
288
+ { U32 const indexToInsert = curr+2;
289
+ hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;
290
+ hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
291
+ hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;
292
+ hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base);
293
+ }
294
+
295
+ /* check immediate repcode */
296
+ while ( (ip <= ilimit)
297
+ && ( (offset_2>0)
298
+ & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
299
+ /* store sequence */
300
+ size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
301
+ U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
302
+ hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
303
+ hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
304
+ ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, rLength);
305
+ ip += rLength;
306
+ anchor = ip;
307
+ continue; /* faster when present ... (?) */
308
+ }
309
+ }
310
+ }
47
311
  }
48
312
 
49
313
 
50
314
  FORCE_INLINE_TEMPLATE
51
- size_t ZSTD_compressBlock_doubleFast_generic(
315
+ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
316
+ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic(
52
317
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
53
318
  void const* src, size_t srcSize,
54
- U32 const mls /* template */, ZSTD_dictMode_e const dictMode)
319
+ U32 const mls /* template */)
55
320
  {
56
321
  ZSTD_compressionParameters const* cParams = &ms->cParams;
57
322
  U32* const hashLong = ms->hashTable;
@@ -69,57 +334,39 @@ size_t ZSTD_compressBlock_doubleFast_generic(
69
334
  const BYTE* const iend = istart + srcSize;
70
335
  const BYTE* const ilimit = iend - HASH_READ_SIZE;
71
336
  U32 offset_1=rep[0], offset_2=rep[1];
72
- U32 offsetSaved = 0;
73
337
 
74
338
  const ZSTD_matchState_t* const dms = ms->dictMatchState;
75
- const ZSTD_compressionParameters* const dictCParams =
76
- dictMode == ZSTD_dictMatchState ?
77
- &dms->cParams : NULL;
78
- const U32* const dictHashLong = dictMode == ZSTD_dictMatchState ?
79
- dms->hashTable : NULL;
80
- const U32* const dictHashSmall = dictMode == ZSTD_dictMatchState ?
81
- dms->chainTable : NULL;
82
- const U32 dictStartIndex = dictMode == ZSTD_dictMatchState ?
83
- dms->window.dictLimit : 0;
84
- const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ?
85
- dms->window.base : NULL;
86
- const BYTE* const dictStart = dictMode == ZSTD_dictMatchState ?
87
- dictBase + dictStartIndex : NULL;
88
- const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ?
89
- dms->window.nextSrc : NULL;
90
- const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ?
91
- prefixLowestIndex - (U32)(dictEnd - dictBase) :
92
- 0;
93
- const U32 dictHBitsL = dictMode == ZSTD_dictMatchState ?
94
- dictCParams->hashLog : hBitsL;
95
- const U32 dictHBitsS = dictMode == ZSTD_dictMatchState ?
96
- dictCParams->chainLog : hBitsS;
339
+ const ZSTD_compressionParameters* const dictCParams = &dms->cParams;
340
+ const U32* const dictHashLong = dms->hashTable;
341
+ const U32* const dictHashSmall = dms->chainTable;
342
+ const U32 dictStartIndex = dms->window.dictLimit;
343
+ const BYTE* const dictBase = dms->window.base;
344
+ const BYTE* const dictStart = dictBase + dictStartIndex;
345
+ const BYTE* const dictEnd = dms->window.nextSrc;
346
+ const U32 dictIndexDelta = prefixLowestIndex - (U32)(dictEnd - dictBase);
347
+ const U32 dictHBitsL = dictCParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS;
348
+ const U32 dictHBitsS = dictCParams->chainLog + ZSTD_SHORT_CACHE_TAG_BITS;
97
349
  const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictStart));
98
350
 
99
- DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_generic");
100
-
101
- assert(dictMode == ZSTD_noDict || dictMode == ZSTD_dictMatchState);
351
+ DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_dictMatchState_generic");
102
352
 
103
353
  /* if a dictionary is attached, it must be within window range */
104
- if (dictMode == ZSTD_dictMatchState) {
105
- assert(ms->window.dictLimit + (1U << cParams->windowLog) >= endIndex);
354
+ assert(ms->window.dictLimit + (1U << cParams->windowLog) >= endIndex);
355
+
356
+ if (ms->prefetchCDictTables) {
357
+ size_t const hashTableBytes = (((size_t)1) << dictCParams->hashLog) * sizeof(U32);
358
+ size_t const chainTableBytes = (((size_t)1) << dictCParams->chainLog) * sizeof(U32);
359
+ PREFETCH_AREA(dictHashLong, hashTableBytes);
360
+ PREFETCH_AREA(dictHashSmall, chainTableBytes);
106
361
  }
107
362
 
108
363
  /* init */
109
364
  ip += (dictAndPrefixLength == 0);
110
- if (dictMode == ZSTD_noDict) {
111
- U32 const curr = (U32)(ip - base);
112
- U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog);
113
- U32 const maxRep = curr - windowLow;
114
- if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
115
- if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
116
- }
117
- if (dictMode == ZSTD_dictMatchState) {
118
- /* dictMatchState repCode checks don't currently handle repCode == 0
119
- * disabling. */
120
- assert(offset_1 <= dictAndPrefixLength);
121
- assert(offset_2 <= dictAndPrefixLength);
122
- }
365
+
366
+ /* dictMatchState repCode checks don't currently handle repCode == 0
367
+ * disabling. */
368
+ assert(offset_1 <= dictAndPrefixLength);
369
+ assert(offset_2 <= dictAndPrefixLength);
123
370
 
124
371
  /* Main Search Loop */
125
372
  while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
@@ -127,37 +374,30 @@ size_t ZSTD_compressBlock_doubleFast_generic(
127
374
  U32 offset;
128
375
  size_t const h2 = ZSTD_hashPtr(ip, hBitsL, 8);
129
376
  size_t const h = ZSTD_hashPtr(ip, hBitsS, mls);
130
- size_t const dictHL = ZSTD_hashPtr(ip, dictHBitsL, 8);
131
- size_t const dictHS = ZSTD_hashPtr(ip, dictHBitsS, mls);
377
+ size_t const dictHashAndTagL = ZSTD_hashPtr(ip, dictHBitsL, 8);
378
+ size_t const dictHashAndTagS = ZSTD_hashPtr(ip, dictHBitsS, mls);
379
+ U32 const dictMatchIndexAndTagL = dictHashLong[dictHashAndTagL >> ZSTD_SHORT_CACHE_TAG_BITS];
380
+ U32 const dictMatchIndexAndTagS = dictHashSmall[dictHashAndTagS >> ZSTD_SHORT_CACHE_TAG_BITS];
381
+ int const dictTagsMatchL = ZSTD_comparePackedTags(dictMatchIndexAndTagL, dictHashAndTagL);
382
+ int const dictTagsMatchS = ZSTD_comparePackedTags(dictMatchIndexAndTagS, dictHashAndTagS);
132
383
  U32 const curr = (U32)(ip-base);
133
384
  U32 const matchIndexL = hashLong[h2];
134
385
  U32 matchIndexS = hashSmall[h];
135
386
  const BYTE* matchLong = base + matchIndexL;
136
387
  const BYTE* match = base + matchIndexS;
137
388
  const U32 repIndex = curr + 1 - offset_1;
138
- const BYTE* repMatch = (dictMode == ZSTD_dictMatchState
139
- && repIndex < prefixLowestIndex) ?
389
+ const BYTE* repMatch = (repIndex < prefixLowestIndex) ?
140
390
  dictBase + (repIndex - dictIndexDelta) :
141
391
  base + repIndex;
142
392
  hashLong[h2] = hashSmall[h] = curr; /* update hash tables */
143
393
 
144
- /* check dictMatchState repcode */
145
- if (dictMode == ZSTD_dictMatchState
146
- && ((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */)
394
+ /* check repcode */
395
+ if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */)
147
396
  && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
148
397
  const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
149
398
  mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
150
399
  ip++;
151
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH);
152
- goto _match_stored;
153
- }
154
-
155
- /* check noDict repcode */
156
- if ( dictMode == ZSTD_noDict
157
- && ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) {
158
- mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
159
- ip++;
160
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH);
400
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength);
161
401
  goto _match_stored;
162
402
  }
163
403
 
@@ -169,9 +409,9 @@ size_t ZSTD_compressBlock_doubleFast_generic(
169
409
  while (((ip>anchor) & (matchLong>prefixLowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
170
410
  goto _match_found;
171
411
  }
172
- } else if (dictMode == ZSTD_dictMatchState) {
412
+ } else if (dictTagsMatchL) {
173
413
  /* check dictMatchState long match */
174
- U32 const dictMatchIndexL = dictHashLong[dictHL];
414
+ U32 const dictMatchIndexL = dictMatchIndexAndTagL >> ZSTD_SHORT_CACHE_TAG_BITS;
175
415
  const BYTE* dictMatchL = dictBase + dictMatchIndexL;
176
416
  assert(dictMatchL < dictEnd);
177
417
 
@@ -187,9 +427,9 @@ size_t ZSTD_compressBlock_doubleFast_generic(
187
427
  if (MEM_read32(match) == MEM_read32(ip)) {
188
428
  goto _search_next_long;
189
429
  }
190
- } else if (dictMode == ZSTD_dictMatchState) {
430
+ } else if (dictTagsMatchS) {
191
431
  /* check dictMatchState short match */
192
- U32 const dictMatchIndexS = dictHashSmall[dictHS];
432
+ U32 const dictMatchIndexS = dictMatchIndexAndTagS >> ZSTD_SHORT_CACHE_TAG_BITS;
193
433
  match = dictBase + dictMatchIndexS;
194
434
  matchIndexS = dictMatchIndexS + dictIndexDelta;
195
435
 
@@ -204,10 +444,11 @@ size_t ZSTD_compressBlock_doubleFast_generic(
204
444
  continue;
205
445
 
206
446
  _search_next_long:
207
-
208
447
  { size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
209
- size_t const dictHLNext = ZSTD_hashPtr(ip+1, dictHBitsL, 8);
448
+ size_t const dictHashAndTagL3 = ZSTD_hashPtr(ip+1, dictHBitsL, 8);
210
449
  U32 const matchIndexL3 = hashLong[hl3];
450
+ U32 const dictMatchIndexAndTagL3 = dictHashLong[dictHashAndTagL3 >> ZSTD_SHORT_CACHE_TAG_BITS];
451
+ int const dictTagsMatchL3 = ZSTD_comparePackedTags(dictMatchIndexAndTagL3, dictHashAndTagL3);
211
452
  const BYTE* matchL3 = base + matchIndexL3;
212
453
  hashLong[hl3] = curr + 1;
213
454
 
@@ -220,9 +461,9 @@ _search_next_long:
220
461
  while (((ip>anchor) & (matchL3>prefixLowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */
221
462
  goto _match_found;
222
463
  }
223
- } else if (dictMode == ZSTD_dictMatchState) {
464
+ } else if (dictTagsMatchL3) {
224
465
  /* check dict long +1 match */
225
- U32 const dictMatchIndexL3 = dictHashLong[dictHLNext];
466
+ U32 const dictMatchIndexL3 = dictMatchIndexAndTagL3 >> ZSTD_SHORT_CACHE_TAG_BITS;
226
467
  const BYTE* dictMatchL3 = dictBase + dictMatchIndexL3;
227
468
  assert(dictMatchL3 < dictEnd);
228
469
  if (dictMatchL3 > dictStart && MEM_read64(dictMatchL3) == MEM_read64(ip+1)) {
@@ -234,7 +475,7 @@ _search_next_long:
234
475
  } } }
235
476
 
236
477
  /* if no long +1 match, explore the short match we found */
237
- if (dictMode == ZSTD_dictMatchState && matchIndexS < prefixLowestIndex) {
478
+ if (matchIndexS < prefixLowestIndex) {
238
479
  mLength = ZSTD_count_2segments(ip+4, match+4, iend, dictEnd, prefixLowest) + 4;
239
480
  offset = (U32)(curr - matchIndexS);
240
481
  while (((ip>anchor) & (match>dictStart)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
@@ -244,13 +485,11 @@ _search_next_long:
244
485
  while (((ip>anchor) & (match>prefixLowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
245
486
  }
246
487
 
247
- /* fall-through */
248
-
249
488
  _match_found:
250
489
  offset_2 = offset_1;
251
490
  offset_1 = offset;
252
491
 
253
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
492
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);
254
493
 
255
494
  _match_stored:
256
495
  /* match found */
@@ -268,53 +507,55 @@ _match_stored:
268
507
  }
269
508
 
270
509
  /* check immediate repcode */
271
- if (dictMode == ZSTD_dictMatchState) {
272
- while (ip <= ilimit) {
273
- U32 const current2 = (U32)(ip-base);
274
- U32 const repIndex2 = current2 - offset_2;
275
- const BYTE* repMatch2 = dictMode == ZSTD_dictMatchState
276
- && repIndex2 < prefixLowestIndex ?
277
- dictBase + repIndex2 - dictIndexDelta :
278
- base + repIndex2;
279
- if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */)
280
- && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
281
- const BYTE* const repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend;
282
- size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixLowest) + 4;
283
- U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
284
- ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2-MINMATCH);
285
- hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
286
- hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
287
- ip += repLength2;
288
- anchor = ip;
289
- continue;
290
- }
291
- break;
292
- } }
293
-
294
- if (dictMode == ZSTD_noDict) {
295
- while ( (ip <= ilimit)
296
- && ( (offset_2>0)
297
- & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
298
- /* store sequence */
299
- size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
300
- U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
301
- hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
302
- hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
303
- ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, rLength-MINMATCH);
304
- ip += rLength;
510
+ while (ip <= ilimit) {
511
+ U32 const current2 = (U32)(ip-base);
512
+ U32 const repIndex2 = current2 - offset_2;
513
+ const BYTE* repMatch2 = repIndex2 < prefixLowestIndex ?
514
+ dictBase + repIndex2 - dictIndexDelta :
515
+ base + repIndex2;
516
+ if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */)
517
+ && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
518
+ const BYTE* const repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend;
519
+ size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixLowest) + 4;
520
+ U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
521
+ ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, repLength2);
522
+ hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
523
+ hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
524
+ ip += repLength2;
305
525
  anchor = ip;
306
- continue; /* faster when present ... (?) */
307
- } } }
526
+ continue;
527
+ }
528
+ break;
529
+ }
530
+ }
308
531
  } /* while (ip < ilimit) */
309
532
 
310
533
  /* save reps for next block */
311
- rep[0] = offset_1 ? offset_1 : offsetSaved;
312
- rep[1] = offset_2 ? offset_2 : offsetSaved;
534
+ rep[0] = offset_1;
535
+ rep[1] = offset_2;
313
536
 
314
537
  /* Return the last literals size */
315
538
  return (size_t)(iend - anchor);
316
539
  }
317
540
 
541
+ #define ZSTD_GEN_DFAST_FN(dictMode, mls) \
542
+ static size_t ZSTD_compressBlock_doubleFast_##dictMode##_##mls( \
543
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \
544
+ void const* src, size_t srcSize) \
545
+ { \
546
+ return ZSTD_compressBlock_doubleFast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mls); \
547
+ }
548
+
549
+ ZSTD_GEN_DFAST_FN(noDict, 4)
550
+ ZSTD_GEN_DFAST_FN(noDict, 5)
551
+ ZSTD_GEN_DFAST_FN(noDict, 6)
552
+ ZSTD_GEN_DFAST_FN(noDict, 7)
553
+
554
+ ZSTD_GEN_DFAST_FN(dictMatchState, 4)
555
+ ZSTD_GEN_DFAST_FN(dictMatchState, 5)
556
+ ZSTD_GEN_DFAST_FN(dictMatchState, 6)
557
+ ZSTD_GEN_DFAST_FN(dictMatchState, 7)
558
+
318
559
 
319
560
  size_t ZSTD_compressBlock_doubleFast(
320
561
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
@@ -325,13 +566,13 @@ size_t ZSTD_compressBlock_doubleFast(
325
566
  {
326
567
  default: /* includes case 3 */
327
568
  case 4 :
328
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_noDict);
569
+ return ZSTD_compressBlock_doubleFast_noDict_4(ms, seqStore, rep, src, srcSize);
329
570
  case 5 :
330
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_noDict);
571
+ return ZSTD_compressBlock_doubleFast_noDict_5(ms, seqStore, rep, src, srcSize);
331
572
  case 6 :
332
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_noDict);
573
+ return ZSTD_compressBlock_doubleFast_noDict_6(ms, seqStore, rep, src, srcSize);
333
574
  case 7 :
334
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_noDict);
575
+ return ZSTD_compressBlock_doubleFast_noDict_7(ms, seqStore, rep, src, srcSize);
335
576
  }
336
577
  }
337
578
 
@@ -345,18 +586,20 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState(
345
586
  {
346
587
  default: /* includes case 3 */
347
588
  case 4 :
348
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_dictMatchState);
589
+ return ZSTD_compressBlock_doubleFast_dictMatchState_4(ms, seqStore, rep, src, srcSize);
349
590
  case 5 :
350
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_dictMatchState);
591
+ return ZSTD_compressBlock_doubleFast_dictMatchState_5(ms, seqStore, rep, src, srcSize);
351
592
  case 6 :
352
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_dictMatchState);
593
+ return ZSTD_compressBlock_doubleFast_dictMatchState_6(ms, seqStore, rep, src, srcSize);
353
594
  case 7 :
354
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_dictMatchState);
595
+ return ZSTD_compressBlock_doubleFast_dictMatchState_7(ms, seqStore, rep, src, srcSize);
355
596
  }
356
597
  }
357
598
 
358
599
 
359
- static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
600
+ static
601
+ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
602
+ size_t ZSTD_compressBlock_doubleFast_extDict_generic(
360
603
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
361
604
  void const* src, size_t srcSize,
362
605
  U32 const mls /* template */)
@@ -387,7 +630,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
387
630
 
388
631
  /* if extDict is invalidated due to maxDistance, switch to "regular" variant */
389
632
  if (prefixStartIndex == dictStartIndex)
390
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, mls, ZSTD_noDict);
633
+ return ZSTD_compressBlock_doubleFast(ms, seqStore, rep, src, srcSize);
391
634
 
392
635
  /* Search Loop */
393
636
  while (ip < ilimit) { /* < instead of <=, because (ip+1) */
@@ -409,12 +652,12 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
409
652
  hashSmall[hSmall] = hashLong[hLong] = curr; /* update hash table */
410
653
 
411
654
  if ((((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex doesn't overlap dict + prefix */
412
- & (repIndex > dictStartIndex))
655
+ & (offset_1 <= curr+1 - dictStartIndex)) /* note: we are searching at curr+1 */
413
656
  && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
414
657
  const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
415
658
  mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
416
659
  ip++;
417
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH);
660
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength);
418
661
  } else {
419
662
  if ((matchLongIndex > dictStartIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
420
663
  const BYTE* const matchEnd = matchLongIndex < prefixStartIndex ? dictEnd : iend;
@@ -425,7 +668,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
425
668
  while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
426
669
  offset_2 = offset_1;
427
670
  offset_1 = offset;
428
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
671
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);
429
672
 
430
673
  } else if ((matchIndex > dictStartIndex) && (MEM_read32(match) == MEM_read32(ip))) {
431
674
  size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
@@ -450,7 +693,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
450
693
  }
451
694
  offset_2 = offset_1;
452
695
  offset_1 = offset;
453
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
696
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);
454
697
 
455
698
  } else {
456
699
  ip += ((ip-anchor) >> kSearchStrength) + 1;
@@ -477,12 +720,12 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
477
720
  U32 const repIndex2 = current2 - offset_2;
478
721
  const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;
479
722
  if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) /* intentional overflow : ensure repIndex2 doesn't overlap dict + prefix */
480
- & (repIndex2 > dictStartIndex))
723
+ & (offset_2 <= current2 - dictStartIndex))
481
724
  && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
482
725
  const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
483
726
  size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
484
727
  U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
485
- ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2-MINMATCH);
728
+ ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, repLength2);
486
729
  hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
487
730
  hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
488
731
  ip += repLength2;
@@ -500,6 +743,10 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
500
743
  return (size_t)(iend - anchor);
501
744
  }
502
745
 
746
+ ZSTD_GEN_DFAST_FN(extDict, 4)
747
+ ZSTD_GEN_DFAST_FN(extDict, 5)
748
+ ZSTD_GEN_DFAST_FN(extDict, 6)
749
+ ZSTD_GEN_DFAST_FN(extDict, 7)
503
750
 
504
751
  size_t ZSTD_compressBlock_doubleFast_extDict(
505
752
  ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
@@ -510,12 +757,14 @@ size_t ZSTD_compressBlock_doubleFast_extDict(
510
757
  {
511
758
  default: /* includes case 3 */
512
759
  case 4 :
513
- return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 4);
760
+ return ZSTD_compressBlock_doubleFast_extDict_4(ms, seqStore, rep, src, srcSize);
514
761
  case 5 :
515
- return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 5);
762
+ return ZSTD_compressBlock_doubleFast_extDict_5(ms, seqStore, rep, src, srcSize);
516
763
  case 6 :
517
- return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 6);
764
+ return ZSTD_compressBlock_doubleFast_extDict_6(ms, seqStore, rep, src, srcSize);
518
765
  case 7 :
519
- return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 7);
766
+ return ZSTD_compressBlock_doubleFast_extDict_7(ms, seqStore, rep, src, srcSize);
520
767
  }
521
768
  }
769
+
770
+ #endif /* ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR */