OLD | NEW |
---|---|
(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 | |
OLD | NEW |