1 // Copyright 2022 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_MAGLEV_MAGLEV_CODE_GEN_STATE_H_ 6 #define V8_MAGLEV_MAGLEV_CODE_GEN_STATE_H_ 7 8 #include "src/codegen/assembler.h" 9 #include "src/codegen/label.h" 10 #include "src/codegen/macro-assembler.h" 11 #include "src/codegen/safepoint-table.h" 12 #include "src/common/globals.h" 13 #include "src/compiler/backend/instruction.h" 14 #include "src/compiler/js-heap-broker.h" 15 #include "src/maglev/maglev-compilation-unit.h" 16 #include "src/maglev/maglev-ir.h" 17 18 namespace v8 { 19 namespace internal { 20 namespace maglev { 21 22 class InterpreterFrameState; 23 24 class DeferredCodeInfo { 25 public: 26 virtual void Generate(MaglevCodeGenState* code_gen_state, 27 Label* return_label) = 0; 28 Label deferred_code_label; 29 Label return_label; 30 }; 31 32 class MaglevCodeGenState { 33 public: MaglevCodeGenState(MaglevCompilationUnit * compilation_unit,SafepointTableBuilder * safepoint_table_builder)34 MaglevCodeGenState(MaglevCompilationUnit* compilation_unit, 35 SafepointTableBuilder* safepoint_table_builder) 36 : compilation_unit_(compilation_unit), 37 safepoint_table_builder_(safepoint_table_builder), 38 masm_(isolate(), CodeObjectRequired::kNo) {} 39 SetVregSlots(int slots)40 void SetVregSlots(int slots) { vreg_slots_ = slots; } 41 PushDeferredCode(DeferredCodeInfo * deferred_code)42 void PushDeferredCode(DeferredCodeInfo* deferred_code) { 43 deferred_code_.push_back(deferred_code); 44 } deferred_code()45 const std::vector<DeferredCodeInfo*>& deferred_code() const { 46 return deferred_code_; 47 } PushEagerDeopt(EagerDeoptInfo * info)48 void PushEagerDeopt(EagerDeoptInfo* info) { eager_deopts_.push_back(info); } PushLazyDeopt(LazyDeoptInfo * info)49 void PushLazyDeopt(LazyDeoptInfo* info) { lazy_deopts_.push_back(info); } eager_deopts()50 const std::vector<EagerDeoptInfo*>& eager_deopts() const { 51 return eager_deopts_; 52 } lazy_deopts()53 const std::vector<LazyDeoptInfo*>& lazy_deopts() const { 54 return lazy_deopts_; 55 } 56 inline void DefineSafepointStackSlots( 57 SafepointTableBuilder::Safepoint& safepoint) const; 58 native_context()59 compiler::NativeContextRef native_context() const { 60 return broker()->target_native_context(); 61 } isolate()62 Isolate* isolate() const { return compilation_unit_->isolate(); } parameter_count()63 int parameter_count() const { return compilation_unit_->parameter_count(); } register_count()64 int register_count() const { return compilation_unit_->register_count(); } bytecode_analysis()65 const compiler::BytecodeAnalysis& bytecode_analysis() const { 66 return compilation_unit_->bytecode_analysis(); 67 } broker()68 compiler::JSHeapBroker* broker() const { return compilation_unit_->broker(); } bytecode()69 const compiler::BytecodeArrayRef& bytecode() const { 70 return compilation_unit_->bytecode(); 71 } graph_labeller()72 MaglevGraphLabeller* graph_labeller() const { 73 return compilation_unit_->graph_labeller(); 74 } masm()75 MacroAssembler* masm() { return &masm_; } vreg_slots()76 int vreg_slots() const { return vreg_slots_; } safepoint_table_builder()77 SafepointTableBuilder* safepoint_table_builder() const { 78 return safepoint_table_builder_; 79 } compilation_unit()80 MaglevCompilationUnit* compilation_unit() const { return compilation_unit_; } 81 82 // TODO(v8:7700): Clean up after all code paths are supported. set_found_unsupported_code_paths(bool val)83 void set_found_unsupported_code_paths(bool val) { 84 found_unsupported_code_paths_ = val; 85 } found_unsupported_code_paths()86 bool found_unsupported_code_paths() const { 87 return found_unsupported_code_paths_; 88 } 89 90 private: 91 MaglevCompilationUnit* const compilation_unit_; 92 SafepointTableBuilder* const safepoint_table_builder_; 93 94 MacroAssembler masm_; 95 std::vector<DeferredCodeInfo*> deferred_code_; 96 std::vector<EagerDeoptInfo*> eager_deopts_; 97 std::vector<LazyDeoptInfo*> lazy_deopts_; 98 int vreg_slots_ = 0; 99 100 // Allow marking some codegen paths as unsupported, so that we can test maglev 101 // incrementally. 102 // TODO(v8:7700): Clean up after all code paths are supported. 103 bool found_unsupported_code_paths_ = false; 104 }; 105 106 // Some helpers for codegen. 107 // TODO(leszeks): consider moving this to a separate header. 108 GetFramePointerOffsetForStackSlot(int index)109inline constexpr int GetFramePointerOffsetForStackSlot(int index) { 110 return StandardFrameConstants::kExpressionsOffset - 111 index * kSystemPointerSize; 112 } 113 GetFramePointerOffsetForStackSlot(const compiler::AllocatedOperand & operand)114inline int GetFramePointerOffsetForStackSlot( 115 const compiler::AllocatedOperand& operand) { 116 return GetFramePointerOffsetForStackSlot(operand.index()); 117 } 118 GetSafepointIndexForStackSlot(int i)119inline int GetSafepointIndexForStackSlot(int i) { 120 // Safepoint tables also contain slots for all fixed frame slots (both 121 // above and below the fp). 122 return StandardFrameConstants::kFixedSlotCount + i; 123 } 124 GetStackSlot(int index)125inline MemOperand GetStackSlot(int index) { 126 return MemOperand(rbp, GetFramePointerOffsetForStackSlot(index)); 127 } 128 GetStackSlot(const compiler::AllocatedOperand & operand)129inline MemOperand GetStackSlot(const compiler::AllocatedOperand& operand) { 130 return GetStackSlot(operand.index()); 131 } 132 ToRegister(const compiler::InstructionOperand & operand)133inline Register ToRegister(const compiler::InstructionOperand& operand) { 134 return compiler::AllocatedOperand::cast(operand).GetRegister(); 135 } 136 ToRegister(const ValueLocation & location)137inline Register ToRegister(const ValueLocation& location) { 138 return ToRegister(location.operand()); 139 } 140 ToMemOperand(const compiler::InstructionOperand & operand)141inline MemOperand ToMemOperand(const compiler::InstructionOperand& operand) { 142 return GetStackSlot(compiler::AllocatedOperand::cast(operand)); 143 } 144 ToMemOperand(const ValueLocation & location)145inline MemOperand ToMemOperand(const ValueLocation& location) { 146 return ToMemOperand(location.operand()); 147 } 148 DefineSafepointStackSlots(SafepointTableBuilder::Safepoint & safepoint)149inline void MaglevCodeGenState::DefineSafepointStackSlots( 150 SafepointTableBuilder::Safepoint& safepoint) const { 151 DCHECK_EQ(compilation_unit()->stack_value_repr().size(), vreg_slots()); 152 int stack_slot = 0; 153 for (ValueRepresentation repr : compilation_unit()->stack_value_repr()) { 154 if (repr == ValueRepresentation::kTagged) { 155 safepoint.DefineTaggedStackSlot( 156 GetSafepointIndexForStackSlot(stack_slot)); 157 } 158 stack_slot++; 159 } 160 } 161 162 } // namespace maglev 163 } // namespace internal 164 } // namespace v8 165 166 #endif // V8_MAGLEV_MAGLEV_CODE_GEN_STATE_H_ 167