From 9564bd535c4ea7e62c61d4d99d1b72401d7f31b3 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Sun, 30 Aug 2026 00:58:10 +0000 Subject: [PATCH] deps: update zlib to 1.3.2.1-motley-5eb4d7e --- deps/zlib/BUILD.gn | 22 ++++----- deps/zlib/CMakeLists.txt | 5 +- deps/zlib/adler32_simd.c | 2 +- deps/zlib/compare256.h | 56 +++++++++++++++++++++++ deps/zlib/contrib/tests/utils_unittest.cc | 37 +++++++++++++++ deps/zlib/cpu_features.c | 5 ++ deps/zlib/crc32_simd.c | 6 +++ deps/zlib/crc_folding.c | 14 ++++++ deps/zlib/deflate.c | 22 +++++++-- src/zlib_version.h | 2 +- 10 files changed, 152 insertions(+), 19 deletions(-) create mode 100644 deps/zlib/compare256.h diff --git a/deps/zlib/BUILD.gn b/deps/zlib/BUILD.gn index eff72b22a29b..c37b4252961e 100644 --- a/deps/zlib/BUILD.gn +++ b/deps/zlib/BUILD.gn @@ -98,10 +98,6 @@ source_set("zlib_adler32_simd") { "adler32_simd.c", "adler32_simd.h", ] - - if (!is_win || is_clang) { - cflags = [ "-mssse3" ] - } } if (use_arm_neon_optimizations) { @@ -168,6 +164,15 @@ if (use_arm_neon_optimizations) { } } +# Enables 64-bit word-at-a-time compare256() in deflate's longest_match() on +# 64-bit little-endian architectures (x64 and arm64). Follows the same pattern +# as INFLATE_CHUNK_READ_64LE and DEFLATE_CHUNK_WRITE_64LE below. +config("zlib_compare256_config") { + if (current_cpu == "x64" || current_cpu == "arm64") { + defines = [ "DEFLATE_COMPARE256_64LE" ] + } +} + config("zlib_data_chunk_simd_config") { if (use_x86_x64_optimizations) { defines = [ "INFLATE_CHUNK_SIMD_SSE2" ] @@ -234,13 +239,6 @@ source_set("zlib_crc32_simd") { "crc32_simd.h", "crc_folding.c", ] - - if (!is_win || is_clang) { - cflags = [ - "-msse4.2", - "-mpclmul", - ] - } } configs += [ ":zlib_internal_config" ] @@ -296,6 +294,7 @@ component("zlib") { sources = [ "adler32.c", "chromeconf.h", + "compare256.h", "compress.c", "contrib/optimizations/insert_string.h", "cpu_features.c", @@ -370,6 +369,7 @@ component("zlib") { public_configs = [ ":zlib_config" ] configs += [ + ":zlib_compare256_config", ":zlib_internal_config", # Must be after no_chromium_code for warning flags to be ordered correctly. diff --git a/deps/zlib/CMakeLists.txt b/deps/zlib/CMakeLists.txt index b569804ace08..87d6613be3ff 100644 --- a/deps/zlib/CMakeLists.txt +++ b/deps/zlib/CMakeLists.txt @@ -94,6 +94,7 @@ if (ENABLE_SIMD_OPTIMIZATIONS) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + add_definitions(-DDEFLATE_COMPARE256_64LE) add_definitions(-DINFLATE_CHUNK_SIMD_SSE2) add_definitions(-DADLER32_SIMD_SSSE3) add_definitions(-DINFLATE_CHUNK_READ_64LE) @@ -101,9 +102,6 @@ if (ENABLE_SIMD_OPTIMIZATIONS) add_definitions(-DCRC32_SIMD_SSE42_PCLMUL) if (ENABLE_SIMD_AVX512) add_definitions(-DCRC32_SIMD_AVX512_PCLMUL) - add_compile_options(-mvpclmulqdq -msse2 -mavx512f -mpclmul) - else() - add_compile_options(-msse4.2 -mpclmul) endif() add_definitions(-DDEFLATE_SLIDE_HASH_SSE2) # Required by CPU features detection code. @@ -118,6 +116,7 @@ if (ENABLE_SIMD_OPTIMIZATIONS) add_definitions(-DDEFLATE_CHUNK_WRITE_64LE) add_definitions(-DCRC32_ARMV8_CRC32) add_definitions(-DDEFLATE_SLIDE_HASH_NEON) + add_definitions(-DDEFLATE_COMPARE256_64LE) # Required by CPU features detection code. if (APPLE) add_definitions(-DARMV8_OS_MACOS) diff --git a/deps/zlib/adler32_simd.c b/deps/zlib/adler32_simd.c index 08c21d3e953a..ce4ce7c5755a 100644 --- a/deps/zlib/adler32_simd.c +++ b/deps/zlib/adler32_simd.c @@ -53,7 +53,7 @@ #include -#if defined(__GNUC__) +#if defined(__GNUC__) || defined(__clang__) __attribute__((__target__("ssse3"))) #endif uint32_t ZLIB_INTERNAL adler32_simd_( /* SSSE3 */ diff --git a/deps/zlib/compare256.h b/deps/zlib/compare256.h new file mode 100644 index 000000000000..80061c3febbd --- /dev/null +++ b/deps/zlib/compare256.h @@ -0,0 +1,56 @@ +/* compare256.h + * + * This does 256-byte match comparison for deflate's longest_match. + * + * Copyright 2026 The Chromium Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the Chromium source repository LICENSE file. + */ +#ifndef COMPARE256_H +#define COMPARE256_H + +#include +#include +#if defined(_MSC_VER) && !defined(__clang__) +#include +#endif + +/* Safe unaligned 16-bit load. Compilers optimize this into a single load + * instruction. */ +static inline uint16_t read16(const void* p) { + uint16_t v; + memcpy(&v, p, sizeof(v)); + return v; +} + +/* Finds the byte offset (0..7) of the first difference in non-zero XOR mask + * `x`: + */ +static inline int compare256_diff(uint64_t x) { +#if defined(_MSC_VER) && !defined(__clang__) + unsigned long i; + _BitScanForward64(&i, x); + return (int)i / 8; +#else + return __builtin_ctzll(x) / 8; +#endif +} + +/* Returns the number of matching leading bytes (0 to 256) between src0 and + * src1. Compares 8 bytes per iteration with early exit. */ +static inline int compare256(const unsigned char* src0, + const unsigned char* src1) { + int len = 0; + do { + uint64_t a, b, x; + memcpy(&a, src0 + len, sizeof(a)); + memcpy(&b, src1 + len, sizeof(b)); + x = a ^ b; + if (x) + return len + compare256_diff(x); + len += (int)sizeof(a); + } while (len < 256); + return 256; +} + +#endif /* COMPARE256_H */ diff --git a/deps/zlib/contrib/tests/utils_unittest.cc b/deps/zlib/contrib/tests/utils_unittest.cc index 6161e39f0262..51ace780d2e7 100644 --- a/deps/zlib/contrib/tests/utils_unittest.cc +++ b/deps/zlib/contrib/tests/utils_unittest.cc @@ -19,8 +19,17 @@ #include "third_party/zlib/contrib/minizip/zip.h" #endif +#include "compare256.h" #include "zlib.h" +// Some tests are for little endian optimizations and should be skipped if +// running on big endian. +#if !defined(__BYTE_ORDER__) || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define ZLIB_TEST_LITTLE_ENDIAN 1 +#else +#define ZLIB_TEST_LITTLE_ENDIAN 0 +#endif + void TestPayloads(size_t input_size, zlib_internal::WrapperType type, const int compression_level = Z_DEFAULT_COMPRESSION) { std::vector input; @@ -1475,4 +1484,32 @@ TEST(ZlibTest, Crbug500521311) { EXPECT_EQ(unzClose(uzf), UNZ_OK); } +// compare256() returns the number of equal leading bytes. The buffers are +// exactly the 256 bytes it may read, so ASan traps any over-read. +TEST(ZlibTest, Compare256) { + if (!ZLIB_TEST_LITTLE_ENDIAN) { + GTEST_SKIP() << "compare256() is little-endian only"; + } + for (int equal = 0; equal <= 256; ++equal) { + std::vector a(256, 'a'), b(256, 'a'); + if (equal < 256) + b[equal] = 'b'; + EXPECT_EQ(compare256(a.data(), b.data()), equal); + } +} + +// longest_match() computes 2 + compare256(scan + 2, match + 2), the first two +// bytes being known equal, so a match must still reach MAX_MATCH (258). +TEST(ZlibTest, Compare256ReachesMaxMatch) { + if (!ZLIB_TEST_LITTLE_ENDIAN) { + GTEST_SKIP() << "compare256() is little-endian only"; + } + for (int match_len = 250; match_len <= 258; ++match_len) { + std::vector a(258, 'a'), b(258, 'a'); + if (match_len < 258) + b[match_len] = 'b'; + EXPECT_EQ(2 + compare256(a.data() + 2, b.data() + 2), match_len); + } +} + #endif diff --git a/deps/zlib/cpu_features.c b/deps/zlib/cpu_features.c index 34ae7b913af9..6613a65e335f 100644 --- a/deps/zlib/cpu_features.c +++ b/deps/zlib/cpu_features.c @@ -160,6 +160,11 @@ static void _cpu_check_features(void) #include #include #endif +/* _xgetbv() below needs the xsave ISA. Annotate it here so the build does not + * need -mxsave. */ +#if defined(CRC32_SIMD_AVX512_PCLMUL) && (defined(__GNUC__) || defined(__clang__)) +__attribute__((__target__("xsave"))) +#endif static void _cpu_check_features(void) { int x86_cpu_has_sse2; diff --git a/deps/zlib/crc32_simd.c b/deps/zlib/crc32_simd.c index 1c60ae9bd3c1..20204e322ebe 100644 --- a/deps/zlib/crc32_simd.c +++ b/deps/zlib/crc32_simd.c @@ -21,6 +21,9 @@ #include #include +#if defined(__GNUC__) || defined(__clang__) +__attribute__((__target__("avx512f,avx512vl,vpclmulqdq"))) +#endif uint32_t ZLIB_INTERNAL crc32_avx512_simd_( /* AVX512+PCLMUL */ const unsigned char *buf, z_size_t len, @@ -212,6 +215,9 @@ uint32_t ZLIB_INTERNAL crc32_avx512_simd_( /* AVX512+PCLMUL */ #include #include +#if defined(__GNUC__) || defined(__clang__) +__attribute__((__target__("sse4.2,pclmul"))) +#endif uint32_t ZLIB_INTERNAL crc32_sse42_simd_( /* SSE4.2+PCLMUL */ const unsigned char *buf, z_size_t len, diff --git a/deps/zlib/crc_folding.c b/deps/zlib/crc_folding.c index 1d54ee8d48cf..3e31ae4a7e44 100644 --- a/deps/zlib/crc_folding.c +++ b/deps/zlib/crc_folding.c @@ -25,6 +25,12 @@ #include #include +#if defined(__GNUC__) || defined(__clang__) +#define TARGET_SSE42_PCLMUL __attribute__((__target__("sse4.2,pclmul"))) +#else +#define TARGET_SSE42_PCLMUL +#endif + #define CRC_LOAD(s) \ do { \ __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)s->crc0 + 0);\ @@ -41,6 +47,7 @@ _mm_storeu_si128((__m128i *)s->crc0 + 4, xmm_crc_part);\ } while (0); +TARGET_SSE42_PCLMUL ZLIB_INTERNAL void crc_fold_init(deflate_state *const s) { CRC_LOAD(s) @@ -55,6 +62,7 @@ ZLIB_INTERNAL void crc_fold_init(deflate_state *const s) s->strm->adler = 0; } +TARGET_SSE42_PCLMUL local void fold_1(deflate_state *const s, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) @@ -81,6 +89,7 @@ local void fold_1(deflate_state *const s, *xmm_crc3 = _mm_castps_si128(ps_res); } +TARGET_SSE42_PCLMUL local void fold_2(deflate_state *const s, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) @@ -115,6 +124,7 @@ local void fold_2(deflate_state *const s, *xmm_crc3 = _mm_castps_si128(ps_res31); } +TARGET_SSE42_PCLMUL local void fold_3(deflate_state *const s, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) @@ -155,6 +165,7 @@ local void fold_3(deflate_state *const s, *xmm_crc3 = _mm_castps_si128(ps_res32); } +TARGET_SSE42_PCLMUL local void fold_4(deflate_state *const s, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) @@ -221,6 +232,7 @@ local const unsigned zalign(32) pshufb_shf_table[60] = { 0x0201008f,0x06050403,0x0a090807,0x0e0d0c0b /* shl 1 (16 -15)/shr15*/ }; +TARGET_SSE42_PCLMUL local void partial_fold(deflate_state *const s, const size_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3, @@ -271,6 +283,7 @@ local void partial_fold(deflate_state *const s, const size_t len, *xmm_crc3 = _mm_castps_si128(ps_res); } +TARGET_SSE42_PCLMUL ZLIB_INTERNAL void crc_fold_copy(deflate_state *const s, unsigned char *dst, const unsigned char *src, long len) { @@ -427,6 +440,7 @@ local const unsigned zalign(16) crc_mask2[4] = { 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; +TARGET_SSE42_PCLMUL unsigned ZLIB_INTERNAL crc_fold_512to32(deflate_state *const s) { const __m128i xmm_mask = _mm_load_si128((__m128i *)crc_mask); diff --git a/deps/zlib/deflate.c b/deps/zlib/deflate.c index d95787f286d8..b98a985e5cac 100644 --- a/deps/zlib/deflate.c +++ b/deps/zlib/deflate.c @@ -57,6 +57,8 @@ #include "slide_hash_simd.h" #endif +#include "compare256.h" + #if defined(QAT_COMPRESSION_ENABLED) #include "contrib/qat/deflate_qat.h" #endif @@ -1492,7 +1494,13 @@ local uInt longest_match(deflate_state *s, IPos cur_match) { Posf *prev = s->prev; uInt wmask = s->w_mask; -#ifdef UNALIGNED_OK +#if defined(DEFLATE_COMPARE256_64LE) + /* Quickly reject non-matches with the 2-byte prefilter + * (scan_start/scan_end); candidates that pass are extended 8 bytes at a + * time with compare256(). */ + uInt scan_start = read16(scan); + uInt scan_end = read16(scan + best_len - 1); +#elif defined(UNALIGNED_OK) /* Compare two bytes at a time. Note: this is not always beneficial. * Try with and without -DUNALIGNED_OK to check. */ @@ -1534,7 +1542,13 @@ local uInt longest_match(deflate_state *s, IPos cur_match) { * However the length of the match is limited to the lookahead, so * the output of deflate is not affected by the uninitialized values. */ -#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) +#if defined(DEFLATE_COMPARE256_64LE) + if (read16(match + best_len - 1) != scan_end || + read16(match) != scan_start) continue; + /* scan_start matched, so bytes 0..1 are equal; compare the remaining + * up to 256 bytes so the length can still reach MAX_MATCH (258). */ + len = 2 + compare256(scan + 2, match + 2); +#elif (defined(UNALIGNED_OK) && MAX_MATCH == 258) /* This code assumes sizeof(unsigned short) == 2. Do not use * UNALIGNED_OK if your compiler uses a different size. */ @@ -1624,7 +1638,9 @@ local uInt longest_match(deflate_state *s, IPos cur_match) { s->match_start = cur_match; best_len = len; if (len >= nice_match) break; -#ifdef UNALIGNED_OK +#if defined(DEFLATE_COMPARE256_64LE) + scan_end = read16(scan + best_len - 1); +#elif defined(UNALIGNED_OK) scan_end = *(ushf*)(scan + best_len - 1); #else scan_end1 = scan[best_len - 1]; diff --git a/src/zlib_version.h b/src/zlib_version.h index 861b339e2bfc..a9d28e3a7cd4 100644 --- a/src/zlib_version.h +++ b/src/zlib_version.h @@ -2,5 +2,5 @@ // Refer to tools/dep_updaters/update-zlib.sh #ifndef SRC_ZLIB_VERSION_H_ #define SRC_ZLIB_VERSION_H_ -#define ZLIB_VERSION "1.3.2.1-motley-8002e91" +#define ZLIB_VERSION "1.3.2.1-motley-5eb4d7e" #endif // SRC_ZLIB_VERSION_H_