1/* 2 * Copyright (C) 2011, 2013, 2014 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#if ENABLE(DFG_JIT) 30 31#include "DFGCommon.h" 32#include "DFGUseKind.h" 33 34namespace JSC { namespace DFG { 35 36class AdjacencyList; 37 38class Edge { 39public: 40 explicit Edge(Node* node = 0, UseKind useKind = UntypedUse, ProofStatus proofStatus = NeedsCheck, KillStatus killStatus = DoesNotKill) 41#if USE(JSVALUE64) 42 : m_encodedWord(makeWord(node, useKind, proofStatus, killStatus)) 43#else 44 : m_node(node) 45 , m_encodedWord(makeWord(useKind, proofStatus, killStatus)) 46#endif 47 { 48 } 49 50#if USE(JSVALUE64) 51 Node* node() const { return bitwise_cast<Node*>(m_encodedWord >> shift()); } 52#else 53 Node* node() const { return m_node; } 54#endif 55 56 Node& operator*() const { return *node(); } 57 Node* operator->() const { return node(); } 58 59 void setNode(Node* node) 60 { 61#if USE(JSVALUE64) 62 m_encodedWord = makeWord(node, useKind(), proofStatus(), killStatus()); 63#else 64 m_node = node; 65#endif 66 } 67 68 UseKind useKindUnchecked() const 69 { 70#if USE(JSVALUE64) 71 unsigned masked = m_encodedWord & (((1 << shift()) - 1)); 72 unsigned shifted = masked >> 2; 73#else 74 unsigned shifted = static_cast<UseKind>(m_encodedWord) >> 2; 75#endif 76 ASSERT(shifted < static_cast<unsigned>(LastUseKind)); 77 UseKind result = static_cast<UseKind>(shifted); 78 ASSERT(node() || result == UntypedUse); 79 return result; 80 } 81 UseKind useKind() const 82 { 83 ASSERT(node()); 84 return useKindUnchecked(); 85 } 86 void setUseKind(UseKind useKind) 87 { 88 ASSERT(node()); 89#if USE(JSVALUE64) 90 m_encodedWord = makeWord(node(), useKind, proofStatus(), killStatus()); 91#else 92 m_encodedWord = makeWord(useKind, proofStatus(), killStatus()); 93#endif 94 } 95 96 ProofStatus proofStatusUnchecked() const 97 { 98 return proofStatusForIsProved(m_encodedWord & 1); 99 } 100 ProofStatus proofStatus() const 101 { 102 ASSERT(node()); 103 return proofStatusUnchecked(); 104 } 105 void setProofStatus(ProofStatus proofStatus) 106 { 107 ASSERT(node()); 108#if USE(JSVALUE64) 109 m_encodedWord = makeWord(node(), useKind(), proofStatus, killStatus()); 110#else 111 m_encodedWord = makeWord(useKind(), proofStatus, killStatus()); 112#endif 113 } 114 bool isProved() const 115 { 116 return proofStatus() == IsProved; 117 } 118 bool needsCheck() const 119 { 120 return proofStatus() == NeedsCheck; 121 } 122 123 bool willNotHaveCheck() const 124 { 125 return isProved() || shouldNotHaveTypeCheck(useKind()); 126 } 127 bool willHaveCheck() const 128 { 129 return !willNotHaveCheck(); 130 } 131 132 KillStatus killStatusUnchecked() const 133 { 134 return killStatusForDoesKill(m_encodedWord & 2); 135 } 136 KillStatus killStatus() const 137 { 138 ASSERT(node()); 139 return killStatusUnchecked(); 140 } 141 void setKillStatus(KillStatus killStatus) 142 { 143 ASSERT(node()); 144#if USE(JSVALUE64) 145 m_encodedWord = makeWord(node(), useKind(), proofStatus(), killStatus); 146#else 147 m_encodedWord = makeWord(useKind(), proofStatus(), killStatus); 148#endif 149 } 150 bool doesKill() const { return DFG::doesKill(killStatus()); } 151 bool doesNotKill() const { return !doesKill(); } 152 153 bool isSet() const { return !!node(); } 154 155 Edge sanitized() const 156 { 157 Edge result = *this; 158#if USE(JSVALUE64) 159 result.m_encodedWord = makeWord(node(), useKindUnchecked(), NeedsCheck, DoesNotKill); 160#else 161 result.m_encodedWord = makeWord(useKindUnchecked(), NeedsCheck, DoesNotKill); 162#endif 163 return result; 164 } 165 166 typedef void* Edge::*UnspecifiedBoolType; 167 operator UnspecifiedBoolType*() const { return reinterpret_cast<UnspecifiedBoolType*>(isSet()); } 168 169 bool operator!() const { return !isSet(); } 170 171 bool operator==(Edge other) const 172 { 173#if USE(JSVALUE64) 174 return m_encodedWord == other.m_encodedWord; 175#else 176 return m_node == other.m_node && m_encodedWord == other.m_encodedWord; 177#endif 178 } 179 bool operator!=(Edge other) const 180 { 181 return !(*this == other); 182 } 183 184 void dump(PrintStream&) const; 185 186 unsigned hash() const 187 { 188#if USE(JSVALUE64) 189 return IntHash<uintptr_t>::hash(m_encodedWord); 190#else 191 return PtrHash<Node*>::hash(m_node) + m_encodedWord; 192#endif 193 } 194 195private: 196 friend class AdjacencyList; 197 198#if USE(JSVALUE64) 199 static uint32_t shift() { return 7; } 200 201 static uintptr_t makeWord(Node* node, UseKind useKind, ProofStatus proofStatus, KillStatus killStatus) 202 { 203 ASSERT(sizeof(node) == 8); 204 uintptr_t shiftedValue = bitwise_cast<uintptr_t>(node) << shift(); 205 ASSERT((shiftedValue >> shift()) == bitwise_cast<uintptr_t>(node)); 206 ASSERT(useKind >= 0 && useKind < LastUseKind); 207 ASSERT((static_cast<uintptr_t>(LastUseKind) << 2) <= (static_cast<uintptr_t>(2) << shift())); 208 return shiftedValue | (static_cast<uintptr_t>(useKind) << 2) | (DFG::doesKill(killStatus) << 1) | DFG::isProved(proofStatus); 209 } 210 211#else 212 static uintptr_t makeWord(UseKind useKind, ProofStatus proofStatus, KillStatus killStatus) 213 { 214 return (static_cast<uintptr_t>(useKind) << 2) | (DFG::doesKill(killStatus) << 1) | DFG::isProved(proofStatus); 215 } 216 217 Node* m_node; 218#endif 219 // On 64-bit this holds both the pointer and the use kind, while on 32-bit 220 // this just holds the use kind. In both cases this may be hijacked by 221 // AdjacencyList for storing firstChild and numChildren. 222 uintptr_t m_encodedWord; 223}; 224 225inline bool operator==(Edge edge, Node* node) 226{ 227 return edge.node() == node; 228} 229inline bool operator==(Node* node, Edge edge) 230{ 231 return edge.node() == node; 232} 233inline bool operator!=(Edge edge, Node* node) 234{ 235 return edge.node() != node; 236} 237inline bool operator!=(Node* node, Edge edge) 238{ 239 return edge.node() != node; 240} 241 242} } // namespace JSC::DFG 243 244#endif // ENABLE(DFG_JIT) 245 246#endif // DFGEdge_h 247 248