DFG/FTL should inline accesses to RegExpObject::m_lastIndex
https://bugs.webkit.org/show_bug.cgi?id=155003
Reviewed by Benjamin Poulain.
Source/JavaScriptCore:
The Octane/regexp benchmark sets RegExps' lastIndex a lot. I could imagine this being
something that people want to do. Right now, I'm not convinced that making the RegExp object
be more plain-JS would be a good idea considering that pretty much all uses of it will
require some special compiler magic. Also, it's good that this patch teaches the compiler
how to reason about lastIndex since some of my other plans for regexp involve having the
compiler treat more regexp stuff as intrinsic.
This is a smaller Octane/regexp speed-up than I hoped - maybe around 1%. It's an enormous
speed-up on the microbenchmarks attached to this patch.
* dfg/DFGAbstractHeap.h:
* 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/DFGHeapLocation.h:
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compilePutAccessorByVal):
(JSC::DFG::SpeculativeJIT::compileGetRegExpObjectLastIndex):
(JSC::DFG::SpeculativeJIT::compileSetRegExpObjectLastIndex):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStoreBarrierInsertionPhase.cpp:
* ftl/FTLAbstractHeapRepository.cpp:
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileStringReplace):
(JSC::FTL::DFG::LowerDFGToB3::compileGetRegExpObjectLastIndex):
(JSC::FTL::DFG::LowerDFGToB3::compileSetRegExpObjectLastIndex):
(JSC::FTL::DFG::LowerDFGToB3::didOverflowStack):
(JSC::FTL::DFG::LowerDFGToB3::lowObject):
(JSC::FTL::DFG::LowerDFGToB3::lowRegExpObject):
(JSC::FTL::DFG::LowerDFGToB3::lowString):
* runtime/RegExpObject.h:
(JSC::RegExpObject::createStructure):
(JSC::RegExpObject::offsetOfLastIndex):
LayoutTests:
* js/regress/regexp-last-index-expected.txt: Added.
* js/regress/regexp-last-index.html: Added.
* js/regress/regexp-set-last-index-expected.txt: Added.
* js/regress/regexp-set-last-index.html: Added.
* js/regress/script-tests/regexp-last-index.js: Added.
* js/regress/script-tests/regexp-set-last-index.js: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@197549 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index fe495e2..cf515d1 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -1072,11 +1072,21 @@
&& !m_graph.hasExitSite(node->origin.semantic, BadCache)
&& !m_graph.hasExitSite(node->origin.semantic, BadIndexingType)
&& !m_graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) {
+
auto uid = m_graph.identifiers()[node->identifierNumber()];
+
if (uid == vm().propertyNames->length.impl()) {
attemptToMakeGetArrayLength(node);
break;
}
+
+ if (uid == vm().propertyNames->lastIndex.impl()
+ && node->child1()->shouldSpeculateRegExpObject()) {
+ node->setOp(GetRegExpObjectLastIndex);
+ node->clearFlags(NodeMustGenerate);
+ fixEdge<RegExpObjectUse>(node->child1());
+ break;
+ }
}
if (node->child1()->shouldSpeculateCell())
@@ -1087,6 +1097,23 @@
case PutById:
case PutByIdFlush:
case PutByIdDirect: {
+ if (node->child1()->shouldSpeculateCellOrOther()
+ && !m_graph.hasExitSite(node->origin.semantic, BadType)
+ && !m_graph.hasExitSite(node->origin.semantic, BadCache)
+ && !m_graph.hasExitSite(node->origin.semantic, BadIndexingType)
+ && !m_graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) {
+
+ auto uid = m_graph.identifiers()[node->identifierNumber()];
+
+ if (uid == vm().propertyNames->lastIndex.impl()
+ && node->child1()->shouldSpeculateRegExpObject()) {
+ node->setOp(SetRegExpObjectLastIndex);
+ fixEdge<RegExpObjectUse>(node->child1());
+ speculateForBarrier(node->child2());
+ break;
+ }
+ }
+
fixEdge<CellUse>(node->child1());
break;
}
@@ -1267,6 +1294,8 @@
case KillStack:
case GetStack:
case StoreBarrier:
+ case GetRegExpObjectLastIndex:
+ case SetRegExpObjectLastIndex:
// These are just nodes that we don't currently expect to see during fixup.
// If we ever wanted to insert them prior to fixup, then we just have to create
// fixup rules for them.