Diff
Modified: trunk/LayoutTests/ChangeLog (197640 => 197641)
--- trunk/LayoutTests/ChangeLog 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/LayoutTests/ChangeLog 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1,3 +1,14 @@
+2016-03-06 Filip Pizlo <fpi...@apple.com>
+
+ RegExpMatchesArray doesn't know how to have a bad time
+ https://bugs.webkit.org/show_bug.cgi?id=155069
+
+ Reviewed by Yusuke Suzuki.
+
+ * js/regress/regexp-exec-expected.txt: Added.
+ * js/regress/regexp-exec.html: Added.
+ * js/regress/script-tests/regexp-exec.js: Added.
+
2016-03-06 Zalan Bujtas <za...@apple.com>
[iOS] Gardening after r197627.
Added: trunk/LayoutTests/js/regress/regexp-exec-expected.txt (0 => 197641)
--- trunk/LayoutTests/js/regress/regexp-exec-expected.txt (rev 0)
+++ trunk/LayoutTests/js/regress/regexp-exec-expected.txt 2016-03-06 20:11:09 UTC (rev 197641)
@@ -0,0 +1,10 @@
+JSRegress/regexp-exec
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/regress/regexp-exec.html (0 => 197641)
--- trunk/LayoutTests/js/regress/regexp-exec.html (rev 0)
+++ trunk/LayoutTests/js/regress/regexp-exec.html 2016-03-06 20:11:09 UTC (rev 197641)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/regress/script-tests/regexp-exec.js (0 => 197641)
--- trunk/LayoutTests/js/regress/script-tests/regexp-exec.js (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/regexp-exec.js 2016-03-06 20:11:09 UTC (rev 197641)
@@ -0,0 +1,9 @@
+(function() {
+ var result = 0;
+ var n = 1000000;
+ var re = /foo/;
+ for (var i = 0; i < n; ++i)
+ result += re.exec("foo").length;
+ if (result != n)
+ throw "Error: bad result: " + result;
+})();
Modified: trunk/Source/_javascript_Core/ChangeLog (197640 => 197641)
--- trunk/Source/_javascript_Core/ChangeLog 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1,3 +1,131 @@
+2016-03-06 Filip Pizlo <fpi...@apple.com>
+
+ RegExpMatchesArray doesn't know how to have a bad time
+ https://bugs.webkit.org/show_bug.cgi?id=155069
+
+ Reviewed by Yusuke Suzuki.
+
+ In trunk if we are having a bad time, the regexp matches array is still allocated with a
+ non-slow-put indexing shape, which makes it have the wrong behavior on indexed setters on
+ the prototype chain.
+
+ Getting this to work right requires introducing bad time code paths into the regexp matches
+ array. It also requires something more drastic: making this code not play games with the
+ global object. The code that creates the matches array needs to have the actual global
+ object of the regexp native function that it's logically created by.
+
+ This is totally different from how we've handled global objects in the past because it means
+ that the global object is not a constant. Normally we can make it a constant because a
+ script executable will know its global object. But with native functions, it's the function
+ instance that knows the global object - not the native executable. When we inline a native
+ intrinsic, we are guaranteed to know the native executable but we're not guaranteed to know
+ the functon instance. This means that the global object may be a variable that gets computed
+ by looking at the instance at run-time. So, the RegExpExec/RegExpTest nodes in DFG IR now
+ take a global object child. That also meant adding a new node type, GetGlobalObject, which
+ does the thing to the callee that CallFrame::lexicalGlobalObject() would have done.
+ Eventually, we'll probably have to make other native intrinsics also use GetGlobalObject. It
+ turns out that this really isn't so bad because usually it's constant-folded anyway, since
+ although the intrinsic code supports executable-based inlining (which leaves the callee
+ instance as an unknown), it happens rarely for intrinsics. So, conveying the global object
+ via a child isn't any worse than conveying it via meta-data, and it's probably better than
+ telling the inliner not to do executable-based inlining of native intrinsics. That would
+ have been a confusing special-case.
+
+ This is perf-neutral on my machines but it fixes a bug and it unlocks some interesting
+ possibilities. For example, RegExpExec can now make a firm promise about the type of array
+ it's creating.
+
+ This also contains some other changes:
+
+ - We are now using Structure::addPropertyTransition() in a lot of places even though it was
+ meant to be an internal method with a quirky contract - for example if only works if you
+ know that there is not existing transition. This relaxes this constraint.
+
+ - Restores the use of "*" for heap references in JSString.h. It's very unusual to have heap
+ references pointed at with "&", since we don't currently do that anywhere. The fact that
+ it was using the wrong reference type also meant that the code couldn't elegantly make use
+ of some our GC pointer helpers like jsCast<>.
+
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::attemptToInlineCall):
+ (JSC::DFG::ByteCodeParser::handleMinMax):
+ (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/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileSkipScope):
+ (JSC::DFG::SpeculativeJIT::compileGetGlobalObject):
+ (JSC::DFG::SpeculativeJIT::compileGetArrayLength):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ * 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::compileSkipScope):
+ (JSC::FTL::DFG::LowerDFGToB3::compileGetGlobalObject):
+ (JSC::FTL::DFG::LowerDFGToB3::compileGetClosureVar):
+ (JSC::FTL::DFG::LowerDFGToB3::compileRegExpExec):
+ (JSC::FTL::DFG::LowerDFGToB3::compileRegExpTest):
+ (JSC::FTL::DFG::LowerDFGToB3::compileNewRegexp):
+ * jit/JITOperations.h:
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::init):
+ (JSC::JSGlobalObject::haveABadTime):
+ (JSC::JSGlobalObject::visitChildren):
+ * runtime/JSGlobalObject.h:
+ * runtime/JSObject.h:
+ (JSC::JSObject::putDirectInternal):
+ * runtime/JSString.h:
+ (JSC::jsString):
+ (JSC::jsSubstring):
+ * runtime/RegExpCachedResult.cpp:
+ (JSC::RegExpCachedResult::lastResult):
+ * runtime/RegExpMatchesArray.cpp:
+ (JSC::tryCreateUninitializedRegExpMatchesArray):
+ (JSC::createRegExpMatchesArray):
+ (JSC::createStructureImpl):
+ (JSC::createRegExpMatchesArrayStructure):
+ (JSC::createRegExpMatchesArraySlowPutStructure):
+ * runtime/RegExpMatchesArray.h:
+ * runtime/RegExpObject.cpp:
+ (JSC::RegExpObject::put):
+ (JSC::RegExpObject::exec):
+ (JSC::RegExpObject::match):
+ * runtime/RegExpObject.h:
+ (JSC::RegExpObject::getLastIndex):
+ (JSC::RegExpObject::test):
+ * runtime/RegExpPrototype.cpp:
+ (JSC::regExpProtoFuncTest):
+ (JSC::regExpProtoFuncExec):
+ (JSC::regExpProtoFuncCompile):
+ * runtime/StringPrototype.cpp:
+ (JSC::stringProtoFuncMatch):
+ * runtime/Structure.cpp:
+ (JSC::Structure::suggestedArrayStorageTransition):
+ (JSC::Structure::addPropertyTransition):
+ (JSC::Structure::addNewPropertyTransition):
+ * runtime/Structure.h:
+ * tests/stress/regexp-matches-array-bad-time.js: Added.
+ * tests/stress/regexp-matches-array-slow-put.js: Added.
+
2016-03-06 Yusuke Suzuki <utatane....@gmail.com>
[JSC] RegExp#lastIndex should handle writable attribute when defining in defineOwnProperty path
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1554,17 +1554,29 @@
}
case RegExpExec:
- if (node->child1().useKind() == RegExpObjectUse
- && node->child2().useKind() == StringUse) {
+ if (node->child2().useKind() == RegExpObjectUse
+ && node->child3().useKind() == StringUse) {
// This doesn't clobber the world since there are no conversions to perform.
} else
clobberWorld(node->origin.semantic, clobberLimit);
- forNode(node).makeHeapTop();
+ if (JSValue globalObjectValue = forNode(node->child1()).m_value) {
+ if (JSGlobalObject* globalObject = jsDynamicCast<JSGlobalObject*>(globalObjectValue)) {
+ if (!globalObject->isHavingABadTime()) {
+ m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
+ Structure* structure = globalObject->regExpMatchesArrayStructure();
+ m_graph.registerStructure(structure);
+ forNode(node).set(m_graph, structure);
+ forNode(node).merge(SpecOther);
+ break;
+ }
+ }
+ }
+ forNode(node).setType(m_graph, SpecOther | SpecArray);
break;
case RegExpTest:
- if (node->child1().useKind() == RegExpObjectUse
- && node->child2().useKind() == StringUse) {
+ if (node->child2().useKind() == RegExpObjectUse
+ && node->child3().useKind() == StringUse) {
// This doesn't clobber the world since there are no conversions to perform.
} else
clobberWorld(node->origin.semantic, clobberLimit);
@@ -1882,6 +1894,33 @@
break;
}
+ case GetGlobalObject: {
+ JSValue child = forNode(node->child1()).value();
+ if (child) {
+ setConstant(node, *m_graph.freeze(JSValue(asObject(child)->globalObject())));
+ break;
+ }
+
+ if (forNode(node->child1()).m_structure.isFinite()) {
+ JSGlobalObject* globalObject = nullptr;
+ bool ok = true;
+ forNode(node->child1()).m_structure.forEach(
+ [&] (Structure* structure) {
+ if (!globalObject)
+ globalObject = structure->globalObject();
+ else if (globalObject != structure->globalObject())
+ ok = false;
+ });
+ if (globalObject && ok) {
+ setConstant(node, *m_graph.freeze(JSValue(globalObject)));
+ break;
+ }
+ }
+
+ forNode(node).setType(m_graph, SpecObjectOther);
+ break;
+ }
+
case GetClosureVar:
if (JSValue value = m_graph.tryGetConstantClosureVar(forNode(node->child1()), node->scopeOffset())) {
setConstant(node, *m_graph.freeze(value));
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -202,7 +202,7 @@
void cancelLinkingForBlock(InlineStackEntry*, BasicBlock*); // Only works when the given block is the last one to have been added for that inline stack entry.
// Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call.
template<typename ChecksFunctor>
- bool handleIntrinsicCall(int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks);
+ bool handleIntrinsicCall(Node* callee, int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks);
template<typename ChecksFunctor>
bool handleIntrinsicGetter(int resultOperand, const GetByIdVariant& intrinsicVariant, Node* thisNode, const ChecksFunctor& insertChecks);
template<typename ChecksFunctor>
@@ -1601,7 +1601,7 @@
Intrinsic intrinsic = callee.intrinsicFor(specializationKind);
if (intrinsic != NoIntrinsic) {
- if (handleIntrinsicCall(resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) {
+ if (handleIntrinsicCall(callTargetNode, resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) {
RELEASE_ASSERT(didInsertChecks);
addToGraph(Phantom, callTargetNode);
emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
@@ -1991,7 +1991,7 @@
}
template<typename ChecksFunctor>
-bool ByteCodeParser::handleIntrinsicCall(int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks)
+bool ByteCodeParser::handleIntrinsicCall(Node* callee, int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks)
{
switch (intrinsic) {
@@ -2172,7 +2172,7 @@
return false;
insertChecks();
- Node* regExpExec = addToGraph(RegExpExec, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
+ Node* regExpExec = addToGraph(RegExpExec, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
set(VirtualRegister(resultOperand), regExpExec);
return true;
@@ -2183,7 +2183,7 @@
return false;
insertChecks();
- Node* regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
+ Node* regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
set(VirtualRegister(resultOperand), regExpExec);
return true;
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2016-03-06 20:11:09 UTC (rev 197641)
@@ -134,6 +134,7 @@
case ArithLog:
case GetScope:
case SkipScope:
+ case GetGlobalObject:
case StringCharCodeAt:
case CompareStrictEq:
case IsUndefined:
@@ -1078,8 +1079,8 @@
case RegExpExec:
case RegExpTest:
- if (node->child1().useKind() == RegExpObjectUse
- && node->child2().useKind() == StringUse) {
+ if (node->child2().useKind() == RegExpObjectUse
+ && node->child3().useKind() == StringUse) {
read(RegExpState);
write(RegExpState);
return;
Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -111,6 +111,7 @@
case CheckArray:
case GetScope:
case SkipScope:
+ case GetGlobalObject:
case GetClosureVar:
case PutClosureVar:
case GetRegExpObjectLastIndex:
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -879,11 +879,13 @@
case RegExpExec:
case RegExpTest: {
- if (node->child1()->shouldSpeculateRegExpObject()) {
- fixEdge<RegExpObjectUse>(node->child1());
+ fixEdge<KnownCellUse>(node->child1());
+
+ if (node->child2()->shouldSpeculateRegExpObject()) {
+ fixEdge<RegExpObjectUse>(node->child2());
- if (node->child2()->shouldSpeculateString())
- fixEdge<StringUse>(node->child2());
+ if (node->child3()->shouldSpeculateString())
+ fixEdge<StringUse>(node->child3());
}
break;
}
@@ -1049,7 +1051,8 @@
case SkipScope:
case GetScope:
case GetGetter:
- case GetSetter: {
+ case GetSetter:
+ case GetGlobalObject: {
fixEdge<KnownCellUse>(node->child1());
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2016-03-06 20:11:09 UTC (rev 197641)
@@ -212,6 +212,7 @@
macro(GetTypedArrayByteOffset, NodeResultInt32) \
macro(GetScope, NodeResultJS) \
macro(SkipScope, NodeResultJS) \
+ macro(GetGlobalObject, NodeResultJS) \
macro(GetClosureVar, NodeResultJS) \
macro(PutClosureVar, NodeMustGenerate) \
macro(GetGlobalVar, NodeResultJS) \
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -619,17 +619,17 @@
return JSValue::encode(array->pop(exec));
}
-EncodedJSValue JIT_OPERATION operationRegExpExecString(ExecState* exec, RegExpObject* regExpObject, JSString* argument)
+EncodedJSValue JIT_OPERATION operationRegExpExecString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* argument)
{
- VM& vm = exec->vm();
+ VM& vm = globalObject->vm();
NativeCallFrameTracer tracer(&vm, exec);
- return JSValue::encode(regExpObject->exec(exec, argument));
+ return JSValue::encode(regExpObject->exec(exec, globalObject, argument));
}
-EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
+EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
{
- VM& vm = exec->vm();
+ VM& vm = globalObject->vm();
NativeCallFrameTracer tracer(&vm, exec);
JSValue argument = JSValue::decode(encodedArgument);
@@ -637,12 +637,12 @@
JSString* input = argument.toStringOrNull(exec);
if (!input)
return JSValue::encode(jsUndefined());
- return JSValue::encode(regExpObject->exec(exec, input));
+ return JSValue::encode(regExpObject->exec(exec, globalObject, input));
}
-EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
+EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
{
- VM& vm = exec->vm();
+ VM& vm = globalObject->vm();
NativeCallFrameTracer tracer(&vm, exec);
JSValue base = JSValue::decode(encodedBase);
@@ -654,20 +654,20 @@
JSString* input = argument.toStringOrNull(exec);
if (!input)
return JSValue::encode(jsUndefined());
- return JSValue::encode(asRegExpObject(base)->exec(exec, input));
+ return JSValue::encode(asRegExpObject(base)->exec(exec, globalObject, input));
}
-size_t JIT_OPERATION operationRegExpTestString(ExecState* exec, RegExpObject* regExpObject, JSString* input)
+size_t JIT_OPERATION operationRegExpTestString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* input)
{
- VM& vm = exec->vm();
+ VM& vm = globalObject->vm();
NativeCallFrameTracer tracer(&vm, exec);
- return regExpObject->test(exec, input);
+ return regExpObject->test(exec, globalObject, input);
}
-size_t JIT_OPERATION operationRegExpTest(ExecState* exec, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
+size_t JIT_OPERATION operationRegExpTest(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
{
- VM& vm = exec->vm();
+ VM& vm = globalObject->vm();
NativeCallFrameTracer tracer(&vm, exec);
JSValue argument = JSValue::decode(encodedArgument);
@@ -675,12 +675,12 @@
JSString* input = argument.toStringOrNull(exec);
if (!input)
return false;
- return regExpObject->test(exec, input);
+ return regExpObject->test(exec, globalObject, input);
}
-size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
+size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
{
- VM& vm = exec->vm();
+ VM& vm = globalObject->vm();
NativeCallFrameTracer tracer(&vm, exec);
JSValue base = JSValue::decode(encodedBase);
@@ -694,7 +694,7 @@
JSString* input = argument.toStringOrNull(exec);
if (!input)
return false;
- return asRegExpObject(base)->test(exec, input);
+ return asRegExpObject(base)->test(exec, globalObject, input);
}
size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2016-03-06 20:11:09 UTC (rev 197641)
@@ -101,13 +101,13 @@
EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState*, double value, JSArray*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationArrayPop(ExecState*, JSArray*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationArrayPopAndRecoverLength(ExecState*, JSArray*) WTF_INTERNAL;
-EncodedJSValue JIT_OPERATION operationRegExpExecString(ExecState*, RegExpObject*, JSString*) WTF_INTERNAL;
-EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState*, RegExpObject*, EncodedJSValue) WTF_INTERNAL;
-EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationRegExpExecString(ExecState*, JSGlobalObject*, RegExpObject*, JSString*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState*, JSGlobalObject*, RegExpObject*, EncodedJSValue) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState*, JSGlobalObject*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
// These comparisons return a boolean within a size_t such that the value is zero extended to fill the register.
-size_t JIT_OPERATION operationRegExpTestString(ExecState*, RegExpObject*, JSString*) WTF_INTERNAL;
-size_t JIT_OPERATION operationRegExpTest(ExecState*, RegExpObject*, EncodedJSValue) WTF_INTERNAL;
-size_t JIT_OPERATION operationRegExpTestGeneric(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
+size_t JIT_OPERATION operationRegExpTestString(ExecState*, JSGlobalObject*, RegExpObject*, JSString*) WTF_INTERNAL;
+size_t JIT_OPERATION operationRegExpTest(ExecState*, JSGlobalObject*, RegExpObject*, EncodedJSValue) WTF_INTERNAL;
+size_t JIT_OPERATION operationRegExpTestGeneric(ExecState*, JSGlobalObject*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
size_t JIT_OPERATION operationCompareStrictEqCell(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
size_t JIT_OPERATION operationCompareStrictEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState*, Structure*, JSScope*, SymbolTable*, EncodedJSValue);
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -550,7 +550,8 @@
break;
}
- case SkipScope: {
+ case SkipScope:
+ case GetGlobalObject: {
changed |= setPrediction(SpecObjectOther);
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2016-03-06 20:11:09 UTC (rev 197641)
@@ -207,6 +207,7 @@
case ArrayifyToStructure:
case GetScope:
case SkipScope:
+ case GetGlobalObject:
case GetClosureVar:
case PutClosureVar:
case GetGlobalVar:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -5342,6 +5342,16 @@
cellResult(result.gpr(), node);
}
+void SpeculativeJIT::compileGetGlobalObject(Node* node)
+{
+ SpeculateCellOperand object(this, node->child1());
+ GPRTemporary result(this);
+ GPRTemporary scratch(this);
+ m_jit.emitLoadStructure(object.gpr(), result.gpr(), scratch.gpr());
+ m_jit.loadPtr(JITCompiler::Address(result.gpr(), Structure::globalObjectOffset()), result.gpr());
+ cellResult(result.gpr(), node);
+}
+
void SpeculativeJIT::compileGetArrayLength(Node* node)
{
switch (node->arrayMode().type()) {
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1217,15 +1217,15 @@
return appendCallSetResult(operation, result);
}
- JITCompiler::Call callOperation(J_JITOperation_EReoJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+ JITCompiler::Call callOperation(J_JITOperation_EGReoJ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
{
- m_jit.setupArgumentsWithExecState(arg1, arg2);
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
return appendCallSetResult(operation, result);
}
- JITCompiler::Call callOperation(J_JITOperation_EReoJss operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+ JITCompiler::Call callOperation(J_JITOperation_EGReoJss operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
{
- m_jit.setupArgumentsWithExecState(arg1, arg2);
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
return appendCallSetResult(operation, result);
}
@@ -1446,16 +1446,21 @@
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallSetResult(operation, result);
}
- JITCompiler::Call callOperation(S_JITOperation_EReoJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+ JITCompiler::Call callOperation(S_JITOperation_EGJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
{
- m_jit.setupArgumentsWithExecState(arg1, arg2);
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
return appendCallSetResult(operation, result);
}
- JITCompiler::Call callOperation(S_JITOperation_EReoJss operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+ JITCompiler::Call callOperation(S_JITOperation_EGReoJ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
{
- m_jit.setupArgumentsWithExecState(arg1, arg2);
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(S_JITOperation_EGReoJss operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+ return appendCallSetResult(operation, result);
+ }
JITCompiler::Call callOperation(J_JITOperation_EPP operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
@@ -1467,6 +1472,11 @@
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(J_JITOperation_EGJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+ return appendCallSetResult(operation, result);
+ }
JITCompiler::Call callOperation(J_JITOperation_EJJ operation, GPRReg result, GPRReg arg1, int32_t imm)
{
m_jit.setupArgumentsWithExecState(arg1, MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(imm))));
@@ -1722,14 +1732,14 @@
m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell), EABI_32BIT_DUMMY_ARG arg2Payload, arg2Tag);
return appendCallSetResult(operation, result);
}
- JITCompiler::Call callOperation(J_JITOperation_EReoJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload)
+ JITCompiler::Call callOperation(J_JITOperation_EGReoJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload)
{
- m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag);
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3Payload, arg3Tag);
return appendCallSetResult(operation, resultPayload, resultTag);
}
- JITCompiler::Call callOperation(J_JITOperation_EReoJss operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2)
+ JITCompiler::Call callOperation(J_JITOperation_EGReoJss operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2, GPRReg arg3)
{
- m_jit.setupArgumentsWithExecState(arg1, arg2);
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
return appendCallSetResult(operation, resultPayload, resultTag);
}
JITCompiler::Call callOperation(J_JITOperation_ESsiCI operation, GPRReg resultTag, GPRReg resultPayload, StructureStubInfo* stubInfo, GPRReg arg1, const UniquedStringImpl* uid)
@@ -1829,21 +1839,31 @@
m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag);
return appendCallSetResult(operation, result);
}
- JITCompiler::Call callOperation(S_JITOperation_EReoJ operation, GPRReg result, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload)
+ JITCompiler::Call callOperation(S_JITOperation_EGJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, GPRReg arg3Tag, GPRReg arg3Payload)
{
- m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag);
+ m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, SH4_32BIT_DUMMY_ARG arg3Payload, arg3Tag);
return appendCallSetResult(operation, result);
}
- JITCompiler::Call callOperation(S_JITOperation_EReoJss operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+ JITCompiler::Call callOperation(S_JITOperation_EGReoJ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload)
{
- m_jit.setupArgumentsWithExecState(arg1, arg2);
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3Payload, arg3Tag);
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(S_JITOperation_EGReoJss operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+ return appendCallSetResult(operation, result);
+ }
JITCompiler::Call callOperation(J_JITOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
{
m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag);
return appendCallSetResult(operation, resultPayload, resultTag);
}
+ JITCompiler::Call callOperation(J_JITOperation_EGJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, GPRReg arg3Tag, GPRReg arg3Payload)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, SH4_32BIT_DUMMY_ARG arg3Payload, arg3Tag);
+ return appendCallSetResult(operation, resultPayload, resultTag);
+ }
JITCompiler::Call callOperation(J_JITOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, MacroAssembler::TrustedImm32 imm)
{
m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG imm, TrustedImm32(JSValue::Int32Tag));
@@ -2309,6 +2329,7 @@
void compileGetScope(Node*);
void compileSkipScope(Node*);
+ void compileGetGlobalObject(Node*);
void compileGetArrayLength(Node*);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -2836,48 +2836,51 @@
}
case RegExpExec: {
- if (node->child1().useKind() == RegExpObjectUse) {
- if (node->child2().useKind() == StringUse) {
- SpeculateCellOperand base(this, node->child1());
- SpeculateCellOperand argument(this, node->child2());
+ SpeculateCellOperand globalObject(this, node->child1());
+ GPRReg globalObjectGPR = globalObject.gpr();
+
+ if (node->child2().useKind() == RegExpObjectUse) {
+ if (node->child3().useKind() == StringUse) {
+ SpeculateCellOperand base(this, node->child2());
+ SpeculateCellOperand argument(this, node->child3());
GPRReg baseGPR = base.gpr();
GPRReg argumentGPR = argument.gpr();
- speculateRegExpObject(node->child1(), baseGPR);
- speculateString(node->child2(), argumentGPR);
+ speculateRegExpObject(node->child2(), baseGPR);
+ speculateString(node->child3(), argumentGPR);
flushRegisters();
GPRFlushedCallResult2 resultTag(this);
GPRFlushedCallResult resultPayload(this);
callOperation(
- operationRegExpExecString, resultTag.gpr(), resultPayload.gpr(), baseGPR,
- argumentGPR);
+ operationRegExpExecString, resultTag.gpr(), resultPayload.gpr(),
+ globalObjectGPR, baseGPR, argumentGPR);
m_jit.exceptionCheck();
jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
break;
}
- SpeculateCellOperand base(this, node->child1());
- JSValueOperand argument(this, node->child2());
+ SpeculateCellOperand base(this, node->child2());
+ JSValueOperand argument(this, node->child3());
GPRReg baseGPR = base.gpr();
GPRReg argumentTagGPR = argument.tagGPR();
GPRReg argumentPayloadGPR = argument.payloadGPR();
- speculateRegExpObject(node->child1(), baseGPR);
+ speculateRegExpObject(node->child2(), baseGPR);
flushRegisters();
GPRFlushedCallResult2 resultTag(this);
GPRFlushedCallResult resultPayload(this);
callOperation(
- operationRegExpExec, resultTag.gpr(), resultPayload.gpr(), baseGPR, argumentTagGPR,
- argumentPayloadGPR);
+ operationRegExpExec, resultTag.gpr(), resultPayload.gpr(), globalObjectGPR, baseGPR,
+ argumentTagGPR, argumentPayloadGPR);
m_jit.exceptionCheck();
jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
break;
}
- JSValueOperand base(this, node->child1());
- JSValueOperand argument(this, node->child2());
+ JSValueOperand base(this, node->child2());
+ JSValueOperand argument(this, node->child3());
GPRReg baseTagGPR = base.tagGPR();
GPRReg basePayloadGPR = base.payloadGPR();
GPRReg argumentTagGPR = argument.tagGPR();
@@ -2886,7 +2889,9 @@
flushRegisters();
GPRFlushedCallResult2 resultTag(this);
GPRFlushedCallResult resultPayload(this);
- callOperation(operationRegExpExecGeneric, resultTag.gpr(), resultPayload.gpr(), baseTagGPR, basePayloadGPR, argumentTagGPR, argumentPayloadGPR);
+ callOperation(
+ operationRegExpExecGeneric, resultTag.gpr(), resultPayload.gpr(), globalObjectGPR,
+ baseTagGPR, basePayloadGPR, argumentTagGPR, argumentPayloadGPR);
m_jit.exceptionCheck();
jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
@@ -2894,43 +2899,48 @@
}
case RegExpTest: {
- if (node->child1().useKind() == RegExpObjectUse) {
- if (node->child2().useKind() == StringUse) {
- SpeculateCellOperand base(this, node->child1());
- SpeculateCellOperand argument(this, node->child2());
+ SpeculateCellOperand globalObject(this, node->child1());
+ GPRReg globalObjectGPR = globalObject.gpr();
+
+ if (node->child2().useKind() == RegExpObjectUse) {
+ if (node->child3().useKind() == StringUse) {
+ SpeculateCellOperand base(this, node->child2());
+ SpeculateCellOperand argument(this, node->child3());
GPRReg baseGPR = base.gpr();
GPRReg argumentGPR = argument.gpr();
- speculateRegExpObject(node->child1(), baseGPR);
- speculateString(node->child2(), argumentGPR);
+ speculateRegExpObject(node->child2(), baseGPR);
+ speculateString(node->child3(), argumentGPR);
flushRegisters();
GPRFlushedCallResult result(this);
- callOperation(operationRegExpTestString, result.gpr(), baseGPR, argumentGPR);
+ callOperation(
+ operationRegExpTestString, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
m_jit.exceptionCheck();
booleanResult(result.gpr(), node);
break;
}
- SpeculateCellOperand base(this, node->child1());
- JSValueOperand argument(this, node->child2());
+ SpeculateCellOperand base(this, node->child2());
+ JSValueOperand argument(this, node->child3());
GPRReg baseGPR = base.gpr();
GPRReg argumentTagGPR = argument.tagGPR();
GPRReg argumentPayloadGPR = argument.payloadGPR();
- speculateRegExpObject(node->child1(), baseGPR);
+ speculateRegExpObject(node->child2(), baseGPR);
flushRegisters();
GPRFlushedCallResult result(this);
callOperation(
- operationRegExpTest, result.gpr(), baseGPR, argumentTagGPR, argumentPayloadGPR);
+ operationRegExpTest, result.gpr(), globalObjectGPR, baseGPR, argumentTagGPR,
+ argumentPayloadGPR);
m_jit.exceptionCheck();
booleanResult(result.gpr(), node);
break;
}
- JSValueOperand base(this, node->child1());
- JSValueOperand argument(this, node->child2());
+ JSValueOperand base(this, node->child2());
+ JSValueOperand argument(this, node->child3());
GPRReg baseTagGPR = base.tagGPR();
GPRReg basePayloadGPR = base.payloadGPR();
GPRReg argumentTagGPR = argument.tagGPR();
@@ -2938,7 +2948,9 @@
flushRegisters();
GPRFlushedCallResult result(this);
- callOperation(operationRegExpTestGeneric, result.gpr(), baseTagGPR, basePayloadGPR, argumentTagGPR, argumentPayloadGPR);
+ callOperation(
+ operationRegExpTestGeneric, result.gpr(), globalObjectGPR, baseTagGPR, basePayloadGPR,
+ argumentTagGPR, argumentPayloadGPR);
m_jit.exceptionCheck();
booleanResult(result.gpr(), node);
@@ -3901,6 +3913,10 @@
compileSkipScope(node);
break;
+ case GetGlobalObject:
+ compileGetGlobalObject(node);
+ break;
+
case GetClosureVar: {
SpeculateCellOperand base(this, node->child1());
GPRTemporary resultTag(this);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -2962,47 +2962,50 @@
}
case RegExpExec: {
- if (node->child1().useKind() == RegExpObjectUse) {
- if (node->child2().useKind() == StringUse) {
- SpeculateCellOperand base(this, node->child1());
- SpeculateCellOperand argument(this, node->child2());
+ SpeculateCellOperand globalObject(this, node->child1());
+ GPRReg globalObjectGPR = globalObject.gpr();
+
+ if (node->child2().useKind() == RegExpObjectUse) {
+ if (node->child3().useKind() == StringUse) {
+ SpeculateCellOperand base(this, node->child2());
+ SpeculateCellOperand argument(this, node->child3());
GPRReg baseGPR = base.gpr();
GPRReg argumentGPR = argument.gpr();
- speculateRegExpObject(node->child1(), baseGPR);
- speculateString(node->child2(), argumentGPR);
+ speculateRegExpObject(node->child2(), baseGPR);
+ speculateString(node->child3(), argumentGPR);
flushRegisters();
GPRFlushedCallResult result(this);
- callOperation(operationRegExpExecString, result.gpr(), baseGPR, argumentGPR);
+ callOperation(operationRegExpExecString, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
m_jit.exceptionCheck();
jsValueResult(result.gpr(), node);
break;
}
- SpeculateCellOperand base(this, node->child1());
- JSValueOperand argument(this, node->child2());
+ SpeculateCellOperand base(this, node->child2());
+ JSValueOperand argument(this, node->child3());
GPRReg baseGPR = base.gpr();
GPRReg argumentGPR = argument.gpr();
- speculateRegExpObject(node->child1(), baseGPR);
+ speculateRegExpObject(node->child2(), baseGPR);
flushRegisters();
GPRFlushedCallResult result(this);
- callOperation(operationRegExpExec, result.gpr(), baseGPR, argumentGPR);
+ callOperation(operationRegExpExec, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
m_jit.exceptionCheck();
jsValueResult(result.gpr(), node);
break;
}
- JSValueOperand base(this, node->child1());
- JSValueOperand argument(this, node->child2());
+ JSValueOperand base(this, node->child2());
+ JSValueOperand argument(this, node->child3());
GPRReg baseGPR = base.gpr();
GPRReg argumentGPR = argument.gpr();
flushRegisters();
GPRFlushedCallResult result(this);
- callOperation(operationRegExpExecGeneric, result.gpr(), baseGPR, argumentGPR);
+ callOperation(operationRegExpExecGeneric, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
m_jit.exceptionCheck();
jsValueResult(result.gpr(), node);
@@ -3010,18 +3013,21 @@
}
case RegExpTest: {
- if (node->child1().useKind() == RegExpObjectUse) {
- if (node->child2().useKind() == StringUse) {
- SpeculateCellOperand base(this, node->child1());
- SpeculateCellOperand argument(this, node->child2());
+ SpeculateCellOperand globalObject(this, node->child1());
+ GPRReg globalObjectGPR = globalObject.gpr();
+
+ if (node->child2().useKind() == RegExpObjectUse) {
+ if (node->child3().useKind() == StringUse) {
+ SpeculateCellOperand base(this, node->child2());
+ SpeculateCellOperand argument(this, node->child3());
GPRReg baseGPR = base.gpr();
GPRReg argumentGPR = argument.gpr();
- speculateRegExpObject(node->child1(), baseGPR);
- speculateString(node->child2(), argumentGPR);
+ speculateRegExpObject(node->child2(), baseGPR);
+ speculateString(node->child3(), argumentGPR);
flushRegisters();
GPRFlushedCallResult result(this);
- callOperation(operationRegExpTestString, result.gpr(), baseGPR, argumentGPR);
+ callOperation(operationRegExpTestString, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
m_jit.exceptionCheck();
m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
@@ -3029,15 +3035,15 @@
break;
}
- SpeculateCellOperand base(this, node->child1());
- JSValueOperand argument(this, node->child2());
+ SpeculateCellOperand base(this, node->child2());
+ JSValueOperand argument(this, node->child3());
GPRReg baseGPR = base.gpr();
GPRReg argumentGPR = argument.gpr();
- speculateRegExpObject(node->child1(), baseGPR);
+ speculateRegExpObject(node->child2(), baseGPR);
flushRegisters();
GPRFlushedCallResult result(this);
- callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
+ callOperation(operationRegExpTest, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
m_jit.exceptionCheck();
m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
@@ -3045,14 +3051,14 @@
break;
}
- JSValueOperand base(this, node->child1());
- JSValueOperand argument(this, node->child2());
+ JSValueOperand base(this, node->child2());
+ JSValueOperand argument(this, node->child3());
GPRReg baseGPR = base.gpr();
GPRReg argumentGPR = argument.gpr();
flushRegisters();
GPRFlushedCallResult result(this);
- callOperation(operationRegExpTestGeneric, result.gpr(), baseGPR, argumentGPR);
+ callOperation(operationRegExpTestGeneric, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
m_jit.exceptionCheck();
m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
@@ -3930,6 +3936,10 @@
case SkipScope:
compileSkipScope(node);
break;
+
+ case GetGlobalObject:
+ compileGetGlobalObject(node);
+ break;
case GetClosureVar: {
SpeculateCellOperand base(this, node->child1());
Modified: trunk/Source/_javascript_Core/dfg/DFGStructureRegistrationPhase.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/dfg/DFGStructureRegistrationPhase.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/dfg/DFGStructureRegistrationPhase.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -149,7 +149,7 @@
case NewGeneratorFunction:
registerStructure(m_graph.globalObjectFor(node->origin.semantic)->generatorFunctionStructure());
break;
-
+
default:
break;
}
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -111,6 +111,7 @@
case ExtractOSREntryLocal:
case LoopHint:
case SkipScope:
+ case GetGlobalObject:
case CreateActivation:
case NewArrowFunction:
case NewFunction:
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -748,6 +748,9 @@
case SkipScope:
compileSkipScope();
break;
+ case GetGlobalObject:
+ compileGetGlobalObject();
+ break;
case GetClosureVar:
compileGetClosureVar();
break;
@@ -4475,6 +4478,12 @@
{
setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSScope_next));
}
+
+ void compileGetGlobalObject()
+ {
+ LValue structure = loadStructure(lowCell(m_node->child1()));
+ setJSValue(m_out.loadPtr(structure, m_heaps.Structure_globalObject));
+ }
void compileGetClosureVar()
{
@@ -6440,52 +6449,66 @@
void compileRegExpExec()
{
- if (m_node->child1().useKind() == RegExpObjectUse) {
- LValue base = lowRegExpObject(m_node->child1());
+ LValue globalObject = lowCell(m_node->child1());
+
+ if (m_node->child2().useKind() == RegExpObjectUse) {
+ LValue base = lowRegExpObject(m_node->child2());
- if (m_node->child2().useKind() == StringUse) {
- LValue argument = lowString(m_node->child2());
+ if (m_node->child3().useKind() == StringUse) {
+ LValue argument = lowString(m_node->child3());
LValue result = vmCall(
- Int64, m_out.operation(operationRegExpExecString), m_callFrame, base, argument);
+ Int64, m_out.operation(operationRegExpExecString), m_callFrame, globalObject,
+ base, argument);
setJSValue(result);
return;
}
- LValue argument = lowJSValue(m_node->child2());
- setJSValue(
- vmCall(Int64, m_out.operation(operationRegExpExec), m_callFrame, base, argument));
+ LValue argument = lowJSValue(m_node->child3());
+ LValue result = vmCall(
+ Int64, m_out.operation(operationRegExpExec), m_callFrame, globalObject, base,
+ argument);
+ setJSValue(result);
return;
}
- LValue base = lowJSValue(m_node->child1());
- LValue argument = lowJSValue(m_node->child2());
- setJSValue(
- vmCall(Int64, m_out.operation(operationRegExpExecGeneric), m_callFrame, base, argument));
+ LValue base = lowJSValue(m_node->child2());
+ LValue argument = lowJSValue(m_node->child3());
+ LValue result = vmCall(
+ Int64, m_out.operation(operationRegExpExecGeneric), m_callFrame, globalObject, base,
+ argument);
+ setJSValue(result);
}
void compileRegExpTest()
{
- if (m_node->child1().useKind() == RegExpObjectUse) {
- LValue base = lowRegExpObject(m_node->child1());
+ LValue globalObject = lowCell(m_node->child1());
+
+ if (m_node->child2().useKind() == RegExpObjectUse) {
+ LValue base = lowRegExpObject(m_node->child2());
- if (m_node->child2().useKind() == StringUse) {
- LValue argument = lowString(m_node->child2());
+ if (m_node->child3().useKind() == StringUse) {
+ LValue argument = lowString(m_node->child3());
LValue result = vmCall(
- Int32, m_out.operation(operationRegExpTestString), m_callFrame, base, argument);
+ Int32, m_out.operation(operationRegExpTestString), m_callFrame, globalObject,
+ base, argument);
setBoolean(result);
return;
}
- LValue argument = lowJSValue(m_node->child2());
- setBoolean(
- vmCall(Int32, m_out.operation(operationRegExpTest), m_callFrame, base, argument));
+ LValue argument = lowJSValue(m_node->child3());
+ LValue result = vmCall(
+ Int32, m_out.operation(operationRegExpTest), m_callFrame, globalObject, base,
+ argument);
+ setBoolean(result);
return;
}
- LValue base = lowJSValue(m_node->child1());
- LValue argument = lowJSValue(m_node->child2());
- setBoolean(
- vmCall(Int32, m_out.operation(operationRegExpTestGeneric), m_callFrame, base, argument));
+ LValue base = lowJSValue(m_node->child2());
+ LValue argument = lowJSValue(m_node->child3());
+ LValue result = vmCall(
+ Int32, m_out.operation(operationRegExpTestGeneric), m_callFrame, globalObject, base,
+ argument);
+ setBoolean(result);
}
void compileNewRegexp()
Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (197640 => 197641)
--- trunk/Source/_javascript_Core/jit/JITOperations.h 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h 2016-03-06 20:11:09 UTC (rev 197641)
@@ -122,6 +122,9 @@
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_ECZ)(ExecState*, JSCell*, int32_t);
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EDA)(ExecState*, double, JSArray*);
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EE)(ExecState*, ExecState*);
+typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EGReoJ)(ExecState*, JSGlobalObject*, RegExpObject*, EncodedJSValue);
+typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EGReoJss)(ExecState*, JSGlobalObject*, RegExpObject*, JSString*);
+typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EGJJ)(ExecState*, JSGlobalObject*, EncodedJSValue, EncodedJSValue);
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EI)(ExecState*, UniquedStringImpl*);
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJ)(ExecState*, EncodedJSValue);
typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJZ)(ExecState*, EncodedJSValue, int32_t);
@@ -201,6 +204,9 @@
typedef int32_t JIT_OPERATION (*Z_JITOperation_EJZZ)(ExecState*, EncodedJSValue, int32_t, int32_t);
typedef size_t JIT_OPERATION (*S_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
typedef size_t JIT_OPERATION (*S_JITOperation_EGC)(ExecState*, JSGlobalObject*, JSCell*);
+typedef size_t JIT_OPERATION (*S_JITOperation_EGJJ)(ExecState*, JSGlobalObject*, EncodedJSValue, EncodedJSValue);
+typedef size_t JIT_OPERATION (*S_JITOperation_EGReoJ)(ExecState*, JSGlobalObject*, RegExpObject*, EncodedJSValue);
+typedef size_t JIT_OPERATION (*S_JITOperation_EGReoJss)(ExecState*, JSGlobalObject*, RegExpObject*, JSString*);
typedef size_t JIT_OPERATION (*S_JITOperation_EJ)(ExecState*, EncodedJSValue);
typedef size_t JIT_OPERATION (*S_JITOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
typedef size_t JIT_OPERATION (*S_JITOperation_EOJss)(ExecState*, JSObject*, JSString*);
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008, 2009, 2014, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009, 2014-2016 Apple Inc. All rights reserved.
* Copyright (C) 2008 Cameron Zwarich (cwzwar...@uwaterloo.ca)
*
* Redistribution and use in source and binary forms, with or without
@@ -364,7 +364,8 @@
m_regExpPrototype.set(vm, this, RegExpPrototype::create(vm, this, RegExpPrototype::createStructure(vm, this, m_objectPrototype.get()), emptyRegex));
m_regExpStructure.set(vm, this, RegExpObject::createStructure(vm, this, m_regExpPrototype.get()));
- m_regExpMatchesArrayStructure.set(vm, this, createRegExpMatchesArrayStructure(vm, *this));
+ m_regExpMatchesArrayStructure.set(vm, this, createRegExpMatchesArrayStructure(vm, this));
+ m_regExpMatchesArraySlowPutStructure.set(vm, this, createRegExpMatchesArraySlowPutStructure(vm, this));
m_moduleRecordStructure.set(vm, this, JSModuleRecord::createStructure(vm, this, m_objectPrototype.get()));
m_moduleNamespaceObjectStructure.set(vm, this, JSModuleNamespaceObject::createStructure(vm, this, jsNull()));
@@ -761,6 +762,9 @@
// this object now load a structure that uses SlowPut.
for (unsigned i = 0; i < NumberOfIndexingShapes; ++i)
m_arrayStructureForIndexingShapeDuringAllocation[i].set(vm, this, originalArrayStructureForIndexingType(ArrayWithSlowPutArrayStorage));
+
+ // Same for any special array structures.
+ m_regExpMatchesArrayStructure.set(vm, this, m_regExpMatchesArraySlowPutStructure.get());
// Make sure that all objects that have indexed storage switch to the slow kind of
// indexed storage.
@@ -900,6 +904,7 @@
visitor.append(&thisObject->m_generatorFunctionStructure);
visitor.append(&thisObject->m_iteratorResultObjectStructure);
visitor.append(&thisObject->m_regExpMatchesArrayStructure);
+ visitor.append(&thisObject->m_regExpMatchesArraySlowPutStructure);
visitor.append(&thisObject->m_moduleRecordStructure);
visitor.append(&thisObject->m_moduleNamespaceObjectStructure);
visitor.append(&thisObject->m_consoleStructure);
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (197640 => 197641)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 Eric Seidel <e...@webkit.org>
- * Copyright (C) 2007, 2008, 2009, 2014, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009, 2014-2016 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -278,6 +278,7 @@
WriteBarrier<Structure> m_internalFunctionStructure;
WriteBarrier<Structure> m_iteratorResultObjectStructure;
WriteBarrier<Structure> m_regExpMatchesArrayStructure;
+ WriteBarrier<Structure> m_regExpMatchesArraySlowPutStructure;
WriteBarrier<Structure> m_moduleRecordStructure;
WriteBarrier<Structure> m_moduleNamespaceObjectStructure;
WriteBarrier<Structure> m_proxyObjectStructure;
Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (197640 => 197641)
--- trunk/Source/_javascript_Core/runtime/JSObject.h 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1376,7 +1376,7 @@
// we want.
DeferredStructureTransitionWatchpointFire deferredWatchpointFire;
- newStructure = Structure::addPropertyTransition(
+ newStructure = Structure::addNewPropertyTransition(
vm, structure, propertyName, attributes, offset, slot.context(), &deferredWatchpointFire);
newStructure->willStoreValueForNewTransition(
vm, propertyName, value, slot.context() == PutPropertySlot::PutById);
Modified: trunk/Source/_javascript_Core/runtime/JSString.h (197640 => 197641)
--- trunk/Source/_javascript_Core/runtime/JSString.h 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/runtime/JSString.h 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999-2001 Harri Porten (por...@kde.org)
* Copyright (C) 2001 Peter Kelly (p...@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2014, 2016 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -293,28 +293,27 @@
fiber(2).set(vm, this, s3);
}
- void finishCreation(ExecState& exec, JSString& base, unsigned offset, unsigned length)
+ void finishCreation(VM& vm, ExecState* exec, JSString* base, unsigned offset, unsigned length)
{
- VM& vm = exec.vm();
Base::finishCreation(vm);
ASSERT(!sumOverflows<int32_t>(offset, length));
- ASSERT(offset + length <= base.length());
+ ASSERT(offset + length <= base->length());
m_length = length;
- setIs8Bit(base.is8Bit());
+ setIs8Bit(base->is8Bit());
setIsSubstring(true);
- if (base.isSubstring()) {
- JSRopeString& baseRope = static_cast<JSRopeString&>(base);
- substringBase().set(vm, this, baseRope.substringBase().get());
- substringOffset() = baseRope.substringOffset() + offset;
+ if (base->isSubstring()) {
+ JSRopeString* baseRope = jsCast<JSRopeString*>(base);
+ substringBase().set(vm, this, baseRope->substringBase().get());
+ substringOffset() = baseRope->substringOffset() + offset;
} else {
- substringBase().set(vm, this, &base);
+ substringBase().set(vm, this, base);
substringOffset() = offset;
// For now, let's not allow substrings with a rope base.
// Resolve non-substring rope bases so we don't have to deal with it.
// FIXME: Evaluate if this would be worth adding more branches.
- if (base.isRope())
- static_cast<JSRopeString&>(base).resolveRope(&exec);
+ if (base->isRope())
+ jsCast<JSRopeString*>(base)->resolveRope(exec);
}
}
@@ -356,10 +355,10 @@
return newString;
}
- static JSString* create(ExecState& exec, JSString& base, unsigned offset, unsigned length)
+ static JSString* create(VM& vm, ExecState* exec, JSString* base, unsigned offset, unsigned length)
{
- JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(exec.vm().heap)) JSRopeString(exec.vm());
- newString->finishCreation(exec, base, offset, length);
+ JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(vm.heap)) JSRopeString(vm);
+ newString->finishCreation(vm, exec, base, offset, length);
return newString;
}
@@ -542,19 +541,23 @@
return JSString::create(*vm, s.impl());
}
-inline JSString* jsSubstring(ExecState* exec, JSString* s, unsigned offset, unsigned length)
+inline JSString* jsSubstring(VM& vm, ExecState* exec, JSString* s, unsigned offset, unsigned length)
{
ASSERT(offset <= static_cast<unsigned>(s->length()));
ASSERT(length <= static_cast<unsigned>(s->length()));
ASSERT(offset + length <= static_cast<unsigned>(s->length()));
- VM& vm = exec->vm();
if (!length)
return vm.smallStrings.emptyString();
if (!offset && length == s->length())
return s;
- return JSRopeString::create(*exec, *s, offset, length);
+ return JSRopeString::create(vm, exec, s, offset, length);
}
+inline JSString* jsSubstring(ExecState* exec, JSString* s, unsigned offset, unsigned length)
+{
+ return jsSubstring(exec->vm(), exec, s, offset, length);
+}
+
inline JSString* jsSubstring(VM* vm, const String& s, unsigned offset, unsigned length)
{
ASSERT(offset <= static_cast<unsigned>(s.length()));
Modified: trunk/Source/_javascript_Core/runtime/RegExpCachedResult.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/runtime/RegExpCachedResult.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/runtime/RegExpCachedResult.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -45,7 +45,7 @@
{
if (!m_reified) {
m_reifiedInput.set(exec->vm(), owner, m_lastInput.get());
- m_reifiedResult.set(exec->vm(), owner, createRegExpMatchesArray(exec, m_lastInput.get(), m_lastRegExp.get(), m_result));
+ m_reifiedResult.set(exec->vm(), owner, createRegExpMatchesArray(exec, exec->lexicalGlobalObject(), m_lastInput.get(), m_lastRegExp.get(), m_result));
m_reified = true;
}
return m_reifiedResult.get();
Modified: trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -50,31 +50,57 @@
return JSArray::createWithButterfly(vm, structure, butterfly);
}
-JSArray* createRegExpMatchesArray(ExecState* exec, JSString* input, RegExp* regExp, MatchResult result)
+JSArray* createRegExpMatchesArray(
+ ExecState* exec, JSGlobalObject* globalObject, JSString* input, RegExp* regExp,
+ MatchResult result)
{
+ SamplingRegion samplingRegion("createRegExpMatchesArray");
+
ASSERT(result);
- VM& vm = exec->vm();
- JSArray* array = tryCreateUninitializedRegExpMatchesArray(vm, exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1);
- RELEASE_ASSERT(array);
+ VM& vm = globalObject->vm();
- SamplingRegion samplingRegion("Reifying substring properties");
-
- array->initializeIndex(vm, 0, jsSubstring(exec, input, result.start, result.end - result.start), ArrayWithContiguous);
-
- if (unsigned numSubpatterns = regExp->numSubpatterns()) {
- Vector<int, 32> subpatternResults;
- int position = regExp->match(vm, input->value(exec), result.start, subpatternResults);
- ASSERT_UNUSED(position, position >= 0 && static_cast<size_t>(position) == result.start);
- ASSERT(result.start == static_cast<size_t>(subpatternResults[0]));
- ASSERT(result.end == static_cast<size_t>(subpatternResults[1]));
-
- for (unsigned i = 1; i <= numSubpatterns; ++i) {
- int start = subpatternResults[2 * i];
- if (start >= 0)
- array->initializeIndex(vm, i, jsSubstring(exec, input, start, subpatternResults[2 * i + 1] - start), ArrayWithContiguous);
- else
- array->initializeIndex(vm, i, jsUndefined(), ArrayWithContiguous);
+ JSArray* array;
+ if (UNLIKELY(globalObject->isHavingABadTime())) {
+ array = JSArray::tryCreateUninitialized(vm, globalObject->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1);
+
+ array->initializeIndex(vm, 0, jsSubstring(vm, exec, input, result.start, result.end - result.start));
+
+ if (unsigned numSubpatterns = regExp->numSubpatterns()) {
+ Vector<int, 32> subpatternResults;
+ int position = regExp->match(vm, input->value(exec), result.start, subpatternResults);
+ ASSERT_UNUSED(position, position >= 0 && static_cast<size_t>(position) == result.start);
+ ASSERT(result.start == static_cast<size_t>(subpatternResults[0]));
+ ASSERT(result.end == static_cast<size_t>(subpatternResults[1]));
+
+ for (unsigned i = 1; i <= numSubpatterns; ++i) {
+ int start = subpatternResults[2 * i];
+ if (start >= 0)
+ array->initializeIndex(vm, i, jsSubstring(vm, exec, input, start, subpatternResults[2 * i + 1] - start));
+ else
+ array->initializeIndex(vm, i, jsUndefined());
+ }
}
+ } else {
+ array = tryCreateUninitializedRegExpMatchesArray(vm, globalObject->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1);
+ RELEASE_ASSERT(array);
+
+ array->initializeIndex(vm, 0, jsSubstring(vm, exec, input, result.start, result.end - result.start), ArrayWithContiguous);
+
+ if (unsigned numSubpatterns = regExp->numSubpatterns()) {
+ Vector<int, 32> subpatternResults;
+ int position = regExp->match(vm, input->value(exec), result.start, subpatternResults);
+ ASSERT_UNUSED(position, position >= 0 && static_cast<size_t>(position) == result.start);
+ ASSERT(result.start == static_cast<size_t>(subpatternResults[0]));
+ ASSERT(result.end == static_cast<size_t>(subpatternResults[1]));
+
+ for (unsigned i = 1; i <= numSubpatterns; ++i) {
+ int start = subpatternResults[2 * i];
+ if (start >= 0)
+ array->initializeIndex(vm, i, jsSubstring(vm, exec, input, start, subpatternResults[2 * i + 1] - start), ArrayWithContiguous);
+ else
+ array->initializeIndex(vm, i, jsUndefined(), ArrayWithContiguous);
+ }
+ }
}
array->putDirect(vm, indexPropertyOffset, jsNumber(result.start));
@@ -83,15 +109,25 @@
return array;
}
-Structure* createRegExpMatchesArrayStructure(VM& vm, JSGlobalObject& globalObject)
+static Structure* createStructureImpl(VM& vm, JSGlobalObject* globalObject, IndexingType indexingType)
{
- Structure* structure = globalObject.arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
+ Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType);
PropertyOffset offset;
- structure = structure->addPropertyTransition(vm, structure, vm.propertyNames->index, 0, offset);
+ structure = Structure::addPropertyTransition(vm, structure, vm.propertyNames->index, 0, offset);
ASSERT(offset == indexPropertyOffset);
- structure = structure->addPropertyTransition(vm, structure, vm.propertyNames->input, 0, offset);
+ structure = Structure::addPropertyTransition(vm, structure, vm.propertyNames->input, 0, offset);
ASSERT(offset == inputPropertyOffset);
return structure;
}
+Structure* createRegExpMatchesArrayStructure(VM& vm, JSGlobalObject* globalObject)
+{
+ return createStructureImpl(vm, globalObject, ArrayWithContiguous);
+}
+
+Structure* createRegExpMatchesArraySlowPutStructure(VM& vm, JSGlobalObject* globalObject)
+{
+ return createStructureImpl(vm, globalObject, ArrayWithSlowPutArrayStorage);
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.h (197640 => 197641)
--- trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.h 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.h 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2016 Apple Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,8 +26,9 @@
namespace JSC {
-JSArray* createRegExpMatchesArray(ExecState*, JSString*, RegExp*, MatchResult);
-Structure* createRegExpMatchesArrayStructure(VM&, JSGlobalObject&);
+JSArray* createRegExpMatchesArray(ExecState*, JSGlobalObject*, JSString*, RegExp*, MatchResult);
+Structure* createRegExpMatchesArrayStructure(VM&, JSGlobalObject*);
+Structure* createRegExpMatchesArraySlowPutStructure(VM&, JSGlobalObject*);
}
Modified: trunk/Source/_javascript_Core/runtime/RegExpObject.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/runtime/RegExpObject.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/runtime/RegExpObject.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2000 Harri Porten (por...@kde.org)
- * Copyright (C) 2003, 2007, 2008, 2012 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2003, 2007, 2008, 2012, 2016 Apple Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -159,20 +159,20 @@
Base::put(cell, exec, propertyName, value, slot);
}
-JSValue RegExpObject::exec(ExecState* exec, JSString* string)
+JSValue RegExpObject::exec(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
{
- if (MatchResult result = match(exec, string))
- return createRegExpMatchesArray(exec, string, regExp(), result);
+ if (MatchResult result = match(exec, globalObject, string))
+ return createRegExpMatchesArray(exec, globalObject, string, regExp(), result);
return jsNull();
}
// Shared implementation used by test and exec.
-MatchResult RegExpObject::match(ExecState* exec, JSString* string)
+MatchResult RegExpObject::match(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
{
RegExp* regExp = this->regExp();
- RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
+ RegExpConstructor* regExpConstructor = globalObject->regExpConstructor();
String input = string->value(exec);
- VM& vm = exec->vm();
+ VM& vm = globalObject->vm();
if (!regExp->global())
return regExpConstructor->performMatch(vm, regExp, string, input, 0);
Modified: trunk/Source/_javascript_Core/runtime/RegExpObject.h (197640 => 197641)
--- trunk/Source/_javascript_Core/runtime/RegExpObject.h 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/runtime/RegExpObject.h 2016-03-06 20:11:09 UTC (rev 197641)
@@ -66,8 +66,8 @@
return m_lastIndex.get();
}
- bool test(ExecState* exec, JSString* string) { return match(exec, string); }
- JSValue exec(ExecState*, JSString*);
+ bool test(ExecState* exec, JSGlobalObject* globalObject, JSString* string) { return match(exec, globalObject, string); }
+ JSValue exec(ExecState*, JSGlobalObject*, JSString*);
static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
@@ -102,7 +102,7 @@
JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
private:
- MatchResult match(ExecState*, JSString*);
+ MatchResult match(ExecState*, JSGlobalObject*, JSString*);
WriteBarrier<RegExp> m_regExp;
WriteBarrier<Unknown> m_lastIndex;
Modified: trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2000 Harri Porten (por...@kde.org)
- * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2003, 2007, 2008, 2016 Apple Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -102,7 +102,7 @@
JSString* string = exec->argument(0).toStringOrNull(exec);
if (!string)
return JSValue::encode(jsUndefined());
- return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->test(exec, string)));
+ return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->test(exec, exec->lexicalGlobalObject(), string)));
}
EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec)
@@ -113,7 +113,7 @@
JSString* string = exec->argument(0).toStringOrNull(exec);
if (!string)
return JSValue::encode(jsUndefined());
- return JSValue::encode(asRegExpObject(thisValue)->exec(exec, string));
+ return JSValue::encode(asRegExpObject(thisValue)->exec(exec, exec->lexicalGlobalObject(), string));
}
EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
Modified: trunk/Source/_javascript_Core/runtime/StringPrototype.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/runtime/StringPrototype.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/runtime/StringPrototype.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1035,7 +1035,8 @@
return throwVMTypeError(exec);
JSString* string = thisValue.toString(exec);
String s = string->value(exec);
- VM* vm = &exec->vm();
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+ VM* vm = &globalObject->vm();
JSValue a0 = exec->argument(0);
@@ -1067,11 +1068,11 @@
if (!regExp->isValid())
return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage()));
}
- RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
+ RegExpConstructor* regExpConstructor = globalObject->regExpConstructor();
MatchResult result = regExpConstructor->performMatch(*vm, regExp, string, s, 0);
// case without 'g' flag is handled like RegExp.prototype.exec
if (!global)
- return JSValue::encode(result ? createRegExpMatchesArray(exec, string, regExp, result) : jsNull());
+ return JSValue::encode(result ? createRegExpMatchesArray(exec, globalObject, string, regExp, result) : jsNull());
// return array of matches
MarkedArgumentBuffer list;
Modified: trunk/Source/_javascript_Core/runtime/Structure.cpp (197640 => 197641)
--- trunk/Source/_javascript_Core/runtime/Structure.cpp 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/runtime/Structure.cpp 2016-03-06 20:11:09 UTC (rev 197641)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2013-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -443,8 +443,19 @@
return AllocateArrayStorage;
}
-Structure* Structure::addPropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, unsigned attributes, PropertyOffset& offset, PutPropertySlot::Context context, DeferredStructureTransitionWatchpointFire* deferred)
+Structure* Structure::addPropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, unsigned attributes, PropertyOffset& offset)
{
+ Structure* newStructure = addPropertyTransitionToExistingStructure(
+ structure, propertyName, attributes, offset);
+ if (newStructure)
+ return newStructure;
+
+ return addNewPropertyTransition(
+ vm, structure, propertyName, attributes, offset, PutPropertySlot::UnknownContext);
+}
+
+Structure* Structure::addNewPropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, unsigned attributes, PropertyOffset& offset, PutPropertySlot::Context context, DeferredStructureTransitionWatchpointFire* deferred)
+{
ASSERT(!structure->isDictionary());
ASSERT(structure->isObject());
ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, offset));
Modified: trunk/Source/_javascript_Core/runtime/Structure.h (197640 => 197641)
--- trunk/Source/_javascript_Core/runtime/Structure.h 2016-03-06 20:08:28 UTC (rev 197640)
+++ trunk/Source/_javascript_Core/runtime/Structure.h 2016-03-06 20:11:09 UTC (rev 197641)
@@ -168,7 +168,8 @@
static void dumpStatistics();
- JS_EXPORT_PRIVATE static Structure* addPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, PropertyOffset&, PutPropertySlot::Context = PutPropertySlot::UnknownContext, DeferredStructureTransitionWatchpointFire* = nullptr);
+ JS_EXPORT_PRIVATE static Structure* addPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, PropertyOffset&);
+ JS_EXPORT_PRIVATE static Structure* addNewPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, PropertyOffset&, PutPropertySlot::Context = PutPropertySlot::UnknownContext, DeferredStructureTransitionWatchpointFire* = nullptr);
static Structure* addPropertyTransitionToExistingStructureConcurrently(Structure*, UniquedStringImpl* uid, unsigned attributes, PropertyOffset&);
JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, PropertyName, unsigned attributes, PropertyOffset&);
static Structure* removePropertyTransition(VM&, Structure*, PropertyName, PropertyOffset&);
@@ -245,6 +246,9 @@
NonPropertyTransition suggestedArrayStorageTransition() const;
JSGlobalObject* globalObject() const { return m_globalObject.get(); }
+
+ // NOTE: This method should only be called during the creation of structures, since the global
+ // object of a structure is presumed to be immutable in a bunch of places.
void setGlobalObject(VM& vm, JSGlobalObject* globalObject) { m_globalObject.set(vm, this, globalObject); }
JSValue storedPrototype() const { return m_prototype.get(); }
Added: trunk/Source/_javascript_Core/tests/stress/regexp-matches-array-bad-time.js (0 => 197641)
--- trunk/Source/_javascript_Core/tests/stress/regexp-matches-array-bad-time.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/regexp-matches-array-bad-time.js 2016-03-06 20:11:09 UTC (rev 197641)
@@ -0,0 +1,19 @@
+(function() {
+ var count = 11;
+
+ var array;
+ for (var i = 0; i < 10000; ++i) {
+ array = /foo/.exec("foo");
+ if (array[0] != "foo")
+ throw "Error: bad result: " + array[0];
+ }
+
+ delete array[0];
+
+ Array.prototype.__defineSetter__("0", function(value) { count += value; });
+
+ array[0] = 42;
+ if (count != 53)
+ throw "Error: bad count: " + count;
+})();
+
Added: trunk/Source/_javascript_Core/tests/stress/regexp-matches-array-slow-put.js (0 => 197641)
--- trunk/Source/_javascript_Core/tests/stress/regexp-matches-array-slow-put.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/regexp-matches-array-slow-put.js 2016-03-06 20:11:09 UTC (rev 197641)
@@ -0,0 +1,15 @@
+(function() {
+ var count = 0;
+ Array.prototype.__defineSetter__("0", function(value) { count += value; });
+
+ for (var i = 0; i < 10000; ++i) {
+ var array = /foo/.exec("foo");
+ if (array[0] != "foo")
+ throw "Error: bad result: " + array[0];
+ delete array[0];
+ array[0] = 42;
+ if (count != (i + 1) * 42)
+ throw "Error: bad count at i = " + i + ": " + count;
+ }
+})();
+