From 6f9c056662cfd29a44dbea3bfcaf38c2dffe5d9e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 1 May 2016 10:26:30 +0200 Subject: [PATCH 01/23] Fixed BMI behavior on x86 and x32 targets, reported by @tycho (#178) --- Makefile | 15 +- lib/common/bitstream.h | 14 +- lib/decompress/zstd_decompress.c | 5 +- programs/bench.c | 2 +- programs/zstdcli.c | 4 +- .../2013/fullbench/fullbench.vcxproj.filters | 170 +++++++++--------- visual/2013/fuzzer/fuzzer.vcxproj.filters | 158 ++++++++-------- 7 files changed, 193 insertions(+), 175 deletions(-) diff --git a/Makefile b/Makefile index 3f32deeb1..0f6363cf5 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,9 @@ all: zstdprogram: $(MAKE) -C $(PRGDIR) +test: + $(MAKE) -C $(PRGDIR) $@ + clean: @$(MAKE) -C $(ZSTDDIR) $@ > $(VOID) @$(MAKE) -C $(PRGDIR) $@ > $(VOID) @@ -75,9 +78,6 @@ uninstall: travis-install: $(MAKE) install PREFIX=~/install_test_dir -test: - $(MAKE) -C $(PRGDIR) $@ - cmaketest: cd contrib/cmake ; cmake . ; $(MAKE) @@ -88,6 +88,15 @@ clangtest: clean gpptest: clean $(MAKE) all CC=g++ CFLAGS="-O3 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror" +bmix64test: clean + CFLAGS="-O3 -mbmi -Werror" $(MAKE) -C $(PRGDIR) test + +bmix32test: clean + CFLAGS="-O3 -mbmi -mx32 -Werror" $(MAKE) -C $(PRGDIR) test + +bmi32test: clean + CFLAGS="-O3 -mbmi -m32 -Werror" $(MAKE) -C $(PRGDIR) test + armtest: clean $(MAKE) -C $(PRGDIR) datagen # use native, faster $(MAKE) -C $(PRGDIR) test CC=arm-linux-gnueabi-gcc ZSTDRTTEST= MOREFLAGS="-Werror -static" diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index fd114e55a..6b3f13df0 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -301,7 +301,12 @@ MEM_STATIC size_t BIT_getUpperBits(size_t bitD, U32 const start) MEM_STATIC size_t BIT_getMiddleBits(size_t bitD, U32 const nbBits, U32 const start) { #if defined(__BMI__) && defined(__GNUC__) /* experimental */ - return __builtin_ia32_bextr_u64(bitD, (nbBits<<8) | start ); +# if defined(__x86_64__) + if (sizeof(bitD)==8) + return _bextr_u64(bitD, start, nbBits); + else +# endif + return _bextr_u32(bitD, start, nbBits); #else return (bitD >> start) & BIT_mask[nbBits]; #endif @@ -322,7 +327,12 @@ MEM_STATIC size_t BIT_getLowerBits(size_t bitD, U32 const nbBits) MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits) { #if defined(__BMI__) && defined(__GNUC__) /* experimental */ - return __builtin_ia32_bextr_u64(bitD->bitContainer, (nbBits<<8) | (64 - bitD->bitsConsumed - nbBits) ); +# if defined(__x86_64__) + if (sizeof(bitD->bitContainer)==8) + return _bextr_u64(bitD->bitContainer, 64 - bitD->bitsConsumed - nbBits, nbBits); + else +# endif + return _bextr_u32(bitD->bitContainer, 32 - bitD->bitsConsumed - nbBits, nbBits); #else U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1; return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask); diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index c34a7eb22..8e1465e8b 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -266,10 +266,9 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx) * @return : size of the Frame Header */ static size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize) { - U32 fcsId; if (srcSize < ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); - fcsId = (((const BYTE*)src)[4]) >> 6; - return ZSTD_frameHeaderSize_min + ZSTD_fcs_fieldSize[fcsId]; + { U32 const fcsId = (((const BYTE*)src)[4]) >> 6; + return ZSTD_frameHeaderSize_min + ZSTD_fcs_fieldSize[fcsId]; } } diff --git a/programs/bench.c b/programs/bench.c index 85c28e8c2..eecc1e87d 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -450,7 +450,7 @@ static void BMK_loadFiles(void* buffer, size_t bufferSize, totalSize += (size_t)fileSize; fclose(f); } - + if (totalSize == 0) EXM_THROW(12, "no data to bench"); } diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 33e3992c3..98e6c0d3a 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -75,7 +75,7 @@ # define ZSTD_VERSION "v" ZSTD_VERSION_STRING #endif #define AUTHOR "Yann Collet" -#define WELCOME_MESSAGE "*** %s %i-bits %s, by %s ***\n", COMPRESSOR_NAME, (int)(sizeof(void*)*8), ZSTD_VERSION, AUTHOR +#define WELCOME_MESSAGE "*** %s %i-bits %s, by %s ***\n", COMPRESSOR_NAME, (int)(sizeof(size_t)*8), ZSTD_VERSION, AUTHOR #define ZSTD_EXTENSION ".zst" #define ZSTD_CAT "zstdcat" @@ -432,7 +432,7 @@ int main(int argCount, const char** argv) operationResult = FIO_compressFilename(outFileName, filenameTable[0], dictFileName, cLevel); else operationResult = FIO_compressMultipleFilenames(filenameTable, filenameIdx, outFileName ? outFileName : ZSTD_EXTENSION, dictFileName, cLevel); - } else + } else #endif { /* decompression */ #ifndef ZSTD_NODECOMPRESS diff --git a/visual/2013/fullbench/fullbench.vcxproj.filters b/visual/2013/fullbench/fullbench.vcxproj.filters index 323b6446e..af5feb17b 100644 --- a/visual/2013/fullbench/fullbench.vcxproj.filters +++ b/visual/2013/fullbench/fullbench.vcxproj.filters @@ -1,86 +1,86 @@ - - - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + \ No newline at end of file diff --git a/visual/2013/fuzzer/fuzzer.vcxproj.filters b/visual/2013/fuzzer/fuzzer.vcxproj.filters index 3e0cbbedc..9f042b24f 100644 --- a/visual/2013/fuzzer/fuzzer.vcxproj.filters +++ b/visual/2013/fuzzer/fuzzer.vcxproj.filters @@ -1,80 +1,80 @@ - - - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + \ No newline at end of file From 17d35b0bf453cf23a75ea22dc7a12cb92d7209b1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 1 May 2016 10:27:54 +0200 Subject: [PATCH 02/23] added : BMI x64 test for Travis CI --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index fda0b05b5..cba3cf994 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ env: - ZSTD_TRAVIS_CI_ENV=cmaketest - ZSTD_TRAVIS_CI_ENV=clangtest - ZSTD_TRAVIS_CI_ENV=gpptest + - ZSTD_TRAVIS_CI_ENV=bmix64test - ZSTD_TRAVIS_CI_ENV=armtest-w-install - ZSTD_TRAVIS_CI_ENV=test - ZSTD_TRAVIS_CI_ENV="-C programs test32" From f6ac47955b734606c3c6d0ff30eaf821363a05b1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 1 May 2016 10:34:04 +0200 Subject: [PATCH 03/23] removed BMI tests on Travis CI : incompatible compiler --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cba3cf994..fda0b05b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,6 @@ env: - ZSTD_TRAVIS_CI_ENV=cmaketest - ZSTD_TRAVIS_CI_ENV=clangtest - ZSTD_TRAVIS_CI_ENV=gpptest - - ZSTD_TRAVIS_CI_ENV=bmix64test - ZSTD_TRAVIS_CI_ENV=armtest-w-install - ZSTD_TRAVIS_CI_ENV=test - ZSTD_TRAVIS_CI_ENV="-C programs test32" From eef5fdb58aba31bdccff68cb2a3b5b4064e50336 Mon Sep 17 00:00:00 2001 From: thatsafunnyname Date: Wed, 4 May 2016 15:39:31 +0100 Subject: [PATCH 04/23] No stdint.h on OpenVMS. No stdint.h on OpenVMS, it is inttypes.h instead, some projects use HAVE_STDINT_H. --- programs/datagen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/datagen.c b/programs/datagen.c index b7e33e3c7..bf35c568b 100644 --- a/programs/datagen.c +++ b/programs/datagen.c @@ -34,7 +34,7 @@ /*-************************************ * Basic Types **************************************/ -#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ +#if !defined (__VMS) && ( defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ ) # include typedef uint8_t BYTE; typedef uint16_t U16; From dca5cf92ac4f489e4565d28d25965b88d339b8a5 Mon Sep 17 00:00:00 2001 From: thatsafunnyname Date: Wed, 4 May 2016 15:42:25 +0100 Subject: [PATCH 05/23] No stdint.h on OpenVMS. No stdint.h on OpenVMS, it is inttypes.h instead, some projects use HAVE_STDINT_H. --- programs/xxhash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/xxhash.c b/programs/xxhash.c index 352d1e540..2a66e251a 100644 --- a/programs/xxhash.c +++ b/programs/xxhash.c @@ -123,7 +123,7 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcp ***************************************/ #ifndef MEM_MODULE # define MEM_MODULE -# if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +# if !defined (__VMS) && ( defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ ) # include typedef uint8_t BYTE; typedef uint16_t U16; From b0e5427d1a94107c706cf5f0db91fb28857f8c64 Mon Sep 17 00:00:00 2001 From: thatsafunnyname Date: Wed, 4 May 2016 15:43:42 +0100 Subject: [PATCH 06/23] No stdint.h on OpenVMS. No stdint.h on OpenVMS, it is inttypes.h instead, some projects use HAVE_STDINT_H. --- lib/common/mem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common/mem.h b/lib/common/mem.h index ceafd57b4..dbefcdb21 100644 --- a/lib/common/mem.h +++ b/lib/common/mem.h @@ -63,7 +63,7 @@ extern "C" { /*-************************************************************** * Basic Types *****************************************************************/ -#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +#if !defined (__VMS) && ( defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) # include typedef uint8_t BYTE; typedef uint16_t U16; From 3f8ed50bf173425dcd15110c245708764c049ca2 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 5 May 2016 03:01:13 +0200 Subject: [PATCH 07/23] Added gnu90 test work-around : disabled automatic selection of huff0 quad-decoder (see #173) --- .travis.yml | 1 + Makefile | 3 +++ lib/compress/zstd_compress.c | 2 +- lib/decompress/huf_decompress.c | 2 +- programs/paramgrill.c | 3 +++ 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fda0b05b5..b7faed3eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ env: - ZSTD_TRAVIS_CI_ENV=cmaketest - ZSTD_TRAVIS_CI_ENV=clangtest - ZSTD_TRAVIS_CI_ENV=gpptest + - ZSTD_TRAVIS_CI_ENV=gnu90test - ZSTD_TRAVIS_CI_ENV=armtest-w-install - ZSTD_TRAVIS_CI_ENV=test - ZSTD_TRAVIS_CI_ENV="-C programs test32" diff --git a/Makefile b/Makefile index 0f6363cf5..5aad596d1 100644 --- a/Makefile +++ b/Makefile @@ -88,6 +88,9 @@ clangtest: clean gpptest: clean $(MAKE) all CC=g++ CFLAGS="-O3 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror" +gnu90test: clean + $(MAKE) all CFLAGS="-Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wstrict-aliasing=1 -Wswitch-enum -Wstrict-prototypes -Wundef -Werror" + bmix64test: clean CFLAGS="-O3 -mbmi -Werror" $(MAKE) -C $(PRGDIR) test diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 7b07eb454..1bb75c68c 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -852,7 +852,7 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const B static const BYTE* g_start = NULL; const U32 pos = (U32)(literals - g_start); if (g_start==NULL) g_start = literals; - if ((pos > 5810300) && (pos < 5810500)) + if ((pos > 2587900) && (pos < 2588050)) printf("Cpos %6u :%5u literals & match %3u bytes at distance %6u \n", pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode); #endif diff --git a/lib/decompress/huf_decompress.c b/lib/decompress/huf_decompress.c index 79e6fbae3..7637bd941 100644 --- a/lib/decompress/huf_decompress.c +++ b/lib/decompress/huf_decompress.c @@ -1118,7 +1118,7 @@ size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcS Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */ if (Dtime[1] < Dtime[0]) algoNb = 1; - if (Dtime[2] < Dtime[algoNb]) algoNb = 2; + //if (Dtime[2] < Dtime[algoNb]) algoNb = 2; return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); diff --git a/programs/paramgrill.c b/programs/paramgrill.c index f36a6916f..566197f55 100644 --- a/programs/paramgrill.c +++ b/programs/paramgrill.c @@ -44,6 +44,9 @@ #if defined(_MSC_VER) # define snprintf _snprintf /* snprintf unsupported by Visual <= 2012 */ +#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +#else +# define snprintf(b, s, ...) sprintf(b, __VA_ARGS__) #endif From ddb8ebd5b306240915d734403c808ff481243f7b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 5 May 2016 04:59:53 +0200 Subject: [PATCH 08/23] Stricter gnu90 tests --- Makefile | 5 ++++- lib/common/zstd_internal.h | 8 ++++---- lib/legacy/zstd_v01.c | 4 ++-- lib/legacy/zstd_v02.c | 4 ++-- lib/legacy/zstd_v03.c | 4 ++-- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 5aad596d1..7d1ae713f 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,10 @@ gpptest: clean $(MAKE) all CC=g++ CFLAGS="-O3 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror" gnu90test: clean - $(MAKE) all CFLAGS="-Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wstrict-aliasing=1 -Wswitch-enum -Wstrict-prototypes -Wundef -Werror" + $(MAKE) all CFLAGS="-std=gnu90 -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wstrict-aliasing=1 -Wswitch-enum -Wstrict-prototypes -Wundef -Wdeclaration-after-statement -Werror" + +c90test: clean + $(MAKE) all CFLAGS="-std=c90 -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wstrict-aliasing=1 -Wswitch-enum -Wstrict-prototypes -Wundef -Werror" # will fail, due to // and long long bmix64test: clean CFLAGS="-O3 -mbmi -Werror" $(MAKE) -C $(PRGDIR) test diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index d5cc255a9..4c9a7615a 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -203,10 +203,10 @@ typedef struct { #include ".debug/zstd_stats.h" #else typedef struct { U32 unused; } ZSTD_stats_t; - MEM_STATIC void ZSTD_statsPrint(ZSTD_stats_t* stats, U32 searchLength) { (void)stats; (void)searchLength; }; - MEM_STATIC void ZSTD_statsInit(ZSTD_stats_t* stats) { (void)stats; }; - MEM_STATIC void ZSTD_statsResetFreqs(ZSTD_stats_t* stats) { (void)stats; }; - MEM_STATIC void ZSTD_statsUpdatePrices(ZSTD_stats_t* stats, size_t litLength, const BYTE* literals, size_t offset, size_t matchLength) { (void)stats; (void)litLength; (void)literals; (void)offset; (void)matchLength; }; + MEM_STATIC void ZSTD_statsPrint(ZSTD_stats_t* stats, U32 searchLength) { (void)stats; (void)searchLength; } + MEM_STATIC void ZSTD_statsInit(ZSTD_stats_t* stats) { (void)stats; } + MEM_STATIC void ZSTD_statsResetFreqs(ZSTD_stats_t* stats) { (void)stats; } + MEM_STATIC void ZSTD_statsUpdatePrices(ZSTD_stats_t* stats, size_t litLength, const BYTE* literals, size_t offset, size_t matchLength) { (void)stats; (void)litLength; (void)literals; (void)offset; (void)matchLength; } #endif typedef struct { diff --git a/lib/legacy/zstd_v01.c b/lib/legacy/zstd_v01.c index 2fcf18885..d62367df2 100644 --- a/lib/legacy/zstd_v01.c +++ b/lib/legacy/zstd_v01.c @@ -407,7 +407,7 @@ FORCE_INLINE unsigned FSE_highbit32 (register U32 val) static U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; } -#define FSE_DECODE_TYPE FSE_TYPE_NAME(FSE_decode_t, FSE_FUNCTION_EXTENSION) +#define FSE_DECODE_TYPE FSE_decode_t typedef struct { @@ -415,7 +415,7 @@ typedef struct { U16 fastMode; } FSE_DTableHeader; /* sizeof U32 */ -static size_t FSE_FUNCTION_NAME(FSE_buildDTable, FSE_FUNCTION_EXTENSION) +static size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) { void* ptr = dt; diff --git a/lib/legacy/zstd_v02.c b/lib/legacy/zstd_v02.c index 860df94a6..89501111e 100644 --- a/lib/legacy/zstd_v02.c +++ b/lib/legacy/zstd_v02.c @@ -1266,11 +1266,11 @@ typedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)]; /* Function templates */ -#define FSE_DECODE_TYPE FSE_TYPE_NAME(FSE_decode_t, FSE_FUNCTION_EXTENSION) +#define FSE_DECODE_TYPE FSE_decode_t static U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; } -static size_t FSE_FUNCTION_NAME(FSE_buildDTable, FSE_FUNCTION_EXTENSION) +static size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) { void* ptr = dt+1; diff --git a/lib/legacy/zstd_v03.c b/lib/legacy/zstd_v03.c index 6a048fd27..32be1c8dd 100644 --- a/lib/legacy/zstd_v03.c +++ b/lib/legacy/zstd_v03.c @@ -1266,11 +1266,11 @@ typedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)]; /* Function templates */ -#define FSE_DECODE_TYPE FSE_TYPE_NAME(FSE_decode_t, FSE_FUNCTION_EXTENSION) +#define FSE_DECODE_TYPE FSE_decode_t static U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; } -static size_t FSE_FUNCTION_NAME(FSE_buildDTable, FSE_FUNCTION_EXTENSION) +static size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) { void* ptr = dt+1; From 6d1d25299ab3abfce95bdf4ec57c47e493a51976 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 5 May 2016 12:41:36 +0200 Subject: [PATCH 09/23] fixed Huff0 quad-symbols decoder (#173) --- lib/common/huf_static.h | 39 +++++----- lib/decompress/huf_decompress.c | 125 +++++++++++++++++--------------- 2 files changed, 87 insertions(+), 77 deletions(-) diff --git a/lib/common/huf_static.h b/lib/common/huf_static.h index d2d29a42b..e68ec33dd 100644 --- a/lib/common/huf_static.h +++ b/lib/common/huf_static.h @@ -76,7 +76,7 @@ extern "C" { ******************************************/ size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */ size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbols decoder */ -size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* quad-symbols decoder */ +size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* quad-symbols decoder, only works for dstSize >= 64 */ /* **************************************** @@ -122,7 +122,7 @@ size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, si size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */ size_t HUF_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */ -size_t HUF_decompress1X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* quad-symbol decoder */ +size_t HUF_decompress1X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* quad-symbols decoder, only works for dstSize >= 64 */ size_t HUF_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable); size_t HUF_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable); @@ -157,7 +157,6 @@ MEM_STATIC size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, const void* src, size_t srcSize) { U32 weightTotal; - U32 tableLog; const BYTE* ip = (const BYTE*) src; size_t iSize = ip[0]; size_t oSize; @@ -191,31 +190,31 @@ MEM_STATIC size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, /* collect weight stats */ memset(rankStats, 0, (HUF_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32)); weightTotal = 0; - { U32 n; for (n=0; n= HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected); - rankStats[huffWeight[n]]++; - weightTotal += (1 << huffWeight[n]) >> 1; - }} + { U32 n; for (n=0; n= HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected); + rankStats[huffWeight[n]]++; + weightTotal += (1 << huffWeight[n]) >> 1; + } } /* get last non-null symbol weight (implied, total must be 2^n) */ - tableLog = BIT_highbit32(weightTotal) + 1; - if (tableLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected); - /* determine last weight */ - { U32 const total = 1 << tableLog; - U32 const rest = total - weightTotal; - U32 const verif = 1 << BIT_highbit32(rest); - U32 const lastWeight = BIT_highbit32(rest) + 1; - if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */ - huffWeight[oSize] = (BYTE)lastWeight; - rankStats[lastWeight]++; - } + { U32 const tableLog = BIT_highbit32(weightTotal) + 1; + if (tableLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected); + *tableLogPtr = tableLog; + /* determine last weight */ + { U32 const total = 1 << tableLog; + U32 const rest = total - weightTotal; + U32 const verif = 1 << BIT_highbit32(rest); + U32 const lastWeight = BIT_highbit32(rest) + 1; + if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */ + huffWeight[oSize] = (BYTE)lastWeight; + rankStats[lastWeight]++; + } } /* check tree construction validity */ if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */ /* results */ *nbSymbolsPtr = (U32)(oSize+1); - *tableLogPtr = tableLog; return iSize+1; } diff --git a/lib/decompress/huf_decompress.c b/lib/decompress/huf_decompress.c index 7637bd941..d64808f65 100644 --- a/lib/decompress/huf_decompress.c +++ b/lib/decompress/huf_decompress.c @@ -847,17 +847,17 @@ size_t HUF_readDTableX6 (U32* DTable, const void* src, size_t srcSize) static U32 HUF_decodeSymbolX6(void* op, BIT_DStream_t* DStream, const HUF_DDescX6* dd, const HUF_DSeqX6* ds, const U32 dtLog) { - const size_t val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ + size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ memcpy(op, ds+val, sizeof(HUF_DSeqX6)); BIT_skipBits(DStream, dd[val].nbBits); return dd[val].nbBytes; } -static U32 HUF_decodeLastSymbolsX6(void* op, const U32 maxL, BIT_DStream_t* DStream, +static U32 HUF_decodeLastSymbolsX6(void* op, U32 const maxL, BIT_DStream_t* DStream, const HUF_DDescX6* dd, const HUF_DSeqX6* ds, const U32 dtLog) { - const size_t val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ - U32 length = dd[val].nbBytes; + size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ + U32 const length = dd[val].nbBytes; if (length <= maxL) { memcpy(op, ds+val, length); BIT_skipBits(DStream, dd[val].nbBits); @@ -910,7 +910,6 @@ static inline size_t HUF_decodeStreamX6(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* c return p-pStart; } - size_t HUF_decompress1X6_usingDTable( void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, @@ -919,17 +918,15 @@ size_t HUF_decompress1X6_usingDTable( const BYTE* const istart = (const BYTE*) cSrc; BYTE* const ostart = (BYTE*) dst; BYTE* const oend = ostart + dstSize; - - const U32 dtLog = DTable[0]; - size_t errorCode; + BIT_DStream_t bitD; /* Init */ - BIT_DStream_t bitD; - errorCode = BIT_initDStream(&bitD, istart, cSrcSize); - if (HUF_isError(errorCode)) return errorCode; + { size_t const errorCode = BIT_initDStream(&bitD, istart, cSrcSize); + if (HUF_isError(errorCode)) return errorCode; } /* finish bitStreams one by one */ - HUF_decodeStreamX6(ostart, &bitD, oend, DTable, dtLog); + { U32 const dtLog = DTable[0]; + HUF_decodeStreamX6(ostart, &bitD, oend, DTable, dtLog); } /* check */ if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected); @@ -943,7 +940,7 @@ size_t HUF_decompress1X6 (void* dst, size_t dstSize, const void* cSrc, size_t cS HUF_CREATE_STATIC_DTABLEX6(DTable, HUF_MAX_TABLELOG); const BYTE* ip = (const BYTE*) cSrc; - size_t hSize = HUF_readDTableX6 (DTable, cSrc, cSrcSize); + size_t const hSize = HUF_readDTableX6 (DTable, cSrc, cSrcSize); if (HUF_isError(hSize)) return hSize; if (hSize >= cSrcSize) return ERROR(srcSize_wrong); ip += hSize; @@ -953,6 +950,24 @@ size_t HUF_decompress1X6 (void* dst, size_t dstSize, const void* cSrc, size_t cS } +#define HUF_DECODE_ROUNDX6 \ + HUF_DECODE_SYMBOLX6_2(op1, &bitD1); \ + HUF_DECODE_SYMBOLX6_2(op2, &bitD2); \ + HUF_DECODE_SYMBOLX6_2(op3, &bitD3); \ + HUF_DECODE_SYMBOLX6_2(op4, &bitD4); \ + HUF_DECODE_SYMBOLX6_1(op1, &bitD1); \ + HUF_DECODE_SYMBOLX6_1(op2, &bitD2); \ + HUF_DECODE_SYMBOLX6_1(op3, &bitD3); \ + HUF_DECODE_SYMBOLX6_1(op4, &bitD4); \ + HUF_DECODE_SYMBOLX6_2(op1, &bitD1); \ + HUF_DECODE_SYMBOLX6_2(op2, &bitD2); \ + HUF_DECODE_SYMBOLX6_2(op3, &bitD3); \ + HUF_DECODE_SYMBOLX6_2(op4, &bitD4); \ + HUF_DECODE_SYMBOLX6_0(op1, &bitD1); \ + HUF_DECODE_SYMBOLX6_0(op2, &bitD2); \ + HUF_DECODE_SYMBOLX6_0(op3, &bitD3); \ + HUF_DECODE_SYMBOLX6_0(op4, &bitD4); + size_t HUF_decompress4X6_usingDTable( void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, @@ -960,6 +975,7 @@ size_t HUF_decompress4X6_usingDTable( { /* Check */ if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ + if (dstSize < 64) return ERROR(dstSize_tooSmall); /* only work for dstSize >= 64 */ { const BYTE* const istart = (const BYTE*) cSrc; BYTE* const ostart = (BYTE*) dst; @@ -970,7 +986,6 @@ size_t HUF_decompress4X6_usingDTable( const HUF_DDescX6* dd = (const HUF_DDescX6*)ddPtr; const void* const dsPtr = DTable + 1 + ((size_t)1<<(dtLog-1)); const HUF_DSeqX6* ds = (const HUF_DSeqX6*)dsPtr; - size_t errorCode; /* Init */ BIT_DStream_t bitD1; @@ -997,43 +1012,41 @@ size_t HUF_decompress4X6_usingDTable( length4 = cSrcSize - (length1 + length2 + length3 + 6); if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ - errorCode = BIT_initDStream(&bitD1, istart1, length1); - if (HUF_isError(errorCode)) return errorCode; - errorCode = BIT_initDStream(&bitD2, istart2, length2); - if (HUF_isError(errorCode)) return errorCode; - errorCode = BIT_initDStream(&bitD3, istart3, length3); - if (HUF_isError(errorCode)) return errorCode; - errorCode = BIT_initDStream(&bitD4, istart4, length4); - if (HUF_isError(errorCode)) return errorCode; + { size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1); + if (HUF_isError(errorCode)) return errorCode; } + { size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2); + if (HUF_isError(errorCode)) return errorCode; } + { size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3); + if (HUF_isError(errorCode)) return errorCode; } + { size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4); + if (HUF_isError(errorCode)) return errorCode; } - /* 16-64 symbols per loop (4-16 symbols per stream) */ + /* 4-64 symbols per loop (1-16 symbols per stream) */ endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); - for ( ; (op3 <= opStart4) && (endSignal==BIT_DStream_unfinished) && (op4<=(oend-16)) ; ) { - HUF_DECODE_SYMBOLX6_2(op1, &bitD1); - HUF_DECODE_SYMBOLX6_2(op2, &bitD2); - HUF_DECODE_SYMBOLX6_2(op3, &bitD3); - HUF_DECODE_SYMBOLX6_2(op4, &bitD4); - HUF_DECODE_SYMBOLX6_1(op1, &bitD1); - HUF_DECODE_SYMBOLX6_1(op2, &bitD2); - HUF_DECODE_SYMBOLX6_1(op3, &bitD3); - HUF_DECODE_SYMBOLX6_1(op4, &bitD4); - HUF_DECODE_SYMBOLX6_2(op1, &bitD1); - HUF_DECODE_SYMBOLX6_2(op2, &bitD2); - HUF_DECODE_SYMBOLX6_2(op3, &bitD3); - HUF_DECODE_SYMBOLX6_2(op4, &bitD4); - HUF_DECODE_SYMBOLX6_0(op1, &bitD1); - HUF_DECODE_SYMBOLX6_0(op2, &bitD2); - HUF_DECODE_SYMBOLX6_0(op3, &bitD3); - HUF_DECODE_SYMBOLX6_0(op4, &bitD4); - - endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); - } + if (endSignal==BIT_DStream_unfinished) { + HUF_DECODE_ROUNDX6; + if (sizeof(bitD1.bitContainer)==4) { /* need to decode at least 4 bytes per stream */ + endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); + HUF_DECODE_ROUNDX6; + } + { U32 const saved2 = MEM_read32(opStart2); /* saved from overwrite */ + U32 const saved3 = MEM_read32(opStart3); + U32 const saved4 = MEM_read32(opStart4); + endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); + for ( ; (op3 <= opStart4) && (endSignal==BIT_DStream_unfinished) && (op4<=(oend-16)) ; ) { + HUF_DECODE_ROUNDX6; + endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); + } + MEM_write32(opStart2, saved2); + MEM_write32(opStart3, saved3); + MEM_write32(opStart4, saved4); + } } /* check corruption */ if (op1 > opStart2) return ERROR(corruption_detected); if (op2 > opStart3) return ERROR(corruption_detected); if (op3 > opStart4) return ERROR(corruption_detected); - /* note : op4 supposed already verified within main loop */ + /* note : op4 already verified within main loop */ /* finish bitStreams one by one */ HUF_decodeStreamX6(op1, &bitD1, opStart2, DTable, dtLog); @@ -1097,12 +1110,7 @@ typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) { static const decompressionAlgo decompress[3] = { HUF_decompress4X2, HUF_decompress4X4, HUF_decompress4X6 }; - /* estimate decompression time */ - U32 Q; - const U32 D256 = (U32)(dstSize >> 8); - U32 Dtime[3]; - U32 algoNb = 0; - int n; + U32 Dtime[3]; /* decompression time estimation */ /* validation checks */ if (dstSize == 0) return ERROR(dstSize_tooSmall); @@ -1111,16 +1119,19 @@ size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcS if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ /* decoder timing evaluation */ - Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */ - for (n=0; n<3; n++) - Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256); + { U32 const Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */ + U32 const D256 = (U32)(dstSize >> 8); + U32 n; for (n=0; n<3; n++) + Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256); + } Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */ - if (Dtime[1] < Dtime[0]) algoNb = 1; - //if (Dtime[2] < Dtime[algoNb]) algoNb = 2; - - return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); + { U32 algoNb = 0; + if (Dtime[1] < Dtime[0]) algoNb = 1; + if (Dtime[2] < Dtime[algoNb]) algoNb = 2; + return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); + } //return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize); /* multi-streams single-symbol decoding */ //return HUF_decompress4X4(dst, dstSize, cSrc, cSrcSize); /* multi-streams double-symbols decoding */ From 8283a2f0aae3d8ecc5b90c42fae3166c36f0ae2b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 6 May 2016 01:51:31 +0200 Subject: [PATCH 10/23] Fixed decoding corruption error with quad-symbols huffman on legacy decoders --- lib/legacy/zstd_v03.c | 360 +-------------------------------------- lib/legacy/zstd_v04.c | 356 +-------------------------------------- lib/legacy/zstd_v05.c | 381 +----------------------------------------- 3 files changed, 4 insertions(+), 1093 deletions(-) diff --git a/lib/legacy/zstd_v03.c b/lib/legacy/zstd_v03.c index 32be1c8dd..f06b47fdc 100644 --- a/lib/legacy/zstd_v03.c +++ b/lib/legacy/zstd_v03.c @@ -991,7 +991,6 @@ extern "C" { ******************************************/ static size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */ static size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbols decoder */ -static size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* quad-symbols decoder */ #if defined (__cplusplus) @@ -2371,362 +2370,6 @@ static size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, si } -/**********************************/ -/* quad-symbol decoding */ -/**********************************/ -typedef struct { BYTE nbBits; BYTE nbBytes; } HUF_DDescX6; -typedef union { BYTE byte[4]; U32 sequence; } HUF_DSeqX6; - -/* recursive, up to level 3; may benefit from