1 // Copyright 2016 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_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_ 6 #define V8_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_ 7 8 #include "src/base/compiler-specific.h" 9 #include "src/globals.h" 10 #include "src/interpreter/bytecode-pipeline.h" 11 12 namespace v8 { 13 namespace internal { 14 namespace interpreter { 15 16 // An optimization stage for eliminating unnecessary transfers between 17 // registers. The bytecode generator uses temporary registers 18 // liberally for correctness and convenience and this stage removes 19 // transfers that are not required and preserves correctness. 20 class V8_EXPORT_PRIVATE BytecodeRegisterOptimizer final NON_EXPORTED_BASE(BytecodeRegisterAllocator::Observer)21 : public NON_EXPORTED_BASE(BytecodeRegisterAllocator::Observer), 22 public NON_EXPORTED_BASE(ZoneObject) { 23 public: 24 BytecodeRegisterOptimizer(Zone* zone, 25 BytecodeRegisterAllocator* register_allocator, 26 int fixed_registers_count, int parameter_count, 27 BytecodePipelineStage* next_stage); 28 virtual ~BytecodeRegisterOptimizer() {} 29 30 // Perform explicit register transfer operations. 31 void DoLdar(Register input, BytecodeSourceInfo source_info) { 32 RegisterInfo* input_info = GetRegisterInfo(input); 33 RegisterTransfer(input_info, accumulator_info_, source_info); 34 } 35 void DoStar(Register output, BytecodeSourceInfo source_info) { 36 RegisterInfo* output_info = GetRegisterInfo(output); 37 RegisterTransfer(accumulator_info_, output_info, source_info); 38 } 39 void DoMov(Register input, Register output, BytecodeSourceInfo source_info) { 40 RegisterInfo* input_info = GetRegisterInfo(input); 41 RegisterInfo* output_info = GetRegisterInfo(output); 42 RegisterTransfer(input_info, output_info, source_info); 43 } 44 45 // Materialize all live registers and flush equivalence sets. 46 void Flush(); 47 48 // Prepares for |bytecode|. 49 void PrepareForBytecode(Bytecode bytecode); 50 51 // Prepares |reg| for being used as an output operand. 52 void PrepareOutputRegister(Register reg); 53 54 // Prepares registers in |reg_list| for being used as an output operand. 55 void PrepareOutputRegisterList(RegisterList reg_list); 56 57 // Returns an equivalent register to |reg| to be used as an input operand. 58 Register GetInputRegister(Register reg); 59 60 // Returns an equivalent register list to |reg_list| to be used as an input 61 // operand. 62 RegisterList GetInputRegisterList(RegisterList reg_list); 63 64 int maxiumum_register_index() const { return max_register_index_; } 65 66 private: 67 static const uint32_t kInvalidEquivalenceId; 68 69 class RegisterInfo; 70 71 // BytecodeRegisterAllocator::Observer interface. 72 void RegisterAllocateEvent(Register reg) override; 73 void RegisterListAllocateEvent(RegisterList reg_list) override; 74 void RegisterListFreeEvent(RegisterList reg) override; 75 76 // Update internal state for register transfer from |input| to 77 // |output| using |source_info| as source position information if 78 // any bytecodes are emitted due to transfer. 79 void RegisterTransfer(RegisterInfo* input, RegisterInfo* output, 80 BytecodeSourceInfo source_info); 81 82 // Emit a register transfer bytecode from |input| to |output|. 83 void OutputRegisterTransfer( 84 RegisterInfo* input, RegisterInfo* output, 85 BytecodeSourceInfo source_info = BytecodeSourceInfo()); 86 87 // Emits a Nop to preserve source position information in the 88 // bytecode pipeline. 89 void EmitNopForSourceInfo(BytecodeSourceInfo source_info) const; 90 91 void CreateMaterializedEquivalent(RegisterInfo* info); 92 RegisterInfo* GetMaterializedEquivalent(RegisterInfo* info); 93 RegisterInfo* GetMaterializedEquivalentNotAccumulator(RegisterInfo* info); 94 void Materialize(RegisterInfo* info); 95 void AddToEquivalenceSet(RegisterInfo* set_member, 96 RegisterInfo* non_set_member); 97 98 // Methods for finding and creating metadata for each register. 99 RegisterInfo* GetRegisterInfo(Register reg) { 100 size_t index = GetRegisterInfoTableIndex(reg); 101 DCHECK_LT(index, register_info_table_.size()); 102 return register_info_table_[index]; 103 } 104 RegisterInfo* GetOrCreateRegisterInfo(Register reg) { 105 size_t index = GetRegisterInfoTableIndex(reg); 106 return index < register_info_table_.size() ? register_info_table_[index] 107 : NewRegisterInfo(reg); 108 } 109 RegisterInfo* NewRegisterInfo(Register reg) { 110 size_t index = GetRegisterInfoTableIndex(reg); 111 DCHECK_GE(index, register_info_table_.size()); 112 GrowRegisterMap(reg); 113 return register_info_table_[index]; 114 } 115 116 void GrowRegisterMap(Register reg); 117 118 bool RegisterIsTemporary(Register reg) const { 119 return reg >= temporary_base_; 120 } 121 122 bool RegisterIsObservable(Register reg) const { 123 return reg != accumulator_ && !RegisterIsTemporary(reg); 124 } 125 126 static Register OperandToRegister(uint32_t operand) { 127 return Register::FromOperand(static_cast<int32_t>(operand)); 128 } 129 130 size_t GetRegisterInfoTableIndex(Register reg) const { 131 return static_cast<size_t>(reg.index() + register_info_table_offset_); 132 } 133 134 Register RegisterFromRegisterInfoTableIndex(size_t index) const { 135 return Register(static_cast<int>(index) - register_info_table_offset_); 136 } 137 138 uint32_t NextEquivalenceId() { 139 equivalence_id_++; 140 // TODO(rmcilroy): use the same type for these and remove static_cast. 141 CHECK_NE(static_cast<size_t>(equivalence_id_), kInvalidEquivalenceId); 142 return equivalence_id_; 143 } 144 145 Zone* zone() { return zone_; } 146 147 const Register accumulator_; 148 RegisterInfo* accumulator_info_; 149 const Register temporary_base_; 150 int max_register_index_; 151 152 // Direct mapping to register info. 153 ZoneVector<RegisterInfo*> register_info_table_; 154 int register_info_table_offset_; 155 156 // Counter for equivalence sets identifiers. 157 int equivalence_id_; 158 159 BytecodePipelineStage* next_stage_; 160 bool flush_required_; 161 Zone* zone_; 162 163 DISALLOW_COPY_AND_ASSIGN(BytecodeRegisterOptimizer); 164 }; 165 166 } // namespace interpreter 167 } // namespace internal 168 } // namespace v8 169 170 #endif // V8_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_ 171