Title: [143955] trunk/Source/_javascript_Core
Revision
143955
Author
[email protected]
Date
2013-02-25 12:23:55 -0800 (Mon, 25 Feb 2013)

Log Message

The DFG special case checks for isCreatedThisArgument are fragile
https://bugs.webkit.org/show_bug.cgi?id=110535

Reviewed by Oliver Hunt.
        
There may be many situations in which we want to force a variable to never be
unboxed. Capturing is one such case, and the created this argument is another.
Previously all code that dealt with this issue had to query both scenarios.
        
Now DFG::VariableAccessData knows these things. You just have to ask
VariableAccessData for whether a variable should be unboxed. Anyone wishing to
force a variable to never be unboxed just tells VariableAccessData.

* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::initialize):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
(DFG):
* dfg/DFGCFGSimplificationPhase.cpp:
(CFGSimplificationPhase):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.h:
(Graph):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::doRoundOfDoubleVoting):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGUnificationPhase.cpp:
(JSC::DFG::UnificationPhase::run):
* dfg/DFGVariableAccessData.h:
(JSC::DFG::VariableAccessData::VariableAccessData):
(JSC::DFG::VariableAccessData::mergeIsCaptured):
(JSC::DFG::VariableAccessData::mergeShouldNeverUnbox):
(VariableAccessData):
(JSC::DFG::VariableAccessData::shouldNeverUnbox):
(JSC::DFG::VariableAccessData::shouldUnboxIfPossible):
(JSC::DFG::VariableAccessData::shouldUseDoubleFormat):
(JSC::DFG::VariableAccessData::tallyVotesForShouldUseDoubleFormat):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (143954 => 143955)


--- trunk/Source/_javascript_Core/ChangeLog	2013-02-25 19:36:14 UTC (rev 143954)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-02-25 20:23:55 UTC (rev 143955)
@@ -1,3 +1,49 @@
+2013-02-22  Filip Pizlo  <[email protected]>
+
+        The DFG special case checks for isCreatedThisArgument are fragile
+        https://bugs.webkit.org/show_bug.cgi?id=110535
+
+        Reviewed by Oliver Hunt.
+        
+        There may be many situations in which we want to force a variable to never be
+        unboxed. Capturing is one such case, and the created this argument is another.
+        Previously all code that dealt with this issue had to query both scenarios.
+        
+        Now DFG::VariableAccessData knows these things. You just have to ask
+        VariableAccessData for whether a variable should be unboxed. Anyone wishing to
+        force a variable to never be unboxed just tells VariableAccessData.
+
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::initialize):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        (DFG):
+        * dfg/DFGCFGSimplificationPhase.cpp:
+        (CFGSimplificationPhase):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGGraph.h:
+        (Graph):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::doRoundOfDoubleVoting):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGUnificationPhase.cpp:
+        (JSC::DFG::UnificationPhase::run):
+        * dfg/DFGVariableAccessData.h:
+        (JSC::DFG::VariableAccessData::VariableAccessData):
+        (JSC::DFG::VariableAccessData::mergeIsCaptured):
+        (JSC::DFG::VariableAccessData::mergeShouldNeverUnbox):
+        (VariableAccessData):
+        (JSC::DFG::VariableAccessData::shouldNeverUnbox):
+        (JSC::DFG::VariableAccessData::shouldUnboxIfPossible):
+        (JSC::DFG::VariableAccessData::shouldUseDoubleFormat):
+        (JSC::DFG::VariableAccessData::tallyVotesForShouldUseDoubleFormat):
+
 2013-02-25  Geoffrey Garen  <[email protected]>
 
         Do one lookup per code cache insertion instead of two

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp (143954 => 143955)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2013-02-25 19:36:14 UTC (rev 143954)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2013-02-25 20:23:55 UTC (rev 143955)
@@ -96,7 +96,7 @@
             continue;
         }
         
-        if (node->variableAccessData()->isCaptured()) {
+        if (!node->variableAccessData()->shouldUnboxIfPossible()) {
             root->valuesAtHead.argument(i).makeTop();
             continue;
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGArgumentPosition.h (143954 => 143955)


--- trunk/Source/_javascript_Core/dfg/DFGArgumentPosition.h	2013-02-25 19:36:14 UTC (rev 143954)
+++ trunk/Source/_javascript_Core/dfg/DFGArgumentPosition.h	2013-02-25 20:23:55 UTC (rev 143955)
@@ -37,6 +37,7 @@
     ArgumentPosition()
         : m_prediction(SpecNone)
         , m_doubleFormatState(EmptyDoubleFormatState)
+        , m_shouldNeverUnbox(false)
     {
     }
     
@@ -45,12 +46,22 @@
         m_variables.append(variable);
     }
     
+    bool mergeShouldNeverUnbox(bool shouldNeverUnbox)
+    {
+        bool newShouldNeverUnbox = m_shouldNeverUnbox | shouldNeverUnbox;
+        if (newShouldNeverUnbox == m_shouldNeverUnbox)
+            return false;
+        m_shouldNeverUnbox = newShouldNeverUnbox;
+        return true;
+    }
+    
     bool mergeArgumentAwareness()
     {
         bool changed = false;
         for (unsigned i = 0; i < m_variables.size(); ++i) {
             changed |= mergeSpeculation(m_prediction, m_variables[i]->argumentAwarePrediction());
             changed |= mergeDoubleFormatState(m_doubleFormatState, m_variables[i]->doubleFormatState());
+            changed |= mergeShouldNeverUnbox(m_variables[i]->shouldNeverUnbox());
         }
         if (!changed)
             return false;
@@ -58,6 +69,7 @@
         for (unsigned i = 0; i < m_variables.size(); ++i) {
             changed |= m_variables[i]->mergeArgumentAwarePrediction(m_prediction);
             changed |= m_variables[i]->mergeDoubleFormatState(m_doubleFormatState);
+            changed |= m_variables[i]->mergeShouldNeverUnbox(m_shouldNeverUnbox);
         }
         return changed;
     }
@@ -72,6 +84,7 @@
 private:
     SpeculatedType m_prediction;
     DoubleFormatState m_doubleFormatState;
+    bool m_shouldNeverUnbox;
     
     Vector<VariableAccessData*, 2> m_variables;
 };

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (143954 => 143955)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2013-02-25 19:36:14 UTC (rev 143954)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2013-02-25 20:23:55 UTC (rev 143955)
@@ -199,10 +199,6 @@
     template<PhiStackType stackType>
     void processPhiStack();
     
-    void fixVariableAccessPredictions();
-    // Add spill locations to nodes.
-    void allocateVirtualRegisters();
-    
     VariableAccessData* newVariableAccessData(int operand, bool isCaptured)
     {
         ASSERT(operand < FirstConstantRegisterIndex);
@@ -372,11 +368,16 @@
         
         bool isCaptured = m_codeBlock->isCaptured(operand);
 
-        // Always flush arguments, except for 'this'.
-        if (argument && setMode == NormalSet)
-            flushDirect(operand);
-        
         VariableAccessData* variableAccessData = newVariableAccessData(operand, isCaptured);
+
+        // Always flush arguments, except for 'this'. If 'this' is created by us,
+        // then make sure that it's never unboxed.
+        if (argument) {
+            if (setMode == NormalSet)
+                flushDirect(operand);
+        } else if (m_codeBlock->specializationKind() == CodeForConstruct)
+            variableAccessData->mergeShouldNeverUnbox(true);
+        
         variableAccessData->mergeStructureCheckHoistingFailed(
             m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
         Node* node = addToGraph(SetLocal, OpInfo(variableAccessData), value);
@@ -1951,6 +1952,7 @@
                 argumentToOperand(argument), m_codeBlock->isCaptured(argumentToOperand(argument)));
             variable->mergeStructureCheckHoistingFailed(
                 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
+            
             Node* setArgument = addToGraph(SetArgument, OpInfo(variable));
             m_graph.m_arguments[argument] = setArgument;
             m_currentBlock->variablesAtTail.setArgumentFirstTime(argument, setArgument);
@@ -3342,16 +3344,6 @@
     }
 }
 
-void ByteCodeParser::fixVariableAccessPredictions()
-{
-    for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
-        VariableAccessData* data = ""
-        data->find()->predict(data->nonUnifiedPrediction());
-        data->find()->mergeIsCaptured(data->isCaptured());
-        data->find()->mergeStructureCheckHoistingFailed(data->structureCheckHoistingFailed());
-    }
-}
-
 void ByteCodeParser::linkBlock(BasicBlock* block, Vector<BlockIndex>& possibleTargets)
 {
     ASSERT(!block->isLinked);

Modified: trunk/Source/_javascript_Core/dfg/DFGCFGSimplificationPhase.cpp (143954 => 143955)


--- trunk/Source/_javascript_Core/dfg/DFGCFGSimplificationPhase.cpp	2013-02-25 19:36:14 UTC (rev 143954)
+++ trunk/Source/_javascript_Core/dfg/DFGCFGSimplificationPhase.cpp	2013-02-25 20:23:55 UTC (rev 143955)
@@ -305,141 +305,6 @@
         }
     }
     
-    void removePotentiallyDeadPhiReference(Node* myNode, Node* phiNode, unsigned edgeIndex, bool changeRef)
-    {
-        if (phiNode->children.child(edgeIndex).node() != myNode)
-            return;
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
-        dataLogF(" Removing reference at child %u.", edgeIndex);
-#endif
-        if (changeRef && phiNode->shouldGenerate())
-            m_graph.deref(myNode);
-        phiNode->children.removeEdgeFromBag(edgeIndex);
-    }
-    
-    struct OperandSubstitution {
-        OperandSubstitution()
-            : oldChild(0)
-            , newChild(0)
-        {
-        }
-        
-        explicit OperandSubstitution(Node* oldChild)
-            : oldChild(oldChild)
-            , newChild(oldChild)
-        {
-        }
-        
-        OperandSubstitution(Node* oldChild, Node* newChild)
-            : oldChild(oldChild)
-            , newChild(newChild)
-        {
-            ASSERT((!oldChild) == (!newChild));
-        }
-        
-        void dump(PrintStream& out) const
-        {
-            if (!oldChild)
-                out.printf("-");
-            else
-                out.printf("@%u -> @%u", oldChild->index(), newChild->index());
-        }
-        
-        Node* oldChild;
-        Node* newChild;
-    };
-    
-    Node* skipGetLocal(Node* node)
-    {
-        if (!node)
-            return 0;
-        if (node->op() == GetLocal)
-            return node->child1().node();
-        return node;
-    }
-    
-    void recordPossibleIncomingReference(
-        BasicBlock* secondBlock, Operands<OperandSubstitution>& substitutions, int operand)
-    {
-        substitutions.operand(operand) = OperandSubstitution(
-            skipGetLocal(secondBlock->variablesAtTail.operand(operand)));
-    }
-    
-    void recordNewTarget(Operands<OperandSubstitution>& substitutions, int operand, Node* node)
-    {
-        ASSERT(
-            node->op() == SetLocal
-            || node->op() == SetArgument
-            || node->op() == Flush
-            || node->op() == Phi);
-        substitutions.operand(operand).newChild = node;
-    }
-    
-    void fixTailOperand(
-        BasicBlock* firstBlock, BasicBlock* secondBlock, int operand,
-        Operands<OperandSubstitution>& substitutions)
-    {
-        Node* atSecondTail = secondBlock->variablesAtTail.operand(operand);
-        
-        if (!atSecondTail) {
-            // If the variable is dead at the end of the second block, then do nothing; essentially
-            // this means that we want the tail state to reflect whatever the first block did.
-            return;
-        }
-
-        switch (atSecondTail->op()) {
-        case SetLocal:
-        case Flush: {
-            // The second block did interesting things to the variables, so update the tail
-            // accordingly.
-            firstBlock->variablesAtTail.operand(operand) = atSecondTail;
-            break;
-        }
-            
-        case Phi: {
-            // Keep what was in the first block.
-            ASSERT(firstBlock->variablesAtTail.operand(operand));
-            recordNewTarget(substitutions, operand, skipGetLocal(firstBlock->variablesAtTail.operand(operand)));
-            break;
-        }
-
-        case GetLocal: {
-            // If it's a GetLocal on a captured var, then definitely keep what was
-            // in the second block. In particular, it's possible that the first
-            // block doesn't even know about this variable.
-            if (atSecondTail->variableAccessData()->isCaptured()) {
-                firstBlock->variablesAtTail.operand(operand) = atSecondTail;
-                recordNewTarget(substitutions, operand, atSecondTail->child1().node());
-                break;
-            }
-            
-            // It's possible that the second block had a GetLocal and the first block
-            // had a SetArgument or a Phi. Then update the tail. Otherwise keep what was in the
-            // first block.
-            Node* atFirstTail = firstBlock->variablesAtTail.operand(operand);
-            ASSERT(atFirstTail);
-            switch (atFirstTail->op()) {
-            case SetArgument:
-            case Phi:
-                firstBlock->variablesAtTail.operand(operand) = atSecondTail;
-                recordNewTarget(substitutions, operand, atSecondTail->child1().node());
-                break;
-
-            default:
-                // Keep what was in the first block, and adjust the substitution to account for
-                // the fact that successors will refer to the child of the GetLocal.
-                ASSERT(firstBlock->variablesAtTail.operand(operand));
-                recordNewTarget(substitutions, operand, skipGetLocal(firstBlock->variablesAtTail.operand(operand)));
-                break;
-            }
-            break;
-        }
-            
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-        }
-    }
-    
     void mergeBlocks(
         BlockIndex firstBlockIndex, BlockIndex secondBlockIndex, BlockIndex jettisonedBlockIndex)
     {

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (143954 => 143955)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2013-02-25 19:36:14 UTC (rev 143954)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2013-02-25 20:23:55 UTC (rev 143955)
@@ -82,8 +82,7 @@
         case SetLocal: {
             VariableAccessData* variable = node->variableAccessData();
             
-            if (variable->isCaptured()
-                || m_graph.isCreatedThisArgument(variable->local()))
+            if (!variable->shouldUnboxIfPossible())
                 break;
             
             if (variable->shouldUseDoubleFormat()) {

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (143954 => 143955)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.h	2013-02-25 19:36:14 UTC (rev 143954)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h	2013-02-25 20:23:55 UTC (rev 143955)
@@ -514,15 +514,6 @@
         return m_codeBlock->usesArguments();
     }
     
-    bool isCreatedThisArgument(int operand)
-    {
-        if (!operandIsArgument(operand))
-            return false;
-        if (operandToArgument(operand))
-            return false;
-        return m_codeBlock->specializationKind() == CodeForConstruct;
-    }
-    
     unsigned numSuccessors(BasicBlock* block)
     {
         return block->last()->numSuccessors();

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (143954 => 143955)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2013-02-25 19:36:14 UTC (rev 143954)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2013-02-25 20:23:55 UTC (rev 143955)
@@ -1022,9 +1022,6 @@
             VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i];
             if (!variableAccessData->isRoot())
                 continue;
-            if (operandIsArgument(variableAccessData->local())
-                || variableAccessData->isCaptured())
-                continue;
             m_changed |= variableAccessData->tallyVotesForShouldUseDoubleFormat();
         }
         for (unsigned i = 0; i < m_graph.m_argumentPositions.size(); ++i)
@@ -1033,9 +1030,6 @@
             VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i];
             if (!variableAccessData->isRoot())
                 continue;
-            if (operandIsArgument(variableAccessData->local())
-                || variableAccessData->isCaptured())
-                continue;
             m_changed |= variableAccessData->makePredictionForDoubleFormat();
         }
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (143954 => 143955)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2013-02-25 19:36:14 UTC (rev 143954)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2013-02-25 20:23:55 UTC (rev 143955)
@@ -1646,7 +1646,7 @@
             valueSource = ValueSource(SourceIsDead);
         else if (node->variableAccessData()->isArgumentsAlias())
             valueSource = ValueSource(ArgumentsSource);
-        else if (node->variableAccessData()->isCaptured())
+        else if (!node->variableAccessData()->shouldUnboxIfPossible())
             valueSource = ValueSource(ValueInJSStack);
         else if (!node->refCount())
             valueSource = ValueSource(SourceIsDead);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (143954 => 143955)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2013-02-25 19:36:14 UTC (rev 143954)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2013-02-25 20:23:55 UTC (rev 143955)
@@ -1936,7 +1936,7 @@
 
     case GetLocal: {
         SpeculatedType prediction = node->variableAccessData()->prediction();
-        AbstractValue& value = block()->valuesAtHead.operand(node->local());
+        AbstractValue& value = m_state.variables().operand(node->local());
 
         // If we have no prediction for this local, then don't attempt to compile.
         if (prediction == SpecNone) {
@@ -1944,61 +1944,59 @@
             break;
         }
         
-        if (!node->variableAccessData()->isCaptured()) {
-            // If the CFA is tracking this variable and it found that the variable
-            // cannot have been assigned, then don't attempt to proceed.
-            if (value.isClear()) {
-                // FIXME: We should trap instead.
-                // https://bugs.webkit.org/show_bug.cgi?id=110383
-                terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
-                break;
-            }
+        // If the CFA is tracking this variable and it found that the variable
+        // cannot have been assigned, then don't attempt to proceed.
+        if (value.isClear()) {
+            // FIXME: We should trap instead.
+            // https://bugs.webkit.org/show_bug.cgi?id=110383
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
+            break;
+        }
+        
+        if (node->variableAccessData()->shouldUseDoubleFormat()) {
+            FPRTemporary result(this);
+            m_jit.loadDouble(JITCompiler::addressFor(node->local()), result.fpr());
+            VirtualRegister virtualRegister = node->virtualRegister();
+            m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
+            m_generationInfo[virtualRegister].initDouble(node, node->refCount(), result.fpr());
+            break;
+        }
+        
+        if (isInt32Speculation(value.m_type)) {
+            GPRTemporary result(this);
+            m_jit.load32(JITCompiler::payloadFor(node->local()), result.gpr());
             
-            if (node->variableAccessData()->shouldUseDoubleFormat()) {
-                FPRTemporary result(this);
-                m_jit.loadDouble(JITCompiler::addressFor(node->local()), result.fpr());
-                VirtualRegister virtualRegister = node->virtualRegister();
-                m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
-                m_generationInfo[virtualRegister].initDouble(node, node->refCount(), result.fpr());
-                break;
-            }
+            // Like integerResult, but don't useChildren - our children are phi nodes,
+            // and don't represent values within this dataflow with virtual registers.
+            VirtualRegister virtualRegister = node->virtualRegister();
+            m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
+            m_generationInfo[virtualRegister].initInteger(node, node->refCount(), result.gpr());
+            break;
+        }
         
-            if (isInt32Speculation(value.m_type)) {
-                GPRTemporary result(this);
-                m_jit.load32(JITCompiler::payloadFor(node->local()), result.gpr());
-
-                // Like integerResult, but don't useChildren - our children are phi nodes,
-                // and don't represent values within this dataflow with virtual registers.
-                VirtualRegister virtualRegister = node->virtualRegister();
-                m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
-                m_generationInfo[virtualRegister].initInteger(node, node->refCount(), result.gpr());
-                break;
-            }
-
-            if (isCellSpeculation(value.m_type)) {
-                GPRTemporary result(this);
-                m_jit.load32(JITCompiler::payloadFor(node->local()), result.gpr());
-
-                // Like cellResult, but don't useChildren - our children are phi nodes,
-                // and don't represent values within this dataflow with virtual registers.
-                VirtualRegister virtualRegister = node->virtualRegister();
-                m_gprs.retain(result.gpr(), virtualRegister, SpillOrderCell);
-                m_generationInfo[virtualRegister].initCell(node, node->refCount(), result.gpr());
-                break;
-            }
-
-            if (isBooleanSpeculation(value.m_type)) {
-                GPRTemporary result(this);
-                m_jit.load32(JITCompiler::payloadFor(node->local()), result.gpr());
-
-                // Like booleanResult, but don't useChildren - our children are phi nodes,
-                // and don't represent values within this dataflow with virtual registers.
-                VirtualRegister virtualRegister = node->virtualRegister();
-                m_gprs.retain(result.gpr(), virtualRegister, SpillOrderBoolean);
-                m_generationInfo[virtualRegister].initBoolean(node, node->refCount(), result.gpr());
-                break;
-            }
+        if (isCellSpeculation(value.m_type)) {
+            GPRTemporary result(this);
+            m_jit.load32(JITCompiler::payloadFor(node->local()), result.gpr());
+            
+            // Like cellResult, but don't useChildren - our children are phi nodes,
+            // and don't represent values within this dataflow with virtual registers.
+            VirtualRegister virtualRegister = node->virtualRegister();
+            m_gprs.retain(result.gpr(), virtualRegister, SpillOrderCell);
+            m_generationInfo[virtualRegister].initCell(node, node->refCount(), result.gpr());
+            break;
         }
+        
+        if (isBooleanSpeculation(value.m_type)) {
+            GPRTemporary result(this);
+            m_jit.load32(JITCompiler::payloadFor(node->local()), result.gpr());
+            
+            // Like booleanResult, but don't useChildren - our children are phi nodes,
+            // and don't represent values within this dataflow with virtual registers.
+            VirtualRegister virtualRegister = node->virtualRegister();
+            m_gprs.retain(result.gpr(), virtualRegister, SpillOrderBoolean);
+            m_generationInfo[virtualRegister].initBoolean(node, node->refCount(), result.gpr());
+            break;
+        }
 
         GPRTemporary result(this);
         GPRTemporary tag(this);
@@ -2011,13 +2009,7 @@
         m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
         m_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS);
 
-        DataFormat format;
-        if (isCellSpeculation(value.m_type)
-            && !node->variableAccessData()->isCaptured())
-            format = DataFormatJSCell;
-        else
-            format = DataFormatJS;
-        m_generationInfo[virtualRegister].initJSValue(node, node->refCount(), tag.gpr(), result.gpr(), format);
+        m_generationInfo[virtualRegister].initJSValue(node, node->refCount(), tag.gpr(), result.gpr(), DataFormatJS);
         break;
     }
         
@@ -2037,7 +2029,7 @@
         // stack.
         compileMovHint(node);
         
-        if (!node->variableAccessData()->isCaptured() && !m_jit.graph().isCreatedThisArgument(node->local())) {
+        if (node->variableAccessData()->shouldUnboxIfPossible()) {
             if (node->variableAccessData()->shouldUseDoubleFormat()) {
                 SpeculateDoubleOperand value(this, node->child1(), ForwardSpeculation);
                 m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->local()));

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (143954 => 143955)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2013-02-25 19:36:14 UTC (rev 143954)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2013-02-25 20:23:55 UTC (rev 143955)
@@ -1902,7 +1902,7 @@
 
     case GetLocal: {
         SpeculatedType prediction = node->variableAccessData()->prediction();
-        AbstractValue& value = block()->valuesAtHead.operand(node->local());
+        AbstractValue& value = m_state.variables().operand(node->local());
 
         // If we have no prediction for this local, then don't attempt to compile.
         if (prediction == SpecNone) {
@@ -1910,36 +1910,34 @@
             break;
         }
         
-        if (!node->variableAccessData()->isCaptured()) {
-            // If the CFA is tracking this variable and it found that the variable
-            // cannot have been assigned, then don't attempt to proceed.
-            if (value.isClear()) {
-                // FIXME: We should trap instead.
-                // https://bugs.webkit.org/show_bug.cgi?id=110383
-                terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
-                break;
-            }
+        // If the CFA is tracking this variable and it found that the variable
+        // cannot have been assigned, then don't attempt to proceed.
+        if (value.isClear()) {
+            // FIXME: We should trap instead.
+            // https://bugs.webkit.org/show_bug.cgi?id=110383
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
+            break;
+        }
+        
+        if (node->variableAccessData()->shouldUseDoubleFormat()) {
+            FPRTemporary result(this);
+            m_jit.loadDouble(JITCompiler::addressFor(node->local()), result.fpr());
+            VirtualRegister virtualRegister = node->virtualRegister();
+            m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
+            m_generationInfo[virtualRegister].initDouble(node, node->refCount(), result.fpr());
+            break;
+        }
+        
+        if (isInt32Speculation(value.m_type)) {
+            GPRTemporary result(this);
+            m_jit.load32(JITCompiler::payloadFor(node->local()), result.gpr());
             
-            if (node->variableAccessData()->shouldUseDoubleFormat()) {
-                FPRTemporary result(this);
-                m_jit.loadDouble(JITCompiler::addressFor(node->local()), result.fpr());
-                VirtualRegister virtualRegister = node->virtualRegister();
-                m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
-                m_generationInfo[virtualRegister].initDouble(node, node->refCount(), result.fpr());
-                break;
-            }
-            
-            if (isInt32Speculation(value.m_type)) {
-                GPRTemporary result(this);
-                m_jit.load32(JITCompiler::payloadFor(node->local()), result.gpr());
-                
-                // Like integerResult, but don't useChildren - our children are phi nodes,
-                // and don't represent values within this dataflow with virtual registers.
-                VirtualRegister virtualRegister = node->virtualRegister();
-                m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
-                m_generationInfo[virtualRegister].initInteger(node, node->refCount(), result.gpr());
-                break;
-            }
+            // Like integerResult, but don't useChildren - our children are phi nodes,
+            // and don't represent values within this dataflow with virtual registers.
+            VirtualRegister virtualRegister = node->virtualRegister();
+            m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
+            m_generationInfo[virtualRegister].initInteger(node, node->refCount(), result.gpr());
+            break;
         }
 
         GPRTemporary result(this);
@@ -1951,9 +1949,7 @@
         m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
 
         DataFormat format;
-        if (node->variableAccessData()->isCaptured())
-            format = DataFormatJS;
-        else if (isCellSpeculation(value.m_type))
+        if (isCellSpeculation(value.m_type))
             format = DataFormatJSCell;
         else if (isBooleanSpeculation(value.m_type))
             format = DataFormatJSBoolean;
@@ -1980,7 +1976,7 @@
         // stack.
         compileMovHint(node);
         
-        if (!node->variableAccessData()->isCaptured() && !m_jit.graph().isCreatedThisArgument(node->local())) {
+        if (node->variableAccessData()->shouldUnboxIfPossible()) {
             if (node->variableAccessData()->shouldUseDoubleFormat()) {
                 SpeculateDoubleOperand value(this, node->child1(), ForwardSpeculation);
                 m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->local()));

Modified: trunk/Source/_javascript_Core/dfg/DFGUnificationPhase.cpp (143954 => 143955)


--- trunk/Source/_javascript_Core/dfg/DFGUnificationPhase.cpp	2013-02-25 19:36:14 UTC (rev 143954)
+++ trunk/Source/_javascript_Core/dfg/DFGUnificationPhase.cpp	2013-02-25 20:23:55 UTC (rev 143955)
@@ -72,6 +72,7 @@
             data->find()->predict(data->nonUnifiedPrediction());
             data->find()->mergeIsCaptured(data->isCaptured());
             data->find()->mergeStructureCheckHoistingFailed(data->structureCheckHoistingFailed());
+            data->find()->mergeShouldNeverUnbox(data->shouldNeverUnbox());
         }
         
         m_graph.m_unificationState = GloballyUnified;

Modified: trunk/Source/_javascript_Core/dfg/DFGVariableAccessData.h (143954 => 143955)


--- trunk/Source/_javascript_Core/dfg/DFGVariableAccessData.h	2013-02-25 19:36:14 UTC (rev 143954)
+++ trunk/Source/_javascript_Core/dfg/DFGVariableAccessData.h	2013-02-25 20:23:55 UTC (rev 143955)
@@ -46,10 +46,11 @@
         , m_prediction(SpecNone)
         , m_argumentAwarePrediction(SpecNone)
         , m_flags(0)
-        , m_doubleFormatState(EmptyDoubleFormatState)
         , m_isCaptured(false)
+        , m_shouldNeverUnbox(false)
         , m_isArgumentsAlias(false)
         , m_structureCheckHoistingFailed(false)
+        , m_doubleFormatState(EmptyDoubleFormatState)
     {
         clearVotes();
     }
@@ -59,10 +60,11 @@
         , m_prediction(SpecNone)
         , m_argumentAwarePrediction(SpecNone)
         , m_flags(0)
-        , m_doubleFormatState(EmptyDoubleFormatState)
         , m_isCaptured(isCaptured)
+        , m_shouldNeverUnbox(isCaptured)
         , m_isArgumentsAlias(false)
         , m_structureCheckHoistingFailed(false)
+        , m_doubleFormatState(EmptyDoubleFormatState)
     {
         clearVotes();
     }
@@ -80,6 +82,7 @@
     
     bool mergeIsCaptured(bool isCaptured)
     {
+        m_shouldNeverUnbox |= isCaptured;
         bool newIsCaptured = m_isCaptured | isCaptured;
         if (newIsCaptured == m_isCaptured)
             return false;
@@ -92,6 +95,32 @@
         return m_isCaptured;
     }
     
+    bool mergeShouldNeverUnbox(bool shouldNeverUnbox)
+    {
+        bool newShouldNeverUnbox = m_shouldNeverUnbox | shouldNeverUnbox;
+        if (newShouldNeverUnbox == m_shouldNeverUnbox)
+            return false;
+        m_shouldNeverUnbox = newShouldNeverUnbox;
+        return true;
+    }
+    
+    // Returns true if it would be unsound to store the value in an unboxed fashion.
+    // If this returns false, it simply means that it is sound to unbox; it doesn't
+    // mean that we have actually done so.
+    bool shouldNeverUnbox()
+    {
+        ASSERT(!(m_isCaptured && !m_shouldNeverUnbox));
+        return m_shouldNeverUnbox;
+    }
+    
+    // Returns true if we should be unboxing the value provided that the predictions
+    // and double format vote say so. This may return false even if shouldNeverUnbox()
+    // returns false, since this incorporates heuristics of profitability.
+    bool shouldUnboxIfPossible()
+    {
+        return !shouldNeverUnbox();
+    }
+    
     bool mergeStructureCheckHoistingFailed(bool failed)
     {
         bool newFailed = m_structureCheckHoistingFailed | failed;
@@ -210,13 +239,19 @@
     bool shouldUseDoubleFormat()
     {
         ASSERT(isRoot());
-        return m_doubleFormatState == UsingDoubleFormat;
+        bool result = m_doubleFormatState == UsingDoubleFormat;
+        ASSERT(!(result && shouldNeverUnbox()));
+        ASSERT(!(result && isCaptured()));
+        return result;
     }
     
     bool tallyVotesForShouldUseDoubleFormat()
     {
         ASSERT(isRoot());
         
+        if (operandIsArgument(local()) || shouldNeverUnbox())
+            return DFG::mergeDoubleFormatState(m_doubleFormatState, NotUsingDoubleFormat);
+        
         if (m_doubleFormatState == CantUseDoubleFormat)
             return false;
         
@@ -270,12 +305,13 @@
     SpeculatedType m_argumentAwarePrediction;
     NodeFlags m_flags;
     
-    float m_votes[2]; // Used primarily for double voting but may be reused for other purposes.
-    DoubleFormatState m_doubleFormatState;
-    
     bool m_isCaptured;
+    bool m_shouldNeverUnbox;
     bool m_isArgumentsAlias;
     bool m_structureCheckHoistingFailed;
+
+    float m_votes[2]; // Used primarily for double voting but may be reused for other purposes.
+    DoubleFormatState m_doubleFormatState;
 };
 
 } } // namespace JSC::DFG

Modified: trunk/Source/_javascript_Core/dfg/DFGVariableAccessDataDump.cpp (143954 => 143955)


--- trunk/Source/_javascript_Core/dfg/DFGVariableAccessDataDump.cpp	2013-02-25 19:36:14 UTC (rev 143954)
+++ trunk/Source/_javascript_Core/dfg/DFGVariableAccessDataDump.cpp	2013-02-25 20:23:55 UTC (rev 143955)
@@ -63,6 +63,10 @@
     
     if (m_data->isCaptured())
         out.print("*");
+    else if (m_data->shouldNeverUnbox())
+        out.print("!");
+    else if (!m_data->shouldUnboxIfPossible())
+        out.print("~");
 
     out.print(AbbreviatedSpeculationDump(m_data->prediction()));
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to