OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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-register-optimizer.h" | 5 #include "src/interpreter/bytecode-register-optimizer.h" |
6 | 6 |
7 namespace v8 { | 7 namespace v8 { |
8 namespace internal { | 8 namespace internal { |
9 namespace interpreter { | 9 namespace interpreter { |
10 | 10 |
11 const uint32_t BytecodeRegisterOptimizer::kInvalidEquivalenceId; | 11 const uint32_t BytecodeRegisterOptimizer::kInvalidEquivalenceId; |
12 | 12 |
13 // A class for tracking the state of a register. This class tracks | 13 // A class for tracking the state of a register. This class tracks |
14 // which equivalence set a register is a member of and also whether a | 14 // which equivalence set a register is a member of and also whether a |
15 // register is materialized in the bytecode stream. | 15 // register is materialized in the bytecode stream. |
16 class BytecodeRegisterOptimizer::RegisterInfo final : public ZoneObject { | 16 class BytecodeRegisterOptimizer::RegisterInfo final : public ZoneObject { |
17 public: | 17 public: |
18 RegisterInfo(Register reg, uint32_t equivalence_id, bool materialized) | 18 RegisterInfo(Register reg, uint32_t equivalence_id, bool materialized, |
| 19 bool allocated) |
19 : register_(reg), | 20 : register_(reg), |
20 equivalence_id_(equivalence_id), | 21 equivalence_id_(equivalence_id), |
21 materialized_(materialized), | 22 materialized_(materialized), |
| 23 allocated_(allocated), |
22 next_(this), | 24 next_(this), |
23 prev_(this) {} | 25 prev_(this) {} |
24 | 26 |
25 void AddToEquivalenceSetOf(RegisterInfo* info); | 27 void AddToEquivalenceSetOf(RegisterInfo* info); |
26 void MoveToNewEquivalenceSet(uint32_t equivalence_id, bool materialized); | 28 void MoveToNewEquivalenceSet(uint32_t equivalence_id, bool materialized); |
27 bool IsOnlyMemberOfEquivalenceSet() const; | 29 bool IsOnlyMemberOfEquivalenceSet() const; |
28 bool IsOnlyMaterializedMemberOfEquivalenceSet() const; | 30 bool IsOnlyMaterializedMemberOfEquivalenceSet() const; |
29 bool IsInSameEquivalenceSet(RegisterInfo* info) const; | 31 bool IsInSameEquivalenceSet(RegisterInfo* info) const; |
30 | 32 |
31 // Get a member of this register's equivalence set that is | 33 // Get a member of this register's equivalence set that is |
32 // materialized. The materialized equivalent will be this register | 34 // materialized. The materialized equivalent will be this register |
33 // if it is materialized. Returns nullptr if no materialized | 35 // if it is materialized. Returns nullptr if no materialized |
34 // equivalent exists. | 36 // equivalent exists. |
35 RegisterInfo* GetMaterializedEquivalent(); | 37 RegisterInfo* GetMaterializedEquivalent(); |
36 | 38 |
37 // Get a member of this register's equivalence set that is | 39 // Get a member of this register's equivalence set that is |
38 // materialized and not register |reg|. The materialized equivalent | 40 // materialized and not register |reg|. The materialized equivalent |
39 // will be this register if it is materialized. Returns nullptr if | 41 // will be this register if it is materialized. Returns nullptr if |
40 // no materialized equivalent exists. | 42 // no materialized equivalent exists. |
41 RegisterInfo* GetMaterializedEquivalentOtherThan(Register reg); | 43 RegisterInfo* GetMaterializedEquivalentOtherThan(Register reg); |
42 | 44 |
43 // Get a member of this register's equivalence set that is intended | 45 // Get a member of this register's equivalence set that is intended |
44 // to be materialized in place of this register (which is currently | 46 // to be materialized in place of this register (which is currently |
45 // materialized). The best candidate is deemed to be the register | 47 // materialized). The best candidate is deemed to be the register |
46 // with the lowest index as this permits temporary registers to be | 48 // with the lowest index as this permits temporary registers to be |
47 // removed from the bytecode stream. Returns nullptr if no candidate | 49 // removed from the bytecode stream. Returns nullptr if no candidate |
48 // exists. | 50 // exists. |
49 RegisterInfo* GetEquivalentToMaterialize(); | 51 RegisterInfo* GetEquivalentToMaterialize(); |
50 | 52 |
| 53 // Marks all temporary registers of the equivalence set as unmaterialized. |
| 54 void MarkTemporariesAsUnmaterialized(Register temporary_base); |
| 55 |
51 // Get an equivalent register. Returns this if none exists. | 56 // Get an equivalent register. Returns this if none exists. |
52 RegisterInfo* GetEquivalent(); | 57 RegisterInfo* GetEquivalent(); |
53 | 58 |
54 Register register_value() const { return register_; } | 59 Register register_value() const { return register_; } |
55 bool materialized() const { return materialized_; } | 60 bool materialized() const { return materialized_; } |
56 void set_materialized(bool materialized) { materialized_ = materialized; } | 61 void set_materialized(bool materialized) { materialized_ = materialized; } |
| 62 bool allocated() const { return allocated_; } |
| 63 void set_allocated(bool allocated) { allocated_ = allocated; } |
57 void set_equivalence_id(uint32_t equivalence_id) { | 64 void set_equivalence_id(uint32_t equivalence_id) { |
58 equivalence_id_ = equivalence_id; | 65 equivalence_id_ = equivalence_id; |
59 } | 66 } |
60 uint32_t equivalence_id() const { return equivalence_id_; } | 67 uint32_t equivalence_id() const { return equivalence_id_; } |
61 | 68 |
62 private: | 69 private: |
63 Register register_; | 70 Register register_; |
64 uint32_t equivalence_id_; | 71 uint32_t equivalence_id_; |
65 bool materialized_; | 72 bool materialized_; |
| 73 bool allocated_; |
66 | 74 |
67 // Equivalence set pointers. | 75 // Equivalence set pointers. |
68 RegisterInfo* next_; | 76 RegisterInfo* next_; |
69 RegisterInfo* prev_; | 77 RegisterInfo* prev_; |
70 | 78 |
71 DISALLOW_COPY_AND_ASSIGN(RegisterInfo); | 79 DISALLOW_COPY_AND_ASSIGN(RegisterInfo); |
72 }; | 80 }; |
73 | 81 |
74 void BytecodeRegisterOptimizer::RegisterInfo::AddToEquivalenceSetOf( | 82 void BytecodeRegisterOptimizer::RegisterInfo::AddToEquivalenceSetOf( |
75 RegisterInfo* info) { | 83 RegisterInfo* info) { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 | 156 |
149 BytecodeRegisterOptimizer::RegisterInfo* | 157 BytecodeRegisterOptimizer::RegisterInfo* |
150 BytecodeRegisterOptimizer::RegisterInfo::GetEquivalentToMaterialize() { | 158 BytecodeRegisterOptimizer::RegisterInfo::GetEquivalentToMaterialize() { |
151 DCHECK(this->materialized()); | 159 DCHECK(this->materialized()); |
152 RegisterInfo* visitor = this->next_; | 160 RegisterInfo* visitor = this->next_; |
153 RegisterInfo* best_info = nullptr; | 161 RegisterInfo* best_info = nullptr; |
154 while (visitor != this) { | 162 while (visitor != this) { |
155 if (visitor->materialized()) { | 163 if (visitor->materialized()) { |
156 return nullptr; | 164 return nullptr; |
157 } | 165 } |
158 if (best_info == nullptr || | 166 if (visitor->allocated() && |
159 visitor->register_value() < best_info->register_value()) { | 167 (best_info == nullptr || |
| 168 visitor->register_value() < best_info->register_value())) { |
160 best_info = visitor; | 169 best_info = visitor; |
161 } | 170 } |
162 visitor = visitor->next_; | 171 visitor = visitor->next_; |
163 } | 172 } |
164 return best_info; | 173 return best_info; |
165 } | 174 } |
166 | 175 |
| 176 void BytecodeRegisterOptimizer::RegisterInfo::MarkTemporariesAsUnmaterialized( |
| 177 Register temporary_base) { |
| 178 DCHECK(this->register_value() < temporary_base); |
| 179 DCHECK(this->materialized()); |
| 180 RegisterInfo* visitor = this->next_; |
| 181 while (visitor != this) { |
| 182 if (visitor->register_value() >= temporary_base) { |
| 183 visitor->set_materialized(false); |
| 184 } |
| 185 visitor = visitor->next_; |
| 186 } |
| 187 } |
| 188 |
167 BytecodeRegisterOptimizer::RegisterInfo* | 189 BytecodeRegisterOptimizer::RegisterInfo* |
168 BytecodeRegisterOptimizer::RegisterInfo::GetEquivalent() { | 190 BytecodeRegisterOptimizer::RegisterInfo::GetEquivalent() { |
169 return next_; | 191 return next_; |
170 } | 192 } |
171 | 193 |
172 BytecodeRegisterOptimizer::BytecodeRegisterOptimizer( | 194 BytecodeRegisterOptimizer::BytecodeRegisterOptimizer( |
173 Zone* zone, TemporaryRegisterAllocator* register_allocator, | 195 Zone* zone, BytecodeRegisterAllocator* register_allocator, |
174 int parameter_count, BytecodePipelineStage* next_stage) | 196 int fixed_registers_count, int parameter_count, |
| 197 BytecodePipelineStage* next_stage) |
175 : accumulator_(Register::virtual_accumulator()), | 198 : accumulator_(Register::virtual_accumulator()), |
176 temporary_base_(register_allocator->allocation_base()), | 199 temporary_base_(fixed_registers_count), |
177 max_register_index_(register_allocator->allocation_base() - 1), | 200 max_register_index_(fixed_registers_count - 1), |
178 register_info_table_(zone), | 201 register_info_table_(zone), |
179 equivalence_id_(0), | 202 equivalence_id_(0), |
180 next_stage_(next_stage), | 203 next_stage_(next_stage), |
181 flush_required_(false), | 204 flush_required_(false), |
182 zone_(zone) { | 205 zone_(zone) { |
183 register_allocator->set_observer(this); | 206 register_allocator->set_observer(this); |
184 | 207 |
185 // Calculate offset so register index values can be mapped into | 208 // Calculate offset so register index values can be mapped into |
186 // a vector of register metadata. | 209 // a vector of register metadata. |
187 if (parameter_count != 0) { | 210 if (parameter_count != 0) { |
188 register_info_table_offset_ = | 211 register_info_table_offset_ = |
189 -Register::FromParameterIndex(0, parameter_count).index(); | 212 -Register::FromParameterIndex(0, parameter_count).index(); |
190 } else { | 213 } else { |
191 // TODO(oth): This path shouldn't be necessary in bytecode generated | 214 // TODO(oth): This path shouldn't be necessary in bytecode generated |
192 // from Javascript, but a set of tests do not include the JS receiver. | 215 // from Javascript, but a set of tests do not include the JS receiver. |
193 register_info_table_offset_ = -accumulator_.index(); | 216 register_info_table_offset_ = -accumulator_.index(); |
194 } | 217 } |
195 | 218 |
196 // Initialize register map for parameters, locals, and the | 219 // Initialize register map for parameters, locals, and the |
197 // accumulator. | 220 // accumulator. |
198 register_info_table_.resize(register_info_table_offset_ + | 221 register_info_table_.resize(register_info_table_offset_ + |
199 static_cast<size_t>(temporary_base_.index())); | 222 static_cast<size_t>(temporary_base_.index())); |
200 for (size_t i = 0; i < register_info_table_.size(); ++i) { | 223 for (size_t i = 0; i < register_info_table_.size(); ++i) { |
201 register_info_table_[i] = new (zone) RegisterInfo( | 224 register_info_table_[i] = new (zone) RegisterInfo( |
202 RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), true); | 225 RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), true, true); |
203 DCHECK_EQ(register_info_table_[i]->register_value().index(), | 226 DCHECK_EQ(register_info_table_[i]->register_value().index(), |
204 RegisterFromRegisterInfoTableIndex(i).index()); | 227 RegisterFromRegisterInfoTableIndex(i).index()); |
205 } | 228 } |
206 accumulator_info_ = GetRegisterInfo(accumulator_); | 229 accumulator_info_ = GetRegisterInfo(accumulator_); |
207 DCHECK(accumulator_info_->register_value() == accumulator_); | 230 DCHECK(accumulator_info_->register_value() == accumulator_); |
208 } | 231 } |
209 | 232 |
210 // override | 233 // override |
211 Handle<BytecodeArray> BytecodeRegisterOptimizer::ToBytecodeArray( | 234 Handle<BytecodeArray> BytecodeRegisterOptimizer::ToBytecodeArray( |
212 Isolate* isolate, int register_count, int parameter_count, | 235 Isolate* isolate, int register_count, int parameter_count, |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 // Materialize all live registers and break equivalences. | 312 // Materialize all live registers and break equivalences. |
290 size_t count = register_info_table_.size(); | 313 size_t count = register_info_table_.size(); |
291 for (size_t i = 0; i < count; ++i) { | 314 for (size_t i = 0; i < count; ++i) { |
292 RegisterInfo* reg_info = register_info_table_[i]; | 315 RegisterInfo* reg_info = register_info_table_[i]; |
293 if (reg_info->materialized()) { | 316 if (reg_info->materialized()) { |
294 // Walk equivalents of materialized registers, materializing | 317 // Walk equivalents of materialized registers, materializing |
295 // each equivalent register as necessary and placing in their | 318 // each equivalent register as necessary and placing in their |
296 // own equivalence set. | 319 // own equivalence set. |
297 RegisterInfo* equivalent; | 320 RegisterInfo* equivalent; |
298 while ((equivalent = reg_info->GetEquivalent()) != reg_info) { | 321 while ((equivalent = reg_info->GetEquivalent()) != reg_info) { |
299 if (!equivalent->materialized()) { | 322 if (equivalent->allocated() && !equivalent->materialized()) { |
300 OutputRegisterTransfer(reg_info, equivalent); | 323 OutputRegisterTransfer(reg_info, equivalent); |
301 } | 324 } |
302 equivalent->MoveToNewEquivalenceSet(NextEquivalenceId(), true); | 325 equivalent->MoveToNewEquivalenceSet(NextEquivalenceId(), true); |
303 } | 326 } |
304 } | 327 } |
305 } | 328 } |
306 | 329 |
307 flush_required_ = false; | 330 flush_required_ = false; |
308 } | 331 } |
309 | 332 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 RegisterIsObservable(output_info->register_value()); | 420 RegisterIsObservable(output_info->register_value()); |
398 if (output_is_observable) { | 421 if (output_is_observable) { |
399 // Force store to be emitted when register is observable. | 422 // Force store to be emitted when register is observable. |
400 output_info->set_materialized(false); | 423 output_info->set_materialized(false); |
401 RegisterInfo* materialized_info = input_info->GetMaterializedEquivalent(); | 424 RegisterInfo* materialized_info = input_info->GetMaterializedEquivalent(); |
402 OutputRegisterTransfer(materialized_info, output_info, source_info); | 425 OutputRegisterTransfer(materialized_info, output_info, source_info); |
403 } else if (source_info->is_valid()) { | 426 } else if (source_info->is_valid()) { |
404 // Emit a placeholder nop to maintain source position info. | 427 // Emit a placeholder nop to maintain source position info. |
405 EmitNopForSourceInfo(source_info); | 428 EmitNopForSourceInfo(source_info); |
406 } | 429 } |
| 430 |
| 431 bool input_is_observable = RegisterIsObservable(input_info->register_value()); |
| 432 if (input_is_observable) { |
| 433 // If input is observable by the debugger, mark all other temporaries |
| 434 // registers as unmaterialized so that this register is used in preference. |
| 435 input_info->MarkTemporariesAsUnmaterialized(temporary_base_); |
| 436 } |
407 } | 437 } |
408 | 438 |
409 void BytecodeRegisterOptimizer::EmitNopForSourceInfo( | 439 void BytecodeRegisterOptimizer::EmitNopForSourceInfo( |
410 BytecodeSourceInfo* source_info) const { | 440 BytecodeSourceInfo* source_info) const { |
411 DCHECK(source_info->is_valid()); | 441 DCHECK(source_info->is_valid()); |
412 BytecodeNode nop(Bytecode::kNop, source_info); | 442 BytecodeNode nop(Bytecode::kNop, source_info); |
413 next_stage_->Write(&nop); | 443 next_stage_->Write(&nop); |
414 } | 444 } |
415 | 445 |
416 void BytecodeRegisterOptimizer::DoLdar(BytecodeNode* node) { | 446 void BytecodeRegisterOptimizer::DoLdar(BytecodeNode* node) { |
417 Register input = GetRegisterInputOperand( | 447 Register input = GetRegisterInputOperand( |
418 0, node->bytecode(), node->operands(), node->operand_count()); | 448 0, node->bytecode(), node->operands(), node->operand_count()); |
419 RegisterInfo* input_info = GetRegisterInfo(input); | 449 RegisterInfo* input_info = GetRegisterInfo(input); |
420 RegisterTransfer(input_info, accumulator_info_, node->source_info_ptr()); | 450 RegisterTransfer(input_info, accumulator_info_, node->source_info_ptr()); |
421 } | 451 } |
422 | 452 |
423 void BytecodeRegisterOptimizer::DoMov(BytecodeNode* node) { | 453 void BytecodeRegisterOptimizer::DoMov(BytecodeNode* node) { |
424 Register input = GetRegisterInputOperand( | 454 Register input = GetRegisterInputOperand( |
425 0, node->bytecode(), node->operands(), node->operand_count()); | 455 0, node->bytecode(), node->operands(), node->operand_count()); |
426 RegisterInfo* input_info = GetRegisterInfo(input); | 456 RegisterInfo* input_info = GetRegisterInfo(input); |
427 Register output = GetRegisterOutputOperand( | 457 Register output = GetRegisterOutputOperand( |
428 1, node->bytecode(), node->operands(), node->operand_count()); | 458 1, node->bytecode(), node->operands(), node->operand_count()); |
429 RegisterInfo* output_info = GetOrCreateRegisterInfo(output); | 459 RegisterInfo* output_info = GetRegisterInfo(output); |
430 RegisterTransfer(input_info, output_info, node->source_info_ptr()); | 460 RegisterTransfer(input_info, output_info, node->source_info_ptr()); |
431 } | 461 } |
432 | 462 |
433 void BytecodeRegisterOptimizer::DoStar(BytecodeNode* node) { | 463 void BytecodeRegisterOptimizer::DoStar(BytecodeNode* node) { |
434 Register output = GetRegisterOutputOperand( | 464 Register output = GetRegisterOutputOperand( |
435 0, node->bytecode(), node->operands(), node->operand_count()); | 465 0, node->bytecode(), node->operands(), node->operand_count()); |
436 RegisterInfo* output_info = GetOrCreateRegisterInfo(output); | 466 RegisterInfo* output_info = GetRegisterInfo(output); |
437 RegisterTransfer(accumulator_info_, output_info, node->source_info_ptr()); | 467 RegisterTransfer(accumulator_info_, output_info, node->source_info_ptr()); |
438 } | 468 } |
439 | 469 |
440 void BytecodeRegisterOptimizer::PrepareRegisterOutputOperand( | 470 void BytecodeRegisterOptimizer::PrepareRegisterOutputOperand( |
441 RegisterInfo* reg_info) { | 471 RegisterInfo* reg_info) { |
442 if (reg_info->materialized()) { | 472 if (reg_info->materialized()) { |
443 CreateMaterializedEquivalent(reg_info); | 473 CreateMaterializedEquivalent(reg_info); |
444 } | 474 } |
445 max_register_index_ = | 475 max_register_index_ = |
446 std::max(max_register_index_, reg_info->register_value().index()); | 476 std::max(max_register_index_, reg_info->register_value().index()); |
447 reg_info->MoveToNewEquivalenceSet(NextEquivalenceId(), true); | 477 reg_info->MoveToNewEquivalenceSet(NextEquivalenceId(), true); |
448 } | 478 } |
449 | 479 |
450 void BytecodeRegisterOptimizer::PrepareRegisterRangeOutputOperand( | 480 void BytecodeRegisterOptimizer::PrepareRegisterRangeOutputOperand( |
451 Register start, int count) { | 481 Register start, int count) { |
452 for (int i = 0; i < count; ++i) { | 482 for (int i = 0; i < count; ++i) { |
453 Register reg(start.index() + i); | 483 Register reg(start.index() + i); |
454 RegisterInfo* reg_info = GetOrCreateRegisterInfo(reg); | 484 RegisterInfo* reg_info = GetRegisterInfo(reg); |
455 PrepareRegisterOutputOperand(reg_info); | 485 PrepareRegisterOutputOperand(reg_info); |
456 } | 486 } |
457 } | 487 } |
458 | 488 |
459 Register BytecodeRegisterOptimizer::GetEquivalentRegisterForInputOperand( | 489 Register BytecodeRegisterOptimizer::GetEquivalentRegisterForInputOperand( |
460 Register reg) { | 490 Register reg) { |
461 // For a temporary register, RegInfo state may need be created. For | 491 // For a temporary register, RegInfo state may need be created. For |
462 // locals and parameters, the RegInfo state is created in the | 492 // locals and parameters, the RegInfo state is created in the |
463 // BytecodeRegisterOptimizer constructor. | 493 // BytecodeRegisterOptimizer constructor. |
464 RegisterInfo* reg_info = GetOrCreateRegisterInfo(reg); | 494 RegisterInfo* reg_info = GetRegisterInfo(reg); |
465 if (reg_info->materialized()) { | 495 if (reg_info->materialized()) { |
466 return reg; | 496 return reg; |
467 } else { | 497 } else { |
468 RegisterInfo* equivalent_info = | 498 RegisterInfo* equivalent_info = |
469 GetMaterializedEquivalentNotAccumulator(reg_info); | 499 GetMaterializedEquivalentNotAccumulator(reg_info); |
470 return equivalent_info->register_value(); | 500 return equivalent_info->register_value(); |
471 } | 501 } |
472 } | 502 } |
473 | 503 |
474 void BytecodeRegisterOptimizer::PrepareRegisterInputOperand( | 504 void BytecodeRegisterOptimizer::PrepareRegisterInputOperand( |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 int index, Bytecode bytecode, const uint32_t* operands, int operand_count) { | 593 int index, Bytecode bytecode, const uint32_t* operands, int operand_count) { |
564 DCHECK_LT(index, operand_count); | 594 DCHECK_LT(index, operand_count); |
565 DCHECK(Bytecodes::IsRegisterOutputOperandType( | 595 DCHECK(Bytecodes::IsRegisterOutputOperandType( |
566 Bytecodes::GetOperandType(bytecode, index))); | 596 Bytecodes::GetOperandType(bytecode, index))); |
567 return OperandToRegister(operands[index]); | 597 return OperandToRegister(operands[index]); |
568 } | 598 } |
569 | 599 |
570 BytecodeRegisterOptimizer::RegisterInfo* | 600 BytecodeRegisterOptimizer::RegisterInfo* |
571 BytecodeRegisterOptimizer::GetRegisterInfo(Register reg) { | 601 BytecodeRegisterOptimizer::GetRegisterInfo(Register reg) { |
572 size_t index = GetRegisterInfoTableIndex(reg); | 602 size_t index = GetRegisterInfoTableIndex(reg); |
573 return (index < register_info_table_.size()) ? register_info_table_[index] | 603 DCHECK_LT(index, register_info_table_.size()); |
574 : nullptr; | 604 return register_info_table_[index]; |
575 } | 605 } |
576 | 606 |
577 BytecodeRegisterOptimizer::RegisterInfo* | 607 BytecodeRegisterOptimizer::RegisterInfo* |
578 BytecodeRegisterOptimizer::GetOrCreateRegisterInfo(Register reg) { | 608 BytecodeRegisterOptimizer::GetOrCreateRegisterInfo(Register reg) { |
579 size_t index = GetRegisterInfoTableIndex(reg); | 609 size_t index = GetRegisterInfoTableIndex(reg); |
580 return index < register_info_table_.size() ? register_info_table_[index] | 610 return index < register_info_table_.size() ? register_info_table_[index] |
581 : NewRegisterInfo(reg); | 611 : NewRegisterInfo(reg); |
582 } | 612 } |
583 | 613 |
584 BytecodeRegisterOptimizer::RegisterInfo* | 614 BytecodeRegisterOptimizer::RegisterInfo* |
585 BytecodeRegisterOptimizer::NewRegisterInfo(Register reg) { | 615 BytecodeRegisterOptimizer::NewRegisterInfo(Register reg) { |
586 size_t index = GetRegisterInfoTableIndex(reg); | 616 size_t index = GetRegisterInfoTableIndex(reg); |
587 DCHECK_GE(index, register_info_table_.size()); | 617 DCHECK_GE(index, register_info_table_.size()); |
588 GrowRegisterMap(reg); | 618 GrowRegisterMap(reg); |
589 return register_info_table_[index]; | 619 return register_info_table_[index]; |
590 } | 620 } |
591 | 621 |
592 void BytecodeRegisterOptimizer::GrowRegisterMap(Register reg) { | 622 void BytecodeRegisterOptimizer::GrowRegisterMap(Register reg) { |
593 DCHECK(RegisterIsTemporary(reg)); | 623 DCHECK(RegisterIsTemporary(reg)); |
594 size_t index = GetRegisterInfoTableIndex(reg); | 624 size_t index = GetRegisterInfoTableIndex(reg); |
595 DCHECK_GE(index, register_info_table_.size()); | 625 if (index >= register_info_table_.size()) { |
596 size_t new_size = index + 1; | 626 size_t new_size = index + 1; |
597 size_t old_size = register_info_table_.size(); | 627 size_t old_size = register_info_table_.size(); |
598 register_info_table_.resize(new_size); | 628 register_info_table_.resize(new_size); |
599 for (size_t i = old_size; i < new_size; ++i) { | 629 for (size_t i = old_size; i < new_size; ++i) { |
600 register_info_table_[i] = new (zone()) RegisterInfo( | 630 register_info_table_[i] = |
601 RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), false); | 631 new (zone()) RegisterInfo(RegisterFromRegisterInfoTableIndex(i), |
| 632 NextEquivalenceId(), false, false); |
| 633 } |
602 } | 634 } |
603 } | 635 } |
604 | 636 |
605 void BytecodeRegisterOptimizer::TemporaryRegisterFreeEvent(Register reg) { | 637 void BytecodeRegisterOptimizer::RegisterAllocateEvent(Register reg) { |
606 RegisterInfo* info = GetRegisterInfo(reg); | 638 GetOrCreateRegisterInfo(reg)->set_allocated(true); |
607 if (info != nullptr) { | 639 } |
608 // If register is materialized and part of equivalence set, make | 640 |
609 // sure another member of the set holds the value before the | 641 void BytecodeRegisterOptimizer::RegisterListAllocateEvent( |
610 // temporary register is removed. | 642 RegisterList reg_list) { |
611 if (info->materialized()) { | 643 if (reg_list.register_count() != 0) { |
612 CreateMaterializedEquivalent(info); | 644 int first_index = reg_list.first_register().index(); |
| 645 GrowRegisterMap(Register(first_index + reg_list.register_count() - 1)); |
| 646 for (int i = 0; i < reg_list.register_count(); i++) { |
| 647 GetRegisterInfo(Register(first_index + i))->set_allocated(true); |
613 } | 648 } |
614 info->MoveToNewEquivalenceSet(kInvalidEquivalenceId, false); | |
615 } | 649 } |
616 } | 650 } |
617 | 651 |
| 652 void BytecodeRegisterOptimizer::RegisterListFreeEvent(RegisterList reg_list) { |
| 653 int first_index = reg_list.first_register().index(); |
| 654 for (int i = 0; i < reg_list.register_count(); i++) { |
| 655 GetRegisterInfo(Register(first_index + i))->set_allocated(false); |
| 656 } |
| 657 } |
| 658 |
618 } // namespace interpreter | 659 } // namespace interpreter |
619 } // namespace internal | 660 } // namespace internal |
620 } // namespace v8 | 661 } // namespace v8 |
OLD | NEW |