Skip to content

Commit

Permalink
Sync Brotli ode with Upstream (#87)
Browse files Browse the repository at this point in the history
* Sync Brotli ode with Upstream
  • Loading branch information
hyperxpro authored Feb 19, 2023
1 parent 31e2799 commit 7aae1c5
Show file tree
Hide file tree
Showing 66 changed files with 805 additions and 634 deletions.
3 changes: 2 additions & 1 deletion brotli/common/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
#ifndef BROTLI_COMMON_CONSTANTS_H_
#define BROTLI_COMMON_CONSTANTS_H_

#include "platform.h"
#include <brotli/port.h>
#include <brotli/types.h>

#include "platform.h"

/* Specification: 7.3. Encoding of the context map */
#define BROTLI_CONTEXT_MAP_MAX_RLE 16

Expand Down
2 changes: 1 addition & 1 deletion brotli/common/dictionary.c
Original file line number Diff line number Diff line change
Expand Up @@ -5897,7 +5897,7 @@ static BrotliDictionary kBrotliDictionary = {
#endif
};

const BrotliDictionary* BrotliGetDictionary() {
const BrotliDictionary* BrotliGetDictionary(void) {
return &kBrotliDictionary;
}

Expand Down
3 changes: 2 additions & 1 deletion brotli/common/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@

#include <stdlib.h>

#include "platform.h"
#include <brotli/types.h>

#include "platform.h"

/* Default brotli_alloc_func */
void* BrotliDefaultAllocFunc(void* opaque, size_t size) {
BROTLI_UNUSED(opaque);
Expand Down
123 changes: 36 additions & 87 deletions brotli/common/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
* BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations
* BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations
* BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations
* BROTLI_BUILD_PORTABLE disables dangerous optimizations, like unaligned
read and overlapping memcpy; this reduces decompression speed by 5%
* BROTLI_BUILD_NO_RBIT disables "rbit" optimization for ARM CPUs
* BROTLI_BUILD_NO_UNALIGNED_READ_FAST forces off the fast-unaligned-read
optimizations (mainly for testing purposes).
* BROTLI_DEBUG dumps file name and line number when decoder detects stream
or memory error
* BROTLI_ENABLE_LOG enables asserts and dumps various state information
Expand Down Expand Up @@ -208,15 +208,19 @@ To apply compiler hint, enclose the branching condition into macros, like this:
#define BROTLI_TARGET_RISCV64
#endif

#if defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8_64) || \
defined(BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64)
#define BROTLI_TARGET_64_BITS 1
#else
#define BROTLI_TARGET_64_BITS 0
#endif

#if defined(BROTLI_BUILD_64_BIT)
#define BROTLI_64_BITS 1
#elif defined(BROTLI_BUILD_32_BIT)
#define BROTLI_64_BITS 0
#elif defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8_64) || \
defined(BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64)
#define BROTLI_64_BITS 1
#else
#define BROTLI_64_BITS 0
#define BROTLI_64_BITS BROTLI_TARGET_64_BITS
#endif

#if (BROTLI_64_BITS)
Expand Down Expand Up @@ -260,18 +264,19 @@ To apply compiler hint, enclose the branching condition into macros, like this:
#undef BROTLI_X_BIG_ENDIAN
#endif

#if defined(BROTLI_BUILD_PORTABLE)
#define BROTLI_ALIGNED_READ (!!1)
#elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) || \
#if defined(BROTLI_BUILD_NO_UNALIGNED_READ_FAST)
#define BROTLI_UNALIGNED_READ_FAST (!!0)
#elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) || \
defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY) || \
defined(BROTLI_TARGET_RISCV64)
/* Allow unaligned read only for white-listed CPUs. */
#define BROTLI_ALIGNED_READ (!!0)
/* These targets are known to generate efficient code for unaligned reads
* (e.g. a single instruction, not multiple 1-byte loads, shifted and or'd
* together). */
#define BROTLI_UNALIGNED_READ_FAST (!!1)
#else
#define BROTLI_ALIGNED_READ (!!1)
#define BROTLI_UNALIGNED_READ_FAST (!!0)
#endif

#if BROTLI_ALIGNED_READ
/* Portable unaligned memory access: read / write values via memcpy. */
static BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) {
uint16_t t;
Expand All @@ -291,75 +296,6 @@ static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
memcpy(p, &v, sizeof v);
}
#else /* BROTLI_ALIGNED_READ */
/* Unaligned memory access is allowed: just cast pointer to requested type. */
#if BROTLI_SANITIZED
/* Consider we have an unaligned load/store of 4 bytes from address 0x...05.
AddressSanitizer will treat it as a 3-byte access to the range 05:07 and
will miss a bug if 08 is the first unaddressable byte.
ThreadSanitizer will also treat this as a 3-byte access to 05:07 and will
miss a race between this access and some other accesses to 08.
MemorySanitizer will correctly propagate the shadow on unaligned stores
and correctly report bugs on unaligned loads, but it may not properly
update and report the origin of the uninitialized memory.
For all three tools, replacing an unaligned access with a tool-specific
callback solves the problem. */
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
uint16_t __sanitizer_unaligned_load16(const void* p);
uint32_t __sanitizer_unaligned_load32(const void* p);
uint64_t __sanitizer_unaligned_load64(const void* p);
void __sanitizer_unaligned_store64(void* p, uint64_t v);
#if defined(__cplusplus)
} /* extern "C" */
#endif /* __cplusplus */
#define BrotliUnalignedRead16 __sanitizer_unaligned_load16
#define BrotliUnalignedRead32 __sanitizer_unaligned_load32
#define BrotliUnalignedRead64 __sanitizer_unaligned_load64
#define BrotliUnalignedWrite64 __sanitizer_unaligned_store64
#else /* BROTLI_SANITIZED */
static BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) {
return *(const uint16_t*)p;
}
static BROTLI_INLINE uint32_t BrotliUnalignedRead32(const void* p) {
return *(const uint32_t*)p;
}
#if (BROTLI_64_BITS)
static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
return *(const uint64_t*)p;
}
static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
*(uint64_t*)p = v;
}
#else /* BROTLI_64_BITS */
/* Avoid emitting LDRD / STRD, which require properly aligned address. */
/* If __attribute__(aligned) is available, use that. Otherwise, memcpy. */

#if BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0)
typedef BROTLI_ALIGNED(1) uint64_t brotli_unaligned_uint64_t;

static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
return (uint64_t) ((const brotli_unaligned_uint64_t*) p)[0];
}
static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
brotli_unaligned_uint64_t* dwords = (brotli_unaligned_uint64_t*) p;
dwords[0] = (brotli_unaligned_uint64_t) v;
}
#else /* BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) */
static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
uint64_t v;
memcpy(&v, p, sizeof(uint64_t));
return v;
}

static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
memcpy(p, &v, sizeof(uint64_t));
}
#endif /* BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) */
#endif /* BROTLI_64_BITS */
#endif /* BROTLI_SANITIZED */
#endif /* BROTLI_ALIGNED_READ */

#if BROTLI_LITTLE_ENDIAN
/* Straight endianness. Just read / write values. */
Expand Down Expand Up @@ -435,6 +371,16 @@ static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) {
}
#endif /* BROTLI_LITTLE_ENDIAN */

static BROTLI_INLINE void* BROTLI_UNALIGNED_LOAD_PTR(const void* p) {
void* v;
memcpy(&v, p, sizeof(void*));
return v;
}

static BROTLI_INLINE void BROTLI_UNALIGNED_STORE_PTR(void* p, const void* v) {
memcpy(p, &v, sizeof(void*));
}

/* BROTLI_IS_CONSTANT macros returns true for compile-time constants. */
#if BROTLI_GNUC_HAS_BUILTIN(__builtin_constant_p, 3, 0, 1) || \
BROTLI_INTEL_VERSION_CHECK(16, 0, 0)
Expand Down Expand Up @@ -467,6 +413,8 @@ static BROTLI_INLINE void BrotliDump(const char* f, int l, const char* fn) {
#define BROTLI_DUMP() (void)(0)
#endif

/* BrotliRBit assumes brotli_reg_t fits native CPU register type. */
#if (BROTLI_64_BITS == BROTLI_TARGET_64_BITS)
/* TODO(eustas): add appropriate icc/sunpro/arm/ibm/ti checks. */
#if (BROTLI_GNUC_VERSION_CHECK(3, 0, 0) || defined(__llvm__)) && \
!defined(BROTLI_BUILD_NO_RBIT)
Expand All @@ -480,15 +428,14 @@ static BROTLI_INLINE brotli_reg_t BrotliRBit(brotli_reg_t input) {
#define BROTLI_RBIT(x) BrotliRBit(x)
#endif /* armv7 / armv8 */
#endif /* gcc || clang */
#endif /* brotli_reg_t is native */
#if !defined(BROTLI_RBIT)
static BROTLI_INLINE void BrotliRBit(void) { /* Should break build if used. */ }
#endif /* BROTLI_RBIT */

#define BROTLI_REPEAT(N, X) { \
if ((N & 1) != 0) {X;} \
if ((N & 2) != 0) {X; X;} \
if ((N & 4) != 0) {X; X; X; X;} \
}
#define BROTLI_REPEAT_4(X) {X; X; X; X;}
#define BROTLI_REPEAT_5(X) {X; X; X; X; X;}
#define BROTLI_REPEAT_6(X) {X; X; X; X; X; X;}

#define BROTLI_UNUSED(X) (void)(X)

Expand Down Expand Up @@ -553,6 +500,8 @@ BROTLI_UNUSED_FUNCTION void BrotliSuppressUnusedFunctions(void) {
BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD32LE);
BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD64LE);
BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE64LE);
BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD_PTR);
BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE_PTR);
BROTLI_UNUSED(&BrotliRBit);
BROTLI_UNUSED(&brotli_min_double);
BROTLI_UNUSED(&brotli_max_double);
Expand Down
5 changes: 3 additions & 2 deletions brotli/common/shared_dictionary_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
#ifndef BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_
#define BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_

#include "dictionary.h"
#include <brotli/shared_dictionary.h>
#include "transform.h"
#include <brotli/types.h>

#include "dictionary.h"
#include "transform.h"

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
Expand Down
5 changes: 3 additions & 2 deletions brotli/dec/bit_reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@

#include "bit_reader.h"

#include "../common/platform.h"
#include <brotli/types.h>

#include "../common/platform.h"

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
Expand All @@ -36,7 +37,7 @@ BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br) {
/* Fixing alignment after unaligned BrotliFillWindow would result accumulator
overflow. If unalignment is caused by BrotliSafeReadBits, then there is
enough space in accumulator to fix alignment. */
if (!BROTLI_ALIGNED_READ) {
if (BROTLI_UNALIGNED_READ_FAST) {
aligned_read_mask = 0;
}
if (BrotliGetAvailableBits(br) == 0) {
Expand Down
29 changes: 19 additions & 10 deletions brotli/dec/bit_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@

#include <string.h> /* memcpy */

#include <brotli/types.h>

#include "../common/constants.h"
#include "../common/platform.h"
#include <brotli/types.h>

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
Expand Down Expand Up @@ -53,8 +54,8 @@ BROTLI_INTERNAL void BrotliInitBitReader(BrotliBitReader* const br);
/* Ensures that accumulator is not empty.
May consume up to sizeof(brotli_reg_t) - 1 bytes of input.
Returns BROTLI_FALSE if data is required but there is no input available.
For BROTLI_ALIGNED_READ this function also prepares bit reader for aligned
reading. */
For !BROTLI_UNALIGNED_READ_FAST this function also prepares bit reader for
aligned reading. */
BROTLI_INTERNAL BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br);

/* Fallback for BrotliSafeReadBits32. Extracted as noninlined method to unburden
Expand Down Expand Up @@ -107,7 +108,8 @@ static BROTLI_INLINE BROTLI_BOOL BrotliCheckInputAmount(
static BROTLI_INLINE void BrotliFillBitWindow(
BrotliBitReader* const br, uint32_t n_bits) {
#if (BROTLI_64_BITS)
if (!BROTLI_ALIGNED_READ && BROTLI_IS_CONSTANT(n_bits) && (n_bits <= 8)) {
if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&
(n_bits <= 8)) {
uint32_t bit_pos = br->bit_pos_;
if (bit_pos >= 56) {
br->val_ =
Expand All @@ -117,8 +119,8 @@ static BROTLI_INLINE void BrotliFillBitWindow(
br->avail_in -= 7;
br->next_in += 7;
}
} else if (
!BROTLI_ALIGNED_READ && BROTLI_IS_CONSTANT(n_bits) && (n_bits <= 16)) {
} else if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&
(n_bits <= 16)) {
uint32_t bit_pos = br->bit_pos_;
if (bit_pos >= 48) {
br->val_ =
Expand All @@ -140,7 +142,8 @@ static BROTLI_INLINE void BrotliFillBitWindow(
}
}
#else
if (!BROTLI_ALIGNED_READ && BROTLI_IS_CONSTANT(n_bits) && (n_bits <= 8)) {
if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&
(n_bits <= 8)) {
uint32_t bit_pos = br->bit_pos_;
if (bit_pos >= 24) {
br->val_ =
Expand Down Expand Up @@ -338,6 +341,11 @@ static BROTLI_INLINE BROTLI_BOOL BrotliJumpToByteBoundary(BrotliBitReader* br) {
return TO_BROTLI_BOOL(pad_bits == 0);
}

static BROTLI_INLINE void BrotliDropBytes(BrotliBitReader* br, size_t num) {
br->avail_in -= num;
br->next_in += num;
}

/* Copies remaining input bytes stored in the bit reader to the output. Value
|num| may not be larger than BrotliGetRemainingBytes. The bit reader must be
warmed up again after this. */
Expand All @@ -349,9 +357,10 @@ static BROTLI_INLINE void BrotliCopyBytes(uint8_t* dest,
++dest;
--num;
}
memcpy(dest, br->next_in, num);
br->avail_in -= num;
br->next_in += num;
if (num > 0) {
memcpy(dest, br->next_in, num);
BrotliDropBytes(br, num);
}
}

#if defined(__cplusplus) || defined(c_plusplus)
Expand Down
Loading

0 comments on commit 7aae1c5

Please sign in to comment.