Bug 1585519 - Part 1: Add MOZ_UNLIKELY to error handling code. r=Yoric
authorTooru Fujisawa <arai_a@mac.com>
Mon, 07 Oct 2019 05:11:01 +0000
changeset 496464 8ea58e64530bb0fc2996d7f2a922eb67d1dabe78
parent 496463 8f3223ff55e267cb478968433c8f1cfa4e4fcb97
child 496465 d34594143118bcfd489a5a13de958e8e24ad62ab
push id36659
push userrgurzau@mozilla.com
push dateMon, 07 Oct 2019 09:29:54 +0000
treeherdermozilla-central@3955e0a93047 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersYoric
bugs1585519
milestone71.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1585519 - Part 1: Add MOZ_UNLIKELY to error handling code. r=Yoric Differential Revision: https://phabricator.services.mozilla.com/D48013
js/src/frontend/BinASTParserPerTokenizer.cpp
js/src/frontend/BinASTParserPerTokenizer.h
js/src/frontend/BinASTRuntimeSupport.cpp
js/src/frontend/BinASTToken.cpp
js/src/frontend/BinASTTokenReaderBase.cpp
js/src/frontend/BinASTTokenReaderBase.h
js/src/frontend/BinASTTokenReaderContext.cpp
--- a/js/src/frontend/BinASTParserPerTokenizer.cpp
+++ b/js/src/frontend/BinASTParserPerTokenizer.cpp
@@ -117,34 +117,34 @@ JS::Result<ParseNode*> BinASTParserPerTo
     GlobalSharedContext* globalsc, const uint8_t* start, const size_t length,
     BinASTSourceMetadata** metadataPtr) {
   MOZ_ASSERT(globalsc);
 
   tokenizer_.emplace(cx_, this, start, length);
 
   BinASTParseContext globalpc(cx_, this, globalsc,
                               /* newDirectives = */ nullptr);
-  if (!globalpc.init()) {
+  if (MOZ_UNLIKELY(!globalpc.init())) {
     return cx_->alreadyReportedError();
   }
 
   ParseContext::VarScope varScope(cx_, &globalpc, usedNames_);
-  if (!varScope.init(&globalpc)) {
+  if (MOZ_UNLIKELY(!varScope.init(&globalpc))) {
     return cx_->alreadyReportedError();
   }
 
   MOZ_TRY(tokenizer_->readHeader());
 
   ParseNode* result(nullptr);
   const auto topContext = RootContext();
   MOZ_TRY_VAR(result, asFinalParser()->parseProgram(topContext));
 
   mozilla::Maybe<GlobalScope::Data*> bindings =
       NewGlobalScopeData(cx_, varScope, alloc_, pc_);
-  if (!bindings) {
+  if (MOZ_UNLIKELY(!bindings)) {
     return cx_->alreadyReportedError();
   }
   globalsc->bindings = *bindings;
 
   if (metadataPtr) {
     *metadataPtr = tokenizer_->takeMetadata();
   }
 
@@ -240,24 +240,24 @@ JS::Result<FunctionBox*> BinASTParserPer
 
   // Name might be any of {Identifier,ComputedPropertyName,LiteralPropertyName}
   if (name && name->is<NameNode>()) {
     atom = name->as<NameNode>().atom();
   }
 
   if (pc_ && syntax == FunctionSyntaxKind::Statement) {
     auto ptr = pc_->varScope().lookupDeclaredName(atom);
-    if (!ptr) {
+    if (MOZ_UNLIKELY(!ptr)) {
       return raiseError(
           "FunctionDeclaration without corresponding AssertedDeclaredName.");
     }
 
     DeclarationKind declaredKind = ptr->value()->kind();
     if (DeclarationKindIsVar(declaredKind)) {
-      if (!pc_->atBodyLevel()) {
+      if (MOZ_UNLIKELY(!pc_->atBodyLevel())) {
         return raiseError(
             "body-level FunctionDeclaration inside non-body-level context.");
       }
       RedeclareVar(ptr, DeclarationKind::BodyLevelFunction);
     }
   }
 
   // Allocate the function before walking down the tree.
@@ -277,17 +277,17 @@ JS::Result<FunctionBox*> BinASTParserPer
     directives.emplace(pc_);
   } else {
     directives.emplace(lazyScript_->strict());
   }
 
   auto* funbox = alloc_.new_<FunctionBox>(
       cx_, traceListHead_, fun, /* toStringStart = */ 0, *directives,
       /* extraWarning = */ false, generatorKind, functionAsyncKind);
-  if (!funbox) {
+  if (MOZ_UNLIKELY(!funbox)) {
     return raiseOOM();
   }
 
   traceListHead_ = funbox;
   if (pc_) {
     funbox->initWithEnclosingParseContext(pc_, fun, syntax);
   } else {
     funbox->initFromLazyFunction(fun);
@@ -453,17 +453,17 @@ template <typename Tok>
 JS::Result<Ok> BinASTParserPerTokenizer<Tok>::getDeclaredScope(
     AssertedScopeKind scopeKind, AssertedDeclaredKind kind,
     ParseContext::Scope*& scope, DeclarationKind& declKind) {
   MOZ_ASSERT(scopeKind == AssertedScopeKind::Block ||
              scopeKind == AssertedScopeKind::Global ||
              scopeKind == AssertedScopeKind::Var);
   switch (kind) {
     case AssertedDeclaredKind::Var:
-      if (scopeKind == AssertedScopeKind::Block) {
+      if (MOZ_UNLIKELY(scopeKind == AssertedScopeKind::Block)) {
         return raiseError("AssertedBlockScope cannot contain 'var' binding");
       }
       declKind = DeclarationKind::Var;
       scope = &pc_->varScope();
       break;
     case AssertedDeclaredKind::NonConstLexical:
       declKind = DeclarationKind::Let;
       scope = pc_->innermostScope();
@@ -505,17 +505,17 @@ template <typename Tok>
 JS::Result<Ok> BinASTParserPerTokenizer<Tok>::checkBinding(JSAtom* name) {
   // Check that the variable appears in the corresponding scope.
   ParseContext::Scope& scope =
       variableDeclarationKind_ == VariableDeclarationKind::Var
           ? pc_->varScope()
           : *pc_->innermostScope();
 
   auto ptr = scope.lookupDeclaredName(name->asPropertyName());
-  if (!ptr) {
+  if (MOZ_UNLIKELY(!ptr)) {
     return raiseMissingVariableInAssertedScope(name);
   }
 
   return Ok();
 }
 
 // Binary AST (revision 8eab67e0c434929a66ff6abe99ff790bca087dda)
 // 3.1.5 CheckPositionalParameterIndices.
@@ -545,41 +545,41 @@ JS::Result<Ok> BinASTParserPerTokenizer<
     if (isRest) {
       // Rest parameter
 
       // Step 3.
       if (i >= positionalParams.get().length()) {
         continue;
       }
 
-      if (positionalParams.get()[i]) {
+      if (MOZ_UNLIKELY(positionalParams.get()[i])) {
         return raiseError(
             "Expected positional parameter per "
             "AssertedParameterScope.paramNames, got rest parameter");
       }
     } else if (param->isKind(ParseNodeKind::Name)) {
       // Simple or default parameter.
 
       // Step 2.a.
-      if (i >= positionalParams.get().length()) {
+      if (MOZ_UNLIKELY(i >= positionalParams.get().length())) {
         return raiseError(
             "AssertedParameterScope.paramNames doesn't have corresponding "
             "entry to positional parameter");
       }
 
       JSAtom* name = positionalParams.get()[i];
-      if (!name) {
+      if (MOZ_UNLIKELY(!name)) {
         // Step 2.a.ii.1.
         return raiseError(
             "Expected destructuring/rest parameter per "
             "AssertedParameterScope.paramNames, got positional parameter");
       }
 
       // Step 2.a.i.
-      if (param->as<NameNode>().name() != name) {
+      if (MOZ_UNLIKELY(param->as<NameNode>().name() != name)) {
         // Step 2.a.ii.1.
         return raiseError(
             "Name mismatch between AssertedPositionalParameterName in "
             "AssertedParameterScope.paramNames and actual parameter");
       }
 
       // Step 2.a.i.1.
       // Implicitly done.
@@ -589,56 +589,56 @@ JS::Result<Ok> BinASTParserPerTokenizer<
       MOZ_ASSERT(param->isKind(ParseNodeKind::ObjectExpr) ||
                  param->isKind(ParseNodeKind::ArrayExpr));
 
       // Step 3.
       if (i >= positionalParams.get().length()) {
         continue;
       }
 
-      if (positionalParams.get()[i]) {
+      if (MOZ_UNLIKELY(positionalParams.get()[i])) {
         return raiseError(
             "Expected positional parameter per "
             "AssertedParameterScope.paramNames, got destructuring parameter");
       }
     }
 
     i++;
   }
 
   // Step 3.
-  if (positionalParams.get().length() > params->count()) {
+  if (MOZ_UNLIKELY(positionalParams.get().length() > params->count())) {
     // `positionalParams` has unchecked entries.
     return raiseError(
         "AssertedParameterScope.paramNames has unmatching items than the "
         "actual parameters");
   }
 
   return Ok();
 }
 
 // Binary AST (revision 8eab67e0c434929a66ff6abe99ff790bca087dda)
 // 3.1.13 CheckFunctionLength.
 template <typename Tok>
 JS::Result<Ok> BinASTParserPerTokenizer<Tok>::checkFunctionLength(
     uint32_t expectedLength) {
-  if (pc_->functionBox()->length != expectedLength) {
+  if (MOZ_UNLIKELY(pc_->functionBox()->length != expectedLength)) {
     return raiseError("Function length does't match");
   }
   return Ok();
 }
 
 template <typename Tok>
 JS::Result<Ok> BinASTParserPerTokenizer<Tok>::checkClosedVars(
     ParseContext::Scope& scope) {
   for (ParseContext::Scope::BindingIter bi = scope.bindings(pc_); bi; bi++) {
     if (UsedNamePtr p = usedNames_.lookup(bi.name())) {
       bool closedOver;
       p->value().noteBoundInScope(pc_->scriptId(), scope.id(), &closedOver);
-      if (closedOver && !bi.closedOver()) {
+      if (MOZ_UNLIKELY(closedOver && !bi.closedOver())) {
         return raiseInvalidClosedVar(bi.name());
       }
     }
   }
 
   return Ok();
 }
 
--- a/js/src/frontend/BinASTParserPerTokenizer.h
+++ b/js/src/frontend/BinASTParserPerTokenizer.h
@@ -226,17 +226,17 @@ class BinASTParserPerTokenizer : public 
      * We use JSContext.tempLifoAlloc to allocate parsed objects and place them
      * on a list in this Parser to ensure GC safety. Thus the tempLifoAlloc
      * arenas containing the entries must be alive until we are done with
      * scanning, parsing and code generation for the whole script or top-level
      * function.
      */
 
     ObjectBox* objbox = alloc_.new_<ObjectBox>(obj, traceListHead_);
-    if (!objbox) {
+    if (MOZ_UNLIKELY(!objbox)) {
       ReportOutOfMemory(cx_);
       return nullptr;
     }
 
     traceListHead_ = objbox;
 
     return objbox;
   }
--- a/js/src/frontend/BinASTRuntimeSupport.cpp
+++ b/js/src/frontend/BinASTRuntimeSupport.cpp
@@ -15,17 +15,17 @@ namespace frontend {
 
 /* static */
 BinASTSourceMetadata* BinASTSourceMetadata::Create(
     const Vector<BinASTKind>& binASTKinds, uint32_t numStrings) {
   uint32_t numBinASTKinds = binASTKinds.length();
 
   BinASTSourceMetadata* data = static_cast<BinASTSourceMetadata*>(
       js_malloc(BinASTSourceMetadata::totalSize(numBinASTKinds, numStrings)));
-  if (!data) {
+  if (MOZ_UNLIKELY(!data)) {
     return nullptr;
   }
 
   new (data) BinASTSourceMetadata(numBinASTKinds, numStrings);
   memcpy(data->binASTKindBase(), binASTKinds.begin(),
          binASTKinds.length() * sizeof(BinASTKind));
 
   return data;
--- a/js/src/frontend/BinASTToken.cpp
+++ b/js/src/frontend/BinASTToken.cpp
@@ -128,17 +128,17 @@ bool BinaryASTSupport::ensureBinTablesIn
 bool BinaryASTSupport::ensureBinASTKindsInitialized(JSContext* cx) {
   MOZ_ASSERT(!cx->isHelperThreadContext());
   if (binASTKindMap_.empty()) {
     for (size_t i = 0; i < frontend::BINASTKIND_LIMIT; ++i) {
       const BinASTKind variant = static_cast<BinASTKind>(i);
       const CharSlice& key = getBinASTKind(variant);
       auto ptr = binASTKindMap_.lookupForAdd(key);
       MOZ_ASSERT(!ptr);
-      if (!binASTKindMap_.add(ptr, key, variant)) {
+      if (MOZ_UNLIKELY(!binASTKindMap_.add(ptr, key, variant))) {
         ReportOutOfMemory(cx);
         return false;
       }
     }
   }
 
   return true;
 }
@@ -146,31 +146,31 @@ bool BinaryASTSupport::ensureBinASTKinds
 bool BinaryASTSupport::ensureBinASTVariantsInitialized(JSContext* cx) {
   MOZ_ASSERT(!cx->isHelperThreadContext());
   if (binASTVariantMap_.empty()) {
     for (size_t i = 0; i < frontend::BINASTVARIANT_LIMIT; ++i) {
       const BinASTVariant variant = static_cast<BinASTVariant>(i);
       const CharSlice& key = getBinASTVariant(variant);
       auto ptr = binASTVariantMap_.lookupForAdd(key);
       MOZ_ASSERT(!ptr);
-      if (!binASTVariantMap_.add(ptr, key, variant)) {
+      if (MOZ_UNLIKELY(!binASTVariantMap_.add(ptr, key, variant))) {
         ReportOutOfMemory(cx);
         return false;
       }
     }
   }
   return true;
 }
 
 JS::Result<const js::frontend::BinASTKind*> BinaryASTSupport::binASTKind(
     JSContext* cx, const CharSlice key) {
   MOZ_ASSERT_IF(cx->isHelperThreadContext(), !binASTKindMap_.empty());
   if (!cx->isHelperThreadContext()) {
     // Initialize Lazily if on main thread.
-    if (!ensureBinASTKindsInitialized(cx)) {
+    if (MOZ_UNLIKELY(!ensureBinASTKindsInitialized(cx))) {
       return cx->alreadyReportedError();
     }
   }
 
   auto ptr = binASTKindMap_.readonlyThreadsafeLookup(key);
   if (!ptr) {
     return nullptr;
   }
@@ -178,17 +178,17 @@ JS::Result<const js::frontend::BinASTKin
   return &ptr->value();
 }
 
 JS::Result<const js::frontend::BinASTVariant*> BinaryASTSupport::binASTVariant(
     JSContext* cx, const CharSlice key) {
   MOZ_ASSERT_IF(cx->isHelperThreadContext(), !binASTVariantMap_.empty());
   if (!cx->isHelperThreadContext()) {
     // Initialize lazily if on main thread.
-    if (!ensureBinASTVariantsInitialized(cx)) {
+    if (MOZ_UNLIKELY(!ensureBinASTVariantsInitialized(cx))) {
       return cx->alreadyReportedError();
     }
   }
 
   auto ptr = binASTVariantMap_.readonlyThreadsafeLookup(key);
   if (!ptr) {
     return nullptr;
   }
--- a/js/src/frontend/BinASTTokenReaderBase.cpp
+++ b/js/src/frontend/BinASTTokenReaderBase.cpp
@@ -81,17 +81,17 @@ TokenPos BinASTTokenReaderBase::pos(size
 void BinASTTokenReaderBase::seek(size_t offset) {
   MOZ_ASSERT(start_ + offset >= start_ && start_ + offset < stop_);
   current_ = start_ + offset;
 }
 
 JS::Result<Ok> BinASTTokenReaderBase::readBuf(uint8_t* bytes, uint32_t len) {
   MOZ_ASSERT(!hasRaisedError());
 
-  if (stop_ < current_ + len) {
+  if (MOZ_UNLIKELY(stop_ < current_ + len)) {
     return raiseError("Buffer exceeds length");
   }
 
   for (uint32_t i = 0; i < len; ++i) {
     *bytes++ = *current_++;
   }
 
   return Ok();
--- a/js/src/frontend/BinASTTokenReaderBase.h
+++ b/js/src/frontend/BinASTTokenReaderBase.h
@@ -158,17 +158,17 @@ class MOZ_STACK_CLASS BinASTTokenReaderB
    * Read a sequence of chars, ensuring that they match an expected
    * sequence of chars.
    *
    * @param value The sequence of chars to expect, NUL-terminated.
    */
   template <size_t N>
   MOZ_MUST_USE JS::Result<Ok> readConst(const char (&value)[N]) {
     updateLatestKnownGood();
-    if (!matchConst(value, false)) {
+    if (MOZ_UNLIKELY(!matchConst(value, false))) {
       return raiseError("Could not find expected literal");
     }
     return Ok();
   }
 
   /**
    * Read a sequence of chars, consuming the bytes only if they match an
    * expected sequence of chars.
@@ -180,17 +180,17 @@ class MOZ_STACK_CLASS BinASTTokenReaderB
    * otherwise there is no side-effect.
    */
   template <size_t N>
   MOZ_MUST_USE bool matchConst(const char (&value)[N], bool expectNul) {
     MOZ_ASSERT(N > 0);
     MOZ_ASSERT(value[N - 1] == 0);
     MOZ_ASSERT(!hasRaisedError());
 
-    if (current_ + N - 1 > stop_) {
+    if (MOZ_UNLIKELY(current_ + N - 1 > stop_)) {
       return false;
     }
 
 #ifndef FUZZING
     // Perform lookup, without side-effects.
     if (memcmp(current_, value, N + (expectNul ? 0 : -1) /*implicit NUL*/) !=
         0) {
       return false;
--- a/js/src/frontend/BinASTTokenReaderContext.cpp
+++ b/js/src/frontend/BinASTTokenReaderContext.cpp
@@ -561,17 +561,17 @@ class HuffmanPreludeReader {
     // If `Entry` is an indexed type, this is fetched from the grammar.
     BINJS_MOZ_TRY_DECL(numberOfSymbols, readNumberOfSymbols<Entry>(entry));
 
     MOZ_ASSERT(numberOfSymbols <= MAX_NUMBER_OF_SYMBOLS);
 
     if (numberOfSymbols == 1) {
       // Special case: only one symbol.
       BINJS_MOZ_TRY_DECL(bitLength, reader.readByte<Compression::No>());
-      if (bitLength != 0) {
+      if (MOZ_UNLIKELY(bitLength != 0)) {
         // Since there is a single symbol, it doesn't make sense to have a non-0
         // bit length.
         return raiseInvalidTableData(entry.identity);
       }
 
       // Read the symbol.
       // If `Entry` is an indexed type, it is fetched directly from the grammar.
       BINJS_MOZ_TRY_DECL(
@@ -606,17 +606,17 @@ class HuffmanPreludeReader {
         auxStorageLength.empty());  // We must have cleaned it up properly.
     BINJS_TRY(auxStorageLength.reserve(numberOfSymbols + 1));
 
     uint8_t largestBitLength = 0;
 
     // First read and store the bit lengths for all symbols.
     for (size_t i = 0; i < numberOfSymbols; ++i) {
       BINJS_MOZ_TRY_DECL(bitLength, reader.readByte<Compression::No>());
-      if (bitLength == 0) {
+      if (MOZ_UNLIKELY(bitLength == 0)) {
         return raiseInvalidTableData(entry.identity);
       }
       if (bitLength > largestBitLength) {
         largestBitLength = bitLength;
       }
       BINJS_TRY(auxStorageLength.append(BitLengthAndIndex(bitLength, i)));
     }
     // Append a terminator.
@@ -628,17 +628,17 @@ class HuffmanPreludeReader {
     MOZ_TRY(table.initStart(cx_, numberOfSymbols, largestBitLength));
 
     for (size_t i = 0; i < numberOfSymbols; ++i) {
       const auto bitLength = auxStorageLength[i].bitLength;
       const auto nextBitLength =
           auxStorageLength[i + 1]
               .bitLength;  // Guaranteed to exist, as we have a terminator.
 
-      if (bitLength > nextBitLength) {
+      if (MOZ_UNLIKELY(bitLength > nextBitLength)) {
         // By format invariant, bit lengths are always non-0
         // and always ranked by increasing order.
         return raiseInvalidTableData(entry.identity);
       }
 
       // Read and add symbol.
       BINJS_MOZ_TRY_DECL(
           symbol, readSymbol<Entry>(entry, i));  // Symbol is read from disk.
@@ -669,17 +669,17 @@ class HuffmanPreludeReader {
     // - Lengths MAY be 0.
     // - Lengths are not sorted on disk.
 
     uint8_t largestBitLength = 0;
 
     // First read the length for all symbols, only store non-0 lengths.
     for (size_t i = 0; i < numberOfSymbols; ++i) {
       BINJS_MOZ_TRY_DECL(bitLength, reader.readByte<Compression::No>());
-      if (bitLength > MAX_CODE_BIT_LENGTH) {
+      if (MOZ_UNLIKELY(bitLength > MAX_CODE_BIT_LENGTH)) {
         MOZ_CRASH("FIXME: Implement error");
       }
       if (bitLength > 0) {
         BINJS_TRY(auxStorageLength.append(BitLengthAndIndex(bitLength, i)));
         if (bitLength > largestBitLength) {
           largestBitLength = bitLength;
         }
       }
@@ -745,17 +745,17 @@ class HuffmanPreludeReader {
     return readTable<HuffmanTableValue, Entry>(table, entry);
   }
 
   // Two-arguments version: pass table explicitly. Generally called from single-
   // argument version, but may be called manually, e.g. for list lengths, as
   // their tables don't appear in `dictionary.tableForField`.
   template <typename HuffmanTable, typename Entry>
   MOZ_MUST_USE JS::Result<Ok> readTable(HuffmanTable& table, Entry entry) {
-    if (!table.template is<HuffmanTableInitializing>()) {
+    if (MOZ_UNLIKELY(!table.template is<HuffmanTableInitializing>())) {
       // We're attempting to re-read a table that has already been read.
       // FIXME: Shouldn't this be a MOZ_CRASH?
       return raiseDuplicateTableError(entry.identity);
     }
 
     uint8_t headerByte;
     MOZ_TRY_VAR(headerByte, reader.readByte<Compression::No>());
     switch (headerByte) {
@@ -1135,44 +1135,44 @@ JS::Result<Ok> BinASTTokenReaderContext:
   // Check that we don't call this function twice.
   MOZ_ASSERT(!posBeforeTree_);
 
 #if BINAST_CX_MAGIC_HEADER
   // Read global headers.
   MOZ_TRY(readConst(CX_MAGIC_HEADER));
   BINJS_MOZ_TRY_DECL(version, readVarU32<Compression::No>());
 
-  if (version != MAGIC_FORMAT_VERSION) {
+  if (MOZ_UNLIKELY(version != MAGIC_FORMAT_VERSION)) {
     return raiseError("Format version not implemented");
   }
 #endif  // BINAST_CX_MAGIC_HEADER
 
   MOZ_TRY(readStringPrelude());
   MOZ_TRY(readHuffmanPrelude());
 
   return Ok();
 }
 
 JS::Result<Ok> BinASTTokenReaderContext::readStringPrelude() {
   BINJS_MOZ_TRY_DECL(stringsNumberOfEntries, readVarU32<Compression::No>());
 
   const uint32_t MAX_NUMBER_OF_STRINGS = 32768;
 
-  if (stringsNumberOfEntries > MAX_NUMBER_OF_STRINGS) {
+  if (MOZ_UNLIKELY(stringsNumberOfEntries > MAX_NUMBER_OF_STRINGS)) {
     return raiseError("Too many entries in strings dictionary");
   }
 
   // FIXME: We don't use the global table like multipart format, but
   //        (interface, field)-local dictionary.
   //        Metadata should be fixed to store that.
   Vector<BinASTKind> binASTKinds(cx_);
 
   BinASTSourceMetadata* metadata =
       BinASTSourceMetadata::Create(binASTKinds, stringsNumberOfEntries);
-  if (!metadata) {
+  if (MOZ_UNLIKELY(!metadata)) {
     return raiseOOM();
   }
 
   // Free it if we don't make it out of here alive. Since we don't want to
   // calloc(), we need to avoid marking atoms that might not be there.
   auto se = mozilla::MakeScopeExit([metadata]() { js_free(metadata); });
 
   // Below, we read at most DECODED_BUFFER_SIZE bytes at once and look for
@@ -1183,23 +1183,23 @@ JS::Result<Ok> BinASTTokenReaderContext:
   // to the actual encoding of the strings that is WTF-8, but the validation
   // should be done later by `AtomizeWTF8Chars`, not immediately.
   StringBuffer buf(cx_);
 
   RootedAtom atom(cx_);
 
   for (uint32_t stringIndex = 0; stringIndex < stringsNumberOfEntries;
        stringIndex++) {
-    if (current_ >= stop_) {
+    if (MOZ_UNLIKELY(current_ >= stop_)) {
       return raiseError("End of file reached while reading strings table");
     }
 
     const uint8_t* end =
         static_cast<const uint8_t*>(memchr(current_, '\0', stop_ - current_));
-    if (!end) {
+    if (MOZ_UNLIKELY(!end)) {
       return raiseError("Invalid string, missing NUL");
     }
 
     // FIXME: handle 0x01-escaped string here.
 
     const char* start = reinterpret_cast<const char*>(current_);
     BINJS_TRY_VAR(atom, AtomizeWTF8Chars(cx_, start, end - current_));
 
@@ -1399,27 +1399,27 @@ struct TagReader {
   TagReader(const HuffmanLookup bits, BitBuffer& bitBuffer,
             BinASTTokenReaderContext& owner)
       : bits(bits), bitBuffer(bitBuffer), owner(owner) {}
   JS::Result<BinASTKind> operator()(
       const HuffmanTableIndexedSymbolsSum& specialized) {
     // We're entering either a single interface or a sum.
     const auto lookup = specialized.lookup(bits);
     bitBuffer.advanceBitBuffer<Compression::No>(lookup.key.bitLength);
-    if (!lookup.value) {
+    if (MOZ_UNLIKELY(!lookup.value)) {
       return owner.raiseInvalidValue();
     }
     return *lookup.value;
   }
   JS::Result<BinASTKind> operator()(
       const HuffmanTableIndexedSymbolsMaybeInterface& specialized) {
     // We're entering an optional interface.
     const auto lookup = specialized.lookup(bits);
     bitBuffer.advanceBitBuffer<Compression::No>(lookup.key.bitLength);
-    if (!lookup.value) {
+    if (MOZ_UNLIKELY(!lookup.value)) {
       return owner.raiseInvalidValue();
     }
     return *lookup.value;
   }
   template <typename Table>
   JS::Result<BinASTKind> operator()(const Table&) {
     MOZ_CRASH("Unreachable");
   }
@@ -1437,24 +1437,24 @@ JS::Result<BinASTKind> BinASTTokenReader
 
 template <typename Table>
 JS::Result<typename Table::Contents>
 BinASTTokenReaderContext::readFieldFromTable(
     const BinASTInterfaceAndField& identity) {
   // Extract the table.
   const auto& table =
       dictionary.tableForField(NormalizedInterfaceAndField(identity));
-  if (!table.is<Table>()) {
+  if (MOZ_UNLIKELY(!table.is<Table>())) {
     return raiseNotInPrelude();
   }
   BINJS_MOZ_TRY_DECL(bits, bitBuffer.getHuffmanLookup<Compression::No>(*this));
   const auto lookup = table.as<Table>().lookup(bits);
 
   bitBuffer.advanceBitBuffer<Compression::No>(lookup.key.bitLength);
-  if (!lookup.value) {
+  if (MOZ_UNLIKELY(!lookup.value)) {
     return raiseInvalidValue();
   }
   return *lookup.value;
 }
 
 JS::Result<bool> BinASTTokenReaderContext::readBool(
     const FieldContext& context) {
   return readFieldFromTable<HuffmanTableIndexedSymbolsBool>(context.position);
@@ -1587,17 +1587,17 @@ JS::Result<Ok> BinASTTokenReaderContext:
                                                    AutoList& guard) {
   const auto identity = context.content;
   const auto& table = dictionary.tableForListLength(identity);
   BINJS_MOZ_TRY_DECL(bits, bitBuffer.getHuffmanLookup<Compression::No>(*this));
   const auto& tableForLookup =
       table.as<HuffmanTableExplicitSymbolsListLength>();
   const auto lookup = tableForLookup.lookup(bits);
   bitBuffer.advanceBitBuffer<Compression::No>(lookup.key.bitLength);
-  if (!lookup.value) {
+  if (MOZ_UNLIKELY(!lookup.value)) {
     return raiseInvalidValue();
   }
   items = *lookup.value;
   return Ok();
 }
 
 void BinASTTokenReaderContext::AutoBase::init() { initialized_ = true; }
 
@@ -1633,28 +1633,28 @@ JS::Result<uint32_t> BinASTTokenReaderCo
   uint32_t result = 0;
   uint32_t shift = 0;
   while (true) {
     MOZ_ASSERT(shift < 32);
     uint32_t byte;
     MOZ_TRY_VAR(byte, readByte<compression>());
 
     const uint32_t newResult = result | (byte & 0x7f) << shift;
-    if (newResult < result) {
+    if (MOZ_UNLIKELY(newResult < result)) {
       return raiseError("Overflow during readVarU32");
     }
 
     result = newResult;
     shift += 7;
 
     if ((byte & 0x80) == 0) {
       return result;
     }
 
-    if (shift >= 32) {
+    if (MOZ_UNLIKELY(shift >= 32)) {
       return raiseError("Overflow during readVarU32");
     }
   }
 }
 
 JS::Result<uint32_t> BinASTTokenReaderContext::readUnpackedLong() {
   uint8_t bytes[4];
   uint32_t length = 4;
@@ -1938,28 +1938,28 @@ HuffmanEntry<const T*> GenericHuffmanTab
         MOZ_CRASH("GenericHuffmanTable is unitialized!");
       });
 }
 
 template <typename T, int N>
 JS::Result<Ok> NaiveHuffmanTable<T, N>::initWithSingleValue(JSContext* cx,
                                                             T&& value) {
   MOZ_ASSERT(values.empty());  // Make sure that we're initializing.
-  if (!values.append(HuffmanEntry<T>(0, 0, std::move(value)))) {
+  if (MOZ_UNLIKELY(!values.append(HuffmanEntry<T>(0, 0, std::move(value))))) {
     return cx->alreadyReportedError();
   }
   return Ok();
 }
 
 template <typename T, int N>
 JS::Result<Ok> NaiveHuffmanTable<T, N>::initStart(JSContext* cx,
                                                   size_t numberOfSymbols,
                                                   uint8_t) {
   MOZ_ASSERT(values.empty());  // Make sure that we're initializing.
-  if (!values.initCapacity(numberOfSymbols)) {
+  if (MOZ_UNLIKELY(!values.initCapacity(numberOfSymbols))) {
     return cx->alreadyReportedError();
   }
   return Ok();
 }
 
 template <typename T, int N>
 JS::Result<Ok> NaiveHuffmanTable<T, N>::initComplete() {
   MOZ_ASSERT(values.length() <= N);
@@ -1970,19 +1970,18 @@ template <typename T, int N>
 JS::Result<Ok> NaiveHuffmanTable<T, N>::addSymbol(uint32_t bits,
                                                   uint8_t bitLength,
                                                   T&& value) {
   MOZ_ASSERT(bitLength != 0,
              "Adding a symbol with a bitLength of 0 doesn't make sense.");
   MOZ_ASSERT(values.empty() || values.back().key.bitLength <= bitLength,
              "Symbols must be ranked by increasing bits length");
   MOZ_ASSERT_IF(bitLength != 32 /* >> 32 is UB */, bits >> bitLength == 0);
-  if (!values.emplaceBack(bits, bitLength, std::move(value))) {
-    MOZ_CRASH();  // Memory was reserved in `init()`.
-  }
+  // Memory was reserved in `init()`.
+  MOZ_ALWAYS_TRUE(values.emplaceBack(bits, bitLength, std::move(value)));
 
   return Ok();
 }
 
 template <typename T, int N>
 HuffmanEntry<const T*> NaiveHuffmanTable<T, N>::lookup(
     HuffmanLookup key) const {
   // This current implementation is O(length) and designed mostly for testing.
@@ -2006,44 +2005,44 @@ HuffmanEntry<const T*> NaiveHuffmanTable
   return HuffmanEntry<const T*>(0, 0, nullptr);
 }
 
 template <typename T>
 JS::Result<Ok> MapBasedHuffmanTable<T>::initWithSingleValue(JSContext* cx,
                                                             T&& value) {
   MOZ_ASSERT(values.empty());  // Make sure that we're initializing.
   const HuffmanKey key(0, 0);
-  if (!values.put(FlatHuffmanKey(key), std::move(value)) || !keys.append(key)) {
+  if (MOZ_UNLIKELY(!values.put(FlatHuffmanKey(key), std::move(value)) ||
+                   !keys.append(key))) {
     ReportOutOfMemory(cx);
     return cx->alreadyReportedError();
   }
   return Ok();
 }
 
 template <typename T>
 JS::Result<Ok> MapBasedHuffmanTable<T>::initStart(JSContext* cx,
                                                   size_t numberOfSymbols,
                                                   uint8_t) {
   MOZ_ASSERT(values.empty());  // Make sure that we're initializing.
-  if (!values.reserve(numberOfSymbols) || !keys.reserve(numberOfSymbols)) {
+  if (MOZ_UNLIKELY(!values.reserve(numberOfSymbols) ||
+                   !keys.reserve(numberOfSymbols))) {
     ReportOutOfMemory(cx);
     return cx->alreadyReportedError();
   }
   return Ok();
 }
 
 template <typename T>
 JS::Result<Ok> MapBasedHuffmanTable<T>::initComplete() {
 #if DEBUG
   // Check that there is a bijection between `keys` and `values`.
   // 1. Injection.
   for (const auto& key : keys) {
-    if (!values.has(FlatHuffmanKey(key))) {
-      MOZ_CRASH();
-    }
+    MOZ_ALWAYS_TRUE(values.has(FlatHuffmanKey(key)));
   }
   // 2. Cardinality.
   MOZ_ASSERT(values.count() == keys.length());
 #endif  // DEBUG
   return Ok();
 }
 
 template <typename T>
@@ -2102,41 +2101,41 @@ bool SingleLookupHuffmanTable<T>::Iterat
     const Iterator& other) const {
   return position != other.position;
 }
 
 template <typename T>
 JS::Result<Ok> SingleLookupHuffmanTable<T>::initWithSingleValue(JSContext* cx,
                                                                 T&& value) {
   MOZ_ASSERT(values.empty());  // Make sure that we're initializing.
-  if (!values.emplaceBack(0, 0, std::move(value))) {
+  if (MOZ_UNLIKELY(!values.emplaceBack(0, 0, std::move(value)))) {
     return cx->alreadyReportedError();
   }
-  if (!saturated.emplaceBack(0)) {
+  if (MOZ_UNLIKELY(!saturated.emplaceBack(0))) {
     return cx->alreadyReportedError();
   }
   this->largestBitLength = 0;
   return Ok();
 }
 
 template <typename T>
 JS::Result<Ok> SingleLookupHuffmanTable<T>::initStart(
     JSContext* cx, size_t numberOfSymbols, uint8_t largestBitLength) {
   MOZ_ASSERT_IF(largestBitLength != 32,
                 (uint32_t(1) << largestBitLength) - 1 <=
                     mozilla::MaxValue<InternalIndex>::value);
   MOZ_ASSERT(values.empty());  // Make sure that we're initializing.
 
   this->largestBitLength = largestBitLength;
 
-  if (!values.initCapacity(numberOfSymbols)) {
+  if (MOZ_UNLIKELY(!values.initCapacity(numberOfSymbols))) {
     return cx->alreadyReportedError();
   }
   const size_t saturatedLength = 1 << largestBitLength;
-  if (!saturated.initCapacity(saturatedLength)) {
+  if (MOZ_UNLIKELY(!saturated.initCapacity(saturatedLength))) {
     return cx->alreadyReportedError();
   }
   // Enlarge `saturated`, as we're going to fill it in random order.
   for (size_t i = 0; i < saturatedLength; ++i) {
     // Capacity reserved in this method.
     saturated.infallibleAppend(InternalIndex(-1));
   }
   return Ok();
@@ -2258,20 +2257,20 @@ operator!=(const Iterator& other) const 
 template <typename T, typename Subtable, uint8_t PrefixBitLength>
 JS::Result<Ok> MultiLookupHuffmanTable<T, Subtable, PrefixBitLength>::initStart(
     JSContext* cx, size_t numberOfSymbols, uint8_t largestBitLength) {
   static_assert(PrefixBitLength < MAX_CODE_BIT_LENGTH,
                 "Invalid PrefixBitLength");
   MOZ_ASSERT(values.empty());  // Make sure that we're initializing.
   MOZ_ASSERT(subTables.empty());
   this->largestBitLength = largestBitLength;
-  if (!values.initCapacity(numberOfSymbols)) {
+  if (MOZ_UNLIKELY(!values.initCapacity(numberOfSymbols))) {
     return cx->alreadyReportedError();
   }
-  if (!subTables.initCapacity(1 << PrefixBitLength)) {
+  if (MOZ_UNLIKELY(!subTables.initCapacity(1 << PrefixBitLength))) {
     return cx->alreadyReportedError();
   }
   return Ok();
 }
 
 template <typename T, typename Subtable, uint8_t PrefixBitLength>
 JS::Result<Ok> MultiLookupHuffmanTable<T, Subtable, PrefixBitLength>::addSymbol(
     uint32_t bits, uint8_t bitLength, T&& value) {
@@ -2479,17 +2478,17 @@ MOZ_MUST_USE JS::Result<bool> HuffmanPre
 }
 
 // Reading a single-value table of booleans
 template <>
 MOZ_MUST_USE JS::Result<Ok> HuffmanPreludeReader::readSingleValueTable<Boolean>(
     Boolean::Table& table, const Boolean& entry) {
   uint8_t indexByte;
   MOZ_TRY_VAR(indexByte, reader.readByte<Compression::No>());
-  if (indexByte >= 2) {
+  if (MOZ_UNLIKELY(indexByte >= 2)) {
     return raiseInvalidTableData(entry.identity);
   }
 
   MOZ_TRY(table.initWithSingleValue(cx_, indexByte != 0));
   return Ok();
 }
 
 // ------ Optional interfaces.
@@ -2514,17 +2513,17 @@ MOZ_MUST_USE JS::Result<BinASTKind> Huff
 
 // Reading a single-value table of optional interfaces
 template <>
 MOZ_MUST_USE JS::Result<Ok>
 HuffmanPreludeReader::readSingleValueTable<MaybeInterface>(
     MaybeInterface::Table& table, const MaybeInterface& entry) {
   uint8_t indexByte;
   MOZ_TRY_VAR(indexByte, reader.readByte<Compression::No>());
-  if (indexByte >= 2) {
+  if (MOZ_UNLIKELY(indexByte >= 2)) {
     return raiseInvalidTableData(entry.identity);
   }
 
   MOZ_TRY(table.initWithSingleValue(
       cx_, indexByte == 0 ? BinASTKind::_Null : entry.kind));
   return Ok();
 }
 
@@ -2547,17 +2546,17 @@ MOZ_MUST_USE JS::Result<BinASTKind> Huff
   return entry.interfaceAt(index);
 }
 
 // Reading a single-value table of sums of interfaces.
 template <>
 MOZ_MUST_USE JS::Result<Ok> HuffmanPreludeReader::readSingleValueTable<Sum>(
     HuffmanTableIndexedSymbolsSum& table, const Sum& sum) {
   BINJS_MOZ_TRY_DECL(index, reader.readVarU32<Compression::No>());
-  if (index >= sum.maxNumberOfSymbols()) {
+  if (MOZ_UNLIKELY(index >= sum.maxNumberOfSymbols())) {
     return raiseInvalidTableData(sum.identity);
   }
 
   MOZ_TRY(table.initWithSingleValue(cx_, sum.interfaceAt(index)));
   return Ok();
 }
 
 // ------ Optional sums of interfaces
@@ -2581,33 +2580,33 @@ MOZ_MUST_USE JS::Result<BinASTKind> Huff
 }
 
 // Reading a single-value table of sums of interfaces.
 template <>
 MOZ_MUST_USE JS::Result<Ok>
 HuffmanPreludeReader::readSingleValueTable<MaybeSum>(
     HuffmanTableIndexedSymbolsSum& table, const MaybeSum& sum) {
   BINJS_MOZ_TRY_DECL(index, reader.readVarU32<Compression::No>());
-  if (index >= sum.maxNumberOfSymbols()) {
+  if (MOZ_UNLIKELY(index >= sum.maxNumberOfSymbols())) {
     return raiseInvalidTableData(sum.identity);
   }
 
   MOZ_TRY(table.initWithSingleValue(cx_, sum.interfaceAt(index)));
   return Ok();
 }
 
 // ------ Numbers
 // 64 bits, IEEE 754, big endian
 
 // Read the number of symbols from the stream.
 template <>
 MOZ_MUST_USE JS::Result<uint32_t> HuffmanPreludeReader::readNumberOfSymbols(
     const Number& number) {
   BINJS_MOZ_TRY_DECL(length, reader.readVarU32<Compression::No>());
-  if (length > MAX_NUMBER_OF_SYMBOLS) {
+  if (MOZ_UNLIKELY(length > MAX_NUMBER_OF_SYMBOLS)) {
     return raiseInvalidTableData(number.identity);
   }
   return length;
 }
 
 // Read a single symbol from the stream.
 template <>
 MOZ_MUST_USE JS::Result<double> HuffmanPreludeReader::readSymbol(
@@ -2643,77 +2642,77 @@ MOZ_MUST_USE JS::Result<Ok> HuffmanPrelu
 // ------ List lengths
 // varnum
 
 // Read the number of symbols from the grammar.
 template <>
 MOZ_MUST_USE JS::Result<uint32_t> HuffmanPreludeReader::readNumberOfSymbols(
     const List& list) {
   BINJS_MOZ_TRY_DECL(length, reader.readVarU32<Compression::No>());
-  if (length > MAX_NUMBER_OF_SYMBOLS) {
+  if (MOZ_UNLIKELY(length > MAX_NUMBER_OF_SYMBOLS)) {
     return raiseInvalidTableData(list.identity);
   }
   return length;
 }
 
 // Read a single symbol from the stream.
 template <>
 MOZ_MUST_USE JS::Result<uint32_t> HuffmanPreludeReader::readSymbol(
     const List& list, size_t) {
   BINJS_MOZ_TRY_DECL(length, reader.readUnpackedLong());
-  if (length > MAX_LIST_LENGTH) {
+  if (MOZ_UNLIKELY(length > MAX_LIST_LENGTH)) {
     return raiseInvalidTableData(list.identity);
   }
   return length;
 }
 
 // Reading a single-value table of list lengths.
 template <>
 MOZ_MUST_USE JS::Result<Ok> HuffmanPreludeReader::readSingleValueTable<List>(
     HuffmanTableExplicitSymbolsListLength& table, const List& list) {
   BINJS_MOZ_TRY_DECL(length, reader.readUnpackedLong());
-  if (length > MAX_LIST_LENGTH) {
+  if (MOZ_UNLIKELY(length > MAX_LIST_LENGTH)) {
     return raiseInvalidTableData(list.identity);
   }
   MOZ_TRY(table.initWithSingleValue(cx_, std::move(length)));
   return Ok();
 }
 
 // ------ Strings, non-nullable
 // varnum (index)
 
 // Read the number of symbols from the stream.
 template <>
 MOZ_MUST_USE JS::Result<uint32_t> HuffmanPreludeReader::readNumberOfSymbols(
     const String& string) {
   BINJS_MOZ_TRY_DECL(length, reader.readVarU32<Compression::No>());
-  if (length > MAX_NUMBER_OF_SYMBOLS ||
-      length > reader.metadata_->numStrings()) {
+  if (MOZ_UNLIKELY(length > MAX_NUMBER_OF_SYMBOLS ||
+                   length > reader.metadata_->numStrings())) {
     return raiseInvalidTableData(string.identity);
   }
   return length;
 }
 
 // Read a single symbol from the stream.
 template <>
 MOZ_MUST_USE JS::Result<JSAtom*> HuffmanPreludeReader::readSymbol(
     const String& entry, size_t) {
   BINJS_MOZ_TRY_DECL(index, reader.readVarU32<Compression::No>());
-  if (index > reader.metadata_->numStrings()) {
+  if (MOZ_UNLIKELY(index > reader.metadata_->numStrings())) {
     return raiseInvalidTableData(entry.identity);
   }
   return reader.metadata_->getAtom(index);
 }
 
 // Reading a single-value table of string indices.
 template <>
 MOZ_MUST_USE JS::Result<Ok> HuffmanPreludeReader::readSingleValueTable<String>(
     HuffmanTableIndexedSymbolsLiteralString& table, const String& entry) {
   BINJS_MOZ_TRY_DECL(index, reader.readVarU32<Compression::No>());
-  if (index > reader.metadata_->numStrings()) {
+  if (MOZ_UNLIKELY(index > reader.metadata_->numStrings())) {
     return raiseInvalidTableData(entry.identity);
   }
   // Note: The `std::move` is useless for performance, but necessary to keep
   // a consistent API.
   JSAtom* value = reader.metadata_->getAtom(index);
   MOZ_TRY(table.initWithSingleValue(
       cx_,
       /* NOLINT(performance-move-const-arg) */ std::move(value)));
@@ -2724,45 +2723,45 @@ MOZ_MUST_USE JS::Result<Ok> HuffmanPrelu
 // varnum 0 -> null
 // varnum i > 0 -> string at index i - 1
 
 // Read the number of symbols from the metadata.
 template <>
 MOZ_MUST_USE JS::Result<uint32_t> HuffmanPreludeReader::readNumberOfSymbols(
     const MaybeString& entry) {
   BINJS_MOZ_TRY_DECL(length, reader.readVarU32<Compression::No>());
-  if (length > MAX_NUMBER_OF_SYMBOLS ||
-      length > reader.metadata_->numStrings() + 1) {
+  if (MOZ_UNLIKELY(length > MAX_NUMBER_OF_SYMBOLS ||
+                   length > reader.metadata_->numStrings() + 1)) {
     return raiseInvalidTableData(entry.identity);
   }
   return length;
 }
 
 // Read a single symbol from the stream.
 template <>
 MOZ_MUST_USE JS::Result<JSAtom*> HuffmanPreludeReader::readSymbol(
     const MaybeString& entry, size_t) {
   BINJS_MOZ_TRY_DECL(index, reader.readVarU32<Compression::No>());
   if (index == 0) {
     return nullptr;
-  } else if (index > reader.metadata_->numStrings() + 1) {
+  }
+  if (MOZ_UNLIKELY(index > reader.metadata_->numStrings() + 1)) {
     return raiseInvalidTableData(entry.identity);
-  } else {
-    return reader.metadata_->getAtom(index - 1);
   }
+  return reader.metadata_->getAtom(index - 1);
 }
 
 // Reading a single-value table of string indices.
 template <>
 MOZ_MUST_USE JS::Result<Ok>
 HuffmanPreludeReader::readSingleValueTable<MaybeString>(
     HuffmanTableIndexedSymbolsOptionalLiteralString& table,
     const MaybeString& entry) {
   BINJS_MOZ_TRY_DECL(index, reader.readVarU32<Compression::No>());
-  if (index > reader.metadata_->numStrings() + 1) {
+  if (MOZ_UNLIKELY(index > reader.metadata_->numStrings() + 1)) {
     return raiseInvalidTableData(entry.identity);
   }
   JSAtom* symbol = index == 0 ? nullptr : reader.metadata_->getAtom(index - 1);
   // Note: The `std::move` is useless for performance, but necessary to keep
   // a consistent API.
   MOZ_TRY(table.initWithSingleValue(
       cx_,
       /* NOLINT(performance-move-const-arg) */ std::move(symbol)));
@@ -2787,17 +2786,17 @@ MOZ_MUST_USE JS::Result<BinASTVariant> H
 }
 
 // Reading a single-value table of string indices.
 template <>
 MOZ_MUST_USE JS::Result<Ok>
 HuffmanPreludeReader::readSingleValueTable<StringEnum>(
     HuffmanTableIndexedSymbolsStringEnum& table, const StringEnum& entry) {
   BINJS_MOZ_TRY_DECL(index, reader.readVarU32<Compression::No>());
-  if (index > entry.maxNumberOfSymbols()) {
+  if (MOZ_UNLIKELY(index > entry.maxNumberOfSymbols())) {
     return raiseInvalidTableData(entry.identity);
   }
 
   BinASTVariant symbol = entry.variantAt(index);
   // Note: The `std::move` is useless for performance, but necessary to keep
   // a consistent API.
   MOZ_TRY(table.initWithSingleValue(
       cx_,
@@ -2808,17 +2807,17 @@ HuffmanPreludeReader::readSingleValueTab
 // ------ Unsigned Longs
 // Unpacked 32-bit
 
 // Read the number of symbols from the stream.
 template <>
 MOZ_MUST_USE JS::Result<uint32_t> HuffmanPreludeReader::readNumberOfSymbols(
     const UnsignedLong& entry) {
   BINJS_MOZ_TRY_DECL(length, reader.readVarU32<Compression::No>());
-  if (length > MAX_NUMBER_OF_SYMBOLS) {
+  if (MOZ_UNLIKELY(length > MAX_NUMBER_OF_SYMBOLS)) {
     return raiseInvalidTableData(entry.identity);
   }
   return length;
 }
 
 // Read a single symbol from the stream.
 template <>
 MOZ_MUST_USE JS::Result<uint32_t> HuffmanPreludeReader::readSymbol(