Bug 1519097 - Relax the meaning of 'poisoned' SourceUnits to allow SourceUnits initialized with null units and zero length to be considered not-poisoned. r=bustage
authorJeff Walden <jwalden@mit.edu>
Thu, 28 Feb 2019 20:14:14 -0800
changeset 519793 b7f57b355891
parent 519792 015b9fdf0034
child 519794 3ea769ff9a9a
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbustage
bugs1519097
milestone67.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 1519097 - Relax the meaning of 'poisoned' SourceUnits to allow SourceUnits initialized with null units and zero length to be considered not-poisoned. r=bustage
js/src/frontend/TokenStream.h
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -1168,49 +1168,52 @@ class SourceUnits {
  public:
   SourceUnits(const Unit* units, size_t length, size_t startOffset)
       : base_(units),
         startOffset_(startOffset),
         limit_(units + length),
         ptr(units) {}
 
   bool atStart() const {
-    MOZ_ASSERT(ptr, "shouldn't be using if poisoned");
+    MOZ_ASSERT(!isPoisoned(), "shouldn't be using if poisoned");
     return ptr == base_;
   }
 
   bool atEnd() const {
+    MOZ_ASSERT(!isPoisoned(), "shouldn't be using if poisoned");
     MOZ_ASSERT(ptr <= limit_, "shouldn't have overrun");
     return ptr >= limit_;
   }
 
   size_t remaining() const {
-    MOZ_ASSERT(ptr, "can't get a count of remaining code units if poisoned");
+    MOZ_ASSERT(!isPoisoned(),
+               "can't get a count of remaining code units if poisoned");
     return mozilla::PointerRangeSize(ptr, limit_);
   }
 
   size_t startOffset() const { return startOffset_; }
 
   size_t offset() const {
     return startOffset_ + mozilla::PointerRangeSize(base_, ptr);
   }
 
   const Unit* codeUnitPtrAt(size_t offset) const {
+    MOZ_ASSERT(!isPoisoned(), "shouldn't be using if poisoned");
     MOZ_ASSERT(startOffset_ <= offset);
     MOZ_ASSERT(offset - startOffset_ <=
                mozilla::PointerRangeSize(base_, limit_));
     return base_ + (offset - startOffset_);
   }
 
   const Unit* current() const { return ptr; }
 
   const Unit* limit() const { return limit_; }
 
   Unit previousCodeUnit() {
-    MOZ_ASSERT(ptr, "can't get previous code unit if poisoned");
+    MOZ_ASSERT(!isPoisoned(), "can't get previous code unit if poisoned");
     MOZ_ASSERT(!atStart(), "must have a previous code unit to get");
     return *(ptr - 1);
   }
 
   Unit getCodeUnit() {
     return *ptr++;  // this will nullptr-crash if poisoned
   }
 
@@ -1256,17 +1259,17 @@ class SourceUnits {
     assertNextCodePoint(peeked);
 #endif
 
     ptr += peeked.lengthInUnits();
   }
 
   /** Match |n| hexadecimal digits and store their value in |*out|. */
   bool matchHexDigits(uint8_t n, char16_t* out) {
-    MOZ_ASSERT(ptr, "shouldn't peek into poisoned SourceUnits");
+    MOZ_ASSERT(!isPoisoned(), "shouldn't peek into poisoned SourceUnits");
     MOZ_ASSERT(n <= 4, "hexdigit value can't overflow char16_t");
     if (n > remaining()) {
       return false;
     }
 
     char16_t v = 0;
     for (uint8_t i = 0; i < n; i++) {
       auto unit = CodeUnitValue(ptr[i]);
@@ -1278,17 +1281,17 @@ class SourceUnits {
     }
 
     *out = v;
     ptr += n;
     return true;
   }
 
   bool matchCodeUnits(const char* chars, uint8_t length) {
-    MOZ_ASSERT(ptr, "shouldn't match into poisoned SourceUnits");
+    MOZ_ASSERT(!isPoisoned(), "shouldn't match into poisoned SourceUnits");
     if (length > remaining()) {
       return false;
     }
 
     const Unit* start = ptr;
     const Unit* end = ptr + length;
     while (ptr < end) {
       if (*ptr++ != Unit(*chars++)) {
@@ -1296,90 +1299,104 @@ class SourceUnits {
         return false;
       }
     }
 
     return true;
   }
 
   void skipCodeUnits(uint32_t n) {
-    MOZ_ASSERT(ptr, "shouldn't use poisoned SourceUnits");
+    MOZ_ASSERT(!isPoisoned(), "shouldn't use poisoned SourceUnits");
     MOZ_ASSERT(n <= remaining(), "shouldn't skip beyond end of SourceUnits");
     ptr += n;
   }
 
   void unskipCodeUnits(uint32_t n) {
-    MOZ_ASSERT(ptr, "shouldn't use poisoned SourceUnits");
+    MOZ_ASSERT(!isPoisoned(), "shouldn't use poisoned SourceUnits");
     MOZ_ASSERT(n <= mozilla::PointerRangeSize(base_, ptr),
                "shouldn't unskip beyond start of SourceUnits");
     ptr -= n;
   }
 
  private:
   friend class TokenStreamCharsBase<Unit>;
 
   bool internalMatchCodeUnit(Unit c) {
-    MOZ_ASSERT(ptr, "shouldn't use poisoned SourceUnits");
+    MOZ_ASSERT(!isPoisoned(), "shouldn't use poisoned SourceUnits");
     if (MOZ_LIKELY(!atEnd()) && *ptr == c) {
       ptr++;
       return true;
     }
     return false;
   }
 
  public:
   void consumeKnownCodeUnit(Unit c) {
-    MOZ_ASSERT(ptr, "shouldn't use poisoned SourceUnits");
+    MOZ_ASSERT(!isPoisoned(), "shouldn't use poisoned SourceUnits");
     MOZ_ASSERT(*ptr == c, "consuming the wrong code unit");
     ptr++;
   }
 
   /**
    * Unget the '\n' (CR) that precedes a '\n' (LF), when ungetting a line
    * terminator that's a full "\r\n" sequence.  If the prior code unit isn't
    * '\r', do nothing.
    */
   void ungetOptionalCRBeforeLF() {
-    MOZ_ASSERT(ptr, "shouldn't unget a '\\r' from poisoned SourceUnits");
+    MOZ_ASSERT(!isPoisoned(),
+               "shouldn't unget a '\\r' from poisoned SourceUnits");
     MOZ_ASSERT(*ptr == Unit('\n'),
                "function should only be called when a '\\n' was just "
                "ungotten, and any '\\r' preceding it must also be "
                "ungotten");
     if (*(ptr - 1) == Unit('\r')) {
       ptr--;
     }
   }
 
   /** Unget U+2028 LINE SEPARATOR or U+2029 PARAGRAPH SEPARATOR. */
   inline void ungetLineOrParagraphSeparator();
 
   void ungetCodeUnit() {
+    MOZ_ASSERT(!isPoisoned(), "can't unget from poisoned units");
     MOZ_ASSERT(!atStart(), "can't unget if currently at start");
-    MOZ_ASSERT(ptr);  // make sure it hasn't been poisoned
     ptr--;
   }
 
   const Unit* addressOfNextCodeUnit(bool allowPoisoned = false) const {
-    MOZ_ASSERT_IF(!allowPoisoned, ptr);  // make sure it hasn't been poisoned
+    MOZ_ASSERT_IF(!allowPoisoned, !isPoisoned());
     return ptr;
   }
 
   // Use this with caution!
   void setAddressOfNextCodeUnit(const Unit* a, bool allowPoisoned = false) {
     MOZ_ASSERT_IF(!allowPoisoned, a);
     ptr = a;
   }
 
   // Poison the SourceUnits so they can't be accessed again.
   void poisonInDebug() {
 #ifdef DEBUG
     ptr = nullptr;
 #endif
   }
 
+ private:
+  bool isPoisoned() const {
+#ifdef DEBUG
+    // |ptr| can be null for unpoisoned SourceUnits if this was initialized with
+    // |units == nullptr| and |length == 0|.  In that case, for lack of any
+    // better options, consider this to not be poisoned.
+    return ptr == nullptr && ptr != limit_;
+#else
+    return false;
+#endif
+  }
+
+ public:
   /**
    * Consume the rest of a single-line comment (but not the EOL/EOF that
    * terminates it).
    *
    * If an encoding error is encountered -- possible only for UTF-8 because
    * JavaScript's conception of UTF-16 encompasses any sequence of 16-bit
    * code units -- valid code points prior to the encoding error are consumed
    * and subsequent invalid code units are not consumed.  For example, given