Bug 1269755 - Don't report OOM in ConcatStrings<NoGC> r=jandem
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 29 Sep 2016 10:18:50 +0100
changeset 315818 d9b67ef4fb0a2f2de2c398034ffe027c07aae8e9
parent 315817 955340c5cf9eff6f6aa79c88f656fa27428fb12f
child 315819 6a996a75330fb7d4376b4ed6d439126d8b5a50a2
push id20634
push usercbook@mozilla.com
push dateFri, 30 Sep 2016 10:10:13 +0000
treeherderfx-team@afe79b010d13 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1269755
milestone52.0a1
Bug 1269755 - Don't report OOM in ConcatStrings<NoGC> r=jandem
js/src/vm/String.cpp
--- a/js/src/vm/String.cpp
+++ b/js/src/vm/String.cpp
@@ -572,16 +572,27 @@ JSRope::flatten(ExclusiveContext* maybec
         sps.emplace(maybecx->asJSContext()->runtime(), "JSRope::flatten");
 
     if (zone()->needsIncrementalBarrier())
         return flattenInternal<WithIncrementalBarrier>(maybecx);
     return flattenInternal<NoBarrier>(maybecx);
 }
 
 template <AllowGC allowGC>
+static JSLinearString*
+EnsureLinear(ExclusiveContext* cx, typename MaybeRooted<JSString*, allowGC>::HandleType string)
+{
+    JSLinearString* linear = string->ensureLinear(cx);
+    // Don't report an exception if GC is not allowed, just return nullptr.
+    if (!linear && !allowGC)
+        cx->recoverFromOutOfMemory();
+    return linear;
+}
+
+template <AllowGC allowGC>
 JSString*
 js::ConcatStrings(ExclusiveContext* cx,
                   typename MaybeRooted<JSString*, allowGC>::HandleType left,
                   typename MaybeRooted<JSString*, allowGC>::HandleType right)
 {
     MOZ_ASSERT_IF(!left->isAtom(), cx->isInsideCurrentZone(left));
     MOZ_ASSERT_IF(!right->isAtom(), cx->isInsideCurrentZone(right));
 
@@ -589,37 +600,41 @@ js::ConcatStrings(ExclusiveContext* cx,
     if (leftLen == 0)
         return right;
 
     size_t rightLen = right->length();
     if (rightLen == 0)
         return left;
 
     size_t wholeLength = leftLen + rightLen;
-    if (!JSString::validateLength(cx, wholeLength))
+    if (MOZ_UNLIKELY(wholeLength > JSString::MAX_LENGTH)) {
+        // Don't report an exception if GC is not allowed, just return nullptr.
+        if (allowGC)
+            js::ReportAllocationOverflow(cx);
         return nullptr;
+    }
 
     bool isLatin1 = left->hasLatin1Chars() && right->hasLatin1Chars();
     bool canUseInline = isLatin1
                         ? JSInlineString::lengthFits<Latin1Char>(wholeLength)
                         : JSInlineString::lengthFits<char16_t>(wholeLength);
     if (canUseInline && cx->isJSContext()) {
         Latin1Char* latin1Buf = nullptr;  // initialize to silence GCC warning
         char16_t* twoByteBuf = nullptr;  // initialize to silence GCC warning
         JSInlineString* str = isLatin1
             ? AllocateInlineString<allowGC>(cx, wholeLength, &latin1Buf)
             : AllocateInlineString<allowGC>(cx, wholeLength, &twoByteBuf);
         if (!str)
             return nullptr;
 
         AutoCheckCannotGC nogc;
-        JSLinearString* leftLinear = left->ensureLinear(cx);
+        JSLinearString* leftLinear = EnsureLinear<allowGC>(cx, left);
         if (!leftLinear)
             return nullptr;
-        JSLinearString* rightLinear = right->ensureLinear(cx);
+        JSLinearString* rightLinear = EnsureLinear<allowGC>(cx, right);
         if (!rightLinear)
             return nullptr;
 
         if (isLatin1) {
             PodCopy(latin1Buf, leftLinear->latin1Chars(nogc), leftLen);
             PodCopy(latin1Buf + leftLen, rightLinear->latin1Chars(nogc), rightLen);
             latin1Buf[wholeLength] = 0;
         } else {