9b17868c2bc930908fd7626a3472761ca18e3320
[WebKit-https.git] / Source / JavaScriptCore / ftl / FTLAbstractHeap.h
1 /*
2  * Copyright (C) 2013, 2015-2016 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 "B3HeapRange.h"
32 #include "FTLAbbreviatedTypes.h"
33 #include "JSCJSValue.h"
34 #include <array>
35 #include <wtf/FastMalloc.h>
36 #include <wtf/HashMap.h>
37 #include <wtf/Noncopyable.h>
38 #include <wtf/Vector.h>
39 #include <wtf/text/CString.h>
40
41 namespace JSC { namespace FTL {
42
43 class AbstractHeapRepository;
44 class Output;
45 class TypedPointer;
46
47 class AbstractHeap {
48     WTF_MAKE_NONCOPYABLE(AbstractHeap); WTF_MAKE_FAST_ALLOCATED;
49 public:
50     AbstractHeap()
51     {
52     }
53     
54     AbstractHeap(AbstractHeap* parent, const char* heapName, ptrdiff_t offset = 0);
55
56     bool isInitialized() const { return !!m_heapName; }
57     
58     void initialize(AbstractHeap* parent, const char* heapName, ptrdiff_t offset = 0)
59     {
60         changeParent(parent);
61         m_heapName = heapName;
62         m_offset = offset;
63     }
64     
65     void changeParent(AbstractHeap* parent);
66
67     AbstractHeap* parent() const
68     {
69         ASSERT(isInitialized());
70         return m_parent;
71     }
72
73     const Vector<AbstractHeap*>& children() const;
74     
75     const char* heapName() const
76     {
77         ASSERT(isInitialized());
78         return m_heapName;
79     }
80
81     B3::HeapRange range() const
82     {
83         // This will not have a valid value until after all lowering is done. Do associate an
84         // AbstractHeap with a B3::Value*, use AbstractHeapRepository::decorateXXX().
85         if (!m_range)
86             badRangeError();
87         
88         return m_range;
89     }
90
91     // WARNING: Not all abstract heaps have a meaningful offset.
92     ptrdiff_t offset() const
93     {
94         ASSERT(isInitialized());
95         return m_offset;
96     }
97
98     void compute(unsigned begin = 0);
99
100     // Print information about just this heap.
101     void shallowDump(PrintStream&) const;
102
103     // Print information about this heap and its ancestors. This is the default.
104     void dump(PrintStream&) const;
105
106     // Print information about this heap and its descendents. This is a multi-line dump.
107     void deepDump(PrintStream&, unsigned indent = 0) const;
108
109 private:
110     friend class AbstractHeapRepository;
111
112     NO_RETURN_DUE_TO_CRASH void badRangeError() const;
113
114     AbstractHeap* m_parent { nullptr };
115     Vector<AbstractHeap*> m_children;
116     intptr_t m_offset { 0 };
117     B3::HeapRange m_range;
118     const char* m_heapName { nullptr };
119 };
120
121 class IndexedAbstractHeap {
122 public:
123     IndexedAbstractHeap(AbstractHeap* parent, const char* heapName, ptrdiff_t offset, size_t elementSize);
124     ~IndexedAbstractHeap();
125     
126     const AbstractHeap& atAnyIndex() const { return m_heapForAnyIndex; }
127     
128     const AbstractHeap& at(ptrdiff_t index)
129     {
130         if (static_cast<size_t>(index) < m_smallIndices.size())
131             return returnInitialized(m_smallIndices[index], index);
132         return atSlow(index);
133     }
134     
135     const AbstractHeap& operator[](ptrdiff_t index) { return at(index); }
136     
137     TypedPointer baseIndex(Output& out, LValue base, LValue index, JSValue indexAsConstant = JSValue(), ptrdiff_t offset = 0);
138     
139     void dump(PrintStream&) const;
140
141 private:
142     const AbstractHeap& returnInitialized(AbstractHeap& field, ptrdiff_t index)
143     {
144         if (UNLIKELY(!field.isInitialized()))
145             initialize(field, index);
146         return field;
147     }
148
149     const AbstractHeap& atSlow(ptrdiff_t index);
150     void initialize(AbstractHeap& field, ptrdiff_t index);
151
152     AbstractHeap m_heapForAnyIndex;
153     size_t m_heapNameLength;
154     ptrdiff_t m_offset;
155     size_t m_elementSize;
156     std::array<AbstractHeap, 16> m_smallIndices;
157     
158     struct WithoutZeroOrOneHashTraits : WTF::GenericHashTraits<ptrdiff_t> {
159         static void constructDeletedValue(ptrdiff_t& slot) { slot = 1; }
160         static bool isDeletedValue(ptrdiff_t value) { return value == 1; }
161     };
162     typedef HashMap<ptrdiff_t, std::unique_ptr<AbstractHeap>, WTF::IntHash<ptrdiff_t>, WithoutZeroOrOneHashTraits> MapType;
163     
164     std::unique_ptr<MapType> m_largeIndices;
165     Vector<CString, 16> m_largeIndexNames;
166 };
167
168 // A numbered abstract heap is like an indexed abstract heap, except that you
169 // can't rely on there being a relationship between the number you use to
170 // retrieve the sub-heap, and the offset that this heap has. (In particular,
171 // the sub-heaps don't have indices.)
172
173 class NumberedAbstractHeap {
174 public:
175     NumberedAbstractHeap(AbstractHeap* parent, const char* heapName);
176     ~NumberedAbstractHeap();
177     
178     const AbstractHeap& atAnyNumber() const { return m_indexedHeap.atAnyIndex(); }
179     
180     const AbstractHeap& at(unsigned number) { return m_indexedHeap.at(number); }
181     const AbstractHeap& operator[](unsigned number) { return at(number); }
182
183     void dump(PrintStream&) const;
184
185 private:
186     
187     // We use the fact that the indexed heap already has a superset of the
188     // functionality we need.
189     IndexedAbstractHeap m_indexedHeap;
190 };
191
192 class AbsoluteAbstractHeap {
193 public:
194     AbsoluteAbstractHeap(AbstractHeap* parent, const char* heapName);
195     ~AbsoluteAbstractHeap();
196     
197     const AbstractHeap& atAnyAddress() const { return m_indexedHeap.atAnyIndex(); }
198     
199     const AbstractHeap& at(void* address)
200     {
201         return m_indexedHeap.at(bitwise_cast<ptrdiff_t>(address));
202     }
203     
204     const AbstractHeap& operator[](void* address) { return at(address); }
205
206     void dump(PrintStream&) const;
207
208 private:
209     // The trick here is that the indexed heap is "indexed" by a pointer-width
210     // integer. Pointers are themselves pointer-width integers. So we can reuse
211     // all of the functionality.
212     IndexedAbstractHeap m_indexedHeap;
213 };
214
215 } } // namespace JSC::FTL
216
217 #endif // ENABLE(FTL_JIT)
218
219 #endif // FTLAbstractHeap_h
220