2 * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "FTLOutput.h"
31 #include "B3MathExtras.h"
32 #include "B3StackmapGenerationParams.h"
34 namespace JSC { namespace FTL {
38 Output::Output(State& state)
47 void Output::initialize(AbstractHeapRepository& heaps)
52 LBasicBlock Output::newBlock(const char*)
54 LBasicBlock result = m_proc.addBlock(m_frequency);
57 m_blockOrder.append(result);
59 m_blockOrder.insertBefore(m_nextBlock, result);
64 void Output::applyBlockOrder()
66 m_proc.setBlockOrder(m_blockOrder);
69 LBasicBlock Output::appendTo(LBasicBlock block, LBasicBlock nextBlock)
72 return insertNewBlocksBefore(nextBlock);
75 void Output::appendTo(LBasicBlock block)
80 SlotBaseValue* Output::lockedStackSlot(size_t bytes)
82 return m_block->appendNew<SlotBaseValue>(m_proc, origin(), m_proc.addStackSlot(bytes));
85 LValue Output::neg(LValue value)
87 return m_block->appendNew<Value>(m_proc, B3::Neg, origin(), value);
90 LValue Output::bitNot(LValue value)
92 return m_block->appendNew<B3::Value>(m_proc, B3::BitXor, origin(),
94 m_block->appendIntConstant(m_proc, origin(), value->type(), -1));
97 LValue Output::logicalNot(LValue value)
99 return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), value, int32Zero);
102 LValue Output::load(TypedPointer pointer, LType type)
104 LValue load = m_block->appendNew<MemoryValue>(m_proc, Load, type, origin(), pointer.value());
105 m_heaps->decorateMemory(pointer.heap(), load);
109 LValue Output::doublePowi(LValue x, LValue y)
111 // FIXME: powDoubleInt32() should be inlined here since Output knows about block layout and
112 // should be involved in any operation that creates blocks.
113 // https://bugs.webkit.org/show_bug.cgi?id=152223
114 auto result = powDoubleInt32(m_proc, m_block, origin(), x, y);
115 m_block = result.first;
116 return result.second;
119 bool Output::hasSensibleDoubleToInt()
121 return optimizeForX86();
124 LValue Output::doubleToInt(LValue value)
126 PatchpointValue* result = patchpoint(Int32);
127 result->append(value, ValueRep::SomeRegister);
128 result->setGenerator(
129 [] (CCallHelpers& jit, const StackmapGenerationParams& params) {
130 jit.truncateDoubleToInt32(params[1].fpr(), params[0].gpr());
132 result->effects = Effects::none();
136 LValue Output::doubleToUInt(LValue value)
138 PatchpointValue* result = patchpoint(Int32);
139 result->append(value, ValueRep::SomeRegister);
140 result->setGenerator(
141 [] (CCallHelpers& jit, const StackmapGenerationParams& params) {
142 jit.truncateDoubleToUint32(params[1].fpr(), params[0].gpr());
144 result->effects = Effects::none();
148 LValue Output::unsignedToDouble(LValue value)
150 return intToDouble(zeroExt(value, Int64));
153 LValue Output::load8SignExt32(TypedPointer pointer)
155 LValue load = m_block->appendNew<MemoryValue>(m_proc, Load8S, Int32, origin(), pointer.value());
156 m_heaps->decorateMemory(pointer.heap(), load);
160 LValue Output::load8ZeroExt32(TypedPointer pointer)
162 LValue load = m_block->appendNew<MemoryValue>(m_proc, Load8Z, Int32, origin(), pointer.value());
163 m_heaps->decorateMemory(pointer.heap(), load);
167 LValue Output::load16SignExt32(TypedPointer pointer)
169 LValue load = m_block->appendNew<MemoryValue>(m_proc, Load16S, Int32, origin(), pointer.value());
170 m_heaps->decorateMemory(pointer.heap(), load);
174 LValue Output::load16ZeroExt32(TypedPointer pointer)
176 LValue load = m_block->appendNew<MemoryValue>(m_proc, Load16Z, Int32, origin(), pointer.value());
177 m_heaps->decorateMemory(pointer.heap(), load);
181 void Output::store(LValue value, TypedPointer pointer)
183 LValue store = m_block->appendNew<MemoryValue>(m_proc, Store, origin(), value, pointer.value());
184 m_heaps->decorateMemory(pointer.heap(), store);
187 void Output::store32As8(LValue value, TypedPointer pointer)
189 LValue store = m_block->appendNew<MemoryValue>(m_proc, Store8, origin(), value, pointer.value());
190 m_heaps->decorateMemory(pointer.heap(), store);
193 void Output::store32As16(LValue value, TypedPointer pointer)
195 LValue store = m_block->appendNew<MemoryValue>(m_proc, Store16, origin(), value, pointer.value());
196 m_heaps->decorateMemory(pointer.heap(), store);
199 LValue Output::baseIndex(LValue base, LValue index, Scale scale, ptrdiff_t offset)
201 LValue accumulatedOffset;
205 accumulatedOffset = index;
208 accumulatedOffset = shl(index, intPtrOne);
211 accumulatedOffset = shl(index, intPtrTwo);
215 accumulatedOffset = shl(index, intPtrThree);
220 accumulatedOffset = add(accumulatedOffset, constIntPtr(offset));
222 return add(base, accumulatedOffset);
225 void Output::branch(LValue condition, LBasicBlock taken, Weight takenWeight, LBasicBlock notTaken, Weight notTakenWeight)
227 m_block->appendNew<ControlValue>(
228 m_proc, B3::Branch, origin(), condition,
229 FrequentedBlock(taken, takenWeight.frequencyClass()),
230 FrequentedBlock(notTaken, notTakenWeight.frequencyClass()));
233 void Output::check(LValue condition, WeightedTarget taken, Weight notTakenWeight)
235 LBasicBlock continuation = FTL_NEW_BLOCK(*this, ("Output::check continuation"));
236 branch(condition, taken, WeightedTarget(continuation, notTakenWeight));
237 appendTo(continuation);
240 void Output::check(LValue condition, WeightedTarget taken)
242 check(condition, taken, taken.weight().inverse());
245 LValue Output::load(TypedPointer pointer, LoadType type)
249 return load8SignExt32(pointer);
251 return load8ZeroExt32(pointer);
252 case Load16SignExt32:
253 return load8SignExt32(pointer);
254 case Load16ZeroExt32:
255 return load8ZeroExt32(pointer);
257 return load32(pointer);
259 return load64(pointer);
261 return loadPtr(pointer);
263 return loadFloat(pointer);
265 return loadDouble(pointer);
267 RELEASE_ASSERT_NOT_REACHED();
271 void Output::store(LValue value, TypedPointer pointer, StoreType type)
275 store32As8(value, pointer);
278 store32As16(value, pointer);
281 store32(value, pointer);
284 store64(value, pointer);
287 storePtr(value, pointer);
290 storeFloat(value, pointer);
293 storeDouble(value, pointer);
296 RELEASE_ASSERT_NOT_REACHED();
299 } } // namespace JSC::FTL
301 #endif // ENABLE(FTL_JIT)