Title: [151885] branches/dfgFourthTier
Revision
151885
Author
[email protected]
Date
2013-06-22 21:57:11 -0700 (Sat, 22 Jun 2013)

Log Message

fourthTier: DFG shouldn't exit just because a String GetByVal went out-of-bounds
https://bugs.webkit.org/show_bug.cgi?id=117906

Source/_javascript_Core: 

Reviewed by Mark Hahnenberg.
        
This does the obvious thing, but also makes sure that out-of-bounds accesses
don't fall off into a C call, but try to do the fast thing if the prototype
chain is sane. We ought to probably do this for other array accesses in the
future, as well, since it's so darn easy.

* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::executeEffects):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileGetByValOnString):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::objectPrototypeIsSane):
(JSC):
(JSC::JSGlobalObject::arrayPrototypeChainIsSane):
(JSC::JSGlobalObject::stringPrototypeChainIsSane):
* runtime/JSGlobalObject.h:
(JSGlobalObject):

LayoutTests: 

Reviewed by Mark Hahnenberg.
        
The out-of-bounds benchmark that isn't insane speeds up by 22x in this
patch.

* fast/js/regress/script-tests/string-get-by-val-out-of-bounds-insane.js: Added.
(foo):
* fast/js/regress/script-tests/string-get-by-val-out-of-bounds.js: Added.
(foo):
* fast/js/regress/string-get-by-val-out-of-bounds-expected.txt: Added.
* fast/js/regress/string-get-by-val-out-of-bounds-insane-expected.txt: Added.
* fast/js/regress/string-get-by-val-out-of-bounds-insane.html: Added.
* fast/js/regress/string-get-by-val-out-of-bounds.html: Added.

Modified Paths

Added Paths

Diff

Modified: branches/dfgFourthTier/LayoutTests/ChangeLog (151884 => 151885)


--- branches/dfgFourthTier/LayoutTests/ChangeLog	2013-06-23 03:31:43 UTC (rev 151884)
+++ branches/dfgFourthTier/LayoutTests/ChangeLog	2013-06-23 04:57:11 UTC (rev 151885)
@@ -1,5 +1,24 @@
 2013-06-21  Filip Pizlo  <[email protected]>
 
+        fourthTier: DFG shouldn't exit just because a String GetByVal went out-of-bounds
+        https://bugs.webkit.org/show_bug.cgi?id=117906
+
+        Reviewed by Mark Hahnenberg.
+        
+        The out-of-bounds benchmark that isn't insane speeds up by 22x in this
+        patch.
+
+        * fast/js/regress/script-tests/string-get-by-val-out-of-bounds-insane.js: Added.
+        (foo):
+        * fast/js/regress/script-tests/string-get-by-val-out-of-bounds.js: Added.
+        (foo):
+        * fast/js/regress/string-get-by-val-out-of-bounds-expected.txt: Added.
+        * fast/js/regress/string-get-by-val-out-of-bounds-insane-expected.txt: Added.
+        * fast/js/regress/string-get-by-val-out-of-bounds-insane.html: Added.
+        * fast/js/regress/string-get-by-val-out-of-bounds.html: Added.
+
+2013-06-21  Filip Pizlo  <[email protected]>
+
         fourthTier: DFG should CSE MakeRope
         https://bugs.webkit.org/show_bug.cgi?id=117905
 

Added: branches/dfgFourthTier/LayoutTests/fast/js/regress/script-tests/string-get-by-val-out-of-bounds-insane.js (0 => 151885)


--- branches/dfgFourthTier/LayoutTests/fast/js/regress/script-tests/string-get-by-val-out-of-bounds-insane.js	                        (rev 0)
+++ branches/dfgFourthTier/LayoutTests/fast/js/regress/script-tests/string-get-by-val-out-of-bounds-insane.js	2013-06-23 04:57:11 UTC (rev 151885)
@@ -0,0 +1,14 @@
+function foo(string) {
+    var result = ["", ""];
+    for (var i = 0; i < 100000; ++i)
+        result[i & 1] = string[i & 1];
+    return result;
+}
+
+Object.prototype[1] = 42;
+
+var result = foo("x");
+if (result[0] != "x")
+    throw "Bad result[0]: " + result[0];
+if (result[1] != 42)
+    throw "Bad result[1]: " + result[1];

Added: branches/dfgFourthTier/LayoutTests/fast/js/regress/script-tests/string-get-by-val-out-of-bounds.js (0 => 151885)


--- branches/dfgFourthTier/LayoutTests/fast/js/regress/script-tests/string-get-by-val-out-of-bounds.js	                        (rev 0)
+++ branches/dfgFourthTier/LayoutTests/fast/js/regress/script-tests/string-get-by-val-out-of-bounds.js	2013-06-23 04:57:11 UTC (rev 151885)
@@ -0,0 +1,12 @@
+function foo(string) {
+    var result = ["", ""];
+    for (var i = 0; i < 1000000; ++i)
+        result[i & 1] = string[i & 1];
+    return result;
+}
+
+var result = foo("x");
+if (result[0] != "x")
+    throw "Bad result[0]: " + result[0];
+if (typeof result[1] != "undefined")
+    throw "Bad result[1]: " + result[1];

Added: branches/dfgFourthTier/LayoutTests/fast/js/regress/string-get-by-val-out-of-bounds-expected.txt (0 => 151885)


--- branches/dfgFourthTier/LayoutTests/fast/js/regress/string-get-by-val-out-of-bounds-expected.txt	                        (rev 0)
+++ branches/dfgFourthTier/LayoutTests/fast/js/regress/string-get-by-val-out-of-bounds-expected.txt	2013-06-23 04:57:11 UTC (rev 151885)
@@ -0,0 +1,10 @@
+JSRegress/string-get-by-val-out-of-bounds
+
+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: branches/dfgFourthTier/LayoutTests/fast/js/regress/string-get-by-val-out-of-bounds-insane-expected.txt (0 => 151885)


--- branches/dfgFourthTier/LayoutTests/fast/js/regress/string-get-by-val-out-of-bounds-insane-expected.txt	                        (rev 0)
+++ branches/dfgFourthTier/LayoutTests/fast/js/regress/string-get-by-val-out-of-bounds-insane-expected.txt	2013-06-23 04:57:11 UTC (rev 151885)
@@ -0,0 +1,10 @@
+JSRegress/string-get-by-val-out-of-bounds-insane
+
+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: branches/dfgFourthTier/LayoutTests/fast/js/regress/string-get-by-val-out-of-bounds-insane.html (0 => 151885)


--- branches/dfgFourthTier/LayoutTests/fast/js/regress/string-get-by-val-out-of-bounds-insane.html	                        (rev 0)
+++ branches/dfgFourthTier/LayoutTests/fast/js/regress/string-get-by-val-out-of-bounds-insane.html	2013-06-23 04:57:11 UTC (rev 151885)
@@ -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: branches/dfgFourthTier/LayoutTests/fast/js/regress/string-get-by-val-out-of-bounds.html (0 => 151885)


--- branches/dfgFourthTier/LayoutTests/fast/js/regress/string-get-by-val-out-of-bounds.html	                        (rev 0)
+++ branches/dfgFourthTier/LayoutTests/fast/js/regress/string-get-by-val-out-of-bounds.html	2013-06-23 04:57:11 UTC (rev 151885)
@@ -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>

Modified: branches/dfgFourthTier/Source/_javascript_Core/ChangeLog (151884 => 151885)


--- branches/dfgFourthTier/Source/_javascript_Core/ChangeLog	2013-06-23 03:31:43 UTC (rev 151884)
+++ branches/dfgFourthTier/Source/_javascript_Core/ChangeLog	2013-06-23 04:57:11 UTC (rev 151885)
@@ -1,5 +1,35 @@
 2013-06-22  Filip Pizlo  <[email protected]>
 
+        fourthTier: DFG shouldn't exit just because a String GetByVal went out-of-bounds
+        https://bugs.webkit.org/show_bug.cgi?id=117906
+
+        Reviewed by Mark Hahnenberg.
+        
+        This does the obvious thing, but also makes sure that out-of-bounds accesses
+        don't fall off into a C call, but try to do the fast thing if the prototype
+        chain is sane. We ought to probably do this for other array accesses in the
+        future, as well, since it's so darn easy.
+
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::executeEffects):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileGetByValOnString):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::objectPrototypeIsSane):
+        (JSC):
+        (JSC::JSGlobalObject::arrayPrototypeChainIsSane):
+        (JSC::JSGlobalObject::stringPrototypeChainIsSane):
+        * runtime/JSGlobalObject.h:
+        (JSGlobalObject):
+
+2013-06-22  Filip Pizlo  <[email protected]>
+
         fourthTier: GC's put_by_id transition fixpoint should converge more quickly
         https://bugs.webkit.org/show_bug.cgi?id=117912
 

Modified: branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGAbstractState.cpp (151884 => 151885)


--- branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2013-06-23 03:31:43 UTC (rev 151884)
+++ branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2013-06-23 04:57:11 UTC (rev 151885)
@@ -889,7 +889,19 @@
             forNode(node).makeTop();
             break;
         case Array::String:
-            forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
+            if (node->arrayMode().isOutOfBounds()) {
+                // If the watchpoint was still valid we could totally set this to be
+                // SpecString | SpecOther. Except that we'd have to be careful. If we
+                // tested the watchpoint state here then it could change by the time
+                // we got to the backend. So to do this right, we'd have to get the
+                // fixup phase to check the watchpoint state and then bake into the
+                // GetByVal operation the fact that we're using a watchpoint, using
+                // something like Array::SaneChain (except not quite, because that
+                // implies an in-bounds access). None of this feels like it's worth it,
+                // so we're going with TOP for now.
+                forNode(node).makeTop();
+            } else
+                forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
             break;
         case Array::Arguments:
             forNode(node).makeTop();

Modified: branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (151884 => 151885)


--- branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2013-06-23 03:31:43 UTC (rev 151884)
+++ branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2013-06-23 04:57:11 UTC (rev 151885)
@@ -367,13 +367,25 @@
             blessArrayOperation(node->child1(), node->child2(), node->child3());
             
             ArrayMode arrayMode = node->arrayMode();
-            if (arrayMode.type() == Array::Double
-                && arrayMode.arrayClass() == Array::OriginalArray
-                && arrayMode.speculation() == Array::InBounds
-                && arrayMode.conversion() == Array::AsIs
-                && m_graph.globalObjectFor(node->codeOrigin)->arrayPrototypeChainIsSane()
-                && !(node->flags() & NodeUsedAsOther))
-                node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
+            switch (arrayMode.type()) {
+            case Array::Double:
+                if (arrayMode.arrayClass() == Array::OriginalArray
+                    && arrayMode.speculation() == Array::InBounds
+                    && arrayMode.conversion() == Array::AsIs
+                    && m_graph.globalObjectFor(node->codeOrigin)->arrayPrototypeChainIsSane()
+                    && !(node->flags() & NodeUsedAsOther))
+                    node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
+                break;
+                
+            case Array::String:
+                if ((node->prediction() & ~SpecString)
+                    || m_graph.hasExitSite(node->codeOrigin, OutOfBounds))
+                    node->setArrayMode(arrayMode.withSpeculation(Array::OutOfBounds));
+                break;
+                
+            default:
+                break;
+            }
             
             switch (node->arrayMode().type()) {
             case Array::SelectUsingPredictions:

Modified: branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGOperations.cpp (151884 => 151885)


--- branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGOperations.cpp	2013-06-23 03:31:43 UTC (rev 151884)
+++ branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGOperations.cpp	2013-06-23 04:57:11 UTC (rev 151885)
@@ -471,7 +471,7 @@
     return JSValue::encode(JSValue(base).get(exec, ident));
 }
 
-EncodedJSValue DFG_OPERATION operationGetByValArrayInt(ExecState* exec, JSArray* base, int32_t index)
+ALWAYS_INLINE EncodedJSValue getByValCellInt(ExecState* exec, JSCell* base, int32_t index)
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
@@ -485,6 +485,16 @@
     return JSValue::encode(JSValue(base).get(exec, index));
 }
 
+EncodedJSValue DFG_OPERATION operationGetByValArrayInt(ExecState* exec, JSArray* base, int32_t index)
+{
+    return getByValCellInt(exec, base, index);
+}
+
+EncodedJSValue DFG_OPERATION operationGetByValStringInt(ExecState* exec, JSString* base, int32_t index)
+{
+    return getByValCellInt(exec, base, index);
+}
+
 EncodedJSValue DFG_OPERATION operationGetById(ExecState* exec, EncodedJSValue base, StringImpl* uid)
 {
     VM* vm = &exec->vm();

Modified: branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGOperations.h (151884 => 151885)


--- branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGOperations.h	2013-06-23 03:31:43 UTC (rev 151884)
+++ branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGOperations.h	2013-06-23 04:57:11 UTC (rev 151885)
@@ -69,6 +69,7 @@
 typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJA)(ExecState*, EncodedJSValue, JSArray*);
 typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJI)(ExecState*, EncodedJSValue, StringImpl*);
 typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJssZ)(ExecState*, JSString*, int32_t);
 typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJP)(ExecState*, EncodedJSValue, void*);
 typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EP)(ExecState*, void*);
 typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPP)(ExecState*, void*, void*);
@@ -132,6 +133,7 @@
 EncodedJSValue DFG_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty) WTF_INTERNAL;
 EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty) WTF_INTERNAL;
 EncodedJSValue DFG_OPERATION operationGetByValArrayInt(ExecState*, JSArray*, int32_t) WTF_INTERNAL;
+EncodedJSValue DFG_OPERATION operationGetByValStringInt(ExecState*, JSString*, int32_t) WTF_INTERNAL;
 EncodedJSValue DFG_OPERATION operationGetById(ExecState*, EncodedJSValue, StringImpl*) WTF_INTERNAL;
 EncodedJSValue DFG_OPERATION operationGetByIdBuildList(ExecState*, EncodedJSValue, StringImpl*) WTF_INTERNAL;
 EncodedJSValue DFG_OPERATION operationGetByIdOptimize(ExecState*, EncodedJSValue, StringImpl*) WTF_INTERNAL;

Modified: branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (151884 => 151885)


--- branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2013-06-23 03:31:43 UTC (rev 151884)
+++ branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2013-06-23 04:57:11 UTC (rev 151885)
@@ -2042,14 +2042,39 @@
     GPRReg propertyReg = property.gpr();
     GPRReg storageReg = storage.gpr();
 
+    GPRTemporary scratch(this);
+    GPRReg scratchReg = scratch.gpr();
+#if USE(JSVALUE32_64)
+    GPRTemporary resultTag;
+    GPRReg resultTagReg = InvalidGPRReg;
+    if (node->arrayMode().isOutOfBounds()) {
+        GPRTemporary realResultTag(this);
+        resultTag.adopt(realResultTag);
+        resultTagReg = resultTag.gpr();
+    }
+#endif
+
+    if (node->arrayMode().isOutOfBounds()) {
+        JSGlobalObject* globalObject = m_jit.globalObjectFor(node->codeOrigin);
+        if (globalObject->stringPrototypeChainIsSane()) {
+            m_jit.addLazily(
+                speculationWatchpoint(),
+                globalObject->stringPrototype()->structure()->transitionWatchpointSet());
+            m_jit.addLazily(
+                speculationWatchpoint(),
+                globalObject->objectPrototype()->structure()->transitionWatchpointSet());
+        }
+    }
+
     ASSERT(ArrayMode(Array::String).alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1())));
 
     // unsigned comparison so we can filter out negative indices and indices that are too large
-    speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSString::offsetOfLength())));
+    JITCompiler::Jump outOfBounds = m_jit.branch32(
+        MacroAssembler::AboveOrEqual, propertyReg,
+        MacroAssembler::Address(baseReg, JSString::offsetOfLength()));
+    if (node->arrayMode().isInBounds())
+        speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds);
 
-    GPRTemporary scratch(this);
-    GPRReg scratchReg = scratch.gpr();
-
     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), scratchReg);
 
     // Load the character into scratchReg
@@ -2077,7 +2102,46 @@
         slowPathCall(
             bigCharacter, this, operationSingleCharacterString, scratchReg, scratchReg));
 
-    cellResult(scratchReg, m_currentNode);
+    if (node->arrayMode().isOutOfBounds()) {
+#if USE(JSVALUE32_64)
+        m_jit.move(TrustedImm32(JSValue::CellTag), resultTagReg);
+#endif
+
+        JSGlobalObject* globalObject = m_jit.globalObjectFor(node->codeOrigin);
+        if (globalObject->stringPrototypeChainIsSane()) {
+#if USE(JSVALUE64)
+            addSlowPathGenerator(
+                slowPathMove(
+                    outOfBounds, this, TrustedImm64(JSValue::encode(jsUndefined())),
+                    scratchReg));
+#else
+            addSlowPathGenerator(
+                slowPathMove(
+                    outOfBounds, this,
+                    TrustedImm32(JSValue::UndefinedTag), resultTagReg,
+                    TrustedImm32(0), scratchReg));
+#endif
+        } else {
+#if USE(JSVALUE64)
+            addSlowPathGenerator(
+                slowPathCall(
+                    outOfBounds, this, operationGetByValStringInt,
+                    scratchReg, baseReg, propertyReg));
+#else
+            addSlowPathGenerator(
+                slowPathCall(
+                    outOfBounds, this, operationGetByValStringInt,
+                    resultTagReg, scratchReg, baseReg, propertyReg));
+#endif
+        }
+        
+#if USE(JSVALUE64)
+        jsValueResult(scratchReg, m_currentNode);
+#else
+        jsValueResult(resultTagReg, scratchReg, m_currentNode);
+#endif
+    } else
+        cellResult(scratchReg, m_currentNode);
 }
 
 GeneratedOperandType SpeculativeJIT::checkGeneratedTypeForToInt32(Node* node)

Modified: branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (151884 => 151885)


--- branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2013-06-23 03:31:43 UTC (rev 151884)
+++ branches/dfgFourthTier/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2013-06-23 04:57:11 UTC (rev 151885)
@@ -1155,6 +1155,11 @@
         m_jit.setupArgumentsWithExecState(arg1, arg2);
         return appendCallWithExceptionCheckSetResult(operation, result);
     }
+    JITCompiler::Call callOperation(J_DFGOperation_EJssZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
     JITCompiler::Call callOperation(J_DFGOperation_EPS operation, GPRReg result, void* pointer, size_t size)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer), TrustedImmPtr(size));
@@ -1375,6 +1380,11 @@
         m_jit.setupArgumentsWithExecState(arg1, arg2);
         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
     }
+    JITCompiler::Call callOperation(J_DFGOperation_EJssZ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
     JITCompiler::Call callOperation(J_DFGOperation_EPS operation, GPRReg resultTag, GPRReg resultPayload, void* pointer, size_t size)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer), TrustedImmPtr(size));

Modified: branches/dfgFourthTier/Source/_javascript_Core/runtime/JSGlobalObject.cpp (151884 => 151885)


--- branches/dfgFourthTier/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2013-06-23 03:31:43 UTC (rev 151884)
+++ branches/dfgFourthTier/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2013-06-23 04:57:11 UTC (rev 151885)
@@ -437,14 +437,26 @@
     }
 }
 
+bool JSGlobalObject::objectPrototypeIsSane()
+{
+    return !hasIndexedProperties(m_objectPrototype->structure()->indexingType())
+        && m_objectPrototype->prototype().isNull();
+}
+
 bool JSGlobalObject::arrayPrototypeChainIsSane()
 {
     return !hasIndexedProperties(m_arrayPrototype->structure()->indexingType())
         && m_arrayPrototype->prototype() == m_objectPrototype.get()
-        && !hasIndexedProperties(m_objectPrototype->structure()->indexingType())
-        && m_objectPrototype->prototype().isNull();
+        && objectPrototypeIsSane();
 }
 
+bool JSGlobalObject::stringPrototypeChainIsSane()
+{
+    return !hasIndexedProperties(m_stringPrototype->structure()->indexingType())
+        && m_stringPrototype->prototype() == m_objectPrototype.get()
+        && objectPrototypeIsSane();
+}
+
 void JSGlobalObject::createThrowTypeError(ExecState* exec)
 {
     JSFunction* thrower = JSFunction::create(exec, this, 0, String(), globalFuncThrowTypeError);

Modified: branches/dfgFourthTier/Source/_javascript_Core/runtime/JSGlobalObject.h (151884 => 151885)


--- branches/dfgFourthTier/Source/_javascript_Core/runtime/JSGlobalObject.h	2013-06-23 03:31:43 UTC (rev 151884)
+++ branches/dfgFourthTier/Source/_javascript_Core/runtime/JSGlobalObject.h	2013-06-23 04:57:11 UTC (rev 151885)
@@ -341,7 +341,9 @@
         
     void haveABadTime(VM&);
         
+    bool objectPrototypeIsSane();
     bool arrayPrototypeChainIsSane();
+    bool stringPrototypeChainIsSane();
 
     void setProfileGroup(unsigned value) { createRareDataIfNeeded(); m_rareData->profileGroup = value; }
     unsigned profileGroup() const
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to