1/*
2 * Copyright (C) 2014-2019 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 "DFGAbstractHeap.h"
31#include "DFGLazyNode.h"
32#include "DFGNode.h"
33
34namespace JSC { namespace DFG {
35
36enum LocationKind {
37 InvalidLocationKind,
38
39 ArrayLengthLoc,
40 ArrayMaskLoc,
41 VectorLengthLoc,
42 ButterflyLoc,
43 CheckTypeInfoFlagsLoc,
44 OverridesHasInstanceLoc,
45 ClosureVariableLoc,
46 DirectArgumentsLoc,
47 GetterLoc,
48 GlobalVariableLoc,
49 HasIndexedPropertyLoc,
50 IndexedPropertyDoubleLoc,
51 IndexedPropertyDoubleSaneChainLoc,
52 IndexedPropertyInt32Loc,
53 IndexedPropertyInt52Loc,
54 IndexedPropertyJSLoc,
55 IndexedPropertyStorageLoc,
56 InvalidationPointLoc,
57 IsFunctionLoc,
58 IsObjectOrNullLoc,
59 NamedPropertyLoc,
60 RegExpObjectLastIndexLoc,
61 SetterLoc,
62 StructureLoc,
63 TypedArrayByteOffsetLoc,
64 PrototypeLoc,
65 StackLoc,
66 StackPayloadLoc,
67 DateFieldLoc,
68 MapBucketLoc,
69 MapBucketHeadLoc,
70 MapBucketValueLoc,
71 MapBucketKeyLoc,
72 MapBucketNextLoc,
73 WeakMapGetLoc,
74 PromiseInternalFieldLoc,
75 DOMStateLoc,
76};
77
78class HeapLocation {
79public:
80 HeapLocation(
81 LocationKind kind = InvalidLocationKind,
82 AbstractHeap heap = AbstractHeap(),
83 Node* base = nullptr, LazyNode index = LazyNode(), Node* descriptor = nullptr)
84 : m_kind(kind)
85 , m_heap(heap)
86 , m_base(base)
87 , m_index(index)
88 , m_descriptor(descriptor)
89 {
90 ASSERT((kind == InvalidLocationKind) == !heap);
91 ASSERT(!!m_heap || !m_base);
92 ASSERT(m_base || (!m_index && !m_descriptor));
93 }
94
95 HeapLocation(LocationKind kind, AbstractHeap heap, Node* base, Node* index, Node* descriptor = nullptr)
96 : HeapLocation(kind, heap, base, LazyNode(index), descriptor)
97 {
98 }
99
100 HeapLocation(LocationKind kind, AbstractHeap heap, Edge base, Edge index = Edge(), Edge descriptor = Edge())
101 : HeapLocation(kind, heap, base.node(), index.node(), descriptor.node())
102 {
103 }
104
105 HeapLocation(WTF::HashTableDeletedValueType)
106 : m_kind(InvalidLocationKind)
107 , m_heap(WTF::HashTableDeletedValue)
108 , m_base(nullptr)
109 , m_index(nullptr)
110 , m_descriptor(nullptr)
111 {
112 }
113
114 bool operator!() const { return !m_heap; }
115
116 LocationKind kind() const { return m_kind; }
117 AbstractHeap heap() const { return m_heap; }
118 Node* base() const { return m_base; }
119 LazyNode index() const { return m_index; }
120
121 unsigned hash() const
122 {
123 return m_kind + m_heap.hash() + m_index.hash() + static_cast<unsigned>(bitwise_cast<uintptr_t>(m_base)) + static_cast<unsigned>(bitwise_cast<uintptr_t>(m_descriptor));
124 }
125
126 bool operator==(const HeapLocation& other) const
127 {
128 return m_kind == other.m_kind
129 && m_heap == other.m_heap
130 && m_base == other.m_base
131 && m_index == other.m_index
132 && m_descriptor == other.m_descriptor;
133 }
134
135 bool isHashTableDeletedValue() const
136 {
137 return m_heap.isHashTableDeletedValue();
138 }
139
140 void dump(PrintStream& out) const;
141
142private:
143 LocationKind m_kind;
144 AbstractHeap m_heap;
145 Node* m_base;
146 LazyNode m_index;
147 Node* m_descriptor;
148};
149
150struct HeapLocationHash {
151 static unsigned hash(const HeapLocation& key) { return key.hash(); }
152 static bool equal(const HeapLocation& a, const HeapLocation& b) { return a == b; }
153 static constexpr bool safeToCompareToEmptyOrDeleted = true;
154};
155
156LocationKind indexedPropertyLocForResultType(NodeFlags);
157
158inline LocationKind indexedPropertyLocForResultType(NodeFlags canonicalResultRepresentation)
159{
160 if (!canonicalResultRepresentation)
161 return IndexedPropertyJSLoc;
162
163 ASSERT((canonicalResultRepresentation & NodeResultMask) == canonicalResultRepresentation);
164 switch (canonicalResultRepresentation) {
165 case NodeResultDouble:
166 return IndexedPropertyDoubleLoc;
167 case NodeResultInt52:
168 return IndexedPropertyInt52Loc;
169 case NodeResultInt32:
170 return IndexedPropertyInt32Loc;
171 case NodeResultJS:
172 return IndexedPropertyJSLoc;
173 case NodeResultStorage:
174 RELEASE_ASSERT_NOT_REACHED();
175 default:
176 break;
177 }
178 RELEASE_ASSERT_NOT_REACHED();
179}
180
181} } // namespace JSC::DFG
182
183namespace WTF {
184
185void printInternal(PrintStream&, JSC::DFG::LocationKind);
186
187template<typename T> struct DefaultHash;
188template<> struct DefaultHash<JSC::DFG::HeapLocation> {
189 typedef JSC::DFG::HeapLocationHash Hash;
190};
191
192template<typename T> struct HashTraits;
193template<> struct HashTraits<JSC::DFG::HeapLocation> : SimpleClassHashTraits<JSC::DFG::HeapLocation> {
194 static constexpr bool emptyValueIsZero = false;
195};
196
197} // namespace WTF
198
199#endif // ENABLE(DFG_JIT)
200