Re-landing: ES6: Implement RegExp.prototype[@@search].
https://bugs.webkit.org/show_bug.cgi?id=156331
Reviewed by Keith Miller.
Source/JavaScriptCore:
What changed?
1. Implemented search builtin in RegExpPrototype.js.
The native path is now used as a fast path.
2. Added DFG support for an IsRegExpObjectIntrinsic (modelled after the
IsJSArrayIntrinsic).
3. Renamed @isRegExp to @isRegExpObject to match the new IsRegExpObjectIntrinsic.
4. Change the esSpecIsRegExpObject() implementation to check if the object's
JSType is RegExpObjectType instead of walking the classinfo chain.
* builtins/RegExpPrototype.js:
(search):
* builtins/StringPrototype.js:
(search):
- fixed some indentation.
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileIsArrayConstructor):
(JSC::DFG::SpeculativeJIT::compileIsRegExpObject):
(JSC::DFG::SpeculativeJIT::compileCallObjectConstructor):
* dfg/DFGSpeculativeJIT.h:
* 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::compileIsFunction):
(JSC::FTL::DFG::LowerDFGToB3::compileIsRegExpObject):
(JSC::FTL::DFG::LowerDFGToB3::compileTypeOf):
(JSC::FTL::DFG::LowerDFGToB3::isExoticForTypeof):
(JSC::FTL::DFG::LowerDFGToB3::isRegExpObject):
(JSC::FTL::DFG::LowerDFGToB3::isType):
* runtime/Intrinsic.h:
- Added IsRegExpObjectIntrinsic.
* runtime/CommonIdentifiers.h:
* runtime/ECMAScriptSpecInternalFunctions.cpp:
(JSC::esSpecIsConstructor):
- Changed to use uncheckedArgument since this is only called from internal code.
(JSC::esSpecIsRegExpObject):
(JSC::esSpecIsRegExp): Deleted.
* runtime/ECMAScriptSpecInternalFunctions.h:
- Changed to check the object for a JSType of RegExpObjectType.
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
- Added split fast path.
* runtime/RegExpPrototype.cpp:
(JSC::RegExpPrototype::finishCreation):
(JSC::regExpProtoFuncSearchFast):
(JSC::regExpProtoFuncSearch): Deleted.
* runtime/RegExpPrototype.h:
* tests/es6.yaml:
* tests/stress/regexp-search.js:
- Rebased test.
LayoutTests:
* js/regress/regexp-prototype-search-observable-side-effects-expected.txt: Added.
* js/regress/regexp-prototype-search-observable-side-effects.html: Added.
* js/regress/regexp-prototype-search-observable-side-effects2-expected.txt: Added.
* js/regress/regexp-prototype-search-observable-side-effects2.html: Added.
* js/regress/script-tests/regexp-prototype-search-observable-side-effects.js: Added.
* js/regress/script-tests/regexp-prototype-search-observable-side-effects2.js: Added.
* js/regress/script-tests/string-prototype-search-observable-side-effects.js: Added.
* js/regress/script-tests/string-prototype-search-observable-side-effects2.js: Added.
* js/regress/script-tests/string-prototype-search-observable-side-effects3.js: Added.
* js/regress/script-tests/string-prototype-search-observable-side-effects4.js: Added.
* js/regress/string-prototype-search-observable-side-effects-expected.txt: Added.
* js/regress/string-prototype-search-observable-side-effects.html: Added.
* js/regress/string-prototype-search-observable-side-effects2-expected.txt: Added.
* js/regress/string-prototype-search-observable-side-effects2.html: Added.
* js/regress/string-prototype-search-observable-side-effects3-expected.txt: Added.
* js/regress/string-prototype-search-observable-side-effects3.html: Added.
* js/regress/string-prototype-search-observable-side-effects4-expected.txt: Added.
* js/regress/string-prototype-search-observable-side-effects4.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@199748 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
index ab15e25..535348e 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
@@ -988,7 +988,8 @@
case IsString:
case IsObject:
case IsObjectOrNull:
- case IsFunction: {
+ case IsFunction:
+ case IsRegExpObject: {
AbstractValue child = forNode(node->child1());
if (child.value()) {
bool constantWasSet = true;
@@ -1063,6 +1064,9 @@
} else
setConstant(node, jsBoolean(false));
break;
+ case IsRegExpObject:
+ setConstant(node, jsBoolean(child.value().isObject() && child.value().getObject()->type() == RegExpObjectType));
+ break;
default:
constantWasSet = false;
break;
@@ -1205,6 +1209,21 @@
break;
}
break;
+
+ case IsRegExpObject:
+ // We don't have a SpeculatedType for Proxies yet so we can't do better at proving false.
+ if (!(child.m_type & ~SpecRegExpObject)) {
+ setConstant(node, jsBoolean(true));
+ constantWasSet = true;
+ break;
+ }
+ if (!(child.m_type & SpecObject)) {
+ setConstant(node, jsBoolean(false));
+ constantWasSet = true;
+ break;
+ }
+ break;
+
default:
break;
}
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index ab658cb..606fc93 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -2244,6 +2244,15 @@
return true;
}
+ case IsRegExpObjectIntrinsic: {
+ ASSERT(argumentCountIncludingThis == 2);
+
+ insertChecks();
+ Node* isRegExpObject = addToGraph(IsRegExpObject, OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset)));
+ set(VirtualRegister(resultOperand), isRegExpObject);
+ return true;
+ }
+
case StringPrototypeReplaceIntrinsic: {
if (argumentCountIncludingThis != 3)
return false;
diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h
index 1690371..b0516b4 100644
--- a/Source/JavaScriptCore/dfg/DFGClobberize.h
+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h
@@ -160,6 +160,7 @@
case IsNumber:
case IsString:
case IsObject:
+ case IsRegExpObject:
case LogicalNot:
case CheckInBounds:
case DoubleRep:
diff --git a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
index 475b798..02ef942 100644
--- a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
+++ b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
@@ -163,6 +163,7 @@
case IsObject:
case IsObjectOrNull:
case IsFunction:
+ case IsRegExpObject:
case TypeOf:
case LogicalNot:
case ToPrimitive:
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 97ed6ad..3a2b119 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -1530,6 +1530,7 @@
case IsNumber:
case IsObjectOrNull:
case IsFunction:
+ case IsRegExpObject:
case CreateDirectArguments:
case CreateClonedArguments:
case Jump:
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index f471419..4f44749 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -313,6 +313,7 @@
macro(IsObject, NodeResultBoolean) \
macro(IsObjectOrNull, NodeResultBoolean) \
macro(IsFunction, NodeResultBoolean) \
+ macro(IsRegExpObject, NodeResultBoolean) \
macro(TypeOf, NodeResultJS) \
macro(LogicalNot, NodeResultBoolean) \
macro(ToPrimitive, NodeResultJS | NodeMustGenerate) \
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index e4d26e0..1e175d2 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -437,7 +437,8 @@
case IsString:
case IsObject:
case IsObjectOrNull:
- case IsFunction: {
+ case IsFunction:
+ case IsRegExpObject: {
changed |= setPrediction(SpecBoolean);
break;
}
diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
index 31531c6..0e5ea46 100644
--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
@@ -263,6 +263,7 @@
case IsObject:
case IsObjectOrNull:
case IsFunction:
+ case IsRegExpObject:
case TypeOf:
case LogicalNot:
case CallObjectConstructor:
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index 8ce6e95..6509b2e 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -3442,6 +3442,30 @@
unblessedBooleanResult(resultGPR, node);
}
+void SpeculativeJIT::compileIsRegExpObject(Node* node)
+{
+ JSValueOperand value(this, node->child1());
+ GPRFlushedCallResult result(this);
+
+ JSValueRegs valueRegs = value.jsValueRegs();
+ GPRReg resultGPR = result.gpr();
+
+ JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(valueRegs);
+
+ m_jit.compare8(JITCompiler::Equal,
+ JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoTypeOffset()),
+ TrustedImm32(RegExpObjectType),
+ resultGPR);
+ blessBoolean(resultGPR);
+ JITCompiler::Jump done = m_jit.jump();
+
+ isNotCell.link(&m_jit);
+ moveFalseTo(resultGPR);
+
+ done.link(&m_jit);
+ blessedBooleanResult(resultGPR, node);
+}
+
void SpeculativeJIT::compileCallObjectConstructor(Node* node)
{
RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index 1bd88c5..92fcaf5 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -738,6 +738,7 @@
void compileIsJSArray(Node*);
void compileIsArrayConstructor(Node*);
void compileIsArrayObject(Node*);
+ void compileIsRegExpObject(Node*);
void emitCall(Node*);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index b749c94..b52d10c 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -4535,6 +4535,12 @@
compileIsFunction(node);
break;
}
+
+ case IsRegExpObject: {
+ compileIsRegExpObject(node);
+ break;
+ }
+
case TypeOf: {
compileTypeOf(node);
break;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 9915102..4d24a55 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -4563,6 +4563,11 @@
break;
}
+ case IsRegExpObject: {
+ compileIsRegExpObject(node);
+ break;
+ }
+
case TypeOf: {
compileTypeOf(node);
break;