v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
bytecode-register-optimizer.h
Go to the documentation of this file.
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/ast/variables.h"
10#include "src/common/globals.h"
14#include "src/zone/zone.h"
15
16namespace v8 {
17namespace internal {
18namespace interpreter {
19
20// An optimization stage for eliminating unnecessary transfers between
21// registers. The bytecode generator uses temporary registers
22// liberally for correctness and convenience and this stage removes
23// transfers that are not required and preserves correctness.
25 : public NON_EXPORTED_BASE(BytecodeRegisterAllocator::Observer),
26 public NON_EXPORTED_BASE(ZoneObject) {
27 public:
29
31 public:
32 BytecodeWriter() = default;
33 virtual ~BytecodeWriter() = default;
36
37 // Called to emit a register transfer bytecode.
38 virtual void EmitLdar(Register input) = 0;
39 virtual void EmitStar(Register output) = 0;
40 virtual void EmitMov(Register input, Register output) = 0;
41 };
42
44 BytecodeRegisterAllocator* register_allocator,
45 int fixed_registers_count, int parameter_count,
46 BytecodeWriter* bytecode_writer);
47 ~BytecodeRegisterOptimizer() override = default;
50 delete;
51
52 // Perform explicit register transfer operations.
53 void DoLdar(Register input) {
54 // TODO(rmcilroy): Avoid treating accumulator loads as clobbering the
55 // accumulator until the value is actually materialized in the accumulator.
56 RegisterInfo* input_info = GetRegisterInfo(input);
57 RegisterTransfer(input_info, accumulator_info_);
58 }
59 void DoStar(Register output) {
60 RegisterInfo* output_info = GetRegisterInfo(output);
61 RegisterTransfer(accumulator_info_, output_info);
62 }
63 void DoMov(Register input, Register output) {
64 RegisterInfo* input_info = GetRegisterInfo(input);
65 RegisterInfo* output_info = GetRegisterInfo(output);
66 RegisterTransfer(input_info, output_info);
67 }
68
69 // Materialize all live registers and flush equivalence sets.
70 void Flush();
71 bool EnsureAllRegistersAreFlushed() const;
72
73 // Prepares for |bytecode|.
74 template <Bytecode bytecode, ImplicitRegisterUse implicit_register_use>
76 if (Bytecodes::IsJump(bytecode) || Bytecodes::IsSwitch(bytecode) ||
77 bytecode == Bytecode::kDebugger ||
78 bytecode == Bytecode::kSuspendGenerator ||
79 bytecode == Bytecode::kResumeGenerator) {
80 // All state must be flushed before emitting
81 // - a jump bytecode (as the register equivalents at the jump target
82 // aren't known)
83 // - a switch bytecode (as the register equivalents at the switch targets
84 // aren't known)
85 // - a call to the debugger (as it can manipulate locals and parameters),
86 // - a generator suspend (as this involves saving all registers).
87 // - a generator register restore.
88 Flush();
89 }
90
91 // Materialize the accumulator if it is read by the bytecode. The
92 // accumulator is special and no other register can be materialized
93 // in it's place.
94 if (BytecodeOperands::ReadsAccumulator(implicit_register_use)) {
95 Materialize(accumulator_info_);
96 }
97
98 // Materialize an equivalent to the accumulator if it will be
99 // clobbered when the bytecode is dispatched.
100 if (BytecodeOperands::WritesOrClobbersAccumulator(implicit_register_use)) {
101 PrepareOutputRegister(accumulator_);
102 DCHECK_EQ(GetTypeHint(accumulator_), TypeHint::kAny);
103 }
104 }
105
106 // Prepares |reg| for being used as an output operand.
107 void PrepareOutputRegister(Register reg);
108
109 // Prepares registers in |reg_list| for being used as an output operand.
110 void PrepareOutputRegisterList(RegisterList reg_list);
111
112 // Returns an equivalent register to |reg| to be used as an input operand.
113 Register GetInputRegister(Register reg);
114
115 // Returns an equivalent register list to |reg_list| to be used as an input
116 // operand.
117 RegisterList GetInputRegisterList(RegisterList reg_list);
118
119 // Maintain the map between Variable and Register.
120 void SetVariableInRegister(Variable* var, Register reg);
121
122 // Get the variable that might be in the reg. This is a variable value that
123 // is preserved across flushes.
124 Variable* GetPotentialVariableInRegister(Register reg);
125
126 // Get the variable that might be in the accumulator. This is a variable value
127 // that is preserved across flushes.
129 return GetPotentialVariableInRegister(accumulator_);
130 }
131
132 // Return true if the var is in the reg.
133 bool IsVariableInRegister(Variable* var, Register reg);
134
135 TypeHint GetTypeHint(Register reg);
136 void SetTypeHintForAccumulator(TypeHint hint);
137 void ResetTypeHintForAccumulator();
138 bool IsAccumulatorReset();
139
140 int maxiumum_register_index() const { return max_register_index_; }
141
142 private:
143 static const uint32_t kInvalidEquivalenceId;
144
145 class RegisterInfo;
146
147 // BytecodeRegisterAllocator::Observer interface.
148 void RegisterAllocateEvent(Register reg) override;
149 void RegisterListAllocateEvent(RegisterList reg_list) override;
150 void RegisterListFreeEvent(RegisterList reg) override;
151 void RegisterFreeEvent(Register reg) override;
152
153 // Update internal state for register transfer from |input| to |output|
154 void RegisterTransfer(RegisterInfo* input, RegisterInfo* output);
155
156 // Emit a register transfer bytecode from |input| to |output|.
157 void OutputRegisterTransfer(RegisterInfo* input, RegisterInfo* output);
158
159 void CreateMaterializedEquivalent(RegisterInfo* info);
160 RegisterInfo* GetMaterializedEquivalentNotAccumulator(RegisterInfo* info);
161 void Materialize(RegisterInfo* info);
162 void AddToEquivalenceSet(RegisterInfo* set_member,
163 RegisterInfo* non_set_member);
164
165 void PushToRegistersNeedingFlush(RegisterInfo* reg);
166 // Methods for finding and creating metadata for each register.
168 size_t index = GetRegisterInfoTableIndex(reg);
169 DCHECK_LT(index, register_info_table_.size());
170 return register_info_table_[index];
171 }
173 size_t index = GetRegisterInfoTableIndex(reg);
174 return index < register_info_table_.size() ? register_info_table_[index]
175 : NewRegisterInfo(reg);
176 }
178 size_t index = GetRegisterInfoTableIndex(reg);
179 DCHECK_GE(index, register_info_table_.size());
180 GrowRegisterMap(reg);
181 return register_info_table_[index];
182 }
183
184 void GrowRegisterMap(Register reg);
185
187 return reg >= temporary_base_;
188 }
189
191 return reg != accumulator_ && !RegisterIsTemporary(reg);
192 }
193
194 static Register OperandToRegister(uint32_t operand) {
195 return Register::FromOperand(static_cast<int32_t>(operand));
196 }
197
199 return static_cast<size_t>(reg.index() + register_info_table_offset_);
200 }
201
203 return Register(static_cast<int>(index) - register_info_table_offset_);
204 }
205
206 uint32_t NextEquivalenceId() {
207 equivalence_id_++;
208 CHECK_NE(equivalence_id_, kInvalidEquivalenceId);
209 return equivalence_id_;
210 }
211
212 void AllocateRegister(RegisterInfo* info);
213
214 Zone* zone() { return zone_; }
215
220
221 // Direct mapping to register info.
224
226
227 // Counter for equivalence sets identifiers.
229
233};
234
235} // namespace interpreter
236} // namespace internal
237} // namespace v8
238
239#endif // V8_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_
int16_t parameter_count
Definition builtins.cc:67
virtual void EmitMov(Register input, Register output)=0
BytecodeWriter & operator=(const BytecodeWriter &)=delete
BytecodeRegisterOptimizer(const BytecodeRegisterOptimizer &)=delete
BytecodeRegisterOptimizer & operator=(const BytecodeRegisterOptimizer &)=delete
Zone * zone_
OptionalOpIndex index
LiftoffRegister reg
#define NON_EXPORTED_BASE(code)
#define CHECK_NE(lhs, rhs)
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define V8_INLINE
Definition v8config.h:500