<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[197751] releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/197751">197751</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2016-03-08 02:11:41 -0800 (Tue, 08 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/197485">r197485</a> - RegExpPrototype should check for exceptions after calling toString and doing so should not be expensive
https://bugs.webkit.org/show_bug.cgi?id=154927

Reviewed by Saam Barati.

While working on regexp optimizations, I found that RegExpPrototype calls toString(), an
effectful operation that could do anything, without then checking for hadException().

So I added a call to hadException().

But that regressed Octane/regexp by 5%!  That's a lot!  It turns out that
exec-&gt;hadException() is soooper slow. So, I made it cheaper to check for exceptions from
toString(): there is now a variant called toStringFast() that returns null iff it throws an
exception.

This allowed me to add the exception check without regressing perf.

Note that toString() must retain its old behavior of returning an empty string on exception.
There is just too much code that relies on that behavior.

* runtime/JSCJSValue.cpp:
(JSC::JSValue::isValidCallee):
(JSC::JSValue::toStringSlowCase):
(JSC::JSValue::toWTFStringSlowCase):
* runtime/JSCJSValue.h:
(JSC::JSValue::asValue):
* runtime/JSString.h:
(JSC::JSValue::toString):
(JSC::JSValue::toStringFast):
(JSC::JSValue::toWTFString):
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncTest):
(JSC::regExpProtoFuncExec):
(JSC::regExpProtoFuncCompile):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit212SourceJavaScriptCoreChangeLog">releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit212SourceJavaScriptCoreruntimeJSCJSValuecpp">releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/JSCJSValue.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit212SourceJavaScriptCoreruntimeJSCJSValueh">releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/JSCJSValue.h</a></li>
<li><a href="#releasesWebKitGTKwebkit212SourceJavaScriptCoreruntimeJSStringh">releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/JSString.h</a></li>
<li><a href="#releasesWebKitGTKwebkit212SourceJavaScriptCoreruntimeRegExpPrototypecpp">releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/RegExpPrototype.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="releasesWebKitGTKwebkit212SourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/ChangeLog (197750 => 197751)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/ChangeLog        2016-03-08 09:48:32 UTC (rev 197750)
+++ releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/ChangeLog        2016-03-08 10:11:41 UTC (rev 197751)
</span><span class="lines">@@ -1,3 +1,40 @@
</span><ins>+2016-03-02  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        RegExpPrototype should check for exceptions after calling toString and doing so should not be expensive
+        https://bugs.webkit.org/show_bug.cgi?id=154927
+
+        Reviewed by Saam Barati.
+
+        While working on regexp optimizations, I found that RegExpPrototype calls toString(), an
+        effectful operation that could do anything, without then checking for hadException().
+
+        So I added a call to hadException().
+
+        But that regressed Octane/regexp by 5%!  That's a lot!  It turns out that
+        exec-&gt;hadException() is soooper slow. So, I made it cheaper to check for exceptions from
+        toString(): there is now a variant called toStringFast() that returns null iff it throws an
+        exception.
+
+        This allowed me to add the exception check without regressing perf.
+
+        Note that toString() must retain its old behavior of returning an empty string on exception.
+        There is just too much code that relies on that behavior.
+
+        * runtime/JSCJSValue.cpp:
+        (JSC::JSValue::isValidCallee):
+        (JSC::JSValue::toStringSlowCase):
+        (JSC::JSValue::toWTFStringSlowCase):
+        * runtime/JSCJSValue.h:
+        (JSC::JSValue::asValue):
+        * runtime/JSString.h:
+        (JSC::JSValue::toString):
+        (JSC::JSValue::toStringFast):
+        (JSC::JSValue::toWTFString):
+        * runtime/RegExpPrototype.cpp:
+        (JSC::regExpProtoFuncTest):
+        (JSC::regExpProtoFuncExec):
+        (JSC::regExpProtoFuncCompile):
+
</ins><span class="cx"> 2016-03-02  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [JSC] Use a Move without REX byte when possible
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit212SourceJavaScriptCoreruntimeJSCJSValuecpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/JSCJSValue.cpp (197750 => 197751)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/JSCJSValue.cpp        2016-03-08 09:48:32 UTC (rev 197750)
+++ releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/JSCJSValue.cpp        2016-03-08 10:11:41 UTC (rev 197751)
</span><span class="lines">@@ -361,8 +361,14 @@
</span><span class="cx">     return asObject(asCell())-&gt;globalObject();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSString* JSValue::toStringSlowCase(ExecState* exec) const
</del><ins>+JSString* JSValue::toStringSlowCase(ExecState* exec, bool returnEmptyStringOnError) const
</ins><span class="cx"> {
</span><ins>+    auto errorValue = [&amp;] () -&gt; JSString* {
+        if (returnEmptyStringOnError)
+            return jsEmptyString(exec);
+        return nullptr;
+    };
+    
</ins><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     ASSERT(!isString());
</span><span class="cx">     if (isInt32()) {
</span><span class="lines">@@ -383,15 +389,18 @@
</span><span class="cx">         return vm.smallStrings.undefinedString();
</span><span class="cx">     if (isSymbol()) {
</span><span class="cx">         throwTypeError(exec);
</span><del>-        return jsEmptyString(exec);
</del><ins>+        return errorValue();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ASSERT(isCell());
</span><span class="cx">     JSValue value = asCell()-&gt;toPrimitive(exec, PreferString);
</span><del>-    if (exec-&gt;hadException())
-        return jsEmptyString(exec);
</del><ins>+    if (vm.exception())
+        return errorValue();
</ins><span class="cx">     ASSERT(!value.isObject());
</span><del>-    return value.toString(exec);
</del><ins>+    JSString* result = value.toString(exec);
+    if (vm.exception())
+        return errorValue();
+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> String JSValue::toWTFStringSlowCase(ExecState* exec) const
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit212SourceJavaScriptCoreruntimeJSCJSValueh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/JSCJSValue.h (197750 => 197751)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/JSCJSValue.h        2016-03-08 09:48:32 UTC (rev 197750)
+++ releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/JSCJSValue.h        2016-03-08 10:11:41 UTC (rev 197751)
</span><span class="lines">@@ -252,7 +252,8 @@
</span><span class="cx">     // toNumber conversion is expected to be side effect free if an exception has
</span><span class="cx">     // been set in the ExecState already.
</span><span class="cx">     double toNumber(ExecState*) const;
</span><del>-    JSString* toString(ExecState*) const;
</del><ins>+    JSString* toString(ExecState*) const; // On exception, this returns the empty string.
+    JSString* toStringOrNull(ExecState*) const; // On exception, this returns null, to make exception checks faster.
</ins><span class="cx">     Identifier toPropertyKey(ExecState*) const;
</span><span class="cx">     WTF::String toWTFString(ExecState*) const;
</span><span class="cx">     JSObject* toObject(ExecState*) const;
</span><span class="lines">@@ -436,7 +437,7 @@
</span><span class="cx"> 
</span><span class="cx">     inline const JSValue asValue() const { return *this; }
</span><span class="cx">     JS_EXPORT_PRIVATE double toNumberSlowCase(ExecState*) const;
</span><del>-    JS_EXPORT_PRIVATE JSString* toStringSlowCase(ExecState*) const;
</del><ins>+    JS_EXPORT_PRIVATE JSString* toStringSlowCase(ExecState*, bool returnEmptyStringOnError) const;
</ins><span class="cx">     JS_EXPORT_PRIVATE WTF::String toWTFStringSlowCase(ExecState*) const;
</span><span class="cx">     JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
</span><span class="cx">     JS_EXPORT_PRIVATE JSValue toThisSlowCase(ExecState*, ECMAMode) const;
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit212SourceJavaScriptCoreruntimeJSStringh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/JSString.h (197750 => 197751)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/JSString.h        2016-03-08 09:48:32 UTC (rev 197750)
+++ releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/JSString.h        2016-03-08 10:11:41 UTC (rev 197751)
</span><span class="lines">@@ -733,9 +733,18 @@
</span><span class="cx"> {
</span><span class="cx">     if (isString())
</span><span class="cx">         return jsCast&lt;JSString*&gt;(asCell());
</span><del>-    return toStringSlowCase(exec);
</del><ins>+    bool returnEmptyStringOnError = true;
+    return toStringSlowCase(exec, returnEmptyStringOnError);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline JSString* JSValue::toStringOrNull(ExecState* exec) const
+{
+    if (isString())
+        return jsCast&lt;JSString*&gt;(asCell());
+    bool returnEmptyStringOnError = false;
+    return toStringSlowCase(exec, returnEmptyStringOnError);
+}
+
</ins><span class="cx"> inline String JSValue::toWTFString(ExecState* exec) const
</span><span class="cx"> {
</span><span class="cx">     if (isString())
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit212SourceJavaScriptCoreruntimeRegExpPrototypecpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/RegExpPrototype.cpp (197750 => 197751)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/RegExpPrototype.cpp        2016-03-08 09:48:32 UTC (rev 197750)
+++ releases/WebKitGTK/webkit-2.12/Source/JavaScriptCore/runtime/RegExpPrototype.cpp        2016-03-08 10:11:41 UTC (rev 197751)
</span><span class="lines">@@ -97,7 +97,10 @@
</span><span class="cx">     JSValue thisValue = exec-&gt;thisValue();
</span><span class="cx">     if (!thisValue.inherits(RegExpObject::info()))
</span><span class="cx">         return throwVMTypeError(exec);
</span><del>-    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)-&gt;test(exec, exec-&gt;argument(0).toString(exec))));
</del><ins>+    JSString* string = exec-&gt;argument(0).toStringOrNull(exec);
+    if (!string)
+        return JSValue::encode(jsUndefined());
+    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)-&gt;test(exec, string)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec)
</span><span class="lines">@@ -105,7 +108,10 @@
</span><span class="cx">     JSValue thisValue = exec-&gt;thisValue();
</span><span class="cx">     if (!thisValue.inherits(RegExpObject::info()))
</span><span class="cx">         return throwVMTypeError(exec);
</span><del>-    return JSValue::encode(asRegExpObject(thisValue)-&gt;exec(exec, exec-&gt;argument(0).toString(exec)));
</del><ins>+    JSString* string = exec-&gt;argument(0).toStringOrNull(exec);
+    if (!string)
+        return JSValue::encode(jsUndefined());
+    return JSValue::encode(asRegExpObject(thisValue)-&gt;exec(exec, string));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
</span></span></pre>
</div>
</div>

</body>
</html>