OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 #ifndef V8_REGISTER_ALLOCATOR_H_ | 5 #ifndef V8_REGISTER_ALLOCATOR_H_ |
6 #define V8_REGISTER_ALLOCATOR_H_ | 6 #define V8_REGISTER_ALLOCATOR_H_ |
7 | 7 |
8 #include "src/compiler/instruction.h" | 8 #include "src/compiler/instruction.h" |
9 #include "src/zone-containers.h" | 9 #include "src/zone-containers.h" |
10 | 10 |
11 namespace v8 { | 11 namespace v8 { |
12 namespace internal { | 12 namespace internal { |
13 namespace compiler { | 13 namespace compiler { |
14 | 14 |
15 enum RegisterKind { | 15 enum RegisterKind { |
| 16 UNALLOCATED_REGISTERS, |
16 GENERAL_REGISTERS, | 17 GENERAL_REGISTERS, |
17 DOUBLE_REGISTERS | 18 DOUBLE_REGISTERS |
18 }; | 19 }; |
19 | 20 |
20 | 21 |
21 // This class represents a single point of a InstructionOperand's lifetime. For | 22 // This class represents a single point of a InstructionOperand's lifetime. For |
22 // each instruction there are four lifetime positions: | 23 // each instruction there are four lifetime positions: |
23 // | 24 // |
24 // [[START, END], [START, END]] | 25 // [[START, END], [START, END]] |
25 // | 26 // |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 }; | 265 }; |
265 | 266 |
266 | 267 |
267 class SpillRange; | 268 class SpillRange; |
268 | 269 |
269 | 270 |
270 // Representation of SSA values' live ranges as a collection of (continuous) | 271 // Representation of SSA values' live ranges as a collection of (continuous) |
271 // intervals over the instruction ordering. | 272 // intervals over the instruction ordering. |
272 class LiveRange final : public ZoneObject { | 273 class LiveRange final : public ZoneObject { |
273 public: | 274 public: |
274 explicit LiveRange(int id, MachineType machine_type); | 275 explicit LiveRange(int id); |
275 | 276 |
276 UseInterval* first_interval() const { return first_interval_; } | 277 UseInterval* first_interval() const { return first_interval_; } |
277 UsePosition* first_pos() const { return first_pos_; } | 278 UsePosition* first_pos() const { return first_pos_; } |
278 LiveRange* parent() const { return parent_; } | 279 LiveRange* parent() const { return parent_; } |
279 LiveRange* TopLevel() { return (parent_ == nullptr) ? this : parent_; } | 280 LiveRange* TopLevel() { return (parent_ == nullptr) ? this : parent_; } |
280 const LiveRange* TopLevel() const { | 281 const LiveRange* TopLevel() const { |
281 return (parent_ == nullptr) ? this : parent_; | 282 return (parent_ == nullptr) ? this : parent_; |
282 } | 283 } |
283 LiveRange* next() const { return next_; } | 284 LiveRange* next() const { return next_; } |
284 bool IsChild() const { return parent() != nullptr; } | 285 bool IsChild() const { return parent() != nullptr; } |
285 int id() const { return id_; } | 286 int id() const { return id_; } |
286 bool IsFixed() const { return id_ < 0; } | 287 bool IsFixed() const { return id_ < 0; } |
287 bool IsEmpty() const { return first_interval() == nullptr; } | 288 bool IsEmpty() const { return first_interval() == nullptr; } |
288 InstructionOperand GetAssignedOperand() const; | 289 InstructionOperand GetAssignedOperand() const; |
289 int spill_start_index() const { return spill_start_index_; } | 290 int spill_start_index() const { return spill_start_index_; } |
290 | 291 |
291 MachineType machine_type() const { return MachineTypeField::decode(bits_); } | |
292 | |
293 int assigned_register() const { return AssignedRegisterField::decode(bits_); } | 292 int assigned_register() const { return AssignedRegisterField::decode(bits_); } |
294 bool HasRegisterAssigned() const { | 293 bool HasRegisterAssigned() const { |
295 return assigned_register() != kUnassignedRegister; | 294 return assigned_register() != kUnassignedRegister; |
296 } | 295 } |
297 void set_assigned_register(int reg); | 296 void set_assigned_register(int reg); |
298 void UnsetAssignedRegister(); | 297 void UnsetAssignedRegister(); |
299 | 298 |
300 bool spilled() const { return SpilledField::decode(bits_); } | 299 bool spilled() const { return SpilledField::decode(bits_); } |
301 void Spill(); | 300 void Spill(); |
302 | 301 |
303 RegisterKind kind() const; | 302 RegisterKind kind() const { return RegisterKindField::decode(bits_); } |
| 303 void set_kind(RegisterKind kind) { |
| 304 bits_ = RegisterKindField::update(bits_, kind); |
| 305 } |
304 | 306 |
305 // Correct only for parent. | 307 // Correct only for parent. |
306 bool is_phi() const { return IsPhiField::decode(bits_); } | 308 bool is_phi() const { return IsPhiField::decode(bits_); } |
307 void set_is_phi(bool value) { bits_ = IsPhiField::update(bits_, value); } | 309 void set_is_phi(bool value) { bits_ = IsPhiField::update(bits_, value); } |
308 | 310 |
309 // Correct only for parent. | 311 // Correct only for parent. |
310 bool is_non_loop_phi() const { return IsNonLoopPhiField::decode(bits_); } | 312 bool is_non_loop_phi() const { return IsNonLoopPhiField::decode(bits_); } |
311 void set_is_non_loop_phi(bool value) { | 313 void set_is_non_loop_phi(bool value) { |
312 bits_ = IsNonLoopPhiField::update(bits_, value); | 314 bits_ = IsNonLoopPhiField::update(bits_, value); |
313 } | 315 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 DCHECK(spill_type() == SpillType::kSpillRange); | 379 DCHECK(spill_type() == SpillType::kSpillRange); |
378 return spill_range_; | 380 return spill_range_; |
379 } | 381 } |
380 bool HasNoSpillType() const { | 382 bool HasNoSpillType() const { |
381 return spill_type() == SpillType::kNoSpillType; | 383 return spill_type() == SpillType::kNoSpillType; |
382 } | 384 } |
383 bool HasSpillOperand() const { | 385 bool HasSpillOperand() const { |
384 return spill_type() == SpillType::kSpillOperand; | 386 return spill_type() == SpillType::kSpillOperand; |
385 } | 387 } |
386 bool HasSpillRange() const { return spill_type() == SpillType::kSpillRange; } | 388 bool HasSpillRange() const { return spill_type() == SpillType::kSpillRange; } |
387 AllocatedOperand GetSpillRangeOperand() const; | |
388 | 389 |
389 void SpillAtDefinition(Zone* zone, int gap_index, | 390 void SpillAtDefinition(Zone* zone, int gap_index, |
390 InstructionOperand* operand); | 391 InstructionOperand* operand); |
391 void SetSpillOperand(InstructionOperand* operand); | 392 void SetSpillOperand(InstructionOperand* operand); |
392 void SetSpillRange(SpillRange* spill_range); | 393 void SetSpillRange(SpillRange* spill_range); |
| 394 void CommitSpillOperand(AllocatedOperand* operand); |
393 void CommitSpillsAtDefinition(InstructionSequence* sequence, | 395 void CommitSpillsAtDefinition(InstructionSequence* sequence, |
394 const InstructionOperand& operand, | 396 InstructionOperand* operand, |
395 bool might_be_duplicated); | 397 bool might_be_duplicated); |
396 | 398 |
397 void SetSpillStartIndex(int start) { | 399 void SetSpillStartIndex(int start) { |
398 spill_start_index_ = Min(start, spill_start_index_); | 400 spill_start_index_ = Min(start, spill_start_index_); |
399 } | 401 } |
400 | 402 |
401 bool ShouldBeAllocatedBefore(const LiveRange* other) const; | 403 bool ShouldBeAllocatedBefore(const LiveRange* other) const; |
402 bool CanCover(LifetimePosition position) const; | 404 bool CanCover(LifetimePosition position) const; |
403 bool Covers(LifetimePosition position) const; | 405 bool Covers(LifetimePosition position) const; |
404 LifetimePosition FirstIntersection(LiveRange* other) const; | 406 LifetimePosition FirstIntersection(LiveRange* other) const; |
405 | 407 |
406 // Add a new interval or a new use position to this live range. | 408 // Add a new interval or a new use position to this live range. |
407 void EnsureInterval(LifetimePosition start, LifetimePosition end, Zone* zone); | 409 void EnsureInterval(LifetimePosition start, LifetimePosition end, Zone* zone); |
408 void AddUseInterval(LifetimePosition start, LifetimePosition end, Zone* zone); | 410 void AddUseInterval(LifetimePosition start, LifetimePosition end, Zone* zone); |
409 void AddUsePosition(UsePosition* pos); | 411 void AddUsePosition(UsePosition* pos); |
410 | 412 |
411 // Shorten the most recently added interval by setting a new start. | 413 // Shorten the most recently added interval by setting a new start. |
412 void ShortenTo(LifetimePosition start); | 414 void ShortenTo(LifetimePosition start); |
413 | 415 |
414 void Verify() const; | 416 void Verify() const; |
415 | 417 |
416 void ConvertUsesToOperand(const InstructionOperand& op, | 418 void ConvertUsesToOperand(const InstructionOperand& op, |
417 const InstructionOperand& spill_op); | 419 InstructionOperand* spill_op); |
418 void SetUseHints(int register_index); | 420 void SetUseHints(int register_index); |
419 void UnsetUseHints() { SetUseHints(kUnassignedRegister); } | 421 void UnsetUseHints() { SetUseHints(kUnassignedRegister); } |
420 | 422 |
421 private: | 423 private: |
422 struct SpillAtDefinitionList; | 424 struct SpillAtDefinitionList; |
423 | 425 |
424 void set_spill_type(SpillType value) { | 426 void set_spill_type(SpillType value) { |
425 bits_ = SpillTypeField::update(bits_, value); | 427 bits_ = SpillTypeField::update(bits_, value); |
426 } | 428 } |
427 | 429 |
428 void set_spilled(bool value) { bits_ = SpilledField::update(bits_, value); } | 430 void set_spilled(bool value) { bits_ = SpilledField::update(bits_, value); } |
429 | 431 |
430 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const; | 432 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const; |
431 void AdvanceLastProcessedMarker(UseInterval* to_start_of, | 433 void AdvanceLastProcessedMarker(UseInterval* to_start_of, |
432 LifetimePosition but_not_past) const; | 434 LifetimePosition but_not_past) const; |
433 | 435 |
434 typedef BitField<bool, 0, 1> SpilledField; | 436 typedef BitField<bool, 0, 1> SpilledField; |
435 typedef BitField<bool, 1, 1> HasSlotUseField; | 437 typedef BitField<bool, 1, 1> HasSlotUseField; |
436 typedef BitField<bool, 2, 1> IsPhiField; | 438 typedef BitField<bool, 2, 1> IsPhiField; |
437 typedef BitField<bool, 3, 1> IsNonLoopPhiField; | 439 typedef BitField<bool, 3, 1> IsNonLoopPhiField; |
438 typedef BitField<SpillType, 4, 2> SpillTypeField; | 440 typedef BitField<RegisterKind, 4, 2> RegisterKindField; |
439 typedef BitField<int32_t, 6, 6> AssignedRegisterField; | 441 typedef BitField<SpillType, 6, 2> SpillTypeField; |
440 typedef BitField<MachineType, 12, 15> MachineTypeField; | 442 typedef BitField<int32_t, 8, 6> AssignedRegisterField; |
441 | 443 |
442 int id_; | 444 int id_; |
443 int spill_start_index_; | 445 int spill_start_index_; |
444 uint32_t bits_; | 446 uint32_t bits_; |
445 UseInterval* last_interval_; | 447 UseInterval* last_interval_; |
446 UseInterval* first_interval_; | 448 UseInterval* first_interval_; |
447 UsePosition* first_pos_; | 449 UsePosition* first_pos_; |
448 LiveRange* parent_; | 450 LiveRange* parent_; |
449 LiveRange* next_; | 451 LiveRange* next_; |
450 union { | 452 union { |
451 // Correct value determined by spill_type() | 453 // Correct value determined by spill_type() |
452 InstructionOperand* spill_operand_; | 454 InstructionOperand* spill_operand_; |
453 SpillRange* spill_range_; | 455 SpillRange* spill_range_; |
454 }; | 456 }; |
455 SpillAtDefinitionList* spills_at_definition_; | 457 SpillAtDefinitionList* spills_at_definition_; |
456 // This is used as a cache, it doesn't affect correctness. | 458 // This is used as a cache, it doesn't affect correctness. |
457 mutable UseInterval* current_interval_; | 459 mutable UseInterval* current_interval_; |
458 // This is used as a cache, it doesn't affect correctness. | 460 // This is used as a cache, it doesn't affect correctness. |
459 mutable UsePosition* last_processed_use_; | 461 mutable UsePosition* last_processed_use_; |
460 // This is used as a cache, it's invalid outside of BuildLiveRanges. | 462 // This is used as a cache, it's invalid outside of BuildLiveRanges. |
461 mutable UsePosition* current_hint_position_; | 463 mutable UsePosition* current_hint_position_; |
462 | 464 |
463 DISALLOW_COPY_AND_ASSIGN(LiveRange); | 465 DISALLOW_COPY_AND_ASSIGN(LiveRange); |
464 }; | 466 }; |
465 | 467 |
466 | 468 |
467 class SpillRange final : public ZoneObject { | 469 class SpillRange final : public ZoneObject { |
468 public: | 470 public: |
469 static const int kUnassignedSlot = -1; | |
470 SpillRange(LiveRange* range, Zone* zone); | 471 SpillRange(LiveRange* range, Zone* zone); |
471 | 472 |
472 UseInterval* interval() const { return use_interval_; } | 473 UseInterval* interval() const { return use_interval_; } |
473 // Currently, only 4 or 8 byte slots are supported. | 474 RegisterKind kind() const { return live_ranges_[0]->kind(); } |
474 int ByteWidth() const; | |
475 bool IsEmpty() const { return live_ranges_.empty(); } | 475 bool IsEmpty() const { return live_ranges_.empty(); } |
476 bool TryMerge(SpillRange* other); | 476 bool TryMerge(SpillRange* other); |
477 | 477 void SetOperand(AllocatedOperand* op); |
478 void set_assigned_slot(int index) { | |
479 DCHECK_EQ(kUnassignedSlot, assigned_slot_); | |
480 assigned_slot_ = index; | |
481 } | |
482 int assigned_slot() { | |
483 DCHECK_NE(kUnassignedSlot, assigned_slot_); | |
484 return assigned_slot_; | |
485 } | |
486 | 478 |
487 private: | 479 private: |
488 LifetimePosition End() const { return end_position_; } | 480 LifetimePosition End() const { return end_position_; } |
489 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; } | 481 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; } |
490 bool IsIntersectingWith(SpillRange* other) const; | 482 bool IsIntersectingWith(SpillRange* other) const; |
491 // Merge intervals, making sure the use intervals are sorted | 483 // Merge intervals, making sure the use intervals are sorted |
492 void MergeDisjointIntervals(UseInterval* other); | 484 void MergeDisjointIntervals(UseInterval* other); |
493 | 485 |
494 ZoneVector<LiveRange*> live_ranges_; | 486 ZoneVector<LiveRange*> live_ranges_; |
495 UseInterval* use_interval_; | 487 UseInterval* use_interval_; |
496 LifetimePosition end_position_; | 488 LifetimePosition end_position_; |
497 int assigned_slot_; | |
498 | 489 |
499 DISALLOW_COPY_AND_ASSIGN(SpillRange); | 490 DISALLOW_COPY_AND_ASSIGN(SpillRange); |
500 }; | 491 }; |
501 | 492 |
502 | 493 |
503 class RegisterAllocationData final : public ZoneObject { | 494 class RegisterAllocationData final : public ZoneObject { |
504 public: | 495 public: |
505 class PhiMapValue : public ZoneObject { | 496 class PhiMapValue : public ZoneObject { |
506 public: | 497 public: |
507 PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone); | 498 PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 // This zone is for datastructures only needed during register allocation | 542 // This zone is for datastructures only needed during register allocation |
552 // phases. | 543 // phases. |
553 Zone* allocation_zone() const { return allocation_zone_; } | 544 Zone* allocation_zone() const { return allocation_zone_; } |
554 // This zone is for InstructionOperands and moves that live beyond register | 545 // This zone is for InstructionOperands and moves that live beyond register |
555 // allocation. | 546 // allocation. |
556 Zone* code_zone() const { return code()->zone(); } | 547 Zone* code_zone() const { return code()->zone(); } |
557 Frame* frame() const { return frame_; } | 548 Frame* frame() const { return frame_; } |
558 const char* debug_name() const { return debug_name_; } | 549 const char* debug_name() const { return debug_name_; } |
559 const RegisterConfiguration* config() const { return config_; } | 550 const RegisterConfiguration* config() const { return config_; } |
560 | 551 |
561 MachineType MachineTypeFor(int virtual_register); | |
562 | |
563 LiveRange* LiveRangeFor(int index); | 552 LiveRange* LiveRangeFor(int index); |
564 // Creates a new live range. | |
565 LiveRange* NewLiveRange(int index, MachineType machine_type); | |
566 LiveRange* NewChildRangeFor(LiveRange* range); | |
567 | 553 |
568 SpillRange* AssignSpillRangeToLiveRange(LiveRange* range); | 554 SpillRange* AssignSpillRangeToLiveRange(LiveRange* range); |
569 | 555 |
570 MoveOperands* AddGapMove(int index, Instruction::GapPosition position, | 556 MoveOperands* AddGapMove(int index, Instruction::GapPosition position, |
571 const InstructionOperand& from, | 557 const InstructionOperand& from, |
572 const InstructionOperand& to); | 558 const InstructionOperand& to); |
573 | 559 |
574 bool IsReference(int virtual_register) const { | 560 bool IsReference(int virtual_register) const { |
575 return code()->IsReference(virtual_register); | 561 return code()->IsReference(virtual_register); |
576 } | 562 } |
577 | 563 |
578 bool ExistsUseWithoutDefinition(); | 564 bool ExistsUseWithoutDefinition(); |
579 | 565 |
| 566 // Creates a new live range. |
| 567 LiveRange* NewLiveRange(int index); |
| 568 |
580 void MarkAllocated(RegisterKind kind, int index); | 569 void MarkAllocated(RegisterKind kind, int index); |
581 | 570 |
582 PhiMapValue* InitializePhiMap(const InstructionBlock* block, | 571 PhiMapValue* InitializePhiMap(const InstructionBlock* block, |
583 PhiInstruction* phi); | 572 PhiInstruction* phi); |
584 PhiMapValue* GetPhiMapValueFor(int virtual_register); | 573 PhiMapValue* GetPhiMapValueFor(int virtual_register); |
585 | 574 |
586 private: | 575 private: |
587 Zone* const allocation_zone_; | 576 Zone* const allocation_zone_; |
588 Frame* const frame_; | 577 Frame* const frame_; |
589 InstructionSequence* const code_; | 578 InstructionSequence* const code_; |
590 const char* const debug_name_; | 579 const char* const debug_name_; |
591 const RegisterConfiguration* const config_; | 580 const RegisterConfiguration* const config_; |
592 PhiMap phi_map_; | 581 PhiMap phi_map_; |
593 ZoneVector<BitVector*> live_in_sets_; | 582 ZoneVector<BitVector*> live_in_sets_; |
594 ZoneVector<LiveRange*> live_ranges_; | 583 ZoneVector<LiveRange*> live_ranges_; |
595 ZoneVector<LiveRange*> fixed_live_ranges_; | 584 ZoneVector<LiveRange*> fixed_live_ranges_; |
596 ZoneVector<LiveRange*> fixed_double_live_ranges_; | 585 ZoneVector<LiveRange*> fixed_double_live_ranges_; |
597 ZoneVector<SpillRange*> spill_ranges_; | 586 ZoneVector<SpillRange*> spill_ranges_; |
598 BitVector* assigned_registers_; | 587 BitVector* assigned_registers_; |
599 BitVector* assigned_double_registers_; | 588 BitVector* assigned_double_registers_; |
600 int virtual_register_count_; | |
601 | 589 |
602 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationData); | 590 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationData); |
603 }; | 591 }; |
604 | 592 |
605 | 593 |
606 class ConstraintBuilder final : public ZoneObject { | 594 class ConstraintBuilder final : public ZoneObject { |
607 public: | 595 public: |
608 explicit ConstraintBuilder(RegisterAllocationData* data); | 596 explicit ConstraintBuilder(RegisterAllocationData* data); |
609 | 597 |
610 // Phase 1 : insert moves to account for fixed register operands. | 598 // Phase 1 : insert moves to account for fixed register operands. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 void ProcessLoopHeader(const InstructionBlock* block, BitVector* live); | 657 void ProcessLoopHeader(const InstructionBlock* block, BitVector* live); |
670 | 658 |
671 static int FixedLiveRangeID(int index) { return -index - 1; } | 659 static int FixedLiveRangeID(int index) { return -index - 1; } |
672 int FixedDoubleLiveRangeID(int index); | 660 int FixedDoubleLiveRangeID(int index); |
673 LiveRange* FixedLiveRangeFor(int index); | 661 LiveRange* FixedLiveRangeFor(int index); |
674 LiveRange* FixedDoubleLiveRangeFor(int index); | 662 LiveRange* FixedDoubleLiveRangeFor(int index); |
675 | 663 |
676 void MapPhiHint(InstructionOperand* operand, UsePosition* use_pos); | 664 void MapPhiHint(InstructionOperand* operand, UsePosition* use_pos); |
677 void ResolvePhiHint(InstructionOperand* operand, UsePosition* use_pos); | 665 void ResolvePhiHint(InstructionOperand* operand, UsePosition* use_pos); |
678 | 666 |
| 667 // Returns the register kind required by the given virtual register. |
| 668 RegisterKind RequiredRegisterKind(int virtual_register) const; |
| 669 |
679 UsePosition* NewUsePosition(LifetimePosition pos, InstructionOperand* operand, | 670 UsePosition* NewUsePosition(LifetimePosition pos, InstructionOperand* operand, |
680 void* hint, UsePositionHintType hint_type); | 671 void* hint, UsePositionHintType hint_type); |
681 UsePosition* NewUsePosition(LifetimePosition pos) { | 672 UsePosition* NewUsePosition(LifetimePosition pos) { |
682 return NewUsePosition(pos, nullptr, nullptr, UsePositionHintType::kNone); | 673 return NewUsePosition(pos, nullptr, nullptr, UsePositionHintType::kNone); |
683 } | 674 } |
684 LiveRange* LiveRangeFor(InstructionOperand* operand); | 675 LiveRange* LiveRangeFor(InstructionOperand* operand); |
685 // Helper methods for building intervals. | 676 // Helper methods for building intervals. |
686 UsePosition* Define(LifetimePosition position, InstructionOperand* operand, | 677 UsePosition* Define(LifetimePosition position, InstructionOperand* operand, |
687 void* hint, UsePositionHintType hint_type); | 678 void* hint, UsePositionHintType hint_type); |
688 void Define(LifetimePosition position, InstructionOperand* operand) { | 679 void Define(LifetimePosition position, InstructionOperand* operand) { |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
916 RegisterAllocationData* const data_; | 907 RegisterAllocationData* const data_; |
917 | 908 |
918 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); | 909 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); |
919 }; | 910 }; |
920 | 911 |
921 } // namespace compiler | 912 } // namespace compiler |
922 } // namespace internal | 913 } // namespace internal |
923 } // namespace v8 | 914 } // namespace v8 |
924 | 915 |
925 #endif // V8_REGISTER_ALLOCATOR_H_ | 916 #endif // V8_REGISTER_ALLOCATOR_H_ |
OLD | NEW |