cc4bb3976a13cef4f5631bf620df8d4b3c25fe0a
[WebKit-https.git] / Source / JavaScriptCore / ftl / FTLOutput.cpp
1 /*
2  * Copyright (C) 2013-2017 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 "FTLOutput.h"
28
29 #if ENABLE(FTL_JIT)
30
31 #include "B3ArgumentRegValue.h"
32 #include "B3AtomicValue.h"
33 #include "B3BasicBlockInlines.h"
34 #include "B3CCallValue.h"
35 #include "B3Const32Value.h"
36 #include "B3ConstPtrValue.h"
37 #include "B3FenceValue.h"
38 #include "B3MathExtras.h"
39 #include "B3MemoryValue.h"
40 #include "B3SlotBaseValue.h"
41 #include "B3StackmapGenerationParams.h"
42 #include "B3SwitchValue.h"
43 #include "B3UpsilonValue.h"
44 #include "B3ValueInlines.h"
45 #include "SuperSampler.h"
46
47 namespace JSC { namespace FTL {
48
49 using namespace B3;
50
51 Output::Output(State& state)
52     : m_proc(*state.proc)
53 {
54 }
55
56 Output::~Output()
57 {
58 }
59
60 void Output::initialize(AbstractHeapRepository& heaps)
61 {
62     m_heaps = &heaps;
63 }
64
65 LBasicBlock Output::newBlock()
66 {
67     LBasicBlock result = m_proc.addBlock(m_frequency);
68
69     if (!m_nextBlock)
70         m_blockOrder.append(result);
71     else
72         m_blockOrder.insertBefore(m_nextBlock, result);
73
74     return result;
75 }
76
77 void Output::applyBlockOrder()
78 {
79     m_proc.setBlockOrder(m_blockOrder);
80 }
81
82 LBasicBlock Output::appendTo(LBasicBlock block, LBasicBlock nextBlock)
83 {
84     appendTo(block);
85     return insertNewBlocksBefore(nextBlock);
86 }
87
88 void Output::appendTo(LBasicBlock block)
89 {
90     m_block = block;
91 }
92
93 LValue Output::framePointer()
94 {
95     return m_block->appendNew<B3::Value>(m_proc, B3::FramePointer, origin());
96 }
97
98 SlotBaseValue* Output::lockedStackSlot(size_t bytes)
99 {
100     return m_block->appendNew<SlotBaseValue>(m_proc, origin(), m_proc.addStackSlot(bytes));
101 }
102
103 LValue Output::constBool(bool value)
104 {
105     if (value)
106         return booleanTrue;
107     return booleanFalse;
108 }
109
110 LValue Output::constInt32(int32_t value)
111 {
112     return m_block->appendNew<B3::Const32Value>(m_proc, origin(), value);
113 }
114
115 LValue Output::constInt64(int64_t value)
116 {
117     return m_block->appendNew<B3::Const64Value>(m_proc, origin(), value);
118 }
119
120 LValue Output::constDouble(double value)
121 {
122     return m_block->appendNew<B3::ConstDoubleValue>(m_proc, origin(), value);
123 }
124
125 LValue Output::phi(LType type)
126 {
127     return m_block->appendNew<B3::Value>(m_proc, B3::Phi, type, origin());
128 }
129
130 LValue Output::opaque(LValue value)
131 {
132     return m_block->appendNew<Value>(m_proc, Opaque, origin(), value);
133 }
134
135 LValue Output::add(LValue left, LValue right)
136 {
137     if (Value* result = left->addConstant(m_proc, right)) {
138         m_block->append(result);
139         return result;
140     }
141     return m_block->appendNew<B3::Value>(m_proc, B3::Add, origin(), left, right);
142 }
143
144 LValue Output::sub(LValue left, LValue right)
145 {
146     return m_block->appendNew<B3::Value>(m_proc, B3::Sub, origin(), left, right);
147 }
148
149 LValue Output::mul(LValue left, LValue right)
150 {
151     return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right);
152 }
153
154 LValue Output::div(LValue left, LValue right)
155 {
156     return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right);
157 }
158
159 LValue Output::chillDiv(LValue left, LValue right)
160 {
161     return m_block->appendNew<B3::Value>(m_proc, chill(B3::Div), origin(), left, right);
162 }
163
164 LValue Output::mod(LValue left, LValue right)
165 {
166     return m_block->appendNew<B3::Value>(m_proc, B3::Mod, origin(), left, right);
167 }
168
169 LValue Output::chillMod(LValue left, LValue right)
170 {
171     return m_block->appendNew<B3::Value>(m_proc, chill(B3::Mod), origin(), left, right);
172 }
173
174 LValue Output::neg(LValue value)
175 {
176     return m_block->appendNew<Value>(m_proc, B3::Neg, origin(), value);
177 }
178
179 LValue Output::doubleAdd(LValue left, LValue right)
180 {
181     return m_block->appendNew<B3::Value>(m_proc, B3::Add, origin(), left, right);
182 }
183
184 LValue Output::doubleSub(LValue left, LValue right)
185 {
186     return m_block->appendNew<B3::Value>(m_proc, B3::Sub, origin(), left, right);
187 }
188
189 LValue Output::doubleMul(LValue left, LValue right)
190 {
191     return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right);
192 }
193
194 LValue Output::doubleDiv(LValue left, LValue right)
195 {
196     return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right);
197 }
198
199 LValue Output::doubleMod(LValue left, LValue right)
200 {
201     return m_block->appendNew<B3::Value>(m_proc, B3::Mod, origin(), left, right);
202 }
203
204 LValue Output::bitAnd(LValue left, LValue right)
205 {
206     return m_block->appendNew<B3::Value>(m_proc, B3::BitAnd, origin(), left, right);
207 }
208
209 LValue Output::bitOr(LValue left, LValue right)
210 {
211     return m_block->appendNew<B3::Value>(m_proc, B3::BitOr, origin(), left, right);
212 }
213
214 LValue Output::bitXor(LValue left, LValue right)
215 {
216     return m_block->appendNew<B3::Value>(m_proc, B3::BitXor, origin(), left, right);
217 }
218
219 LValue Output::shl(LValue left, LValue right)
220 {
221     right = castToInt32(right);
222     if (Value* result = left->shlConstant(m_proc, right)) {
223         m_block->append(result);
224         return result;
225     }
226     return m_block->appendNew<B3::Value>(m_proc, B3::Shl, origin(), left, right);
227 }
228
229 LValue Output::aShr(LValue left, LValue right)
230 {
231     right = castToInt32(right);
232     if (Value* result = left->sShrConstant(m_proc, right)) {
233         m_block->append(result);
234         return result;
235     }
236     return m_block->appendNew<B3::Value>(m_proc, B3::SShr, origin(), left, right);
237 }
238
239 LValue Output::lShr(LValue left, LValue right)
240 {
241     right = castToInt32(right);
242     if (Value* result = left->zShrConstant(m_proc, right)) {
243         m_block->append(result);
244         return result;
245     }
246     return m_block->appendNew<B3::Value>(m_proc, B3::ZShr, origin(), left, right);
247 }
248
249 LValue Output::bitNot(LValue value)
250 {
251     return m_block->appendNew<B3::Value>(m_proc, B3::BitXor, origin(),
252         value,
253         m_block->appendIntConstant(m_proc, origin(), value->type(), -1));
254 }
255
256 LValue Output::logicalNot(LValue value)
257 {
258     return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), value, int32Zero);
259 }
260
261 LValue Output::ctlz32(LValue operand)
262 {
263     return m_block->appendNew<B3::Value>(m_proc, B3::Clz, origin(), operand);
264 }
265
266 LValue Output::doubleAbs(LValue value)
267 {
268     return m_block->appendNew<B3::Value>(m_proc, B3::Abs, origin(), value);
269 }
270
271 LValue Output::doubleCeil(LValue operand)
272 {
273     return m_block->appendNew<B3::Value>(m_proc, B3::Ceil, origin(), operand);
274 }
275
276 LValue Output::doubleFloor(LValue operand)
277 {
278     return m_block->appendNew<B3::Value>(m_proc, B3::Floor, origin(), operand);
279 }
280
281 LValue Output::doubleTrunc(LValue value)
282 {
283     if (MacroAssembler::supportsFloatingPointRounding()) {
284         PatchpointValue* result = patchpoint(Double);
285         result->append(value, ValueRep::SomeRegister);
286         result->setGenerator(
287             [] (CCallHelpers& jit, const StackmapGenerationParams& params) {
288                 jit.roundTowardZeroDouble(params[1].fpr(), params[0].fpr());
289             });
290         result->effects = Effects::none();
291         return result;
292     }
293     double (*truncDouble)(double) = trunc;
294     return callWithoutSideEffects(Double, truncDouble, value);
295 }
296
297 LValue Output::doubleUnary(DFG::Arith::UnaryType type, LValue value)
298 {
299     double (*unaryFunction)(double) = DFG::arithUnaryFunction(type);
300     return callWithoutSideEffects(B3::Double, unaryFunction, value);
301 }
302
303 LValue Output::doublePow(LValue xOperand, LValue yOperand)
304 {
305     double (*powDouble)(double, double) = pow;
306     return callWithoutSideEffects(B3::Double, powDouble, xOperand, yOperand);
307 }
308
309 LValue Output::doublePowi(LValue x, LValue y)
310 {
311     // FIXME: powDoubleInt32() should be inlined here since Output knows about block layout and
312     // should be involved in any operation that creates blocks.
313     // https://bugs.webkit.org/show_bug.cgi?id=152223
314     auto result = powDoubleInt32(m_proc, m_block, origin(), x, y);
315     m_block = result.first;
316     return result.second;
317 }
318
319 LValue Output::doubleSqrt(LValue value)
320 {
321     return m_block->appendNew<B3::Value>(m_proc, B3::Sqrt, origin(), value);
322 }
323
324 LValue Output::doubleToInt(LValue value)
325 {
326     PatchpointValue* result = patchpoint(Int32);
327     result->append(value, ValueRep::SomeRegister);
328     result->setGenerator(
329         [] (CCallHelpers& jit, const StackmapGenerationParams& params) {
330             jit.truncateDoubleToInt32(params[1].fpr(), params[0].gpr());
331         });
332     result->effects = Effects::none();
333     return result;
334 }
335
336 LValue Output::doubleToUInt(LValue value)
337 {
338     PatchpointValue* result = patchpoint(Int32);
339     result->append(value, ValueRep::SomeRegister);
340     result->setGenerator(
341         [] (CCallHelpers& jit, const StackmapGenerationParams& params) {
342             jit.truncateDoubleToUint32(params[1].fpr(), params[0].gpr());
343         });
344     result->effects = Effects::none();
345     return result;
346 }
347
348 LValue Output::signExt32To64(LValue value)
349 {
350     return m_block->appendNew<B3::Value>(m_proc, B3::SExt32, origin(), value);
351 }
352
353 LValue Output::signExt32ToPtr(LValue value)
354 {
355     return signExt32To64(value);
356 }
357
358 LValue Output::zeroExt(LValue value, LType type)
359 {
360     if (value->type() == type)
361         return value;
362     if (value->hasInt32())
363         return m_block->appendIntConstant(m_proc, origin(), Int64, static_cast<uint64_t>(static_cast<uint32_t>(value->asInt32())));
364     return m_block->appendNew<B3::Value>(m_proc, B3::ZExt32, origin(), value);
365 }
366
367 LValue Output::intToDouble(LValue value)
368 {
369     return m_block->appendNew<B3::Value>(m_proc, B3::IToD, origin(), value);
370 }
371
372 LValue Output::unsignedToDouble(LValue value)
373 {
374     return intToDouble(zeroExt(value, Int64));
375 }
376
377 LValue Output::castToInt32(LValue value)
378 {
379     if (value->type() == Int32)
380         return value;
381     if (value->hasInt64())
382         return constInt32(static_cast<int32_t>(value->asInt64()));
383     return m_block->appendNew<B3::Value>(m_proc, B3::Trunc, origin(), value);
384 }
385
386 LValue Output::doubleToFloat(LValue value)
387 {
388     return m_block->appendNew<B3::Value>(m_proc, B3::DoubleToFloat, origin(), value);
389 }
390
391 LValue Output::floatToDouble(LValue value)
392 {
393     return m_block->appendNew<B3::Value>(m_proc, B3::FloatToDouble, origin(), value);
394 }
395
396 LValue Output::load(TypedPointer pointer, LType type)
397 {
398     LValue load = m_block->appendNew<MemoryValue>(m_proc, Load, type, origin(), pointer.value());
399     m_heaps->decorateMemory(pointer.heap(), load);
400     return load;
401 }
402
403 LValue Output::load8SignExt32(TypedPointer pointer)
404 {
405     LValue load = m_block->appendNew<MemoryValue>(m_proc, Load8S, Int32, origin(), pointer.value());
406     m_heaps->decorateMemory(pointer.heap(), load);
407     return load;
408 }
409
410 LValue Output::load8ZeroExt32(TypedPointer pointer)
411 {
412     LValue load = m_block->appendNew<MemoryValue>(m_proc, Load8Z, Int32, origin(), pointer.value());
413     m_heaps->decorateMemory(pointer.heap(), load);
414     return load;
415 }
416
417 LValue Output::load16SignExt32(TypedPointer pointer)
418 {
419     LValue load = m_block->appendNew<MemoryValue>(m_proc, Load16S, Int32, origin(), pointer.value());
420     m_heaps->decorateMemory(pointer.heap(), load);
421     return load;
422 }
423
424 LValue Output::load16ZeroExt32(TypedPointer pointer)
425 {
426     LValue load = m_block->appendNew<MemoryValue>(m_proc, Load16Z, Int32, origin(), pointer.value());
427     m_heaps->decorateMemory(pointer.heap(), load);
428     return load;
429 }
430
431 LValue Output::store(LValue value, TypedPointer pointer)
432 {
433     LValue store = m_block->appendNew<MemoryValue>(m_proc, Store, origin(), value, pointer.value());
434     m_heaps->decorateMemory(pointer.heap(), store);
435     return store;
436 }
437
438 FenceValue* Output::fence(const AbstractHeap* read, const AbstractHeap* write)
439 {
440     FenceValue* result = m_block->appendNew<FenceValue>(m_proc, origin());
441     m_heaps->decorateFenceRead(read, result);
442     m_heaps->decorateFenceWrite(write, result);
443     return result;
444 }
445
446 LValue Output::store32As8(LValue value, TypedPointer pointer)
447 {
448     LValue store = m_block->appendNew<MemoryValue>(m_proc, Store8, origin(), value, pointer.value());
449     m_heaps->decorateMemory(pointer.heap(), store);
450     return store;
451 }
452
453 LValue Output::store32As16(LValue value, TypedPointer pointer)
454 {
455     LValue store = m_block->appendNew<MemoryValue>(m_proc, Store16, origin(), value, pointer.value());
456     m_heaps->decorateMemory(pointer.heap(), store);
457     return store;
458 }
459
460 LValue Output::baseIndex(LValue base, LValue index, Scale scale, ptrdiff_t offset)
461 {
462     LValue accumulatedOffset;
463         
464     switch (scale) {
465     case ScaleOne:
466         accumulatedOffset = index;
467         break;
468     case ScaleTwo:
469         accumulatedOffset = shl(index, intPtrOne);
470         break;
471     case ScaleFour:
472         accumulatedOffset = shl(index, intPtrTwo);
473         break;
474     case ScaleEight:
475     case ScalePtr:
476         accumulatedOffset = shl(index, intPtrThree);
477         break;
478     }
479         
480     if (offset)
481         accumulatedOffset = add(accumulatedOffset, constIntPtr(offset));
482         
483     return add(base, accumulatedOffset);
484 }
485
486 LValue Output::equal(LValue left, LValue right)
487 {
488     TriState result = left->equalConstant(right);
489     if (result != MixedTriState)
490         return constBool(result == TrueTriState);
491     return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), left, right);
492 }
493
494 LValue Output::notEqual(LValue left, LValue right)
495 {
496     TriState result = left->notEqualConstant(right);
497     if (result != MixedTriState)
498         return constBool(result == TrueTriState);
499     return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), left, right);
500 }
501
502 LValue Output::above(LValue left, LValue right)
503 {
504     TriState result = left->aboveConstant(right);
505     if (result != MixedTriState)
506         return constBool(result == TrueTriState);
507     return m_block->appendNew<B3::Value>(m_proc, B3::Above, origin(), left, right);
508 }
509
510 LValue Output::aboveOrEqual(LValue left, LValue right)
511 {
512     TriState result = left->aboveEqualConstant(right);
513     if (result != MixedTriState)
514         return constBool(result == TrueTriState);
515     return m_block->appendNew<B3::Value>(m_proc, B3::AboveEqual, origin(), left, right);
516 }
517
518 LValue Output::below(LValue left, LValue right)
519 {
520     TriState result = left->belowConstant(right);
521     if (result != MixedTriState)
522         return constBool(result == TrueTriState);
523     return m_block->appendNew<B3::Value>(m_proc, B3::Below, origin(), left, right);
524 }
525
526 LValue Output::belowOrEqual(LValue left, LValue right)
527 {
528     TriState result = left->belowEqualConstant(right);
529     if (result != MixedTriState)
530         return constBool(result == TrueTriState);
531     return m_block->appendNew<B3::Value>(m_proc, B3::BelowEqual, origin(), left, right);
532 }
533
534 LValue Output::greaterThan(LValue left, LValue right)
535 {
536     TriState result = left->greaterThanConstant(right);
537     if (result != MixedTriState)
538         return constBool(result == TrueTriState);
539     return m_block->appendNew<B3::Value>(m_proc, B3::GreaterThan, origin(), left, right);
540 }
541
542 LValue Output::greaterThanOrEqual(LValue left, LValue right)
543 {
544     TriState result = left->greaterEqualConstant(right);
545     if (result != MixedTriState)
546         return constBool(result == TrueTriState);
547     return m_block->appendNew<B3::Value>(m_proc, B3::GreaterEqual, origin(), left, right);
548 }
549
550 LValue Output::lessThan(LValue left, LValue right)
551 {
552     TriState result = left->lessThanConstant(right);
553     if (result != MixedTriState)
554         return constBool(result == TrueTriState);
555     return m_block->appendNew<B3::Value>(m_proc, B3::LessThan, origin(), left, right);
556 }
557
558 LValue Output::lessThanOrEqual(LValue left, LValue right)
559 {
560     TriState result = left->lessEqualConstant(right);
561     if (result != MixedTriState)
562         return constBool(result == TrueTriState);
563     return m_block->appendNew<B3::Value>(m_proc, B3::LessEqual, origin(), left, right);
564 }
565
566 LValue Output::doubleEqual(LValue left, LValue right)
567 {
568     return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), left, right);
569 }
570
571 LValue Output::doubleEqualOrUnordered(LValue left, LValue right)
572 {
573     return m_block->appendNew<B3::Value>(m_proc, B3::EqualOrUnordered, origin(), left, right);
574 }
575
576 LValue Output::doubleNotEqualOrUnordered(LValue left, LValue right)
577 {
578     return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), left, right);
579 }
580
581 LValue Output::doubleLessThan(LValue left, LValue right)
582 {
583     return m_block->appendNew<B3::Value>(m_proc, B3::LessThan, origin(), left, right);
584 }
585
586 LValue Output::doubleLessThanOrEqual(LValue left, LValue right)
587 {
588     return m_block->appendNew<B3::Value>(m_proc, B3::LessEqual, origin(), left, right);
589 }
590
591 LValue Output::doubleGreaterThan(LValue left, LValue right)
592 {
593     return m_block->appendNew<B3::Value>(m_proc, B3::GreaterThan, origin(), left, right);
594 }
595
596 LValue Output::doubleGreaterThanOrEqual(LValue left, LValue right)
597 {
598     return m_block->appendNew<B3::Value>(m_proc, B3::GreaterEqual, origin(), left, right);
599 }
600
601 LValue Output::doubleNotEqualAndOrdered(LValue left, LValue right)
602 {
603     return logicalNot(doubleEqualOrUnordered(left, right));
604 }
605
606 LValue Output::doubleLessThanOrUnordered(LValue left, LValue right)
607 {
608     return logicalNot(doubleGreaterThanOrEqual(left, right));
609 }
610
611 LValue Output::doubleLessThanOrEqualOrUnordered(LValue left, LValue right)
612 {
613     return logicalNot(doubleGreaterThan(left, right));
614 }
615
616 LValue Output::doubleGreaterThanOrUnordered(LValue left, LValue right)
617 {
618     return logicalNot(doubleLessThanOrEqual(left, right));
619 }
620
621 LValue Output::doubleGreaterThanOrEqualOrUnordered(LValue left, LValue right)
622 {
623     return logicalNot(doubleLessThan(left, right));
624 }
625
626 LValue Output::isZero32(LValue value)
627 {
628     return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), value, int32Zero);
629 }
630
631 LValue Output::notZero32(LValue value)
632 {
633     return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), value, int32Zero);
634 }
635
636 LValue Output::isZero64(LValue value)
637 {
638     return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), value, int64Zero);
639 }
640
641 LValue Output::notZero64(LValue value)
642 {
643     return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), value, int64Zero);
644 }
645
646 LValue Output::select(LValue value, LValue taken, LValue notTaken)
647 {
648     if (value->hasInt32()) {
649         if (value->asInt32())
650             return taken;
651         else
652             return notTaken;
653     }
654     return m_block->appendNew<B3::Value>(m_proc, B3::Select, origin(), value, taken, notTaken);
655 }
656
657 LValue Output::atomicXchgAdd(LValue operand, TypedPointer pointer, Width width)
658 {
659     LValue result = m_block->appendNew<AtomicValue>(m_proc, AtomicXchgAdd, origin(), width, operand, pointer.value(), 0, HeapRange(), HeapRange());
660     m_heaps->decorateMemory(pointer.heap(), result);
661     return result;
662 }
663
664 LValue Output::atomicXchgAnd(LValue operand, TypedPointer pointer, Width width)
665 {
666     LValue result = m_block->appendNew<AtomicValue>(m_proc, AtomicXchgAnd, origin(), width, operand, pointer.value(), 0, HeapRange(), HeapRange());
667     m_heaps->decorateMemory(pointer.heap(), result);
668     return result;
669 }
670
671 LValue Output::atomicXchgOr(LValue operand, TypedPointer pointer, Width width)
672 {
673     LValue result = m_block->appendNew<AtomicValue>(m_proc, AtomicXchgOr, origin(), width, operand, pointer.value(), 0, HeapRange(), HeapRange());
674     m_heaps->decorateMemory(pointer.heap(), result);
675     return result;
676 }
677
678 LValue Output::atomicXchgSub(LValue operand, TypedPointer pointer, Width width)
679 {
680     LValue result = m_block->appendNew<AtomicValue>(m_proc, AtomicXchgSub, origin(), width, operand, pointer.value(), 0, HeapRange(), HeapRange());
681     m_heaps->decorateMemory(pointer.heap(), result);
682     return result;
683 }
684
685 LValue Output::atomicXchgXor(LValue operand, TypedPointer pointer, Width width)
686 {
687     LValue result = m_block->appendNew<AtomicValue>(m_proc, AtomicXchgXor, origin(), width, operand, pointer.value(), 0, HeapRange(), HeapRange());
688     m_heaps->decorateMemory(pointer.heap(), result);
689     return result;
690 }
691
692 LValue Output::atomicXchg(LValue operand, TypedPointer pointer, Width width)
693 {
694     LValue result = m_block->appendNew<AtomicValue>(m_proc, AtomicXchg, origin(), width, operand, pointer.value(), 0, HeapRange(), HeapRange());
695     m_heaps->decorateMemory(pointer.heap(), result);
696     return result;
697 }
698
699 LValue Output::atomicStrongCAS(LValue expected, LValue newValue, TypedPointer pointer, Width width)
700 {
701     LValue result = m_block->appendNew<AtomicValue>(m_proc, AtomicStrongCAS, origin(), width, expected, newValue, pointer.value(), 0, HeapRange(), HeapRange());
702     m_heaps->decorateMemory(pointer.heap(), result);
703     return result;
704 }
705
706 void Output::jump(LBasicBlock destination)
707 {
708     m_block->appendNewControlValue(m_proc, B3::Jump, origin(), B3::FrequentedBlock(destination));
709 }
710
711 void Output::branch(LValue condition, LBasicBlock taken, Weight takenWeight, LBasicBlock notTaken, Weight notTakenWeight)
712 {
713     m_block->appendNewControlValue(
714         m_proc, B3::Branch, origin(), condition,
715         FrequentedBlock(taken, takenWeight.frequencyClass()),
716         FrequentedBlock(notTaken, notTakenWeight.frequencyClass()));
717 }
718
719 void Output::check(LValue condition, WeightedTarget taken, Weight notTakenWeight)
720 {
721     LBasicBlock continuation = newBlock();
722     branch(condition, taken, WeightedTarget(continuation, notTakenWeight));
723     appendTo(continuation);
724 }
725
726 void Output::check(LValue condition, WeightedTarget taken)
727 {
728     check(condition, taken, taken.weight().inverse());
729 }
730
731 void Output::ret(LValue value)
732 {
733     m_block->appendNewControlValue(m_proc, B3::Return, origin(), value);
734 }
735
736 void Output::unreachable()
737 {
738     m_block->appendNewControlValue(m_proc, B3::Oops, origin());
739 }
740
741 void Output::appendSuccessor(WeightedTarget target)
742 {
743     m_block->appendSuccessor(target.frequentedBlock());
744 }
745
746 CheckValue* Output::speculate(LValue value)
747 {
748     return m_block->appendNew<B3::CheckValue>(m_proc, B3::Check, origin(), value);
749 }
750
751 CheckValue* Output::speculateAdd(LValue left, LValue right)
752 {
753     return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckAdd, origin(), left, right);
754 }
755
756 CheckValue* Output::speculateSub(LValue left, LValue right)
757 {
758     return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckSub, origin(), left, right);
759 }
760
761 CheckValue* Output::speculateMul(LValue left, LValue right)
762 {
763     return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckMul, origin(), left, right);
764 }
765
766 PatchpointValue* Output::patchpoint(LType type)
767 {
768     return m_block->appendNew<B3::PatchpointValue>(m_proc, type, origin());
769 }
770
771 void Output::trap()
772 {
773     m_block->appendNewControlValue(m_proc, B3::Oops, origin());
774 }
775
776 ValueFromBlock Output::anchor(LValue value)
777 {
778     B3::UpsilonValue* upsilon = m_block->appendNew<B3::UpsilonValue>(m_proc, origin(), value);
779     return ValueFromBlock(upsilon, m_block);
780 }
781
782 LValue Output::bitCast(LValue value, LType type)
783 {
784     ASSERT_UNUSED(type, type == Int64 || type == Double);
785     return m_block->appendNew<B3::Value>(m_proc, B3::BitwiseCast, origin(), value);
786 }
787
788 LValue Output::fround(LValue doubleValue)
789 {
790     return floatToDouble(doubleToFloat(doubleValue));
791 }
792
793 LValue Output::load(TypedPointer pointer, LoadType type)
794 {
795     switch (type) {
796     case Load8SignExt32:
797         return load8SignExt32(pointer);
798     case Load8ZeroExt32:
799         return load8ZeroExt32(pointer);
800     case Load16SignExt32:
801         return load8SignExt32(pointer);
802     case Load16ZeroExt32:
803         return load8ZeroExt32(pointer);
804     case Load32:
805         return load32(pointer);
806     case Load64:
807         return load64(pointer);
808     case LoadPtr:
809         return loadPtr(pointer);
810     case LoadFloat:
811         return loadFloat(pointer);
812     case LoadDouble:
813         return loadDouble(pointer);
814     }
815     RELEASE_ASSERT_NOT_REACHED();
816     return nullptr;
817 }
818
819 LValue Output::store(LValue value, TypedPointer pointer, StoreType type)
820 {
821     switch (type) {
822     case Store32As8:
823         return store32As8(value, pointer);
824     case Store32As16:
825         return store32As16(value, pointer);
826     case Store32:
827         return store32(value, pointer);
828     case Store64:
829         return store64(value, pointer);
830     case StorePtr:
831         return storePtr(value, pointer);
832     case StoreFloat:
833         return storeFloat(value, pointer);
834     case StoreDouble:
835         return storeDouble(value, pointer);
836     }
837     RELEASE_ASSERT_NOT_REACHED();
838     return nullptr;
839 }
840
841 TypedPointer Output::absolute(const void* address)
842 {
843     return TypedPointer(m_heaps->absolute[address], constIntPtr(address));
844 }
845
846 void Output::incrementSuperSamplerCount()
847 {
848     TypedPointer counter = absolute(bitwise_cast<void*>(&g_superSamplerCount));
849     store32(add(load32(counter), int32One), counter);
850 }
851
852 void Output::decrementSuperSamplerCount()
853 {
854     TypedPointer counter = absolute(bitwise_cast<void*>(&g_superSamplerCount));
855     store32(sub(load32(counter), int32One), counter);
856 }
857
858 void Output::addIncomingToPhi(LValue phi, ValueFromBlock value)
859 {
860     if (value)
861         value.value()->as<B3::UpsilonValue>()->setPhi(phi);
862 }
863
864 void Output::entrySwitch(const Vector<LBasicBlock>& cases)
865 {
866     RELEASE_ASSERT(cases.size() == m_proc.numEntrypoints());
867     m_block->appendNew<Value>(m_proc, EntrySwitch, origin());
868     for (LBasicBlock block : cases)
869         m_block->appendSuccessor(FrequentedBlock(block));
870 }
871
872 } } // namespace JSC::FTL
873
874 #endif // ENABLE(FTL_JIT)
875