32#if V8_ENABLE_WEBASSEMBLY
106 if (
kind != other_kind)
return false;
119 int num_slots_other =
121 const bool complex_stack_slot_interference =
122 (num_slots > 1 || num_slots_other > 1);
123 if (!complex_stack_slot_interference) {
132 int index_hi = loc.
index();
136 int other_index_hi = other_loc.
index();
140 return other_index_hi >= index_lo && index_hi >= other_index_lo;
201 return os <<
"[constant:v" << ConstantOperand::cast(op).virtual_register()
205 switch (imm.
type()) {
211 return os <<
"[rpo_immediate:" << imm.
indexed_value() <<
"]";
217 return os <<
"[pending: " << PendingOperand::cast(op).next() <<
"]";
221 os <<
"[stack:" << allocated.index();
223 os <<
"[fp_stack:" << allocated.index();
229 os <<
"[" << name <<
"|R";
236#if V8_TARGET_ARCH_X64
246 switch (allocated.representation()) {
323 os <<
" = " << mo.
source();
330 if (!move->IsRedundant())
return false;
338 !move->destination().IsFPLocationOperand();
343 if (curr->
destination().EqualsCanonicalized(move->source())) {
348 if (no_aliasing && eliminated !=
nullptr)
break;
349 }
else if (curr->
destination().InterferesWith(move->destination())) {
354 if (no_aliasing && replacement !=
nullptr)
break;
361 if (this->
size() != that.size())
return false;
362 for (
size_t i = 0;
i < this->
size(); ++
i) {
363 if (!(*
this)[
i]->
Equals(*that[
i]))
return false;
378 reference_map_(nullptr),
396 reference_map_(nullptr),
401 for (
size_t i = 0;
i < output_count; ++
i) {
402 DCHECK(!outputs[
i].IsInvalid());
405 for (
size_t i = 0;
i < input_count; ++
i) {
406 DCHECK(!inputs[
i].IsInvalid());
409 for (
size_t i = 0;
i < temp_count; ++
i) {
428 const char* delimiter =
"";
430 if (move->IsEliminated())
continue;
431 os << delimiter << *move;
483 return os <<
"branch";
485 return os <<
"deoptimize";
491 return os <<
"select";
493 return os <<
"conditional set";
495 return os <<
"conditional branch";
503 return os <<
"equal";
505 return os <<
"not equal";
507 return os <<
"signed less than";
509 return os <<
"signed greater than or equal";
511 return os <<
"signed less than or equal";
513 return os <<
"signed greater than";
515 return os <<
"unsigned less than";
517 return os <<
"unsigned greater than or equal";
519 return os <<
"unsigned less than or equal";
521 return os <<
"unsigned greater than";
523 return os <<
"less than or unordered (FP)";
525 return os <<
"greater than or equal (FP)";
527 return os <<
"less than or equal (FP)";
529 return os <<
"greater than or unordered (FP)";
531 return os <<
"less than (FP)";
533 return os <<
"greater than, equal or unordered (FP)";
535 return os <<
"less than, equal or unordered (FP)";
537 return os <<
"greater than (FP)";
539 return os <<
"unordered equal";
541 return os <<
"unordered not equal";
543 return os <<
"overflow";
545 return os <<
"not overflow";
547 return os <<
"positive or zero";
549 return os <<
"negative";
551 return os <<
"is nan";
553 return os <<
"is not nan";
582 if (am != kMode_None) {
625 switch (constant.type()) {
627 return os << constant.ToInt32();
629 return os << constant.ToInt64() <<
"l";
631 return os << constant.ToFloat32() <<
"f";
633 return os << constant.ToFloat64().value();
635 return os << constant.ToExternalReference();
638 return os <<
Brief(*constant.ToHeapObject());
640 return os <<
"RPO" << constant.ToRpoNumber().ToInt();
647 : virtual_register_(virtual_register),
670 rpo_number_(rpo_number),
671 loop_header_(loop_header),
673 dominator_(dominator),
676 switch_target_(false),
677 code_target_alignment_(false),
678 loop_header_alignment_(false),
679 needs_frame_(!
v8_flags.turbo_elide_frames),
680 must_construct_frame_(false),
681 must_deconstruct_frame_(false),
682 omitted_by_jump_threading_(false) {}
720 !block->empty() && block->front()->opcode() == IrOpcode::kIfException;
723 GetRpo(block->dominator()), block->deferred(), is_handler);
733 if (block->PredecessorCount() == 1 &&
745 bool deferred = block->get_custom_data(
749 GetRpo(block->GetDominator()), deferred, is_handler);
750 if (block->PredecessorCount() == 1) {
779 os <<
"B" << block->rpo_number();
780 if (block->ao_number().IsValid()) {
781 os <<
": AO#" << block->ao_number();
785 if (block->IsDeferred()) os <<
" (deferred)";
786 if (!block->needs_frame()) os <<
" (no frame)";
787 if (block->must_construct_frame()) os <<
" (construct frame)";
788 if (block->must_deconstruct_frame()) os <<
" (deconstruct frame)";
789 if (block->IsLoopHeader()) {
790 os <<
" loop blocks: [" << block->rpo_number() <<
", " << block->loop_end()
793 os <<
" instructions: [" << block->code_start() <<
", " << block->code_end()
797 for (
RpoNumber pred : block->predecessors()) {
798 os <<
" B" << pred.ToInt();
803 os <<
" phi: " << phi->output() <<
" =";
804 for (
int input : phi->operands()) {
810 for (
int j = block->first_instruction_index();
811 j <= block->last_instruction_index(); j++) {
812 os <<
" " << std::setw(5) << j <<
": " << *code->InstructionAt(j)
816 os <<
" successors:";
817 for (
RpoNumber succ : block->successors()) {
818 os <<
" B" << succ.ToInt();
828 static_cast<int>(
schedule->rpo_order()->size()),
nullptr,
zone);
829 size_t rpo_number = 0;
831 it !=
schedule->rpo_order()->end(); ++it, ++rpo_number) {
832 DCHECK(!(*blocks)[rpo_number]);
844 size_t rpo_number = 0;
851 DCHECK(!(*blocks)[rpo_number]);
864 if (block->SuccessorCount() > 1) {
865 for (
const RpoNumber& successor_id : block->successors()) {
879 if (!block->IsDeferred() || block->SuccessorCount() <= 1)
continue;
880 for (
RpoNumber successor_id : block->successors()) {
893 if (!block->IsDeferred() || block->PredecessorCount() <= 1)
continue;
894 for (
RpoNumber predecessor_id : block->predecessors()) {
904 for (
size_t i = 0;
i < instruction->OutputCount(); ++
i) {
906 int vreg = (output->IsConstant())
907 ? ConstantOperand::cast(output)->virtual_register()
908 : UnallocatedOperand::cast(output)->virtual_register();
910 definitions.
Add(vreg);
926 if (block->IsDeferred())
continue;
927 if (block->ao_number() != invalid)
continue;
928 if (block->IsLoopHeader()) {
929 bool header_align =
true;
936 loop_end != block ) {
945 header_align =
false;
948 block->set_loop_header_alignment(header_align);
950 if (block->loop_header().IsValid() && block->IsSwitchTarget()) {
951 block->set_code_target_alignment(
true);
958 if (block->ao_number() == invalid) {
969 block->set_ao_number(invalid);
975 Zone* instruction_zone,
978 zone_(instruction_zone),
979 instruction_blocks_(instruction_blocks),
984 source_positions_(zone(), instruction_blocks->size() * 2),
986 constants_(zone(), 256),
988 rpo_immediates_(instruction_blocks->size(), zone()),
989 instructions_(zone()),
990 next_virtual_register_(0),
991 reference_maps_(zone()),
992 representations_(zone()),
993 representation_mask_(0),
994 deoptimization_entries_(zone()),
1002 return virtual_register;
1031 if (
instr->NeedsReferenceMap()) {
1035 instr->set_reference_map(reference_map);
1072 int virtual_register)
const {
1082 int virtual_register) {
1101 return deoptimization_id;
1112 operand->IsImmediate()
1114 :
GetConstant(ConstantOperand::cast(operand)->virtual_register());
1115 return constant.ToRpoNumber();
1138 CHECK(block->rpo_number() == rpo);
1160 size_t parameters_count,
1161 size_t locals_count,
1163 uint32_t wasm_liftoff_frame_size) {
1167 static_cast<int>(parameters_count),
static_cast<int>(locals_count));
1168 return info.frame_size_in_bytes();
1178 static_cast<int>(parameters_count));
1179#if V8_ENABLE_WEBASSEMBLY
1180 case FrameStateType::kWasmInlinedIntoJS:
1184 static_cast<int>(parameters_count));
1185 return info.frame_size_in_bytes();
1190#if V8_ENABLE_WEBASSEMBLY
1191 case FrameStateType::kJSToWasmBuiltinContinuation:
1197 static_cast<int>(parameters_count),
1201 return info.frame_size_in_bytes();
1203#if V8_ENABLE_WEBASSEMBLY
1204 case FrameStateType::kLiftoffFunction:
1205 return wasm_liftoff_frame_size;
1212 size_t parameters_count,
1213 size_t locals_count,
1214 BytecodeOffset bailout_id,
1215 uint32_t wasm_liftoff_frame_size,
1216 FrameStateDescriptor* outer_state) {
1217 size_t outer_total_conservative_frame_size_in_bytes =
1218 (outer_state ==
nullptr)
1220 : outer_state->total_conservative_frame_size_in_bytes();
1221 return GetConservativeFrameSizeInBytes(type, parameters_count, locals_count,
1222 bailout_id, wasm_liftoff_frame_size) +
1223 outer_total_conservative_frame_size_in_bytes;
1231 uint16_t max_arguments,
size_t locals_count,
size_t stack_count,
1235 uint32_t wasm_function_index)
1237 bailout_id_(bailout_id),
1238 frame_state_combine_(state_combine),
1239 parameters_count_(parameters_count),
1240 max_arguments_(max_arguments),
1241 locals_count_(locals_count),
1242 stack_count_(stack_count),
1243 total_conservative_frame_size_in_bytes_(
1244 GetTotalConservativeFrameSizeInBytes(
1245 type, parameters_count, locals_count, bailout_id,
1246 wasm_liftoff_frame_size, outer_state)),
1248 shared_info_(shared_info),
1249 bytecode_array_(bytecode_array),
1250 outer_state_(outer_state),
1251 wasm_function_index_(wasm_function_index) {}
1258#if V8_ENABLE_WEBASSEMBLY
1259 case FrameStateType::kJSToWasmBuiltinContinuation:
1260 case FrameStateType::kWasmInlinedIntoJS:
1276#if V8_ENABLE_WEBASSEMBLY
1277 case FrameStateType::kLiftoffFunction:
1290 size_t total_size = 0;
1293 total_size += iter->GetSize();
1318#if V8_ENABLE_WEBASSEMBLY
1319JSToWasmFrameStateDescriptor::JSToWasmFrameStateDescriptor(
1322 size_t locals_count,
size_t stack_count,
1326 parameters_count, 0, locals_count, stack_count,
1327 shared_info, {}, outer_state),
1332 return os << rpo.
ToSize();
1336 for (
size_t i = 0;
i < code.immediates_.
size(); ++
i) {
1337 Constant constant = code.immediates_[
i];
1338 os <<
"IMM#" <<
i <<
": " << constant <<
"\n";
1341 for (ConstantMap::const_iterator it = code.constants_.begin();
1342 it != code.constants_.end(); ++n, ++it) {
1343 os <<
"CST#" << n <<
": v" << it->first <<
" = " << it->second <<
"\n";
1345 for (
int i = 0;
i < code.InstructionBlockCount();
i++) {
1355 return os <<
"ArgumentsElements";
1357 return os <<
"ArgumentsLength";
1359 return os <<
"RestLength";
1361 return os <<
"Plain";
1363 return os <<
"OptimizedOut";
1365 return os <<
"NestedObject";
1367 return os <<
"Duplicate";
1369 return os <<
"StringConcat";
1374 os <<
"kind=" <<
kind_ <<
", type=" <<
type_;
1377 os <<
", id=" <<
id_;
static constexpr T decode(U value)
static int NumSlotsForWidth(int bytes)
bool Contains(int i) const
static BuiltinContinuationFrameInfo Conservative(int parameters_count, const CallInterfaceDescriptor &continuation_descriptor, const RegisterConfiguration *register_config)
static CallInterfaceDescriptor CallInterfaceDescriptorFor(Builtin builtin)
static Builtin GetBuiltinFromBytecodeOffset(BytecodeOffset)
static ConstructStubFrameInfo Conservative(int parameters_count)
uint32_t frame_size_in_bytes() const
static FastConstructStubFrameInfo Conservative()
static constexpr int8_t kNumRegisters
static constexpr QwNeonRegister from_code(int8_t code)
static const RegisterConfiguration * Default()
static constexpr Register from_code(int code)
static const char * GetSpecialRegisterName(int code)
static uint32_t GetStackSizeForAdditionalArguments(int parameters_count)
static UnoptimizedFrameInfo Conservative(int parameters_count_with_receiver, int locals_count)
static constexpr YMMRegister from_code(int code)
void reserve(size_t new_cap)
void resize(size_t new_size)
const RpoNumber * const_iterator
void push_back(const T &value)
T * AllocateArray(size_t length)
BasicBlockVector & successors()
BasicBlockVector & predecessors()
IndirectHandle< HeapObject > ToHeapObject() const
IndirectHandle< Code > ToCode() const
size_t GetJSFrameCount() const
size_t stack_count() const
FrameStateDescriptor *const outer_state_
size_t GetFrameCount() const
uint16_t parameters_count() const
FrameStateDescriptor(Zone *zone, FrameStateType type, BytecodeOffset bailout_id, OutputFrameStateCombine state_combine, uint16_t parameters_count, uint16_t max_arguments, size_t locals_count, size_t stack_count, MaybeIndirectHandle< SharedFunctionInfo > shared_info, MaybeIndirectHandle< BytecodeArray > bytecode_array, FrameStateDescriptor *outer_state=nullptr, uint32_t wasm_liftoff_frame_size=std::numeric_limits< uint32_t >::max(), uint32_t wasm_function_index=std::numeric_limits< uint32_t >::max())
size_t GetTotalSize() const
size_t locals_count() const
FrameStateType type() const
static bool IsJSFunctionType(FrameStateType type)
void set_code_start(int32_t start)
Successors & successors()
void set_loop_header_alignment(bool val)
int32_t code_start() const
void set_code_end(int32_t end)
size_t PredecessorIndexOf(RpoNumber rpo_number) const
void set_ao_number(RpoNumber ao_number)
InstructionBlock(Zone *zone, RpoNumber rpo_number, RpoNumber loop_header, RpoNumber loop_end, RpoNumber dominator, bool deferred, bool handler)
RpoNumber rpo_number() const
Predecessors & predecessors()
void set_switch_target(bool val)
Predecessors predecessors_
size_t PredecessorCount() const
size_t SuccessorCount() const
bool IsSimd256Register() const
bool IsDoubleStackSlot() const
bool EqualsCanonicalized(const InstructionOperand &that) const
bool IsFPRegister() const
bool IsFloatRegister() const
bool IsSimd128StackSlot() const
bool IsFloatStackSlot() const
bool IsDoubleRegister() const
bool IsSimd128Register() const
bool IsFPLocationOperand() const
static const int kInvalidVirtualRegister
bool IsFPStackSlot() const
bool IsAnyStackSlot() const
bool InterferesWith(const InstructionOperand &other) const
DeoptimizationEntry const & GetDeoptimizationEntry(int deoptimization_id)
Instructions instructions_
Constant GetImmediate(const ImmediateOperand *op) const
RpoNumber InputRpo(Instruction *instr, size_t index)
static const RegisterConfiguration * registerConfigurationForTesting_
void ValidateDeferredBlockExitPaths() const
void ComputeAssemblyOrder()
Instruction * InstructionAt(int index) const
void ValidateEdgeSplitForm() const
int VirtualRegisterCount() const
InstructionBlocks * ao_blocks_
int AddDeoptimizationEntry(FrameStateDescriptor *descriptor, DeoptimizeKind kind, DeoptimizeReason reason, NodeId node_id, FeedbackSource const &feedback)
Constant GetConstant(int virtual_register) const
ZoneVector< MachineRepresentation > representations_
InstructionBlock * current_block_
DeoptimizationVector deoptimization_entries_
void PrintBlock(int block_id) const
InstructionBlocks *const instruction_blocks_
static InstructionBlocks * InstructionBlocksFor(Zone *zone, const Schedule *schedule)
SourcePositionMap source_positions_
void StartBlock(RpoNumber rpo)
void EndBlock(RpoNumber rpo)
int next_virtual_register_
Instruction * GetBlockStart(RpoNumber rpo) const
bool GetSourcePosition(const Instruction *instr, SourcePosition *result) const
ReferenceMaps reference_maps_
MachineRepresentation GetRepresentation(int virtual_register) const
static const RegisterConfiguration * RegisterConfigurationForTesting()
static void SetRegisterConfigurationForTesting(const RegisterConfiguration *regConfig)
int NextVirtualRegister()
InstructionSequence(Isolate *isolate, Zone *zone, InstructionBlocks *instruction_blocks)
void MarkAsRepresentation(MachineRepresentation rep, int virtual_register)
void SetSourcePosition(const Instruction *instr, SourcePosition value)
int AddInstruction(Instruction *instr)
static MachineRepresentation DefaultRepresentation()
const InstructionBlocks & instruction_blocks() const
InstructionBlock * InstructionBlockAt(RpoNumber rpo_number)
const_iterator end() const
void ValidateDeferredBlockEntryPaths() const
void RecomputeAssemblyOrderForTesting()
ParallelMove * parallel_moves_[2]
const InstructionOperand * OutputAt(size_t i) const
InstructionCode opcode() const
const InstructionOperand * InputAt(size_t i) const
size_t OutputCount() const
ParallelMove *const * parallel_moves() const
InstructionOperand operands_[1]
size_t InputCount() const
Instruction(const Instruction &)=delete
bool AreMovesRedundant() const
MachineRepresentation representation() const
bool IsCompatible(LocationOperand *op)
LocationKind location_kind() const
static LocationOperand * cast(InstructionOperand *op)
int register_code() const
const InstructionOperand & source() const
const InstructionOperand & destination() const
bool IsEliminated() const
void set_source(const InstructionOperand &operand)
void PrepareInsertAfter(MoveOperands *move, ZoneVector< MoveOperands * > *to_eliminate) const
bool Equals(const ParallelMove &that) const
void RenameInput(size_t offset, int virtual_register)
int virtual_register() const
PhiInstruction(Zone *zone, int virtual_register, size_t input_count)
void SetInput(size_t offset, int virtual_register)
ZoneVector< InstructionOperand > reference_operands_
void RecordReference(const AllocatedOperand &op)
void set_instruction_position(int pos)
static RpoNumber Invalid()
static RpoNumber FromInt(int index)
ArgumentsStateType args_type_
void Print(std::ostream &os) const
int32_t virtual_register() const
@ REGISTER_OR_SLOT_OR_CONSTANT
BasicPolicy basic_policy() const
ExtendedPolicy extended_policy() const
int fixed_register_index() const
int fixed_slot_index() const
Block * NeighboringPredecessor() const
const Operation & LastOperation(const Graph &graph) const
Block * LastPredecessor() const
const Block * GetLoopHeader(const Block *block) const
#define TARGET_ADDRESSING_MODE_LIST(V)
#define ARCH_OPCODE_LIST(V)
ZoneVector< RpoNumber > & result
Comparator::Output * output_
BasicBlock * current_block_
base::SmallVector< int32_t, 1 > stack_slots
base::SmallVector< Block *, 4 > SuccessorBlocks(const Block &block, const Graph &graph)
@ kJavaScriptBuiltinContinuationWithCatch
@ kJavaScriptBuiltinContinuation
static RpoNumber GetLoopEndRpo(const BasicBlock *block)
static MachineRepresentation FilterRepresentation(MachineRepresentation rep)
ZoneVector< InstructionBlock * > InstructionBlocks
FlagsCondition CommuteFlagsCondition(FlagsCondition condition)
static RpoNumber GetRpo(const BasicBlock *block)
static InstructionBlock * InstructionBlockFor(Zone *zone, const BasicBlock *block)
@ kSignedGreaterThanOrEqual
@ kFloatGreaterThanOrEqualOrUnordered
@ kUnsignedLessThanOrEqual
@ kFloatLessThanOrEqualOrUnordered
@ kFloatGreaterThanOrUnordered
@ kFloatGreaterThanOrEqual
@ kUnsignedGreaterThanOrEqual
@ kFloatLessThanOrUnordered
std::ostream & operator<<(std::ostream &os, AccessMode access_mode)
@ kFlags_conditional_branch
const RegisterConfiguration *(* GetRegConfig)()
std::optional< wasm::ValueKind > WasmReturnTypeFromSignature(const CanonicalSig *wasm_signature)
constexpr AliasingKind kFPAliasing
V8_EXPORT_PRIVATE constexpr int RepresentationBit(MachineRepresentation rep)
V8_EXPORT_PRIVATE FlagValues v8_flags
V8_EXPORT_PRIVATE constexpr int ElementSizeInBytes(MachineRepresentation)
#define DCHECK_LE(v1, v2)
#define DCHECK_NOT_NULL(val)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define CHECK_NE(lhs, rhs)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
const InstructionBlock * block_
const InstructionSequence * code_
EmbedderRootsHandler * handler_
#define V8_UNLIKELY(condition)