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