Bug 1319464: Replace flattened with linear strings in Intl.cpp file. r=Waldo
☠☠ backed out by 00df72027708 ☠ ☠
authorAndré Bargull <andre.bargull@gmail.com>
Tue, 22 Nov 2016 09:29:49 -0800
changeset 323926 7251919f6a2318ab715085c4162d927455bae6b7
parent 323925 ee1dffb984713e7d745be4261a7509e6477bfca4
child 323927 aabf76e98464f96bcee92c111286ffe939b98700
push id84274
push usercbook@mozilla.com
push dateWed, 23 Nov 2016 15:56:25 +0000
treeherdermozilla-inbound@aabf76e98464 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1319464
milestone53.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 1319464: Replace flattened with linear strings in Intl.cpp file. r=Waldo
js/src/builtin/Intl.cpp
js/src/builtin/Intl.h
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -99,22 +99,16 @@ Char16ToUChar(const char16_t* chars)
 }
 
 inline UChar*
 Char16ToUChar(char16_t* chars)
 {
     MOZ_CRASH("Char16ToUChar: Intl API disabled");
 }
 
-int32_t
-u_strlen(const UChar* s)
-{
-    MOZ_CRASH("u_strlen: Intl API disabled");
-}
-
 struct UEnumeration;
 
 int32_t
 uenum_count(UEnumeration* en, UErrorCode* status)
 {
     MOZ_CRASH("uenum_count: Intl API disabled");
 }
 
@@ -1519,22 +1513,20 @@ NewUNumberFormat(JSContext* cx, HandleOb
         return nullptr;
 
     if (equal(style, "currency")) {
         if (!GetProperty(cx, internals, internals, cx->names().currency, &value))
             return nullptr;
         currency = value.toString();
         MOZ_ASSERT(currency->length() == 3,
                    "IsWellFormedCurrencyCode permits only length-3 strings");
-        if (!currency->ensureFlat(cx) || !stableChars.initTwoByte(cx, currency))
+        if (!stableChars.initTwoByte(cx, currency))
             return nullptr;
         // uCurrency remains owned by stableChars.
         uCurrency = Char16ToUChar(stableChars.twoByteRange().begin().get());
-        if (!uCurrency)
-            return nullptr;
 
         if (!GetProperty(cx, internals, internals, cx->names().currencyDisplay, &value))
             return nullptr;
         JSAutoByteString currencyDisplay(cx, value.toString());
         if (!currencyDisplay)
             return nullptr;
         if (equal(currencyDisplay, "code")) {
             uStyle = UNUM_CURRENCY_ISO;
@@ -1629,29 +1621,31 @@ intl_FormatNumber(JSContext* cx, UNumber
     // FormatNumber doesn't consider -0.0 to be negative.
     if (IsNegativeZero(x))
         x = 0.0;
 
     Vector<char16_t, INITIAL_CHAR_BUFFER_SIZE> chars(cx);
     if (!chars.resize(INITIAL_CHAR_BUFFER_SIZE))
         return false;
     UErrorCode status = U_ZERO_ERROR;
-    int size = unum_formatDouble(nf, x, Char16ToUChar(chars.begin()), INITIAL_CHAR_BUFFER_SIZE,
-                                 nullptr, &status);
+    int32_t size = unum_formatDouble(nf, x, Char16ToUChar(chars.begin()), INITIAL_CHAR_BUFFER_SIZE,
+                                     nullptr, &status);
     if (status == U_BUFFER_OVERFLOW_ERROR) {
+        MOZ_ASSERT(size >= 0);
         if (!chars.resize(size))
             return false;
         status = U_ZERO_ERROR;
         unum_formatDouble(nf, x, Char16ToUChar(chars.begin()), size, nullptr, &status);
     }
     if (U_FAILURE(status)) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
         return false;
     }
 
+    MOZ_ASSERT(size >= 0);
     JSString* str = NewStringCopyN<CanGC>(cx, chars.begin(), size);
     if (!str)
         return false;
 
     result.setString(str);
     return true;
 }
 
@@ -2043,17 +2037,17 @@ static js::HashNumber
 HashStringIgnoreCaseASCII(const Char* s, size_t length)
 {
     uint32_t hash = 0;
     for (size_t i = 0; i < length; i++)
         hash = mozilla::AddToHash(hash, ToUpperASCII(s[i]));
     return hash;
 }
 
-js::SharedIntlData::TimeZoneHasher::Lookup::Lookup(JSFlatString* timeZone)
+js::SharedIntlData::TimeZoneHasher::Lookup::Lookup(JSLinearString* timeZone)
   : isLatin1(timeZone->hasLatin1Chars()), length(timeZone->length())
 {
     if (isLatin1) {
         latin1Chars = timeZone->latin1Chars(nogc);
         hash = HashStringIgnoreCaseASCII(latin1Chars, length);
     } else {
         twoByteChars = timeZone->twoByteChars(nogc);
         hash = HashStringIgnoreCaseASCII(twoByteChars, length);
@@ -2209,39 +2203,39 @@ js::SharedIntlData::ensureTimeZones(JSCo
 
 bool
 js::SharedIntlData::validateTimeZoneName(JSContext* cx, HandleString timeZone,
                                          MutableHandleString result)
 {
     if (!ensureTimeZones(cx))
         return false;
 
-    Rooted<JSFlatString*> timeZoneFlat(cx, timeZone->ensureFlat(cx));
-    if (!timeZoneFlat)
+    RootedLinearString timeZoneLinear(cx, timeZone->ensureLinear(cx));
+    if (!timeZoneLinear)
         return false;
 
-    TimeZoneHasher::Lookup lookup(timeZoneFlat);
+    TimeZoneHasher::Lookup lookup(timeZoneLinear);
     if (TimeZoneSet::Ptr p = availableTimeZones.lookup(lookup))
         result.set(*p);
 
     return true;
 }
 
 bool
 js::SharedIntlData::tryCanonicalizeTimeZoneConsistentWithIANA(JSContext* cx, HandleString timeZone,
                                                               MutableHandleString result)
 {
     if (!ensureTimeZones(cx))
         return false;
 
-    Rooted<JSFlatString*> timeZoneFlat(cx, timeZone->ensureFlat(cx));
-    if (!timeZoneFlat)
+    RootedLinearString timeZoneLinear(cx, timeZone->ensureLinear(cx));
+    if (!timeZoneLinear)
         return false;
 
-    TimeZoneHasher::Lookup lookup(timeZoneFlat);
+    TimeZoneHasher::Lookup lookup(timeZoneLinear);
     MOZ_ASSERT(availableTimeZones.has(lookup), "Invalid time zone name");
 
     if (TimeZoneMap::Ptr p = ianaLinksCanonicalizedDifferentlyByICU.lookup(lookup)) {
         // The effectively supported time zones aren't known at compile time,
         // when
         // 1. SpiderMonkey was compiled with "--with-system-icu".
         // 2. ICU's dynamic time zone data loading feature was used.
         //    (ICU supports loading time zone files at runtime through the
@@ -2435,54 +2429,52 @@ js::intl_patternForSkeleton(JSContext* c
     MOZ_ASSERT(args.length() == 2);
     MOZ_ASSERT(args[0].isString());
     MOZ_ASSERT(args[1].isString());
 
     JSAutoByteString locale(cx, args[0].toString());
     if (!locale)
         return false;
 
-    JSFlatString* skeletonFlat = args[1].toString()->ensureFlat(cx);
-    if (!skeletonFlat)
+    AutoStableStringChars skeleton(cx);
+    if (!skeleton.initTwoByte(cx, args[1].toString()))
         return false;
 
-    AutoStableStringChars stableChars(cx);
-    if (!stableChars.initTwoByte(cx, skeletonFlat))
-        return false;
-
-    mozilla::Range<const char16_t> skeletonChars = stableChars.twoByteRange();
-    uint32_t skeletonLen = u_strlen(Char16ToUChar(skeletonChars.begin().get()));
+    mozilla::Range<const char16_t> skeletonChars = skeleton.twoByteRange();
 
     UErrorCode status = U_ZERO_ERROR;
     UDateTimePatternGenerator* gen = udatpg_open(icuLocale(locale.ptr()), &status);
     if (U_FAILURE(status)) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
         return false;
     }
     ScopedICUObject<UDateTimePatternGenerator, udatpg_close> toClose(gen);
 
+    Vector<char16_t, INITIAL_CHAR_BUFFER_SIZE> chars(cx);
+    if (!chars.resize(INITIAL_CHAR_BUFFER_SIZE))
+        return false;
+
     int32_t size = udatpg_getBestPattern(gen, Char16ToUChar(skeletonChars.begin().get()),
-                                         skeletonLen, nullptr, 0, &status);
-    if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR) {
-        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
-        return false;
+                                         skeletonChars.length(), Char16ToUChar(chars.begin()),
+                                         INITIAL_CHAR_BUFFER_SIZE, &status);
+    if (status == U_BUFFER_OVERFLOW_ERROR) {
+        MOZ_ASSERT(size >= 0);
+        if (!chars.resize(size))
+            return false;
+        status = U_ZERO_ERROR;
+        udatpg_getBestPattern(gen, Char16ToUChar(skeletonChars.begin().get()),
+                              skeletonChars.length(), Char16ToUChar(chars.begin()), size, &status);
     }
-    ScopedJSFreePtr<UChar> pattern(cx->pod_malloc<UChar>(size + 1));
-    if (!pattern)
-        return false;
-    pattern[size] = '\0';
-    status = U_ZERO_ERROR;
-    udatpg_getBestPattern(gen, Char16ToUChar(skeletonChars.begin().get()),
-                          skeletonLen, pattern, size, &status);
     if (U_FAILURE(status)) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
         return false;
     }
 
-    RootedString str(cx, JS_NewUCStringCopyZ(cx, reinterpret_cast<char16_t*>(pattern.get())));
+    MOZ_ASSERT(size >= 0);
+    JSString* str = NewStringCopyN<CanGC>(cx, chars.begin(), size);
     if (!str)
         return false;
     args.rval().setString(str);
     return true;
 }
 
 /**
  * Returns a new UDateFormat with the locale and date-time formatting options
@@ -2505,39 +2497,36 @@ NewUDateFormat(JSContext* cx, HandleObje
 
     // We don't need to look at calendar and numberingSystem - they can only be
     // set via the Unicode locale extension and are therefore already set on
     // locale.
 
     if (!GetProperty(cx, internals, internals, cx->names().timeZone, &value))
         return nullptr;
 
-    AutoStableStringChars timeZoneChars(cx);
-    Rooted<JSFlatString*> timeZoneFlat(cx, value.toString()->ensureFlat(cx));
-    if (!timeZoneFlat || !timeZoneChars.initTwoByte(cx, timeZoneFlat))
+    AutoStableStringChars timeZone(cx);
+    if (!timeZone.initTwoByte(cx, value.toString()))
         return nullptr;
 
-    const UChar* uTimeZone = Char16ToUChar(timeZoneChars.twoByteRange().begin().get());
-    uint32_t uTimeZoneLength = u_strlen(uTimeZone);
+    mozilla::Range<const char16_t> timeZoneChars = timeZone.twoByteRange();
 
     if (!GetProperty(cx, internals, internals, cx->names().pattern, &value))
         return nullptr;
 
-    AutoStableStringChars patternChars(cx);
-    Rooted<JSFlatString*> patternFlat(cx, value.toString()->ensureFlat(cx));
-    if (!patternFlat || !patternChars.initTwoByte(cx, patternFlat))
+    AutoStableStringChars pattern(cx);
+    if (!pattern.initTwoByte(cx, value.toString()))
         return nullptr;
 
-    const UChar* uPattern = Char16ToUChar(patternChars.twoByteRange().begin().get());
-    uint32_t uPatternLength = u_strlen(uPattern);
+    mozilla::Range<const char16_t> patternChars = pattern.twoByteRange();
 
     UErrorCode status = U_ZERO_ERROR;
     UDateFormat* df =
-        udat_open(UDAT_PATTERN, UDAT_PATTERN, icuLocale(locale.ptr()), uTimeZone, uTimeZoneLength,
-                  uPattern, uPatternLength, &status);
+        udat_open(UDAT_PATTERN, UDAT_PATTERN, icuLocale(locale.ptr()),
+                  Char16ToUChar(timeZoneChars.begin().get()), timeZoneChars.length(),
+                  Char16ToUChar(patternChars.begin().get()), patternChars.length(), &status);
     if (U_FAILURE(status)) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
         return nullptr;
     }
 
     // ECMAScript requires the Gregorian calendar to be used from the beginning
     // of ECMAScript time.
     UCalendar* cal = const_cast<UCalendar*>(udat_getCalendar(df));
@@ -2555,29 +2544,31 @@ intl_FormatDateTime(JSContext* cx, UDate
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DATE_NOT_FINITE);
         return false;
     }
 
     Vector<char16_t, INITIAL_CHAR_BUFFER_SIZE> chars(cx);
     if (!chars.resize(INITIAL_CHAR_BUFFER_SIZE))
         return false;
     UErrorCode status = U_ZERO_ERROR;
-    int size = udat_format(df, x, Char16ToUChar(chars.begin()), INITIAL_CHAR_BUFFER_SIZE,
-                           nullptr, &status);
+    int32_t size = udat_format(df, x, Char16ToUChar(chars.begin()), INITIAL_CHAR_BUFFER_SIZE,
+                               nullptr, &status);
     if (status == U_BUFFER_OVERFLOW_ERROR) {
+        MOZ_ASSERT(size >= 0);
         if (!chars.resize(size))
             return false;
         status = U_ZERO_ERROR;
         udat_format(df, x, Char16ToUChar(chars.begin()), size, nullptr, &status);
     }
     if (U_FAILURE(status)) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
         return false;
     }
 
+    MOZ_ASSERT(size >= 0);
     JSString* str = NewStringCopyN<CanGC>(cx, chars.begin(), size);
     if (!str)
         return false;
 
     result.setString(str);
 
     return true;
 }
@@ -2685,33 +2676,36 @@ intl_FormatToPartsDateTime(JSContext* cx
     UErrorCode status = U_ZERO_ERROR;
     UFieldPositionIterator* fpositer = ufieldpositer_open(&status);
     if (U_FAILURE(status)) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
         return false;
     }
     auto closeFieldPosIter = MakeScopeExit([&]() { ufieldpositer_close(fpositer); });
 
-    int resultSize =
+    int32_t resultSize =
         udat_formatForFields(df, x, Char16ToUChar(chars.begin()), INITIAL_CHAR_BUFFER_SIZE,
                              fpositer, &status);
     if (status == U_BUFFER_OVERFLOW_ERROR) {
+        MOZ_ASSERT(resultSize >= 0);
         if (!chars.resize(resultSize))
             return false;
         status = U_ZERO_ERROR;
         udat_formatForFields(df, x, Char16ToUChar(chars.begin()), resultSize, fpositer, &status);
     }
     if (U_FAILURE(status)) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
         return false;
     }
 
     RootedArrayObject partsArray(cx, NewDenseEmptyArray(cx));
     if (!partsArray)
         return false;
+
+    MOZ_ASSERT(resultSize >= 0);
     if (resultSize == 0) {
         // An empty string contains no parts, so avoid extra work below.
         result.setObject(*partsArray);
         return true;
     }
 
     RootedString overallResult(cx, NewStringCopyN<CanGC>(cx, chars.begin(), resultSize));
     if (!overallResult)
--- a/js/src/builtin/Intl.h
+++ b/js/src/builtin/Intl.h
@@ -77,17 +77,17 @@ class SharedIntlData
                 const JS::Latin1Char* latin1Chars;
                 const char16_t* twoByteChars;
             };
             bool isLatin1;
             size_t length;
             JS::AutoCheckCannotGC nogc;
             HashNumber hash;
 
-            explicit Lookup(JSFlatString* timeZone);
+            explicit Lookup(JSLinearString* timeZone);
         };
 
         static js::HashNumber hash(const Lookup& lookup) { return lookup.hash; }
         static bool match(TimeZoneName key, const Lookup& lookup);
     };
 
     using TimeZoneSet = js::GCHashSet<TimeZoneName,
                                       TimeZoneHasher,