55bool IsValidSmi(intptr_t c) {
57 if (!
IsSmi(as_obj))
return false;
70 using AssemblerT = TSAssembler<ExplicitTruncationReducer, VariableReducer>;
77 GraphBuilder(PipelineData* data,
Zone* phase_zone, Schedule& schedule,
82 isolate(data->isolate()),
85 assembler(data, data->graph(), data->graph(),
phase_zone),
99 std::optional<BailoutReason> Run();
100 AssemblerT& Asm() {
return assembler; }
103 template <
typename T>
116 Block*
Map(BasicBlock* block) {
122 void FixLoopPhis(BasicBlock* loop) {
123 DCHECK(loop->IsLoopHeader());
124 for (Node* node : *loop->nodes()) {
125 if (node->opcode() != IrOpcode::kPhi) {
129 PendingLoopPhiOp& pending_phi =
130 __ output_graph().Get(phi_index).Cast<PendingLoopPhiOp>();
131 __ output_graph().Replace<PhiOp>(
138 void ProcessDeoptInput(FrameStateData::Builder* builder, Node* input,
140 DCHECK_NE(input->opcode(), IrOpcode::kObjectState);
141 DCHECK_NE(input->opcode(), IrOpcode::kStateValues);
142 DCHECK_NE(input->opcode(), IrOpcode::kTypedStateValues);
143 if (input->opcode() == IrOpcode::kObjectId) {
144 builder->AddDematerializedObjectReference(
ObjectIdOf(input->op()));
145 }
else if (input->opcode() == IrOpcode::kTypedObjectState) {
146 const TypedObjectStateInfo& info =
148 int field_count = input->op()->ValueInputCount();
149 builder->AddDematerializedObject(info.object_id(),
150 static_cast<uint32_t
>(field_count));
151 for (
int i = 0;
i < field_count; ++
i) {
152 ProcessDeoptInput(builder, input->InputAt(
i),
153 (*info.machine_types())[
i]);
155 }
else if (input->opcode() == IrOpcode::kArgumentsElementsState) {
157 }
else if (input->opcode() == IrOpcode::kArgumentsLengthState) {
158 builder->AddArgumentsLength();
160 builder->AddInput(type,
Map(input));
164 void ProcessStateValues(FrameStateData::Builder* builder,
165 Node* state_values) {
166 for (
auto it = StateValuesAccess(state_values).
begin(); !it.done(); ++it) {
167 if (Node* node = it.node()) {
168 ProcessDeoptInput(builder, node, (*it).type);
170 builder->AddUnusedRegister();
175 void BuildFrameStateData(FrameStateData::Builder* builder,
176 compiler::FrameState frame_state) {
177 if (frame_state.outer_frame_state()->opcode() != IrOpcode::kStart) {
178 builder->AddParentFrameState(
Map(frame_state.outer_frame_state()));
180 ProcessDeoptInput(builder, frame_state.function(),
182 ProcessStateValues(builder, frame_state.parameters());
184 ProcessStateValues(builder, frame_state.locals());
185 Node* stack = frame_state.stack();
186 ProcessStateValues(builder, stack);
190 switch (block->front()->opcode()) {
191 case IrOpcode::kStart:
193 case IrOpcode::kMerge:
195 case IrOpcode::kIfTrue:
196 case IrOpcode::kIfFalse:
197 case IrOpcode::kIfValue:
198 case IrOpcode::kIfDefault:
199 case IrOpcode::kIfSuccess:
200 case IrOpcode::kIfException:
202 case IrOpcode::kLoop:
205 block->front()->Print();
209 OpIndex Process(Node* node, BasicBlock* block,
210 const base::SmallVector<int, 16>& predecessor_permutation,
211 OpIndex& dominating_frame_state,
212 std::optional<BailoutReason>* bailout,
213 bool is_final_control =
false);
216std::optional<BailoutReason> GraphBuilder::Run() {
217 for (BasicBlock* block : *
schedule.rpo_order()) {
219 block->IsLoopHeader() ?
__ NewLoopHeader() :
__ NewBlock();
222 for (BasicBlock* block : *
schedule.rpo_order()) {
223 Block* target_block =
Map(block);
224 if (!
__ Bind(target_block))
continue;
231 base::SmallVector<int, 16> predecessor_permutation(predecessors.size());
232 std::iota(predecessor_permutation.begin(), predecessor_permutation.end(),
234 std::sort(predecessor_permutation.begin(), predecessor_permutation.end(),
235 [&](
size_t i,
size_t j) {
236 return predecessors[i]->rpo_number() <
237 predecessors[j]->rpo_number();
240 OpIndex dominating_frame_state = OpIndex::Invalid();
241 if (!predecessors.empty()) {
242 dominating_frame_state =
243 block_mapping[predecessors[0]->rpo_number()].final_frame_state;
244 for (
size_t i = 1;
i < predecessors.
size(); ++
i) {
246 dominating_frame_state) {
247 dominating_frame_state = OpIndex::Invalid();
252 std::optional<BailoutReason> bailout = std::nullopt;
253 for (Node* node : *block->nodes()) {
255 int{std::numeric_limits<
256 decltype(Operation::input_count)>::max()})) {
257 return BailoutReason::kTooManyArguments;
259 OpIndex i = Process(node, block, predecessor_permutation,
260 dominating_frame_state, &bailout);
262 if (!
__ current_block())
break;
267 if (!
__ current_block())
continue;
269 if (Node* node = block->control_input()) {
271 int{std::numeric_limits<
272 decltype(Operation::input_count)>::max()})) {
273 return BailoutReason::kTooManyArguments;
275 OpIndex i = Process(node, block, predecessor_permutation,
276 dominating_frame_state, &bailout,
true);
280 switch (block->control()) {
281 case BasicBlock::kGoto: {
287 FixLoopPhis(block->SuccessorAt(0));
291 case BasicBlock::kBranch:
292 case BasicBlock::kSwitch:
293 case BasicBlock::kReturn:
294 case BasicBlock::kDeoptimize:
295 case BasicBlock::kThrow:
296 case BasicBlock::kCall:
297 case BasicBlock::kTailCall:
299 case BasicBlock::kNone:
305 dominating_frame_state;
309 for (OpIndex index :
__ output_graph().AllOperationIndices()) {
310 compiler::NodeId origin =
311 __ output_graph().operation_origins()[
index].DecodeTurbofanNodeId();
312 __ output_graph().source_positions()[
index] =
318 for (OpIndex index :
__ output_graph().AllOperationIndices()) {
320 origins->SetNodeOrigin(index.id(), origin.DecodeTurbofanNodeId());
328 Node* node, BasicBlock* block,
329 const base::SmallVector<int, 16>& predecessor_permutation,
330 OpIndex& dominating_frame_state, std::optional<BailoutReason>* bailout,
331 bool is_final_control) {
332 if (Asm().current_block() ==
nullptr) {
333 return OpIndex::Invalid();
335 __ SetCurrentOrigin(OpIndex::EncodeTurbofanNodeId(node->id()));
336 const Operator* op = node->op();
337 Operator::Opcode opcode = op->opcode();
339 case IrOpcode::kStart:
340 case IrOpcode::kMerge:
341 case IrOpcode::kLoop:
342 case IrOpcode::kIfTrue:
343 case IrOpcode::kIfFalse:
344 case IrOpcode::kIfDefault:
345 case IrOpcode::kIfValue:
346 case IrOpcode::kStateValues:
347 case IrOpcode::kTypedStateValues:
348 case IrOpcode::kObjectId:
349 case IrOpcode::kTypedObjectState:
350 case IrOpcode::kArgumentsElementsState:
351 case IrOpcode::kArgumentsLengthState:
352 case IrOpcode::kEffectPhi:
353 case IrOpcode::kTerminate:
354 return OpIndex::Invalid();
356 case IrOpcode::kCheckpoint: {
358 dominating_frame_state =
Map(NodeProperties::GetFrameStateInput(node));
359 return OpIndex::Invalid();
362 case IrOpcode::kIfException: {
363 return __ CatchBlockBegin();
366 case IrOpcode::kIfSuccess: {
367 return OpIndex::Invalid();
370 case IrOpcode::kParameter: {
372 RegisterRepresentation rep =
373 RegisterRepresentation::FromMachineRepresentation(
376 return __ Parameter(info.index(), rep, info.debug_name());
379 case IrOpcode::kOsrValue: {
383 case IrOpcode::kPhi: {
385 RegisterRepresentation rep =
386 RegisterRepresentation::FromMachineRepresentation(
388 if (
__ current_block()->IsLoop()) {
390 return __ PendingLoopPhi(
Map(node->InputAt(0)), rep);
392 base::SmallVector<OpIndex, 16> inputs;
396 Block* pred =
Map(block->PredecessorAt(predecessor_permutation[
i]));
397 if (!pred->IsBound() ||
398 pred->LastOperation(
__ output_graph()).Is<UnreachableOp>()) {
401 inputs.push_back(
Map(node->InputAt(predecessor_permutation[
i])));
403 return __ Phi(base::VectorOf(inputs), rep);
407 case IrOpcode::kInt64Constant:
408 return __ Word64Constant(
static_cast<uint64_t
>(OpParameter<int64_t>(op)));
409 case IrOpcode::kInt32Constant:
410 return __ Word32Constant(
static_cast<uint32_t
>(OpParameter<int32_t>(op)));
411 case IrOpcode::kFloat64Constant:
412 return __ Float64Constant(OpParameter<double>(op));
413 case IrOpcode::kFloat32Constant:
414 return __ Float32Constant(OpParameter<float>(op));
415 case IrOpcode::kNumberConstant:
417 case IrOpcode::kTaggedIndexConstant:
418 return __ TaggedIndexConstant(OpParameter<int32_t>(op));
419 case IrOpcode::kHeapConstant:
421 case IrOpcode::kCompressedHeapConstant:
423 case IrOpcode::kTrustedHeapConstant:
425 case IrOpcode::kExternalConstant:
426 return __ ExternalConstant(OpParameter<ExternalReference>(op));
427 case IrOpcode::kRelocatableInt64Constant:
428 return __ RelocatableConstant(
429 OpParameter<RelocatablePtrConstantInfo>(op).
value(),
430 OpParameter<RelocatablePtrConstantInfo>(op).rmode());
431#define BINOP_CASE(opcode, assembler_op) \
432 case IrOpcode::k##opcode: \
433 return __ assembler_op(Map(node->InputAt(0)), Map(node->InputAt(1)));
455 BINOP_CASE(Int32MulHigh, Int32MulOverflownBits)
456 BINOP_CASE(Int64MulHigh, Int64MulOverflownBits)
457 BINOP_CASE(Uint32MulHigh, Uint32MulOverflownBits)
458 BINOP_CASE(Uint64MulHigh, Uint64MulOverflownBits)
476 BINOP_CASE(Word32Shr, Word32ShiftRightLogical)
477 BINOP_CASE(Word64Shr, Word64ShiftRightLogical)
498 BINOP_CASE(Int32LessThanOrEqual, Int32LessThanOrEqual)
499 BINOP_CASE(Int64LessThanOrEqual, Int64LessThanOrEqual)
500 BINOP_CASE(Uint32LessThanOrEqual, Uint32LessThanOrEqual)
501 BINOP_CASE(Uint64LessThanOrEqual, Uint64LessThanOrEqual)
502 BINOP_CASE(Float32LessThanOrEqual, Float32LessThanOrEqual)
503 BINOP_CASE(Float64LessThanOrEqual, Float64LessThanOrEqual)
505 BINOP_CASE(Int32AddWithOverflow, Int32AddCheckOverflow)
506 BINOP_CASE(Int64AddWithOverflow, Int64AddCheckOverflow)
507 BINOP_CASE(Int32MulWithOverflow, Int32MulCheckOverflow)
508 BINOP_CASE(Int64MulWithOverflow, Int64MulCheckOverflow)
509 BINOP_CASE(Int32SubWithOverflow, Int32SubCheckOverflow)
510 BINOP_CASE(Int64SubWithOverflow, Int64SubCheckOverflow)
513 case IrOpcode::kWord32Equal: {
520 const bool left_is_tagged =
521 __ output_graph().Get(left).outputs_rep().at(0) ==
522 RegisterRepresentation::Tagged();
523 const bool right_is_tagged =
524 __ output_graph().Get(right).outputs_rep().at(0) ==
525 RegisterRepresentation::Tagged();
526 if (left_is_tagged && right_is_tagged) {
527 return __ TaggedEqual(V<Object>::Cast(left),
528 V<Object>::Cast(right));
529 }
else if (left_is_tagged) {
531 __ TruncateWordPtrToWord32(
532 __ BitcastTaggedToWordPtr(V<Object>::Cast(left))),
533 V<Word32>::Cast(right));
534 }
else if (right_is_tagged) {
536 V<Word32>::Cast(left),
537 __ TruncateWordPtrToWord32(
538 __ BitcastTaggedToWordPtr(V<Object>::Cast(right))));
542 return __ Word32Equal(V<Word32>::Cast(left), V<Word32>::Cast(right));
545 case IrOpcode::kWord64Equal: {
552 const bool left_is_tagged =
553 __ output_graph().Get(left).outputs_rep().at(0) ==
554 RegisterRepresentation::Tagged();
555 const bool right_is_tagged =
556 __ output_graph().Get(right).outputs_rep().at(0) ==
557 RegisterRepresentation::Tagged();
558 if (left_is_tagged && right_is_tagged) {
559 return __ TaggedEqual(V<Object>::Cast(left),
560 V<Object>::Cast(right));
561 }
else if (left_is_tagged) {
562 DCHECK((std::is_same_v<WordPtr, Word64>));
563 return __ Word64Equal(V<Word64>::Cast(
__ BitcastTaggedToWordPtr(
564 V<Object>::Cast(left))),
565 V<Word64>::Cast(right));
566 }
else if (right_is_tagged) {
567 DCHECK((std::is_same_v<WordPtr, Word64>));
568 return __ Word64Equal(V<Word64>::Cast(left),
569 V<Word64>::Cast(
__ BitcastTaggedToWordPtr(
570 V<Object>::Cast(right))));
574 return __ Word64Equal(V<Word64>::Cast(left), V<Word64>::Cast(right));
577 case IrOpcode::kWord64Sar:
578 case IrOpcode::kWord32Sar: {
579 WordRepresentation rep = opcode == IrOpcode::kWord64Sar
580 ? WordRepresentation::Word64()
581 : WordRepresentation::
Word32();
584 case ShiftKind::kShiftOutZeros:
585 kind = ShiftOp::Kind::kShiftRightArithmeticShiftOutZeros;
587 case ShiftKind::kNormal:
588 kind = ShiftOp::Kind::kShiftRightArithmetic;
594#define UNARY_CASE(opcode, assembler_op) \
595 case IrOpcode::k##opcode: \
596 return __ assembler_op(Map(node->InputAt(0)));
598 UNARY_CASE(Word32ReverseBytes, Word32ReverseBytes)
599 UNARY_CASE(Word64ReverseBytes, Word64ReverseBytes)
600 UNARY_CASE(Word32Clz, Word32CountLeadingZeros)
601 UNARY_CASE(Word64Clz, Word64CountLeadingZeros)
602 UNARY_CASE(Word32Ctz, Word32CountTrailingZeros)
603 UNARY_CASE(Word64Ctz, Word64CountTrailingZeros)
606 UNARY_CASE(SignExtendWord8ToInt32, Word32SignExtend8)
607 UNARY_CASE(SignExtendWord16ToInt32, Word32SignExtend16)
608 UNARY_CASE(SignExtendWord8ToInt64, Word64SignExtend8)
609 UNARY_CASE(SignExtendWord16ToInt64, Word64SignExtend16)
610 UNARY_CASE(Int32AbsWithOverflow, Int32AbsCheckOverflow)
611 UNARY_CASE(Int64AbsWithOverflow, Int64AbsCheckOverflow)
617 UNARY_CASE(Float64SilenceNaN, Float64SilenceNaN)
618 UNARY_CASE(Float32RoundDown, Float32RoundDown)
619 UNARY_CASE(Float64RoundDown, Float64RoundDown)
622 UNARY_CASE(Float32RoundTruncate, Float32RoundToZero)
623 UNARY_CASE(Float64RoundTruncate, Float64RoundToZero)
624 UNARY_CASE(Float32RoundTiesEven, Float32RoundTiesEven)
625 UNARY_CASE(Float64RoundTiesEven, Float64RoundTiesEven)
648 UNARY_CASE(BitcastWord32ToWord64, BitcastWord32ToWord64)
649 UNARY_CASE(BitcastFloat32ToInt32, BitcastFloat32ToWord32)
650 UNARY_CASE(BitcastInt32ToFloat32, BitcastWord32ToFloat32)
651 UNARY_CASE(BitcastFloat64ToInt64, BitcastFloat64ToWord64)
652 UNARY_CASE(BitcastInt64ToFloat64, BitcastWord64ToFloat64)
653 UNARY_CASE(ChangeUint32ToUint64, ChangeUint32ToUint64)
654 UNARY_CASE(ChangeInt32ToInt64, ChangeInt32ToInt64)
655 UNARY_CASE(SignExtendWord32ToInt64, ChangeInt32ToInt64)
657 UNARY_CASE(ChangeFloat32ToFloat64, ChangeFloat32ToFloat64)
659 UNARY_CASE(ChangeFloat64ToInt32, ReversibleFloat64ToInt32)
660 UNARY_CASE(ChangeFloat64ToInt64, ReversibleFloat64ToInt64)
661 UNARY_CASE(ChangeFloat64ToUint32, ReversibleFloat64ToUint32)
662 UNARY_CASE(ChangeFloat64ToUint64, ReversibleFloat64ToUint64)
664 UNARY_CASE(ChangeInt32ToFloat64, ChangeInt32ToFloat64)
665 UNARY_CASE(ChangeInt64ToFloat64, ReversibleInt64ToFloat64)
666 UNARY_CASE(ChangeUint32ToFloat64, ChangeUint32ToFloat64)
668 UNARY_CASE(RoundFloat64ToInt32, TruncateFloat64ToInt32OverflowUndefined)
669 UNARY_CASE(RoundInt32ToFloat32, ChangeInt32ToFloat32)
670 UNARY_CASE(RoundInt64ToFloat32, ChangeInt64ToFloat32)
671 UNARY_CASE(RoundInt64ToFloat64, ChangeInt64ToFloat64)
672 UNARY_CASE(RoundUint32ToFloat32, ChangeUint32ToFloat32)
673 UNARY_CASE(RoundUint64ToFloat32, ChangeUint64ToFloat32)
674 UNARY_CASE(RoundUint64ToFloat64, ChangeUint64ToFloat64)
675 UNARY_CASE(TruncateFloat64ToFloat32, TruncateFloat64ToFloat32)
677 TruncateFloat64ToUint32OverflowUndefined)
678 UNARY_CASE(TruncateFloat64ToWord32, JSTruncateFloat64ToWord32)
680 UNARY_CASE(TryTruncateFloat32ToInt64, TryTruncateFloat32ToInt64)
681 UNARY_CASE(TryTruncateFloat32ToUint64, TryTruncateFloat32ToUint64)
682 UNARY_CASE(TryTruncateFloat64ToInt32, TryTruncateFloat64ToInt32)
683 UNARY_CASE(TryTruncateFloat64ToInt64, TryTruncateFloat64ToInt64)
684 UNARY_CASE(TryTruncateFloat64ToUint32, TryTruncateFloat64ToUint32)
685 UNARY_CASE(TryTruncateFloat64ToUint64, TryTruncateFloat64ToUint64)
687 UNARY_CASE(Float64ExtractLowWord32, Float64ExtractLowWord32)
688 UNARY_CASE(Float64ExtractHighWord32, Float64ExtractHighWord32)
691 TruncateFloat64ToFloat16RawBits)
692 UNARY_CASE(ChangeFloat16RawBitsToFloat64, ChangeFloat16RawBitsToFloat64)
694 case IrOpcode::kTruncateInt64ToInt32:
695 return __ TruncateWord64ToWord32(
Map(node->InputAt(0)));
696 case IrOpcode::kTruncateFloat32ToInt32:
697 switch (OpParameter<TruncateKind>(node->op())) {
698 case TruncateKind::kArchitectureDefault:
699 return __ TruncateFloat32ToInt32OverflowUndefined(
700 Map(node->InputAt(0)));
701 case TruncateKind::kSetOverflowToMin:
702 return __ TruncateFloat32ToInt32OverflowToMin(
Map(node->InputAt(0)));
704 case IrOpcode::kTruncateFloat32ToUint32:
705 switch (OpParameter<TruncateKind>(node->op())) {
706 case TruncateKind::kArchitectureDefault:
707 return __ TruncateFloat32ToUint32OverflowUndefined(
708 Map(node->InputAt(0)));
709 case TruncateKind::kSetOverflowToMin:
710 return __ TruncateFloat32ToUint32OverflowToMin(
Map(node->InputAt(0)));
712 case IrOpcode::kTruncateFloat64ToInt64:
713 switch (OpParameter<TruncateKind>(node->op())) {
714 case TruncateKind::kArchitectureDefault:
715 return __ TruncateFloat64ToInt64OverflowUndefined(
716 Map(node->InputAt(0)));
717 case TruncateKind::kSetOverflowToMin:
718 return __ TruncateFloat64ToInt64OverflowToMin(
Map(node->InputAt(0)));
720 case IrOpcode::kFloat64InsertLowWord32: {
722 V<Word32> low = Map<Word32>(node->InputAt(1));
723 if (node->InputAt(0)->opcode() == IrOpcode::kFloat64InsertHighWord32) {
725 high = Map<Word32>(node->InputAt(0)->InputAt(1));
728 high =
__ Float64ExtractHighWord32(
Map(node->InputAt(0)));
730 return __ BitcastWord32PairToFloat64(high, low);
732 case IrOpcode::kFloat64InsertHighWord32: {
733 V<Word32> high = Map<Word32>(node->InputAt(1));
735 if (node->InputAt(0)->opcode() == IrOpcode::kFloat64InsertLowWord32) {
737 low = Map<Word32>(node->InputAt(0)->InputAt(1));
740 low =
__ Float64ExtractLowWord32(Map<Float64>(node->InputAt(0)));
742 return __ BitcastWord32PairToFloat64(high, low);
744 case IrOpcode::kBitcastTaggedToWord:
745 return __ BitcastTaggedToWordPtr(
Map(node->InputAt(0)));
746 case IrOpcode::kBitcastWordToTagged: {
747 V<WordPtr> input =
Map(node->InputAt(0));
751 if (LoadOp* load =
__ output_graph().
Get(input).TryCast<LoadOp>()) {
752 CHECK_EQ(2, node->InputAt(0)->UseCount());
753 CHECK(base::all_equal(node->InputAt(0)->uses(), node));
759 CHECK(load->loaded_rep == MemoryRepresentation::UintPtr() ||
760 load->loaded_rep == (
Is64() ? MemoryRepresentation::Int64()
761 : MemoryRepresentation::Int32()));
762 CHECK_EQ(load->result_rep, RegisterRepresentation::WordPtr());
764 load->loaded_rep = MemoryRepresentation::UncompressedTaggedPointer();
765 load->result_rep = RegisterRepresentation::Tagged();
770 return __ BitcastWordPtrToTagged(
Map(node->InputAt(0)));
772 case IrOpcode::kNumberIsFinite:
773 return __ Float64Is(
Map(node->InputAt(0)), NumericKind::kFinite);
774 case IrOpcode::kNumberIsInteger:
775 return __ Float64Is(
Map(node->InputAt(0)), NumericKind::kInteger);
776 case IrOpcode::kNumberIsSafeInteger:
777 return __ Float64Is(
Map(node->InputAt(0)), NumericKind::kSafeInteger);
778 case IrOpcode::kNumberIsFloat64Hole:
779 return __ Float64Is(
Map(node->InputAt(0)), NumericKind::kFloat64Hole);
780 case IrOpcode::kNumberIsMinusZero:
781 return __ Float64Is(
Map(node->InputAt(0)), NumericKind::kMinusZero);
782 case IrOpcode::kNumberIsNaN:
783 return __ Float64Is(
Map(node->InputAt(0)), NumericKind::kNaN);
784 case IrOpcode::kObjectIsMinusZero:
785 return __ ObjectIsNumericValue(
Map(node->InputAt(0)),
786 NumericKind::kMinusZero,
787 FloatRepresentation::Float64());
788 case IrOpcode::kObjectIsNaN:
789 return __ ObjectIsNumericValue(
Map(node->InputAt(0)), NumericKind::kNaN,
790 FloatRepresentation::Float64());
791 case IrOpcode::kObjectIsFiniteNumber:
792 return __ ObjectIsNumericValue(
Map(node->InputAt(0)),
793 NumericKind::kFinite,
794 FloatRepresentation::Float64());
795 case IrOpcode::kObjectIsInteger:
796 return __ ObjectIsNumericValue(
Map(node->InputAt(0)),
797 NumericKind::kInteger,
798 FloatRepresentation::Float64());
799 case IrOpcode::kObjectIsSafeInteger:
800 return __ ObjectIsNumericValue(
Map(node->InputAt(0)),
801 NumericKind::kSafeInteger,
802 FloatRepresentation::Float64());
804#define OBJECT_IS_CASE(kind) \
805 case IrOpcode::kObjectIs##kind: { \
806 return __ ObjectIs(Map(node->InputAt(0)), ObjectIsOp::Kind::k##kind, \
807 ObjectIsOp::InputAssumptions::kNone); \
823#define CHECK_OBJECT_IS_CASE(code, kind, input_assumptions, reason, feedback) \
824 case IrOpcode::k##code: { \
825 DCHECK(dominating_frame_state.valid()); \
826 V<Object> input = Map(node->InputAt(0)); \
828 __ ObjectIs(input, ObjectIsOp::Kind::k##kind, \
829 ObjectIsOp::InputAssumptions::k##input_assumptions); \
830 __ DeoptimizeIfNot(check, dominating_frame_state, \
831 DeoptimizeReason::k##reason, feedback); \
835 HeapObject, WrongInstanceType, {})
839 NotInt32, CheckParametersOf(op).feedback())
841 NotAJavaScriptObject, {})
843 ReceiverOrNullOrUndefined, HeapObject,
844 NotAJavaScriptObjectOrNullOrUndefined, {})
848 HeapObject, NotAStringOrStringWrapper,
857 case IrOpcode::kPlainPrimitiveToNumber:
858 return
__ ConvertPlainPrimitiveToNumber(
Map(node->InputAt(0)));
859 case IrOpcode::kPlainPrimitiveToWord32:
860 return __ ConvertJSPrimitiveToUntagged(
861 Map(node->InputAt(0)),
862 ConvertJSPrimitiveToUntaggedOp::UntaggedKind::kInt32,
863 ConvertJSPrimitiveToUntaggedOp::InputAssumptions::kPlainPrimitive);
864 case IrOpcode::kPlainPrimitiveToFloat64:
865 return __ ConvertJSPrimitiveToUntagged(
866 Map(node->InputAt(0)),
867 ConvertJSPrimitiveToUntaggedOp::UntaggedKind::kFloat64,
868 ConvertJSPrimitiveToUntaggedOp::InputAssumptions::kPlainPrimitive);
870 case IrOpcode::kConvertTaggedHoleToUndefined: {
873 input,
__ HeapConstant(isolate->factory()->the_hole_value()));
874 return __ Conditional(
875 is_the_hole,
__ HeapConstant(isolate->factory()->undefined_value()),
876 input, BranchHint::kFalse);
879 case IrOpcode::kConvertReceiver:
880 return __ ConvertJSPrimitiveToObject(
881 Map(node->InputAt(0)),
Map(node->InputAt(1)),
Map(node->InputAt(2)),
884 case IrOpcode::kToBoolean:
885 return __ ConvertToBoolean(
Map(node->InputAt(0)));
886 case IrOpcode::kNumberToString:
887 return __ ConvertNumberToString(
Map(node->InputAt(0)));
888 case IrOpcode::kStringToNumber:
889 return __ ConvertStringToNumber(
Map(node->InputAt(0)));
890 case IrOpcode::kChangeTaggedToTaggedSigned:
891 return __ Convert(
Map(node->InputAt(0)),
892 ConvertOp::Kind::kNumberOrOddball,
893 ConvertOp::Kind::kSmi);
895 case IrOpcode::kCheckedTaggedToTaggedSigned: {
896 DCHECK(dominating_frame_state.valid());
898 __ DeoptimizeIfNot(
__ ObjectIsSmi(input), dominating_frame_state,
899 DeoptimizeReason::kNotASmi,
904 case IrOpcode::kCheckedTaggedToTaggedPointer: {
905 DCHECK(dominating_frame_state.valid());
907 __ DeoptimizeIf(
__ ObjectIsSmi(input), dominating_frame_state,
908 DeoptimizeReason::kSmi,
913#define CONVERT_PRIMITIVE_TO_OBJECT_CASE(name, kind, input_type, \
914 input_interpretation) \
915 case IrOpcode::k##name: \
916 return __ ConvertUntaggedToJSPrimitive( \
917 Map(node->InputAt(0)), \
918 ConvertUntaggedToJSPrimitiveOp::JSPrimitiveKind::k##kind, \
919 V<input_type>::rep, \
920 ConvertUntaggedToJSPrimitiveOp::InputInterpretation:: \
921 k##input_interpretation, \
922 CheckForMinusZeroMode::kDontCheckForMinusZero);
946 HeapNumberOrUndefined, Float64, Signed)
948 case IrOpcode::kChangeFloat64ToTagged:
949 return __ ConvertUntaggedToJSPrimitive(
950 Map(node->InputAt(0)),
951 ConvertUntaggedToJSPrimitiveOp::JSPrimitiveKind::kNumber,
952 RegisterRepresentation::Float64(),
953 ConvertUntaggedToJSPrimitiveOp::InputInterpretation::kSigned,
955#undef CONVERT_PRIMITIVE_TO_OBJECT_CASE
957#define CONVERT_PRIMITIVE_TO_OBJECT_OR_DEOPT_CASE(name, kind, input_type, \
958 input_interpretation) \
959 case IrOpcode::k##name: { \
960 DCHECK(dominating_frame_state.valid()); \
961 const CheckParameters& params = CheckParametersOf(node->op()); \
962 return __ ConvertUntaggedToJSPrimitiveOrDeopt( \
963 Map(node->InputAt(0)), dominating_frame_state, \
964 ConvertUntaggedToJSPrimitiveOrDeoptOp::JSPrimitiveKind::k##kind, \
965 V<input_type>::rep, \
966 ConvertUntaggedToJSPrimitiveOrDeoptOp::InputInterpretation:: \
967 k##input_interpretation, \
968 params.feedback()); \
973 Smi, Word32, Unsigned)
977 Smi, Word64, Unsigned)
978#undef CONVERT_PRIMITIVE_TO_OBJECT_OR_DEOPT_CASE
980#define CONVERT_OBJECT_TO_PRIMITIVE_CASE(name, kind, input_assumptions) \
981 case IrOpcode::k##name: \
982 return __ ConvertJSPrimitiveToUntagged( \
983 Map(node->InputAt(0)), \
984 ConvertJSPrimitiveToUntaggedOp::UntaggedKind::k##kind, \
985 ConvertJSPrimitiveToUntaggedOp::InputAssumptions:: \
986 k##input_assumptions);
1000#undef CONVERT_OBJECT_TO_PRIMITIVE_CASE
1002#define TRUNCATE_OBJECT_TO_PRIMITIVE_CASE(name, kind, input_assumptions) \
1003 case IrOpcode::k##name: \
1004 return __ TruncateJSPrimitiveToUntagged( \
1005 Map(node->InputAt(0)), \
1006 TruncateJSPrimitiveToUntaggedOp::UntaggedKind::k##kind, \
1007 TruncateJSPrimitiveToUntaggedOp::InputAssumptions:: \
1008 k##input_assumptions);
1015#undef TRUNCATE_OBJECT_TO_PRIMITIVE_CASE
1017 case IrOpcode::kCheckedTruncateTaggedToWord32:
1018 DCHECK(dominating_frame_state.valid());
1019 using IR = TruncateJSPrimitiveToUntaggedOrDeoptOp::InputRequirement;
1020 IR input_requirement;
1022 case CheckTaggedInputMode::kAdditiveSafeInteger:
1023 input_requirement = IR::kAdditiveSafeInteger;
1025 case CheckTaggedInputMode::kNumber:
1026 input_requirement = IR::kNumber;
1028 case CheckTaggedInputMode::kNumberOrBoolean:
1029 input_requirement = IR::kNumberOrBoolean;
1031 case CheckTaggedInputMode::kNumberOrOddball:
1032 input_requirement = IR::kNumberOrOddball;
1035 return __ TruncateJSPrimitiveToUntaggedOrDeopt(
1036 Map(node->InputAt(0)), dominating_frame_state,
1037 TruncateJSPrimitiveToUntaggedOrDeoptOp::UntaggedKind::kInt32,
1041#define CHANGE_OR_DEOPT_INT_CASE(kind) \
1042 case IrOpcode::kChecked##kind: { \
1043 DCHECK(dominating_frame_state.valid()); \
1044 const CheckParameters& params = CheckParametersOf(node->op()); \
1045 return __ ChangeOrDeopt(Map(node->InputAt(0)), dominating_frame_state, \
1046 ChangeOrDeoptOp::Kind::k##kind, \
1047 CheckForMinusZeroMode::kDontCheckForMinusZero, \
1048 params.feedback()); \
1054#undef CHANGE_OR_DEOPT_INT_CASE
1056 case IrOpcode::kCheckedFloat64ToInt32: {
1057 DCHECK(dominating_frame_state.valid());
1058 const CheckMinusZeroParameters& params =
1060 return __ ChangeOrDeopt(
Map(node->InputAt(0)), dominating_frame_state,
1061 ChangeOrDeoptOp::Kind::kFloat64ToInt32,
1062 params.mode(), params.feedback());
1065 case IrOpcode::kCheckedFloat64ToAdditiveSafeInteger: {
1066 DCHECK(dominating_frame_state.valid());
1067 const CheckMinusZeroParameters& params =
1069 return __ ChangeOrDeopt(
1070 Map(node->InputAt(0)), dominating_frame_state,
1071 ChangeOrDeoptOp::Kind::kFloat64ToAdditiveSafeInteger, params.mode(),
1075 case IrOpcode::kCheckedFloat64ToInt64: {
1076 DCHECK(dominating_frame_state.valid());
1077 const CheckMinusZeroParameters& params =
1079 return __ ChangeOrDeopt(
Map(node->InputAt(0)), dominating_frame_state,
1080 ChangeOrDeoptOp::Kind::kFloat64ToInt64,
1081 params.mode(), params.feedback());
1084 case IrOpcode::kCheckedTaggedToInt32: {
1085 DCHECK(dominating_frame_state.valid());
1086 const CheckMinusZeroParameters& params =
1088 return __ ConvertJSPrimitiveToUntaggedOrDeopt(
1089 Map(node->InputAt(0)), dominating_frame_state,
1090 ConvertJSPrimitiveToUntaggedOrDeoptOp::JSPrimitiveKind::kNumber,
1091 ConvertJSPrimitiveToUntaggedOrDeoptOp::UntaggedKind::kInt32,
1092 params.mode(), params.feedback());
1095 case IrOpcode::kCheckedTaggedToAdditiveSafeInteger: {
1096 DCHECK(dominating_frame_state.valid());
1097 const CheckMinusZeroParameters& params =
1099 return __ ConvertJSPrimitiveToUntaggedOrDeopt(
1100 Map(node->InputAt(0)), dominating_frame_state,
1101 ConvertJSPrimitiveToUntaggedOrDeoptOp::JSPrimitiveKind::kNumber,
1102 ConvertJSPrimitiveToUntaggedOrDeoptOp::UntaggedKind::
1103 kAdditiveSafeInteger,
1104 params.mode(), params.feedback());
1107 case IrOpcode::kCheckedTaggedToInt64: {
1108 DCHECK(dominating_frame_state.valid());
1109 const CheckMinusZeroParameters& params =
1111 return __ ConvertJSPrimitiveToUntaggedOrDeopt(
1112 Map(node->InputAt(0)), dominating_frame_state,
1113 ConvertJSPrimitiveToUntaggedOrDeoptOp::JSPrimitiveKind::kNumber,
1114 ConvertJSPrimitiveToUntaggedOrDeoptOp::UntaggedKind::kInt64,
1115 params.mode(), params.feedback());
1118 case IrOpcode::kCheckedTaggedToFloat64: {
1119 DCHECK(dominating_frame_state.valid());
1120 const CheckTaggedInputParameters& params =
1122 ConvertJSPrimitiveToUntaggedOrDeoptOp::JSPrimitiveKind from_kind;
1123 switch (params.mode()) {
1125 case CheckTaggedInputMode::k##mode: \
1127 ConvertJSPrimitiveToUntaggedOrDeoptOp::JSPrimitiveKind::k##mode; \
1129 CASE(AdditiveSafeInteger)
1131 CASE(NumberOrBoolean)
1132 CASE(NumberOrOddball)
1135 return __ ConvertJSPrimitiveToUntaggedOrDeopt(
1136 Map(node->InputAt(0)), dominating_frame_state, from_kind,
1137 ConvertJSPrimitiveToUntaggedOrDeoptOp::UntaggedKind::kFloat64,
1138 CheckForMinusZeroMode::kDontCheckForMinusZero, params.feedback());
1141 case IrOpcode::kCheckedTaggedToArrayIndex: {
1142 DCHECK(dominating_frame_state.valid());
1144 return __ ConvertJSPrimitiveToUntaggedOrDeopt(
1145 Map(node->InputAt(0)), dominating_frame_state,
1146 ConvertJSPrimitiveToUntaggedOrDeoptOp::JSPrimitiveKind::
1148 ConvertJSPrimitiveToUntaggedOrDeoptOp::UntaggedKind::kArrayIndex,
1149 CheckForMinusZeroMode::kCheckForMinusZero, params.feedback());
1152 case IrOpcode::kCheckedTaggedSignedToInt32: {
1153 DCHECK(dominating_frame_state.valid());
1155 return __ ConvertJSPrimitiveToUntaggedOrDeopt(
1156 Map(node->InputAt(0)), dominating_frame_state,
1157 ConvertJSPrimitiveToUntaggedOrDeoptOp::JSPrimitiveKind::kSmi,
1158 ConvertJSPrimitiveToUntaggedOrDeoptOp::UntaggedKind::kInt32,
1159 CheckForMinusZeroMode::kDontCheckForMinusZero, params.feedback());
1162 case IrOpcode::kSelect: {
1167 return __ Select(cond, vtrue, vfalse,
1168 RegisterRepresentation::FromMachineRepresentation(
1169 params.representation()),
1170 params.hint(), SelectOp::Implementation::kBranch);
1172 case IrOpcode::kWord32Select:
1174 Map<Word32>(node->InputAt(0)), Map<Word32>(node->InputAt(1)),
1175 Map<Word32>(node->InputAt(2)), RegisterRepresentation::Word32(),
1176 BranchHint::kNone, SelectOp::Implementation::kCMove);
1177 case IrOpcode::kWord64Select:
1179 Map<Word32>(node->InputAt(0)), Map<Word64>(node->InputAt(1)),
1180 Map<Word64>(node->InputAt(2)), RegisterRepresentation::Word64(),
1181 BranchHint::kNone, SelectOp::Implementation::kCMove);
1182 case IrOpcode::kFloat32Select:
1184 Map<Word32>(node->InputAt(0)), Map<Float32>(node->InputAt(1)),
1185 Map<Float32>(node->InputAt(2)), RegisterRepresentation::Float32(),
1186 BranchHint::kNone, SelectOp::Implementation::kCMove);
1188 case IrOpcode::kLoad:
1189 case IrOpcode::kLoadImmutable:
1190 case IrOpcode::kUnalignedLoad: {
1191 MemoryRepresentation loaded_rep =
1193 Node*
base = node->InputAt(0);
1194 Node* index = node->InputAt(1);
1196 LoadOp::Kind
kind = opcode == IrOpcode::kUnalignedLoad
1197 ? LoadOp::Kind::RawUnaligned()
1198 : LoadOp::Kind::RawAligned();
1199 if (
__ output_graph().
Get(
Map(
base)).outputs_rep().at(0) ==
1200 RegisterRepresentation::Tagged()) {
1201 kind = LoadOp::Kind::TaggedBase();
1203 if (index->opcode() == IrOpcode::kInt32Constant) {
1204 int32_t offset = OpParameter<int32_t>(index->op());
1205 if (kind.tagged_base) offset += kHeapObjectTag;
1206 return __ Load(Map(base), kind, loaded_rep, offset);
1208 if (index->opcode() == IrOpcode::kInt64Constant) {
1209 int64_t offset = OpParameter<int64_t>(index->op());
1210 if (kind.tagged_base) offset += kHeapObjectTag;
1211 if (base::IsValueInRangeForNumericType<int32_t>(offset)) {
1212 return __ Load(Map(base), kind, loaded_rep,
1213 static_cast<int32_t>(offset));
1217 uint8_t element_size_log2 = 0;
1221 case IrOpcode::kProtectedLoad: {
1222 MemoryRepresentation loaded_rep =
1224 return __ Load(
Map(node->InputAt(0)),
Map(node->InputAt(1)),
1225 LoadOp::Kind::Protected(), loaded_rep);
1228 case IrOpcode::kStore:
1229 case IrOpcode::kUnalignedStore: {
1234 if (
__ output_graph().
Get(
base).outputs_rep()[0] ==
1235 RegisterRepresentation::Tagged()) {
1239 bool aligned = opcode != IrOpcode::kUnalignedStore;
1240 StoreRepresentation store_rep =
1244 StoreOp::Kind
kind = opcode == IrOpcode::kStore
1245 ? StoreOp::Kind::RawAligned()
1246 : StoreOp::Kind::RawUnaligned();
1249 Node* index = node->InputAt(1);
1250 Node* value = node->InputAt(2);
1251 if (index->opcode() == IrOpcode::kInt32Constant) {
1252 int32_t offset = OpParameter<int32_t>(index->op());
1253 __ Store(base, Map(value), kind,
1254 MemoryRepresentation::FromMachineRepresentation(
1255 store_rep.representation()),
1256 store_rep.write_barrier_kind(), offset,
1257 initializing_transitioning);
1258 return OpIndex::Invalid();
1260 if (index->opcode() == IrOpcode::kInt64Constant) {
1261 int64_t offset = OpParameter<int64_t>(index->op());
1262 if (base::IsValueInRangeForNumericType<int32_t>(offset)) {
1263 __ Store(base, Map(value), kind,
1264 MemoryRepresentation::FromMachineRepresentation(
1265 store_rep.representation()),
1266 store_rep.write_barrier_kind(), static_cast<int32_t>(offset),
1267 initializing_transitioning);
1268 return OpIndex::Invalid();
1272 uint8_t element_size_log2 = 0;
1274 MemoryRepresentation::FromMachineRepresentation(
1275 store_rep.representation()),
1276 store_rep.write_barrier_kind(),
offset, element_size_log2,
1277 initializing_transitioning);
1278 return OpIndex::Invalid();
1280 case IrOpcode::kProtectedStore:
1290 case IrOpcode::kRetain:
1291 __ Retain(
Map(node->InputAt(0)));
1293 case IrOpcode::kStackPointerGreaterThan:
1294 return __ StackPointerGreaterThan(
Map<WordPtr>(node->InputAt(0)),
1296 case IrOpcode::kLoadStackCheckOffset:
1297 return __ StackCheckOffset();
1298 case IrOpcode::kLoadFramePointer:
1299 return __ FramePointer();
1300 case IrOpcode::kLoadParentFramePointer:
1301 return __ ParentFramePointer();
1303 case IrOpcode::kStackSlot: {
1305 return __ StackSlot(rep.size(), rep.alignment(), rep.is_tagged());
1307 case IrOpcode::kBranch:
1309 __ Branch(
Map(node->InputAt(0)),
Map(block->SuccessorAt(0)),
1313 case IrOpcode::kSwitch: {
1314 BasicBlock* default_branch = block->successors().back();
1315 DCHECK_EQ(IrOpcode::kIfDefault, default_branch->front()->opcode());
1316 size_t case_count = block->SuccessorCount() - 1;
1317 base::SmallVector<SwitchOp::Case, 16> cases;
1318 for (
size_t i = 0;
i < case_count; ++
i) {
1319 BasicBlock* branch = block->SuccessorAt(
i);
1321 cases.emplace_back(p.value(),
Map(branch), p.hint());
1329 case IrOpcode::kCall: {
1331 const JSWasmCallParameters* wasm_call_parameters =
nullptr;
1332#if V8_ENABLE_WEBASSEMBLY
1333 if (call_descriptor->IsAnyWasmFunctionCall() &&
1334 v8_flags.turboshaft_wasm_in_js_inlining) {
1343 wasm_call_parameters = it->second;
1350 wasm_call_parameters);
1352 base::SmallVector<OpIndex, 16> arguments;
1357 for (
int i = 1; i < static_cast<int>(call_descriptor->InputCount());
1359 arguments.emplace_back(
Map(node->InputAt(
i)));
1363 if (call_descriptor->NeedsFrameState()) {
1364 compiler::FrameState frame_state{
1365 node->InputAt(
static_cast<int>(call_descriptor->InputCount()))};
1366 frame_state_idx =
Map(frame_state);
1368 std::optional<
decltype(
assembler)::CatchScope> catch_scope;
1369 if (is_final_control) {
1370 Block* catch_block =
Map(block->SuccessorAt(1));
1371 catch_scope.emplace(assembler, catch_block);
1374 OpEffects().CanDependOnChecks().CanChangeControlFlow().CanDeopt();
1376 effects = effects.CanAllocate();
1379 effects = effects.CanWriteMemory();
1382 effects = effects.CanReadMemory();
1386 ts_descriptor, effects);
1387 if (is_final_control) {
1391 __ Goto(
Map(block->SuccessorAt(0)));
1396 case IrOpcode::kTailCall: {
1398 base::SmallVector<OpIndex, 16> arguments;
1403 for (
int i = 1; i < static_cast<int>(call_descriptor->InputCount());
1405 arguments.emplace_back(
Map(node->InputAt(
i)));
1417 case IrOpcode::kFrameState: {
1418 compiler::FrameState frame_state{node};
1419 FrameStateData::Builder builder;
1420 BuildFrameStateData(&builder, frame_state);
1421 if (builder.Inputs().size() >
1423 *bailout = BailoutReason::kTooManyArguments;
1426 return __ FrameState(builder.Inputs(), builder.inlined(),
1427 builder.AllocateFrameStateData(
1428 frame_state.frame_state_info(),
graph_zone));
1431 case IrOpcode::kDeoptimizeIf:
1432 __ DeoptimizeIf(
Map(node->InputAt(0)),
Map(node->InputAt(1)),
1435 case IrOpcode::kDeoptimizeUnless:
1436 __ DeoptimizeIfNot(
Map(node->InputAt(0)),
Map(node->InputAt(1)),
1440#if V8_ENABLE_WEBASSEMBLY
1441 case IrOpcode::kTrapIf:
1445 __ TrapIf(
Map(node->InputAt(0)), dominating_frame_state, TrapIdOf(op));
1448 case IrOpcode::kTrapUnless:
1452 __ TrapIfNot(
Map(node->InputAt(0)), dominating_frame_state, TrapIdOf(op));
1456 case IrOpcode::kDeoptimize: {
1462 case IrOpcode::kReturn: {
1463 Node* pop_count = node->InputAt(0);
1464 base::SmallVector<OpIndex, 4> return_values;
1465 for (
int i = 1;
i < node->op()->ValueInputCount(); ++
i) {
1466 return_values.push_back(
Map(node->InputAt(
i)));
1471 case IrOpcode::kUnreachable:
1472 case IrOpcode::kThrow:
1476 case IrOpcode::kDeadValue:
1480 DCHECK_NE(node->InputAt(0)->opcode(), IrOpcode::kUnreachable);
1486 case IrOpcode::kProjection: {
1487 Node* input = node->InputAt(0);
1489 RegisterRepresentation rep =
1492 return __ Projection(
Map(input), index, rep);
1495 case IrOpcode::kStaticAssert:
1499 case IrOpcode::kAllocate: {
1501 return __ FinishInitialization(
1505 case IrOpcode::kAllocateRaw: {
1506 Node* size = node->InputAt(0);
1508 return __ FinishInitialization(
1511 case IrOpcode::kStoreToObject: {
1512 Node*
object = node->InputAt(0);
1513 Node*
offset = node->InputAt(1);
1514 Node* value = node->InputAt(2);
1521 initializing_transitioning);
1524 case IrOpcode::kStoreElement: {
1525 Node*
object = node->InputAt(0);
1526 Node* index = node->InputAt(1);
1527 Node* value = node->InputAt(2);
1529 DCHECK(!access.machine_type.IsMapWord());
1531 MemoryRepresentation rep =
1535 access.write_barrier_kind, access.header_size,
1536 rep.SizeInBytesLog2(), initializing_transitioning);
1539 case IrOpcode::kStoreField: {
1544 DCHECK(!access.type.Is(compiler::Type::ExternalPointer()) ||
1547 DCHECK(!access.type.Is(compiler::Type::SandboxedPointer()));
1549#ifdef V8_ENABLE_SANDBOX
1550 if (access.is_bounded_size_access) {
1551 value =
__ ShiftLeft(value, kBoundedSizeShift,
1560#ifdef V8_MAP_PACKING
1565 bool initializing_transitioning =
1566 access.maybe_initializing_or_transitioning_store;
1570 initializing_transitioning =
false;
1573 MemoryRepresentation rep =
1576 if (
const ConstantOp* value_cst =
1582 if (IsValidSmi(value_cst->signed_integral())) {
1583 value =
__ SmiConstant(
Tagged<Smi>(value_cst->signed_integral()));
1588 __ Store(
object, value,
kind, rep, access.write_barrier_kind,
1589 access.offset, initializing_transitioning,
1590 access.indirect_pointer_tag);
1593 case IrOpcode::kLoadFromObject:
1594 case IrOpcode::kLoadImmutableFromObject: {
1595 Node*
object = node->InputAt(0);
1596 Node*
offset = node->InputAt(1);
1598 MemoryRepresentation rep =
1603 case IrOpcode::kLoadField: {
1604 Node*
object = node->InputAt(0);
1610#ifdef V8_MAP_PACKING
1614 MemoryRepresentation rep =
1616#ifdef V8_ENABLE_SANDBOX
1617 bool is_sandboxed_external =
1618 access.type.Is(compiler::Type::ExternalPointer());
1619 if (is_sandboxed_external) {
1626#ifdef V8_ENABLE_SANDBOX
1627 if (is_sandboxed_external) {
1628 value =
__ DecodeExternalPointer(value, access.external_pointer_tag);
1630 if (access.is_bounded_size_access) {
1631 DCHECK(!is_sandboxed_external);
1632 value =
__ ShiftRightLogical(value, kBoundedSizeShift,
1638 case IrOpcode::kLoadElement: {
1639 Node*
object = node->InputAt(0);
1640 Node* index = node->InputAt(1);
1643 MemoryRepresentation rep =
1646 rep.SizeInBytesLog2());
1648 case IrOpcode::kCheckTurboshaftTypeOf: {
1649 Node* input = node->InputAt(0);
1650 Node* type_description = node->InputAt(1);
1654 m.Ref(
broker).AsString().IsContentAccessible());
1655 StringRef type_string =
m.Ref(
broker).AsString();
1656 DirectHandle<String> pattern_string =
1657 *type_string.ObjectIfContentAccessible(
broker);
1658 std::unique_ptr<char[]>
pattern = pattern_string->ToCString();
1662 if (type_opt == std::nullopt) {
1664 "String '%s' (of %d:CheckTurboshaftTypeOf) is not a valid type "
1670 RegisterRepresentation rep =
1671 __ output_graph().Get(input_index).outputs_rep()[0];
1672 return __ CheckTurboshaftTypeOf(input_index, rep, *type_opt,
false);
1675 case IrOpcode::kNewConsString:
1676 return __ NewConsString(
Map(node->InputAt(0)),
Map(node->InputAt(1)),
1677 Map(node->InputAt(2)));
1678 case IrOpcode::kNewDoubleElements:
1681 case IrOpcode::kNewSmiOrObjectElements:
1685 case IrOpcode::kDoubleArrayMin:
1686 return __ DoubleArrayMinMax(
Map(node->InputAt(0)),
1688 case IrOpcode::kDoubleArrayMax:
1689 return __ DoubleArrayMinMax(
Map(node->InputAt(0)),
1692 case IrOpcode::kLoadFieldByIndex:
1693 return __ LoadFieldByIndex(
Map(node->InputAt(0)),
Map(node->InputAt(1)));
1695 case IrOpcode::kCheckedAdditiveSafeIntegerAdd: {
1697 DCHECK(dominating_frame_state.valid());
1702 auto shifted_result =
__ Word64SignedAddDeoptOnOverflow(
1703 shifted_lhs, shifted_rhs, dominating_frame_state, FeedbackSource{});
1704 return __ Word64ShiftRightArithmetic(shifted_result,
1707 case IrOpcode::kCheckedAdditiveSafeIntegerSub: {
1709 DCHECK(dominating_frame_state.valid());
1714 auto shifted_result =
__ Word64SignedSubDeoptOnOverflow(
1715 shifted_lhs, shifted_rhs, dominating_frame_state, FeedbackSource{});
1716 return __ Word64ShiftRightArithmetic(shifted_result,
1719 case IrOpcode::kCheckedInt64Add:
1721 DCHECK(dominating_frame_state.valid());
1722 return __ Word64SignedAddDeoptOnOverflow(
1723 Map(node->InputAt(0)),
Map(node->InputAt(1)), dominating_frame_state,
1726 case IrOpcode::kCheckedInt64Sub:
1728 DCHECK(dominating_frame_state.valid());
1729 return __ Word64SignedSubDeoptOnOverflow(
1730 Map(node->InputAt(0)),
Map(node->InputAt(1)), dominating_frame_state,
1733 case IrOpcode::kCheckedInt32Add:
1734 DCHECK(dominating_frame_state.valid());
1735 return __ Word32SignedAddDeoptOnOverflow(
1736 Map(node->InputAt(0)),
Map(node->InputAt(1)), dominating_frame_state,
1739 case IrOpcode::kCheckedInt32Sub:
1740 DCHECK(dominating_frame_state.valid());
1741 return __ Word32SignedSubDeoptOnOverflow(
1742 Map(node->InputAt(0)),
Map(node->InputAt(1)), dominating_frame_state,
1745 case IrOpcode::kCheckedInt32Mul: {
1746 DCHECK(dominating_frame_state.valid());
1748 return __ Word32SignedMulDeoptOnOverflow(
1749 Map(node->InputAt(0)),
Map(node->InputAt(1)), dominating_frame_state,
1750 FeedbackSource{}, mode);
1753 case IrOpcode::kCheckedInt64Mul:
1755 DCHECK(dominating_frame_state.valid());
1756 return __ Word64SignedMulDeoptOnOverflow(
1757 Map(node->InputAt(0)),
Map(node->InputAt(1)), dominating_frame_state,
1760 case IrOpcode::kCheckedInt32Div:
1761 DCHECK(dominating_frame_state.valid());
1762 return __ Word32SignedDivDeoptOnOverflow(
1763 Map(node->InputAt(0)),
Map(node->InputAt(1)), dominating_frame_state,
1766 case IrOpcode::kCheckedInt64Div:
1768 DCHECK(dominating_frame_state.valid());
1769 return __ Word64SignedDivDeoptOnOverflow(
1770 Map(node->InputAt(0)),
Map(node->InputAt(1)), dominating_frame_state,
1773 case IrOpcode::kCheckedUint32Div:
1774 DCHECK(dominating_frame_state.valid());
1775 return __ Word32UnsignedDivDeoptOnOverflow(
1776 Map(node->InputAt(0)),
Map(node->InputAt(1)), dominating_frame_state,
1779 case IrOpcode::kCheckedInt32Mod:
1780 DCHECK(dominating_frame_state.valid());
1781 return __ Word32SignedModDeoptOnOverflow(
1782 Map(node->InputAt(0)),
Map(node->InputAt(1)), dominating_frame_state,
1785 case IrOpcode::kCheckedInt64Mod:
1787 DCHECK(dominating_frame_state.valid());
1788 return __ Word64SignedModDeoptOnOverflow(
1789 Map(node->InputAt(0)),
Map(node->InputAt(1)), dominating_frame_state,
1792 case IrOpcode::kCheckedUint32Mod:
1793 DCHECK(dominating_frame_state.valid());
1794 return __ Word32UnsignedModDeoptOnOverflow(
1795 Map(node->InputAt(0)),
Map(node->InputAt(1)), dominating_frame_state,
1798#define BIGINT_BINOP_CASE(op, kind) \
1799 case IrOpcode::kBigInt##op: \
1800 DCHECK(dominating_frame_state.valid()); \
1801 return __ BigIntBinop(Map(node->InputAt(0)), Map(node->InputAt(1)), \
1802 dominating_frame_state, \
1803 BigIntBinopOp::Kind::k##kind);
1814#undef BIGINT_BINOP_CASE
1816 case IrOpcode::kBigIntEqual:
1817 return __ BigIntEqual(
Map(node->InputAt(0)),
Map(node->InputAt(1)));
1819 case IrOpcode::kBigIntLessThan:
1820 return __ BigIntLessThan(
Map(node->InputAt(0)),
Map(node->InputAt(1)));
1821 case IrOpcode::kBigIntLessThanOrEqual:
1822 return __ BigIntLessThanOrEqual(
Map(node->InputAt(0)),
1823 Map(node->InputAt(1)));
1825 case IrOpcode::kBigIntNegate:
1828 case IrOpcode::kLoadRootRegister:
1830 return assembler.ReduceLoadRootRegister();
1832 case IrOpcode::kStringCharCodeAt:
1833 return __ StringCharCodeAt(
Map(node->InputAt(0)),
Map(node->InputAt(1)));
1834 case IrOpcode::kStringCodePointAt:
1835 return __ StringCodePointAt(
Map(node->InputAt(0)),
Map(node->InputAt(1)));
1837#ifdef V8_INTL_SUPPORT
1838 case IrOpcode::kStringToLowerCaseIntl:
1839 return __ StringToLowerCaseIntl(
Map(node->InputAt(0)));
1840 case IrOpcode::kStringToUpperCaseIntl:
1841 return __ StringToUpperCaseIntl(
Map(node->InputAt(0)));
1843 case IrOpcode::kStringToLowerCaseIntl:
1844 case IrOpcode::kStringToUpperCaseIntl:
1848 case IrOpcode::kStringLength:
1849 return __ StringLength(
Map(node->InputAt(0)));
1851 case IrOpcode::kStringWrapperLength: {
1855 return __ StringLength(str);
1858 case IrOpcode::kTypedArrayLength: {
1860 return __ TypedArrayLength(
Map(node->InputAt(0)), elements_kind);
1863 case IrOpcode::kStringIndexOf:
1864 return __ StringIndexOf(
Map(node->InputAt(0)),
Map(node->InputAt(1)),
1865 Map(node->InputAt(2)));
1867 case IrOpcode::kStringFromCodePointAt:
1868 return __ StringFromCodePointAt(
Map(node->InputAt(0)),
1869 Map(node->InputAt(1)));
1871 case IrOpcode::kStringSubstring:
1872 return __ StringSubstring(
Map(node->InputAt(0)),
Map(node->InputAt(1)),
1873 Map(node->InputAt(2)));
1875 case IrOpcode::kStringConcat:
1876 return __ StringConcat(
Map(node->InputAt(0)),
Map(node->InputAt(1)),
1877 Map(node->InputAt(2)));
1879 case IrOpcode::kStringEqual:
1880 return __ StringEqual(
Map(node->InputAt(0)),
Map(node->InputAt(1)));
1881 case IrOpcode::kStringLessThan:
1882 return __ StringLessThan(
Map(node->InputAt(0)),
Map(node->InputAt(1)));
1883 case IrOpcode::kStringLessThanOrEqual:
1884 return __ StringLessThanOrEqual(
Map(node->InputAt(0)),
1885 Map(node->InputAt(1)));
1887 case IrOpcode::kArgumentsLength:
1888 return __ ArgumentsLength();
1889 case IrOpcode::kRestLength:
1892 case IrOpcode::kNewArgumentsElements: {
1900 return __ NewArgumentsElements(
Map(node->InputAt(0)), p.arguments_type(),
1901 p.formal_parameter_count());
1904 case IrOpcode::kLoadTypedElement:
1905 return __ LoadTypedElement(
Map(node->InputAt(0)),
Map(node->InputAt(1)),
1906 Map(node->InputAt(2)),
Map(node->InputAt(3)),
1908 case IrOpcode::kLoadDataViewElement:
1909 return __ LoadDataViewElement(
1910 Map(node->InputAt(0)),
Map(node->InputAt(1)),
Map(node->InputAt(2)),
1912 case IrOpcode::kLoadStackArgument:
1913 return __ LoadStackArgument(
Map(node->InputAt(0)),
Map(node->InputAt(1)));
1915 case IrOpcode::kStoreTypedElement:
1916 __ StoreTypedElement(
Map(node->InputAt(0)),
Map(node->InputAt(1)),
1917 Map(node->InputAt(2)),
Map(node->InputAt(3)),
1918 Map(node->InputAt(4)),
1921 case IrOpcode::kStoreDataViewElement:
1922 __ StoreDataViewElement(
Map(node->InputAt(0)),
Map(node->InputAt(1)),
1923 Map(node->InputAt(2)),
Map(node->InputAt(3)),
1924 Map(node->InputAt(4)),
1927 case IrOpcode::kTransitionAndStoreElement:
1928 __ TransitionAndStoreArrayElement(
1929 Map(node->InputAt(0)),
Map(node->InputAt(1)),
Map(node->InputAt(2)),
1934 case IrOpcode::kTransitionAndStoreNumberElement:
1935 __ TransitionAndStoreArrayElement(
1936 Map(node->InputAt(0)),
Map(node->InputAt(1)),
Map(node->InputAt(2)),
1940 case IrOpcode::kTransitionAndStoreNonNumberElement: {
1943 .
Is(compiler::Type::BooleanOrNullOrUndefined())
1946 __ TransitionAndStoreArrayElement(
1947 Map(node->InputAt(0)),
Map(node->InputAt(1)),
Map(node->InputAt(2)),
1951 case IrOpcode::kStoreSignedSmallElement:
1952 __ StoreSignedSmallElement(
Map(node->InputAt(0)),
Map(node->InputAt(1)),
1953 Map(node->InputAt(2)));
1956 case IrOpcode::kCompareMaps: {
1959 return __ CompareMaps(
Map(node->InputAt(0)), {}, maps);
1962 case IrOpcode::kCheckMaps: {
1963 DCHECK(dominating_frame_state.valid());
1965 __ CheckMaps(
Map(node->InputAt(0)), dominating_frame_state, {}, p.maps(),
1966 p.flags(), p.feedback());
1970 case IrOpcode::kCheckedUint32Bounds:
1971 case IrOpcode::kCheckedUint64Bounds: {
1972 WordRepresentation rep = node->opcode() == IrOpcode::kCheckedUint32Bounds
1974 : WordRepresentation::
Word64();
1978 V<Word32> check =
__ UintLessThan(index, limit, rep);
1983 DCHECK(dominating_frame_state.valid());
1984 __ DeoptimizeIfNot(check, dominating_frame_state,
1985 DeoptimizeReason::kOutOfBounds,
1986 params.check_parameters().feedback());
1991 case IrOpcode::kCheckIf: {
1992 DCHECK(dominating_frame_state.valid());
1994 __ DeoptimizeIfNot(
Map(node->InputAt(0)), dominating_frame_state,
1995 params.reason(), params.feedback());
1999 case IrOpcode::kCheckClosure:
2000 DCHECK(dominating_frame_state.valid());
2001 return __ CheckedClosure(
Map(node->InputAt(0)), dominating_frame_state,
2004 case IrOpcode::kCheckEqualsSymbol:
2005 DCHECK(dominating_frame_state.valid());
2007 __ TaggedEqual(
Map(node->InputAt(0)),
Map(node->InputAt(1))),
2008 dominating_frame_state, DeoptimizeReason::kWrongName,
2012 case IrOpcode::kCheckEqualsInternalizedString:
2013 DCHECK(dominating_frame_state.valid());
2014 __ CheckEqualsInternalizedString(
2015 Map(node->InputAt(0)),
Map(node->InputAt(1)), dominating_frame_state);
2018 case IrOpcode::kCheckFloat64Hole: {
2019 DCHECK(dominating_frame_state.valid());
2024 return __ ChangeOrDeopt(
2030 case IrOpcode::kCheckNotTaggedHole: {
2031 DCHECK(dominating_frame_state.valid());
2034 __ TaggedEqual(value,
2035 __ HeapConstant(isolate->factory()->the_hole_value())),
2036 dominating_frame_state, DeoptimizeReason::kHole, FeedbackSource{});
2040 case IrOpcode::kLoadMessage:
2041 return __ LoadMessage(
Map(node->InputAt(0)));
2042 case IrOpcode::kStoreMessage:
2043 __ StoreMessage(
Map(node->InputAt(0)),
Map(node->InputAt(1)));
2046 case IrOpcode::kSameValue:
2047 return __ SameValue(
Map(node->InputAt(0)),
Map(node->InputAt(1)),
2049 case IrOpcode::kSameValueNumbersOnly:
2050 return __ SameValue(
Map(node->InputAt(0)),
Map(node->InputAt(1)),
2052 case IrOpcode::kNumberSameValue:
2053 return __ Float64SameValue(
Map(node->InputAt(0)),
Map(node->InputAt(1)));
2055 case IrOpcode::kTypeOf:
2056 return __ CallBuiltin_Typeof(isolate,
Map(node->InputAt(0)));
2058 case IrOpcode::kFastApiCall: {
2059 DCHECK(dominating_frame_state.valid());
2060 FastApiCallNode
n(node);
2061 const auto& params = n.Parameters();
2062 FastApiCallFunction c_function = params.c_function();
2063 const int c_arg_count = params.argument_count();
2065 base::SmallVector<OpIndex, 16> slow_call_arguments;
2066 DCHECK_EQ(node->op()->ValueInputCount(),
2068 n.SlowCallArgumentCount());
2069 OpIndex slow_call_callee =
Map(n.SlowCallArgument(0));
2070 for (
int i = 1;
i < n.SlowCallArgumentCount(); ++
i) {
2071 slow_call_arguments.push_back(
Map(n.SlowCallArgument(
i)));
2079#define ELSE_UNREACHABLE \
2081 __ RuntimeAbort(AbortReason::kFastCallFallbackInvalid); \
2084 switch (return_type) {
2092 __ TaggedEqual(
result,
__ FalseConstant())))) {
2094 value,
__ ConvertJSPrimitiveToUntagged(
2106 __ ConvertJSPrimitiveToUntagged(
2118 __ ConvertJSPrimitiveToUntagged(
2131 __ TruncateJSPrimitiveToUntagged(
2142 __ TryTruncateFloat64ToInt64(
2151 __ SetVariable(value,
__ ChangeInt64ToFloat64(
2152 __ template Projection<0>(tuple)));
2164 __ TruncateJSPrimitiveToUntagged(
2177 __ TryTruncateFloat64ToUint64(
2186 __ SetVariable(value,
__ ChangeUint64ToFloat64(
2187 __ template Projection<0>(tuple)));
2203 __ SetVariable(value,
__ TruncateFloat64ToFloat32(f));
2205 __ SetVariable(value, f);
2221#undef ELSE_UNREACHABLE
2224 std::optional<
decltype(
assembler)::CatchScope> catch_scope;
2225 if (is_final_control) {
2226 Block* catch_block =
Map(block->SuccessorAt(1));
2227 catch_scope.emplace(assembler, catch_block);
2230 base::SmallVector<OpIndex, 16> arguments;
2231 for (
int i = 0;
i < c_arg_count; ++
i) {
2238 const FastApiCallParameters* parameters =
2243 CTypeInfo return_type = parameters->c_signature()->ReturnInfo();
2244 int return_count = 2;
2248 const base::Vector<RegisterRepresentation> out_reps =
2249 graph_zone->AllocateVector<RegisterRepresentation>(return_count);
2252 return_type, parameters->c_signature()->GetInt64Representation());
2255 __ FastApiCall(dominating_frame_state, data_argument, context,
2258 V<Word32> result_state =
__ template Projection<0>(fast_call_result);
2260 __ template Projection<1>(fast_call_result, out_reps[1]);
2262 __ SetVariable(
result, result_value);
2273 slow_call_callee, dominating_frame_state,
2278 convert_fallback_return(
2279 result, parameters->c_signature()->GetInt64Representation(),
2280 return_type.GetType(), fallback_result);
2283 if (is_final_control) {
2288 __ Goto(
Map(block->SuccessorAt(0)));
2293 case IrOpcode::kRuntimeAbort:
2297 case IrOpcode::kDateNow:
2298 return __ CallRuntime_DateCurrentTime(isolate,
__ NoContextConstant());
2300 case IrOpcode::kEnsureWritableFastElements:
2301 return __ EnsureWritableFastElements(
Map(node->InputAt(0)),
2302 Map(node->InputAt(1)));
2304 case IrOpcode::kMaybeGrowFastElements: {
2305 DCHECK(dominating_frame_state.valid());
2306 const GrowFastElementsParameters& params =
2308 return __ MaybeGrowFastElements(
2309 Map(node->InputAt(0)),
Map(node->InputAt(1)),
Map(node->InputAt(2)),
2310 Map(node->InputAt(3)), dominating_frame_state, params.mode(),
2314 case IrOpcode::kTransitionElementsKind:
2315 __ TransitionElementsKind(
Map(node->InputAt(0)),
2318 case IrOpcode::kTransitionElementsKindOrCheckMap: {
2319 DCHECK(dominating_frame_state.valid());
2322 __ TransitionElementsKindOrCheckMap(
2323 receiver, map, dominating_frame_state,
2327 case IrOpcode::kAssertType: {
2329 CHECK(type.CanBeAsserted());
2332 DCHECK(isolate->CurrentLocalHeap()->is_main_thread());
2333 std::optional<UnparkedScope> unparked_scope;
2334 if (isolate->CurrentLocalHeap()->IsParked()) {
2335 unparked_scope.emplace(isolate->main_thread_local_isolate());
2338 __ HeapConstant(type.AllocateOnHeap(isolate->factory()));
2340 __ CallBuiltin_CheckTurbofanType(isolate,
__ NoContextConstant(),
2341 Map(node->InputAt(0)), allocated_type,
2342 __ TagSmi(node->id()));
2346 case IrOpcode::kFindOrderedHashMapEntry:
2347 return __ FindOrderedHashMapEntry(
Map(node->InputAt(0)),
2348 Map(node->InputAt(1)));
2349 case IrOpcode::kFindOrderedHashSetEntry:
2350 return __ FindOrderedHashSetEntry(
Map(node->InputAt(0)),
2351 Map(node->InputAt(1)));
2352 case IrOpcode::kFindOrderedHashMapEntryForInt32Key:
2353 return __ FindOrderedHashMapEntryForInt32Key(
Map(node->InputAt(0)),
2354 Map(node->InputAt(1)));
2356 case IrOpcode::kBeginRegion:
2359 case IrOpcode::kFinishRegion:
2361 return Map(node->InputAt(0));
2363 case IrOpcode::kTypeGuard:
2364 return Map(node->InputAt(0));
2366 case IrOpcode::kAbortCSADcheck:
2367 __ AbortCSADcheck(
Map(node->InputAt(0)));
2370 case IrOpcode::kDebugBreak:
2374 case IrOpcode::kComment:
2378 case IrOpcode::kAssert: {
2380 __ AssertImpl(
Map(node->InputAt(0)), p.condition_string(), p.file(),
2385 case IrOpcode::kBitcastTaggedToWordForTagAndSmiBits:
2388 return __ BitcastTaggedToWordPtrForTagAndSmiBits(
Map(node->InputAt(0)));
2389 case IrOpcode::kBitcastWordToTaggedSigned:
2390 return __ BitcastWordPtrToSmi(
Map(node->InputAt(0)));
2392 case IrOpcode::kWord32AtomicLoad:
2393 case IrOpcode::kWord64AtomicLoad: {
2410 RegisterRepresentation result_rep =
2418 result_rep = node->opcode() == IrOpcode::kWord32AtomicLoad
2420 : RegisterRepresentation::
Word64();
2421 return __ TaggedBitcast(
2434 case IrOpcode::kWord32AtomicStore:
2435 case IrOpcode::kWord64AtomicStore: {
2456 p.write_barrier_kind(), 0, 0,
true);
2460 case IrOpcode::kWord32AtomicAdd:
2461 case IrOpcode::kWord32AtomicSub:
2462 case IrOpcode::kWord32AtomicAnd:
2463 case IrOpcode::kWord32AtomicOr:
2464 case IrOpcode::kWord32AtomicXor:
2465 case IrOpcode::kWord32AtomicExchange:
2466 case IrOpcode::kWord32AtomicCompareExchange:
2467 case IrOpcode::kWord64AtomicAdd:
2468 case IrOpcode::kWord64AtomicSub:
2469 case IrOpcode::kWord64AtomicAnd:
2470 case IrOpcode::kWord64AtomicOr:
2471 case IrOpcode::kWord64AtomicXor:
2472 case IrOpcode::kWord64AtomicExchange:
2473 case IrOpcode::kWord64AtomicCompareExchange: {
2474 int input_index = 0;
2478 if (node->opcode() == IrOpcode::kWord32AtomicCompareExchange ||
2479 node->opcode() == IrOpcode::kWord64AtomicCompareExchange) {
2480 expected =
Map(node->InputAt(input_index++));
2482 OpIndex value =
Map(node->InputAt(input_index++));
2484 switch (node->opcode()) {
2485#define BINOP(binop, size) \
2486 case IrOpcode::kWord##size##Atomic##binop: \
2487 return __ AtomicRMW(base, offset, value, AtomicRMWOp::BinOp::k##binop, \
2488 RegisterRepresentation::Word##size(), \
2489 MemoryRepresentation::FromMachineType(p.type()), \
2504 case IrOpcode::kWord32AtomicCompareExchange:
2505 return __ AtomicCompareExchange(
2508 case IrOpcode::kWord64AtomicCompareExchange:
2509 return __ AtomicCompareExchange(
2517 case IrOpcode::kWord32AtomicPairLoad:
2518 return __ AtomicWord32PairLoad(
Map(node->InputAt(0)),
2519 Map(node->InputAt(1)), 0);
2520 case IrOpcode::kWord32AtomicPairStore:
2521 return __ AtomicWord32PairStore(
2522 Map(node->InputAt(0)),
Map(node->InputAt(1)),
Map(node->InputAt(2)),
2523 Map(node->InputAt(3)), 0);
2525#define ATOMIC_WORD32_PAIR_BINOP(kind) \
2526 case IrOpcode::kWord32AtomicPair##kind: \
2527 return __ AtomicWord32PairBinop( \
2528 Map(node->InputAt(0)), Map(node->InputAt(1)), Map(node->InputAt(2)), \
2529 Map(node->InputAt(3)), AtomicRMWOp::BinOp::k##kind, 0);
2536 case IrOpcode::kWord32AtomicPairCompareExchange:
2537 return __ AtomicWord32PairCompareExchange(
2538 Map(node->InputAt(0)),
Map(node->InputAt(1)),
Map(node->InputAt(4)),
2539 Map(node->InputAt(5)),
Map(node->InputAt(2)),
Map(node->InputAt(3)),
2542#ifdef V8_ENABLE_WEBASSEMBLY
2543#define SIMD128_BINOP(name) \
2544 case IrOpcode::k##name: \
2545 return __ Simd128Binop(Map(node->InputAt(0)), Map(node->InputAt(1)), \
2546 Simd128BinopOp::Kind::k##name);
2547 FOREACH_SIMD_128_BINARY_BASIC_OPCODE(SIMD128_BINOP)
2549 case IrOpcode::kI8x16Swizzle: {
2551 return __ Simd128Binop(
Map(node->InputAt(0)),
Map(node->InputAt(1)),
2553 ? Simd128BinopOp::Kind::kI8x16RelaxedSwizzle
2554 : Simd128BinopOp::Kind::kI8x16Swizzle);
2557#define SIMD128_UNOP(name) \
2558 case IrOpcode::k##name: \
2559 return __ Simd128Unary(Map<Simd128>(node->InputAt(0)), \
2560 Simd128UnaryOp::Kind::k##name);
2561 FOREACH_SIMD_128_UNARY_OPCODE(SIMD128_UNOP)
2564#define SIMD128_SHIFT(name) \
2565 case IrOpcode::k##name: \
2566 return __ Simd128Shift(Map<Simd128>(node->InputAt(0)), \
2567 Map<Word32>(node->InputAt(1)), \
2568 Simd128ShiftOp::Kind::k##name);
2569 FOREACH_SIMD_128_SHIFT_OPCODE(SIMD128_SHIFT)
2572#define SIMD128_TEST(name) \
2573 case IrOpcode::k##name: \
2574 return __ Simd128Test(Map<Simd128>(node->InputAt(0)), \
2575 Simd128TestOp::Kind::k##name);
2576 FOREACH_SIMD_128_TEST_OPCODE(SIMD128_TEST)
2579#define SIMD128_SPLAT(name) \
2580 case IrOpcode::k##name##Splat: \
2581 return __ Simd128Splat(Map<Any>(node->InputAt(0)), \
2582 Simd128SplatOp::Kind::k##name);
2583 FOREACH_SIMD_128_SPLAT_OPCODE(SIMD128_SPLAT)
2586#define SIMD128_TERNARY(name) \
2587 case IrOpcode::k##name: \
2588 return __ Simd128Ternary(Map(node->InputAt(0)), Map(node->InputAt(1)), \
2589 Map(node->InputAt(2)), \
2590 Simd128TernaryOp::Kind::k##name);
2591 FOREACH_SIMD_128_TERNARY_OPCODE(SIMD128_TERNARY)
2592#undef SIMD128_TERNARY
2594#define SIMD128_EXTRACT_LANE(name, suffix) \
2595 case IrOpcode::k##name##ExtractLane##suffix: \
2596 return __ Simd128ExtractLane(Map<Simd128>(node->InputAt(0)), \
2597 Simd128ExtractLaneOp::Kind::k##name##suffix, \
2598 OpParameter<int32_t>(node->op()));
2599 SIMD128_EXTRACT_LANE(I8x16,
S)
2600 SIMD128_EXTRACT_LANE(I8x16,
U)
2601 SIMD128_EXTRACT_LANE(I16x8,
S)
2602 SIMD128_EXTRACT_LANE(I16x8,
U)
2603 SIMD128_EXTRACT_LANE(I32x4, )
2604 SIMD128_EXTRACT_LANE(I64x2, )
2605 SIMD128_EXTRACT_LANE(F32x4, )
2606 SIMD128_EXTRACT_LANE(F64x2, )
2609#define SIMD128_REPLACE_LANE(name) \
2610 case IrOpcode::k##name##ReplaceLane: \
2611 return __ Simd128ReplaceLane(Map<Simd128>(node->InputAt(0)), \
2612 Map<Any>(node->InputAt(1)), \
2613 Simd128ReplaceLaneOp::Kind::k##name, \
2614 OpParameter<int32_t>(node->op()));
2615 SIMD128_REPLACE_LANE(I8x16)
2616 SIMD128_REPLACE_LANE(I16x8)
2617 SIMD128_REPLACE_LANE(I32x4)
2618 SIMD128_REPLACE_LANE(I64x2)
2619 SIMD128_REPLACE_LANE(F32x4)
2620 SIMD128_REPLACE_LANE(F64x2)
2621#undef SIMD128_REPLACE_LANE
2623 case IrOpcode::kLoadStackPointer:
2624 return __ LoadStackPointer();
2626 case IrOpcode::kSetStackPointer:
2627 __ SetStackPointer(
Map(node->InputAt(0)));
2632 case IrOpcode::kJSStackCheck: {
2637 __ JSFunctionEntryStackCheck(context, frame_state);
2641 case IrOpcode::kInt32PairAdd:
2642 case IrOpcode::kInt32PairSub:
2643 case IrOpcode::kInt32PairMul:
2644 case IrOpcode::kWord32PairShl:
2645 case IrOpcode::kWord32PairSar:
2646 case IrOpcode::kWord32PairShr: {
2652 switch (node->opcode()) {
2653 case IrOpcode::kInt32PairAdd:
2656 case IrOpcode::kInt32PairSub:
2659 case IrOpcode::kInt32PairMul:
2662 case IrOpcode::kWord32PairShl:
2665 case IrOpcode::kWord32PairSar:
2668 case IrOpcode::kWord32PairShr:
2674 return __ Word32PairBinop(left_low, left_high, right_low, right_high,
2678#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA
2679 case IrOpcode::kGetContinuationPreservedEmbedderData:
2680 return __ GetContinuationPreservedEmbedderData();
2681 case IrOpcode::kSetContinuationPreservedEmbedderData:
2682 __ SetContinuationPreservedEmbedderData(
Map(node->InputAt(0)));
2687 std::cerr <<
"unsupported node type: " << *node->op() <<
"\n";
2688 node->Print(std::cerr);
2701 data->graph().SetCreatedFromTurbofan();
2703 return builder.Run();
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
static constexpr MachineType AnyTagged()
constexpr bool IsMapWord() const
static constexpr MachineType TaggedPointer()
static constexpr int ToInt(const Tagged< Object > object)
static constexpr Tagged< Smi > FromInt(int value)
V8_INLINE constexpr StorageType ptr() const
static FieldAccess ForJSPrimitiveWrapperValue()
FeedbackSource const & feedback() const
FeedbackSource const & feedback() const
static constexpr int kCallbackData
IndirectHandle< Map > object() const
static MachineRepresentation GetProjectionType(Node const *projection)
static Node * GetValueInput(Node *node, int index)
static constexpr MemoryRepresentation FromMachineRepresentation(MachineRepresentation rep)
static MemoryRepresentation FromMachineType(MachineType type)
static MemoryRepresentation FromRegisterRepresentation(RegisterRepresentation repr, bool is_signed)
static constexpr MemoryRepresentation Uint32()
static constexpr OpIndex Invalid()
static OptionalV Nullopt()
static constexpr RegisterRepresentation FromMachineType(MachineType type)
static constexpr RegisterRepresentation FromMachineRepresentation(MachineRepresentation rep)
static constexpr RegisterRepresentation Word32()
static constexpr RegisterRepresentation WordPtr()
static constexpr RegisterRepresentation FromCTypeInfo(CTypeInfo t, CFunctionInfo::Int64Representation int64_repr)
static constexpr RegisterRepresentation Word64()
static constexpr RegisterRepresentation Tagged()
static std::optional< Type > ParseFromString(const std::string_view &str, Zone *zone)
static V< T > Cast(V< U > index)
static constexpr WordRepresentation Word32()
static constexpr WordRepresentation WordPtr()
#define V8_ENABLE_SANDBOX_BOOL
#define CONVERT_PRIMITIVE_TO_OBJECT_CASE(name, kind, input_type, input_interpretation)
JsWasmCallsSidetable * js_wasm_calls_sidetable
#define TRUNCATE_OBJECT_TO_PRIMITIVE_CASE(name, kind, input_assumptions)
TurboshaftPipelineKind pipeline_kind
#define BIGINT_BINOP_CASE(op, kind)
#define UNARY_CASE(opcode, assembler_op)
#define BINOP(binop, size)
NodeAuxData< OpIndex > op_mapping
#define CHANGE_OR_DEOPT_INT_CASE(kind)
#define CONVERT_PRIMITIVE_TO_OBJECT_OR_DEOPT_CASE(name, kind, input_type, input_interpretation)
#define ATOMIC_WORD32_PAIR_BINOP(kind)
#define CHECK_OBJECT_IS_CASE(code, kind, input_assumptions, reason, feedback)
#define BINOP_CASE(opcode, assembler_op)
NodeOriginTable * origins
SourcePositionTable * source_positions
#define OBJECT_IS_CASE(kind)
ZoneVector< BlockData > block_mapping
#define CONVERT_OBJECT_TO_PRIMITIVE_CASE(name, kind, input_assumptions)
OpIndex final_frame_state
ZoneVector< RpoNumber > & result
InstructionOperand destination
void * Allocate(void *address, size_t size, OS::MemoryPermission access)
constexpr Vector< T > VectorOf(T *start, size_t size)
bool Word32Equal(uint32_t a, uint32_t b)
TNode< Oddball > UndefinedConstant(JSGraph *jsgraph)
constexpr size_t input_count()
std::optional< BailoutReason > BuildGraph(PipelineData *data, Schedule *schedule, Zone *phase_zone, Linkage *linkage, JsWasmCallsSidetable *js_wasm_calls_sidetable)
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
any_of(const Args &...) -> any_of< Args... >
WordWithBits< 64 > Word64
WordWithBits< 32 > Word32
SnapshotTable< OpIndex, VariableData >::Key Variable
OptionalV(V< T >) -> OptionalV< T >
uint32_t ObjectIdOf(Operator const *op)
IfValueParameters const & IfValueParametersOf(const Operator *op)
AtomicOpParameters AtomicOpParametersOf(Operator const *op)
const GrowFastElementsParameters & GrowFastElementsParametersOf(const Operator *op)
CheckParameters const & CheckParametersOf(Operator const *op)
size_t ProjectionIndexOf(const Operator *const op)
StackCheckKind StackCheckKindOf(Operator const *op)
AtomicStoreParameters const & AtomicStoreParametersOf(Operator const *op)
ArgumentsStateType ArgumentsStateTypeOf(Operator const *op)
const CheckTaggedInputParameters & CheckTaggedInputParametersOf(const Operator *op)
NumberConstant(std::numeric_limits< double >::quiet_NaN())) DEFINE_GETTER(EmptyStateValues
const NewArgumentsElementsParameters & NewArgumentsElementsParametersOf(const Operator *op)
CheckMapsParameters const & CheckMapsParametersOf(Operator const *op)
BranchHint BranchHintOf(const Operator *const op)
Handle< HeapObject > HeapConstantOf(const Operator *op)
const AssertParameters & AssertParametersOf(const Operator *const op)
CheckFloat64HoleParameters const & CheckFloat64HoleParametersOf(Operator const *op)
StoreRepresentation const & StoreRepresentationOf(Operator const *op)
CheckIfParameters const & CheckIfParametersOf(Operator const *op)
const char * StaticAssertSourceOf(const Operator *op)
const CheckMinusZeroParameters & CheckMinusZeroParametersOf(const Operator *op)
CallDescriptor const * CallDescriptorOf(const Operator *const op)
int FormalParameterCountOf(const Operator *op)
AtomicLoadParameters AtomicLoadParametersOf(Operator const *op)
int ParameterIndexOf(const Operator *const op)
const FieldAccess & FieldAccessOf(const Operator *op)
const ElementAccess & ElementAccessOf(const Operator *op)
const AllocateParameters & AllocateParametersOf(const Operator *op)
const ParameterInfo & ParameterInfoOf(const Operator *const op)
ZoneRefSet< Map > const & CompareMapsParametersOf(Operator const *op)
CheckBoundsParameters const & CheckBoundsParametersOf(Operator const *op)
const ObjectAccess & ObjectAccessOf(const Operator *op)
ZoneMap< NodeId, const JSWasmCallParameters * > JsWasmCallsSidetable
StackSlotRepresentation const & StackSlotRepresentationOf(Operator const *op)
DeoptimizeParameters const & DeoptimizeParametersOf(Operator const *const op)
MapRef FastMapParameterOf(const Operator *op)
Handle< FeedbackCell > FeedbackCellOf(const Operator *op)
Type ValueTypeParameterOf(const Operator *op)
SelectParameters const & SelectParametersOf(const Operator *const op)
LoadRepresentation LoadRepresentationOf(Operator const *op)
ExternalArrayType ExternalArrayTypeOf(const Operator *op)
ZoneVector< BasicBlock * > BasicBlockVector
T const & OpParameter(const Operator *op)
ConvertReceiverMode ConvertReceiverModeOf(Operator const *op)
AllocationType AllocationTypeOf(const Operator *op)
CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator *op)
@ kProtectedByTrapHandler
UnalignedStoreRepresentation const & UnalignedStoreRepresentationOf(Operator const *op)
ElementsTransitionWithMultipleSources const & ElementsTransitionWithMultipleSourcesOf(const Operator *op)
ElementsTransition const & ElementsTransitionOf(const Operator *op)
AbortReason AbortReasonOf(const Operator *op)
MachineRepresentation PhiRepresentationOf(const Operator *const op)
Node::Uses::const_iterator begin(const Node::Uses &uses)
ShiftKind ShiftKindOf(Operator const *op)
int OsrValueIndexOf(Operator const *op)
ZoneCompactSet< typename ref_traits< T >::ref_type > ZoneRefSet
HeapObjectMatcherImpl< IrOpcode::kHeapConstant > HeapObjectMatcher
MapRef DoubleMapParameterOf(const Operator *op)
void Store(LiftoffAssembler *assm, LiftoffRegister src, MemOperand dst, ValueKind kind)
constexpr MachineType machine_type(ValueKind kind)
bool TryCast(Tagged< From > value, Tagged< To > *out)
constexpr int kTaggedSize
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr int kAdditiveSafeIntegerShift
T * NewArray(size_t size)
i::Address Load(i::Address address)
#define DCHECK_NOT_NULL(val)
#define DCHECK_NE(v1, v2)
#define CHECK_NE(lhs, rhs)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
static constexpr uint32_t kFailureValue
static const FastApiCallParameters * Create(FastApiCallFunction c_function, Zone *graph_zone)
static constexpr Kind TaggedBase()
static constexpr Kind RawAligned()
static constexpr Kind Protected()
static constexpr Kind Aligned(BaseTaggedness base_is_tagged)
constexpr Kind Atomic() const
const uint16_t input_count
static const TSCallDescriptor * Create(const CallDescriptor *descriptor, CanThrow can_throw, LazyDeoptOnThrow lazy_deopt_on_throw, Zone *graph_zone, const JSWasmCallParameters *js_wasm_call_parameters=nullptr)
static constexpr uint32_t kSuccessValue
#define V8_UNLIKELY(condition)
std::unique_ptr< ValueMirror > value