]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - dfg/DFGVariableAccessData.h
JavaScriptCore-7600.1.4.9.tar.gz
[apple/javascriptcore.git] / dfg / DFGVariableAccessData.h
index 1d99ed516f486f10d091f8915b768e1ba29b4f4b..cfdd2647ecaa78fff5fe12b43dfab8dbc48efd6f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #ifndef DFGVariableAccessData_h
 #define DFGVariableAccessData_h
 
+#if ENABLE(DFG_JIT)
+
+#include "DFGCommon.h"
 #include "DFGDoubleFormatState.h"
+#include "DFGFlushFormat.h"
+#include "DFGFlushedAt.h"
 #include "DFGNodeFlags.h"
 #include "Operands.h"
-#include "PredictedType.h"
+#include "SpeculatedType.h"
 #include "VirtualRegister.h"
-#include <wtf/Platform.h>
 #include <wtf/UnionFind.h>
 #include <wtf/Vector.h>
 
 namespace JSC { namespace DFG {
 
+struct Node;
+
+enum DoubleBallot { VoteValue, VoteDouble };
+
 class VariableAccessData : public UnionFind<VariableAccessData> {
 public:
-    enum Ballot { VoteValue, VoteDouble };
+    VariableAccessData();
+    VariableAccessData(VirtualRegister local, bool isCaptured);
+    
+    VirtualRegister local()
+    {
+        ASSERT(m_local == find()->m_local);
+        return m_local;
+    }
+    
+    VirtualRegister& machineLocal()
+    {
+        ASSERT(find() == this);
+        return m_machineLocal;
+    }
 
-    VariableAccessData()
-        : m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min()))
-        , m_prediction(PredictNone)
-        , m_argumentAwarePrediction(PredictNone)
-        , m_flags(0)
-        , m_doubleFormatState(EmptyDoubleFormatState)
+    bool mergeIsCaptured(bool isCaptured);
+    
+    bool isCaptured()
     {
-        clearVotes();
+        return m_isCaptured;
     }
     
-    VariableAccessData(VirtualRegister local)
-        : m_local(local)
-        , m_prediction(PredictNone)
-        , m_argumentAwarePrediction(PredictNone)
-        , m_flags(0)
-        , m_doubleFormatState(EmptyDoubleFormatState)
+    bool mergeIsProfitableToUnbox(bool isProfitableToUnbox)
     {
-        clearVotes();
+        return checkAndSet(m_isProfitableToUnbox, m_isProfitableToUnbox | isProfitableToUnbox);
     }
     
-    VirtualRegister local()
+    bool isProfitableToUnbox()
     {
-        ASSERT(m_local == find()->m_local);
-        return m_local;
+        return m_isProfitableToUnbox;
     }
     
-    int operand()
+    bool mergeShouldNeverUnbox(bool shouldNeverUnbox);
+    
+    // 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()
     {
-        return static_cast<int>(local());
+        ASSERT(!(m_isCaptured && !m_shouldNeverUnbox));
+        return m_shouldNeverUnbox;
     }
     
-    bool predict(PredictedType prediction)
+    // 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()
     {
-        VariableAccessData* self = find();
-        bool result = mergePrediction(self->m_prediction, prediction);
-        if (result)
-            mergePrediction(m_argumentAwarePrediction, m_prediction);
-        return result;
+        return !shouldNeverUnbox() && isProfitableToUnbox();
+    }
+
+    bool mergeStructureCheckHoistingFailed(bool failed)
+    {
+        return checkAndSet(m_structureCheckHoistingFailed, m_structureCheckHoistingFailed | failed);
     }
     
-    PredictedType nonUnifiedPrediction()
+    bool mergeCheckArrayHoistingFailed(bool failed)
+    {
+        return checkAndSet(m_checkArrayHoistingFailed, m_checkArrayHoistingFailed | failed);
+    }
+    
+    bool structureCheckHoistingFailed()
+    {
+        return m_structureCheckHoistingFailed;
+    }
+    
+    bool checkArrayHoistingFailed()
+    {
+        return m_checkArrayHoistingFailed;
+    }
+    
+    bool mergeIsArgumentsAlias(bool isArgumentsAlias)
+    {
+        return checkAndSet(m_isArgumentsAlias, m_isArgumentsAlias | isArgumentsAlias);
+    }
+    
+    bool isArgumentsAlias()
+    {
+        return m_isArgumentsAlias;
+    }
+    
+    bool mergeIsLoadedFrom(bool isLoadedFrom)
+    {
+        return checkAndSet(m_isLoadedFrom, m_isLoadedFrom | isLoadedFrom);
+    }
+    
+    void setIsLoadedFrom(bool isLoadedFrom)
+    {
+        m_isLoadedFrom = isLoadedFrom;
+    }
+    
+    bool isLoadedFrom()
+    {
+        return m_isLoadedFrom;
+    }
+    
+    bool predict(SpeculatedType prediction);
+    
+    SpeculatedType nonUnifiedPrediction()
     {
         return m_prediction;
     }
     
-    PredictedType prediction()
+    SpeculatedType prediction()
     {
         return find()->m_prediction;
     }
     
-    PredictedType argumentAwarePrediction()
+    SpeculatedType argumentAwarePrediction()
     {
         return find()->m_argumentAwarePrediction;
     }
     
-    bool mergeArgumentAwarePrediction(PredictedType prediction)
-    {
-        return mergePrediction(find()->m_argumentAwarePrediction, prediction);
-    }
+    bool mergeArgumentAwarePrediction(SpeculatedType prediction);
     
     void clearVotes()
     {
         ASSERT(find() == this);
-        m_votes[VoteValue] = 0;
-        m_votes[VoteDouble] = 0;
+        m_votes[0] = 0;
+        m_votes[1] = 0;
     }
     
-    void vote(Ballot ballot)
+    void vote(unsigned ballot, float weight = 1)
     {
-        ASSERT(static_cast<unsigned>(ballot) < 2);
-        m_votes[ballot]++;
+        ASSERT(ballot < 2);
+        m_votes[ballot] += weight;
     }
     
-    double doubleVoteRatio()
+    double voteRatio()
     {
         ASSERT(find() == this);
-        return static_cast<double>(m_votes[VoteDouble]) / m_votes[VoteValue];
-    }
-    
-    bool shouldUseDoubleFormatAccordingToVote()
-    {
-        // We don't support this facility for arguments, yet.
-        // FIXME: make this work for arguments.
-        if (operandIsArgument(operand()))
-            return false;
-        
-        // If the variable is not a number prediction, then this doesn't
-        // make any sense.
-        if (!isNumberPrediction(prediction()))
-            return false;
-        
-        // If the variable is predicted to hold only doubles, then it's a
-        // no-brainer: it should be formatted as a double.
-        if (isDoublePrediction(prediction()))
-            return true;
-        
-        // If the variable is known to be used as an integer, then be safe -
-        // don't force it to be a double.
-        if (flags() & NodeUsedAsInt)
-            return false;
-        
-        // If the variable has been voted to become a double, then make it a
-        // double.
-        if (doubleVoteRatio() >= Options::doubleVoteRatioForDoubleFormat)
-            return true;
-        
-        return false;
+        return static_cast<double>(m_votes[1]) / m_votes[0];
     }
     
+    bool shouldUseDoubleFormatAccordingToVote();
+    
     DoubleFormatState doubleFormatState()
     {
         return find()->m_doubleFormatState;
@@ -158,70 +191,62 @@ public:
     bool shouldUseDoubleFormat()
     {
         ASSERT(isRoot());
-        return m_doubleFormatState == UsingDoubleFormat;
+        bool doubleState = m_doubleFormatState == UsingDoubleFormat;
+        ASSERT(!(doubleState && shouldNeverUnbox()));
+        ASSERT(!(doubleState && isCaptured()));
+        return doubleState && isProfitableToUnbox();
     }
     
-    bool tallyVotesForShouldUseDoubleFormat()
-    {
-        ASSERT(isRoot());
-        
-        if (m_doubleFormatState == CantUseDoubleFormat)
-            return false;
-        
-        bool newValueOfShouldUseDoubleFormat = shouldUseDoubleFormatAccordingToVote();
-        if (!newValueOfShouldUseDoubleFormat) {
-            // We monotonically convert to double. Hence, if the fixpoint leads us to conclude that we should
-            // switch back to int, we instead ignore this and stick with double.
-            return false;
-        }
-        
-        if (m_doubleFormatState == UsingDoubleFormat)
-            return false;
-        
-        return DFG::mergeDoubleFormatState(m_doubleFormatState, UsingDoubleFormat);
-    }
+    bool tallyVotesForShouldUseDoubleFormat();
     
-    bool mergeDoubleFormatState(DoubleFormatState doubleFormatState)
-    {
-        return DFG::mergeDoubleFormatState(find()->m_doubleFormatState, doubleFormatState);
-    }
+    bool mergeDoubleFormatState(DoubleFormatState);
     
-    bool makePredictionForDoubleFormat()
-    {
-        ASSERT(isRoot());
-        
-        if (m_doubleFormatState != UsingDoubleFormat)
-            return false;
-        
-        return mergePrediction(m_prediction, PredictDouble);
-    }
+    bool makePredictionForDoubleFormat();
     
     NodeFlags flags() const { return m_flags; }
     
     bool mergeFlags(NodeFlags newFlags)
     {
-        newFlags |= m_flags;
-        if (newFlags == m_flags)
-            return false;
-        m_flags = newFlags;
-        return true;
+        return checkAndSet(m_flags, m_flags | newFlags);
     }
     
+    FlushFormat flushFormat();
+    
+    bool couldRepresentInt52();
+    
+    FlushedAt flushedAt()
+    {
+        return FlushedAt(flushFormat(), machineLocal());
+    }
+
 private:
+    bool couldRepresentInt52Impl();
+    
     // This is slightly space-inefficient, since anything we're unified with
     // will have the same operand and should have the same prediction. But
     // putting them here simplifies the code, and we don't expect DFG space
     // usage for variable access nodes do be significant.
 
     VirtualRegister m_local;
-    PredictedType m_prediction;
-    PredictedType m_argumentAwarePrediction;
+    VirtualRegister m_machineLocal;
+    SpeculatedType m_prediction;
+    SpeculatedType m_argumentAwarePrediction;
     NodeFlags m_flags;
-    
-    float m_votes[2];
+
+    bool m_isCaptured;
+    bool m_shouldNeverUnbox;
+    bool m_isArgumentsAlias;
+    bool m_structureCheckHoistingFailed;
+    bool m_checkArrayHoistingFailed;
+    bool m_isProfitableToUnbox;
+    bool m_isLoadedFrom;
+
+    float m_votes[2]; // Used primarily for double voting but may be reused for other purposes.
     DoubleFormatState m_doubleFormatState;
 };
 
 } } // namespace JSC::DFG
 
+#endif // ENABLE(DFG_JIT)
+
 #endif // DFGVariableAccessData_h