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

Side by Side Diff: src/interpreter/bytecode-array-builder.cc

Issue 1613163002: [interpreter] Wide register support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Unbreak tests. Created 4 years, 10 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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698