Title: [113396] trunk/Source/_javascript_Core
Revision
113396
Author
[email protected]
Date
2012-04-05 17:12:25 -0700 (Thu, 05 Apr 2012)

Log Message

Speed up the conversion from JSValue to String for bulk operations
https://bugs.webkit.org/show_bug.cgi?id=83243

Patch by Benjamin Poulain <[email protected]> on 2012-04-05
Reviewed by Geoffrey Garen.

When making operations on primitive types, we loose some time converting
values to JSString in order to extract the string.

This patch speeds up some basic Array operations by avoiding the creation
of intermediary JSString when possible.

For the cases where we need to convert a lot of JSValue in a tight loop,
an inline conversion is used.

* runtime/ArrayPrototype.cpp:
(JSC::arrayProtoFuncToString):
(JSC::arrayProtoFuncToLocaleString):
(JSC::arrayProtoFuncJoin):
(JSC::arrayProtoFuncPush):
(JSC::arrayProtoFuncSort):
* runtime/CommonIdentifiers.h:
* runtime/JSArray.cpp:
(JSC::JSArray::sort):
* runtime/JSString.h:
(JSC::JSValue::toUString):
(JSC):
(JSC::inlineJSValueNotStringtoUString):
(JSC::JSValue::toUStringInline):
* runtime/JSValue.cpp:
(JSC::JSValue::toUStringSlowCase):
(JSC):
* runtime/JSValue.h:
(JSValue):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (113395 => 113396)


--- trunk/Source/_javascript_Core/ChangeLog	2012-04-05 23:54:06 UTC (rev 113395)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-04-06 00:12:25 UTC (rev 113396)
@@ -1,5 +1,41 @@
 2012-04-05  Benjamin Poulain  <[email protected]>
 
+        Speed up the conversion from JSValue to String for bulk operations
+        https://bugs.webkit.org/show_bug.cgi?id=83243
+
+        Reviewed by Geoffrey Garen.
+
+        When making operations on primitive types, we loose some time converting
+        values to JSString in order to extract the string.
+
+        This patch speeds up some basic Array operations by avoiding the creation
+        of intermediary JSString when possible.
+
+        For the cases where we need to convert a lot of JSValue in a tight loop,
+        an inline conversion is used.
+
+        * runtime/ArrayPrototype.cpp:
+        (JSC::arrayProtoFuncToString):
+        (JSC::arrayProtoFuncToLocaleString):
+        (JSC::arrayProtoFuncJoin):
+        (JSC::arrayProtoFuncPush):
+        (JSC::arrayProtoFuncSort):
+        * runtime/CommonIdentifiers.h:
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::sort):
+        * runtime/JSString.h:
+        (JSC::JSValue::toUString):
+        (JSC):
+        (JSC::inlineJSValueNotStringtoUString):
+        (JSC::JSValue::toUStringInline):
+        * runtime/JSValue.cpp:
+        (JSC::JSValue::toUStringSlowCase):
+        (JSC):
+        * runtime/JSValue.h:
+        (JSValue):
+
+2012-04-05  Benjamin Poulain  <[email protected]>
+
         Use QuickSort when sorting primitive values by string representation
         https://bugs.webkit.org/show_bug.cgi?id=83312
 

Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (113395 => 113396)


--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2012-04-05 23:54:06 UTC (rev 113395)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2012-04-06 00:12:25 UTC (rev 113396)
@@ -281,7 +281,7 @@
         if (element.isUndefinedOrNull())
             continue;
         
-        UString str = element.toString(exec)->value(exec);
+        UString str = element.toUString(exec);
         strBuffer[k] = str.impl();
         totalSize += str.length();
         allStrings8Bit = allStrings8Bit && str.is8Bit();
@@ -358,9 +358,9 @@
             CallData callData;
             CallType callType = getCallData(conversionFunction, callData);
             if (callType != CallTypeNone)
-                str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec)->value(exec);
+                str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toUString(exec);
             else
-                str = element.toString(exec)->value(exec);
+                str = element.toUString(exec);
             if (exec->hadException())
                 return JSValue::encode(jsUndefined());
             stringJoiner.append(str);
@@ -383,7 +383,7 @@
 
     UString separator;
     if (!exec->argument(0).isUndefined())
-        separator = exec->argument(0).toString(exec)->value(exec);
+        separator = exec->argument(0).toUString(exec);
     if (separator.isNull())
         separator = UString(",");
 
@@ -399,7 +399,7 @@
 
             JSValue element = array->getIndex(k);
             if (!element.isUndefinedOrNull())
-                stringJoiner.append(element.toString(exec)->value(exec));
+                stringJoiner.append(element.toUStringInline(exec));
             else
                 stringJoiner.append(UString());
         }
@@ -408,7 +408,7 @@
     for (; k < length; k++) {
         JSValue element = thisObj->get(exec, k);
         if (!element.isUndefinedOrNull())
-            stringJoiner.append(element.toString(exec)->value(exec));
+            stringJoiner.append(element.toUStringInline(exec));
         else
             stringJoiner.append(UString());
     }
@@ -501,7 +501,7 @@
             thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->argument(n), true);
         else {
             PutPropertySlot slot;
-            Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toString(exec)->value(exec));
+            Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toUString(exec));
             thisObj->methodTable()->put(thisObj, exec, propertyName, exec->argument(n), slot);
         }
         if (exec->hadException())
@@ -642,7 +642,7 @@
                 l.append(minObj);
                 compareResult = call(exec, function, callType, callData, jsUndefined(), l).toNumber(exec);
             } else
-                compareResult = (jObj.toString(exec)->value(exec) < minObj.toString(exec)->value(exec)) ? -1 : 1;
+                compareResult = (jObj.toUStringInline(exec) < minObj.toUStringInline(exec)) ? -1 : 1;
 
             if (compareResult < 0) {
                 themin = j;

Modified: trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h (113395 => 113396)


--- trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2012-04-05 23:54:06 UTC (rev 113395)
+++ trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2012-04-06 00:12:25 UTC (rev 113396)
@@ -76,6 +76,7 @@
 
 #define JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(macro) \
     macro(null) \
+    macro(undefined) \
     macro(true) \
     macro(false) \
     macro(break) \

Modified: trunk/Source/_javascript_Core/runtime/JSArray.cpp (113395 => 113396)


--- trunk/Source/_javascript_Core/runtime/JSArray.cpp	2012-04-05 23:54:06 UTC (rev 113395)
+++ trunk/Source/_javascript_Core/runtime/JSArray.cpp	2012-04-06 00:12:25 UTC (rev 113396)
@@ -1487,7 +1487,7 @@
     // a toString call raises an exception.
 
     for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
-        values[i].second = values[i].first.toString(exec)->value(exec);
+        values[i].second = values[i].first.toUStringInline(exec);
 
     if (exec->hadException()) {
         Heap::heap(this)->popTempSortVector(&values);

Modified: trunk/Source/_javascript_Core/runtime/JSString.h (113395 => 113396)


--- trunk/Source/_javascript_Core/runtime/JSString.h	2012-04-05 23:54:06 UTC (rev 113395)
+++ trunk/Source/_javascript_Core/runtime/JSString.h	2012-04-06 00:12:25 UTC (rev 113396)
@@ -462,6 +462,39 @@
         return toStringSlowCase(exec);
     }
 
+    inline UString JSValue::toUString(ExecState* exec) const
+    {
+        if (isString())
+            return static_cast<JSString*>(asCell())->value(exec);
+        return toUStringSlowCase(exec);
+    }
+
+    ALWAYS_INLINE UString inlineJSValueNotStringtoUString(const JSValue& value, ExecState* exec)
+    {
+        JSGlobalData& globalData = exec->globalData();
+        if (value.isInt32())
+            return globalData.numericStrings.add(value.asInt32());
+        if (value.isDouble())
+            return globalData.numericStrings.add(value.asDouble());
+        if (value.isTrue())
+            return globalData.propertyNames->trueKeyword.ustring();
+        if (value.isFalse())
+            return globalData.propertyNames->falseKeyword.ustring();
+        if (value.isNull())
+            return globalData.propertyNames->nullKeyword.ustring();
+        if (value.isUndefined())
+            return globalData.propertyNames->undefinedKeyword.ustring();
+        return value.toString(exec)->value(exec);
+    }
+
+    ALWAYS_INLINE UString JSValue::toUStringInline(ExecState* exec) const
+    {
+        if (isString())
+            return static_cast<JSString*>(asCell())->value(exec);
+
+        return inlineJSValueNotStringtoUString(*this, exec);
+    }
+
 } // namespace JSC
 
 #endif // JSString_h

Modified: trunk/Source/_javascript_Core/runtime/JSValue.cpp (113395 => 113396)


--- trunk/Source/_javascript_Core/runtime/JSValue.cpp	2012-04-05 23:54:06 UTC (rev 113395)
+++ trunk/Source/_javascript_Core/runtime/JSValue.cpp	2012-04-06 00:12:25 UTC (rev 113396)
@@ -283,4 +283,9 @@
     return value.toString(exec);
 }
 
+UString JSValue::toUStringSlowCase(ExecState* exec) const
+{
+    return inlineJSValueNotStringtoUString(*this, exec);
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/JSValue.h (113395 => 113396)


--- trunk/Source/_javascript_Core/runtime/JSValue.h	2012-04-05 23:54:06 UTC (rev 113395)
+++ trunk/Source/_javascript_Core/runtime/JSValue.h	2012-04-06 00:12:25 UTC (rev 113396)
@@ -203,6 +203,8 @@
         // been set in the ExecState already.
         double toNumber(ExecState*) const;
         JSString* toString(ExecState*) const;
+        UString toUString(ExecState*) const;
+        UString toUStringInline(ExecState*) const;
         JSObject* toObject(ExecState*) const;
         JSObject* toObject(ExecState*, JSGlobalObject*) const;
 
@@ -251,6 +253,7 @@
         inline const JSValue asValue() const { return *this; }
         JS_EXPORT_PRIVATE double toNumberSlowCase(ExecState*) const;
         JS_EXPORT_PRIVATE JSString* toStringSlowCase(ExecState*) const;
+        JS_EXPORT_PRIVATE UString toUStringSlowCase(ExecState*) const;
         JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
         JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const;
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to