<!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>[197622] trunk/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/197622">197622</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-03-05 16:48:11 -0800 (Sat, 05 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>The most aggressive form of RegExpTest/RegExpExec should speculate more aggressively than just cell
https://bugs.webkit.org/show_bug.cgi?id=154900

Reviewed by Saam Barati.

These old operations used to speculate cell. That's what they did when they were first
introduced. That was probably about as good as they could do back then because we didn't have
very powerful checks. Now we have powerful checks, so we can do this right.

The most profitable thing to check is that child1 is a RegExpObject and child2 is a JSString.
Sometimes though, we will not know what child2 is even though we know that child1 is a
RegExpObject. So, this patch means that RegExpExec/RegExpTest have the following overloads:

    RegExpExec(RegExpObject:, String:)
    RegExpExec(RegExpObject:, Untyped:)
    RegExpExec(Untyped:, Untyped:)

This shaves off some type checks in Octane/regexp. It also cleans up some problems in our
modeling of the effectfulness of these operations.

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileRegExpExec):
(JSC::FTL::DFG::LowerDFGToB3::compileRegExpTest):
* jit/JITOperations.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationsh">trunk/Source/JavaScriptCore/dfg/DFGOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (197621 => 197622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-03-06 00:40:09 UTC (rev 197621)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-03-06 00:48:11 UTC (rev 197622)
</span><span class="lines">@@ -1,3 +1,44 @@
</span><ins>+2016-03-05  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        The most aggressive form of RegExpTest/RegExpExec should speculate more aggressively than just cell
+        https://bugs.webkit.org/show_bug.cgi?id=154900
+
+        Reviewed by Saam Barati.
+
+        These old operations used to speculate cell. That's what they did when they were first
+        introduced. That was probably about as good as they could do back then because we didn't have
+        very powerful checks. Now we have powerful checks, so we can do this right.
+
+        The most profitable thing to check is that child1 is a RegExpObject and child2 is a JSString.
+        Sometimes though, we will not know what child2 is even though we know that child1 is a
+        RegExpObject. So, this patch means that RegExpExec/RegExpTest have the following overloads:
+
+            RegExpExec(RegExpObject:, String:)
+            RegExpExec(RegExpObject:, Untyped:)
+            RegExpExec(Untyped:, Untyped:)
+
+        This shaves off some type checks in Octane/regexp. It also cleans up some problems in our
+        modeling of the effectfulness of these operations.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileRegExpExec):
+        (JSC::FTL::DFG::LowerDFGToB3::compileRegExpTest):
+        * jit/JITOperations.h:
+
</ins><span class="cx"> 2016-03-05  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ES6] Support Reflect.construct
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (197621 => 197622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-03-06 00:40:09 UTC (rev 197621)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-03-06 00:48:11 UTC (rev 197622)
</span><span class="lines">@@ -1554,10 +1554,20 @@
</span><span class="cx">     }
</span><span class="cx">             
</span><span class="cx">     case RegExpExec:
</span><ins>+        if (node-&gt;child1().useKind() == RegExpObjectUse
+            &amp;&amp; node-&gt;child2().useKind() == StringUse) {
+            // This doesn't clobber the world since there are no conversions to perform.
+        } else
+            clobberWorld(node-&gt;origin.semantic, clobberLimit);
</ins><span class="cx">         forNode(node).makeHeapTop();
</span><span class="cx">         break;
</span><span class="cx"> 
</span><span class="cx">     case RegExpTest:
</span><ins>+        if (node-&gt;child1().useKind() == RegExpObjectUse
+            &amp;&amp; node-&gt;child2().useKind() == StringUse) {
+            // This doesn't clobber the world since there are no conversions to perform.
+        } else
+            clobberWorld(node-&gt;origin.semantic, clobberLimit);
</ins><span class="cx">         forNode(node).setType(SpecBoolean);
</span><span class="cx">         break;
</span><span class="cx">             
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (197621 => 197622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-03-06 00:40:09 UTC (rev 197621)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-03-06 00:48:11 UTC (rev 197622)
</span><span class="lines">@@ -1078,8 +1078,14 @@
</span><span class="cx"> 
</span><span class="cx">     case RegExpExec:
</span><span class="cx">     case RegExpTest:
</span><del>-        read(RegExpState);
-        write(RegExpState);
</del><ins>+        if (node-&gt;child1().useKind() == RegExpObjectUse
+            &amp;&amp; node-&gt;child2().useKind() == StringUse) {
+            read(RegExpState);
+            write(RegExpState);
+            return;
+        }
+        read(World);
+        write(Heap);
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     case StringReplace:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (197621 => 197622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-03-06 00:40:09 UTC (rev 197621)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-03-06 00:48:11 UTC (rev 197622)
</span><span class="lines">@@ -879,13 +879,11 @@
</span><span class="cx">             
</span><span class="cx">         case RegExpExec:
</span><span class="cx">         case RegExpTest: {
</span><del>-            // FIXME: These should probably speculate something stronger than cell.
-            // https://bugs.webkit.org/show_bug.cgi?id=154900
-            if (node-&gt;child1()-&gt;shouldSpeculateCell()
-                &amp;&amp; node-&gt;child2()-&gt;shouldSpeculateCell()) {
-                fixEdge&lt;CellUse&gt;(node-&gt;child1());
-                fixEdge&lt;CellUse&gt;(node-&gt;child2());
-                break;
</del><ins>+            if (node-&gt;child1()-&gt;shouldSpeculateRegExpObject()) {
+                fixEdge&lt;RegExpObjectUse&gt;(node-&gt;child1());
+
+                if (node-&gt;child2()-&gt;shouldSpeculateString())
+                    fixEdge&lt;StringUse&gt;(node-&gt;child2());
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (197621 => 197622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-03-06 00:40:09 UTC (rev 197621)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-03-06 00:48:11 UTC (rev 197622)
</span><span class="lines">@@ -619,23 +619,25 @@
</span><span class="cx">     return JSValue::encode(array-&gt;pop(exec));
</span><span class="cx"> }
</span><span class="cx">         
</span><del>-EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, JSCell* base, JSCell* argument)
</del><ins>+EncodedJSValue JIT_OPERATION operationRegExpExecString(ExecState* exec, RegExpObject* regExpObject, JSString* argument)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(&amp;vm, exec);
</span><span class="cx">     
</span><del>-    if (!base-&gt;inherits(RegExpObject::info()))
-        return throwVMTypeError(exec);
</del><ins>+    return JSValue::encode(regExpObject-&gt;exec(exec, argument));
+}
+        
+EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+    
+    JSValue argument = JSValue::decode(encodedArgument);
</ins><span class="cx"> 
</span><del>-    JSString* input;
-    if (argument-&gt;isString())
-        input = asString(argument);
-    else {
-        input = JSValue(argument).toStringOrNull(exec);
-        if (!input)
-            return JSValue::encode(jsUndefined());
-    }
-    return JSValue::encode(asRegExpObject(base)-&gt;exec(exec, input));
</del><ins>+    JSString* input = argument.toStringOrNull(exec);
+    if (!input)
+        return JSValue::encode(jsUndefined());
+    return JSValue::encode(regExpObject-&gt;exec(exec, input));
</ins><span class="cx"> }
</span><span class="cx">         
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
</span><span class="lines">@@ -655,25 +657,25 @@
</span><span class="cx">     return JSValue::encode(asRegExpObject(base)-&gt;exec(exec, input));
</span><span class="cx"> }
</span><span class="cx">         
</span><del>-size_t JIT_OPERATION operationRegExpTest(ExecState* exec, JSCell* base, JSCell* argument)
</del><ins>+size_t JIT_OPERATION operationRegExpTestString(ExecState* exec, RegExpObject* regExpObject, JSString* input)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(&amp;vm, exec);
</span><span class="cx"> 
</span><del>-    if (!base-&gt;inherits(RegExpObject::info())) {
-        throwTypeError(exec);
</del><ins>+    return regExpObject-&gt;test(exec, input);
+}
+
+size_t JIT_OPERATION operationRegExpTest(ExecState* exec, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+
+    JSValue argument = JSValue::decode(encodedArgument);
+
+    JSString* input = argument.toStringOrNull(exec);
+    if (!input)
</ins><span class="cx">         return false;
</span><del>-    }
-
-    JSString* input;
-    if (argument-&gt;isString())
-        input = asString(argument);
-    else {
-        input = JSValue(argument).toStringOrNull(exec);
-        if (!input)
-            return false;
-    }
-    return asRegExpObject(base)-&gt;test(exec, input);
</del><ins>+    return regExpObject-&gt;test(exec, input);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.h (197621 => 197622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2016-03-06 00:40:09 UTC (rev 197621)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2016-03-06 00:48:11 UTC (rev 197622)
</span><span class="lines">@@ -101,10 +101,12 @@
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState*, double value, JSArray*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationArrayPop(ExecState*, JSArray*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationArrayPopAndRecoverLength(ExecState*, JSArray*) WTF_INTERNAL;
</span><del>-EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
</del><ins>+EncodedJSValue JIT_OPERATION operationRegExpExecString(ExecState*, RegExpObject*, JSString*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState*, RegExpObject*, EncodedJSValue) WTF_INTERNAL;
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
</span><span class="cx"> // These comparisons return a boolean within a size_t such that the value is zero extended to fill the register.
</span><del>-size_t JIT_OPERATION operationRegExpTest(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
</del><ins>+size_t JIT_OPERATION operationRegExpTestString(ExecState*, RegExpObject*, JSString*) WTF_INTERNAL;
+size_t JIT_OPERATION operationRegExpTest(ExecState*, RegExpObject*, EncodedJSValue) WTF_INTERNAL;
</ins><span class="cx"> size_t JIT_OPERATION operationRegExpTestGeneric(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
</span><span class="cx"> size_t JIT_OPERATION operationCompareStrictEqCell(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
</span><span class="cx"> size_t JIT_OPERATION operationCompareStrictEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (197621 => 197622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-03-06 00:40:09 UTC (rev 197621)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-03-06 00:48:11 UTC (rev 197622)
</span><span class="lines">@@ -1217,6 +1217,18 @@
</span><span class="cx">         return appendCallSetResult(operation, result);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    JITCompiler::Call callOperation(J_JITOperation_EReoJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
+
+    JITCompiler::Call callOperation(J_JITOperation_EReoJss operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
+
</ins><span class="cx">     JITCompiler::Call callOperation(V_JITOperation_EWs operation, WatchpointSet* watchpointSet)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(TrustedImmPtr(watchpointSet));
</span><span class="lines">@@ -1434,6 +1446,16 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2);
</span><span class="cx">         return appendCallSetResult(operation, result);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(S_JITOperation_EReoJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(S_JITOperation_EReoJss operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
</ins><span class="cx"> 
</span><span class="cx">     JITCompiler::Call callOperation(J_JITOperation_EPP operation, GPRReg result, GPRReg arg1, GPRReg arg2)
</span><span class="cx">     {
</span><span class="lines">@@ -1700,6 +1722,16 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell), EABI_32BIT_DUMMY_ARG arg2Payload, arg2Tag);
</span><span class="cx">         return appendCallSetResult(operation, result);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(J_JITOperation_EReoJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag);
+        return appendCallSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_JITOperation_EReoJss operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallSetResult(operation, resultPayload, resultTag);
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(J_JITOperation_ESsiCI operation, GPRReg resultTag, GPRReg resultPayload, StructureStubInfo* stubInfo, GPRReg arg1, const UniquedStringImpl* uid)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1, TrustedImmPtr(uid));
</span><span class="lines">@@ -1797,6 +1829,16 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag);
</span><span class="cx">         return appendCallSetResult(operation, result);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(S_JITOperation_EReoJ operation, GPRReg result, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag);
+        return appendCallSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(S_JITOperation_EReoJss operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(J_JITOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (197621 => 197622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-03-06 00:40:09 UTC (rev 197621)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-03-06 00:48:11 UTC (rev 197622)
</span><span class="lines">@@ -2836,17 +2836,40 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case RegExpExec: {
</span><del>-        if (node-&gt;child1().useKind() == CellUse
-            &amp;&amp; node-&gt;child2().useKind() == CellUse) {
</del><ins>+        if (node-&gt;child1().useKind() == RegExpObjectUse) {
+            if (node-&gt;child2().useKind() == StringUse) {
+                SpeculateCellOperand base(this, node-&gt;child1());
+                SpeculateCellOperand argument(this, node-&gt;child2());
+                GPRReg baseGPR = base.gpr();
+                GPRReg argumentGPR = argument.gpr();
+                speculateRegExpObject(node-&gt;child1(), baseGPR);
+                speculateString(node-&gt;child2(), argumentGPR);
+                
+                flushRegisters();
+                GPRFlushedCallResult2 resultTag(this);
+                GPRFlushedCallResult resultPayload(this);
+                callOperation(
+                    operationRegExpExecString, resultTag.gpr(), resultPayload.gpr(), baseGPR,
+                    argumentGPR);
+                m_jit.exceptionCheck();
+                
+                jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
+                break;
+            }
+            
</ins><span class="cx">             SpeculateCellOperand base(this, node-&gt;child1());
</span><del>-            SpeculateCellOperand argument(this, node-&gt;child2());
</del><ins>+            JSValueOperand argument(this, node-&gt;child2());
</ins><span class="cx">             GPRReg baseGPR = base.gpr();
</span><del>-            GPRReg argumentGPR = argument.gpr();
</del><ins>+            GPRReg argumentTagGPR = argument.tagGPR();
+            GPRReg argumentPayloadGPR = argument.payloadGPR();
+            speculateRegExpObject(node-&gt;child1(), baseGPR);
</ins><span class="cx">         
</span><span class="cx">             flushRegisters();
</span><span class="cx">             GPRFlushedCallResult2 resultTag(this);
</span><span class="cx">             GPRFlushedCallResult resultPayload(this);
</span><del>-            callOperation(operationRegExpExec, resultTag.gpr(), resultPayload.gpr(), baseGPR, argumentGPR);
</del><ins>+            callOperation(
+                operationRegExpExec, resultTag.gpr(), resultPayload.gpr(), baseGPR, argumentTagGPR,
+                argumentPayloadGPR);
</ins><span class="cx">             m_jit.exceptionCheck();
</span><span class="cx">         
</span><span class="cx">             jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
</span><span class="lines">@@ -2871,16 +2894,35 @@
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     case RegExpTest: {
</span><del>-        if (node-&gt;child1().useKind() == CellUse
-            &amp;&amp; node-&gt;child2().useKind() == CellUse) {
</del><ins>+        if (node-&gt;child1().useKind() == RegExpObjectUse) {
+            if (node-&gt;child2().useKind() == StringUse) {
+                SpeculateCellOperand base(this, node-&gt;child1());
+                SpeculateCellOperand argument(this, node-&gt;child2());
+                GPRReg baseGPR = base.gpr();
+                GPRReg argumentGPR = argument.gpr();
+                speculateRegExpObject(node-&gt;child1(), baseGPR);
+                speculateString(node-&gt;child2(), argumentGPR);
+                
+                flushRegisters();
+                GPRFlushedCallResult result(this);
+                callOperation(operationRegExpTestString, result.gpr(), baseGPR, argumentGPR);
+                m_jit.exceptionCheck();
+                
+                booleanResult(result.gpr(), node);
+                break;
+            }
+            
</ins><span class="cx">             SpeculateCellOperand base(this, node-&gt;child1());
</span><del>-            SpeculateCellOperand argument(this, node-&gt;child2());
</del><ins>+            JSValueOperand argument(this, node-&gt;child2());
</ins><span class="cx">             GPRReg baseGPR = base.gpr();
</span><del>-            GPRReg argumentGPR = argument.gpr();
</del><ins>+            GPRReg argumentTagGPR = argument.tagGPR();
+            GPRReg argumentPayloadGPR = argument.payloadGPR();
+            speculateRegExpObject(node-&gt;child1(), baseGPR);
</ins><span class="cx">         
</span><span class="cx">             flushRegisters();
</span><span class="cx">             GPRFlushedCallResult result(this);
</span><del>-            callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
</del><ins>+            callOperation(
+                operationRegExpTest, result.gpr(), baseGPR, argumentTagGPR, argumentPayloadGPR);
</ins><span class="cx">             m_jit.exceptionCheck();
</span><span class="cx">         
</span><span class="cx">             booleanResult(result.gpr(), node);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (197621 => 197622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-03-06 00:40:09 UTC (rev 197621)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-03-06 00:48:11 UTC (rev 197622)
</span><span class="lines">@@ -2962,12 +2962,29 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case RegExpExec: {
</span><del>-        if (node-&gt;child1().useKind() == CellUse
-            &amp;&amp; node-&gt;child2().useKind() == CellUse) {
</del><ins>+        if (node-&gt;child1().useKind() == RegExpObjectUse) {
+            if (node-&gt;child2().useKind() == StringUse) {
+                SpeculateCellOperand base(this, node-&gt;child1());
+                SpeculateCellOperand argument(this, node-&gt;child2());
+                GPRReg baseGPR = base.gpr();
+                GPRReg argumentGPR = argument.gpr();
+                speculateRegExpObject(node-&gt;child1(), baseGPR);
+                speculateString(node-&gt;child2(), argumentGPR);
+                
+                flushRegisters();
+                GPRFlushedCallResult result(this);
+                callOperation(operationRegExpExecString, result.gpr(), baseGPR, argumentGPR);
+                m_jit.exceptionCheck();
+                
+                jsValueResult(result.gpr(), node);
+                break;
+            }
+            
</ins><span class="cx">             SpeculateCellOperand base(this, node-&gt;child1());
</span><del>-            SpeculateCellOperand argument(this, node-&gt;child2());
</del><ins>+            JSValueOperand argument(this, node-&gt;child2());
</ins><span class="cx">             GPRReg baseGPR = base.gpr();
</span><span class="cx">             GPRReg argumentGPR = argument.gpr();
</span><ins>+            speculateRegExpObject(node-&gt;child1(), baseGPR);
</ins><span class="cx">         
</span><span class="cx">             flushRegisters();
</span><span class="cx">             GPRFlushedCallResult result(this);
</span><span class="lines">@@ -2993,21 +3010,38 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case RegExpTest: {
</span><del>-        if (node-&gt;child1().useKind() == CellUse
-            &amp;&amp; node-&gt;child2().useKind() == CellUse) {
</del><ins>+        if (node-&gt;child1().useKind() == RegExpObjectUse) {
+            if (node-&gt;child2().useKind() == StringUse) {
+                SpeculateCellOperand base(this, node-&gt;child1());
+                SpeculateCellOperand argument(this, node-&gt;child2());
+                GPRReg baseGPR = base.gpr();
+                GPRReg argumentGPR = argument.gpr();
+                speculateRegExpObject(node-&gt;child1(), baseGPR);
+                speculateString(node-&gt;child2(), argumentGPR);
+                
+                flushRegisters();
+                GPRFlushedCallResult result(this);
+                callOperation(operationRegExpTestString, result.gpr(), baseGPR, argumentGPR);
+                m_jit.exceptionCheck();
+                
+                m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+                jsValueResult(result.gpr(), node);
+                break;
+            }
+            
</ins><span class="cx">             SpeculateCellOperand base(this, node-&gt;child1());
</span><del>-            SpeculateCellOperand argument(this, node-&gt;child2());
</del><ins>+            JSValueOperand argument(this, node-&gt;child2());
</ins><span class="cx">             GPRReg baseGPR = base.gpr();
</span><span class="cx">             GPRReg argumentGPR = argument.gpr();
</span><ins>+            speculateRegExpObject(node-&gt;child1(), baseGPR);
</ins><span class="cx">         
</span><span class="cx">             flushRegisters();
</span><span class="cx">             GPRFlushedCallResult result(this);
</span><span class="cx">             callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
</span><span class="cx">             m_jit.exceptionCheck();
</span><span class="cx">         
</span><del>-            // If we add a DataFormatBool, we should use it here.
</del><span class="cx">             m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
</span><del>-            jsValueResult(result.gpr(), node, DataFormatJSBoolean);
</del><ins>+            jsValueResult(result.gpr(), node);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="lines">@@ -3021,7 +3055,6 @@
</span><span class="cx">         callOperation(operationRegExpTestGeneric, result.gpr(), baseGPR, argumentGPR);
</span><span class="cx">         m_jit.exceptionCheck();
</span><span class="cx">         
</span><del>-        // If we add a DataFormatBool, we should use it here.
</del><span class="cx">         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
</span><span class="cx">         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (197621 => 197622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-03-06 00:40:09 UTC (rev 197621)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-03-06 00:48:11 UTC (rev 197622)
</span><span class="lines">@@ -6440,10 +6440,18 @@
</span><span class="cx"> 
</span><span class="cx">     void compileRegExpExec()
</span><span class="cx">     {
</span><del>-        if (m_node-&gt;child1().useKind() == CellUse
-            &amp;&amp; m_node-&gt;child2().useKind() == CellUse) {
-            LValue base = lowCell(m_node-&gt;child1());
-            LValue argument = lowCell(m_node-&gt;child2());
</del><ins>+        if (m_node-&gt;child1().useKind() == RegExpObjectUse) {
+            LValue base = lowRegExpObject(m_node-&gt;child1());
+            
+            if (m_node-&gt;child2().useKind() == StringUse) {
+                LValue argument = lowString(m_node-&gt;child2());
+                LValue result = vmCall(
+                    Int64, m_out.operation(operationRegExpExecString), m_callFrame, base, argument);
+                setJSValue(result);
+                return;
+            }
+            
+            LValue argument = lowJSValue(m_node-&gt;child2());
</ins><span class="cx">             setJSValue(
</span><span class="cx">                 vmCall(Int64, m_out.operation(operationRegExpExec), m_callFrame, base, argument));
</span><span class="cx">             return;
</span><span class="lines">@@ -6457,10 +6465,18 @@
</span><span class="cx"> 
</span><span class="cx">     void compileRegExpTest()
</span><span class="cx">     {
</span><del>-        if (m_node-&gt;child1().useKind() == CellUse
-            &amp;&amp; m_node-&gt;child2().useKind() == CellUse) {
-            LValue base = lowCell(m_node-&gt;child1());
-            LValue argument = lowCell(m_node-&gt;child2());
</del><ins>+        if (m_node-&gt;child1().useKind() == RegExpObjectUse) {
+            LValue base = lowRegExpObject(m_node-&gt;child1());
+            
+            if (m_node-&gt;child2().useKind() == StringUse) {
+                LValue argument = lowString(m_node-&gt;child2());
+                LValue result = vmCall(
+                    Int32, m_out.operation(operationRegExpTestString), m_callFrame, base, argument);
+                setBoolean(result);
+                return;
+            }
+
+            LValue argument = lowJSValue(m_node-&gt;child2());
</ins><span class="cx">             setBoolean(
</span><span class="cx">                 vmCall(Int32, m_out.operation(operationRegExpTest), m_callFrame, base, argument));
</span><span class="cx">             return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (197621 => 197622)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2016-03-06 00:40:09 UTC (rev 197621)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2016-03-06 00:48:11 UTC (rev 197622)
</span><span class="lines">@@ -144,6 +144,8 @@
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EPc)(ExecState*, Instruction*);
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJscC)(ExecState*, JSScope*, JSCell*);
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJscCJ)(ExecState*, JSScope*, JSCell*, EncodedJSValue);
</span><ins>+typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EReoJ)(ExecState*, RegExpObject*, EncodedJSValue);
+typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EReoJss)(ExecState*, RegExpObject*, JSString*);
</ins><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_ESS)(ExecState*, size_t, size_t);
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_ESsiCI)(ExecState*, StructureStubInfo*, JSCell*, UniquedStringImpl*);
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_ESsiJI)(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*);
</span><span class="lines">@@ -202,6 +204,8 @@
</span><span class="cx"> typedef size_t JIT_OPERATION (*S_JITOperation_EJ)(ExecState*, EncodedJSValue);
</span><span class="cx"> typedef size_t JIT_OPERATION (*S_JITOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
</span><span class="cx"> typedef size_t JIT_OPERATION (*S_JITOperation_EOJss)(ExecState*, JSObject*, JSString*);
</span><ins>+typedef size_t JIT_OPERATION (*S_JITOperation_EReoJ)(ExecState*, RegExpObject*, EncodedJSValue);
+typedef size_t JIT_OPERATION (*S_JITOperation_EReoJss)(ExecState*, RegExpObject*, JSString*);
</ins><span class="cx"> typedef size_t JIT_OPERATION (*S_JITOperation_J)(EncodedJSValue);
</span><span class="cx"> typedef SlowPathReturnType JIT_OPERATION (*Sprt_JITOperation_EZ)(ExecState*, int32_t);
</span><span class="cx"> typedef void JIT_OPERATION (*V_JITOperation)();
</span></span></pre>
</div>
</div>

</body>
</html>