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
47namespace JSC { namespace FTL {
48
49using namespace B3;
50
51Output::Output(State& state)
52 : m_proc(*state.proc)
53{
54}
55
56Output::~Output()
57{
58}
59
60void Output::initialize(AbstractHeapRepository& heaps)
61{
62 m_heaps = &heaps;
63}
64
65LBasicBlock 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
77void Output::applyBlockOrder()
78{
79 m_proc.setBlockOrder(m_blockOrder);
80}
81
82LBasicBlock Output::appendTo(LBasicBlock block, LBasicBlock nextBlock)
83{
84 appendTo(block);
85 return insertNewBlocksBefore(nextBlock);
86}
87
88void Output::appendTo(LBasicBlock block)
89{
90 m_block = block;
91}
92
93LValue Output::framePointer()
94{
95 return m_block->appendNew<B3::Value>(m_proc, B3::FramePointer, origin());
96}
97
98SlotBaseValue* Output::lockedStackSlot(size_t bytes)
99{
100 return m_block->appendNew<SlotBaseValue>(m_proc, origin(), m_proc.addStackSlot(bytes));
101}
102
103LValue Output::constBool(bool value)
104{
105 if (value)
106 return booleanTrue;
107 return booleanFalse;
108}
109
110LValue Output::constInt32(int32_t value)
111{
112 return m_block->appendNew<B3::Const32Value>(m_proc, origin(), value);
113}
114
115LValue Output::constInt64(int64_t value)
116{
117 return m_block->appendNew<B3::Const64Value>(m_proc, origin(), value);
118}
119
120LValue Output::constDouble(double value)
121{
122 return m_block->appendNew<B3::ConstDoubleValue>(m_proc, origin(), value);
123}
124
125LValue Output::phi(LType type)
126{
127 return m_block->appendNew<B3::Value>(m_proc, B3::Phi, type, origin());
128}
129
130LValue Output::opaque(LValue value)
131{
132 return m_block->appendNew<Value>(m_proc, Opaque, origin(), value);
133}
134
135LValue 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
144LValue Output::sub(LValue left, LValue right)
145{
146 return m_block->appendNew<B3::Value>(m_proc, B3::Sub, origin(), left, right);
147}
148
149LValue Output::mul(LValue left, LValue right)
150{
151 return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right);
152}
153
154LValue Output::div(LValue left, LValue right)
155{
156 return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right);
157}
158
159LValue Output::chillDiv(LValue left, LValue right)
160{
161 return m_block->appendNew<B3::Value>(m_proc, chill(B3::Div), origin(), left, right);
162}
163
164LValue Output::mod(LValue left, LValue right)
165{
166 return m_block->appendNew<B3::Value>(m_proc, B3::Mod, origin(), left, right);
167}
168
169LValue Output::chillMod(LValue left, LValue right)
170{
171 return m_block->appendNew<B3::Value>(m_proc, chill(B3::Mod), origin(), left, right);
172}
173
174LValue Output::neg(LValue value)
175{
176 return m_block->appendNew<Value>(m_proc, B3::Neg, origin(), value);
177}
178
179LValue Output::doubleAdd(LValue left, LValue right)
180{
181 return m_block->appendNew<B3::Value>(m_proc, B3::Add, origin(), left, right);
182}
183
184LValue Output::doubleSub(LValue left, LValue right)
185{
186 return m_block->appendNew<B3::Value>(m_proc, B3::Sub, origin(), left, right);
187}
188
189LValue Output::doubleMul(LValue left, LValue right)
190{
191 return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right);
192}
193
194LValue Output::doubleDiv(LValue left, LValue right)
195{
196 return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right);
197}
198
199LValue Output::doubleMod(LValue left, LValue right)
200{
201 return m_block->appendNew<B3::Value>(m_proc, B3::Mod, origin(), left, right);
202}
203
204LValue Output::bitAnd(LValue left, LValue right)
205{
206 return m_block->appendNew<B3::Value>(m_proc, B3::BitAnd, origin(), left, right);
207}
208
209LValue Output::bitOr(LValue left, LValue right)
210{
211 return m_block->appendNew<B3::Value>(m_proc, B3::BitOr, origin(), left, right);
212}
213
214LValue Output::bitXor(LValue left, LValue right)
215{
216 return m_block->appendNew<B3::Value>(m_proc, B3::BitXor, origin(), left, right);
217}
218
219LValue 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
229LValue 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
239LValue 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
249LValue 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
256LValue Output::logicalNot(LValue value)
257{
258 return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), value, int32Zero);
259}
260
261LValue Output::ctlz32(LValue operand)
262{
263 return m_block->appendNew<B3::Value>(m_proc, B3::Clz, origin(), operand);
264}
265
266LValue Output::doubleAbs(LValue value)
267{
268 return m_block->appendNew<B3::Value>(m_proc, B3::Abs, origin(), value);
269}
270
271LValue Output::doubleCeil(LValue operand)
272{
273 return m_block->appendNew<B3::Value>(m_proc, B3::Ceil, origin(), operand);
274}
275
276LValue Output::doubleFloor(LValue operand)
277{
278 return m_block->appendNew<B3::Value>(m_proc, B3::Floor, origin(), operand);
279}
280
281LValue 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
297LValue 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
303LValue Output::doublePow(LValue xOperand, LValue yOperand)
304{
305 double (*powDouble)(double, double) = pow;
306 return callWithoutSideEffects(B3::Double, powDouble, xOperand, yOperand);
307}
308
309LValue 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
319LValue Output::doubleSqrt(LValue value)
320{
321 return m_block->appendNew<B3::Value>(m_proc, B3::Sqrt, origin(), value);
322}
323
324LValue 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
336LValue 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
348LValue Output::signExt32To64(LValue value)
349{
350 return m_block->appendNew<B3::Value>(m_proc, B3::SExt32, origin(), value);
351}
352
353LValue Output::signExt32ToPtr(LValue value)
354{
355 return signExt32To64(value);
356}
357
358LValue 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
367LValue Output::intToDouble(LValue value)
368{
369 return m_block->appendNew<B3::Value>(m_proc, B3::IToD, origin(), value);
370}
371
372LValue Output::unsignedToDouble(LValue value)
373{
374 return intToDouble(zeroExt(value, Int64));
375}
376
377LValue 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
386LValue Output::doubleToFloat(LValue value)
387{
388 return m_block->appendNew<B3::Value>(m_proc, B3::DoubleToFloat, origin(), value);
389}
390
391LValue Output::floatToDouble(LValue value)
392{
393 return m_block->appendNew<B3::Value>(m_proc, B3::FloatToDouble, origin(), value);
394}
395
396LValue 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
403LValue 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
410LValue 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
417LValue 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
424LValue 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
431LValue 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
438FenceValue* 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
446LValue 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
453LValue 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
460LValue 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
486LValue 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
494LValue 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
502LValue 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
510LValue 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
518LValue 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
526LValue 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
534LValue 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
542LValue 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
550LValue 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
558LValue 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
566LValue Output::doubleEqual(LValue left, LValue right)
567{
568 return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), left, right);
569}
570
571LValue Output::doubleEqualOrUnordered(LValue left, LValue right)
572{
573 return m_block->appendNew<B3::Value>(m_proc, B3::EqualOrUnordered, origin(), left, right);
574}
575
576LValue Output::doubleNotEqualOrUnordered(LValue left, LValue right)
577{
578 return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), left, right);
579}
580
581LValue Output::doubleLessThan(LValue left, LValue right)
582{
583 return m_block->appendNew<B3::Value>(m_proc, B3::LessThan, origin(), left, right);
584}
585
586LValue Output::doubleLessThanOrEqual(LValue left, LValue right)
587{
588 return m_block->appendNew<B3::Value>(m_proc, B3::LessEqual, origin(), left, right);
589}
590
591LValue Output::doubleGreaterThan(LValue left, LValue right)
592{
593 return m_block->appendNew<B3::Value>(m_proc, B3::GreaterThan, origin(), left, right);
594}
595
596LValue Output::doubleGreaterThanOrEqual(LValue left, LValue right)
597{
598 return m_block->appendNew<B3::Value>(m_proc, B3::GreaterEqual, origin(), left, right);
599}
600
601LValue Output::doubleNotEqualAndOrdered(LValue left, LValue right)
602{
603 return logicalNot(doubleEqualOrUnordered(left, right));
604}
605
606LValue Output::doubleLessThanOrUnordered(LValue left, LValue right)
607{
608 return logicalNot(doubleGreaterThanOrEqual(left, right));
609}
610
611LValue Output::doubleLessThanOrEqualOrUnordered(LValue left, LValue right)
612{
613 return logicalNot(doubleGreaterThan(left, right));
614}
615
616LValue Output::doubleGreaterThanOrUnordered(LValue left, LValue right)
617{
618 return logicalNot(doubleLessThanOrEqual(left, right));
619}
620
621LValue Output::doubleGreaterThanOrEqualOrUnordered(LValue left, LValue right)
622{
623 return logicalNot(doubleLessThan(left, right));
624}
625
626LValue Output::isZero32(LValue value)
627{
628 return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), value, int32Zero);
629}
630
631LValue Output::notZero32(LValue value)
632{
633 return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), value, int32Zero);
634}
635
636LValue Output::isZero64(LValue value)
637{
638 return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), value, int64Zero);
639}
640
641LValue Output::notZero64(LValue value)
642{
643 return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), value, int64Zero);
644}
645
646LValue 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
657LValue 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
664LValue 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
671LValue 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
678LValue 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
685LValue 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
692LValue 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
699LValue 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
706void Output::jump(LBasicBlock destination)
707{
708 m_block->appendNewControlValue(m_proc, B3::Jump, origin(), B3::FrequentedBlock(destination));
709}
710
711void 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
719void 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
726void Output::check(LValue condition, WeightedTarget taken)
727{
728 check(condition, taken, taken.weight().inverse());
729}
730
731void Output::ret(LValue value)
732{
733 m_block->appendNewControlValue(m_proc, B3::Return, origin(), value);
734}
735
736void Output::unreachable()
737{
738 m_block->appendNewControlValue(m_proc, B3::Oops, origin());
739}
740
741void Output::appendSuccessor(WeightedTarget target)
742{
743 m_block->appendSuccessor(target.frequentedBlock());
744}
745
746CheckValue* Output::speculate(LValue value)
747{
748 return m_block->appendNew<B3::CheckValue>(m_proc, B3::Check, origin(), value);
749}
750
751CheckValue* Output::speculateAdd(LValue left, LValue right)
752{
753 return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckAdd, origin(), left, right);
754}
755
756CheckValue* Output::speculateSub(LValue left, LValue right)
757{
758 return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckSub, origin(), left, right);
759}
760
761CheckValue* Output::speculateMul(LValue left, LValue right)
762{
763 return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckMul, origin(), left, right);
764}
765
766PatchpointValue* Output::patchpoint(LType type)
767{
768 return m_block->appendNew<B3::PatchpointValue>(m_proc, type, origin());
769}
770
771void Output::trap()
772{
773 m_block->appendNewControlValue(m_proc, B3::Oops, origin());
774}
775
776ValueFromBlock 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
782LValue 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
788LValue Output::fround(LValue doubleValue)
789{
790 return floatToDouble(doubleToFloat(doubleValue));
791}
792
793LValue 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
819LValue 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
841TypedPointer Output::absolute(const void* address)
842{
843 return TypedPointer(m_heaps->absolute[address], constIntPtr(address));
844}
845
846void Output::incrementSuperSamplerCount()
847{
848 TypedPointer counter = absolute(bitwise_cast<void*>(&g_superSamplerCount));
849 store32(add(load32(counter), int32One), counter);
850}
851
852void Output::decrementSuperSamplerCount()
853{
854 TypedPointer counter = absolute(bitwise_cast<void*>(&g_superSamplerCount));
855 store32(sub(load32(counter), int32One), counter);
856}
857
858void Output::addIncomingToPhi(LValue phi, ValueFromBlock value)
859{
860 if (value)
861 value.value()->as<B3::UpsilonValue>()->setPhi(phi);
862}
863
864void 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
876