2 * Copyright (C) 2013, 2015 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 FTLAbstractHeap_h
27 #define FTLAbstractHeap_h
31 #include "FTLAbbreviations.h"
32 #include "JSCJSValue.h"
34 #include <wtf/FastMalloc.h>
35 #include <wtf/HashMap.h>
36 #include <wtf/Noncopyable.h>
37 #include <wtf/Vector.h>
38 #include <wtf/text/CString.h>
40 namespace JSC
{ namespace FTL
{
42 // The FTL JIT tries to aid LLVM's TBAA. The FTL's notion of how this
43 // happens is the AbstractHeap. AbstractHeaps are a simple type system
46 class AbstractHeapRepository
;
51 WTF_MAKE_NONCOPYABLE(AbstractHeap
); WTF_MAKE_FAST_ALLOCATED
;
60 AbstractHeap(AbstractHeap
* parent
, const char* heapName
)
62 , m_heapName(heapName
)
67 bool isInitialized() const { return !!m_heapName
; }
69 void initialize(AbstractHeap
* parent
, const char* heapName
)
72 m_heapName
= heapName
;
75 void changeParent(AbstractHeap
* parent
)
80 AbstractHeap
* parent() const
82 ASSERT(isInitialized());
86 const char* heapName() const
88 ASSERT(isInitialized());
92 LValue
tbaaMetadata(const AbstractHeapRepository
& repository
) const
94 ASSERT(isInitialized());
95 if (LIKELY(!!m_tbaaMetadata
))
96 return m_tbaaMetadata
;
97 return tbaaMetadataSlow(repository
);
100 void decorateInstruction(LValue instruction
, const AbstractHeapRepository
&) const;
102 void dump(PrintStream
&) const;
105 friend class AbstractHeapRepository
;
107 LValue
tbaaMetadataSlow(const AbstractHeapRepository
&) const;
109 AbstractHeap
* m_parent
;
110 const char* m_heapName
;
111 mutable LValue m_tbaaMetadata
;
114 // Think of "AbstractField" as being an "AbstractHeapWithOffset". I would have named
115 // it the latter except that I don't like typing that much.
116 class AbstractField
: public AbstractHeap
{
122 AbstractField(AbstractHeap
* parent
, const char* heapName
, ptrdiff_t offset
)
123 : AbstractHeap(parent
, heapName
)
128 void initialize(AbstractHeap
* parent
, const char* heapName
, ptrdiff_t offset
)
130 AbstractHeap::initialize(parent
, heapName
);
134 ptrdiff_t offset() const
136 ASSERT(isInitialized());
140 void dump(PrintStream
&) const;
146 class IndexedAbstractHeap
{
148 IndexedAbstractHeap(LContext
, AbstractHeap
* parent
, const char* heapName
, ptrdiff_t offset
, size_t elementSize
);
149 ~IndexedAbstractHeap();
151 const AbstractHeap
& atAnyIndex() const { return m_heapForAnyIndex
; }
153 const AbstractField
& at(ptrdiff_t index
)
155 if (static_cast<size_t>(index
) < m_smallIndices
.size())
156 return returnInitialized(m_smallIndices
[index
], index
);
157 return atSlow(index
);
160 const AbstractField
& operator[](ptrdiff_t index
) { return at(index
); }
162 TypedPointer
baseIndex(Output
& out
, LValue base
, LValue index
, JSValue indexAsConstant
= JSValue(), ptrdiff_t offset
= 0);
164 void dump(PrintStream
&) const;
167 const AbstractField
& returnInitialized(AbstractField
& field
, ptrdiff_t index
)
169 if (UNLIKELY(!field
.isInitialized()))
170 initialize(field
, index
);
174 const AbstractField
& atSlow(ptrdiff_t index
);
175 void initialize(AbstractField
& field
, ptrdiff_t index
);
177 AbstractHeap m_heapForAnyIndex
;
178 size_t m_heapNameLength
;
180 size_t m_elementSize
;
183 std::array
<AbstractField
, 16> m_smallIndices
;
185 struct WithoutZeroOrOneHashTraits
: WTF::GenericHashTraits
<ptrdiff_t> {
186 static void constructDeletedValue(ptrdiff_t& slot
) { slot
= 1; }
187 static bool isDeletedValue(ptrdiff_t value
) { return value
== 1; }
189 typedef HashMap
<ptrdiff_t, std::unique_ptr
<AbstractField
>, WTF::IntHash
<ptrdiff_t>, WithoutZeroOrOneHashTraits
> MapType
;
191 std::unique_ptr
<MapType
> m_largeIndices
;
192 Vector
<CString
, 16> m_largeIndexNames
;
195 // A numbered abstract heap is like an indexed abstract heap, except that you
196 // can't rely on there being a relationship between the number you use to
197 // retrieve the sub-heap, and the offset that this heap has. (In particular,
198 // the sub-heaps don't have indices.)
200 class NumberedAbstractHeap
{
202 NumberedAbstractHeap(LContext
, AbstractHeap
* parent
, const char* heapName
);
203 ~NumberedAbstractHeap();
205 const AbstractHeap
& atAnyNumber() const { return m_indexedHeap
.atAnyIndex(); }
207 const AbstractHeap
& at(unsigned number
) { return m_indexedHeap
.at(number
); }
208 const AbstractHeap
& operator[](unsigned number
) { return at(number
); }
210 void dump(PrintStream
&) const;
214 // We use the fact that the indexed heap already has a superset of the
215 // functionality we need.
216 IndexedAbstractHeap m_indexedHeap
;
219 class AbsoluteAbstractHeap
{
221 AbsoluteAbstractHeap(LContext
, AbstractHeap
* parent
, const char* heapName
);
222 ~AbsoluteAbstractHeap();
224 const AbstractHeap
& atAnyAddress() const { return m_indexedHeap
.atAnyIndex(); }
226 const AbstractHeap
& at(void* address
)
228 return m_indexedHeap
.at(bitwise_cast
<ptrdiff_t>(address
));
231 const AbstractHeap
& operator[](void* address
) { return at(address
); }
233 void dump(PrintStream
&) const;
236 // The trick here is that the indexed heap is "indexed" by a pointer-width
237 // integer. Pointers are themselves pointer-width integers. So we can reuse
238 // all of the functionality.
239 IndexedAbstractHeap m_indexedHeap
;
242 } } // namespace JSC::FTL
244 #endif // ENABLE(FTL_JIT)
246 #endif // FTLAbstractHeap_h