Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(116)

Side by Side Diff: src/interpreter/register-translator.cc

Issue 1613163002: [interpreter] Wide register support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Added tests, fixed off-by-one error in register indicies. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 #include "src/interpreter/register-translator.h"
6
7 #include "src/interpreter/bytecode-array-builder.h"
8
9 namespace v8 {
10 namespace internal {
11 namespace interpreter {
12
13 RegisterTranslator::RegisterTranslator(RegisterMover* mover)
14 : mover_(mover), window_registers_count_(0), register_operands_count_(0) {}
15
16
17 Register RegisterTranslator::Translate(Bytecode bytecode, Register reg) {
18 if (register_operands_count_ == 0) {
19 bytecode_ = bytecode;
20 }
21 DCHECK_EQ(bytecode, bytecode_);
rmcilroy 2016/01/22 17:50:57 I'm not sure what the point of passing bytecode to
22 DCHECK_LT(register_operands_count_,
23 static_cast<int>(arraysize(register_operands_)));
24 OperandType operand_type =
25 GetRegisterOperandType(bytecode, register_operands_count_);
26 Register translated_reg = Translate(reg);
27 Register addressable = MakeAddressable(translated_reg, operand_type);
28 register_operands_[register_operands_count_] = addressable.ToRawOperand();
rmcilroy 2016/01/22 17:50:57 Do we need to keep the register_operands_ in vecto
29 register_operands_count_ += 1;
30 if (addressable != translated_reg) {
31 Move(translated_reg, addressable, operand_type);
32 }
33 return addressable;
34 }
35
36
37 Register RegisterTranslator::MakeAddressable(Register translated_reg,
38 OperandType translated_reg_type) {
39 DCHECK(!InTranslationWindow(translated_reg));
40 OperandSize translated_reg_size =
41 Bytecodes::SizeOfOperand(translated_reg_type);
42 if (translated_reg_size == OperandSize::kByte &&
43 !FitsInReg8Operand(translated_reg)) {
44 // TODO(oth): Moves into and out from translation window could be
45 // decoupled if there were metadata to say whether the register was
46 // an input, output, or both.
47 Register destination(kTranslationWindowStart + window_registers_count_);
48 window_registers_[window_registers_count_] = translated_reg;
49 window_registers_count_ += 1;
50 DCHECK_LE(window_registers_count_, kTranslationWindowLength);
51 return destination;
52 } else {
53 return translated_reg;
54 }
55 }
56
57
58 void RegisterTranslator::Move(Register from, Register to,
59 OperandType to_operand_type) {
60 bool expect_movable = true;
61 if (to_operand_type != OperandType::kReg8) {
62 // Only tests should visit this path.
rmcilroy 2016/01/22 17:50:57 What test kick this path? It seems non-obvious tha
63 from = to = Register::IllegalRegister();
64 expect_movable = false;
65 }
66
67 bool movable = mover()->MoveRegisterUntranslated(from, to);
68 CHECK_EQ(expect_movable, movable);
69 }
70
71
72 void RegisterTranslator::CompleteTranslations() {
73 while (window_registers_count_ > 0) {
74 window_registers_count_ -= 1;
75 Register source(kTranslationWindowStart + window_registers_count_);
76 Register destination = window_registers_[window_registers_count_];
77 mover()->MoveRegisterUntranslated(source, destination);
78 }
79 register_operands_count_ = 0;
80 bytecode_ = static_cast<Bytecode>(-1);
81 }
82
83
84 bool RegisterTranslator::RegisterOperandsValid(Bytecode bytecode,
85 const uint32_t* const operands,
86 int operands_count) const {
87 if (bytecode != bytecode_ && bytecode == Bytecode::kMovWide) {
88 // Checking move emitted by register translator for bytecode_.
89 DCHECK_EQ(operands_count, 2);
90 Register from = Register::FromRawOperand(operands[0]);
91 Register to = Register::FromRawOperand(operands[1]);
92 return MoveIsValid(from, to);
93 } else if (register_operands_count_ == 0) {
94 DCHECK_EQ(Bytecodes::NumberOfRegisterOperands(bytecode), 0);
95 return true;
96 }
97
98 int reg_count = 0;
99 for (int i = 0; i < operands_count; i++) {
100 OperandType operand_type = Bytecodes::GetOperandType(bytecode, i);
101 bool next_operand_is_reg_count = false;
102 if (i != operands_count - 1) {
103 OperandType next_operand_type =
104 Bytecodes::GetOperandType(bytecode, i + 1);
105 next_operand_is_reg_count =
106 next_operand_type == OperandType::kRegCount8 ||
107 next_operand_type == OperandType::kRegCount16;
rmcilroy 2016/01/22 17:50:57 You don't seem to use next_operand_is_reg_count ?
108 }
109
110 Register reg;
111 int length = 0;
112 switch (operand_type) {
113 case OperandType::kNone:
114 UNREACHABLE();
115 return false;
116 case OperandType::kIdx8:
117 case OperandType::kIdx16:
118 case OperandType::kImm8:
119 case OperandType::kRegCount8:
120 case OperandType::kRegCount16:
121 break;
122 case OperandType::kMaybeReg8:
123 case OperandType::kMaybeReg16: {
124 DCHECK(next_operand_is_reg_count);
125 reg = Register::FromRawOperand(operands[i]);
126 length = static_cast<int>(operands[i + 1]);
127 break;
128 }
129 case OperandType::kRegPair8:
130 case OperandType::kRegPair16: {
131 reg = Register::FromRawOperand(operands[i]);
132 length = 2;
133 break;
134 }
135 case OperandType::kRegTriple8:
136 case OperandType::kRegTriple16: {
137 reg = Register::FromRawOperand(operands[i]);
138 length = 3;
139 break;
140 }
141 case OperandType::kReg8:
142 case OperandType::kReg16: {
143 reg = Register::FromRawOperand(operands[i]);
144 if (next_operand_is_reg_count) {
145 length = static_cast<int>(operands[i + 1]);
146 } else {
147 length = 1;
148 }
149 break;
150 }
151 }
152 if (reg.is_valid()) {
153 if (reg.ToRawOperand() != register_operands_[reg_count]) {
154 return false;
155 } else if (reg.index() < kTranslationWindowStart &&
156 reg.index() + length > kTranslationWindowStart) {
157 return false;
158 }
159 reg_count++;
160 }
161 }
162 return reg_count == Bytecodes::NumberOfRegisterOperands(bytecode) &&
163 reg_count == register_operands_count_;
164 }
165
166
167 bool RegisterTranslator::MoveIsValid(Register from, Register to) const {
168 // Checking a move bytecode ahead of emitting actual bytecode. The move
169 // is ensuring all register operands are reachable.
170 if (InTranslationWindow(to)) {
171 // Moving register into translation window.
172 DCHECK(!FitsInReg8Operand(from));
173 DCHECK(from.index() > kTranslationWindowLimit || !from.is_byte_operand());
174 DCHECK_GT(window_registers_count_, 0);
175 DCHECK_LE(window_registers_count_,
176 static_cast<int>(arraysize(window_registers_)));
177 Register last_window_register =
178 window_registers_[window_registers_count_ - 1];
179 return from == last_window_register;
180 } else if (InTranslationWindow(from)) {
181 // Moving register out of translation window.
182 DCHECK(!FitsInReg8Operand(to));
183 DCHECK(to.index() > kTranslationWindowLimit || !to.is_byte_operand());
184 DCHECK_GE(window_registers_count_, 0);
185 DCHECK_LT(window_registers_count_,
186 static_cast<int>(arraysize(window_registers_)));
187 Register last_window_register = window_registers_[window_registers_count_];
188 return to == last_window_register;
189 } else {
190 UNREACHABLE();
191 return false;
192 }
193 }
194
195
196 // static
197 Register RegisterTranslator::Translate(Register reg) {
198 if (reg.index() >= kTranslationWindowStart) {
199 return Register(reg.index() + kTranslationWindowLength);
rmcilroy 2016/01/22 17:50:57 I wonder whether we should have a TranslatedRegist
200 } else {
201 return reg;
202 }
203 }
204
205
206 // static
207 OperandType RegisterTranslator::GetRegisterOperandType(Bytecode bytecode,
208 int register_operand) {
209 int operand_count = Bytecodes::NumberOfOperands(bytecode);
210 for (int operand = 0; operand < operand_count; ++operand) {
rmcilroy 2016/01/22 17:50:56 Would it be possible to calculate this statically
211 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand);
212 switch (operand_type) {
213 #define REGISTER_OPERAND_CASE(op, _) case OperandType::k##op:
214 REGISTER_OPERAND_TYPE_LIST(REGISTER_OPERAND_CASE)
215 #undef REGISTER_OPERAND_CASE
216 if (register_operand-- == 0) {
217 return operand_type;
218 }
219 break;
220 default:
221 break;
222 }
223 }
224 UNREACHABLE();
225 return OperandType::kNone;
226 }
227
228
229 // static
230 bool RegisterTranslator::InTranslationWindow(Register reg) {
231 return (reg.index() >= kTranslationWindowStart &&
232 reg.index() <= kTranslationWindowLimit);
233 }
234
235
236 // static
237 int RegisterTranslator::DistanceToTranslationWindow(Register reg) {
238 return kTranslationWindowStart - reg.index();
239 }
240
241
242 // static
243 bool RegisterTranslator::FitsInReg8Operand(Register reg) {
244 return reg.is_byte_operand() && reg.index() < kTranslationWindowStart;
245 }
246
247
248 // static
249 bool RegisterTranslator::FitsInReg16Operand(Register reg) {
250 int max_index = Register::MaxRegisterIndex() - kTranslationWindowLength + 1;
251 return reg.is_short_operand() && reg.index() < max_index;
252 }
253
254
255 // static
256 int RegisterTranslator::RegisterCountAdjustment(int register_count,
257 int parameter_count) {
258 if (register_count > kTranslationWindowStart) {
259 return kTranslationWindowLength;
260 } else if (parameter_count > 0) {
261 Register param0 = Register::FromParameterIndex(0, parameter_count);
262 DCHECK_LT(param0.index(), 0);
263 if (param0.index() < kMinInt8) {
264 // TODO(oth): Translation window does not relocate when number of
265 // registers is small, but number of parameters is large enough to
266 // require translation. The frame may be 128 registers too large.
267 return kTranslationWindowLimit + 1 - register_count;
268 }
269 }
270 return 0;
271 }
272
273 } // namespace interpreter
274 } // namespace internal
275 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698