2 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef DFGAbstractHeap_h
27 #define DFGAbstractHeap_h
31 #include "VirtualRegister.h"
32 #include <wtf/HashMap.h>
33 #include <wtf/PrintStream.h>
35 namespace JSC
{ namespace DFG
{
37 // Implements a three-level type hierarchy:
38 // - World is the supertype of all of the things.
39 // - Kind with TOP payload is the direct subtype of World.
40 // - Kind with non-TOP payload is the direct subtype of its corresponding TOP Kind.
42 #define FOR_EACH_ABSTRACT_HEAP_KIND(macro) \
43 macro(InvalidAbstractHeap) \
45 macro(Arguments_numArguments) \
46 macro(Arguments_overrideLength) \
47 macro(Arguments_registers) \
48 macro(Arguments_slowArguments) \
49 macro(ArrayBuffer_data) \
50 macro(Butterfly_arrayBuffer) \
51 macro(Butterfly_publicLength) \
52 macro(Butterfly_vectorLength) \
53 macro(JSArrayBufferView_length) \
54 macro(JSArrayBufferView_mode) \
55 macro(JSArrayBufferView_vector) \
56 macro(JSCell_structureID) \
57 macro(JSCell_indexingType) \
58 macro(JSCell_typeInfoFlags) \
59 macro(JSCell_typeInfoType) \
60 macro(JSFunction_executable) \
61 macro(JSFunction_scopeChain) \
62 macro(JSObject_butterfly) \
63 macro(JSVariableObject_registers) \
64 macro(NamedProperties) \
65 macro(IndexedInt32Properties) \
66 macro(IndexedDoubleProperties) \
67 macro(IndexedContiguousProperties) \
68 macro(ArrayStorageProperties) \
70 macro(TypedArrayProperties) \
74 macro(InternalState) \
76 /* Use this for writes only, to indicate that this may fire watchpoints. Usually this is never directly written but instead we test to see if a node clobbers this; it just so happens that you have to write world to clobber it. */\
77 macro(Watchpoint_fire) \
78 /* Use this for reads only, just to indicate that if the world got clobbered, then this operation will not work. */\
80 /* Use this for writes only, just to indicate that hoisting the node is invalid. This works because we don't hoist anything that has any side effects at all. */\
83 enum AbstractHeapKind
{
84 #define ABSTRACT_HEAP_DECLARATION(name) name,
85 FOR_EACH_ABSTRACT_HEAP_KIND(ABSTRACT_HEAP_DECLARATION
)
86 #undef ABSTRACT_HEAP_DECLARATION
99 Payload(bool isTop
, int64_t value
)
103 ASSERT(!(isTop
&& value
));
106 Payload(int64_t value
)
112 Payload(const void* pointer
)
114 , m_value(bitwise_cast
<intptr_t>(pointer
))
118 Payload(VirtualRegister operand
)
120 , m_value(operand
.offset())
124 static Payload
top() { return Payload(true, 0); }
126 bool isTop() const { return m_isTop
; }
127 int64_t value() const
132 int64_t valueImpl() const
137 bool operator==(const Payload
& other
) const
139 return m_isTop
== other
.m_isTop
140 && m_value
== other
.m_value
;
143 bool operator!=(const Payload
& other
) const
145 return !(*this == other
);
148 bool operator<(const Payload
& other
) const
151 return !other
.isTop();
154 return value() < other
.value();
157 bool isDisjoint(const Payload
& other
) const
163 return m_value
!= other
.m_value
;
166 bool overlaps(const Payload
& other
) const
168 return !isDisjoint(other
);
171 void dump(PrintStream
&) const;
180 m_value
= encode(InvalidAbstractHeap
, Payload());
183 AbstractHeap(AbstractHeapKind kind
)
185 ASSERT(kind
!= InvalidAbstractHeap
);
186 m_value
= encode(kind
, Payload::top());
189 AbstractHeap(AbstractHeapKind kind
, Payload payload
)
191 ASSERT(kind
!= InvalidAbstractHeap
&& kind
!= World
);
192 m_value
= encode(kind
, payload
);
195 AbstractHeap(WTF::HashTableDeletedValueType
)
197 m_value
= encode(InvalidAbstractHeap
, Payload::top());
200 bool operator!() const { return kind() == InvalidAbstractHeap
&& !payloadImpl().isTop(); }
202 AbstractHeapKind
kind() const { return static_cast<AbstractHeapKind
>(m_value
& ((1 << topShift
) - 1)); }
203 Payload
payload() const
205 ASSERT(kind() != World
&& kind() != InvalidAbstractHeap
);
206 return payloadImpl();
209 bool isDisjoint(const AbstractHeap
& other
)
211 ASSERT(kind() != InvalidAbstractHeap
);
212 ASSERT(other
.kind() != InvalidAbstractHeap
);
215 if (other
.kind() == World
)
217 if (kind() != other
.kind())
219 return payload().isDisjoint(other
.payload());
222 bool overlaps(const AbstractHeap
& other
)
224 return !isDisjoint(other
);
227 AbstractHeap
supertype() const
229 ASSERT(kind() != InvalidAbstractHeap
);
231 return AbstractHeap();
232 if (payload().isTop())
234 return AbstractHeap(kind());
237 unsigned hash() const
239 return WTF::IntHash
<int64_t>::hash(m_value
);
242 bool operator==(const AbstractHeap
& other
) const
244 return m_value
== other
.m_value
;
247 bool operator!=(const AbstractHeap
& other
) const
249 return !(*this == other
);
252 bool operator<(const AbstractHeap
& other
) const
254 if (kind() != other
.kind())
255 return kind() < other
.kind();
256 return payload() < other
.payload();
259 bool isHashTableDeletedValue() const
261 return kind() == InvalidAbstractHeap
&& payloadImpl().isTop();
264 void dump(PrintStream
& out
) const;
267 static const unsigned valueShift
= 15;
268 static const unsigned topShift
= 14;
270 Payload
payloadImpl() const
272 return Payload((m_value
>> topShift
) & 1, m_value
>> valueShift
);
275 static int64_t encode(AbstractHeapKind kind
, Payload payload
)
277 int64_t kindAsInt
= static_cast<int64_t>(kind
);
278 ASSERT(kindAsInt
< (1 << topShift
));
279 return kindAsInt
| (payload
.isTop() << topShift
) | (payload
.valueImpl() << valueShift
);
282 // The layout of the value is:
283 // Low 14 bits: the Kind
284 // 15th bit: whether or not the payload is TOP.
285 // The upper bits: the payload.value().
289 struct AbstractHeapHash
{
290 static unsigned hash(const AbstractHeap
& key
) { return key
.hash(); }
291 static bool equal(const AbstractHeap
& a
, const AbstractHeap
& b
) { return a
== b
; }
292 static const bool safeToCompareToEmptyOrDeleted
= true;
295 } } // namespace JSC::DFG
299 void printInternal(PrintStream
&, JSC::DFG::AbstractHeapKind
);
301 template<typename T
> struct DefaultHash
;
302 template<> struct DefaultHash
<JSC::DFG::AbstractHeap
> {
303 typedef JSC::DFG::AbstractHeapHash Hash
;
306 template<typename T
> struct HashTraits
;
307 template<> struct HashTraits
<JSC::DFG::AbstractHeap
> : SimpleClassHashTraits
<JSC::DFG::AbstractHeap
> { };
311 #endif // ENABLE(DFG_JIT)
313 #endif // DFGAbstractHeap_h