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

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: Compilation fixes for gcc/msvc. 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), emitting_moves_(false), window_registers_count_(0) {}
15
16
17 void RegisterTranslator::TranslateRegisters(Bytecode bytecode,
18 uint32_t* raw_operands,
19 int raw_operand_count) {
20 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), raw_operand_count);
21 if (!emitting_moves_) {
22 emitting_moves_ = true;
23 DCHECK_EQ(window_registers_count_, 0);
24 int register_bitmap = Bytecodes::GetRegisterOperandBitmap(bytecode);
25 for (int i = 0; i < raw_operand_count; i++) {
26 if ((register_bitmap & (1 << i)) == 0) {
27 DCHECK(NonRegisterOperandIsValid(bytecode, i));
28 continue;
29 }
30 Register in_reg = Register::FromRawOperand(raw_operands[i]);
31 Register out_reg = TranslateAndMove(bytecode, i, in_reg);
32 raw_operands[i] = out_reg.ToRawOperand();
33 }
34 emitting_moves_ = false;
35 } else {
36 // When the register translator is translating registers, it will
37 // cause the bytecode generator to emit moves on it's behalf. This
38 // path is reached by these moves.
39 DCHECK(bytecode == Bytecode::kMovWide && raw_operand_count == 2 &&
40 Register::FromRawOperand(raw_operands[0]).is_valid() &&
41 Register::FromRawOperand(raw_operands[1]).is_valid());
42 }
43 }
44
45
46 Register RegisterTranslator::TranslateAndMove(Bytecode bytecode,
47 int operand_index, Register reg) {
48 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
49 Register translated_reg = Translate(reg);
50 Register addressable_reg = MakeAddressable(translated_reg, operand_type);
51 if (addressable_reg != translated_reg) {
52 if (operand_type == OperandType::kReg8 &&
53 OperandIsMoveable(bytecode, operand_index)) {
54 mover()->MoveRegisterUntranslated(translated_reg, addressable_reg);
55 } else {
56 Register invalid_reg;
57 mover()->MoveRegisterUntranslated(invalid_reg, invalid_reg);
rmcilroy 2016/01/25 12:12:05 Maybe we can make this a Death test instead? If
oth 2016/01/25 16:51:57 Didn't appreciate death test was an option. Have n
58 }
59 }
60 return addressable_reg;
61 }
62
63
64 void RegisterTranslator::UntranslateRegisters() {
65 if (!emitting_moves_) {
66 emitting_moves_ = true;
67 while (window_registers_count_ > 0) {
68 window_registers_count_ -= 1;
69 Register source(kTranslationWindowStart + window_registers_count_);
70 Register destination = window_registers_[window_registers_count_];
71 mover()->MoveRegisterUntranslated(source, destination);
72 }
73 emitting_moves_ = false;
74 }
75 }
76
77
78 Register RegisterTranslator::MakeAddressable(Register reg,
79 OperandType reg_type) {
80 DCHECK(!InTranslationWindow(reg));
81 OperandSize reg_size = Bytecodes::SizeOfOperand(reg_type);
82 if (reg_size == OperandSize::kByte && !FitsInReg8Operand(reg)) {
83 // TODO(oth): Moves into and out from translation window could be
84 // decoupled if there were metadata to say whether the register
85 // operand was an input, output, or input-and-output for a given
86 // bytecode.
87 Register destination(kTranslationWindowStart + window_registers_count_);
88 window_registers_[window_registers_count_] = reg;
89 window_registers_count_ += 1;
90 DCHECK_LE(window_registers_count_, kTranslationWindowLength);
91 return destination;
92 } else {
93 return reg;
94 }
95 }
96
97
98 // static
99 bool RegisterTranslator::NonRegisterOperandIsValid(Bytecode bytecode,
100 int operand_index) {
101 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
102 if (operand_type == OperandType::kRegCount8 ||
103 operand_type == OperandType::kRegCount16) {
rmcilroy 2016/01/25 12:12:05 Should this not be checked in OperandIsValid in by
oth 2016/01/25 16:51:57 Done.
104 if (operand_index > 0) {
105 switch (Bytecodes::GetOperandType(bytecode, operand_index - 1)) {
106 case OperandType::kMaybeReg8:
107 case OperandType::kMaybeReg16:
108 case OperandType::kReg8:
109 case OperandType::kReg16:
110 return true;
111 case OperandType::kNone:
112 UNREACHABLE();
113 case OperandType::kIdx8:
114 case OperandType::kIdx16:
115 case OperandType::kImm8:
116 case OperandType::kRegCount8:
117 case OperandType::kRegCount16:
118 case OperandType::kRegPair8:
119 case OperandType::kRegPair16:
120 case OperandType::kRegTriple8:
121 case OperandType::kRegTriple16:
122 break;
123 }
124 }
125 return false;
126 } else {
127 return true;
128 }
129 }
130
131
132 // static
133 bool RegisterTranslator::OperandIsMoveable(Bytecode bytecode,
rmcilroy 2016/01/25 12:12:05 This could be exposed as part of the RegisterMover
oth 2016/01/25 16:51:56 Done.
134 int operand_index) {
135 // By design, the translator does not copy any register ranges into
136 // the translation window. There should be wide variants of such
137 // bytecodes instead to avoid the need for a large translation
138 // window.
139 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
140 if (operand_type == OperandType::kReg8 ||
141 operand_type == OperandType::kReg16) {
142 if (operand_index == Bytecodes::NumberOfOperands(bytecode) - 1) {
143 return true;
144 }
145 OperandType next_operand_type =
146 Bytecodes::GetOperandType(bytecode, operand_index + 1);
147 return (next_operand_type != OperandType::kRegCount8 &&
148 next_operand_type != OperandType::kRegCount16);
149 } else {
150 return false;
151 }
152 }
153
154
155 // static
156 Register RegisterTranslator::Translate(Register reg) {
157 if (reg.index() >= kTranslationWindowStart) {
158 return Register(reg.index() + kTranslationWindowLength);
159 } else {
160 return reg;
161 }
162 }
163
164
165 // static
166 bool RegisterTranslator::InTranslationWindow(Register reg) {
167 return (reg.index() >= kTranslationWindowStart &&
168 reg.index() <= kTranslationWindowLimit);
169 }
170
171
172 // static
173 int RegisterTranslator::DistanceToTranslationWindow(Register reg) {
174 return kTranslationWindowStart - reg.index();
175 }
176
177
178 // static
179 bool RegisterTranslator::FitsInReg8Operand(Register reg) {
180 return reg.is_byte_operand() && reg.index() < kTranslationWindowStart;
181 }
182
183
184 // static
185 bool RegisterTranslator::FitsInReg16Operand(Register reg) {
186 int max_index = Register::MaxRegisterIndex() - kTranslationWindowLength + 1;
187 return reg.is_short_operand() && reg.index() < max_index;
188 }
189
190
191 // static
192 int RegisterTranslator::RegisterCountAdjustment(int register_count,
193 int parameter_count) {
194 if (register_count > kTranslationWindowStart) {
195 return kTranslationWindowLength;
196 } else if (parameter_count > 0) {
197 Register param0 = Register::FromParameterIndex(0, parameter_count);
198 if (!param0.is_byte_operand()) {
199 // TODO(oth): Move translation window in this scenario.
rmcilroy 2016/01/25 12:12:05 Explain why (i.e., the translation window causes a
oth 2016/01/25 16:51:56 Done.
200 return kTranslationWindowLimit + 1 - register_count;
201 }
202 }
203 return 0;
204 }
205
206 } // namespace interpreter
207 } // namespace internal
208 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698