Title: [198256] trunk/Source/_javascript_Core
Revision
198256
Author
[email protected]
Date
2016-03-15 19:16:40 -0700 (Tue, 15 Mar 2016)

Log Message

[JSC] Help clang generate better code on arrayProtoFuncToString()
https://bugs.webkit.org/show_bug.cgi?id=155512

Patch by Benjamin Poulain <[email protected]> on 2016-03-15
Reviewed by Mark Lam.

3d-raytrace hits Array.toString() hard with small arrays.
Half of the time is going into overhead around the StringJoiner.
This patch makes the function shorter and the layout better.

* runtime/ArrayPrototype.cpp:
(JSC::arrayProtoFuncToString):
Add "UNLIKELY" on rare cases. Clang pushes that code to the tail.

Factor the code of jsMakeNontrivialString() so that the operation
is not duplicated in the function.

* runtime/JSStringBuilder.h:
(JSC::jsMakeNontrivialString):
jsNontrivialString() supports r-value reference.
Move the result string into jsNontrivialString(), this removes
the deref+destructor from the function.

* runtime/JSStringJoiner.cpp:
(JSC::JSStringJoiner::~JSStringJoiner):
The destructor is pretty large. No point in inlining it.

(JSC::joinStrings):
* runtime/JSStringJoiner.h:
(JSC::JSStringJoiner::JSStringJoiner):
(JSC::JSStringJoiner::append):
The calls were duplicated. That's unnecessary.

* runtime/NumericStrings.h:
(JSC::NumericStrings::add):
Return a reference in all cases.
This removes a deref+destructor.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (198255 => 198256)


--- trunk/Source/_javascript_Core/ChangeLog	2016-03-16 01:51:12 UTC (rev 198255)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-03-16 02:16:40 UTC (rev 198256)
@@ -1,3 +1,42 @@
+2016-03-15  Benjamin Poulain  <[email protected]>
+
+        [JSC] Help clang generate better code on arrayProtoFuncToString()
+        https://bugs.webkit.org/show_bug.cgi?id=155512
+
+        Reviewed by Mark Lam.
+
+        3d-raytrace hits Array.toString() hard with small arrays.
+        Half of the time is going into overhead around the StringJoiner.
+        This patch makes the function shorter and the layout better.
+
+        * runtime/ArrayPrototype.cpp:
+        (JSC::arrayProtoFuncToString):
+        Add "UNLIKELY" on rare cases. Clang pushes that code to the tail.
+
+        Factor the code of jsMakeNontrivialString() so that the operation
+        is not duplicated in the function.
+
+        * runtime/JSStringBuilder.h:
+        (JSC::jsMakeNontrivialString):
+        jsNontrivialString() supports r-value reference.
+        Move the result string into jsNontrivialString(), this removes
+        the deref+destructor from the function.
+
+        * runtime/JSStringJoiner.cpp:
+        (JSC::JSStringJoiner::~JSStringJoiner):
+        The destructor is pretty large. No point in inlining it.
+
+        (JSC::joinStrings):
+        * runtime/JSStringJoiner.h:
+        (JSC::JSStringJoiner::JSStringJoiner):
+        (JSC::JSStringJoiner::append):
+        The calls were duplicated. That's unnecessary.
+
+        * runtime/NumericStrings.h:
+        (JSC::NumericStrings::add):
+        Return a reference in all cases.
+        This removes a deref+destructor.
+
 2016-03-15  Joseph Pecoraro  <[email protected]>
 
         Remove stale ArrayPrototype declarations

Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (198255 => 198256)


--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2016-03-16 01:51:12 UTC (rev 198255)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2016-03-16 02:16:40 UTC (rev 198256)
@@ -322,18 +322,23 @@
 
     // 1. Let array be the result of calling ToObject on the this value.
     JSObject* thisObject = thisValue.toObject(exec);
-    if (exec->hadException())
+    VM& vm = exec->vm();
+    if (UNLIKELY(vm.exception()))
         return JSValue::encode(jsUndefined());
     
     // 2. Let func be the result of calling the [[Get]] internal method of array with argument "join".
     JSValue function = JSValue(thisObject).get(exec, exec->propertyNames().join);
 
     // 3. If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2).
+    bool customJoinCase = false;
     if (!function.isCell())
-        return JSValue::encode(jsMakeNontrivialString(exec, "[object ", thisObject->methodTable(exec->vm())->className(thisObject), "]"));
+        customJoinCase = true;
     CallData callData;
     CallType callType = getCallData(function, callData);
     if (callType == CallType::None)
+        customJoinCase = true;
+
+    if (UNLIKELY(customJoinCase))
         return JSValue::encode(jsMakeNontrivialString(exec, "[object ", thisObject->methodTable(exec->vm())->className(thisObject), "]"));
 
     // 4. Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list.
@@ -350,18 +355,18 @@
         return JSValue::encode(earlyReturnValue);
 
     JSStringJoiner joiner(*exec, ',', length);
-    if (exec->hadException())
+    if (UNLIKELY(vm.exception()))
         return JSValue::encode(jsUndefined());
 
     for (unsigned i = 0; i < length; ++i) {
         JSValue element = thisArray->tryGetIndexQuickly(i);
         if (!element) {
             element = thisArray->get(exec, i);
-            if (exec->hadException())
+            if (UNLIKELY(vm.exception()))
                 return JSValue::encode(jsUndefined());
         }
         joiner.append(*exec, element);
-        if (exec->hadException())
+        if (UNLIKELY(vm.exception()))
             return JSValue::encode(jsUndefined());
     }
 

Modified: trunk/Source/_javascript_Core/runtime/JSStringBuilder.h (198255 => 198256)


--- trunk/Source/_javascript_Core/runtime/JSStringBuilder.h	2016-03-16 01:51:12 UTC (rev 198255)
+++ trunk/Source/_javascript_Core/runtime/JSStringBuilder.h	2016-03-16 02:16:40 UTC (rev 198256)
@@ -130,7 +130,7 @@
     String result = WTF::tryMakeString(string, strings...);
     if (!result)
         return throwOutOfMemoryError(exec);
-    return jsNontrivialString(exec, result);
+    return jsNontrivialString(exec, WTFMove(result));
 }
 
 }

Modified: trunk/Source/_javascript_Core/runtime/JSStringJoiner.cpp (198255 => 198256)


--- trunk/Source/_javascript_Core/runtime/JSStringJoiner.cpp	2016-03-16 01:51:12 UTC (rev 198255)
+++ trunk/Source/_javascript_Core/runtime/JSStringJoiner.cpp	2016-03-16 02:16:40 UTC (rev 198256)
@@ -30,6 +30,10 @@
 
 namespace JSC {
 
+JSStringJoiner::~JSStringJoiner()
+{
+}
+
 template<typename CharacterType>
 static inline void appendStringToData(CharacterType*& data, StringView string)
 {
@@ -44,7 +48,7 @@
 
     CharacterType* data;
     String result = StringImpl::tryCreateUninitialized(joinedLength, data);
-    if (result.isNull())
+    if (UNLIKELY(result.isNull()))
         return result;
 
     appendStringToData(data, strings[0].view);

Modified: trunk/Source/_javascript_Core/runtime/JSStringJoiner.h (198255 => 198256)


--- trunk/Source/_javascript_Core/runtime/JSStringJoiner.h	2016-03-16 01:51:12 UTC (rev 198255)
+++ trunk/Source/_javascript_Core/runtime/JSStringJoiner.h	2016-03-16 02:16:40 UTC (rev 198256)
@@ -35,6 +35,7 @@
 public:
     JSStringJoiner(ExecState&, LChar separator, unsigned stringCount);
     JSStringJoiner(ExecState&, StringView separator, unsigned stringCount);
+    ~JSStringJoiner();
 
     void append(ExecState&, JSValue);
     void appendEmptyString();
@@ -58,7 +59,7 @@
     : m_separator(separator)
     , m_isAll8Bit(m_separator.is8Bit())
 {
-    if (!m_strings.tryReserveCapacity(stringCount))
+    if (UNLIKELY(!m_strings.tryReserveCapacity(stringCount)))
         throwOutOfMemoryError(&state);
 }
 
@@ -66,7 +67,7 @@
     : m_singleCharacterSeparator(separator)
     , m_separator { &m_singleCharacterSeparator, 1 }
 {
-    if (!m_strings.tryReserveCapacity(stringCount))
+    if (UNLIKELY(!m_strings.tryReserveCapacity(stringCount)))
         throwOutOfMemoryError(&state);
 }
 
@@ -106,11 +107,12 @@
     // 5) It uses optimized code paths for all the cases known to be 8-bit and for the empty string.
 
     if (value.isCell()) {
-        if (value.asCell()->isString()) {
-            append(asString(value)->viewWithUnderlyingString(state));
-            return;
-        }
-        append(value.toString(&state)->viewWithUnderlyingString(state));
+        JSString* jsString;
+        if (value.asCell()->isString())
+            jsString = asString(value);
+        else
+            jsString = value.toString(&state);
+        append(jsString->viewWithUnderlyingString(state));
         return;
     }
 

Modified: trunk/Source/_javascript_Core/runtime/NumericStrings.h (198255 => 198256)


--- trunk/Source/_javascript_Core/runtime/NumericStrings.h	2016-03-16 01:51:12 UTC (rev 198255)
+++ trunk/Source/_javascript_Core/runtime/NumericStrings.h	2016-03-16 02:16:40 UTC (rev 198256)
@@ -34,7 +34,7 @@
 
 class NumericStrings {
 public:
-    ALWAYS_INLINE String add(double d)
+    ALWAYS_INLINE const String& add(double d)
     {
         CacheEntry<double>& entry = lookup(d);
         if (d == entry.key && !entry.value.isNull())
@@ -44,7 +44,7 @@
         return entry.value;
     }
 
-    ALWAYS_INLINE String add(int i)
+    ALWAYS_INLINE const String& add(int i)
     {
         if (static_cast<unsigned>(i) < cacheSize)
             return lookupSmallString(static_cast<unsigned>(i));
@@ -56,7 +56,7 @@
         return entry.value;
     }
 
-    ALWAYS_INLINE String add(unsigned i)
+    ALWAYS_INLINE const String& add(unsigned i)
     {
         if (i < cacheSize)
             return lookupSmallString(static_cast<unsigned>(i));
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to