[FTL] Drop NewRegexp for String.prototype.match with RegExp + global flag
https://bugs.webkit.org/show_bug.cgi?id=181848

Reviewed by Sam Weinig.

JSTests:

* microbenchmarks/regexp-u-global-es5.js: Added.
(fn):
* microbenchmarks/regexp-u-global-es6.js: Added.
(fn):
* stress/materialized-regexp-has-correct-last-index-set-by-match-at-osr-exit.js: Added.
(shouldBe):
(test):
(i.switch):
* stress/materialized-regexp-has-correct-last-index-set-by-match.js: Added.
(shouldBe):
(test):

Source/JavaScriptCore:

In r181535, we support `string.match(/nonglobal/)` code. However, `string.match(/global/g)` is not
optimized since it sets `lastIndex` value before performing RegExp operation.

This patch optimizes the above "with a global flag" case by emitting `SetRegExpObjectLastIndex` properly.
RegExpMatchFast is converted to SetRegExpObjectLastIndex and RegExpMatchFastGlobal. The latter node
just holds RegExp (not RegExpObject) cell so that it can offer a chance to make NewRegexp PhantomNewRegexp
in object allocation sinking phase.

Added microbenchmarks shows that this patch makes NewRegexp PhantomNewRegexp even if the given RegExp
has a global flag. And it improves the performance.

                              baseline                  patched

regexp-u-global-es5       44.1298+-4.6128     ^     33.7920+-2.0110        ^ definitely 1.3059x faster
regexp-u-global-es6      182.3272+-2.2861     ^    154.3414+-7.6769        ^ definitely 1.1813x faster

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGMayExit.cpp:
* dfg/DFGNode.cpp:
(JSC::DFG::Node::convertToRegExpMatchFastGlobal):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasHeapPrediction):
(JSC::DFG::Node::hasCellOperand):
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileRegExpMatchFastGlobal):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileRegExpMatchFastGlobal):
* runtime/RegExpObject.cpp:
(JSC::collectMatches): Deleted.
* runtime/RegExpObject.h:
* runtime/RegExpObjectInlines.h:
(JSC::RegExpObject::execInline):
(JSC::RegExpObject::matchInline):
(JSC::advanceStringUnicode):
(JSC::collectMatches):
(JSC::RegExpObject::advanceStringUnicode): Deleted.
* runtime/RegExpPrototype.cpp:
(JSC::advanceStringIndex):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@229514 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp b/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
index c190e27..5c1be68 100644
--- a/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
@@ -495,12 +495,30 @@
                 regExp = m_node->castOperand<RegExp*>();
 
             if (m_node->op() == RegExpMatchFast) {
-                if (!regExp->global()) {
-                    m_node->setOp(RegExpExec);
+                if (regExp->global()) {
+                    if (regExp->sticky())
+                        break;
+                    if (m_node->child3().useKind() != StringUse)
+                        break;
+                    NodeOrigin origin = m_node->origin;
+                    m_insertionSet.insertNode(
+                        m_nodeIndex, SpecNone, Check, origin, m_node->children.justChecks());
+                    m_insertionSet.insertNode(
+                        m_nodeIndex, SpecNone, SetRegExpObjectLastIndex, origin,
+                        OpInfo(false),
+                        Edge(regExpObjectNode, RegExpObjectUse),
+                        m_insertionSet.insertConstantForUse(
+                            m_nodeIndex, origin, jsNumber(0), UntypedUse));
+                    origin = origin.withInvalidExit();
+                    m_node->convertToRegExpMatchFastGlobal(m_graph.freeze(regExp));
+                    m_node->origin = origin;
                     m_changed = true;
-                    // Continue performing strength reduction onto RegExpExec node.
-                } else
                     break;
+                }
+
+                m_node->setOp(RegExpExec);
+                m_changed = true;
+                // Continue performing strength reduction onto RegExpExec node.
             }
 
             ASSERT(m_node->op() != RegExpMatchFast);