fourthTier: FTL shouldn't use the LLVM global context, and should instead create...
[WebKit-https.git] / Source / JavaScriptCore / ftl / FTLAbstractHeap.h
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 #ifndef FTLAbstractHeap_h
27 #define FTLAbstractHeap_h
28
29 #include <wtf/Platform.h>
30
31 #if ENABLE(FTL_JIT)
32
33 #include "FTLAbbreviations.h"
34 #include "JSCJSValue.h"
35 #include <wtf/FastAllocBase.h>
36 #include <wtf/FixedArray.h>
37 #include <wtf/HashMap.h>
38 #include <wtf/Noncopyable.h>
39 #include <wtf/OwnPtr.h>
40 #include <wtf/Vector.h>
41 #include <wtf/text/CString.h>
42
43 namespace JSC { namespace FTL {
44
45 // The FTL JIT tries to aid LLVM's TBAA. The FTL's notion of how this
46 // happens is the AbstractHeap. AbstractHeaps are a simple type system
47 // with sub-typing.
48
49 class AbstractHeapRepository;
50 class Output;
51 class TypedPointer;
52
53 class AbstractHeap {
54     WTF_MAKE_NONCOPYABLE(AbstractHeap); WTF_MAKE_FAST_ALLOCATED;
55 public:
56     AbstractHeap()
57         : m_parent(0)
58         , m_heapName(0)
59         , m_tbaaMetadata(0)
60     {
61     }
62     
63     AbstractHeap(AbstractHeap* parent, const char* heapName)
64         : m_parent(parent)
65         , m_heapName(heapName)
66         , m_tbaaMetadata(0)
67     {
68     }
69     
70     bool isInitialized() const { return !!m_heapName; }
71     
72     void initialize(AbstractHeap* parent, const char* heapName)
73     {
74         m_parent = parent;
75         m_heapName = heapName;
76     }
77
78     AbstractHeap* parent() const
79     {
80         ASSERT(isInitialized());
81         return m_parent;
82     }
83     
84     const char* heapName() const
85     {
86         ASSERT(isInitialized());
87         return m_heapName;
88     }
89     
90     LValue tbaaMetadata(const AbstractHeapRepository& repository) const
91     {
92         ASSERT(isInitialized());
93         if (LIKELY(!!m_tbaaMetadata))
94             return m_tbaaMetadata;
95         return tbaaMetadataSlow(repository);
96     }
97     
98     void decorateInstruction(LValue instruction, const AbstractHeapRepository&) const;
99
100 private:
101     friend class AbstractHeapRepository;
102     
103     LValue tbaaMetadataSlow(const AbstractHeapRepository&) const;
104     
105     AbstractHeap* m_parent;
106     const char* m_heapName;
107     mutable LValue m_tbaaMetadata;
108 };
109
110 // Think of "AbstractField" as being an "AbstractHeapWithOffset". I would have named
111 // it the latter except that I don't like typing that much.
112 class AbstractField : public AbstractHeap {
113 public:
114     AbstractField()
115     {
116     }
117     
118     AbstractField(AbstractHeap* parent, const char* heapName, ptrdiff_t offset)
119         : AbstractHeap(parent, heapName)
120         , m_offset(offset)
121     {
122     }
123     
124     void initialize(AbstractHeap* parent, const char* heapName, ptrdiff_t offset)
125     {
126         AbstractHeap::initialize(parent, heapName);
127         m_offset = offset;
128     }
129     
130     ptrdiff_t offset() const
131     {
132         ASSERT(isInitialized());
133         return m_offset;
134     }
135     
136 private:
137     ptrdiff_t m_offset;
138 };
139
140 class IndexedAbstractHeap {
141 public:
142     IndexedAbstractHeap(LContext, AbstractHeap* parent, const char* heapName, size_t elementSize);
143     ~IndexedAbstractHeap();
144     
145     const AbstractHeap& atAnyIndex() const { return m_heapForAnyIndex; }
146     
147     const AbstractField& at(ptrdiff_t index)
148     {
149         if (static_cast<size_t>(index) < m_smallIndices.size())
150             return returnInitialized(m_smallIndices[index], index);
151         return atSlow(index);
152     }
153     
154     const AbstractField& operator[](ptrdiff_t index) { return at(index); }
155     
156     TypedPointer baseIndex(Output& out, LValue base, LValue index, JSValue indexAsConstant = JSValue(), ptrdiff_t offset = 0);
157     
158 private:
159     const AbstractField& returnInitialized(AbstractField& field, ptrdiff_t index)
160     {
161         if (UNLIKELY(!field.isInitialized()))
162             initialize(field, index);
163         return field;
164     }
165
166     const AbstractField& atSlow(ptrdiff_t index);
167     void initialize(AbstractField& field, ptrdiff_t index);
168
169     AbstractHeap m_heapForAnyIndex;
170     size_t m_heapNameLength;
171     size_t m_elementSize;
172     LValue m_scaleTerm;
173     bool m_canShift;
174     FixedArray<AbstractField, 16> m_smallIndices;
175     
176     struct WithoutZeroOrOneHashTraits : WTF::GenericHashTraits<ptrdiff_t> {
177         static void constructDeletedValue(ptrdiff_t& slot) { slot = 1; }
178         static bool isDeletedValue(ptrdiff_t value) { return value == 1; }
179     };
180     typedef HashMap<ptrdiff_t, OwnPtr<AbstractField>, WTF::IntHash<ptrdiff_t>, WithoutZeroOrOneHashTraits> MapType;
181     
182     OwnPtr<MapType> m_largeIndices;
183     Vector<CString, 16> m_largeIndexNames;
184 };
185
186 // A numbered abstract heap is like an indexed abstract heap, except that you
187 // can't rely on there being a relationship between the number you use to
188 // retrieve the sub-heap, and the offset that this heap has. (In particular,
189 // the sub-heaps don't have indices.)
190
191 class NumberedAbstractHeap {
192 public:
193     NumberedAbstractHeap(LContext, AbstractHeap* parent, const char* heapName);
194     ~NumberedAbstractHeap();
195     
196     const AbstractHeap& atAnyNumber() const { return m_indexedHeap.atAnyIndex(); }
197     
198     const AbstractHeap& at(unsigned number) { return m_indexedHeap.at(number); }
199     const AbstractHeap& operator[](unsigned number) { return at(number); }
200
201 private:
202     
203     // We use the fact that the indexed heap already has a superset of the
204     // functionality we need.
205     IndexedAbstractHeap m_indexedHeap;
206 };
207
208 class AbsoluteAbstractHeap {
209 public:
210     AbsoluteAbstractHeap(LContext, AbstractHeap* parent, const char* heapName);
211     ~AbsoluteAbstractHeap();
212     
213     const AbstractHeap& atAnyAddress() const { return m_indexedHeap.atAnyIndex(); }
214     
215     const AbstractHeap& at(void* address)
216     {
217         return m_indexedHeap.at(bitwise_cast<ptrdiff_t>(address));
218     }
219     
220     const AbstractHeap& operator[](void* address) { return at(address); }
221
222 private:
223     // The trick here is that the indexed heap is "indexed" by a pointer-width
224     // integer. Pointers are themselves pointer-width integers. So we can reuse
225     // all of the functionality.
226     IndexedAbstractHeap m_indexedHeap;
227 };
228
229 } } // namespace JSC::FTL
230
231 #endif // ENABLE(FTL_JIT)
232
233 #endif // FTLAbstractHeap_h
234