Title: [124398] trunk/Source/_javascript_Core
Revision
124398
Author
fpi...@apple.com
Date
2012-08-01 18:28:10 -0700 (Wed, 01 Aug 2012)

Log Message

DFG should distinguish between PutByVal's that clobber the world and ones that don't
https://bugs.webkit.org/show_bug.cgi?id=92923

Reviewed by Mark Hahnenberg.

This is performance-neutral. I also confirmed that it's neutral if we make the
clobbering variant (PutByValSafe) clobber all knowledge of what is an array,
which should feed nicely into work on removing uses of ClassInfo.

* bytecode/DFGExitProfile.h:
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::getByValLoadElimination):
(JSC::DFG::CSEPhase::checkStructureLoadElimination):
(JSC::DFG::CSEPhase::structureTransitionWatchpointElimination):
(JSC::DFG::CSEPhase::getByOffsetLoadElimination):
(JSC::DFG::CSEPhase::putByOffsetStoreElimination):
(JSC::DFG::CSEPhase::getPropertyStorageLoadElimination):
(JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::byValIsPure):
(JSC::DFG::Graph::clobbersWorld):
* dfg/DFGNodeType.h:
(DFG):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (124397 => 124398)


--- trunk/Source/_javascript_Core/ChangeLog	2012-08-02 01:26:52 UTC (rev 124397)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-08-02 01:28:10 UTC (rev 124398)
@@ -1,3 +1,42 @@
+2012-08-01  Filip Pizlo  <fpi...@apple.com>
+
+        DFG should distinguish between PutByVal's that clobber the world and ones that don't
+        https://bugs.webkit.org/show_bug.cgi?id=92923
+
+        Reviewed by Mark Hahnenberg.
+
+        This is performance-neutral. I also confirmed that it's neutral if we make the
+        clobbering variant (PutByValSafe) clobber all knowledge of what is an array,
+        which should feed nicely into work on removing uses of ClassInfo.
+
+        * bytecode/DFGExitProfile.h:
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::execute):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::getByValLoadElimination):
+        (JSC::DFG::CSEPhase::checkStructureLoadElimination):
+        (JSC::DFG::CSEPhase::structureTransitionWatchpointElimination):
+        (JSC::DFG::CSEPhase::getByOffsetLoadElimination):
+        (JSC::DFG::CSEPhase::putByOffsetStoreElimination):
+        (JSC::DFG::CSEPhase::getPropertyStorageLoadElimination):
+        (JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination):
+        (JSC::DFG::CSEPhase::performNodeCSE):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::byValIsPure):
+        (JSC::DFG::Graph::clobbersWorld):
+        * dfg/DFGNodeType.h:
+        (DFG):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+
 2012-08-01  Jian Li  <jia...@chromium.org>
 
         Add new CSS property "-webkit-widget-region" to expose dashboard region support for other port

Modified: trunk/Source/_javascript_Core/bytecode/DFGExitProfile.h (124397 => 124398)


--- trunk/Source/_javascript_Core/bytecode/DFGExitProfile.h	2012-08-02 01:26:52 UTC (rev 124397)
+++ trunk/Source/_javascript_Core/bytecode/DFGExitProfile.h	2012-08-02 01:28:10 UTC (rev 124398)
@@ -38,6 +38,7 @@
     BadCache, // We exited because an inline cache was wrong.
     Overflow, // We exited because of overflow.
     NegativeZero, // We exited because we encountered negative zero.
+    OutOfBounds, // We had an out-of-bounds access to an array.
     InadequateCoverage, // We exited because we ended up in code that didn't have profiling coverage.
     ArgumentsEscaped, // We exited because arguments escaped but we didn't expect them to.
     Uncountable, // We exited for none of the above reasons, and we should not count it. Most uses of this should be viewed as a FIXME.

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp (124397 => 124398)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2012-08-02 01:26:52 UTC (rev 124397)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2012-08-02 01:28:10 UTC (rev 124398)
@@ -950,7 +950,8 @@
     }
             
     case PutByVal:
-    case PutByValAlias: {
+    case PutByValAlias:
+    case PutByValSafe: {
         node.setCanExit(true);
 
         Edge child1 = m_graph.varArgChild(node, 0);
@@ -966,7 +967,7 @@
             || m_graph[child1].shouldSpeculateArguments()
 #endif
             ) {
-            ASSERT(node.op() == PutByVal);
+            ASSERT(node.op() == PutByVal || node.op() == PutByValSafe);
             clobberWorld(node.codeOrigin, indexInBlock);
             forNode(nodeIndex).makeTop();
             break;
@@ -1055,7 +1056,7 @@
         ASSERT(m_graph[child1].shouldSpeculateArray());
         forNode(child1).filter(SpecArray);
         forNode(child2).filter(SpecInt32);
-        if (node.op() == PutByVal)
+        if (node.op() == PutByValSafe)
             clobberWorld(node.codeOrigin, indexInBlock);
         break;
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (124397 => 124398)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-08-02 01:26:52 UTC (rev 124397)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-08-02 01:28:10 UTC (rev 124398)
@@ -2152,10 +2152,14 @@
             NodeIndex property = get(currentInstruction[2].u.operand);
             NodeIndex value = get(currentInstruction[3].u.operand);
 
+            bool makeSafe =
+                m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex)
+                || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, OutOfBounds);
+            
             addVarArgChild(base);
             addVarArgChild(property);
             addVarArgChild(value);
-            addToGraph(Node::VarArg, PutByVal, OpInfo(0), OpInfo(0));
+            addToGraph(Node::VarArg, makeSafe ? PutByValSafe : PutByVal, OpInfo(0), OpInfo(0));
 
             NEXT_OPCODE(op_put_by_val);
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp (124397 => 124398)


--- trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2012-08-02 01:26:52 UTC (rev 124397)
+++ trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2012-08-02 01:28:10 UTC (rev 124398)
@@ -284,7 +284,8 @@
                     return index;
                 break;
             case PutByVal:
-            case PutByValAlias: {
+            case PutByValAlias:
+            case PutByValSafe: {
                 if (!m_graph.byValIsPure(node))
                     return NoNode;
                 if (m_graph.varArgChild(node, 0) == child1 && canonicalize(m_graph.varArgChild(node, 1)) == canonicalize(child2))
@@ -362,6 +363,7 @@
                 
             case PutByVal:
             case PutByValAlias:
+            case PutByValSafe:
                 if (m_graph.byValIsPure(node)) {
                     // If PutByVal speculates that it's accessing an array with an
                     // integer index, then it's impossible for it to cause a structure
@@ -404,6 +406,7 @@
                 
             case PutByVal:
             case PutByValAlias:
+            case PutByValSafe:
                 if (m_graph.byValIsPure(node)) {
                     // If PutByVal speculates that it's accessing an array with an
                     // integer index, then it's impossible for it to cause a structure
@@ -507,6 +510,7 @@
                 
             case PutByVal:
             case PutByValAlias:
+            case PutByValSafe:
                 if (m_graph.byValIsPure(node)) {
                     // If PutByVal speculates that it's accessing an array with an
                     // integer index, then it's impossible for it to cause a structure
@@ -551,6 +555,7 @@
             case PutByVal:
             case PutByValAlias:
             case GetByVal:
+            case PutByValSafe:
                 if (m_graph.byValIsPure(node)) {
                     // If PutByVal speculates that it's accessing an array with an
                     // integer index, then it's impossible for it to cause a structure
@@ -603,6 +608,7 @@
                 
             case PutByVal:
             case PutByValAlias:
+            case PutByValSafe:
                 if (m_graph.byValIsPure(node)) {
                     // If PutByVal speculates that it's accessing an array with an
                     // integer index, then it's impossible for it to cause a structure
@@ -643,15 +649,6 @@
                 // change the property storage pointer.
                 break;
                 
-            case PutByValAlias:
-                // PutByValAlias can't change the indexed storage pointer
-                break;
-                
-            case PutByVal:
-                if (isFixedIndexedStorageObjectSpeculation(m_graph[m_graph.varArgChild(node, 0)].prediction()) && m_graph.byValIsPure(node))
-                    break;
-                return NoNode;
-
             default:
                 if (m_graph.clobbersWorld(index))
                     return NoNode;
@@ -1093,7 +1090,8 @@
                 setReplacement(getByValLoadElimination(node.child1().index(), node.child2().index()));
             break;
             
-        case PutByVal: {
+        case PutByVal:
+        case PutByValSafe: {
             Edge child1 = m_graph.varArgChild(node, 0);
             Edge child2 = m_graph.varArgChild(node, 1);
             if (isActionableMutableArraySpeculation(m_graph[child1].prediction())

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (124397 => 124398)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2012-08-02 01:26:52 UTC (rev 124397)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2012-08-02 01:28:10 UTC (rev 124398)
@@ -314,7 +314,8 @@
             break;
         }
             
-        case PutByVal: {
+        case PutByVal:
+        case PutByValSafe: {
             Edge child1 = m_graph.varArgChild(node, 0);
             Edge child2 = m_graph.varArgChild(node, 1);
             Edge child3 = m_graph.varArgChild(node, 2);

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (124397 => 124398)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.h	2012-08-02 01:26:52 UTC (rev 124397)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h	2012-08-02 01:28:10 UTC (rev 124398)
@@ -479,6 +479,15 @@
             SpeculatedType prediction = at(varArgChild(node, 0)).prediction();
             if (!isActionableMutableArraySpeculation(prediction))
                 return false;
+            return true;
+        }
+            
+        case PutByValSafe: {
+            if (!at(varArgChild(node, 1)).shouldSpeculateInteger())
+                return false;
+            SpeculatedType prediction = at(varArgChild(node, 0)).prediction();
+            if (!isActionableMutableArraySpeculation(prediction))
+                return false;
             if (isArraySpeculation(prediction))
                 return false;
             return true;
@@ -524,6 +533,7 @@
             return !isPredictedNumerical(node);
         case GetByVal:
         case PutByVal:
+        case PutByValSafe:
         case PutByValAlias:
             return !byValIsPure(node);
         default:

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (124397 => 124398)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2012-08-02 01:26:52 UTC (rev 124397)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2012-08-02 01:28:10 UTC (rev 124398)
@@ -113,6 +113,7 @@
     /* opcodes use VarArgs beause they may have up to 4 children. */\
     macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
     macro(PutByVal, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
+    macro(PutByValSafe, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
     macro(PutByValAlias, NodeMustGenerate | NodeHasVarArgs | NodeMightClobber) \
     macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
     macro(GetByIdFlush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (124397 => 124398)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2012-08-02 01:26:52 UTC (rev 124397)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2012-08-02 01:28:10 UTC (rev 124398)
@@ -637,6 +637,7 @@
         }
         
         case PutByVal:
+        case PutByValSafe:
             changed |= m_graph[m_graph.varArgChild(node, 0)].mergeFlags(NodeUsedAsValue);
             changed |= m_graph[m_graph.varArgChild(node, 1)].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
             changed |= m_graph[m_graph.varArgChild(node, 2)].mergeFlags(NodeUsedAsValue);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (124397 => 124398)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2012-08-02 01:26:52 UTC (rev 124397)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2012-08-02 01:28:10 UTC (rev 124398)
@@ -2483,7 +2483,8 @@
         break;
     }
 
-    case PutByVal: {
+    case PutByVal:
+    case PutByValSafe: {
         Edge child1 = m_jit.graph().varArgChild(node, 0);
         Edge child2 = m_jit.graph().varArgChild(node, 1);
         Edge child3 = m_jit.graph().varArgChild(node, 2);
@@ -2599,12 +2600,14 @@
         if (!isArraySpeculation(m_state.forNode(child1).m_type))
             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), child1, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
 
+        MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
+        if (node.op() == PutByVal)
+            speculationCheck(OutOfBounds, JSValueRegs(), NoNode, beyondArrayBounds);
+
         base.use();
         property.use();
         value.use();
         
-        MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
-
         // Get the array storage.
         GPRReg storageReg = scratchReg;
         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
@@ -2626,12 +2629,14 @@
         m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
         m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
         
-        addSlowPathGenerator(
-            slowPathCall(
-                beyondArrayBounds, this,
-                m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
-                NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg));
-
+        if (node.op() == PutByValSafe) {
+            addSlowPathGenerator(
+                slowPathCall(
+                    beyondArrayBounds, this,
+                    m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
+                    NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg));
+        }
+            
         noResult(m_compileIndex, UseChildrenCalledExplicitly);
         break;
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (124397 => 124398)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2012-08-02 01:26:52 UTC (rev 124397)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2012-08-02 01:28:10 UTC (rev 124398)
@@ -2508,7 +2508,8 @@
         break;
     }
 
-    case PutByVal: {
+    case PutByVal:
+    case PutByValSafe: {
         Edge child1 = m_jit.graph().varArgChild(node, 0);
         Edge child2 = m_jit.graph().varArgChild(node, 1);
         Edge child3 = m_jit.graph().varArgChild(node, 2);
@@ -2675,13 +2676,15 @@
         // If we have predicted the base to be type array, we can skip the check.
         if (!isArraySpeculation(m_state.forNode(child1).m_type))
             speculationCheck(BadType, JSValueRegs(baseReg), child1, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+        
+        MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
+        if (node.op() == PutByVal)
+            speculationCheck(OutOfBounds, JSValueRegs(), NoNode, beyondArrayBounds);
 
         base.use();
         property.use();
         value.use();
         
-        MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
-
         // Get the array storage.
         GPRReg storageReg = scratchReg;
         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
@@ -2702,11 +2705,13 @@
         // Store the value to the array.
         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
 
-        addSlowPathGenerator(
-            slowPathCall(
-                beyondArrayBounds, this,
-                m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
-                NoResult, baseReg, propertyReg, valueReg));
+        if (node.op() == PutByValSafe) {
+            addSlowPathGenerator(
+                slowPathCall(
+                    beyondArrayBounds, this,
+                    m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
+                    NoResult, baseReg, propertyReg, valueReg));
+        }
 
         noResult(m_compileIndex, UseChildrenCalledExplicitly);
         break;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to