Title: [240992] trunk/Source/_javascript_Core
Revision
240992
Author
andy@vanwagoner.family
Date
2019-02-05 14:09:32 -0800 (Tue, 05 Feb 2019)

Log Message

[INTL] improve efficiency of Intl.NumberFormat formatToParts
https://bugs.webkit.org/show_bug.cgi?id=185557

Reviewed by Mark Lam.

Since field nesting depth is minimal, this algorithm should be effectively O(n),
where n is the number of characters in the formatted string.
It may be less memory efficient than the previous impl, since the intermediate Vector
is the length of the string, instead of the count of the fields.

* runtime/IntlNumberFormat.cpp:
(JSC::IntlNumberFormat::formatToParts):
* runtime/IntlNumberFormat.h:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (240991 => 240992)


--- trunk/Source/_javascript_Core/ChangeLog	2019-02-05 21:59:52 UTC (rev 240991)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-02-05 22:09:32 UTC (rev 240992)
@@ -1,3 +1,19 @@
+2019-02-05  Andy VanWagoner  <andy@vanwagoner.family>
+
+        [INTL] improve efficiency of Intl.NumberFormat formatToParts
+        https://bugs.webkit.org/show_bug.cgi?id=185557
+
+        Reviewed by Mark Lam.
+
+        Since field nesting depth is minimal, this algorithm should be effectively O(n),
+        where n is the number of characters in the formatted string.
+        It may be less memory efficient than the previous impl, since the intermediate Vector
+        is the length of the string, instead of the count of the fields.
+
+        * runtime/IntlNumberFormat.cpp:
+        (JSC::IntlNumberFormat::formatToParts):
+        * runtime/IntlNumberFormat.h:
+
 2019-02-05  Mark Lam  <mark....@apple.com>
 
         Move DFG nodes that clobberize() says will write(Heap) to the doesGC() list that returns true.

Modified: trunk/Source/_javascript_Core/runtime/IntlNumberFormat.cpp (240991 => 240992)


--- trunk/Source/_javascript_Core/runtime/IntlNumberFormat.cpp	2019-02-05 21:59:52 UTC (rev 240991)
+++ trunk/Source/_javascript_Core/runtime/IntlNumberFormat.cpp	2019-02-05 22:09:32 UTC (rev 240992)
@@ -510,16 +510,19 @@
     if (U_FAILURE(status))
         return throwTypeError(&exec, scope, "failed to format a number."_s);
 
-    Vector<IntlNumberFormatField> fields;
+    int32_t literalFieldType = -1;
+    auto literalField = IntlNumberFormatField(literalFieldType, resultLength);
+    Vector<IntlNumberFormatField> fields(resultLength, literalField);
     int32_t beginIndex = 0;
     int32_t endIndex = 0;
     auto fieldType = ufieldpositer_next(fieldItr.get(), &beginIndex, &endIndex);
     while (fieldType >= 0) {
-        IntlNumberFormatField field;
-        field.type = UNumberFormatFields(fieldType);
-        field.beginIndex = beginIndex;
-        field.endIndex = endIndex;
-        fields.append(field);
+        auto size = endIndex - beginIndex;
+        for (auto i = beginIndex; i < endIndex; ++i) {
+            // Only override previous value if new value is more specific.
+            if (fields[i].size >= size)
+                fields[i] = IntlNumberFormatField(fieldType, size);
+        }
         fieldType = ufieldpositer_next(fieldItr.get(), &beginIndex, &endIndex);
     }
 
@@ -533,29 +536,21 @@
     auto typePropertyName = Identifier::fromString(&vm, "type");
     auto literalString = jsString(&exec, "literal"_s);
 
-    // FIXME: <http://webkit.org/b/185557> This is O(N^2) and could be done in O(N log N).
     int32_t currentIndex = 0;
     while (currentIndex < resultLength) {
-        IntlNumberFormatField field;
-        int32_t nextStartIndex = resultLength;
-        for (const auto &candidate : fields) {
-            if (candidate.beginIndex <= currentIndex && currentIndex < candidate.endIndex && (!field.size() || candidate.size() < field.size()))
-                field = candidate;
-            if (currentIndex < candidate.beginIndex && candidate.beginIndex < nextStartIndex)
-                nextStartIndex = candidate.beginIndex;
-        }
-        auto nextIndex = field.size() ? std::min(field.endIndex, nextStartIndex) : nextStartIndex;
-        auto type = field.size() ? jsString(&exec, partTypeString(field.type, value)) : literalString;
-        auto value = jsSubstring(&vm, resultString, currentIndex, nextIndex - currentIndex);
+        auto startIndex = currentIndex;
+        auto fieldType = fields[currentIndex].type;
+        while (currentIndex < resultLength && fields[currentIndex].type == fieldType)
+            ++currentIndex;
+        auto partType = fieldType == literalFieldType ? literalString : jsString(&exec, partTypeString(UNumberFormatFields(fieldType), value));
+        auto partValue = jsSubstring(&vm, resultString, startIndex, currentIndex - startIndex);
         JSObject* part = constructEmptyObject(&exec);
-        part->putDirect(vm, typePropertyName, type);
-        part->putDirect(vm, vm.propertyNames->value, value);
+        part->putDirect(vm, typePropertyName, partType);
+        part->putDirect(vm, vm.propertyNames->value, partValue);
         parts->putDirectIndex(&exec, index++, part);
         RETURN_IF_EXCEPTION(scope, { });
-        currentIndex = nextIndex;
     }
 
-
     return parts;
 }
 #endif

Modified: trunk/Source/_javascript_Core/runtime/IntlNumberFormat.h (240991 => 240992)


--- trunk/Source/_javascript_Core/runtime/IntlNumberFormat.h	2019-02-05 21:59:52 UTC (rev 240991)
+++ trunk/Source/_javascript_Core/runtime/IntlNumberFormat.h	2019-02-05 22:09:32 UTC (rev 240992)
@@ -95,13 +95,12 @@
     };
 
     struct IntlNumberFormatField {
-        UNumberFormatFields type;
-        int32_t beginIndex { 0 };
-        int32_t endIndex { 0 };
-        int32_t size() const
-        {
-            return endIndex - beginIndex;
-        };
+        int32_t type;
+        int32_t size;
+        IntlNumberFormatField(int32_t type, int32_t size)
+            : type(type)
+            , size(size)
+        { }
     };
 
     static ASCIILiteral partTypeString(UNumberFormatFields, double);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to