1/*
2 * Copyright (C) 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#pragma once
27
28#if ENABLE(DFG_JIT)
29
30#include "DFGFlushedAt.h"
31#include "DFGVariableAccessData.h"
32
33namespace JSC { namespace DFG {
34
35struct Node;
36
37class Availability {
38public:
39 Availability()
40 : m_node(0)
41 , m_flushedAt(DeadFlush)
42 {
43 }
44
45 explicit Availability(Node* node)
46 : m_node(node)
47 , m_flushedAt(ConflictingFlush)
48 {
49 }
50
51 explicit Availability(FlushedAt flushedAt)
52 : m_node(unavailableMarker())
53 , m_flushedAt(flushedAt)
54 {
55 }
56
57 Availability(Node* node, FlushedAt flushedAt)
58 : m_node(node)
59 , m_flushedAt(flushedAt)
60 {
61 }
62
63 static Availability unavailable()
64 {
65 return Availability(unavailableMarker(), FlushedAt(ConflictingFlush));
66 }
67
68 Availability withFlush(FlushedAt flush) const
69 {
70 return Availability(m_node, flush);
71 }
72
73 Availability withNode(Node* node) const
74 {
75 return Availability(node, m_flushedAt);
76 }
77
78 Availability withUnavailableNode() const
79 {
80 return withNode(unavailableMarker());
81 }
82
83 void setFlush(FlushedAt flushedAt)
84 {
85 m_flushedAt = flushedAt;
86 }
87
88 void setNode(Node* node)
89 {
90 m_node = node;
91 }
92
93 void setNodeUnavailable()
94 {
95 m_node = unavailableMarker();
96 }
97
98 bool nodeIsUndecided() const { return !m_node; }
99 bool nodeIsUnavailable() const { return m_node == unavailableMarker(); }
100
101 bool hasNode() const { return !nodeIsUndecided() && !nodeIsUnavailable(); }
102 bool shouldUseNode() const { return !isFlushUseful() && hasNode(); }
103
104 Node* node() const
105 {
106 ASSERT(!nodeIsUndecided());
107 ASSERT(!nodeIsUnavailable());
108 return m_node;
109 }
110
111 FlushedAt flushedAt() const { return m_flushedAt; }
112 bool isFlushUseful() const
113 {
114 return flushedAt().format() != DeadFlush && flushedAt().format() != ConflictingFlush;
115 }
116
117 bool isDead() const { return !isFlushUseful() && !hasNode(); }
118
119 bool operator!() const { return nodeIsUnavailable() && flushedAt().format() == ConflictingFlush; }
120
121 bool operator==(const Availability& other) const
122 {
123 return m_node == other.m_node
124 && m_flushedAt == other.m_flushedAt;
125 }
126
127 bool operator!=(const Availability& other) const
128 {
129 return !(*this == other);
130 }
131
132 Availability merge(const Availability& other) const
133 {
134 return Availability(
135 mergeNodes(m_node, other.m_node),
136 m_flushedAt.merge(other.m_flushedAt));
137 }
138
139 void dump(PrintStream&) const;
140 void dumpInContext(PrintStream&, DumpContext*) const;
141
142private:
143 static Node* mergeNodes(Node* a, Node* b)
144 {
145 if (!a)
146 return b;
147 if (!b)
148 return a;
149 if (a == b)
150 return a;
151 return unavailableMarker();
152 }
153
154 static Node* unavailableMarker()
155 {
156 return bitwise_cast<Node*>(static_cast<intptr_t>(1));
157 }
158
159 Node* m_node;
160 FlushedAt m_flushedAt;
161};
162
163} } // namespace JSC::DFG
164
165#endif // ENABLE(DFG_JIT)
166