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