• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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