Title: [197357] trunk/Source/_javascript_Core
Revision
197357
Author
fpi...@apple.com
Date
2016-02-29 10:05:17 -0800 (Mon, 29 Feb 2016)

Log Message

FTL should be able to run everything in Octane/regexp
https://bugs.webkit.org/show_bug.cgi?id=154266

Reviewed by Saam Barati.

Adds FTL support for NewRegexp, RegExpTest, and RegExpExec. I couldn't figure out how to
make the RegExpExec peephole optimization work in FTL. This optimizations shouldn't be a
DFG backend optimization anyway - if we need this optimization then it should be a
strength reduction rule over IR. That way, it can be shared by all backends.

I measured whether removing that optimization had any effect on performance separately
from measuring the performance of this patch. Removing that optimization did not change
our score on any benchmarks.

This patch does have an overall negative effect on the Octane/regexp score. This is
presumably because tiering up to the FTL has no value to the code in the regexp test. Or
maybe it's something else. No matter - the overall effect on the Octane score is not
statistically significant and we don't want this kind of coverage blocked by the fact
that adding coverage hurts a benchmark.

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGNode.h:
(JSC::DFG::Node::setIndexingType):
(JSC::DFG::Node::hasRegexpIndex):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileNotifyWrite):
(JSC::DFG::SpeculativeJIT::compileIsObjectOrNull):
(JSC::DFG::SpeculativeJIT::compileRegExpExec): Deleted.
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileCheckWatchdogTimer):
(JSC::FTL::DFG::LowerDFGToB3::compileRegExpExec):
(JSC::FTL::DFG::LowerDFGToB3::compileRegExpTest):
(JSC::FTL::DFG::LowerDFGToB3::compileNewRegexp):
(JSC::FTL::DFG::LowerDFGToB3::didOverflowStack):
* tests/stress/ftl-regexp-exec.js: Added.
* tests/stress/ftl-regexp-test.js: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (197356 => 197357)


--- trunk/Source/_javascript_Core/ChangeLog	2016-02-29 17:54:11 UTC (rev 197356)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-02-29 18:05:17 UTC (rev 197357)
@@ -1,3 +1,50 @@
+2016-02-28  Filip Pizlo  <fpi...@apple.com>
+
+        FTL should be able to run everything in Octane/regexp
+        https://bugs.webkit.org/show_bug.cgi?id=154266
+
+        Reviewed by Saam Barati.
+
+        Adds FTL support for NewRegexp, RegExpTest, and RegExpExec. I couldn't figure out how to
+        make the RegExpExec peephole optimization work in FTL. This optimizations shouldn't be a
+        DFG backend optimization anyway - if we need this optimization then it should be a
+        strength reduction rule over IR. That way, it can be shared by all backends.
+
+        I measured whether removing that optimization had any effect on performance separately
+        from measuring the performance of this patch. Removing that optimization did not change
+        our score on any benchmarks.
+
+        This patch does have an overall negative effect on the Octane/regexp score. This is
+        presumably because tiering up to the FTL has no value to the code in the regexp test. Or
+        maybe it's something else. No matter - the overall effect on the Octane score is not
+        statistically significant and we don't want this kind of coverage blocked by the fact
+        that adding coverage hurts a benchmark.
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::setIndexingType):
+        (JSC::DFG::Node::hasRegexpIndex):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileNotifyWrite):
+        (JSC::DFG::SpeculativeJIT::compileIsObjectOrNull):
+        (JSC::DFG::SpeculativeJIT::compileRegExpExec): Deleted.
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCheckWatchdogTimer):
+        (JSC::FTL::DFG::LowerDFGToB3::compileRegExpExec):
+        (JSC::FTL::DFG::LowerDFGToB3::compileRegExpTest):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewRegexp):
+        (JSC::FTL::DFG::LowerDFGToB3::didOverflowStack):
+        * tests/stress/ftl-regexp-exec.js: Added.
+        * tests/stress/ftl-regexp-test.js: Added.
+
 2016-02-28  Andreas Kling  <akl...@apple.com>
 
         Make JSFunction.name allocation fully lazy.

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (197356 => 197357)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-02-29 17:54:11 UTC (rev 197356)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-02-29 18:05:17 UTC (rev 197357)
@@ -3340,6 +3340,9 @@
         }
             
         case op_new_regexp: {
+            // FIXME: We really should be able to inline code that uses NewRegexp. That means
+            // using something other than the index into the CodeBlock here.
+            // https://bugs.webkit.org/show_bug.cgi?id=154808
             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewRegexp, OpInfo(currentInstruction[2].u.operand)));
             NEXT_OPCODE(op_new_regexp);
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (197356 => 197357)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2016-02-29 17:54:11 UTC (rev 197356)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2016-02-29 18:05:17 UTC (rev 197357)
@@ -1022,6 +1022,9 @@
         m_opInfo = indexingType;
     }
     
+    // FIXME: We really should be able to inline code that uses NewRegexp. That means
+    // using something other than the index into the CodeBlock here.
+    // https://bugs.webkit.org/show_bug.cgi?id=154808
     bool hasRegexpIndex()
     {
         return op() == NewRegexp;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (197356 => 197357)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2016-02-29 17:54:11 UTC (rev 197356)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2016-02-29 18:05:17 UTC (rev 197357)
@@ -5910,46 +5910,6 @@
     noResult(node);
 }
 
-bool SpeculativeJIT::compileRegExpExec(Node* node)
-{
-    unsigned branchIndexInBlock = detectPeepHoleBranch();
-    if (branchIndexInBlock == UINT_MAX)
-        return false;
-    Node* branchNode = m_block->at(branchIndexInBlock);
-    ASSERT(node->adjustedRefCount() == 1);
-
-    BasicBlock* taken = branchNode->branchData()->taken.block;
-    BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
-    
-    bool invert = false;
-    if (taken == nextBlock()) {
-        invert = true;
-        BasicBlock* tmp = taken;
-        taken = notTaken;
-        notTaken = tmp;
-    }
-
-    SpeculateCellOperand base(this, node->child1());
-    SpeculateCellOperand argument(this, node->child2());
-    GPRReg baseGPR = base.gpr();
-    GPRReg argumentGPR = argument.gpr();
-    
-    flushRegisters();
-    GPRFlushedCallResult result(this);
-    callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
-    m_jit.exceptionCheck();
-
-    branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, result.gpr(), taken);
-    jump(notTaken);
-
-    use(node->child1());
-    use(node->child2());
-    m_indexInBlock = branchIndexInBlock;
-    m_currentNode = branchNode;
-
-    return true;
-}
-
 void SpeculativeJIT::compileIsObjectOrNull(Node* node)
 {
     JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (197356 => 197357)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-02-29 17:54:11 UTC (rev 197356)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-02-29 18:05:17 UTC (rev 197357)
@@ -2834,26 +2834,6 @@
     }
 
     case RegExpExec: {
-        if (compileRegExpExec(node))
-            return;
-
-        if (!node->adjustedRefCount()) {
-            SpeculateCellOperand base(this, node->child1());
-            SpeculateCellOperand argument(this, node->child2());
-            GPRReg baseGPR = base.gpr();
-            GPRReg argumentGPR = argument.gpr();
-            
-            flushRegisters();
-            GPRFlushedCallResult result(this);
-            callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
-            m_jit.exceptionCheck();
-            
-            // Must use jsValueResult because otherwise we screw up register
-            // allocation, which thinks that this node has a result.
-            booleanResult(result.gpr(), node);
-            break;
-        }
-
         SpeculateCellOperand base(this, node->child1());
         SpeculateCellOperand argument(this, node->child2());
         GPRReg baseGPR = base.gpr();

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (197356 => 197357)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-02-29 17:54:11 UTC (rev 197356)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-02-29 18:05:17 UTC (rev 197357)
@@ -2959,25 +2959,6 @@
     }
 
     case RegExpExec: {
-        if (compileRegExpExec(node))
-            return;
-        if (!node->adjustedRefCount()) {
-            SpeculateCellOperand base(this, node->child1());
-            SpeculateCellOperand argument(this, node->child2());
-            GPRReg baseGPR = base.gpr();
-            GPRReg argumentGPR = argument.gpr();
-            
-            flushRegisters();
-            GPRFlushedCallResult result(this);
-            callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
-            m_jit.exceptionCheck();
-            
-            // Must use jsValueResult because otherwise we screw up register
-            // allocation, which thinks that this node has a result.
-            jsValueResult(result.gpr(), node);
-            break;
-        }
-
         SpeculateCellOperand base(this, node->child1());
         SpeculateCellOperand argument(this, node->child2());
         GPRReg baseGPR = base.gpr();
@@ -3683,6 +3664,9 @@
         flushRegisters();
         GPRFlushedCallResult result(this);
         
+        // FIXME: We really should be able to inline code that uses NewRegexp. That means not
+        // reaching into the CodeBlock here.
+        // https://bugs.webkit.org/show_bug.cgi?id=154808
         callOperation(operationNewRegexp, result.gpr(), m_jit.codeBlock()->regexp(node->regexpIndex()));
         m_jit.exceptionCheck();
         

Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (197356 => 197357)


--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2016-02-29 17:54:11 UTC (rev 197356)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2016-02-29 18:05:17 UTC (rev 197357)
@@ -218,6 +218,9 @@
     case PutSetterByVal:
     case CopyRest:
     case GetRestLength:
+    case RegExpExec:
+    case RegExpTest:
+    case NewRegexp:
         // These are OK.
         break;
 

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (197356 => 197357)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-02-29 17:54:11 UTC (rev 197356)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-02-29 18:05:17 UTC (rev 197357)
@@ -908,6 +908,15 @@
         case GetRestLength:
             compileGetRestLength();
             break;
+        case RegExpExec:
+            compileRegExpExec();
+            break;
+        case RegExpTest:
+            compileRegExpTest();
+            break;
+        case NewRegexp:
+            compileNewRegexp();
+            break;
 
         case PhantomLocal:
         case LoopHint:
@@ -6387,6 +6396,36 @@
         m_out.appendTo(continuation, lastNext);
     }
 
+    void compileRegExpExec()
+    {
+        LValue base = lowCell(m_node->child1());
+        LValue argument = lowCell(m_node->child2());
+        setJSValue(
+            vmCall(Int64, m_out.operation(operationRegExpExec), m_callFrame, base, argument));
+    }
+
+    void compileRegExpTest()
+    {
+        LValue base = lowCell(m_node->child1());
+        LValue argument = lowCell(m_node->child2());
+        setBoolean(
+            vmCall(Int32, m_out.operation(operationRegExpTest), m_callFrame, base, argument));
+    }
+
+    void compileNewRegexp()
+    {
+        // FIXME: We really should be able to inline code that uses NewRegexp. That means not
+        // reaching into the CodeBlock here.
+        // https://bugs.webkit.org/show_bug.cgi?id=154808
+
+        LValue result = vmCall(
+            pointerType(),
+            m_out.operation(operationNewRegexp), m_callFrame,
+            m_out.constIntPtr(codeBlock()->regexp(m_node->regexpIndex())));
+        
+        setJSValue(result);
+    }
+
     LValue didOverflowStack()
     {
         // This does a very simple leaf function analysis. The invariant of FTL call

Added: trunk/Source/_javascript_Core/tests/stress/ftl-regexp-exec.js (0 => 197357)


--- trunk/Source/_javascript_Core/tests/stress/ftl-regexp-exec.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/ftl-regexp-exec.js	2016-02-29 18:05:17 UTC (rev 197357)
@@ -0,0 +1,17 @@
+function foo(s) {
+    return /foo/.exec(s);
+}
+
+noInline(foo);
+
+for (var i = 0; i < 100000; ++i) {
+    var result = foo("foo");
+    if (!result)
+        throw "Error: bad result for foo";
+    if (result.length != 1)
+        throw "Error: bad result for foo: " + result;
+    if (result[0] != "foo")
+        throw "Error: bad result for foo: " + result;
+    if (foo("bar"))
+        throw "Error: bad result for bar";
+}

Added: trunk/Source/_javascript_Core/tests/stress/ftl-regexp-test.js (0 => 197357)


--- trunk/Source/_javascript_Core/tests/stress/ftl-regexp-test.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/ftl-regexp-test.js	2016-02-29 18:05:17 UTC (rev 197357)
@@ -0,0 +1,12 @@
+function foo(s) {
+    return /foo/.test(s);
+}
+
+noInline(foo);
+
+for (var i = 0; i < 100000; ++i) {
+    if (!foo("foo"))
+        throw "Error: bad result for foo";
+    if (foo("bar"))
+        throw "Error: bad result for bar";
+}
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to