1/* 2 * Copyright (C) 2011, 2013 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#ifndef DFGEdge_h 27#define DFGEdge_h 28 29#include <wtf/Platform.h> 30 31#if ENABLE(DFG_JIT) 32 33#include "DFGCommon.h" 34#include "DFGUseKind.h" 35 36namespace JSC { namespace DFG { 37 38class AdjacencyList; 39 40class Edge { 41public: 42 explicit Edge(Node* node = 0, UseKind useKind = UntypedUse, ProofStatus proofStatus = NeedsCheck) 43#if USE(JSVALUE64) 44 : m_encodedWord(makeWord(node, useKind, proofStatus)) 45#else 46 : m_node(node) 47 , m_encodedWord(makeWord(useKind, proofStatus)) 48#endif 49 { 50 } 51 52#if USE(JSVALUE64) 53 Node* node() const { return bitwise_cast<Node*>(m_encodedWord >> shift()); } 54#else 55 Node* node() const { return m_node; } 56#endif 57 58 Node& operator*() const { return *node(); } 59 Node* operator->() const { return node(); } 60 61 void setNode(Node* node) 62 { 63#if USE(JSVALUE64) 64 m_encodedWord = makeWord(node, useKind(), proofStatus()); 65#else 66 m_node = node; 67#endif 68 } 69 70 UseKind useKindUnchecked() const 71 { 72#if USE(JSVALUE64) 73 unsigned masked = m_encodedWord & (((1 << shift()) - 1)); 74 unsigned shifted = masked >> 1; 75#else 76 unsigned shifted = static_cast<UseKind>(m_encodedWord) >> 1; 77#endif 78 ASSERT(shifted < static_cast<unsigned>(LastUseKind)); 79 UseKind result = static_cast<UseKind>(shifted); 80 ASSERT(node() || result == UntypedUse); 81 return result; 82 } 83 UseKind useKind() const 84 { 85 ASSERT(node()); 86 return useKindUnchecked(); 87 } 88 void setUseKind(UseKind useKind) 89 { 90 ASSERT(node()); 91#if USE(JSVALUE64) 92 m_encodedWord = makeWord(node(), useKind, proofStatus()); 93#else 94 m_encodedWord = makeWord(useKind, proofStatus()); 95#endif 96 } 97 98 ProofStatus proofStatusUnchecked() const 99 { 100 return proofStatusForIsProved(m_encodedWord & 1); 101 } 102 ProofStatus proofStatus() const 103 { 104 ASSERT(node()); 105 return proofStatusUnchecked(); 106 } 107 void setProofStatus(ProofStatus proofStatus) 108 { 109 ASSERT(node()); 110#if USE(JSVALUE64) 111 m_encodedWord = makeWord(node(), useKind(), proofStatus); 112#else 113 m_encodedWord = makeWord(useKind(), proofStatus); 114#endif 115 } 116 bool isProved() const 117 { 118 return proofStatus() == IsProved; 119 } 120 bool needsCheck() const 121 { 122 return proofStatus() == NeedsCheck; 123 } 124 125 bool isSet() const { return !!node(); } 126 127 typedef void* Edge::*UnspecifiedBoolType; 128 operator UnspecifiedBoolType*() const { return reinterpret_cast<UnspecifiedBoolType*>(isSet()); } 129 130 bool operator!() const { return !isSet(); } 131 132 bool operator==(Edge other) const 133 { 134#if USE(JSVALUE64) 135 return m_encodedWord == other.m_encodedWord; 136#else 137 return m_node == other.m_node && m_encodedWord == other.m_encodedWord; 138#endif 139 } 140 bool operator!=(Edge other) const 141 { 142 return !(*this == other); 143 } 144 145 void dump(PrintStream&) const; 146 147private: 148 friend class AdjacencyList; 149 150#if USE(JSVALUE64) 151 static uint32_t shift() { return 6; } 152 153 static uintptr_t makeWord(Node* node, UseKind useKind, ProofStatus proofStatus) 154 { 155 ASSERT(sizeof(node) == 8); 156 uintptr_t shiftedValue = bitwise_cast<uintptr_t>(node) << shift(); 157 ASSERT((shiftedValue >> shift()) == bitwise_cast<uintptr_t>(node)); 158 ASSERT(useKind >= 0 && useKind < LastUseKind); 159 ASSERT((static_cast<uintptr_t>(LastUseKind) << 1) <= (static_cast<uintptr_t>(1) << shift())); 160 return shiftedValue | (static_cast<uintptr_t>(useKind) << 1) | DFG::isProved(proofStatus); 161 } 162 163#else 164 static uintptr_t makeWord(UseKind useKind, ProofStatus proofStatus) 165 { 166 return (static_cast<uintptr_t>(useKind) << 1) | DFG::isProved(proofStatus); 167 } 168 169 Node* m_node; 170#endif 171 // On 64-bit this holds both the pointer and the use kind, while on 32-bit 172 // this just holds the use kind. In both cases this may be hijacked by 173 // AdjacencyList for storing firstChild and numChildren. 174 uintptr_t m_encodedWord; 175}; 176 177inline bool operator==(Edge edge, Node* node) 178{ 179 return edge.node() == node; 180} 181inline bool operator==(Node* node, Edge edge) 182{ 183 return edge.node() == node; 184} 185inline bool operator!=(Edge edge, Node* node) 186{ 187 return edge.node() != node; 188} 189inline bool operator!=(Node* node, Edge edge) 190{ 191 return edge.node() != node; 192} 193 194} } // namespace JSC::DFG 195 196#endif // ENABLE(DFG_JIT) 197 198#endif // DFGEdge_h 199 200