]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - dfg/DFGEdge.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGEdge.h
index 7b4b5b8bfa2622c825085f250589eec5253def4c..7a05fabae05e4faf329ecfa86735ebf60c741765 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2013, 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 DFGEdge_h
 #define DFGEdge_h
 
-#include <wtf/Platform.h>
-
 #if ENABLE(DFG_JIT)
 
 #include "DFGCommon.h"
+#include "DFGUseKind.h"
 
 namespace JSC { namespace DFG {
 
@@ -38,88 +37,202 @@ class AdjacencyList;
 
 class Edge {
 public:
-    Edge()
-        : m_encodedWord(makeWord(NoNode, UntypedUse))
+    explicit Edge(Node* node = 0, UseKind useKind = UntypedUse, ProofStatus proofStatus = NeedsCheck, KillStatus killStatus = DoesNotKill)
+#if USE(JSVALUE64)
+        : m_encodedWord(makeWord(node, useKind, proofStatus, killStatus))
+#else
+        : m_node(node)
+        , m_encodedWord(makeWord(useKind, proofStatus, killStatus))
+#endif
     {
     }
     
-    explicit Edge(NodeIndex nodeIndex)
-        : m_encodedWord(makeWord(nodeIndex, UntypedUse))
+#if USE(JSVALUE64)
+    Node* node() const { return bitwise_cast<Node*>(m_encodedWord >> shift()); }
+#else
+    Node* node() const { return m_node; }
+#endif
+
+    Node& operator*() const { return *node(); }
+    Node* operator->() const { return node(); }
+    
+    void setNode(Node* node)
     {
+#if USE(JSVALUE64)
+        m_encodedWord = makeWord(node, useKind(), proofStatus(), killStatus());
+#else
+        m_node = node;
+#endif
     }
     
-    Edge(NodeIndex nodeIndex, UseKind useKind)
-        : m_encodedWord(makeWord(nodeIndex, useKind))
+    UseKind useKindUnchecked() const
+    {
+#if USE(JSVALUE64)
+        unsigned masked = m_encodedWord & (((1 << shift()) - 1));
+        unsigned shifted = masked >> 2;
+#else
+        unsigned shifted = static_cast<UseKind>(m_encodedWord) >> 2;
+#endif
+        ASSERT(shifted < static_cast<unsigned>(LastUseKind));
+        UseKind result = static_cast<UseKind>(shifted);
+        ASSERT(node() || result == UntypedUse);
+        return result;
+    }
+    UseKind useKind() const
+    {
+        ASSERT(node());
+        return useKindUnchecked();
+    }
+    void setUseKind(UseKind useKind)
     {
+        ASSERT(node());
+#if USE(JSVALUE64)
+        m_encodedWord = makeWord(node(), useKind, proofStatus(), killStatus());
+#else
+        m_encodedWord = makeWord(useKind, proofStatus(), killStatus());
+#endif
     }
     
-    NodeIndex indexUnchecked() const { return m_encodedWord >> shift(); }
-    NodeIndex index() const
+    ProofStatus proofStatusUnchecked() const
+    {
+        return proofStatusForIsProved(m_encodedWord & 1);
+    }
+    ProofStatus proofStatus() const
+    {
+        ASSERT(node());
+        return proofStatusUnchecked();
+    }
+    void setProofStatus(ProofStatus proofStatus)
     {
-        ASSERT(isSet());
-        return m_encodedWord >> shift();
+        ASSERT(node());
+#if USE(JSVALUE64)
+        m_encodedWord = makeWord(node(), useKind(), proofStatus, killStatus());
+#else
+        m_encodedWord = makeWord(useKind(), proofStatus, killStatus());
+#endif
     }
-    void setIndex(NodeIndex nodeIndex)
+    bool isProved() const
     {
-        m_encodedWord = makeWord(nodeIndex, useKind());
+        return proofStatus() == IsProved;
     }
     
-    UseKind useKind() const
+    bool willNotHaveCheck() const
     {
-        ASSERT(isSet());
-        unsigned masked = m_encodedWord & (((1 << shift()) - 1));
-        ASSERT(masked < LastUseKind);
-        return static_cast<UseKind>(masked);
+        return isProved() || shouldNotHaveTypeCheck(useKind());
     }
-    void setUseKind(UseKind useKind)
+    bool willHaveCheck() const
+    {
+        return !willNotHaveCheck();
+    }
+    
+    KillStatus killStatusUnchecked() const
+    {
+        return killStatusForDoesKill(m_encodedWord & 2);
+    }
+    KillStatus killStatus() const
+    {
+        ASSERT(node());
+        return killStatusUnchecked();
+    }
+    void setKillStatus(KillStatus killStatus)
+    {
+        ASSERT(node());
+#if USE(JSVALUE64)
+        m_encodedWord = makeWord(node(), useKind(), proofStatus(), killStatus);
+#else
+        m_encodedWord = makeWord(useKind(), proofStatus(), killStatus);
+#endif
+    }
+    bool doesKill() const { return DFG::doesKill(killStatus()); }
+    bool doesNotKill() const { return !doesKill(); }
+    
+    bool isSet() const { return !!node(); }
+
+    Edge sanitized() const
     {
-        ASSERT(isSet());
-        m_encodedWord = makeWord(index(), useKind);
+        Edge result = *this;
+#if USE(JSVALUE64)
+        result.m_encodedWord = makeWord(node(), useKindUnchecked(), NeedsCheck, DoesNotKill);
+#else
+        result.m_encodedWord = makeWord(useKindUnchecked(), NeedsCheck, DoesNotKill);
+#endif
+        return result;
     }
     
-    bool isSet() const { return indexUnchecked() != NoNode; }
+    typedef void* Edge::*UnspecifiedBoolType;
+    operator UnspecifiedBoolType*() const { return reinterpret_cast<UnspecifiedBoolType*>(isSet()); }
+    
     bool operator!() const { return !isSet(); }
     
     bool operator==(Edge other) const
     {
+#if USE(JSVALUE64)
         return m_encodedWord == other.m_encodedWord;
+#else
+        return m_node == other.m_node && m_encodedWord == other.m_encodedWord;
+#endif
     }
     bool operator!=(Edge other) const
     {
-        return m_encodedWord != other.m_encodedWord;
+        return !(*this == other);
+    }
+    
+    void dump(PrintStream&) const;
+    
+    unsigned hash() const
+    {
+#if USE(JSVALUE64)
+        return IntHash<uintptr_t>::hash(m_encodedWord);
+#else
+        return PtrHash<Node*>::hash(m_node) + m_encodedWord;
+#endif
     }
 
 private:
     friend class AdjacencyList;
     
-    static uint32_t shift() { return 4; }
+#if USE(JSVALUE64)
+    static uint32_t shift() { return 7; }
     
-    static int32_t makeWord(NodeIndex nodeIndex, UseKind useKind)
+    static uintptr_t makeWord(Node* node, UseKind useKind, ProofStatus proofStatus, KillStatus killStatus)
     {
-        ASSERT(static_cast<uint32_t>(((static_cast<int32_t>(nodeIndex) << shift()) >> shift())) == nodeIndex);
+        ASSERT(sizeof(node) == 8);
+        uintptr_t shiftedValue = bitwise_cast<uintptr_t>(node) << shift();
+        ASSERT((shiftedValue >> shift()) == bitwise_cast<uintptr_t>(node));
         ASSERT(useKind >= 0 && useKind < LastUseKind);
-        ASSERT(LastUseKind <= (1 << shift()));
-        return (nodeIndex << shift()) | useKind;
+        ASSERT((static_cast<uintptr_t>(LastUseKind) << 2) <= (static_cast<uintptr_t>(2) << shift()));
+        return shiftedValue | (static_cast<uintptr_t>(useKind) << 2) | (DFG::doesKill(killStatus) << 1) | static_cast<uintptr_t>(DFG::isProved(proofStatus));
+    }
+    
+#else
+    static uintptr_t makeWord(UseKind useKind, ProofStatus proofStatus, KillStatus killStatus)
+    {
+        return (static_cast<uintptr_t>(useKind) << 2) | (DFG::doesKill(killStatus) << 1) | static_cast<uintptr_t>(DFG::isProved(proofStatus));
     }
     
-    int32_t m_encodedWord;
+    Node* m_node;
+#endif
+    // On 64-bit this holds both the pointer and the use kind, while on 32-bit
+    // this just holds the use kind. In both cases this may be hijacked by
+    // AdjacencyList for storing firstChild and numChildren.
+    uintptr_t m_encodedWord;
 };
 
-inline bool operator==(Edge nodeUse, NodeIndex nodeIndex)
+inline bool operator==(Edge edge, Node* node)
 {
-    return nodeUse.indexUnchecked() == nodeIndex;
+    return edge.node() == node;
 }
-inline bool operator==(NodeIndex nodeIndex, Edge nodeUse)
+inline bool operator==(Node* node, Edge edge)
 {
-    return nodeUse.indexUnchecked() == nodeIndex;
+    return edge.node() == node;
 }
-inline bool operator!=(Edge nodeUse, NodeIndex nodeIndex)
+inline bool operator!=(Edge edge, Node* node)
 {
-    return nodeUse.indexUnchecked() != nodeIndex;
+    return edge.node() != node;
 }
-inline bool operator!=(NodeIndex nodeIndex, Edge nodeUse)
+inline bool operator!=(Node* node, Edge edge)
 {
-    return nodeUse.indexUnchecked() != nodeIndex;
+    return edge.node() != node;
 }
 
 } } // namespace JSC::DFG