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