OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/interpreter/bytecode-array-builder.h" | 5 #include "src/interpreter/bytecode-array-builder.h" |
6 | 6 |
7 namespace v8 { | 7 namespace v8 { |
8 namespace internal { | 8 namespace internal { |
9 namespace interpreter { | 9 namespace interpreter { |
10 | 10 |
11 class BytecodeArrayBuilder::PreviousBytecodeHelper { | 11 class BytecodeArrayBuilder::PreviousBytecodeHelper BASE_EMBEDDED { |
12 public: | 12 public: |
13 explicit PreviousBytecodeHelper(const BytecodeArrayBuilder& array_builder) | 13 explicit PreviousBytecodeHelper(const BytecodeArrayBuilder& array_builder) |
14 : array_builder_(array_builder), | 14 : array_builder_(array_builder), |
15 previous_bytecode_start_(array_builder_.last_bytecode_start_) { | 15 previous_bytecode_start_(array_builder_.last_bytecode_start_) { |
16 // This helper is expected to be instantiated only when the last bytecode is | 16 // This helper is expected to be instantiated only when the last bytecode is |
17 // in the same basic block. | 17 // in the same basic block. |
18 DCHECK(array_builder_.LastBytecodeInSameBlock()); | 18 DCHECK(array_builder_.LastBytecodeInSameBlock()); |
19 } | 19 } |
20 | 20 |
21 // Returns the previous bytecode in the same basic block. | 21 // Returns the previous bytecode in the same basic block. |
22 MUST_USE_RESULT Bytecode GetBytecode() const { | 22 MUST_USE_RESULT Bytecode GetBytecode() const { |
23 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); | 23 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); |
24 return Bytecodes::FromByte( | 24 return Bytecodes::FromByte( |
25 array_builder_.bytecodes()->at(previous_bytecode_start_)); | 25 array_builder_.bytecodes()->at(previous_bytecode_start_)); |
26 } | 26 } |
27 | 27 |
28 // Returns the operand at operand_index for the previous bytecode in the | 28 // Returns the operand at operand_index for the previous bytecode in the |
29 // same basic block. | 29 // same basic block. |
30 MUST_USE_RESULT uint32_t GetOperand(int operand_index) const { | 30 MUST_USE_RESULT uint32_t GetOperand(int operand_index) const { |
31 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); | 31 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); |
32 Bytecode bytecode = GetBytecode(); | 32 Bytecode bytecode = GetBytecode(); |
33 DCHECK_GE(operand_index, 0); | 33 DCHECK_GE(operand_index, 0); |
34 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode)); | 34 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode)); |
35 size_t operand_offset = | 35 size_t operand_offset = |
36 previous_bytecode_start_ + | 36 previous_bytecode_start_ + |
37 Bytecodes::GetOperandOffset(bytecode, operand_index); | 37 Bytecodes::GetOperandOffset(bytecode, operand_index); |
38 OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index); | 38 OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index); |
39 switch (size) { | 39 switch (size) { |
40 default: | |
41 case OperandSize::kNone: | 40 case OperandSize::kNone: |
42 UNREACHABLE(); | 41 UNREACHABLE(); |
42 break; | |
43 case OperandSize::kByte: | 43 case OperandSize::kByte: |
44 return static_cast<uint32_t>( | 44 return static_cast<uint32_t>( |
45 array_builder_.bytecodes()->at(operand_offset)); | 45 array_builder_.bytecodes()->at(operand_offset)); |
46 case OperandSize::kShort: | 46 case OperandSize::kShort: |
47 uint16_t operand = | 47 uint16_t operand = |
48 (array_builder_.bytecodes()->at(operand_offset) << 8) + | 48 (array_builder_.bytecodes()->at(operand_offset) << 8) + |
49 array_builder_.bytecodes()->at(operand_offset + 1); | 49 array_builder_.bytecodes()->at(operand_offset + 1); |
50 return static_cast<uint32_t>(operand); | 50 return static_cast<uint32_t>(operand); |
51 } | 51 } |
52 return 0; | |
52 } | 53 } |
53 | 54 |
54 Handle<Object> GetConstantForIndexOperand(int operand_index) const { | 55 Handle<Object> GetConstantForIndexOperand(int operand_index) const { |
55 return array_builder_.constant_array_builder()->At( | 56 return array_builder_.constant_array_builder()->At( |
56 GetOperand(operand_index)); | 57 GetOperand(operand_index)); |
57 } | 58 } |
58 | 59 |
59 private: | 60 private: |
60 const BytecodeArrayBuilder& array_builder_; | 61 const BytecodeArrayBuilder& array_builder_; |
61 size_t previous_bytecode_start_; | 62 size_t previous_bytecode_start_; |
(...skipping 10 matching lines...) Expand all Loading... | |
72 constant_array_builder_(isolate, zone), | 73 constant_array_builder_(isolate, zone), |
73 handler_table_builder_(isolate, zone), | 74 handler_table_builder_(isolate, zone), |
74 last_block_end_(0), | 75 last_block_end_(0), |
75 last_bytecode_start_(~0), | 76 last_bytecode_start_(~0), |
76 exit_seen_in_block_(false), | 77 exit_seen_in_block_(false), |
77 unbound_jumps_(0), | 78 unbound_jumps_(0), |
78 parameter_count_(-1), | 79 parameter_count_(-1), |
79 local_register_count_(-1), | 80 local_register_count_(-1), |
80 context_register_count_(-1), | 81 context_register_count_(-1), |
81 temporary_register_count_(0), | 82 temporary_register_count_(0), |
82 free_temporaries_(zone) {} | 83 free_temporaries_(zone), |
84 register_translator_(this) {} | |
83 | 85 |
84 | 86 |
85 BytecodeArrayBuilder::~BytecodeArrayBuilder() { DCHECK_EQ(0, unbound_jumps_); } | 87 BytecodeArrayBuilder::~BytecodeArrayBuilder() { DCHECK_EQ(0, unbound_jumps_); } |
86 | 88 |
87 | 89 |
88 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) { | 90 void BytecodeArrayBuilder::set_locals_count(int number_of_locals) { |
89 local_register_count_ = number_of_locals; | 91 local_register_count_ = number_of_locals; |
90 DCHECK_LE(context_register_count_, 0); | 92 DCHECK_LE(context_register_count_, 0); |
91 } | 93 } |
92 | 94 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
141 return temporary_register_count_ > 0 && first_temporary_register() <= reg && | 143 return temporary_register_count_ > 0 && first_temporary_register() <= reg && |
142 reg <= last_temporary_register(); | 144 reg <= last_temporary_register(); |
143 } | 145 } |
144 | 146 |
145 | 147 |
146 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { | 148 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { |
147 DCHECK_EQ(bytecode_generated_, false); | 149 DCHECK_EQ(bytecode_generated_, false); |
148 EnsureReturn(); | 150 EnsureReturn(); |
149 | 151 |
150 int bytecode_size = static_cast<int>(bytecodes_.size()); | 152 int bytecode_size = static_cast<int>(bytecodes_.size()); |
151 int register_count = fixed_register_count() + temporary_register_count_; | 153 int register_count = |
154 fixed_and_temporary_register_count() + translation_register_count(); | |
152 int frame_size = register_count * kPointerSize; | 155 int frame_size = register_count * kPointerSize; |
153 Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray(); | 156 Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray(); |
154 Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable(); | 157 Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable(); |
155 Handle<BytecodeArray> output = isolate_->factory()->NewBytecodeArray( | 158 Handle<BytecodeArray> output = isolate_->factory()->NewBytecodeArray( |
156 bytecode_size, &bytecodes_.front(), frame_size, parameter_count(), | 159 bytecode_size, &bytecodes_.front(), frame_size, parameter_count(), |
157 constant_pool); | 160 constant_pool); |
158 output->set_handler_table(*handler_table); | 161 output->set_handler_table(*handler_table); |
159 bytecode_generated_ = true; | 162 bytecode_generated_ = true; |
160 return output; | 163 return output; |
161 } | 164 } |
162 | 165 |
163 | 166 |
164 template <size_t N> | 167 template <size_t N> |
165 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) { | 168 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) { |
166 // Don't output dead code. | 169 // Don't output dead code. |
167 if (exit_seen_in_block_) return; | 170 if (exit_seen_in_block_) return; |
168 | 171 |
169 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), static_cast<int>(N)); | 172 int operand_count = static_cast<int>(N); |
173 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count); | |
174 | |
175 int register_operand_count = Bytecodes::NumberOfRegisterOperands(bytecode); | |
176 if (register_operand_count > 0) { | |
177 register_translator()->TranslateInputRegisters(bytecode, operands, | |
178 operand_count); | |
179 } | |
180 | |
170 last_bytecode_start_ = bytecodes()->size(); | 181 last_bytecode_start_ = bytecodes()->size(); |
171 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); | 182 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); |
172 for (int i = 0; i < static_cast<int>(N); i++) { | 183 for (int i = 0; i < operand_count; i++) { |
173 DCHECK(OperandIsValid(bytecode, i, operands[i])); | 184 DCHECK(OperandIsValid(bytecode, i, operands[i])); |
174 switch (Bytecodes::GetOperandSize(bytecode, i)) { | 185 switch (Bytecodes::GetOperandSize(bytecode, i)) { |
175 case OperandSize::kNone: | 186 case OperandSize::kNone: |
176 UNREACHABLE(); | 187 UNREACHABLE(); |
188 break; | |
177 case OperandSize::kByte: | 189 case OperandSize::kByte: |
178 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); | 190 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); |
179 break; | 191 break; |
180 case OperandSize::kShort: { | 192 case OperandSize::kShort: { |
181 uint8_t operand_bytes[2]; | 193 uint8_t operand_bytes[2]; |
182 WriteUnalignedUInt16(operand_bytes, operands[i]); | 194 WriteUnalignedUInt16(operand_bytes, operands[i]); |
183 bytecodes()->insert(bytecodes()->end(), operand_bytes, | 195 bytecodes()->insert(bytecodes()->end(), operand_bytes, |
184 operand_bytes + 2); | 196 operand_bytes + 2); |
185 break; | 197 break; |
186 } | 198 } |
187 } | 199 } |
188 } | 200 } |
201 | |
202 if (register_operand_count > 0) { | |
203 register_translator()->TranslateOutputRegisters(); | |
204 } | |
189 } | 205 } |
190 | 206 |
191 | 207 |
192 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 208 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
193 uint32_t operand1, uint32_t operand2, | 209 uint32_t operand1, uint32_t operand2, |
194 uint32_t operand3) { | 210 uint32_t operand3) { |
195 uint32_t operands[] = {operand0, operand1, operand2, operand3}; | 211 uint32_t operands[] = {operand0, operand1, operand2, operand3}; |
196 Output(bytecode, operands); | 212 Output(bytecode, operands); |
197 } | 213 } |
198 | 214 |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
354 if (!IsRegisterInAccumulator(reg)) { | 370 if (!IsRegisterInAccumulator(reg)) { |
355 Output(Bytecode::kStar, reg.ToRawOperand()); | 371 Output(Bytecode::kStar, reg.ToRawOperand()); |
356 } | 372 } |
357 return *this; | 373 return *this; |
358 } | 374 } |
359 | 375 |
360 | 376 |
361 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, | 377 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, |
362 Register to) { | 378 Register to) { |
363 DCHECK(from != to); | 379 DCHECK(from != to); |
364 if (FitsInReg8Operand(to) && FitsInReg8Operand(from)) { | 380 if (FitsInReg8Operand(from) && FitsInReg8Operand(to)) { |
381 DCHECK(RegisterIsValid(from, OperandType::kReg8) && | |
382 RegisterIsValid(to, OperandType::kReg8)); | |
rmcilroy
2016/01/26 11:01:45
Are these DCHECKs needed any longer, since they wi
oth
2016/01/26 13:39:56
Done.
| |
365 Output(Bytecode::kMov, from.ToRawOperand(), to.ToRawOperand()); | 383 Output(Bytecode::kMov, from.ToRawOperand(), to.ToRawOperand()); |
366 } else if (FitsInReg16Operand(to) && FitsInReg16Operand(from)) { | 384 } else if (FitsInReg16Operand(from) && FitsInReg16Operand(to)) { |
385 DCHECK(RegisterIsValid(from, OperandType::kReg16) && | |
386 RegisterIsValid(to, OperandType::kReg16)); | |
367 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); | 387 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); |
368 } else { | 388 } else { |
369 UNIMPLEMENTED(); | 389 UNIMPLEMENTED(); |
370 } | 390 } |
371 return *this; | 391 return *this; |
372 } | 392 } |
373 | 393 |
374 | 394 |
395 void BytecodeArrayBuilder::MoveRegisterUntranslated(Register from, | |
396 Register to) { | |
397 // Move bytecodes modify the stack. Checking validity is essential. | |
rmcilroy
2016/01/26 11:01:45
nit- "Move bytecodes modify the stack, so it is es
oth
2016/01/26 13:39:57
Done.
| |
398 if (FitsInReg8OperandUntranslated(from)) { | |
399 CHECK(RegisterIsValid(from, OperandType::kReg8) && | |
400 RegisterIsValid(to, OperandType::kReg16)); | |
401 } else if (FitsInReg8OperandUntranslated(to)) { | |
402 CHECK(RegisterIsValid(from, OperandType::kReg16) && | |
403 RegisterIsValid(to, OperandType::kReg8)); | |
404 } else { | |
405 UNIMPLEMENTED(); | |
406 } | |
407 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); | |
408 } | |
409 | |
410 | |
411 bool BytecodeArrayBuilder::RegisterOperandIsMovable(Bytecode bytecode, | |
412 int operand_index) { | |
413 // By design, we only support moving individual registers. There | |
414 // should be wide variants of such bytecodes instead to avoid the | |
415 // need for a large translation window. | |
416 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); | |
417 if (operand_type == OperandType::kReg8 || | |
418 operand_type == OperandType::kReg16) { | |
419 if (operand_index == Bytecodes::NumberOfOperands(bytecode) - 1) { | |
420 return true; | |
421 } | |
422 OperandType next_operand_type = | |
423 Bytecodes::GetOperandType(bytecode, operand_index + 1); | |
424 return (next_operand_type != OperandType::kRegCount8 && | |
425 next_operand_type != OperandType::kRegCount16); | |
426 } else { | |
427 // TODO(oth): In the next CL in the series, this is possible: | |
428 // DCHECK(Bytecodes::IsRegisterOperand(bytecode, operand_index)); | |
rmcilroy
2016/01/26 11:01:45
Could we do this bytecode right at the top of the
oth
2016/01/26 13:39:56
Re-ordered. Test not necessary here, comment remov
| |
429 return false; | |
430 } | |
431 } | |
432 | |
375 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal( | 433 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal( |
376 const Handle<String> name, int feedback_slot, LanguageMode language_mode, | 434 const Handle<String> name, int feedback_slot, LanguageMode language_mode, |
377 TypeofMode typeof_mode) { | 435 TypeofMode typeof_mode) { |
378 // TODO(rmcilroy): Potentially store language and typeof information in an | 436 // TODO(rmcilroy): Potentially store language and typeof information in an |
379 // operand rather than having extra bytecodes. | 437 // operand rather than having extra bytecodes. |
380 Bytecode bytecode = BytecodeForLoadGlobal(language_mode, typeof_mode); | 438 Bytecode bytecode = BytecodeForLoadGlobal(language_mode, typeof_mode); |
381 size_t name_index = GetConstantPoolEntry(name); | 439 size_t name_index = GetConstantPoolEntry(name); |
382 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { | 440 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { |
383 Output(bytecode, static_cast<uint8_t>(name_index), | 441 Output(bytecode, static_cast<uint8_t>(name_index), |
384 static_cast<uint8_t>(feedback_slot)); | 442 static_cast<uint8_t>(feedback_slot)); |
(...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1076 } | 1134 } |
1077 | 1135 |
1078 | 1136 |
1079 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, | 1137 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, |
1080 Register first_arg, | 1138 Register first_arg, |
1081 size_t arg_count) { | 1139 size_t arg_count) { |
1082 if (!first_arg.is_valid()) { | 1140 if (!first_arg.is_valid()) { |
1083 DCHECK_EQ(0u, arg_count); | 1141 DCHECK_EQ(0u, arg_count); |
1084 first_arg = Register(0); | 1142 first_arg = Register(0); |
1085 } | 1143 } |
1086 | |
1087 if (FitsInReg8Operand(constructor) && FitsInReg8Operand(first_arg) && | 1144 if (FitsInReg8Operand(constructor) && FitsInReg8Operand(first_arg) && |
1088 FitsInIdx8Operand(arg_count)) { | 1145 FitsInIdx8Operand(arg_count)) { |
1089 Output(Bytecode::kNew, constructor.ToRawOperand(), first_arg.ToRawOperand(), | 1146 Output(Bytecode::kNew, constructor.ToRawOperand(), first_arg.ToRawOperand(), |
1090 static_cast<uint8_t>(arg_count)); | 1147 static_cast<uint8_t>(arg_count)); |
1091 } else if (FitsInReg16Operand(constructor) && FitsInReg16Operand(first_arg) && | 1148 } else if (FitsInReg16Operand(constructor) && FitsInReg16Operand(first_arg) && |
1092 FitsInIdx16Operand(arg_count)) { | 1149 FitsInIdx16Operand(arg_count)) { |
1093 Output(Bytecode::kNewWide, constructor.ToRawOperand(), | 1150 Output(Bytecode::kNewWide, constructor.ToRawOperand(), |
1094 first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); | 1151 first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); |
1095 } else { | 1152 } else { |
1096 UNIMPLEMENTED(); | 1153 UNIMPLEMENTED(); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1174 Output(Bytecode::kDeleteLookupSlot); | 1231 Output(Bytecode::kDeleteLookupSlot); |
1175 return *this; | 1232 return *this; |
1176 } | 1233 } |
1177 | 1234 |
1178 | 1235 |
1179 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 1236 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
1180 return constant_array_builder()->Insert(object); | 1237 return constant_array_builder()->Insert(object); |
1181 } | 1238 } |
1182 | 1239 |
1183 | 1240 |
1241 void BytecodeArrayBuilder::ForgeTemporaryRegister() { | |
1242 temporary_register_count_++; | |
1243 } | |
1244 | |
1245 | |
1184 int BytecodeArrayBuilder::BorrowTemporaryRegister() { | 1246 int BytecodeArrayBuilder::BorrowTemporaryRegister() { |
1185 if (free_temporaries_.empty()) { | 1247 if (free_temporaries_.empty()) { |
1186 temporary_register_count_ += 1; | 1248 ForgeTemporaryRegister(); |
1187 return last_temporary_register().index(); | 1249 return last_temporary_register().index(); |
1188 } else { | 1250 } else { |
1189 auto pos = free_temporaries_.begin(); | 1251 auto pos = free_temporaries_.begin(); |
1190 int retval = *pos; | 1252 int retval = *pos; |
1191 free_temporaries_.erase(pos); | 1253 free_temporaries_.erase(pos); |
1192 return retval; | 1254 return retval; |
1193 } | 1255 } |
1194 } | 1256 } |
1195 | 1257 |
1196 | 1258 |
1197 int BytecodeArrayBuilder::BorrowTemporaryRegisterNotInRange(int start_index, | 1259 int BytecodeArrayBuilder::BorrowTemporaryRegisterNotInRange(int start_index, |
1198 int end_index) { | 1260 int end_index) { |
1199 auto index = free_temporaries_.lower_bound(start_index); | 1261 auto index = free_temporaries_.lower_bound(start_index); |
1200 if (index == free_temporaries_.begin()) { | 1262 if (index == free_temporaries_.begin()) { |
1201 // If start_index is the first free register, check for a register | 1263 // If start_index is the first free register, check for a register |
1202 // greater than end_index. | 1264 // greater than end_index. |
1203 index = free_temporaries_.upper_bound(end_index); | 1265 index = free_temporaries_.upper_bound(end_index); |
1204 if (index == free_temporaries_.end()) { | 1266 if (index == free_temporaries_.end()) { |
1205 temporary_register_count_ += 1; | 1267 ForgeTemporaryRegister(); |
1206 return last_temporary_register().index(); | 1268 return last_temporary_register().index(); |
1207 } | 1269 } |
1208 } else { | 1270 } else { |
1209 // If there is a free register < start_index | 1271 // If there is a free register < start_index |
1210 index--; | 1272 index--; |
1211 } | 1273 } |
1212 | 1274 |
1213 int retval = *index; | 1275 int retval = *index; |
1214 free_temporaries_.erase(index); | 1276 free_temporaries_.erase(index); |
1215 return retval; | 1277 return retval; |
(...skipping 11 matching lines...) Expand all Loading... | |
1227 free_temporaries_.insert(reg_index); | 1289 free_temporaries_.insert(reg_index); |
1228 } | 1290 } |
1229 | 1291 |
1230 | 1292 |
1231 int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters( | 1293 int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters( |
1232 size_t count) { | 1294 size_t count) { |
1233 if (count == 0) { | 1295 if (count == 0) { |
1234 return -1; | 1296 return -1; |
1235 } | 1297 } |
1236 | 1298 |
1299 // TODO(oth): replace use of set<> here for free_temporaries with a | |
1300 // more efficient structure. And/or partition into two searches - | |
1301 // one before the translation window and one after. | |
1302 | |
1303 // A run will require at least |count| free temporaries. | |
1304 while (free_temporaries_.size() < count) { | |
1305 ForgeTemporaryRegister(); | |
1306 free_temporaries_.insert(last_temporary_register().index()); | |
1307 } | |
1308 | |
1237 // Search within existing temporaries for a run. | 1309 // Search within existing temporaries for a run. |
1238 auto start = free_temporaries_.begin(); | 1310 auto start = free_temporaries_.begin(); |
1239 size_t run_length = 0; | 1311 size_t run_length = 0; |
1240 for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) { | 1312 for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) { |
1241 if (*run_end != *start + static_cast<int>(run_length)) { | 1313 int expected = *start + static_cast<int>(run_length); |
1314 if (*run_end != expected) { | |
1242 start = run_end; | 1315 start = run_end; |
1243 run_length = 0; | 1316 run_length = 0; |
1244 } | 1317 } |
1318 Register reg_start(*start); | |
1319 Register reg_expected(expected); | |
1320 if (RegisterTranslator::DistanceToTranslationWindow(reg_start) > 0 && | |
1321 RegisterTranslator::DistanceToTranslationWindow(reg_expected) <= 0) { | |
1322 // Run straddles the lower edge of the translation window. Registers | |
1323 // after the start of this boundary are displaced by the register | |
1324 // translator to provide a hole for translation. Runs either side | |
1325 // of the boundary are fine. | |
1326 start = run_end; | |
1327 run_length = 0; | |
1328 } | |
1245 if (++run_length == count) { | 1329 if (++run_length == count) { |
1246 return *start; | 1330 return *start; |
1247 } | 1331 } |
1248 } | 1332 } |
1249 | 1333 |
1250 // Continue run if possible across existing last temporary. | 1334 // Continue run if possible across existing last temporary. |
1251 if (temporary_register_count_ > 0 && | 1335 if (temporary_register_count_ > 0 && |
1252 (start == free_temporaries_.end() || | 1336 (start == free_temporaries_.end() || |
1253 *start + static_cast<int>(run_length) != | 1337 *start + static_cast<int>(run_length) != |
1254 last_temporary_register().index() + 1)) { | 1338 last_temporary_register().index() + 1)) { |
1255 run_length = 0; | 1339 run_length = 0; |
1256 } | 1340 } |
1257 | 1341 |
1342 // Pad temporaries if extended run would cross translation boundary. | |
1343 Register reg_first(*start); | |
1344 Register reg_last(*start + static_cast<int>(count) - 1); | |
1345 DCHECK_GT(RegisterTranslator::DistanceToTranslationWindow(reg_first), | |
1346 RegisterTranslator::DistanceToTranslationWindow(reg_last)); | |
1347 while (RegisterTranslator::DistanceToTranslationWindow(reg_first) > 0 && | |
1348 RegisterTranslator::DistanceToTranslationWindow(reg_last) <= 0) { | |
1349 ForgeTemporaryRegister(); | |
1350 free_temporaries_.insert(last_temporary_register().index()); | |
1351 start = --free_temporaries_.end(); | |
1352 reg_first = Register(*start); | |
1353 reg_last = Register(*start + static_cast<int>(count) - 1); | |
1354 run_length = 0; | |
1355 } | |
1356 | |
1258 // Ensure enough registers for run. | 1357 // Ensure enough registers for run. |
1259 while (run_length++ < count) { | 1358 while (run_length++ < count) { |
1260 temporary_register_count_++; | 1359 ForgeTemporaryRegister(); |
1261 free_temporaries_.insert(last_temporary_register().index()); | 1360 free_temporaries_.insert(last_temporary_register().index()); |
1262 } | 1361 } |
1263 return last_temporary_register().index() - static_cast<int>(count) + 1; | 1362 |
1363 int run_start = | |
1364 last_temporary_register().index() - static_cast<int>(count) + 1; | |
1365 DCHECK(RegisterTranslator::DistanceToTranslationWindow(Register(run_start)) <= | |
1366 0 || | |
1367 RegisterTranslator::DistanceToTranslationWindow( | |
1368 Register(run_start + static_cast<int>(count) - 1)) > 0); | |
1369 return run_start; | |
1264 } | 1370 } |
1265 | 1371 |
1266 | 1372 |
1267 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { | 1373 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { |
1268 if (temporary_register_count_ > 0) { | 1374 if (temporary_register_count_ > 0) { |
1269 DCHECK(reg.index() >= first_temporary_register().index() && | 1375 DCHECK(reg.index() >= first_temporary_register().index() && |
1270 reg.index() <= last_temporary_register().index()); | 1376 reg.index() <= last_temporary_register().index()); |
1271 return free_temporaries_.find(reg.index()) == free_temporaries_.end(); | 1377 return free_temporaries_.find(reg.index()) == free_temporaries_.end(); |
1272 } else { | 1378 } else { |
1273 return false; | 1379 return false; |
1274 } | 1380 } |
1275 } | 1381 } |
1276 | 1382 |
1277 | 1383 |
1278 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, | 1384 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, |
1279 uint32_t operand_value) const { | 1385 uint32_t operand_value) const { |
1280 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); | 1386 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); |
1281 switch (operand_type) { | 1387 switch (operand_type) { |
1282 case OperandType::kNone: | 1388 case OperandType::kNone: |
1283 return false; | 1389 return false; |
rmcilroy
2016/01/26 11:01:45
The DCHECK below looks like dead code?
oth
2016/01/26 13:39:57
Done. Rebase or re-org snafu. Looks like it once b
| |
1284 case OperandType::kRegCount16: | 1390 DCHECK(operand_index != 0); |
rmcilroy
2016/01/26 11:01:45
Dead code?
oth
2016/01/26 13:39:56
Assuming this is flagging the same dead code as th
rmcilroy
2016/01/26 14:08:07
Yes it was. Weirdly the tool told me it failed to
| |
1391 case OperandType::kRegCount16: { | |
1392 // Expect kRegCount16 is part of a range previous operand is a | |
1393 // valid operand to start a range. | |
1394 if (operand_index > 0) { | |
rmcilroy
2016/01/26 11:01:45
Just DCHECK operand_index > 0 here (and below) ?
oth
2016/01/26 13:39:57
Leaving as-is. This method should be consistent an
rmcilroy
2016/01/26 14:08:07
Acknowledged.
| |
1395 OperandType previous_operand_type = | |
1396 Bytecodes::GetOperandType(bytecode, operand_index - 1); | |
1397 return ((previous_operand_type == OperandType::kMaybeReg16 || | |
1398 previous_operand_type == OperandType::kReg16) && | |
1399 static_cast<uint16_t>(operand_value) == operand_value); | |
1400 } else { | |
1401 return false; | |
1402 } | |
1403 } | |
1404 case OperandType::kRegCount8: { | |
1405 // Expect kRegCount8 is part of a range previous operand is a | |
1406 // valid operand to start a range. | |
1407 if (operand_index > 0) { | |
1408 OperandType previous_operand_type = | |
1409 Bytecodes::GetOperandType(bytecode, operand_index - 1); | |
1410 return ((previous_operand_type == OperandType::kMaybeReg8 || | |
1411 previous_operand_type == OperandType::kReg8 || | |
1412 previous_operand_type == OperandType::kMaybeReg16 || | |
1413 previous_operand_type == OperandType::kReg16) && | |
rmcilroy
2016/01/26 11:01:45
Should the kReg16 be valid here? Maybe kRegCount8
oth
2016/01/26 13:39:56
Removed kReg16.
CallRuntimeWide and CallRuntimeFo
| |
1414 static_cast<uint8_t>(operand_value) == operand_value); | |
1415 } else { | |
1416 return false; | |
1417 } | |
1418 } | |
1285 case OperandType::kIdx16: | 1419 case OperandType::kIdx16: |
1286 return static_cast<uint16_t>(operand_value) == operand_value; | 1420 return static_cast<uint16_t>(operand_value) == operand_value; |
1287 case OperandType::kRegCount8: | |
1288 case OperandType::kImm8: | 1421 case OperandType::kImm8: |
1289 case OperandType::kIdx8: | 1422 case OperandType::kIdx8: |
1290 return static_cast<uint8_t>(operand_value) == operand_value; | 1423 return static_cast<uint8_t>(operand_value) == operand_value; |
1291 case OperandType::kMaybeReg8: | 1424 case OperandType::kMaybeReg8: |
1292 if (operand_value == 0) { | 1425 if (operand_value == 0) { |
1293 return true; | 1426 return true; |
1294 } | 1427 } |
1295 // Fall-through to kReg8 case. | 1428 // Fall-through to kReg8 case. |
1296 case OperandType::kReg8: | 1429 case OperandType::kReg8: |
1297 return RegisterIsValid(Register::FromRawOperand(operand_value), | 1430 return RegisterIsValid(Register::FromRawOperand(operand_value), |
(...skipping 24 matching lines...) Expand all Loading... | |
1322 return RegisterIsValid(reg, operand_type); | 1455 return RegisterIsValid(reg, operand_type); |
1323 } | 1456 } |
1324 } | 1457 } |
1325 UNREACHABLE(); | 1458 UNREACHABLE(); |
1326 return false; | 1459 return false; |
1327 } | 1460 } |
1328 | 1461 |
1329 | 1462 |
1330 bool BytecodeArrayBuilder::RegisterIsValid(Register reg, | 1463 bool BytecodeArrayBuilder::RegisterIsValid(Register reg, |
1331 OperandType reg_type) const { | 1464 OperandType reg_type) const { |
1465 if (!reg.is_valid()) { | |
1466 return false; | |
1467 } | |
1468 | |
1332 switch (Bytecodes::SizeOfOperand(reg_type)) { | 1469 switch (Bytecodes::SizeOfOperand(reg_type)) { |
1333 case OperandSize::kByte: | 1470 case OperandSize::kByte: |
1334 if (!FitsInReg8Operand(reg)) { return false; } | 1471 if (!FitsInReg8OperandUntranslated(reg)) { |
1472 return false; | |
1473 } | |
1335 break; | 1474 break; |
1336 case OperandSize::kShort: | 1475 case OperandSize::kShort: |
1337 if (!FitsInReg16Operand(reg)) { return false; } | 1476 if (!FitsInReg16OperandUntranslated(reg)) { |
1477 return false; | |
1478 } | |
1338 break; | 1479 break; |
1339 case OperandSize::kNone: | 1480 case OperandSize::kNone: |
1340 UNREACHABLE(); | 1481 UNREACHABLE(); |
1341 return false; | 1482 return false; |
1342 } | 1483 } |
1343 | 1484 |
1344 if (reg.is_current_context() || reg.is_function_closure() || | 1485 if (reg.is_current_context() || reg.is_function_closure() || |
1345 reg.is_new_target()) { | 1486 reg.is_new_target()) { |
1346 return true; | 1487 return true; |
1347 } else if (reg.is_parameter()) { | 1488 } else if (reg.is_parameter()) { |
1348 int parameter_index = reg.ToParameterIndex(parameter_count_); | 1489 int parameter_index = reg.ToParameterIndex(parameter_count()); |
1349 return parameter_index >= 0 && parameter_index < parameter_count_; | 1490 return parameter_index >= 0 && parameter_index < parameter_count(); |
1350 } else if (reg.index() < fixed_register_count()) { | 1491 } else if (RegisterTranslator::InTranslationWindow(reg)) { |
1351 return true; | 1492 return translation_register_count() > 0; |
1352 } else { | 1493 } else { |
1353 return TemporaryRegisterIsLive(reg); | 1494 reg = RegisterTranslator::UntranslateRegister(reg); |
1495 if (reg.index() < fixed_register_count()) { | |
1496 return true; | |
1497 } else { | |
1498 return TemporaryRegisterIsLive(reg); | |
1499 } | |
1354 } | 1500 } |
1355 } | 1501 } |
1356 | 1502 |
1357 | 1503 |
1358 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { | 1504 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { |
1359 return last_bytecode_start_ < bytecodes()->size() && | 1505 return last_bytecode_start_ < bytecodes()->size() && |
1360 last_bytecode_start_ >= last_block_end_; | 1506 last_bytecode_start_ >= last_block_end_; |
1361 } | 1507 } |
1362 | 1508 |
1363 | 1509 |
1364 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { | 1510 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { |
1365 if (LastBytecodeInSameBlock()) { | 1511 if (LastBytecodeInSameBlock()) { |
1366 PreviousBytecodeHelper previous_bytecode(*this); | 1512 PreviousBytecodeHelper previous_bytecode(*this); |
1367 Bytecode bytecode = previous_bytecode.GetBytecode(); | 1513 Bytecode bytecode = previous_bytecode.GetBytecode(); |
1368 if ((bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) && | 1514 if (bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) { |
1369 (reg == Register::FromOperand(previous_bytecode.GetOperand(0)))) { | 1515 Register previous_reg = |
1370 return true; | 1516 Register::FromOperand(previous_bytecode.GetOperand(0)); |
1517 return previous_reg == reg; | |
1371 } | 1518 } |
1372 } | 1519 } |
1373 return false; | 1520 return false; |
1374 } | 1521 } |
1375 | 1522 |
1376 | 1523 |
1377 // static | 1524 // static |
1378 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { | 1525 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { |
1379 switch (op) { | 1526 switch (op) { |
1380 case Token::Value::ADD: | 1527 case Token::Value::ADD: |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1673 | 1820 |
1674 | 1821 |
1675 // static | 1822 // static |
1676 bool BytecodeArrayBuilder::FitsInIdx16Operand(size_t value) { | 1823 bool BytecodeArrayBuilder::FitsInIdx16Operand(size_t value) { |
1677 return value <= static_cast<size_t>(kMaxUInt16); | 1824 return value <= static_cast<size_t>(kMaxUInt16); |
1678 } | 1825 } |
1679 | 1826 |
1680 | 1827 |
1681 // static | 1828 // static |
1682 bool BytecodeArrayBuilder::FitsInReg8Operand(Register value) { | 1829 bool BytecodeArrayBuilder::FitsInReg8Operand(Register value) { |
1683 return kMinInt8 <= value.index() && value.index() <= kMaxInt8; | 1830 return RegisterTranslator::FitsInReg8Operand(value); |
1831 } | |
1832 | |
1833 | |
1834 // static | |
1835 bool BytecodeArrayBuilder::FitsInReg8OperandUntranslated(Register value) { | |
1836 return value.is_byte_operand(); | |
1684 } | 1837 } |
1685 | 1838 |
1686 | 1839 |
1687 // static | 1840 // static |
1688 bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) { | 1841 bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) { |
1689 return kMinInt16 <= value.index() && value.index() <= kMaxInt16; | 1842 return RegisterTranslator::FitsInReg16Operand(value); |
1843 } | |
1844 | |
1845 | |
1846 // static | |
1847 bool BytecodeArrayBuilder::FitsInReg16OperandUntranslated(Register value) { | |
1848 return value.is_short_operand(); | |
1690 } | 1849 } |
1691 | 1850 |
1692 } // namespace interpreter | 1851 } // namespace interpreter |
1693 } // namespace internal | 1852 } // namespace internal |
1694 } // namespace v8 | 1853 } // namespace v8 |
OLD | NEW |