fourthTier: FTL shouldn't use the LLVM global context, and should instead create...
[WebKit-https.git] / Source / JavaScriptCore / ftl / FTLAbstractHeap.cpp
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 #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 "Operations.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 IndexedAbstractHeap::IndexedAbstractHeap(LContext context, AbstractHeap* parent, const char* heapName, size_t elementSize)
57     : m_heapForAnyIndex(parent, heapName)
58     , m_heapNameLength(strlen(heapName))
59     , m_elementSize(elementSize)
60     , m_scaleTerm(0)
61     , m_canShift(false)
62 {
63     // See if there is a common shift amount we could use instead of multiplying. Don't
64     // try too hard. This is just a speculative optimization to reduce load on LLVM.
65     for (unsigned i = 0; i < 4; ++i) {
66         if ((1 << i) == m_elementSize) {
67             if (i)
68                 m_scaleTerm = constInt(intPtrType(context), i, ZeroExtend);
69             m_canShift = true;
70             break;
71         }
72     }
73     
74     if (!m_canShift)
75         m_scaleTerm = constInt(intPtrType(context), m_elementSize, ZeroExtend);
76 }
77
78 IndexedAbstractHeap::~IndexedAbstractHeap()
79 {
80 }
81
82 TypedPointer IndexedAbstractHeap::baseIndex(Output& out, LValue base, LValue index, JSValue indexAsConstant, ptrdiff_t offset)
83 {
84     if (indexAsConstant.isInt32())
85         return out.address(base, at(indexAsConstant.asInt32()), offset);
86     
87     LValue result;
88     if (m_canShift) {
89         if (!m_scaleTerm)
90             result = out.add(base, index);
91         else
92             result = out.add(base, out.shl(index, m_scaleTerm));
93     } else
94         result = out.add(base, out.mul(index, m_scaleTerm));
95     
96     return TypedPointer(atAnyIndex(), out.addPtr(result, offset));
97 }
98
99 const AbstractField& IndexedAbstractHeap::atSlow(ptrdiff_t index)
100 {
101     ASSERT(static_cast<size_t>(index) >= m_smallIndices.size());
102     
103     if (UNLIKELY(!m_largeIndices))
104         m_largeIndices = adoptPtr(new MapType());
105     
106     MapType::const_iterator iter = m_largeIndices->find(index);
107     if (iter != m_largeIndices->end())
108         return *iter->value;
109     
110     OwnPtr<AbstractField> field = adoptPtr(new AbstractField());
111     AbstractField* result = field.get();
112     initialize(*result, index);
113     m_largeIndices->add(index, field.release());
114     return *result;
115 }
116
117 void IndexedAbstractHeap::initialize(AbstractField& field, ptrdiff_t signedIndex)
118 {
119     // Build up a name of the form:
120     //
121     //    heapName_hexIndex
122     //
123     // or:
124     //
125     //    heapName_neg_hexIndex
126     //
127     // For example if you access an indexed heap called FooBar at index 5, you'll
128     // get:
129     //
130     //    FooBar_5
131     //
132     // Or if you access an indexed heap called Blah at index -10, you'll get:
133     //
134     //    Blah_neg_A
135     //
136     // This is important because LLVM uses the string to distinguish the types.
137     
138     static const char* negSplit = "_neg_";
139     static const char* posSplit = "_";
140     
141     bool negative;
142     size_t index;
143     if (signedIndex < 0) {
144         negative = true;
145         index = -signedIndex;
146     } else {
147         negative = false;
148         index = signedIndex;
149     }
150     
151     for (unsigned power = 4; power <= sizeof(void*) * 8; power += 4) {
152         if (isGreaterThanNonZeroPowerOfTwo(index, power))
153             continue;
154         
155         unsigned numHexlets = power >> 2;
156         
157         size_t stringLength = m_heapNameLength + (negative ? strlen(negSplit) : strlen(posSplit)) + numHexlets;
158         char* characters;
159         m_largeIndexNames.append(CString::newUninitialized(stringLength, characters));
160         
161         memcpy(characters, m_heapForAnyIndex.heapName(), m_heapNameLength);
162         if (negative)
163             memcpy(characters + m_heapNameLength, negSplit, strlen(negSplit));
164         else
165             memcpy(characters + m_heapNameLength, posSplit, strlen(posSplit));
166         
167         size_t accumulator = index;
168         for (unsigned i = 0; i < numHexlets; ++i) {
169             characters[stringLength - i - 1] = lowerNibbleToASCIIHexDigit(accumulator);
170             accumulator >>= 4;
171         }
172         
173         field.initialize(&m_heapForAnyIndex, characters, signedIndex * m_elementSize);
174         return;
175     }
176     
177     RELEASE_ASSERT_NOT_REACHED();
178 }
179
180 NumberedAbstractHeap::NumberedAbstractHeap(
181     LContext context, AbstractHeap* heap, const char* heapName)
182     : m_indexedHeap(context, heap, heapName, 1)
183 {
184 }
185
186 NumberedAbstractHeap::~NumberedAbstractHeap()
187 {
188 }
189
190 AbsoluteAbstractHeap::AbsoluteAbstractHeap(
191     LContext context, AbstractHeap* heap, const char* heapName)
192     : m_indexedHeap(context, heap, heapName, 1)
193 {
194 }
195
196 AbsoluteAbstractHeap::~AbsoluteAbstractHeap()
197 {
198 }
199
200 } } // namespace JSC::FTL
201
202 #endif // ENABLE(FTL_JIT)
203