Roll brotli to latest HEAD commit

The brotli release from 3 weeks ago (v1.2.1) was from a branch that
predates our previous version and is missing a lot of fixes from the
last year so this fast-forwards to the current HEAD commit.

Bug: 585364170
Change-Id: I8e659128646b294791e0f3c1cfd2c9a812e9a997
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8812621
Reviewed-by: Kenichi Ishibashi <bashi@chromium.org>
Commit-Queue: Patrick Meenan <pmeenan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1744715}
NOKEYCHECK=True
GitOrigin-RevId: 4b6765a3fe2e82458d1811bca527fa147ca4b8cf
diff --git a/BUILD.gn b/BUILD.gn
index 02237cc..d57b270 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -30,6 +30,7 @@
     "include/brotli/decode.h",
     "include/brotli/encode.h",
     "include/brotli/port.h",
+    "include/brotli/shared_dictionary.h",
     "include/brotli/types.h",
   ]
 }
@@ -88,6 +89,7 @@
   "enc/backward_references_hq.c",
   "enc/backward_references_hq.h",
   "enc/backward_references_inc.h",
+  "enc/backward_references_opt_inc.h",
   "enc/bit_cost.c",
   "enc/bit_cost.h",
   "enc/bit_cost_inc.h",
@@ -129,6 +131,7 @@
   "enc/hash_longest_match_inc.h",
   "enc/hash_longest_match_quickly_inc.h",
   "enc/hash_longest_match_simd_inc.h",
+  "enc/hash_longest_match_simd_opt_inc.h",
   "enc/hash_rolling_inc.h",
   "enc/hash_to_binary_tree_inc.h",
   "enc/histogram.c",
diff --git a/README.chromium b/README.chromium
index bee4db5..00acfaa 100644
--- a/README.chromium
+++ b/README.chromium
@@ -1,7 +1,7 @@
 Name: Brotli
 URL: https://github.com/google/brotli
-Version: cfa184a997ac19454d5a3ae97f6d600aac2445a6
-Revision: cfa184a997ac19454d5a3ae97f6d600aac2445a6
+Version: d89c4b1c52e25ddafe047bc78bbee5c1e24b1809
+Revision: d89c4b1c52e25ddafe047bc78bbee5c1e24b1809
 Update Mechanism: Manual
 License: MIT
 License File: LICENSE
diff --git a/common/platform.h b/common/platform.h
index e1254d5..d4d4723 100644
--- a/common/platform.h
+++ b/common/platform.h
@@ -24,6 +24,7 @@
 #ifndef BROTLI_COMMON_PLATFORM_H_
 #define BROTLI_COMMON_PLATFORM_H_
 
+#include <limits.h>
 #include <string.h>  /* IWYU pragma: export memcmp, memcpy, memset */
 #include <stdlib.h>  /* IWYU pragma: export exit, free, malloc */
 #include <sys/types.h>  /* should include endian.h for us */
@@ -522,6 +523,14 @@
 #define BROTLI_MIN(T, A, B) (brotli_min_ ## T((A), (B)))
 #define BROTLI_MAX(T, A, B) (brotli_max_ ## T((A), (B)))
 
+static BROTLI_INLINE int brotli_safe_add_int(int a, int b, int* result) {
+  if (b > 0 && a > INT_MAX - b) return 0;
+  if (b < 0 && a < INT_MIN - b) return 0;
+  *result = a + b;
+  return 1;
+}
+#define BROTLI_SAFE_ADD(T, A, B, R) (brotli_safe_add_ ## T((A), (B), (R)))
+
 #define BROTLI_SWAP(T, A, I, J) { \
   T __brotli_swap_tmp = (A)[(I)]; \
   (A)[(I)] = (A)[(J)];            \
@@ -607,6 +616,7 @@
   BROTLI_UNUSED(&brotli_max_uint32_t);
   BROTLI_UNUSED(&brotli_min_uint8_t);
   BROTLI_UNUSED(&brotli_max_uint8_t);
+  BROTLI_UNUSED(&brotli_safe_add_int);
   BROTLI_UNUSED(&BrotliDefaultAllocFunc);
   BROTLI_UNUSED(&BrotliDefaultFreeFunc);
   BROTLI_UNUSED(&BrotliRotateRight16);
@@ -615,6 +625,7 @@
 #if BROTLI_ENABLE_DUMP
   BROTLI_UNUSED(&BrotliDump);
 #endif
+}
 
 #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) && \
     !defined(_M_ARM64EC)
@@ -650,11 +661,12 @@
 
 /* The SIMD matchers are only faster at certain quality levels. */
 #if defined(_M_X64) && defined(BROTLI_TZCNT64)
+#define BROTLI_MAX_RECOMMENDED_SIMD_QUALITY 7
 #define BROTLI_MAX_SIMD_QUALITY 7
 #elif defined(BROTLI_TZCNT64)
-#define BROTLI_MAX_SIMD_QUALITY 6
+#define BROTLI_MAX_RECOMMENDED_SIMD_QUALITY 6
+#define BROTLI_MAX_SIMD_QUALITY 7
 #endif
-}
 
 #if defined(_MSC_VER)
 #define BROTLI_CRASH() __debugbreak(), (void)abort()
diff --git a/dec/decode.c b/dec/decode.c
index 19c7e02..1ab505e 100644
--- a/dec/decode.c
+++ b/dec/decode.c
@@ -11,6 +11,7 @@
 #include "../common/dictionary.h"
 #include "../common/platform.h"
 #include "../common/shared_dictionary_internal.h"
+#include <brotli/shared_dictionary.h>
 #include "../common/transform.h"
 #include "../common/version.h"
 #include "bit_reader.h"
@@ -481,6 +482,9 @@
                                                         uint8_t* ringbuffer,
                                                         int pos,
                                                         const int limit) {
+  const int kMaximalOverread = 4;
+  int pos_limit = limit;
+  int copies = 0;
   /* Calculate range where CheckInputAmount is always true.
      Start with the number of bytes we can read. */
   int64_t new_lim = br->guard_in - br->next_in;
@@ -488,9 +492,6 @@
   new_lim *= 8;
   /* At most 15 bits per symbol, so this is safe. */
   new_lim /= 15;
-  const int kMaximalOverread = 4;
-  int pos_limit = limit;
-  int copies = 0;
   if ((new_lim - kMaximalOverread) <= limit) {
     // Safe cast, since new_lim is already < num_steps
     pos_limit = (int)(new_lim - kMaximalOverread);
@@ -1317,7 +1318,7 @@
   return DecodeDistanceBlockSwitchInternal(0, s);
 }
 
-static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeDistanceBlockSwitch(
+static BROTLI_NOINLINE BrotliDecoderErrorCode SafeDecodeDistanceBlockSwitch(
     BrotliDecoderState* s) {
   return DecodeDistanceBlockSwitchInternal(1, s);
 }
@@ -1526,23 +1527,34 @@
 static BROTLI_BOOL AttachCompoundDictionary(
     BrotliDecoderState* state, const uint8_t* data, size_t size) {
   BrotliDecoderCompoundDictionary* addon = state->compound_dictionary;
+  /* Soft lie: no dictionary is attached; i.e. this call is not accounted
+   * towards SHARED_BROTLI_MAX_COMPOUND_DICTS limit. */
+  if (size == 0) return BROTLI_TRUE;
+  if (size > SHARED_BROTLI_MAX_RAW_DICT_SIZE) return BROTLI_FALSE;
   if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE;
   if (!addon) {
     addon = (BrotliDecoderCompoundDictionary*)BROTLI_DECODER_ALLOC(
         state, sizeof(BrotliDecoderCompoundDictionary));
     if (!addon) return BROTLI_FALSE;
-    addon->num_chunks = 0;
-    addon->total_size = 0;
-    addon->br_length = 0;
-    addon->br_copied = 0;
-    addon->block_bits = -1;
-    addon->chunk_offsets[0] = 0;
+    addon->num_chunks = 0u;
+    addon->block_bits = 255u;
+    addon->br_index = 0u;
+    addon->total_size = 0u;
+    addon->br_offset = 0u;
+    addon->br_length = 0u;
+    addon->br_copied = 0u;
+    addon->chunk_offsets[0] = 0u;
     state->compound_dictionary = addon;
   }
-  if (addon->num_chunks == 15) return BROTLI_FALSE;
+  if (addon->num_chunks == SHARED_BROTLI_MAX_COMPOUND_DICTS) {
+    return BROTLI_FALSE;
+  }
+  if (size > SHARED_BROTLI_MAX_RAW_DICT_SIZE - addon->total_size) {
+    return BROTLI_FALSE;
+  }
   addon->chunks[addon->num_chunks] = data;
   addon->num_chunks++;
-  addon->total_size += (int)size;
+  addon->total_size += (uint32_t)size;
   addon->chunk_offsets[addon->num_chunks] = addon->total_size;
   return BROTLI_TRUE;
 }
@@ -1550,41 +1562,51 @@
 static void EnsureCompoundDictionaryInitialized(BrotliDecoderState* state) {
   BrotliDecoderCompoundDictionary* addon = state->compound_dictionary;
   /* 256 = (1 << 8) slots in block map. */
-  int block_bits = 8;
-  int cursor = 0;
-  int index = 0;
-  if (addon->block_bits != -1) return;
-  while (((addon->total_size - 1) >> block_bits) != 0) block_bits++;
-  block_bits -= 8;
-  addon->block_bits = block_bits;
-  while (cursor < addon->total_size) {
-    while (addon->chunk_offsets[index + 1] < cursor) index++;
+  size_t block_bits = 8u;
+  uint32_t cursor = 0u;
+  size_t index = 0u;
+  uint32_t maximal_address = addon->total_size - 1u;
+  BROTLI_DCHECK(addon->total_size > 0u);
+  if (addon->block_bits != 255u) return;
+  while ((maximal_address >> block_bits) != 0u) block_bits++;
+  block_bits -= 8u;
+  addon->block_bits = (uint8_t)block_bits;
+  while (cursor <= maximal_address) {
+    /* We have sentinel value equal maximal_address + 1. */
+    while (addon->chunk_offsets[index + 1u] < cursor) index++;
     addon->block_map[cursor >> block_bits] = (uint8_t)index;
-    cursor += 1 << block_bits;
+    cursor += 1u << block_bits;
   }
+  /* Now if X is in the range [0..maximal_address] then
+   * block_map[X >> block_bits] is in [0..num_chunks). */
 }
 
 static BROTLI_BOOL InitializeCompoundDictionaryCopy(BrotliDecoderState* s,
-    int address, int length) {
+    uint32_t address, uint32_t length) {
   BrotliDecoderCompoundDictionary* addon = s->compound_dictionary;
-  int index;
+  size_t index;
+  BROTLI_DCHECK(addon->total_size > 0u);
+  BROTLI_DCHECK(address < addon->total_size);
+  BROTLI_DCHECK(length > 0u);
   EnsureCompoundDictionaryInitialized(s);
   index = addon->block_map[address >> addon->block_bits];
+  /* Several chunks might be mapped to the same block index. */
   while (address >= addon->chunk_offsets[index + 1]) index++;
-  if (addon->total_size < address + length) return BROTLI_FALSE;
+  /* Check that the whole chunk is within dictionary bounds. */
+  if (length > addon->total_size - address) return BROTLI_FALSE;
   /* Update the recent distances cache. */
   s->dist_rb[s->dist_rb_idx & 3] = s->distance_code;
   ++s->dist_rb_idx;
-  s->meta_block_remaining_len -= length;
-  addon->br_index = index;
+  s->meta_block_remaining_len -= (int)length;
+  addon->br_index = (uint16_t)index;
   addon->br_offset = address - addon->chunk_offsets[index];
   addon->br_length = length;
-  addon->br_copied = 0;
+  addon->br_copied = 0u;
   return BROTLI_TRUE;
 }
 
-static int GetCompoundDictionarySize(BrotliDecoderState* s) {
-  return s->compound_dictionary ? s->compound_dictionary->total_size : 0;
+static uint32_t GetCompoundDictionarySize(BrotliDecoderState* s) {
+  return s->compound_dictionary ? s->compound_dictionary->total_size : 0u;
 }
 
 static int CopyFromCompoundDictionary(BrotliDecoderState* s, int pos) {
@@ -1595,18 +1617,19 @@
     const uint8_t* copy_src =
         addon->chunks[addon->br_index] + addon->br_offset;
     int space = s->ringbuffer_size - pos;
-    int rem_chunk_length = (addon->chunk_offsets[addon->br_index + 1] -
-        addon->chunk_offsets[addon->br_index]) - addon->br_offset;
-    int length = addon->br_length - addon->br_copied;
+    uint32_t rem_chunk_length = (addon->chunk_offsets[addon->br_index + 1] -
+                                 addon->chunk_offsets[addon->br_index]) -
+                                addon->br_offset;
+    uint32_t length = addon->br_length - addon->br_copied;
     if (length > rem_chunk_length) length = rem_chunk_length;
-    if (length > space) length = space;
+    if (length > (uint32_t)space) length = (uint32_t)space;
     memcpy(copy_dst, copy_src, (size_t)length);
-    pos += length;
+    pos += (int)length;
     addon->br_offset += length;
     addon->br_copied += length;
     if (length == rem_chunk_length) {
       addon->br_index++;
-      addon->br_offset = 0;
+      addon->br_offset = 0u;
     }
     if (pos == s->ringbuffer_size) break;
   }
@@ -1985,7 +2008,7 @@
   int i = s->loop_counter;
   BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;
   BrotliBitReader* br = &s->br;
-  int compound_dictionary_size = GetCompoundDictionarySize(s);
+  uint32_t compound_dictionary_size = GetCompoundDictionarySize(s);
 
   if (!CheckInputAmount(safe, br)) {
     result = BROTLI_DECODER_NEEDS_MORE_INPUT;
@@ -2086,10 +2109,10 @@
       } while (--i != 0);
     } else { /* safe */
       do {
+        brotli_reg_t literal;
         if (BROTLI_PREDICT_FALSE(s->block_length[0] == 0)) {
           goto NextLiteralBlock;
         }
-        brotli_reg_t literal;
         if (!SafeReadSymbol(s->literal_htree, br, &literal)) {
           result = BROTLI_DECODER_NEEDS_MORE_INPUT;
           goto saveStateAndReturn;
@@ -2186,10 +2209,14 @@
           pos, s->distance_code, i, s->meta_block_remaining_len));
       return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DISTANCE);
     }
-    if (s->distance_code - s->max_distance - 1 < compound_dictionary_size) {
-      int address = compound_dictionary_size -
-          (s->distance_code - s->max_distance);
-      if (!InitializeCompoundDictionaryCopy(s, address, i)) {
+    /* Check that LZ77-dictionary address is non-negative. */
+    if ((uint32_t)(s->distance_code - s->max_distance) - 1u <
+        compound_dictionary_size) {
+      /* Given that `s->distance_code - s->max_distance > 0` we have `address`
+       * is strictly less than `compound_dictionary_size`. */
+      uint32_t address = compound_dictionary_size -
+                         (uint32_t)(s->distance_code - s->max_distance);
+      if (!InitializeCompoundDictionaryCopy(s, address, (uint32_t)i)) {
         return BROTLI_FAILURE(BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY);
       }
       pos += CopyFromCompoundDictionary(s, pos);
@@ -2197,6 +2224,9 @@
         s->state = BROTLI_STATE_COMMAND_POST_WRITE_1;
         goto saveStateAndReturn;
       }
+      /* In else branch we have:
+       * `s->distance_code - s->max_distance - 1 >= compound_dictionary_size`;
+       * that implies that `compound_dictionary_size` could be cast to int. */
     } else if (i >= SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH &&
                i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH) {
       uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask];
@@ -2208,8 +2238,8 @@
       const BrotliTransforms* transforms = s->dictionary->transforms[dict_id];
       int offset = (int)words->offsets_by_length[i];
       brotli_reg_t shift = words->size_bits_by_length[i];
-      int address =
-          s->distance_code - s->max_distance - 1 - compound_dictionary_size;
+      int address = s->distance_code - s->max_distance - 1 -
+                    (int)compound_dictionary_size;
       int mask = (int)BitMask(shift);
       int word_idx = address & mask;
       int transform_idx = address >> shift;
diff --git a/dec/state.h b/dec/state.h
index aa371fb..4fcdb4a 100644
--- a/dec/state.h
+++ b/dec/state.h
@@ -190,15 +190,15 @@
 
 /* BrotliDecoderState addon, used for Compound Dictionary functionality. */
 typedef struct BrotliDecoderCompoundDictionary {
-  int num_chunks;
-  int total_size;
-  int br_index;
-  int br_offset;
-  int br_length;
-  int br_copied;
+  uint8_t num_chunks;
+  uint8_t block_bits;
+  uint16_t br_index;
+  uint32_t total_size;
+  uint32_t br_offset;
+  uint32_t br_length;
+  uint32_t br_copied;
   const uint8_t* chunks[16];
-  int chunk_offsets[16];
-  int block_bits;
+  uint32_t chunk_offsets[16];
   uint8_t block_map[256];
 } BrotliDecoderCompoundDictionary;
 
diff --git a/enc/backward_references.c b/enc/backward_references.c
index b48dd85..1a7d3d0 100644
--- a/enc/backward_references.c
+++ b/enc/backward_references.c
@@ -18,6 +18,98 @@
 #include "params.h"
 #include "quality.h"  /* IWYU pragma: keep for inc */
 
+BROTLI_INTERNAL const BROTLI_MODEL("small")
+    uint8_t kIsBase64[256] = {
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+        0, 0, 0, 1, /* 43 '+', 47 '/' (45 '-' is 0) */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 48-57 '0'-'9' (61 '='
+                                                           is 0) */
+        0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 65-79 'A'-'O' */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 80-90 'P'-'Z' */
+        0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 97-111 'a'-'o' */
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 112-122 'p'-'z' */
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static const size_t kBase64TriggerLen = 8;
+
+static BROTLI_INLINE BROTLI_BOOL IsBase64Char(uint8_t c) {
+  return TO_BROTLI_BOOL(kIsBase64[c]);
+}
+
+static BROTLI_INLINE BROTLI_BOOL MatchTrigger(const uint8_t* ringbuffer,
+                                              size_t mask, size_t pos) {
+  const char* trigger = ";base64,";
+  size_t i;
+  for (i = 0; i < kBase64TriggerLen; ++i) {
+    if (ringbuffer[(pos + i) & mask] != trigger[i]) return BROTLI_FALSE;
+  }
+  return BROTLI_TRUE;
+}
+
+static const uint64_t kBase64Trigger64 =
+    BROTLI_MAKE_UINT64_T(0x2C343665u, 0x7361623Bu);
+
+static size_t FindNextBase64Trigger(const uint8_t* ringbuffer, size_t mask,
+                                    size_t pos, size_t end) {
+  while (pos + kBase64TriggerLen <= end) {
+    size_t ringbuffer_size = mask + 1;
+    size_t pos_index = pos & mask;
+    size_t contiguous_len = ringbuffer_size - pos_index;
+    size_t max_scan_len = end - pos;
+    size_t scan_len = BROTLI_MIN(size_t, contiguous_len, max_scan_len);
+
+    const uint8_t* p =
+        (const uint8_t*)memchr(&ringbuffer[pos_index], ';', scan_len);
+    if (p != NULL) {
+      size_t offset = (size_t)(p - &ringbuffer[pos_index]);
+      if (offset + kBase64TriggerLen <= scan_len) {
+        if (BROTLI_UNALIGNED_LOAD64LE(p) == kBase64Trigger64) {
+          return pos + offset;
+        }
+      } else if (pos + offset + kBase64TriggerLen <= end) {
+        if (MatchTrigger(ringbuffer, mask, pos + offset)) {
+          return pos + offset;
+        }
+      } else {
+        return end;
+      }
+      pos += offset + 1;
+    } else {
+      pos += scan_len;
+    }
+  }
+  return end;
+}
+
+static BROTLI_INLINE BROTLI_BOOL CompareRingbuffer(
+    const uint8_t* ringbuffer, size_t mask,
+    size_t pos1, size_t pos2, size_t len) {
+  size_t idx1 = pos1 & mask;
+  size_t idx2 = pos2 & mask;
+  if (idx1 + len <= mask + 1 && idx2 + len <= mask + 1) {
+    return TO_BROTLI_BOOL(
+        memcmp(&ringbuffer[idx1], &ringbuffer[idx2], len) == 0);
+  }
+  while (len > 0) {
+    size_t chunk1 = mask + 1 - (pos1 & mask);
+    size_t chunk2 = mask + 1 - (pos2 & mask);
+    size_t chunk = BROTLI_MIN(size_t, len, BROTLI_MIN(size_t, chunk1, chunk2));
+    if (memcmp(&ringbuffer[pos1 & mask], &ringbuffer[pos2 & mask], chunk) != 0) {
+      return BROTLI_FALSE;
+    }
+    pos1 += chunk;
+    pos2 += chunk;
+    len -= chunk;
+  }
+  return BROTLI_TRUE;
+}
+
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
 #endif
@@ -120,6 +212,11 @@
 #include "backward_references_inc.h"
 #undef HASHER
 
+#define HASHER() H59
+/* NOLINTNEXTLINE(build/include) */
+#include "backward_references_opt_inc.h"
+#undef HASHER
+
 #define HASHER() H68
 /* NOLINTNEXTLINE(build/include) */
 #include "backward_references_inc.h"
@@ -172,6 +269,10 @@
 /* NOLINTNEXTLINE(build/include) */
 #include "backward_references_inc.h"
 #undef HASHER
+#define HASHER() H59
+/* NOLINTNEXTLINE(build/include) */
+#include "backward_references_opt_inc.h"
+#undef HASHER
 #define HASHER() H68
 /* NOLINTNEXTLINE(build/include) */
 #include "backward_references_inc.h"
@@ -206,6 +307,7 @@
       CASE_(6)
 #if defined(BROTLI_MAX_SIMD_QUALITY)
       CASE_(58)
+      CASE_(59)
       CASE_(68)
 #endif
       CASE_(40)
diff --git a/enc/backward_references_hq.c b/enc/backward_references_hq.c
index 07e82d1..a4718b5 100644
--- a/enc/backward_references_hq.c
+++ b/enc/backward_references_hq.c
@@ -433,8 +433,6 @@
   const CompoundDictionary* addon = &params->dictionary.compound;
   size_t gap = addon->total_size;
 
-  BROTLI_DCHECK(cur_ix_masked + max_len <= ringbuffer_mask + 1);
-
   EvaluateNode(block_start + stream_offset, pos, max_backward_limit, gap,
       starting_dist_cache, model, queue, nodes);
 
diff --git a/enc/backward_references_inc.h b/enc/backward_references_inc.h
index 752c12e..7238fca 100644
--- a/enc/backward_references_inc.h
+++ b/enc/backward_references_inc.h
@@ -35,7 +35,145 @@
 
   FN(PrepareDistanceCache)(privat, dist_cache);
 
+  size_t next_base64_pos = pos_end;
+  /* End of a payload whose trigger was covered by a backward reference. */
+  size_t base64_end = 0;
+  if (params->base64_mode &&
+      hasher->common.num_base64_regions < params->max_base64_regions) {
+    next_base64_pos =
+        FindNextBase64Trigger(ringbuffer, ringbuffer_mask, position, pos_end);
+  }
   while (position + FN(HashTypeLength)() < pos_end) {
+    if (position >= next_base64_pos) {
+      if (position > next_base64_pos) {
+        /* A previous backward match jumped over the trigger position. Note
+           where that payload ends, then find the next trigger. */
+        size_t payload_end = next_base64_pos + kBase64TriggerLen;
+        while (payload_end < pos_end &&
+               IsBase64Char(ringbuffer[payload_end & ringbuffer_mask])) {
+          payload_end++;
+        }
+        if (payload_end - (next_base64_pos + kBase64TriggerLen) >=
+            params->min_base64_region_len) {
+          base64_end = payload_end;
+        }
+        next_base64_pos = FindNextBase64Trigger(ringbuffer, ringbuffer_mask,
+            BROTLI_MAX(size_t, position, payload_end), pos_end);
+        if (position < next_base64_pos) {
+          goto skip_base64_trigger;
+        }
+      }
+      /* Find where it ends */
+      size_t scan_pos = position + kBase64TriggerLen;
+      size_t first_equal_pos = 0;
+      while (scan_pos < pos_end) {
+        uint8_t c = ringbuffer[scan_pos & ringbuffer_mask];
+        if (IsBase64Char(c)) {
+          if (first_equal_pos != 0) {
+            scan_pos = first_equal_pos;
+            break;
+          }
+          scan_pos++;
+        } else if (c == '=') {
+          if (first_equal_pos == 0) {
+            first_equal_pos = scan_pos;
+          }
+          scan_pos++;
+        } else {
+          break;
+        }
+      }
+      /* Jump directly to the end of base64 block */
+      size_t start_pos = position + kBase64TriggerLen;
+      size_t length = scan_pos - start_pos;
+      /* Exclude '=' characters from the flat 6-bit entropy block */
+      while (length > 0 &&
+             ringbuffer[(start_pos + length - 1) & ringbuffer_mask] == '=') {
+        length--;
+      }
+      BROTLI_BOOL is_dupe = BROTLI_FALSE;
+      size_t copy_len = scan_pos - position;
+      size_t dupe_dist = 0;
+      if (length > 0 && hasher->common.num_base64_regions > 0) {
+        size_t r = hasher->common.num_base64_regions;
+        while (r > 0) {
+          --r;
+          size_t prev_start =
+              hasher->common.base64_regions[r].start_literal_pos;
+          size_t prev_length = hasher->common.base64_regions[r].length;
+          if (prev_length != length) {
+            continue;
+          }
+          size_t prev_pos = prev_start - kBase64TriggerLen;
+          size_t distance = position - prev_pos;
+          if (distance == 0 || distance > max_backward_limit) {
+            continue;
+          }
+          if (CompareRingbuffer(ringbuffer, ringbuffer_mask, prev_pos, position,
+                                copy_len)) {
+            is_dupe = BROTLI_TRUE;
+            dupe_dist = distance;
+            break;
+          }
+        }
+      }
+      if (is_dupe) {
+        size_t dictionary_start =
+            BROTLI_MIN(size_t, position + position_offset, max_backward_limit);
+        size_t distance_code =
+            ComputeDistanceCode(dupe_dist, dictionary_start + gap, dist_cache);
+        if ((dupe_dist <= (dictionary_start + gap)) && distance_code > 0) {
+          dist_cache[3] = dist_cache[2];
+          dist_cache[2] = dist_cache[1];
+          dist_cache[1] = dist_cache[0];
+          dist_cache[0] = (int)dupe_dist;
+          FN(PrepareDistanceCache)(privat, dist_cache);
+        }
+        InitCommand(commands++, &params->dist, insert_length, copy_len, 0,
+                    distance_code);
+        *num_literals += insert_length;
+        insert_length = 0;
+        position = scan_pos;
+        apply_random_heuristics =
+            position + 2 * copy_len + random_heuristics_window_size;
+        if (hasher->common.num_base64_regions < params->max_base64_regions) {
+          next_base64_pos = FindNextBase64Trigger(ringbuffer, ringbuffer_mask,
+                                                  position, pos_end);
+        } else {
+          next_base64_pos = pos_end;
+        }
+        continue;
+      }
+      if (length >= params->min_base64_region_len && length > 0) {
+        hasher->common.base64_regions[hasher->common.num_base64_regions]
+            .start_literal_pos = start_pos;
+        hasher->common.base64_regions[hasher->common.num_base64_regions]
+            .length = length;
+        hasher->common.num_base64_regions++;
+        insert_length += (scan_pos - position);
+        position = scan_pos;
+        if (hasher->common.num_base64_regions < params->max_base64_regions) {
+          next_base64_pos = FindNextBase64Trigger(ringbuffer, ringbuffer_mask,
+                                                  position, pos_end);
+        } else {
+          next_base64_pos = pos_end;
+        }
+        continue;
+      } else {
+        next_base64_pos = FindNextBase64Trigger(ringbuffer, ringbuffer_mask,
+                                                position + 1, pos_end);
+        goto skip_base64_trigger;
+      }
+    }
+  skip_base64_trigger:;
+    if (position < base64_end && position > apply_random_heuristics) {
+      /* No backward reference for a while inside the payload: the rest of it
+         is high-entropy (e.g. image data). Emit it as literals without
+         searching. */
+      insert_length += base64_end - position;
+      position = base64_end;
+      continue;
+    }
     size_t max_length = pos_end - position;
     size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit);
     size_t dictionary_start = BROTLI_MIN(size_t,
@@ -59,7 +197,7 @@
     FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id],
         ringbuffer, ringbuffer_mask, dist_cache, position, max_length,
         max_distance, dictionary_start + gap, params->dist.max_distance, &sr);
-    if (ENABLE_COMPOUND_DICTIONARY) {
+    if (ENABLE_COMPOUND_DICTIONARY && position >= base64_end) {
       LookupCompoundDictionaryMatch(&params->dictionary.compound, ringbuffer,
           ringbuffer_mask, dist_cache, position, max_length,
           dictionary_start, params->dist.max_distance, &sr);
@@ -90,7 +228,7 @@
             ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length,
             max_distance, dictionary_start + gap, params->dist.max_distance,
             &sr2);
-        if (ENABLE_COMPOUND_DICTIONARY) {
+        if (ENABLE_COMPOUND_DICTIONARY && position + 1 >= base64_end) {
           LookupCompoundDictionaryMatch(
               &params->dictionary.compound, ringbuffer,
               ringbuffer_mask, dist_cache, position + 1, max_length,
diff --git a/enc/backward_references_opt_inc.h b/enc/backward_references_opt_inc.h
new file mode 100644
index 0000000..3ad6755
--- /dev/null
+++ b/enc/backward_references_opt_inc.h
@@ -0,0 +1,265 @@
+/* NOLINT(build/header_guard) */
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+   Distributed under MIT license.
+   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* template parameters: EXPORT_FN, FN */
+
+static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)(
+    size_t num_bytes, size_t position,
+    const uint8_t* ringbuffer, size_t ringbuffer_mask,
+    ContextLut literal_context_lut, const BrotliEncoderParams* params,
+    Hasher* hasher, int* dist_cache, size_t* last_insert_len,
+    Command* commands, size_t* num_commands, size_t* num_literals) {
+  HASHER()* privat = &hasher->privat.FN(_);
+  /* Set maximum distance, see section 9.1. of the spec. */
+  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
+  const size_t position_offset = params->stream_offset;
+
+  const Command* const orig_commands = commands;
+  size_t insert_length = *last_insert_len;
+  const size_t pos_end = position + num_bytes;
+  const size_t store_end = num_bytes >= FN(StoreLookahead)() ?
+      position + num_bytes - FN(StoreLookahead)() + 1 : position;
+
+  /* For speed up heuristics for random data. */
+  const size_t random_heuristics_window_size =
+      LiteralSpreeLengthForSparseSearch(params);
+  size_t apply_random_heuristics = position + random_heuristics_window_size;
+  const size_t gap = params->dictionary.compound.total_size;
+  /* Compound-dictionary probe state: written by the prefetch helper before
+     each FindLongestMatch, consumed by the lookup after it. */
+  PreparedDictionaryProbe dict_probes[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1];
+
+  /* Minimum score to accept a backward reference. */
+  const score_t kMinScore = BROTLI_SCORE_BASE + 100;
+
+  FN(PrepareDistanceCache)(privat, dist_cache);
+
+  size_t next_base64_pos = pos_end;
+  if (params->base64_mode &&
+      hasher->common.num_base64_regions < params->max_base64_regions) {
+    next_base64_pos =
+        FindNextBase64Trigger(ringbuffer, ringbuffer_mask, position, pos_end);
+  }
+  while (position + FN(HashTypeLength)() < pos_end) {
+    if (position >= next_base64_pos) {
+      /* Find where it ends */
+      size_t scan_pos = position + kBase64TriggerLen;
+      size_t first_equal_pos = 0;
+      while (scan_pos < pos_end) {
+        uint8_t c = ringbuffer[scan_pos & ringbuffer_mask];
+        if (IsBase64Char(c)) {
+          if (first_equal_pos != 0) {
+            scan_pos = first_equal_pos;
+            break;
+          }
+          scan_pos++;
+        } else if (c == '=') {
+          if (first_equal_pos == 0) {
+            first_equal_pos = scan_pos;
+          }
+          scan_pos++;
+        } else {
+          break;
+        }
+      }
+      /* Jump directly to the end of base64 block */
+      /* Skip the ';base64,' trigger */
+      size_t start_pos = position + kBase64TriggerLen;
+      size_t length = scan_pos - start_pos;
+      /* Exclude '=' characters from the flat 6-bit entropy block */
+      while (length > 0 &&
+             ringbuffer[(start_pos + length - 1) & ringbuffer_mask] == '=') {
+        length--;
+      }
+      if (length > 0) {
+        hasher->common.base64_regions[hasher->common.num_base64_regions]
+            .start_literal_pos = start_pos;
+        hasher->common.base64_regions[hasher->common.num_base64_regions]
+            .length = length;
+        hasher->common.num_base64_regions++;
+      }
+      insert_length += (scan_pos - position);
+      position = scan_pos;
+      if (hasher->common.num_base64_regions < params->max_base64_regions) {
+        next_base64_pos = FindNextBase64Trigger(ringbuffer, ringbuffer_mask,
+                                                position, pos_end);
+      } else {
+        next_base64_pos = pos_end;
+      }
+      continue;
+    }
+    size_t max_length = pos_end - position;
+    size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit);
+    size_t dictionary_start = BROTLI_MIN(size_t,
+        position + position_offset, max_backward_limit);
+    HasherSearchResult sr;
+    int dict_id = 0;
+    uint8_t p1 = 0;
+    uint8_t p2 = 0;
+    if (params->dictionary.contextual.context_based) {
+      p1 = position >= 1 ?
+          ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0;
+      p2 = position >= 2 ?
+          ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0;
+      dict_id = params->dictionary.contextual.context_map[
+          BROTLI_CONTEXT(p1, p2, literal_context_lut)];
+    }
+    sr.len = 0;
+    sr.len_code_delta = 0;
+    sr.distance = 0;
+    sr.score = kMinScore;
+    if (ENABLE_COMPOUND_DICTIONARY) {
+      PrefetchCompoundDictionaryMatchOpt(&params->dictionary.compound,
+          ringbuffer, ringbuffer_mask, position, dict_probes);
+    }
+    FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id],
+        ringbuffer, ringbuffer_mask, dist_cache, position, max_length,
+        max_distance, dictionary_start + gap, params->dist.max_distance, &sr);
+    if (ENABLE_COMPOUND_DICTIONARY) {
+      LookupCompoundDictionaryMatchOpt(
+          &params->dictionary.compound, dict_probes, ringbuffer,
+          ringbuffer_mask, dist_cache, position, max_length, dictionary_start,
+          params->dist.max_distance, &sr);
+    }
+    if (sr.score > kMinScore) {
+      /* Found a match. Let's look for something even better ahead. */
+      int delayed_backward_references_in_row = 0;
+      --max_length;
+      for (;; --max_length) {
+        const score_t cost_diff_lazy = 175;
+        HasherSearchResult sr2;
+        sr2.len =
+            params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH
+                ? BROTLI_MIN(size_t, sr.len - 1, max_length)
+                : BROTLI_MIN(size_t,
+                             MinimumBetterLength(sr.score + cost_diff_lazy - 1),
+                             max_length);
+        sr2.len_code_delta = 0;
+        sr2.distance = 0;
+        sr2.score = kMinScore;
+        max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit);
+        dictionary_start = BROTLI_MIN(size_t,
+            position + 1 + position_offset, max_backward_limit);
+        if (params->dictionary.contextual.context_based) {
+          p2 = p1;
+          p1 = ringbuffer[position & ringbuffer_mask];
+          dict_id = params->dictionary.contextual.context_map[
+              BROTLI_CONTEXT(p1, p2, literal_context_lut)];
+        }
+        if (ENABLE_COMPOUND_DICTIONARY) {
+          PrefetchCompoundDictionaryMatchOpt(&params->dictionary.compound,
+              ringbuffer, ringbuffer_mask, position + 1, dict_probes);
+        }
+        FN(FindLongestMatch)(privat,
+            params->dictionary.contextual.dict[dict_id],
+            ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length,
+            max_distance, dictionary_start + gap, params->dist.max_distance,
+            &sr2);
+        if (ENABLE_COMPOUND_DICTIONARY) {
+          LookupCompoundDictionaryMatchOpt(
+              &params->dictionary.compound, dict_probes, ringbuffer,
+              ringbuffer_mask, dist_cache, position + 1, max_length,
+              dictionary_start, params->dist.max_distance, &sr2);
+        }
+        if (sr2.score >= sr.score + cost_diff_lazy) {
+          /* Ok, let's just write one byte for now and start a match from the
+             next byte. */
+          ++position;
+          ++insert_length;
+          sr = sr2;
+          if (++delayed_backward_references_in_row < 4 &&
+              position + FN(HashTypeLength)() < pos_end) {
+            continue;
+          }
+        }
+        break;
+      }
+      apply_random_heuristics =
+          position + 2 * sr.len + random_heuristics_window_size;
+      dictionary_start = BROTLI_MIN(size_t,
+          position + position_offset, max_backward_limit);
+      {
+        /* The first 16 codes are special short-codes,
+           and the minimum offset is 1. */
+        size_t distance_code = ComputeDistanceCode(
+            sr.distance, dictionary_start + gap, dist_cache);
+        if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) {
+          dist_cache[3] = dist_cache[2];
+          dist_cache[2] = dist_cache[1];
+          dist_cache[1] = dist_cache[0];
+          dist_cache[0] = (int)sr.distance;
+          FN(PrepareDistanceCache)(privat, dist_cache);
+        }
+        InitCommand(commands++, &params->dist, insert_length,
+            sr.len, sr.len_code_delta, distance_code);
+      }
+      *num_literals += insert_length;
+      insert_length = 0;
+      /* Put the hash keys into the table, if there are enough bytes left.
+         Depending on the hasher implementation, it can push all positions
+         in the given range or only a subset of them.
+         Avoid hash poisoning with RLE data. */
+      {
+        size_t range_start = position + 2;
+        size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end);
+        if (sr.distance < (sr.len >> 2)) {
+          range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t,
+              range_start, position + sr.len - (sr.distance << 2)));
+        }
+        /* The next search is at position + sr.len (the one-ahead in the
+           prefetch helper covers only the cur_ix + 1 successor): prefetch its
+           dictionary heads[] line before the StoreRange loop. */
+        if (ENABLE_COMPOUND_DICTIONARY) {
+          PrefetchCompoundDictionaryHeadsOpt(&params->dictionary.compound,
+              ringbuffer, ringbuffer_mask, range_end);
+        }
+        FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start,
+                       range_end);
+      }
+      position += sr.len;
+    } else {
+      ++insert_length;
+      ++position;
+      /* If we have not seen matches for a long time, we can skip some
+         match lookups. Unsuccessful match lookups are very very expensive
+         and this kind of a heuristic speeds up compression quite
+         a lot. */
+      if (position > apply_random_heuristics) {
+        /* Going through uncompressible data, jump. */
+        if (position >
+            apply_random_heuristics + 4 * random_heuristics_window_size) {
+          /* It is quite a long time since we saw a copy, so we assume
+             that this data is not compressible, and store hashes less
+             often. Hashes of non compressible data are less likely to
+             turn out to be useful in the future, too, so we store less of
+             them to not to flood out the hash table of good compressible
+             data. */
+          const size_t kMargin =
+              BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4);
+          size_t pos_jump =
+              BROTLI_MIN(size_t, position + 16, pos_end - kMargin);
+          for (; position < pos_jump; position += 4) {
+            FN(Store)(privat, ringbuffer, ringbuffer_mask, position);
+            insert_length += 4;
+          }
+        } else {
+          const size_t kMargin =
+              BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2);
+          size_t pos_jump =
+              BROTLI_MIN(size_t, position + 8, pos_end - kMargin);
+          for (; position < pos_jump; position += 2) {
+            FN(Store)(privat, ringbuffer, ringbuffer_mask, position);
+            insert_length += 2;
+          }
+        }
+      }
+    }
+  }
+  insert_length += pos_end - position;
+  *last_insert_len = insert_length;
+  *num_commands += (size_t)(commands - orig_commands);
+}
diff --git a/enc/block_encoder_inc.h b/enc/block_encoder_inc.h
index 8cbd5ea..5a90658 100644
--- a/enc/block_encoder_inc.h
+++ b/enc/block_encoder_inc.h
@@ -1,20 +1,14 @@
-/* NOLINT(build/header_guard) */
-/* Copyright 2014 Google Inc. All Rights Reserved.
-
-   Distributed under MIT license.
-   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
-*/
-
-/* template parameters: FN */
+#if !defined(BROTLI_BASE64_LUT_)
+#define BROTLI_BASE64_LUT_
+BROTLI_INTERNAL extern const BROTLI_MODEL("small") uint8_t kIsBase64[256];
+#endif
 
 #define HistogramType FN(Histogram)
 
-/* Creates entropy codes for all block types and stores them to the bit
-   stream. */
-static void FN(BuildAndStoreEntropyCodes)(MemoryManager* m, BlockEncoder* self,
-    const HistogramType* histograms, const size_t histograms_size,
-    const size_t alphabet_size, HuffmanTree* tree,
-    size_t* storage_ix, uint8_t* storage) {
+static void FN(BuildAndStoreEntropyCodes)(
+    MemoryManager* m, BlockEncoder* self, const HistogramType* histograms,
+    const size_t histograms_size, const size_t alphabet_size, HuffmanTree* tree,
+    const uint8_t* is_base64_histogram, size_t* storage_ix, uint8_t* storage) {
   const size_t table_size = histograms_size * self->histogram_length_;
   self->depths_ = BROTLI_ALLOC(m, uint8_t, table_size);
   self->bits_ = BROTLI_ALLOC(m, uint16_t, table_size);
@@ -24,9 +18,37 @@
     size_t i;
     for (i = 0; i < histograms_size; ++i) {
       size_t ix = i * self->histogram_length_;
-      BuildAndStoreHuffmanTree(&histograms[i].data_[0], self->histogram_length_,
-          alphabet_size, tree, &self->depths_[ix], &self->bits_[ix],
-          storage_ix, storage);
+      if (self->histogram_length_ == 256 && is_base64_histogram && i < 256 &&
+          is_base64_histogram[i]) {
+        size_t k;
+        BROTLI_BOOL all_base64 = BROTLI_TRUE;
+        for (k = 0; k < 256; ++k) {
+          if (histograms[i].data_[k] > 0 && !kIsBase64[k]) {
+            all_base64 = BROTLI_FALSE;
+            break;
+          }
+        }
+        if (all_base64) {
+          memset(&self->depths_[ix], 0, 256);
+          for (k = 0; k < 256; ++k) {
+            if (kIsBase64[k]) {
+              self->depths_[ix + k] = 6;
+            }
+          }
+          BrotliConvertBitDepthsToSymbols(&self->depths_[ix], 256,
+                                          &self->bits_[ix]);
+          BrotliStoreHuffmanTree(&self->depths_[ix], 256, tree, storage_ix,
+                                 storage);
+        } else {
+          BuildAndStoreHuffmanTree(
+              &histograms[i].data_[0], self->histogram_length_, alphabet_size,
+              tree, &self->depths_[ix], &self->bits_[ix], storage_ix, storage);
+        }
+      } else {
+        BuildAndStoreHuffmanTree(
+            &histograms[i].data_[0], self->histogram_length_, alphabet_size,
+            tree, &self->depths_[ix], &self->bits_[ix], storage_ix, storage);
+      }
     }
   }
 }
diff --git a/enc/brotli_bit_stream.c b/enc/brotli_bit_stream.c
index 1e9e946..10727e0 100644
--- a/enc/brotli_bit_stream.c
+++ b/enc/brotli_bit_stream.c
@@ -1017,16 +1017,44 @@
     if (BROTLI_IS_OOM(m)) return;
   }
 
-  BuildAndStoreEntropyCodesLiteral(m, literal_enc, mb->literal_histograms,
-      mb->literal_histograms_size, BROTLI_NUM_LITERAL_SYMBOLS, tree,
-      storage_ix, storage);
+  {
+    uint8_t is_base64_histogram[256] = {0};
+    size_t max_type_id = BROTLI_MIN(size_t, mb->literal_split.num_types, 256);
+    size_t type_id;
+    for (type_id = 0; type_id < max_type_id; ++type_id) {
+      if (mb->literal_is_base64[type_id >> 3] & (1u << (type_id & 7))) {
+        if (mb->literal_context_map) {
+          size_t j;
+          for (j = 0; j < (1u << BROTLI_LITERAL_CONTEXT_BITS); ++j) {
+            uint32_t b64_histo_id =
+                mb->literal_context_map[(type_id << BROTLI_LITERAL_CONTEXT_BITS) + j];
+            if (b64_histo_id < 256) {
+              is_base64_histogram[b64_histo_id] = 1;
+            }
+          }
+        } else {
+          uint32_t b64_histo_id = (uint32_t)type_id;
+          if (b64_histo_id < 256) {
+            is_base64_histogram[b64_histo_id] = 1;
+          }
+        }
+      }
+    }
+
+    BuildAndStoreEntropyCodesLiteral(m, literal_enc, mb->literal_histograms,
+        mb->literal_histograms_size, BROTLI_NUM_LITERAL_SYMBOLS, tree,
+        is_base64_histogram,
+        storage_ix, storage);
+  }
   if (BROTLI_IS_OOM(m)) return;
   BuildAndStoreEntropyCodesCommand(m, command_enc, mb->command_histograms,
       mb->command_histograms_size, BROTLI_NUM_COMMAND_SYMBOLS, tree,
+      NULL,
       storage_ix, storage);
   if (BROTLI_IS_OOM(m)) return;
   BuildAndStoreEntropyCodesDistance(m, distance_enc, mb->distance_histograms,
       mb->distance_histograms_size, num_distance_symbols, tree,
+      NULL,
       storage_ix, storage);
   if (BROTLI_IS_OOM(m)) return;
   BROTLI_FREE(m, tree);
diff --git a/enc/compound_dictionary.c b/enc/compound_dictionary.c
index bf323a4..23166c8 100644
--- a/enc/compound_dictionary.c
+++ b/enc/compound_dictionary.c
@@ -155,6 +155,9 @@
   uint32_t hash_bits = 40;
   uint16_t bucket_limit = 32;
   size_t volume = 16u << bucket_bits;
+  if (source_size > SHARED_BROTLI_MAX_RAW_DICT_SIZE) {
+    return NULL;
+  }
   /* Tune parameters to fit dictionary size. */
   while (volume < source_size && bucket_bits < 22) {
     bucket_bits++;
@@ -183,6 +186,9 @@
   if (!dictionary) return BROTLI_FALSE;
 
   length = dictionary->source_size;
+  if (length > SHARED_BROTLI_MAX_RAW_DICT_SIZE - compound->total_size) {
+    return BROTLI_FALSE;
+  }
   index = compound->num_chunks;
   compound->total_size += length;
   compound->chunks[index] = dictionary;
@@ -199,6 +205,17 @@
       compound->chunk_source[index] =
           (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail);
     }
+    {
+      PreparedDictionaryView* view = &compound->chunk_views[index];
+      view->slot_offsets = slot_offsets;
+      view->heads = heads;
+      view->items = items;
+      view->source = compound->chunk_source[index];
+      view->source_size = dictionary->source_size;
+      view->hash_shift = 64u - dictionary->bucket_bits;
+      view->slot_mask = (~((uint32_t)0U)) >> (32 - dictionary->slot_bits);
+      view->hash_mask = (~((uint64_t)0U)) >> (64 - dictionary->hash_bits);
+    }
   }
   compound->num_chunks++;
   return BROTLI_TRUE;
diff --git a/enc/compound_dictionary.h b/enc/compound_dictionary.h
index 686f92f..240a7f9 100644
--- a/enc/compound_dictionary.h
+++ b/enc/compound_dictionary.h
@@ -51,12 +51,28 @@
 BROTLI_INTERNAL void DestroyPreparedDictionary(MemoryManager* m,
     PreparedDictionary* dictionary);
 
+/* A derived view of a PreparedDictionary, optimized for faster lookup.  Used by
+ * the optimized H59 hasher.  Its fields are a pure function of
+ * PreparedDictionary's so we can generate it at attach time. */
+typedef struct PreparedDictionaryView {
+  const uint32_t* slot_offsets;
+  const uint16_t* heads;
+  const uint32_t* items;
+  const uint8_t* source;
+  uint32_t source_size;
+  uint32_t hash_shift;  /* 64 - bucket_bits */
+  uint32_t slot_mask;
+  uint64_t hash_mask;
+} PreparedDictionaryView;
+
 typedef struct CompoundDictionary {
   /* LZ77 prefix, compound dictionary */
   size_t num_chunks;
   size_t total_size;
   /* Client instances. */
   const PreparedDictionary* chunks[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1];
+  /* TODO: const? */
+  PreparedDictionaryView chunk_views[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1];
   const uint8_t* chunk_source[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1];
   size_t chunk_offsets[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1];
 
diff --git a/enc/encode.c b/enc/encode.c
index 9e72744..44b447a 100644
--- a/enc/encode.c
+++ b/enc/encode.c
@@ -105,6 +105,28 @@
       state->params.stream_offset = value;
       return BROTLI_TRUE;
 
+    case BROTLI_PARAM_BASE64_MODE:
+      state->params.base64_mode = (int)(value & 1);
+      return BROTLI_TRUE;
+
+    case BROTLI_PARAM_MAX_BASE64_REGIONS:
+      state->params.max_base64_regions = value;
+      return BROTLI_TRUE;
+
+    case BROTLI_PARAM_MIN_BASE64_REGION_LEN:
+      state->params.min_base64_region_len = value;
+      return BROTLI_TRUE;
+
+    case BROTLI_PARAM_SIMD_HASHER:
+      if (value > 2) return BROTLI_FALSE;
+      state->params.simd_hasher = (BrotliEncoderSimdHasher)value;
+      return BROTLI_TRUE;
+
+    case BROTLI_PARAM_HASHER_OPT:
+      if ((value != 0) && (value != 1)) return BROTLI_FALSE;
+      state->params.hasher_opt = TO_BROTLI_BOOL(value);
+      return BROTLI_TRUE;
+
     default: return BROTLI_FALSE;
   }
 }
@@ -488,6 +510,8 @@
                                    const uint64_t last_flush_pos,
                                    const size_t bytes,
                                    const BROTLI_BOOL is_last,
+                                   const Base64Region* base64_regions,
+                                   size_t num_base64_regions,
                                    ContextType literal_context_mode,
                                    const BrotliEncoderParams* params,
                                    const uint8_t prev_byte,
@@ -556,11 +580,14 @@
         BROTLI_FREE(m, arena);
       }
       BrotliBuildMetaBlockGreedy(m, data, wrapped_last_flush_pos, mask,
+          base64_regions, num_base64_regions,
           prev_byte, prev_byte2, literal_context_lut, num_literal_contexts,
           literal_context_map, commands, num_commands, &mb);
       if (BROTLI_IS_OOM(m)) return;
     } else {
-      BrotliBuildMetaBlock(m, data, wrapped_last_flush_pos, mask, &block_params,
+      BrotliBuildMetaBlock(m, data, wrapped_last_flush_pos, mask,
+                           base64_regions, num_base64_regions,
+                           &block_params,
                            prev_byte, prev_byte2,
                            commands, num_commands,
                            literal_context_mode,
@@ -688,6 +715,11 @@
   params->size_hint = 0;
   params->disable_literal_context_modeling = BROTLI_FALSE;
   BrotliInitSharedEncoderDictionary(&params->dictionary);
+  params->base64_mode = (int)BROTLI_DEFAULT_BASE64_MODE;
+  params->max_base64_regions = BROTLI_DEFAULT_MAX_BASE64_REGIONS;
+  params->min_base64_region_len = BROTLI_DEFAULT_MIN_BASE64_REGION_LEN;
+  params->simd_hasher = BROTLI_DEFAULT_SIMD_HASHER;
+  params->hasher_opt = BROTLI_FALSE;
   params->dist.distance_postfix_bits = 0;
   params->dist.num_direct_distance_codes = 0;
   params->dist.alphabet_size_max =
@@ -757,15 +789,17 @@
   /* Save the state of the distance cache in case we need to restore it for
      emitting an uncompressed block. */
   memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_));
+  s->hasher_.common.num_base64_regions = 0;
 }
 
 BrotliEncoderState* BrotliEncoderCreateInstance(
     brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
+  BrotliEncoderState* state;
   BROTLI_BOOL healthy = BrotliEncoderEnsureStaticInit();
   if (!healthy) {
     return 0;
   }
-  BrotliEncoderState* state = (BrotliEncoderState*)BrotliBootstrapAlloc(
+  state = (BrotliEncoderState*)BrotliBootstrapAlloc(
       sizeof(BrotliEncoderState), alloc_func, free_func, opaque);
   if (state == NULL) {
     /* BROTLI_DUMP(); */
@@ -1169,10 +1203,12 @@
     storage[1] = (uint8_t)(s->last_bytes_ >> 8);
     WriteMetaBlockInternal(
         m, data, mask, s->last_flush_pos_, metablock_size, is_last,
+        s->hasher_.common.base64_regions, s->hasher_.common.num_base64_regions,
         literal_context_mode, &s->params, s->prev_byte_, s->prev_byte2_,
         s->num_literals_, s->num_commands_, s->commands_, s->saved_dist_cache_,
         s->dist_cache_, &storage_ix, storage);
     if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
+    s->hasher_.common.num_base64_regions = 0;
     s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]);
     s->last_bytes_bits_ = storage_ix & 7u;
     s->last_flush_pos_ = s->input_pos_;
diff --git a/enc/hash.h b/enc/hash.h
index eb9e455..0340611 100644
--- a/enc/hash.h
+++ b/enc/hash.h
@@ -29,6 +29,11 @@
 #endif
 
 typedef struct {
+  size_t start_literal_pos;
+  size_t length;
+} Base64Region;
+
+typedef struct {
   /**
    * Dynamically allocated areas; regular hasher uses one or two allocations;
    * "composite" hasher uses up to 4 allocations.
@@ -52,6 +57,9 @@
    * data initialization (using input ringbuffer).
    */
   BROTLI_BOOL is_prepared_;
+
+  Base64Region* base64_regions;
+  size_t num_base64_regions;
 } HasherCommon;
 
 #define score_t size_t
@@ -118,6 +126,13 @@
       BROTLI_DISTANCE_BIT_PENALTY * Log2FloorNonZero(backward_reference_offset);
 }
 
+/* Returns the minimum length of a backward reference that will improve on the
+ provided score.  We conservatively assume that the match will be a last
+ distance match, the best case scenario for the next match.*/
+static BROTLI_INLINE size_t MinimumBetterLength(score_t score) {
+  return (score - (BROTLI_SCORE_BASE + 15)) / BROTLI_LITERAL_BYTE_SCORE;
+}
+
 static BROTLI_INLINE score_t BackwardReferenceScoreUsingLastDistance(
     size_t copy_length) {
   return BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length +
@@ -283,6 +298,10 @@
 #include "hash_longest_match_simd_inc.h" /* NOLINT(build/include) */
 #undef HASHER
 
+#define HASHER() H59
+#include "hash_longest_match_simd_opt_inc.h" /* NOLINT(build/include) */
+#undef HASHER
+
 #define HASHER() H68
 #include "hash_longest_match64_simd_inc.h" /* NOLINT(build/include) */
 #undef HASHER
@@ -381,7 +400,7 @@
 
 #if defined(BROTLI_MAX_SIMD_QUALITY)
 #define FOR_SIMPLE_HASHERS(H) \
-  H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54) H(58) H(68)
+  H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54) H(58) H(59) H(68)
 #else
 #define FOR_SIMPLE_HASHERS(H) \
   H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54)
@@ -408,6 +427,7 @@
   hasher->common.extra[1] = NULL;
   hasher->common.extra[2] = NULL;
   hasher->common.extra[3] = NULL;
+  hasher->common.base64_regions = NULL;
 }
 
 static BROTLI_INLINE void DestroyHasher(MemoryManager* m, Hasher* hasher) {
@@ -415,6 +435,9 @@
   if (hasher->common.extra[1] != NULL) BROTLI_FREE(m, hasher->common.extra[1]);
   if (hasher->common.extra[2] != NULL) BROTLI_FREE(m, hasher->common.extra[2]);
   if (hasher->common.extra[3] != NULL) BROTLI_FREE(m, hasher->common.extra[3]);
+  if (hasher->common.base64_regions != NULL) {
+    BROTLI_FREE(m, hasher->common.base64_regions);
+  }
 }
 
 static BROTLI_INLINE void HasherReset(Hasher* hasher) {
@@ -452,6 +475,13 @@
       hasher->common.extra[i] = BROTLI_ALLOC(m, uint8_t, alloc_size[i]);
       if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(hasher->common.extra[i])) return;
     }
+    if (params->base64_mode && params->max_base64_regions > 0) {
+      hasher->common.base64_regions = BROTLI_ALLOC(
+          m, Base64Region, params->max_base64_regions);
+      if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(hasher->common.base64_regions)) {
+        return;
+      }
+    }
     switch (hasher->common.params.type) {
 #define INITIALIZE_(N)                        \
       case N:                                 \
@@ -545,8 +575,6 @@
     source = (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail);
   }
 
-  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask + 1);
-
   for (i = 0; i < 4; ++i) {
     const size_t distance = (size_t)distance_cache[i];
     size_t offset;
@@ -656,8 +684,6 @@
     source = (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail);
   }
 
-  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask + 1);
-
   while (item == 0) {
     size_t offset;
     size_t distance;
@@ -728,6 +754,188 @@
   return total_found;
 }
 
+/* Struct for handing state between the prefetch and find calls.  Avoids
+ * recalculating the hash and dependent variables. */
+typedef struct PreparedDictionaryProbe {
+  const uint32_t* chain;
+  uint32_t item;
+} PreparedDictionaryProbe;
+
+static BROTLI_INLINE void PrefetchCompoundDictionaryMatchOpt(
+    const CompoundDictionary* addon, const uint8_t* BROTLI_RESTRICT data,
+    const size_t ring_buffer_mask, const size_t cur_ix,
+    PreparedDictionaryProbe* BROTLI_RESTRICT probes) {
+  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
+  const uint64_t bytes = BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix_masked]);
+  size_t d;
+  for (d = 0; d < addon->num_chunks; ++d) {
+    const PreparedDictionaryView* view = &addon->chunk_views[d];
+    const uint64_t h =
+        (bytes & view->hash_mask) * kPreparedDictionaryHashMul64Long;
+    const uint32_t key = (uint32_t)(h >> view->hash_shift);
+    const uint32_t slot = key & view->slot_mask;
+    const uint32_t head = view->heads[key];
+    /* Deliberately branchless - if head == 0xFFFF (no items), we'll prefetch
+     * some garbage address.  Prefetch can't fault, so this is safe.*/
+    const uint32_t* chain = &view->items[view->slot_offsets[slot] + head];
+    PREFETCH_L1(chain);
+    probes[d].chain = chain;
+    probes[d].item = (head == 0xFFFF) ? 1 : 0;
+
+    /* One-ahead for the heads[] line of the next probe: the next search is
+       at cur_ix + 1 (the lazy search, or the next position after a miss),
+       whose hash covers bytes cur_ix+1.. -- the same 8-byte load shifted by
+       one byte (hash_mask spans at most 56 bits for this to be exact; a
+       mismatch would only waste the prefetch). The heads[key] load above
+       misses L1 ~94% of the time (mostly L3 fills). */
+    {
+      const uint64_t h1 =
+          ((bytes >> 8) & view->hash_mask) * kPreparedDictionaryHashMul64Long;
+      PREFETCH_L1(&view->heads[(uint32_t)(h1 >> view->hash_shift)]);
+    }
+  }
+}
+
+/* The heads[] half of PrefetchCompoundDictionaryMatchOpt: hash the position
+   and prefetch its heads[] line, with no dependent items[] load. Used at the
+   commit site, where the successor position is known but the probe state for
+   it would not survive the intervening StoreRange. */
+static BROTLI_INLINE void PrefetchCompoundDictionaryHeadsOpt(
+    const CompoundDictionary* addon, const uint8_t* BROTLI_RESTRICT data,
+    const size_t ring_buffer_mask, const size_t cur_ix) {
+  const uint64_t bytes =
+      BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix & ring_buffer_mask]);
+  size_t d;
+  for (d = 0; d < addon->num_chunks; ++d) {
+    const PreparedDictionaryView* view = &addon->chunk_views[d];
+    const uint64_t h =
+        (bytes & view->hash_mask) * kPreparedDictionaryHashMul64Long;
+    PREFETCH_L1(&view->heads[(uint32_t)(h >> view->hash_shift)]);
+  }
+}
+
+static BROTLI_INLINE void FindCompoundDictionaryMatchOpt(
+    const PreparedDictionaryView* self,
+    const PreparedDictionaryProbe* BROTLI_RESTRICT probe,
+    const uint8_t* BROTLI_RESTRICT data,
+    const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache,
+    const size_t cur_ix, const size_t max_length, const size_t distance_offset,
+    const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) {
+  const uint32_t source_size = self->source_size;
+  const size_t boundary = distance_offset - source_size;
+
+  const uint8_t* source = self->source;
+
+  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
+  score_t best_score = out->score;
+  size_t best_len = out->len;
+  size_t i;
+  /* The hash and hashtable offsets were calculated in Prefetch, reuse the
+   * results. */
+  const uint32_t* BROTLI_RESTRICT chain = probe->chain;
+  uint32_t item = probe->item;
+#if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG)
+  {
+    const uint64_t bytes = BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix_masked]);
+    const uint64_t h =
+        (bytes & self->hash_mask) * kPreparedDictionaryHashMul64Long;
+    const uint32_t key = (uint32_t)(h >> self->hash_shift);
+    const uint32_t slot = key & self->slot_mask;
+    const uint32_t head = self->heads[key];
+    const uint32_t* expected_chain =
+        &self->items[self->slot_offsets[slot] + head];
+    const uint32_t expected_item = (head == 0xFFFF) ? 1 : 0;
+    BROTLI_DCHECK(probe->chain == expected_chain);
+    BROTLI_DCHECK(probe->item == expected_item);
+  }
+#endif
+
+  for (i = 0; i < 4; ++i) {
+    const size_t distance = (size_t)distance_cache[i];
+    size_t offset;
+    size_t limit;
+    size_t len;
+    if (distance <= boundary || distance > distance_offset) continue;
+    offset = distance_offset - distance;
+    limit = source_size - offset;
+    limit = limit > max_length ? max_length : limit;
+    len = FindMatchLengthWithLimit(&source[offset], &data[cur_ix_masked],
+                                   limit);
+    if (len >= 2) {
+      score_t score = BackwardReferenceScoreUsingLastDistance(len);
+      if (best_score < score) {
+        if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);
+        if (best_score < score) {
+          best_score = score;
+          if (len > best_len) best_len = len;
+          out->len = len;
+          out->len_code_delta = 0;
+          out->distance = distance;
+          out->score = best_score;
+        }
+      }
+    }
+  }
+  /* we require matches of len >4, so increase best_len to 3, so we can compare
+   * 4 bytes all the time. */
+  if (best_len < 3) {
+    best_len = 3;
+  }
+  while (item == 0) {
+    size_t offset;
+    size_t distance;
+    size_t limit;
+    item = *chain;
+    chain++;
+    offset = item & 0x7FFFFFFF;
+    item &= 0x80000000;
+    distance = distance_offset - offset;
+    limit = source_size - offset;
+    limit = (limit > max_length) ? max_length : limit;
+    if (distance > max_distance) continue;
+    if (best_len >= limit ||
+        /* compare 4 bytes ending at best_len + 1 */
+        BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=
+            BrotliUnalignedRead32(&source[offset + best_len - 3])) {
+      continue;
+    }
+    {
+      const size_t len = FindMatchLengthWithLimit(&source[offset],
+                                                  &data[cur_ix_masked],
+                                                  limit);
+      if (len >= 4) {
+        score_t score = BackwardReferenceScore(len, distance);
+        if (best_score < score) {
+          best_score = score;
+          best_len = len;
+          out->len = best_len;
+          out->len_code_delta = 0;
+          out->distance = distance;
+          out->score = best_score;
+        }
+      }
+    }
+  }
+}
+
+static BROTLI_INLINE void LookupCompoundDictionaryMatchOpt(
+    const CompoundDictionary* addon,
+    const PreparedDictionaryProbe* BROTLI_RESTRICT probes,
+    const uint8_t* BROTLI_RESTRICT data,
+    const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache,
+    const size_t cur_ix, const size_t max_length,
+    const size_t max_ring_buffer_distance, const size_t max_distance,
+    HasherSearchResult* sr) {
+  size_t base_offset = max_ring_buffer_distance + 1 + addon->total_size - 1;
+  size_t d;
+  for (d = 0; d < addon->num_chunks; ++d) {
+    FindCompoundDictionaryMatchOpt(
+        &addon->chunk_views[d], &probes[d], data, ring_buffer_mask,
+        distance_cache, cur_ix, max_length,
+        base_offset - addon->chunk_offsets[d], max_distance, sr);
+  }
+}
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }  /* extern "C" */
 #endif
diff --git a/enc/hash_forgetful_chain_inc.h b/enc/hash_forgetful_chain_inc.h
index b653698..31269bc 100644
--- a/enc/hash_forgetful_chain_inc.h
+++ b/enc/hash_forgetful_chain_inc.h
@@ -213,8 +213,6 @@
   out->len = 0;
   out->len_code_delta = 0;
 
-  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask + 1);
-
   /* Try last distance first. */
   for (i = 0; i < NUM_LAST_DISTANCES_TO_CHECK; ++i) {
     const size_t backward = (size_t)distance_cache[i];
diff --git a/enc/hash_longest_match64_inc.h b/enc/hash_longest_match64_inc.h
index 3131451..4e6d7d6 100644
--- a/enc/hash_longest_match64_inc.h
+++ b/enc/hash_longest_match64_inc.h
@@ -178,8 +178,6 @@
   out->len = 0;
   out->len_code_delta = 0;
 
-  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask + 1);
-
   /* Try last distance first. */
   for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {
     const size_t backward = (size_t)distance_cache[i];
diff --git a/enc/hash_longest_match64_simd_inc.h b/enc/hash_longest_match64_simd_inc.h
index 17dc67d..ea16330 100644
--- a/enc/hash_longest_match64_simd_inc.h
+++ b/enc/hash_longest_match64_simd_inc.h
@@ -195,8 +195,6 @@
   out->len = 0;
   out->len_code_delta = 0;
 
-  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask + 1);
-
   /* Try last distance first. */
   for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {
     const size_t backward = (size_t)distance_cache[i];
diff --git a/enc/hash_longest_match_inc.h b/enc/hash_longest_match_inc.h
index 674dced..ddf155f 100644
--- a/enc/hash_longest_match_inc.h
+++ b/enc/hash_longest_match_inc.h
@@ -178,8 +178,6 @@
   out->len = 0;
   out->len_code_delta = 0;
 
-  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask + 1);
-
   /* Try last distance first. */
   for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {
     const size_t backward = (size_t)distance_cache[i];
diff --git a/enc/hash_longest_match_quickly_inc.h b/enc/hash_longest_match_quickly_inc.h
index 12fdb44..8fa8bf9 100644
--- a/enc/hash_longest_match_quickly_inc.h
+++ b/enc/hash_longest_match_quickly_inc.h
@@ -165,8 +165,6 @@
   size_t cached_backward = (size_t)distance_cache[0];
   size_t prev_ix = cur_ix - cached_backward;
 
-  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask + 1);
-
   out->len_code_delta = 0;
   if (prev_ix < cur_ix && cached_backward <= max_backward) {
     prev_ix &= (uint32_t)ring_buffer_mask;
diff --git a/enc/hash_longest_match_simd_inc.h b/enc/hash_longest_match_simd_inc.h
index 075f6da..6b92380 100644
--- a/enc/hash_longest_match_simd_inc.h
+++ b/enc/hash_longest_match_simd_inc.h
@@ -170,8 +170,6 @@
   out->len = 0;
   out->len_code_delta = 0;
 
-  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask + 1);
-
   /* Try last distance first. */
   for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {
     const size_t backward = (size_t)distance_cache[i];
diff --git a/enc/hash_longest_match_simd_opt_inc.h b/enc/hash_longest_match_simd_opt_inc.h
new file mode 100644
index 0000000..6c54fae
--- /dev/null
+++ b/enc/hash_longest_match_simd_opt_inc.h
@@ -0,0 +1,284 @@
+/* NOLINT(build/header_guard) */
+/* Copyright 2010 Google Inc. All Rights Reserved.
+   Distributed under MIT license.
+   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+/* template parameters: FN */
+/* A (forgetful) hash table to the data seen by the compressor, to
+   help create backward references to previous data.
+   This is a hash map of fixed size (bucket_size_) to a ring buffer of
+   fixed size (block_size_). The ring buffer contains the last block_size_
+   index positions of the given hash key in the compressed data. */
+#define HashLongestMatch HASHER()
+#define TAG_HASH_BITS 8
+#define TAG_HASH_MASK ((1 << TAG_HASH_BITS) - 1)
+static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }
+static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; }
+/* HashBytes is the function that chooses the bucket to place the address in. */
+static uint32_t FN(HashBytes)(
+    const uint8_t* BROTLI_RESTRICT data, const int shift) {
+  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;
+  /* The higher bits contain more mixture from the multiplication,
+     so we take our results from there. */
+  return (uint32_t)(h >> shift);
+}
+typedef struct HashLongestMatch {
+  /* Number of hash buckets. */
+  size_t bucket_size_;
+  /* Only block_size_ newest backward references are kept,
+     and the older are forgotten. */
+  size_t block_size_;
+  /* Left-shift for computing hash bucket index from hash value. */
+  int hash_shift_;
+  /* Mask for accessing entries in a block (in a ring-buffer manner). */
+  uint32_t block_mask_;
+  int block_bits_;
+  int num_last_distances_to_check_;
+  /* Shortcuts. */
+  HasherCommon* common_;
+  /* --- Dynamic size members --- */
+  /* Number of entries in a particular bucket. */
+  uint16_t* num_;  /* uint16_t[bucket_size]; */
+  uint8_t* tags_;
+  /* Buckets containing block_size_ of backward references. */
+  uint32_t* buckets_;  /* uint32_t[bucket_size * block_size]; */
+} HashLongestMatch;
+static void FN(Initialize)(
+    HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self,
+    const BrotliEncoderParams* params) {
+  self->common_ = common;
+  BROTLI_UNUSED(params);
+  self->hash_shift_ = 32 - common->params.bucket_bits - TAG_HASH_BITS;
+  self->bucket_size_ = (size_t)1 << common->params.bucket_bits;
+  self->block_size_ = (size_t)1 << common->params.block_bits;
+  self->block_mask_ = (uint32_t)(self->block_size_ - 1);
+  self->num_ = (uint16_t*)common->extra[0];
+  self->tags_ = (uint8_t*)common->extra[1];
+  self->buckets_ = (uint32_t*)common->extra[2];
+  self->block_bits_ = common->params.block_bits;
+  self->num_last_distances_to_check_ =
+      common->params.num_last_distances_to_check;
+}
+static void FN(Prepare)(
+    HashLongestMatch* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,
+    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {
+  uint16_t* BROTLI_RESTRICT num = self->num_;
+  /* Partial preparation is 100 times slower (per socket). */
+  size_t partial_prepare_threshold = self->bucket_size_ >> 6;
+  if (one_shot && input_size <= partial_prepare_threshold) {
+    size_t i;
+    for (i = 0; i < input_size; ++i) {
+      const uint32_t hash = FN(HashBytes)(&data[i], self->hash_shift_);
+      const uint32_t key = hash >> TAG_HASH_BITS;
+      num[key] = 65535;
+    }
+  } else {
+    /* Set all the bytes of num to 255, which makes each uint16_t 65535. */
+    memset(num, 255, self->bucket_size_ * sizeof(num[0]));
+  }
+}
+static BROTLI_INLINE void FN(HashMemAllocInBytes)(
+    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
+    size_t input_size, size_t* alloc_size) {
+  size_t bucket_size = (size_t)1 << params->hasher.bucket_bits;
+  size_t block_size = (size_t)1 << params->hasher.block_bits;
+  BROTLI_UNUSED(one_shot);
+  BROTLI_UNUSED(input_size);
+  alloc_size[0] = sizeof(uint16_t) * bucket_size;
+  alloc_size[1] = sizeof(uint8_t) * bucket_size * block_size;
+  alloc_size[2] = sizeof(uint32_t) * bucket_size * block_size;
+}
+/* Look at 4 bytes at &data[ix & mask].
+   Compute a hash from these, and store the value of ix at that position. */
+static BROTLI_INLINE void FN(Store)(
+    HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,
+    const size_t mask, const size_t ix) {
+  uint16_t* BROTLI_RESTRICT num = self->num_;
+  uint8_t* BROTLI_RESTRICT tags = self->tags_;
+  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;
+  const size_t hash = FN(HashBytes)(&data[ix & mask], self->hash_shift_);
+  const size_t key = hash >> TAG_HASH_BITS;
+  const uint8_t tag = hash & TAG_HASH_MASK;
+  const size_t minor_ix = num[key] & self->block_mask_;
+  const size_t offset = minor_ix + (key << self->block_bits_);
+  --num[key];
+  buckets[offset] = (uint32_t)ix;
+  tags[offset] = tag;
+}
+static BROTLI_NOINLINE void FN(StoreRange)(
+    HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,
+    const size_t mask, const size_t ix_start, const size_t ix_end) {
+  size_t i;
+  for (i = ix_start; i < ix_end; ++i) {
+    FN(Store)(self, data, mask, i);
+  }
+}
+static BROTLI_INLINE void FN(StitchToPreviousBlock)(
+    HashLongestMatch* BROTLI_RESTRICT self,
+    size_t num_bytes, size_t position, const uint8_t* ringbuffer,
+    size_t ringbuffer_mask) {
+  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {
+    /* Prepare the hashes for three last bytes of the last write.
+       These could not be calculated before, since they require knowledge
+       of both the previous and the current block. */
+    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3);
+    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2);
+    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1);
+  }
+}
+static BROTLI_INLINE void FN(PrepareDistanceCache)(
+    HashLongestMatch* BROTLI_RESTRICT self,
+    int* BROTLI_RESTRICT distance_cache) {
+  PrepareDistanceCache(distance_cache, self->num_last_distances_to_check_);
+}
+
+/* Find a longest backward match of &data[cur_ix] up to the length of
+   max_length and stores the position cur_ix in the hash table.
+   REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache
+             values; if this method is invoked repeatedly with the same distance
+             cache values, it is enough to invoke FN(PrepareDistanceCache) once.
+   Does not look for matches longer than max_length.
+   Does not look for matches further away than max_backward.
+   Writes the best match into |out|.
+   |out|->score is updated only if a better match is found. */
+static BROTLI_INLINE void FN(FindLongestMatch)(
+    HashLongestMatch* BROTLI_RESTRICT self,
+    const BrotliEncoderDictionary* dictionary,
+    const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
+    const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,
+    const size_t max_length, const size_t max_backward,
+    const size_t dictionary_distance, const size_t max_distance,
+    HasherSearchResult* BROTLI_RESTRICT out) {
+  uint16_t* BROTLI_RESTRICT num = self->num_;
+  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;
+  uint8_t* BROTLI_RESTRICT tags = self->tags_;
+  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
+  /* Don't accept a short copy from far away. */
+  score_t min_score = out->score;
+  score_t best_score = out->score;
+  /* If we're still searching the static dictionary, we have to do the full
+     search to determine if we should check the static dictionary. */
+  size_t best_len =
+      self->common_->dict_num_matches < (self->common_->dict_num_lookups >> 7)
+          ? out->len
+          : 0;
+  size_t i;
+  /* Precalculate the hash key and prefetch the bucket. */
+  const uint32_t hash =
+      FN(HashBytes)(&data[cur_ix_masked], self->hash_shift_);
+  const uint32_t key = hash >> TAG_HASH_BITS;
+  uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];
+  uint8_t* BROTLI_RESTRICT tag_bucket = &tags[key << self->block_bits_];
+  PREFETCH_L1(bucket);
+  PREFETCH_L1(tag_bucket);
+  if (self->block_bits_ > 4) PREFETCH_L1(bucket + 16);
+  out->len = 0;
+  out->len_code_delta = 0;
+
+  if (best_len < 1) {
+    best_len = 1;
+  }
+  /* Try last distance first. */
+  for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {
+    const size_t backward = (size_t)distance_cache[i];
+    size_t prev_ix = (size_t)(cur_ix - backward);
+    if (prev_ix >= cur_ix) {
+      continue;
+    }
+    if (BROTLI_PREDICT_FALSE(backward > max_backward)) {
+      continue;
+    }
+    prev_ix &= ring_buffer_mask;
+
+    if (BrotliUnalignedRead16(&data[cur_ix_masked + best_len - 1]) !=
+            BrotliUnalignedRead16(&data[prev_ix + best_len - 1])) {
+      continue;
+    }
+    {
+      const size_t len = FindMatchLengthWithLimit(&data[prev_ix],
+                                                  &data[cur_ix_masked],
+                                                  max_length);
+      if (len >= 3 || (len == 2 && i < 2)) {
+        /* Comparing for >= 2 does not change the semantics, but just saves for
+           a few unnecessary binary logarithms in backward reference score,
+           since we are not interested in such short matches. */
+        score_t score = BackwardReferenceScoreUsingLastDistance(len);
+        if (best_score < score) {
+          if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);
+          if (best_score < score) {
+            best_score = score;
+            best_len = len;
+            out->len = best_len;
+            out->distance = backward;
+            out->score = best_score;
+          }
+        }
+      }
+    }
+  }
+  /* we require matches of len >4, so increase best_len to 3, so we can compare
+   * 4 bytes all the time. */
+  if (best_len < 3) {
+    best_len = 3;
+  }
+  {
+    const uint8_t tag = hash & TAG_HASH_MASK;
+    const size_t head = (num[key] + 1) & self->block_mask_;
+    uint64_t matches =
+        GetMatchingTagMask(self->block_size_ / 16, tag, tag_bucket, head);
+    /* Mask off any matches from uninitialized tags. */
+    uint16_t n = 65535 - num[key];
+    uint64_t block_has_unused_slots = self->block_size_ > n;
+    uint64_t mask = (block_has_unused_slots << (n & (64 - 1))) - 1;
+    matches &= mask;
+    for (; matches > 0; matches &= (matches - 1)) {
+      const size_t rb_index =
+          (head + (size_t)BROTLI_TZCNT64(matches)) & self->block_mask_;
+      size_t prev_ix = bucket[rb_index];
+      const size_t backward = cur_ix - prev_ix;
+      if (BROTLI_PREDICT_FALSE(backward > max_backward)) {
+        break;
+      }
+      prev_ix &= ring_buffer_mask;
+      if (/* compare 4 bytes ending at best_len + 1 */
+          BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=
+              BrotliUnalignedRead32(&data[prev_ix + best_len - 3])) {
+        continue;
+      }
+      {
+        const size_t len = FindMatchLengthWithLimit(&data[prev_ix],
+                                                    &data[cur_ix_masked],
+                                                    max_length);
+        if (len >= 4) {
+          /* Comparing for >= 3 does not change the semantics, but just saves
+             for a few unnecessary binary logarithms in backward reference
+             score, since we are not interested in such short matches. */
+          score_t score = BackwardReferenceScore(len, backward);
+          if (best_score < score) {
+            best_score = score;
+            best_len = len;
+            out->len = best_len;
+            out->distance = backward;
+            out->score = best_score;
+          }
+        }
+      }
+    }
+    bucket[num[key] & self->block_mask_] = (uint32_t)cur_ix;
+    tag_bucket[num[key] & self->block_mask_] = tag;
+    --num[key];
+  }
+  if (min_score == out->score) {
+    SearchInStaticDictionary(dictionary,
+        self->common_, &data[cur_ix_masked], max_length, dictionary_distance,
+        max_distance, out, BROTLI_FALSE);
+  }
+}
+/* `StoreRange` is deliberately not inlined, so it is not eligible for the
+   `BROTLI_INLINE` treatment that keeps unused hasher methods quiet; reference
+   it explicitly for the translation units that do not call it. */
+BROTLI_UNUSED_FUNCTION void FN(SuppressUnusedFunctions)(void) {
+  BROTLI_UNUSED(&FN(SuppressUnusedFunctions));
+  BROTLI_UNUSED(&FN(StoreRange));
+}
+#undef HashLongestMatch
diff --git a/enc/metablock.c b/enc/metablock.c
index dfe8120..2204f17 100644
--- a/enc/metablock.c
+++ b/enc/metablock.c
@@ -9,23 +9,171 @@
 
 #include "metablock.h"
 
-#include "../common/constants.h"
-#include "../common/context.h"
-#include "../common/platform.h"
 #include "bit_cost.h"
 #include "block_splitter.h"
 #include "cluster.h"
 #include "command.h"
 #include "entropy_encode.h"
+#include "hash.h"
 #include "histogram.h"
 #include "memory.h"
 #include "params.h"
 #include "prefix.h"
+#include "../common/constants.h"
+#include "../common/context.h"
+#include "../common/platform.h"
 
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
 #endif
 
+static void ForceBase64LiteralSplits(MemoryManager* m, BlockSplit* split,
+                                     const Base64Region* base64_regions,
+                                     size_t num_base64_regions,
+                                     size_t last_flush_pos,
+                                     MetaBlockSplit* mb) {
+  size_t r;
+  /* Each base64 region can split an existing block into at most 3 blocks
+     (adding 2 new blocks). In the worst case, every base64 region splits
+     a different block, increasing the number of blocks by 2 *
+     num_base64_regions. We add 1 extra block as a safety margin. */
+  size_t new_alloc_size = split->num_blocks + num_base64_regions * 2 + 1;
+  uint8_t* new_types = BROTLI_ALLOC(m, uint8_t, new_alloc_size);
+  uint32_t* new_lengths = BROTLI_ALLOC(m, uint32_t, new_alloc_size);
+  size_t new_num_blocks = 0;
+  size_t curr_offset = 0;
+  size_t block_idx = 0;
+
+  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_types) ||
+      BROTLI_IS_NULL(new_lengths)) {
+    return;
+  }
+
+  memset(mb->literal_is_base64, 0, sizeof(mb->literal_is_base64));
+  uint8_t base64_type_id = (uint8_t)split->num_types;
+  mb->literal_is_base64[base64_type_id >> 3] |=
+      (uint8_t)(1u << (base64_type_id & 7));
+
+  for (block_idx = 0; block_idx < split->num_blocks; ++block_idx) {
+    uint32_t block_len = split->lengths[block_idx];
+    uint8_t block_type = split->types[block_idx];
+    size_t block_start = curr_offset;
+    size_t block_end = curr_offset + block_len;
+
+    BROTLI_BOOL intersected = BROTLI_FALSE;
+    for (r = 0; r < num_base64_regions; ++r) {
+      size_t b64_start = base64_regions[r].start_literal_pos - last_flush_pos;
+      size_t b64_end = b64_start + base64_regions[r].length;
+
+      if (b64_start < block_end && b64_end > block_start) {
+        if (b64_start > block_start) {
+          new_types[new_num_blocks] = block_type;
+          new_lengths[new_num_blocks] = (uint32_t)(b64_start - block_start);
+          new_num_blocks++;
+        }
+        size_t intersect_start = BROTLI_MAX(size_t, block_start, b64_start);
+        size_t intersect_end = BROTLI_MIN(size_t, block_end, b64_end);
+        new_types[new_num_blocks] = base64_type_id;
+        new_lengths[new_num_blocks] =
+            (uint32_t)(intersect_end - intersect_start);
+        new_num_blocks++;
+
+        if (b64_end < block_end) {
+          block_start = b64_end;
+          block_len = (uint32_t)(block_end - b64_end);
+          continue;
+        } else {
+          block_len = 0;
+          intersected = BROTLI_TRUE;
+          break;
+        }
+      }
+    }
+
+    if (!intersected && block_len > 0) {
+      new_types[new_num_blocks] = block_type;
+      new_lengths[new_num_blocks] = block_len;
+      new_num_blocks++;
+    }
+    curr_offset = block_end;
+  }
+
+  BROTLI_FREE(m, split->types);
+  BROTLI_FREE(m, split->lengths);
+  split->types = new_types;
+  split->lengths = new_lengths;
+  split->num_blocks = new_num_blocks;
+  split->num_types++;
+}
+
+static void AppendBase64Histogram(MemoryManager* m, MetaBlockSplit* mb) {
+  size_t base64_type_id = mb->literal_split.num_types - 1;
+  size_t b64_histo_id = mb->literal_histograms_size;
+  size_t new_context_map_size =
+      mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS;
+  HistogramLiteral* new_histos =
+      BROTLI_ALLOC(m, HistogramLiteral, mb->literal_histograms_size + 1);
+  uint32_t* new_context_map =
+      BROTLI_ALLOC(m, uint32_t, new_context_map_size);
+  size_t i;
+  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_histos) ||
+      BROTLI_IS_NULL(new_context_map)) {
+    BROTLI_FREE(m, new_histos);
+    BROTLI_FREE(m, new_context_map);
+    return;
+  }
+  memcpy(new_histos, mb->literal_histograms,
+         mb->literal_histograms_size * sizeof(HistogramLiteral));
+  BROTLI_FREE(m, mb->literal_histograms);
+  mb->literal_histograms = new_histos;
+  HistogramClearLiteral(&mb->literal_histograms[b64_histo_id]);
+  mb->literal_histograms_size++;
+
+  if (mb->literal_context_map != NULL) {
+    memcpy(new_context_map, mb->literal_context_map,
+           mb->literal_context_map_size * sizeof(uint32_t));
+    BROTLI_FREE(m, mb->literal_context_map);
+  } else {
+    /* If context map was NULL (num_contexts == 1), initialize preceding types */
+    size_t t;
+    for (t = 0; t < base64_type_id; ++t) {
+      for (i = 0; i < 64; ++i) {
+        new_context_map[(t << 6) + i] = (uint32_t)t;
+      }
+    }
+  }
+  mb->literal_context_map = new_context_map;
+  mb->literal_context_map_size = new_context_map_size;
+  for (i = 0; i < 64; ++i) {
+    mb->literal_context_map[(base64_type_id << 6) + i] = (uint32_t)b64_histo_id;
+  }
+}
+
+static void MapBase64RegionsToLiteralPositions(
+    const Command* commands, size_t num_commands, size_t last_flush_pos,
+    const Base64Region* in_regions, size_t num_in_regions,
+    Base64Region* out_regions) {
+  size_t r;
+  for (r = 0; r < num_in_regions; ++r) {
+    size_t target_ring_pos = in_regions[r].start_literal_pos;
+    size_t curr_ring_pos = last_flush_pos;
+    size_t curr_lit_pos = 0;
+    size_t i;
+    for (i = 0; i < num_commands; ++i) {
+      const Command cmd = commands[i];
+      if (curr_ring_pos + cmd.insert_len_ >= target_ring_pos) {
+        size_t offset = target_ring_pos > curr_ring_pos ? target_ring_pos - curr_ring_pos : 0;
+        curr_lit_pos += offset;
+        break;
+      }
+      curr_lit_pos += cmd.insert_len_;
+      curr_ring_pos += cmd.insert_len_ + CommandCopyLen(&cmd);
+    }
+    out_regions[r].start_literal_pos = curr_lit_pos;
+    out_regions[r].length = in_regions[r].length;
+  }
+}
+
 void BrotliInitDistanceParams(BrotliDistanceParams* dist_params,
     uint32_t npostfix, uint32_t ndirect, BROTLI_BOOL large_window) {
   uint32_t alphabet_size_max;
@@ -123,16 +271,13 @@
   return BROTLI_TRUE;
 }
 
-void BrotliBuildMetaBlock(MemoryManager* m,
-                          const uint8_t* ringbuffer,
-                          const size_t pos,
-                          const size_t mask,
-                          BrotliEncoderParams* params,
-                          uint8_t prev_byte,
-                          uint8_t prev_byte2,
-                          Command* cmds,
-                          size_t num_commands,
-                          ContextType literal_context_mode,
+void BrotliBuildMetaBlock(MemoryManager* m, const uint8_t* ringbuffer,
+                          const size_t pos, const size_t mask,
+                          const Base64Region* base64_regions,
+                          size_t num_base64_regions,
+                          BrotliEncoderParams* params, uint8_t prev_byte,
+                          uint8_t prev_byte2, Command* cmds,
+                          size_t num_commands, ContextType literal_context_mode,
                           MetaBlockSplit* mb) {
   /* Histogram ids need to fit in one byte. */
   static const size_t kMaxNumberOfHistograms = 256;
@@ -263,6 +408,21 @@
     }
   }
 
+  if (num_base64_regions > 0 && mb->literal_split.num_types < 256 &&
+      mb->literal_histograms_size < 256) {
+    Base64Region local_b64[256];
+    size_t safe_num_b64 = BROTLI_MIN(size_t, num_base64_regions, 256);
+    MapBase64RegionsToLiteralPositions(cmds, num_commands, pos,
+                                       base64_regions, safe_num_b64,
+                                       local_b64);
+    ForceBase64LiteralSplits(m, &mb->literal_split, local_b64,
+                             safe_num_b64, 0, mb);
+    if (!BROTLI_IS_OOM(m)) {
+      AppendBase64Histogram(m, mb);
+    }
+    if (BROTLI_IS_OOM(m)) return;
+  }
+
   BROTLI_DCHECK(mb->distance_context_map == 0);
   mb->distance_context_map_size =
       mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS;
@@ -547,10 +707,12 @@
 
 static BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal(
     MemoryManager* m, GreedyMetablockArena* arena, const uint8_t* ringbuffer,
-    size_t pos, size_t mask, uint8_t prev_byte, uint8_t prev_byte2,
+    size_t pos, size_t mask, const Base64Region* base64_regions,
+    size_t num_base64_regions, uint8_t prev_byte, uint8_t prev_byte2,
     ContextLut literal_context_lut, const size_t num_contexts,
     const uint32_t* static_context_map, const Command* commands,
     size_t n_commands, MetaBlockSplit* mb) {
+  const size_t start_pos = pos;
   size_t num_literals = 0;
   size_t i;
   for (i = 0; i < n_commands; ++i) {
@@ -614,6 +776,36 @@
         &arena->lit_blocks.ctx, m, /* is_final = */ BROTLI_TRUE);
     if (BROTLI_IS_OOM(m)) return;
   }
+
+  if (num_base64_regions > 0 && mb->literal_split.num_types < 256 &&
+      mb->literal_histograms_size + num_contexts <= 256) {
+    Base64Region local_b64[256];
+    size_t safe_num_b64 = BROTLI_MIN(size_t, num_base64_regions, 256);
+    MapBase64RegionsToLiteralPositions(commands, n_commands, start_pos,
+                                       base64_regions, safe_num_b64,
+                                       local_b64);
+    ForceBase64LiteralSplits(m, &mb->literal_split, local_b64,
+                             safe_num_b64, 0, mb);
+    if (BROTLI_IS_OOM(m)) return;
+    {
+      size_t num_b64_histos = num_contexts;
+      size_t b64_histo_id = mb->literal_histograms_size;
+      HistogramLiteral* new_histos = BROTLI_ALLOC(
+          m, HistogramLiteral, mb->literal_histograms_size + num_b64_histos);
+      if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_histos)) {
+        return;
+      }
+      memcpy(new_histos, mb->literal_histograms,
+             mb->literal_histograms_size * sizeof(HistogramLiteral));
+      BROTLI_FREE(m, mb->literal_histograms);
+      mb->literal_histograms = new_histos;
+      for (i = 0; i < num_b64_histos; ++i) {
+        HistogramClearLiteral(&mb->literal_histograms[b64_histo_id + i]);
+      }
+      mb->literal_histograms_size += num_b64_histos;
+    }
+  }
+
   BlockSplitterFinishBlockCommand(
       &arena->cmd_blocks, /* is_final = */ BROTLI_TRUE);
   BlockSplitterFinishBlockDistance(
@@ -624,26 +816,22 @@
   }
 }
 
-void BrotliBuildMetaBlockGreedy(MemoryManager* m,
-                                const uint8_t* ringbuffer,
-                                size_t pos,
-                                size_t mask,
-                                uint8_t prev_byte,
-                                uint8_t prev_byte2,
-                                ContextLut literal_context_lut,
-                                size_t num_contexts,
-                                const uint32_t* static_context_map,
-                                const Command* commands,
-                                size_t n_commands,
-                                MetaBlockSplit* mb) {
+void BrotliBuildMetaBlockGreedy(
+    MemoryManager* m, const uint8_t* ringbuffer, size_t pos, size_t mask,
+    const Base64Region* base64_regions, size_t num_base64_regions,
+    uint8_t prev_byte, uint8_t prev_byte2, ContextLut literal_context_lut,
+    size_t num_contexts, const uint32_t* static_context_map,
+    const Command* commands, size_t n_commands, MetaBlockSplit* mb) {
   GreedyMetablockArena* arena = BROTLI_ALLOC(m, GreedyMetablockArena, 1);
   if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;
   if (num_contexts == 1) {
-    BrotliBuildMetaBlockGreedyInternal(m, arena, ringbuffer, pos, mask,
+    BrotliBuildMetaBlockGreedyInternal(
+        m, arena, ringbuffer, pos, mask, base64_regions, num_base64_regions,
         prev_byte, prev_byte2, literal_context_lut, 1, NULL, commands,
         n_commands, mb);
   } else {
-    BrotliBuildMetaBlockGreedyInternal(m, arena, ringbuffer, pos, mask,
+    BrotliBuildMetaBlockGreedyInternal(
+        m, arena, ringbuffer, pos, mask, base64_regions, num_base64_regions,
         prev_byte, prev_byte2, literal_context_lut, num_contexts,
         static_context_map, commands, n_commands, mb);
   }
diff --git a/enc/metablock.h b/enc/metablock.h
index e7d1052..5e2b456 100644
--- a/enc/metablock.h
+++ b/enc/metablock.h
@@ -10,13 +10,14 @@
 #ifndef BROTLI_ENC_METABLOCK_H_
 #define BROTLI_ENC_METABLOCK_H_
 
-#include "../common/context.h"
-#include "../common/platform.h"
 #include "block_splitter.h"
 #include "command.h"
+#include "hash.h"
 #include "histogram.h"
 #include "memory.h"
 #include "params.h"
+#include "../common/context.h"
+#include "../common/platform.h"
 
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
@@ -38,6 +39,7 @@
   size_t command_histograms_size;
   HistogramDistance* distance_histograms;
   size_t distance_histograms_size;
+  uint8_t literal_is_base64[32];
 } MetaBlockSplit;
 
 static BROTLI_INLINE void InitMetaBlockSplit(MetaBlockSplit* mb) {
@@ -54,6 +56,7 @@
   mb->command_histograms_size = 0;
   mb->distance_histograms = 0;
   mb->distance_histograms_size = 0;
+  memset(mb->literal_is_base64, 0, sizeof(mb->literal_is_base64));
 }
 
 static BROTLI_INLINE void DestroyMetaBlockSplit(
@@ -72,23 +75,19 @@
    The distance parameters are dynamically selected based on the commands
    which get recomputed under the new distance parameters. The new distance
    parameters are stored into *params. */
-BROTLI_INTERNAL void BrotliBuildMetaBlock(MemoryManager* m,
-                                          const uint8_t* ringbuffer,
-                                          const size_t pos,
-                                          const size_t mask,
-                                          BrotliEncoderParams* params,
-                                          uint8_t prev_byte,
-                                          uint8_t prev_byte2,
-                                          Command* cmds,
-                                          size_t num_commands,
-                                          ContextType literal_context_mode,
-                                          MetaBlockSplit* mb);
+BROTLI_INTERNAL void BrotliBuildMetaBlock(
+    MemoryManager* m, const uint8_t* ringbuffer, const size_t pos,
+    const size_t mask, const Base64Region* base64_regions,
+    size_t num_base64_regions, BrotliEncoderParams* params, uint8_t prev_byte,
+    uint8_t prev_byte2, Command* cmds, size_t num_commands,
+    ContextType literal_context_mode, MetaBlockSplit* mb);
 
 /* Uses a fast greedy block splitter that tries to merge current block with the
    last or the second last block and uses a static context clustering which
    is the same for all block types. */
 BROTLI_INTERNAL void BrotliBuildMetaBlockGreedy(
     MemoryManager* m, const uint8_t* ringbuffer, size_t pos, size_t mask,
+    const Base64Region* base64_regions, size_t num_base64_regions,
     uint8_t prev_byte, uint8_t prev_byte2, ContextLut literal_context_lut,
     size_t num_contexts, const uint32_t* static_context_map,
     const Command* commands, size_t n_commands, MetaBlockSplit* mb);
diff --git a/enc/params.h b/enc/params.h
index fd1de00..b1659dc 100644
--- a/enc/params.h
+++ b/enc/params.h
@@ -41,6 +41,11 @@
   BrotliDistanceParams dist;
   /* TODO(eustas): rename to BrotliShared... */
   SharedEncoderDictionary dictionary;
+  int base64_mode;
+  size_t max_base64_regions;
+  size_t min_base64_region_len;
+  BrotliEncoderSimdHasher simd_hasher;
+  BROTLI_BOOL hasher_opt;
 } BrotliEncoderParams;
 
 #endif  /* BROTLI_ENC_PARAMS_H_ */
diff --git a/enc/quality.h b/enc/quality.h
index 45d67bf..b3d2bed 100644
--- a/enc/quality.h
+++ b/enc/quality.h
@@ -128,14 +128,17 @@
    - q04: h54 (longest_match_quickly), b20, l7 | for large files
 
    - q05: h58 (longest_match_simd   ), b14, l4
+   - q05: h59 (longest_match_simd_opt), b14, l4
    - q05: h68 (longest_match64_simd ), b15, l5 | for large files
    - q05: h40 (forgetful_chain      ), b15, l4 | for small window
 
    - q06: h58 (longest_match_simd   ), b14, l4
+   - q06: h59 (longest_match_simd_opt), b14, l4
    - q06: h68 (longest_match64_simd ), b15, l5 | for large files
    - q06: h40 (forgetful_chain      ), b15, l4 | for small window
 
    - q07: h58 (longest_match_simd   ), b15, l4
+   - q07: h59 (longest_match_simd_opt), b15, l4
    - q07: h68 (longest_match64_simd ), b15, l5 | for large files
    - q07: h41 (forgetful_chain      ), b15, l4 | for small window
 
@@ -153,6 +156,22 @@
 
   Where "q" is quality, "h" is hasher type, "b" is bucket bits,
   "l" is source len. */
+
+#if defined(BROTLI_MAX_SIMD_QUALITY)
+static BROTLI_INLINE BROTLI_BOOL
+ShouldUseSimdHasher(const BrotliEncoderParams* params) {
+  if (params->simd_hasher == BROTLI_SIMD_HASHER_DISABLE) {
+    return BROTLI_FALSE;
+  }
+  int max_quality = BROTLI_MAX_RECOMMENDED_SIMD_QUALITY;
+
+  if (params->simd_hasher == BROTLI_SIMD_HASHER_ENABLE) {
+    max_quality = BROTLI_MAX_SIMD_QUALITY;
+  }
+  return TO_BROTLI_BOOL(params->quality <= max_quality);
+}
+#endif
+
 static BROTLI_INLINE void ChooseHasher(const BrotliEncoderParams* params,
                                        BrotliHasherParams* hparams) {
   if (params->quality > 9) {
@@ -165,7 +184,7 @@
     hparams->type = params->quality < 7 ? 40 : params->quality < 9 ? 41 : 42;
   } else if (params->size_hint >= (1 << 20) && params->lgwin >= 19) {
 #if defined(BROTLI_MAX_SIMD_QUALITY)
-    hparams->type = params->quality <= BROTLI_MAX_SIMD_QUALITY ? 68 : 6;
+    hparams->type = ShouldUseSimdHasher(params) ? 68 : 6;
 #else
     hparams->type = 6;
 #endif
@@ -177,7 +196,8 @@
     /* TODO(eustas): often previous setting (H6) is faster and denser; consider
                      adding an option to use it. */
 #if defined(BROTLI_MAX_SIMD_QUALITY)
-    hparams->type = params->quality <= BROTLI_MAX_SIMD_QUALITY ? 58 : 5;
+    hparams->type =
+        ShouldUseSimdHasher(params) ? (params->hasher_opt ? 59 : 58) : 5;
 #else
     hparams->type = 5;
 #endif
diff --git a/enc/ringbuffer.h b/enc/ringbuffer.h
index 5bb75ed..71ba9a5 100644
--- a/enc/ringbuffer.h
+++ b/enc/ringbuffer.h
@@ -123,9 +123,11 @@
        later when we copy the last two bytes to the first two positions. */
     rb->buffer_[rb->size_ - 2] = 0;
     rb->buffer_[rb->size_ - 1] = 0;
-    /* Initialize tail; might be touched by "best_len++" optimization when
-       ring buffer is "full". */
-    rb->buffer_[rb->size_] = 241;
+    /* Mirror the bytes written by the "first write" shortcut (see above) into
+       the tail.  That deliberately avoids initializing the ring buffer tail,
+       but that requires that we copy the bytes here. */
+    memcpy(&rb->buffer_[rb->size_], rb->buffer_,
+           BROTLI_MIN(size_t, rb->pos_, rb->tail_size_));
   }
   {
     const size_t masked_pos = rb->pos_ & rb->mask_;
diff --git a/include/brotli/encode.h b/include/brotli/encode.h
index ac26ea8..22c57ab 100644
--- a/include/brotli/encode.h
+++ b/include/brotli/encode.h
@@ -57,6 +57,33 @@
   BROTLI_MODE_FONT = 2
 } BrotliEncoderMode;
 
+/** Options for ::BROTLI_PARAM_BASE64_MODE parameter. */
+typedef enum BrotliEncoderBase64Mode {
+  /** Base64 optimization is disabled. */
+  BROTLI_BASE64_MODE_DISABLED = 0,
+  /** Automatic detection of Base64 zones and direct jump (skipping dictionary
+      and LZ77 lookups). */
+  BROTLI_BASE64_MODE_DETECTION = 1
+} BrotliEncoderBase64Mode;
+
+#define BROTLI_DEFAULT_BASE64_MODE BROTLI_BASE64_MODE_DISABLED
+
+#define BROTLI_DEFAULT_MAX_BASE64_REGIONS 16
+
+#define BROTLI_DEFAULT_MIN_BASE64_REGION_LEN 2048
+
+/** Options for ::BROTLI_PARAM_SIMD_HASHER parameter. */
+typedef enum BrotliEncoderSimdHasher {
+  /** Use SIMD hasher when recommended for the quality level. */
+  BROTLI_SIMD_HASHER_DEFAULT = 0,
+  /** Use SIMD hasher when supported up to quality 7. */
+  BROTLI_SIMD_HASHER_ENABLE = 1,
+  /** Never use SIMD hasher. */
+  BROTLI_SIMD_HASHER_DISABLE = 2
+} BrotliEncoderSimdHasher;
+
+#define BROTLI_DEFAULT_SIMD_HASHER BROTLI_SIMD_HASHER_DEFAULT
+
 /** Default value for ::BROTLI_PARAM_QUALITY parameter. */
 #define BROTLI_DEFAULT_QUALITY 11
 /** Default value for ::BROTLI_PARAM_LGWIN parameter. */
@@ -218,7 +245,38 @@
    * maximal window size have the same effect. Values greater than 2**30 are not
    * allowed.
    */
-  BROTLI_PARAM_STREAM_OFFSET = 9
+  BROTLI_PARAM_STREAM_OFFSET = 9,
+  /**
+   * Base64 encoding mode. Controls how the encoder handles Base64 content.
+   * Currently supports 0 (disabled) and 1 (automatic detection and skip
+   * dictionary lookups).
+   */
+  BROTLI_PARAM_BASE64_MODE = 10,
+  /**
+   * Maximum number of Base64 regions to detect.
+   * Default is 16.
+   */
+  BROTLI_PARAM_MAX_BASE64_REGIONS = 11,
+  /**
+   * SIMD hasher usage mode.
+   *
+   * Controls whether the encoder uses SIMD hashers.
+   * See ::BrotliEncoderSimdHasher for options.
+   */
+  BROTLI_PARAM_SIMD_HASHER = 12,
+  /**
+   * Engage optimized hasher.
+   *
+   * When enabled (1), engages H59 instead of H58.
+   */
+  BROTLI_PARAM_HASHER_OPT = 13,
+  /**
+   * Minimum length of a Base64 region to trigger detection and literal block
+   * splitting. Below this threshold, Base64 regions are encoded using standard
+   * LZ77 and Huffman coding.
+   * Default is 2048.
+   */
+  BROTLI_PARAM_MIN_BASE64_REGION_LEN = 14
 } BrotliEncoderParameter;
 
 /**
diff --git a/include/brotli/shared_dictionary.h b/include/brotli/shared_dictionary.h
index 2970c2d..fdfdbfc 100644
--- a/include/brotli/shared_dictionary.h
+++ b/include/brotli/shared_dictionary.h
@@ -22,6 +22,18 @@
 #define SHARED_BROTLI_MAX_COMPOUND_DICTS 15
 
 /**
+ * Practical limit for RAW dictionary size.
+ *
+ * Maximal distance (for non large window mode) is `(2 << 26 + 11) << NPOSTFIX`.
+ * Usually NPOSTFIX is 0 for regular data (i.e. not WORD/DWORD/QWORD stream).
+ * In large window mode, distance could be much larger.
+ *
+ * Currently, there are no known use cases for larger than 64MiB dictionary in
+ * regular mode and 2GiB in large window mode.
+ */
+#define SHARED_BROTLI_MAX_RAW_DICT_SIZE (1u << (23u + sizeof(size_t)))
+
+/**
  * Opaque structure that holds shared dictionary data.
  *
  * Allocated and initialized with ::BrotliSharedDictionaryCreateInstance.
diff --git a/include/brotli/types.h b/include/brotli/types.h
index 2dc61ff..7b5a6f5 100644
--- a/include/brotli/types.h
+++ b/include/brotli/types.h
@@ -41,7 +41,7 @@
  * evaluated, for example: @code{.cpp}
  * if (SomeBrotliFunction(encoder, BROTLI_TRUE) &&
  *     !OtherBrotliFunction(decoder, BROTLI_FALSE)) {
- *   bool x = !!YetAnotherBrotliFunction(encoder, TO_BROLTI_BOOL(2 * 2 == 4));
+ *   bool x = !!YetAnotherBrotliFunction(encoder, TO_BROTLI_BOOL(2 * 2 == 4));
  *   DoSomething(x);
  * }
  * @endcode
diff --git a/tools/brotli.c b/tools/brotli.c
index fe088d4..433efd6 100644
--- a/tools/brotli.c
+++ b/tools/brotli.c
@@ -50,8 +50,8 @@
 #define fopen ms_fopen
 #define open ms_open
 
-#define chmod(F, P) (0)
-#define chown(F, O, G) (0)
+#define fchmod(FD, P) (0)
+#define fchown(FD, O, G) (0)
 
 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
 #define fseek _fseeki64
@@ -79,6 +79,9 @@
 #define HAVE_UTIMENSAT 1
 #elif defined(_ATFILE_SOURCE)
 #define HAVE_UTIMENSAT 1
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \
+    defined(__DragonFly__)
+#define HAVE_UTIMENSAT 1
 #else
 #define HAVE_UTIMENSAT 0
 #endif
@@ -301,11 +304,6 @@
        contain pointers to strings"; NULL and 0-length are not forbidden. */
     size_t arg_len = arg ? strlen(arg) : 0;
 
-    if (arg_len == 0) {
-      params->not_input_indices[next_option_index++] = i;
-      continue;
-    }
-
     /* Too many options. The expected longest option list is:
        "-q 0 -w 10 -o f -D d -S b -d -f -k -n -v -K --", i.e. 17 items in total.
        This check is an additional guard that is never triggered, but provides
@@ -315,6 +313,11 @@
       return COMMAND_INVALID;
     }
 
+    if (arg_len == 0) {
+      params->not_input_indices[next_option_index++] = i;
+      continue;
+    }
+
     /* Input file entry. */
     if (after_dash_dash || arg[0] != '-' || arg_len == 1) {
       input_count++;
@@ -833,16 +836,21 @@
   return retval;
 }
 
-static int CopyTimeStat(const struct stat* statbuf, const char* output_path) {
+static int CopyTimeStat(const struct stat* statbuf, const char* output_path,
+                        FILE* fout) {
 #if HAVE_UTIMENSAT
   struct timespec times[2];
+  int fd = fileno(fout);
+  (void)output_path;
+  if (fd < 0) return -1;
   times[0].tv_sec = statbuf->st_atime;
   times[0].tv_nsec = ATIME_NSEC(statbuf);
   times[1].tv_sec = statbuf->st_mtime;
   times[1].tv_nsec = MTIME_NSEC(statbuf);
-  return utimensat(AT_FDCWD, output_path, times, AT_SYMLINK_NOFOLLOW);
+  return futimens(fd, times);
 #else
   struct utimbuf times;
+  (void)fout;
   times.actime = statbuf->st_atime;
   times.modtime = statbuf->st_mtime;
   return utime(output_path, &times);
@@ -852,27 +860,33 @@
 /* Copy file times and permissions.
    TODO(eustas): this is a "best effort" implementation; honest cross-platform
    fully featured implementation is way too hacky; add more hacks by request. */
-static void CopyStat(const char* input_path, const char* output_path) {
+static void CopyStat(const char* input_path, const char* output_path,
+                     FILE* fout) {
   struct stat statbuf;
+  int fd;
   int res;
-  if (input_path == 0 || output_path == 0) {
+  if (input_path == 0 || output_path == 0 || fout == NULL) {
+    return;
+  }
+  fd = fileno(fout);
+  if (fd < 0) {
     return;
   }
   if (stat(input_path, &statbuf) != 0) {
     return;
   }
-  res = CopyTimeStat(&statbuf, output_path);
-  res = chmod(output_path, statbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
+  res = CopyTimeStat(&statbuf, output_path, fout);
+  res = fchmod(fd, statbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
   if (res != 0) {
     fprintf(stderr, "setting access bits failed for [%s]: %s\n",
             PrintablePath(output_path), strerror(errno));
   }
-  res = chown(output_path, (uid_t)-1, statbuf.st_gid);
+  res = fchown(fd, (uid_t)-1, statbuf.st_gid);
   if (res != 0) {
     fprintf(stderr, "setting group failed for [%s]: %s\n",
             PrintablePath(output_path), strerror(errno));
   }
-  res = chown(output_path, statbuf.st_uid, (gid_t)-1);
+  res = fchown(fd, statbuf.st_uid, (gid_t)-1);
   if (res != 0) {
     fprintf(stderr, "setting user failed for [%s]: %s\n",
             PrintablePath(output_path), strerror(errno));
@@ -1028,6 +1042,19 @@
                               BROTLI_BOOL rm_output) {
   BROTLI_BOOL is_ok = BROTLI_TRUE;
   if (!context->test_integrity && context->fout) {
+    /* Flush before the metadata copy, so a failed write is reported. */
+    if (fflush(context->fout) != 0) {
+      fprintf(stderr, "failed to write output [%s]: %s\n",
+              PrintablePath(context->current_output_path), strerror(errno));
+      is_ok = BROTLI_FALSE;
+    }
+    /* Apply metadata via the still-open fd, before close, to close the TOCTOU
+       window between fclose() and the metadata syscalls. */
+    if (is_ok && !rm_output && context->copy_stat &&
+        context->current_output_path) {
+      CopyStat(context->current_input_path, context->current_output_path,
+               context->fout);
+    }
     if (fclose(context->fout) != 0) {
       if (is_ok) {
         fprintf(stderr, "fclose failed [%s]: %s\n",
@@ -1038,11 +1065,6 @@
     if (rm_output && context->current_output_path) {
       unlink(context->current_output_path);
     }
-
-    /* TOCTOU violation, but otherwise it is impossible to set file times. */
-    if (!rm_output && is_ok && context->copy_stat) {
-      CopyStat(context->current_input_path, context->current_output_path);
-    }
   }
 
   if (context->fin) {
@@ -1054,7 +1076,7 @@
       is_ok = BROTLI_FALSE;
     }
   }
-  if (rm_input && context->current_input_path) {
+  if (rm_input && is_ok && context->current_input_path) {
     unlink(context->current_input_path);
   }
 
@@ -1293,6 +1315,7 @@
           if (context->verbosity > 0) {
             fprintf(stderr, "reason: comment mismatch\n");
           }
+          return BROTLI_FALSE;
         }
         return BROTLI_TRUE;
       }