]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
Refactor buildSequencesStatistics() to avoid pointer increment for superblocks
authorsenhuang42 <senhuang96@fb.com>
Fri, 8 Jan 2021 20:50:19 +0000 (15:50 -0500)
committerSen Huang <senhuang96@fb.com>
Wed, 24 Mar 2021 15:21:29 +0000 (08:21 -0700)
lib/compress/zstd_compress.c
lib/compress/zstd_compress_internal.h
lib/compress/zstd_compress_superblock.c

index 9c4835b1007719e3cf6b24203bce9ff939792676..854a8e39891c815c4b02cfbdfc448d50b0cca766 100644 (file)
@@ -2204,18 +2204,18 @@ static int ZSTD_useBlockSplitting(const ZSTD_CCtx_params* cctxParams)
 
 /* ZSTD_buildSequencesStatistics():
  * Returns the size of the statistics for a given set of sequences, or a ZSTD error code,
+ * Also modifies LLtype, Offtype, MLtype, and lastNCount to the appropriate values.
  */
 MEM_STATIC size_t
 ZSTD_buildSequencesStatistics(seqStore_t* seqStorePtr, size_t nbSeq,
+                              U32* LLtype, U32* Offtype, U32* MLtype, BYTE** lastNCount,
                         const ZSTD_fseCTables_t* prevEntropy, ZSTD_fseCTables_t* nextEntropy,
                               BYTE* dst, const BYTE* const dstEnd,
-                              ZSTD_strategy strategy, BYTE** lastNCount, ZSTD_fseCTablesMetadata_t* fseMetadata,
+                              ZSTD_strategy strategy,
                               void* entropyWorkspace, size_t entropyWkspSize) {
-    U32 LLtype, Offtype, MLtype;   /* compressed, raw or rle */
     BYTE* const ostart = dst;
     const BYTE* const oend = dstEnd;
     BYTE* op = ostart;
-    BYTE* seqHead = op++;
 
     unsigned* const countWorkspace = (unsigned*)entropyWorkspace;
 
@@ -2229,34 +2229,31 @@ ZSTD_buildSequencesStatistics(seqStore_t* seqStorePtr, size_t nbSeq,
     /* convert length/distances into codes */
     ZSTD_seqToCodes(seqStorePtr);
     assert(op <= oend);
+    assert(LLtype && Offtype && MLtype);
     /* build CTable for Literal Lengths */
     {   unsigned max = MaxLL;
         size_t const mostFrequent = HIST_countFast_wksp(countWorkspace, &max, llCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);   /* can't fail */
         DEBUGLOG(5, "Building LL table");
         nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;
-        LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode,
+        *LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode,
                                         countWorkspace, max, mostFrequent, nbSeq,
                                         LLFSELog, prevEntropy->litlengthCTable,
                                         LL_defaultNorm, LL_defaultNormLog,
                                         ZSTD_defaultAllowed, strategy);
         assert(set_basic < set_compressed && set_rle < set_compressed);
-        assert(!(LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
+        assert(!(*LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
         {   size_t const countSize = ZSTD_buildCTable(
                 op, (size_t)(oend - op),
-                CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
+                CTable_LitLength, LLFSELog, (symbolEncodingType_e)*LLtype,
                 countWorkspace, max, llCodeTable, nbSeq,
                 LL_defaultNorm, LL_defaultNormLog, MaxLL,
                 prevEntropy->litlengthCTable,
                 sizeof(prevEntropy->litlengthCTable),
                 entropyWorkspace, entropyWkspSize);
             FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed");
-            if (LLtype == set_compressed)
+            if (*LLtype == set_compressed)
                 *lastNCount = op;
             op += countSize;
-            if (fseMetadata) {
-                if (LLtype == set_compressed) fseMetadata->lastCountSize = countSize;
-                fseMetadata->llType = (symbolEncodingType_e) LLtype;
-            }
             assert(op <= oend);
     }   }
     /* build CTable for Offsets */
@@ -2267,28 +2264,24 @@ ZSTD_buildSequencesStatistics(seqStore_t* seqStorePtr, size_t nbSeq,
         ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
         DEBUGLOG(5, "Building OF table");
         nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
-        Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode,
+        *Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode,
                                         countWorkspace, max, mostFrequent, nbSeq,
                                         OffFSELog, prevEntropy->offcodeCTable,
                                         OF_defaultNorm, OF_defaultNormLog,
                                         defaultPolicy, strategy);
-        assert(!(Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
+        assert(!(*Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
         {   size_t const countSize = ZSTD_buildCTable(
                 op, (size_t)(oend - op),
-                CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
+                CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)*Offtype,
                 countWorkspace, max, ofCodeTable, nbSeq,
                 OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
                 prevEntropy->offcodeCTable,
                 sizeof(prevEntropy->offcodeCTable),
                 entropyWorkspace, entropyWkspSize);
             FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed");
-            if (Offtype == set_compressed)
+            if (*Offtype == set_compressed)
                 *lastNCount = op;
             op += countSize;
-            if (fseMetadata) {
-                if (Offtype == set_compressed) fseMetadata->lastCountSize = countSize;
-                fseMetadata->ofType = (symbolEncodingType_e) Offtype;
-            }
             assert(op <= oend);
     }   }
     /* build CTable for MatchLengths */
@@ -2297,32 +2290,26 @@ ZSTD_buildSequencesStatistics(seqStore_t* seqStorePtr, size_t nbSeq,
             countWorkspace, &max, mlCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);   /* can't fail */
         DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
         nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
-        MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode,
+        *MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode,
                                         countWorkspace, max, mostFrequent, nbSeq,
                                         MLFSELog, prevEntropy->matchlengthCTable,
                                         ML_defaultNorm, ML_defaultNormLog,
                                         ZSTD_defaultAllowed, strategy);
-        assert(!(MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
+        assert(!(*MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
         {   size_t const countSize = ZSTD_buildCTable(
                 op, (size_t)(oend - op),
-                CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
+                CTable_MatchLength, MLFSELog, (symbolEncodingType_e)*MLtype,
                 countWorkspace, max, mlCodeTable, nbSeq,
                 ML_defaultNorm, ML_defaultNormLog, MaxML,
                 prevEntropy->matchlengthCTable,
                 sizeof(prevEntropy->matchlengthCTable),
                 entropyWorkspace, entropyWkspSize);
             FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed");
-            if (MLtype == set_compressed)
+            if (*MLtype == set_compressed)
                 *lastNCount = op;
             op += countSize;
-            if (fseMetadata) {
-                if (MLtype == set_compressed) fseMetadata->lastCountSize = countSize;
-                fseMetadata->mlType = (symbolEncodingType_e) MLtype;
-            }
             assert(op <= oend);
     }   }
-
-    *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
     return op-ostart;
 }
 
@@ -2353,6 +2340,7 @@ ZSTD_entropyCompressSequences_internal(seqStore_t* seqStorePtr,
     BYTE* const oend = ostart + dstCapacity;
     BYTE* op = ostart;
     BYTE* lastNCount = NULL;
+    BYTE* seqHead;
 
     entropyWorkspace = count + (MaxSeq + 1);
     entropyWkspSize -= (MaxSeq + 1) * sizeof(*count);
@@ -2398,13 +2386,22 @@ ZSTD_entropyCompressSequences_internal(seqStore_t* seqStorePtr,
         return (size_t)(op - ostart);
     }
 
-    /* build stats for sequences */
-    entropyStatisticsSize = ZSTD_buildSequencesStatistics(seqStorePtr,
-                                                 nbSeq, &prevEntropy->fse, &nextEntropy->fse, op, oend,
-                                                 strategy, &lastNCount, NULL /* no fseMetadata needed */,
+    {
+        U32 LLtype;
+        U32 Offtype;
+        U32 MLtype;
+        seqHead = op++;
+        /* build stats for sequences */
+        entropyStatisticsSize = ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq,
+                                                 &LLtype, &Offtype, &MLtype, &lastNCount,
+                                                 &prevEntropy->fse, &nextEntropy->fse,
+                                                 op, oend,
+                                                 strategy,
                                                  entropyWorkspace, entropyWkspSize);
-    FORWARD_IF_ERROR(entropyStatisticsSize, "FSE statistics building failed!");
-    op += entropyStatisticsSize;
+        FORWARD_IF_ERROR(entropyStatisticsSize, "FSE statistics building failed!");
+        *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
+        op += entropyStatisticsSize;
+    }
 
     {   size_t const bitstreamSize = ZSTD_encodeSequences(
                                         op, (size_t)(oend - op),
@@ -2890,13 +2887,23 @@ static size_t ZSTD_buildBlockEntropyStats_sequences(seqStore_t* seqStorePtr,
     BYTE* const oend = ostart + sizeof(fseMetadata->fseTablesBuffer);
     BYTE* op = ostart;
     BYTE* lastNCount = NULL;
+    size_t hSize;
+    U32 LLtype;
+    U32 Offtype;
+    U32 MLtype;
+
     DEBUGLOG(5, "ZSTD_buildBlockEntropyStats_sequences (nbSeq=%zu)", nbSeq);
     ZSTD_memset(workspace, 0, wkspSize);
-
-    fseMetadata->lastCountSize = 0;
-    return ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq, prevEntropy, nextEntropy, op, oend,
-                                    strategy, &lastNCount, fseMetadata,
+    hSize = ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq,
+                                    &LLtype, &Offtype, &MLtype, &lastNCount,
+                                    prevEntropy, nextEntropy, op, oend,
+                                    strategy,
                                     workspace, wkspSize);
+    fseMetadata->lastNCount = lastNCount;
+    fseMetadata->llType = (symbolEncodingType_e) LLtype;
+    fseMetadata->ofType = (symbolEncodingType_e) Offtype;
+    fseMetadata->mlType = (symbolEncodingType_e) MLtype;
+    return hSize;
 }
 
 
index 33c653e27e052da2db5527a2aec1688ec842c853..6cfeb628c5d6e4b10922314f9b6d68bb4fc50d38 100644 (file)
@@ -107,7 +107,7 @@ typedef struct {
     symbolEncodingType_e mlType;
     BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE];
     size_t fseTablesSize;
-    size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_compressSubBlock_sequences() */
+    BYTE* lastNCount; /* This is to account for bug in 1.3.4. More detail in ZSTD_compressSubBlock_sequences() */
 } ZSTD_fseCTablesMetadata_t;
 
 typedef struct {
index eb0abb0cacb02dff4251a6b5dbbdc851829c532e..1612c7bccc20b783a5dafa6ecfd24e8ba9295148 100644 (file)
@@ -500,9 +500,9 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables
          * block, since it isn't worth optimizing.
          */
 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-        if (writeEntropy && fseMetadata->lastCountSize && fseMetadata->lastCountSize + bitstreamSize < 4) {
+        if (writeEntropy && fseMetadata->lastNCount && (op - fseMetadata->lastNCount) < 4) {
             /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */
-            assert(fseMetadata->lastCountSize + bitstreamSize == 3);
+            assert(op - fseMetadata->lastNCount == 3);
             DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by "
                         "emitting an uncompressed block.");
             return 0;