Title: [197641] trunk
Revision
197641
Author
fpi...@apple.com
Date
2016-03-06 12:11:09 -0800 (Sun, 06 Mar 2016)

Log Message

RegExpMatchesArray doesn't know how to have a bad time
https://bugs.webkit.org/show_bug.cgi?id=155069

Reviewed by Yusuke Suzuki.

Source/_javascript_Core:

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.

LayoutTests:

* js/regress/regexp-exec-expected.txt: Added.
* js/regress/regexp-exec.html: Added.
* js/regress/script-tests/regexp-exec.js: Added.

Modified Paths

Added Paths

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;
+    }
+})();
+ 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to