]> git.saurik.com Git - apple/javascriptcore.git/blob - ftl/FTLAbstractHeap.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / ftl / FTLAbstractHeap.cpp
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 #include "config.h"
27 #include "FTLAbstractHeap.h"
28
29 #if ENABLE(FTL_JIT)
30
31 #include "FTLAbbreviations.h"
32 #include "FTLAbstractHeapRepository.h"
33 #include "FTLOutput.h"
34 #include "FTLTypedPointer.h"
35 #include "JSCInlines.h"
36 #include "Options.h"
37
38 namespace JSC { namespace FTL {
39
40 LValue AbstractHeap::tbaaMetadataSlow(const AbstractHeapRepository& repository) const
41 {
42 m_tbaaMetadata = mdNode(
43 repository.m_context,
44 mdString(repository.m_context, m_heapName),
45 m_parent->tbaaMetadata(repository));
46 return m_tbaaMetadata;
47 }
48
49 void AbstractHeap::decorateInstruction(LValue instruction, const AbstractHeapRepository& repository) const
50 {
51 if (!Options::useFTLTBAA())
52 return;
53 setMetadata(instruction, repository.m_tbaaKind, tbaaMetadata(repository));
54 }
55
56 void AbstractHeap::dump(PrintStream& out) const
57 {
58 out.print(heapName());
59 if (m_parent)
60 out.print("->", *m_parent);
61 }
62
63 void AbstractField::dump(PrintStream& out) const
64 {
65 out.print(heapName(), "(", m_offset, ")");
66 if (parent())
67 out.print("->", *parent());
68 }
69
70 IndexedAbstractHeap::IndexedAbstractHeap(LContext context, AbstractHeap* parent, const char* heapName, ptrdiff_t offset, size_t elementSize)
71 : m_heapForAnyIndex(parent, heapName)
72 , m_heapNameLength(strlen(heapName))
73 , m_offset(offset)
74 , m_elementSize(elementSize)
75 , m_scaleTerm(0)
76 , m_canShift(false)
77 {
78 // See if there is a common shift amount we could use instead of multiplying. Don't
79 // try too hard. This is just a speculative optimization to reduce load on LLVM.
80 for (unsigned i = 0; i < 4; ++i) {
81 if (1U << i == m_elementSize) {
82 if (i)
83 m_scaleTerm = constInt(intPtrType(context), i, ZeroExtend);
84 m_canShift = true;
85 break;
86 }
87 }
88
89 if (!m_canShift)
90 m_scaleTerm = constInt(intPtrType(context), m_elementSize, ZeroExtend);
91 }
92
93 IndexedAbstractHeap::~IndexedAbstractHeap()
94 {
95 }
96
97 TypedPointer IndexedAbstractHeap::baseIndex(Output& out, LValue base, LValue index, JSValue indexAsConstant, ptrdiff_t offset)
98 {
99 if (indexAsConstant.isInt32())
100 return out.address(base, at(indexAsConstant.asInt32()), offset);
101
102 LValue result;
103 if (m_canShift) {
104 if (!m_scaleTerm)
105 result = out.add(base, index);
106 else
107 result = out.add(base, out.shl(index, m_scaleTerm));
108 } else
109 result = out.add(base, out.mul(index, m_scaleTerm));
110
111 return TypedPointer(atAnyIndex(), out.addPtr(result, m_offset + offset));
112 }
113
114 const AbstractField& IndexedAbstractHeap::atSlow(ptrdiff_t index)
115 {
116 ASSERT(static_cast<size_t>(index) >= m_smallIndices.size());
117
118 if (UNLIKELY(!m_largeIndices))
119 m_largeIndices = std::make_unique<MapType>();
120
121 std::unique_ptr<AbstractField>& field = m_largeIndices->add(index, nullptr).iterator->value;
122 if (!field) {
123 field = std::make_unique<AbstractField>();
124 initialize(*field, index);
125 }
126
127 return *field;
128 }
129
130 void IndexedAbstractHeap::initialize(AbstractField& field, ptrdiff_t signedIndex)
131 {
132 // Build up a name of the form:
133 //
134 // heapName_hexIndex
135 //
136 // or:
137 //
138 // heapName_neg_hexIndex
139 //
140 // For example if you access an indexed heap called FooBar at index 5, you'll
141 // get:
142 //
143 // FooBar_5
144 //
145 // Or if you access an indexed heap called Blah at index -10, you'll get:
146 //
147 // Blah_neg_A
148 //
149 // This is important because LLVM uses the string to distinguish the types.
150
151 static const char* negSplit = "_neg_";
152 static const char* posSplit = "_";
153
154 bool negative;
155 size_t index;
156 if (signedIndex < 0) {
157 negative = true;
158 index = -signedIndex;
159 } else {
160 negative = false;
161 index = signedIndex;
162 }
163
164 for (unsigned power = 4; power <= sizeof(void*) * 8; power += 4) {
165 if (isGreaterThanNonZeroPowerOfTwo(index, power))
166 continue;
167
168 unsigned numHexlets = power >> 2;
169
170 size_t stringLength = m_heapNameLength + (negative ? strlen(negSplit) : strlen(posSplit)) + numHexlets;
171 char* characters;
172 m_largeIndexNames.append(CString::newUninitialized(stringLength, characters));
173
174 memcpy(characters, m_heapForAnyIndex.heapName(), m_heapNameLength);
175 if (negative)
176 memcpy(characters + m_heapNameLength, negSplit, strlen(negSplit));
177 else
178 memcpy(characters + m_heapNameLength, posSplit, strlen(posSplit));
179
180 size_t accumulator = index;
181 for (unsigned i = 0; i < numHexlets; ++i) {
182 characters[stringLength - i - 1] = lowerNibbleToASCIIHexDigit(accumulator);
183 accumulator >>= 4;
184 }
185
186 field.initialize(&m_heapForAnyIndex, characters, m_offset + signedIndex * m_elementSize);
187 return;
188 }
189
190 RELEASE_ASSERT_NOT_REACHED();
191 }
192
193 void IndexedAbstractHeap::dump(PrintStream& out) const
194 {
195 out.print("Indexed:", atAnyIndex());
196 }
197
198 NumberedAbstractHeap::NumberedAbstractHeap(LContext context, AbstractHeap* heap, const char* heapName)
199 : m_indexedHeap(context, heap, heapName, 0, 1)
200 {
201 }
202
203 NumberedAbstractHeap::~NumberedAbstractHeap()
204 {
205 }
206
207 void NumberedAbstractHeap::dump(PrintStream& out) const
208 {
209 out.print("Numbered: ", atAnyNumber());
210 }
211
212 AbsoluteAbstractHeap::AbsoluteAbstractHeap(LContext context, AbstractHeap* heap, const char* heapName)
213 : m_indexedHeap(context, heap, heapName, 0, 1)
214 {
215 }
216
217 AbsoluteAbstractHeap::~AbsoluteAbstractHeap()
218 {
219 }
220
221 void AbsoluteAbstractHeap::dump(PrintStream& out) const
222 {
223 out.print("Absolute:", atAnyAddress());
224 }
225
226 } } // namespace JSC::FTL
227
228 #endif // ENABLE(FTL_JIT)
229