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

Side by Side Diff: src/compiler/register-allocator.h

Issue 1087983007: [turbofan] Cleanup register allocator a little after split. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 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
« no previous file with comments | « src/compiler/pipeline.cc ('k') | src/compiler/register-allocator.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 131
132 // Representation of the non-empty interval [start,end[. 132 // Representation of the non-empty interval [start,end[.
133 class UseInterval final : public ZoneObject { 133 class UseInterval final : public ZoneObject {
134 public: 134 public:
135 UseInterval(LifetimePosition start, LifetimePosition end) 135 UseInterval(LifetimePosition start, LifetimePosition end)
136 : start_(start), end_(end), next_(nullptr) { 136 : start_(start), end_(end), next_(nullptr) {
137 DCHECK(start.Value() < end.Value()); 137 DCHECK(start.Value() < end.Value());
138 } 138 }
139 139
140 LifetimePosition start() const { return start_; } 140 LifetimePosition start() const { return start_; }
141 void set_start(LifetimePosition start) { start_ = start; }
141 LifetimePosition end() const { return end_; } 142 LifetimePosition end() const { return end_; }
143 void set_end(LifetimePosition end) { end_ = end; }
142 UseInterval* next() const { return next_; } 144 UseInterval* next() const { return next_; }
145 void set_next(UseInterval* next) { next_ = next; }
143 146
144 // Split this interval at the given position without effecting the 147 // Split this interval at the given position without effecting the
145 // live range that owns it. The interval must contain the position. 148 // live range that owns it. The interval must contain the position.
146 void SplitAt(LifetimePosition pos, Zone* zone); 149 void SplitAt(LifetimePosition pos, Zone* zone);
147 150
148 // If this interval intersects with other return smallest position 151 // If this interval intersects with other return smallest position
149 // that belongs to both of them. 152 // that belongs to both of them.
150 LifetimePosition Intersect(const UseInterval* other) const { 153 LifetimePosition Intersect(const UseInterval* other) const {
151 if (other->start().Value() < start_.Value()) return other->Intersect(this); 154 if (other->start().Value() < start_.Value()) return other->Intersect(this);
152 if (other->start().Value() < end_.Value()) return other->start(); 155 if (other->start().Value() < end_.Value()) return other->start();
153 return LifetimePosition::Invalid(); 156 return LifetimePosition::Invalid();
154 } 157 }
155 158
156 bool Contains(LifetimePosition point) const { 159 bool Contains(LifetimePosition point) const {
157 return start_.Value() <= point.Value() && point.Value() < end_.Value(); 160 return start_.Value() <= point.Value() && point.Value() < end_.Value();
158 } 161 }
159 162
160 void set_start(LifetimePosition start) { start_ = start; } 163 private:
161 void set_next(UseInterval* next) { next_ = next; }
162
163 LifetimePosition start_; 164 LifetimePosition start_;
164 LifetimePosition end_; 165 LifetimePosition end_;
165 UseInterval* next_; 166 UseInterval* next_;
166 167
167 private:
168 DISALLOW_COPY_AND_ASSIGN(UseInterval); 168 DISALLOW_COPY_AND_ASSIGN(UseInterval);
169 }; 169 };
170 170
171 171
172 enum class UsePositionType : uint8_t { kAny, kRequiresRegister, kRequiresSlot }; 172 enum class UsePositionType : uint8_t { kAny, kRequiresRegister, kRequiresSlot };
173 173
174 174
175 // Representation of a use position. 175 // Representation of a use position.
176 class UsePosition final : public ZoneObject { 176 class UsePosition final : public ZoneObject {
177 public: 177 public:
178 UsePosition(LifetimePosition pos, InstructionOperand* operand, 178 UsePosition(LifetimePosition pos, InstructionOperand* operand,
179 InstructionOperand* hint); 179 InstructionOperand* hint);
180 180
181 InstructionOperand* operand() const { return operand_; } 181 InstructionOperand* operand() const { return operand_; }
182 bool HasOperand() const { return operand_ != nullptr; } 182 bool HasOperand() const { return operand_ != nullptr; }
183 183
184 InstructionOperand* hint() const { return hint_; } 184 InstructionOperand* hint() const { return hint_; }
185 bool HasHint() const; 185 bool HasHint() const;
186 bool RegisterIsBeneficial() const { 186 bool RegisterIsBeneficial() const {
187 return RegisterBeneficialField::decode(flags_); 187 return RegisterBeneficialField::decode(flags_);
188 } 188 }
189 UsePositionType type() const { return TypeField::decode(flags_); } 189 UsePositionType type() const { return TypeField::decode(flags_); }
190 190
191 LifetimePosition pos() const { return pos_; } 191 LifetimePosition pos() const { return pos_; }
192 UsePosition* next() const { return next_; } 192 UsePosition* next() const { return next_; }
193 193
194 void set_next(UsePosition* next) { next_ = next; } 194 void set_next(UsePosition* next) { next_ = next; }
195 void set_type(UsePositionType type, bool register_beneficial); 195 void set_type(UsePositionType type, bool register_beneficial);
196 196
197 private:
198 typedef BitField8<UsePositionType, 0, 2> TypeField;
199 typedef BitField8<bool, 2, 1> RegisterBeneficialField;
200
197 InstructionOperand* const operand_; 201 InstructionOperand* const operand_;
198 InstructionOperand* const hint_; 202 InstructionOperand* const hint_;
199 LifetimePosition const pos_; 203 LifetimePosition const pos_;
200 UsePosition* next_; 204 UsePosition* next_;
201
202 private:
203 typedef BitField8<UsePositionType, 0, 2> TypeField;
204 typedef BitField8<bool, 2, 1> RegisterBeneficialField;
205 uint8_t flags_; 205 uint8_t flags_;
206 206
207 DISALLOW_COPY_AND_ASSIGN(UsePosition); 207 DISALLOW_COPY_AND_ASSIGN(UsePosition);
208 }; 208 };
209 209
210 class SpillRange; 210 class SpillRange;
211 211
212 212
213 // Representation of SSA values' live ranges as a collection of (continuous) 213 // Representation of SSA values' live ranges as a collection of (continuous)
214 // intervals over the instruction ordering. 214 // intervals over the instruction ordering.
215 class LiveRange final : public ZoneObject { 215 class LiveRange final : public ZoneObject {
216 public: 216 public:
217 static const int kInvalidAssignment = 0x7fffffff; 217 static const int kInvalidAssignment = 0x7fffffff;
218 218
219 LiveRange(int id, Zone* zone); 219 explicit LiveRange(int id);
220 220
221 UseInterval* first_interval() const { return first_interval_; } 221 UseInterval* first_interval() const { return first_interval_; }
222 UsePosition* first_pos() const { return first_pos_; } 222 UsePosition* first_pos() const { return first_pos_; }
223 LiveRange* parent() const { return parent_; } 223 LiveRange* parent() const { return parent_; }
224 LiveRange* TopLevel() { return (parent_ == nullptr) ? this : parent_; } 224 LiveRange* TopLevel() { return (parent_ == nullptr) ? this : parent_; }
225 const LiveRange* TopLevel() const { 225 const LiveRange* TopLevel() const {
226 return (parent_ == nullptr) ? this : parent_; 226 return (parent_ == nullptr) ? this : parent_;
227 } 227 }
228 LiveRange* next() const { return next_; } 228 LiveRange* next() const { return next_; }
229 bool IsChild() const { return parent() != nullptr; } 229 bool IsChild() const { return parent() != nullptr; }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 } 295 }
296 296
297 LifetimePosition End() const { 297 LifetimePosition End() const {
298 DCHECK(!IsEmpty()); 298 DCHECK(!IsEmpty());
299 return last_interval_->end(); 299 return last_interval_->end();
300 } 300 }
301 301
302 enum class SpillType { kNoSpillType, kSpillOperand, kSpillRange }; 302 enum class SpillType { kNoSpillType, kSpillOperand, kSpillRange };
303 SpillType spill_type() const { return spill_type_; } 303 SpillType spill_type() const { return spill_type_; }
304 InstructionOperand* GetSpillOperand() const { 304 InstructionOperand* GetSpillOperand() const {
305 return spill_type_ == SpillType::kSpillOperand ? spill_operand_ : nullptr; 305 DCHECK(spill_type_ == SpillType::kSpillOperand);
306 return spill_operand_;
306 } 307 }
307 SpillRange* GetSpillRange() const { 308 SpillRange* GetSpillRange() const {
308 return spill_type_ == SpillType::kSpillRange ? spill_range_ : nullptr; 309 DCHECK(spill_type_ == SpillType::kSpillRange);
310 return spill_range_;
309 } 311 }
310 bool HasNoSpillType() const { return spill_type_ == SpillType::kNoSpillType; } 312 bool HasNoSpillType() const { return spill_type_ == SpillType::kNoSpillType; }
311 bool HasSpillOperand() const { 313 bool HasSpillOperand() const {
312 return spill_type_ == SpillType::kSpillOperand; 314 return spill_type_ == SpillType::kSpillOperand;
313 } 315 }
314 bool HasSpillRange() const { return spill_type_ == SpillType::kSpillRange; } 316 bool HasSpillRange() const { return spill_type_ == SpillType::kSpillRange; }
315 317
316 void SpillAtDefinition(Zone* zone, int gap_index, 318 void SpillAtDefinition(Zone* zone, int gap_index,
317 InstructionOperand* operand); 319 InstructionOperand* operand);
318 void SetSpillOperand(InstructionOperand* operand); 320 void SetSpillOperand(InstructionOperand* operand);
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 // allocation. 456 // allocation.
455 Zone* code_zone() const { return code()->zone(); } 457 Zone* code_zone() const { return code()->zone(); }
456 const PhiMap& phi_map() const { return phi_map_; } 458 const PhiMap& phi_map() const { return phi_map_; }
457 PhiMap& phi_map() { return phi_map_; } 459 PhiMap& phi_map() { return phi_map_; }
458 Frame* frame() const { return frame_; } 460 Frame* frame() const { return frame_; }
459 const char* debug_name() const { return debug_name_; } 461 const char* debug_name() const { return debug_name_; }
460 const RegisterConfiguration* config() const { return config_; } 462 const RegisterConfiguration* config() const { return config_; }
461 463
462 void SetLiveRangeAssignedRegister(LiveRange* range, int reg); 464 void SetLiveRangeAssignedRegister(LiveRange* range, int reg);
463 LiveRange* LiveRangeFor(int index); 465 LiveRange* LiveRangeFor(int index);
464 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); } 466 Instruction* InstructionAt(int index) const {
467 return code()->InstructionAt(index);
468 }
465 469
466 void AssignPhiInput(LiveRange* range, const InstructionOperand& assignment); 470 void AssignPhiInput(LiveRange* range, const InstructionOperand& assignment);
467 SpillRange* AssignSpillRangeToLiveRange(LiveRange* range); 471 SpillRange* AssignSpillRangeToLiveRange(LiveRange* range);
468 472
469 MoveOperands* AddGapMove(int index, Instruction::GapPosition position, 473 MoveOperands* AddGapMove(int index, Instruction::GapPosition position,
470 const InstructionOperand& from, 474 const InstructionOperand& from,
471 const InstructionOperand& to); 475 const InstructionOperand& to);
472 476
473 bool IsBlockBoundary(LifetimePosition pos) {
474 return pos.IsFullStart() &&
475 code()
476 ->GetInstructionBlock(pos.ToInstructionIndex())
477 ->code_start() == pos.ToInstructionIndex();
478 }
479
480 const InstructionBlock* GetInstructionBlock(LifetimePosition pos) const {
481 return code()->GetInstructionBlock(pos.ToInstructionIndex());
482 }
483
484 bool IsReference(int virtual_register) const { 477 bool IsReference(int virtual_register) const {
485 return code()->IsReference(virtual_register); 478 return code()->IsReference(virtual_register);
486 } 479 }
487 480
488 bool ExistsUseWithoutDefinition(); 481 bool ExistsUseWithoutDefinition();
489 482
490 // Creates a new live range. 483 // Creates a new live range.
491 LiveRange* NewLiveRange(int index); 484 LiveRange* NewLiveRange(int index);
492 485
493 private: 486 private:
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 InstructionOperand* operand, InstructionOperand* hint); 575 InstructionOperand* operand, InstructionOperand* hint);
583 576
584 RegisterAllocationData* const data_; 577 RegisterAllocationData* const data_;
585 578
586 DISALLOW_COPY_AND_ASSIGN(LiveRangeBuilder); 579 DISALLOW_COPY_AND_ASSIGN(LiveRangeBuilder);
587 }; 580 };
588 581
589 582
590 class LinearScanAllocator final : public ZoneObject { 583 class LinearScanAllocator final : public ZoneObject {
591 public: 584 public:
592 explicit LinearScanAllocator(RegisterAllocationData* data, RegisterKind kind); 585 LinearScanAllocator(RegisterAllocationData* data, RegisterKind kind,
586 Zone* local_zone);
593 587
594 // Phase 4: compute register assignments. 588 // Phase 4: compute register assignments.
595 void AllocateRegisters(); 589 void AllocateRegisters();
596 590
597 private: 591 private:
598 RegisterAllocationData* data() const { return data_; } 592 RegisterAllocationData* data() const { return data_; }
599 InstructionSequence* code() const { return data()->code(); } 593 InstructionSequence* code() const { return data()->code(); }
600 Zone* allocation_zone() const { return data()->allocation_zone(); } 594 Zone* allocation_zone() const { return data()->allocation_zone(); }
601 Zone* code_zone() const { return code()->zone(); } 595 Zone* code_zone() const { return code()->zone(); }
602 const RegisterConfiguration* config() const { return data()->config(); } 596 const RegisterConfiguration* config() const { return data()->config(); }
597 int num_registers() const { return num_registers_; }
598 const char* RegisterName(int allocation_index) const;
599
600 ZoneVector<LiveRange*>& live_ranges() { return data()->live_ranges(); }
601 ZoneVector<LiveRange*>& unhandled_live_ranges() {
602 return unhandled_live_ranges_;
603 }
604 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; }
605 ZoneVector<LiveRange*>& inactive_live_ranges() {
606 return inactive_live_ranges_;
607 }
608 ZoneVector<SpillRange*>& spill_ranges() { return data()->spill_ranges(); }
609 RegisterAllocationData::PhiMap& phi_map() { return data()->phi_map(); }
603 610
604 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); } 611 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); }
605
606 int GetVirtualRegister() { return code()->NextVirtualRegister(); }
607
608 bool IsReference(int virtual_register) const { 612 bool IsReference(int virtual_register) const {
609 return data()->IsReference(virtual_register); 613 return data()->IsReference(virtual_register);
610 } 614 }
611
612 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); } 615 LiveRange* LiveRangeFor(int index) { return data()->LiveRangeFor(index); }
613 616
614 // Helper methods for updating the life range lists. 617 // Helper methods for updating the life range lists.
615 void AddToActive(LiveRange* range); 618 void AddToActive(LiveRange* range);
616 void AddToInactive(LiveRange* range); 619 void AddToInactive(LiveRange* range);
617 void AddToUnhandledSorted(LiveRange* range); 620 void AddToUnhandledSorted(LiveRange* range);
618 void AddToUnhandledUnsorted(LiveRange* range); 621 void AddToUnhandledUnsorted(LiveRange* range);
619 void SortUnhandled(); 622 void SortUnhandled();
620 bool UnhandledIsSorted(); 623 bool UnhandledIsSorted();
621 void ActiveToHandled(LiveRange* range); 624 void ActiveToHandled(LiveRange* range);
(...skipping 19 matching lines...) Expand all
641 // Split the given range in a position from the interval [start, end]. 644 // Split the given range in a position from the interval [start, end].
642 LiveRange* SplitBetween(LiveRange* range, LifetimePosition start, 645 LiveRange* SplitBetween(LiveRange* range, LifetimePosition start,
643 LifetimePosition end); 646 LifetimePosition end);
644 647
645 // Find a lifetime position in the interval [start, end] which 648 // Find a lifetime position in the interval [start, end] which
646 // is optimal for splitting: it is either header of the outermost 649 // is optimal for splitting: it is either header of the outermost
647 // loop covered by this interval or the latest possible position. 650 // loop covered by this interval or the latest possible position.
648 LifetimePosition FindOptimalSplitPos(LifetimePosition start, 651 LifetimePosition FindOptimalSplitPos(LifetimePosition start,
649 LifetimePosition end); 652 LifetimePosition end);
650 653
654 void Spill(LiveRange* range);
655
651 // Spill the given life range after position pos. 656 // Spill the given life range after position pos.
652 void SpillAfter(LiveRange* range, LifetimePosition pos); 657 void SpillAfter(LiveRange* range, LifetimePosition pos);
653 658
654 // Spill the given life range after position [start] and up to position [end]. 659 // Spill the given life range after position [start] and up to position [end].
655 void SpillBetween(LiveRange* range, LifetimePosition start, 660 void SpillBetween(LiveRange* range, LifetimePosition start,
656 LifetimePosition end); 661 LifetimePosition end);
657 662
658 // Spill the given life range after position [start] and up to position [end]. 663 // Spill the given life range after position [start] and up to position [end].
659 // Range is guaranteed to be spilled at least until position [until]. 664 // Range is guaranteed to be spilled at least until position [until].
660 void SpillBetweenUntil(LiveRange* range, LifetimePosition start, 665 void SpillBetweenUntil(LiveRange* range, LifetimePosition start,
661 LifetimePosition until, LifetimePosition end); 666 LifetimePosition until, LifetimePosition end);
662 667
663 void SplitAndSpillIntersecting(LiveRange* range); 668 void SplitAndSpillIntersecting(LiveRange* range);
664 669
665 // If we are trying to spill a range inside the loop try to 670 // If we are trying to spill a range inside the loop try to
666 // hoist spill position out to the point just before the loop. 671 // hoist spill position out to the point just before the loop.
667 LifetimePosition FindOptimalSpillingPos(LiveRange* range, 672 LifetimePosition FindOptimalSpillingPos(LiveRange* range,
668 LifetimePosition pos); 673 LifetimePosition pos);
669 674
670 void Spill(LiveRange* range);
671
672 // Return the block which contains give lifetime position.
673 const InstructionBlock* GetInstructionBlock(LifetimePosition pos) const {
674 return data()->GetInstructionBlock(pos);
675 }
676
677 void SetLiveRangeAssignedRegister(LiveRange* range, int reg) {
678 data()->SetLiveRangeAssignedRegister(range, reg);
679 }
680
681 // Helper methods for the fixed registers.
682 int RegisterCount() const { return num_registers_; }
683 const char* RegisterName(int allocation_index);
684
685 ZoneVector<LiveRange*>& live_ranges() { return data()->live_ranges(); }
686 ZoneVector<LiveRange*>& fixed_live_ranges() {
687 return data()->fixed_live_ranges();
688 }
689 ZoneVector<LiveRange*>& fixed_double_live_ranges() {
690 return data()->fixed_double_live_ranges();
691 }
692 ZoneVector<LiveRange*>& unhandled_live_ranges() {
693 return unhandled_live_ranges_;
694 }
695 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; }
696 ZoneVector<LiveRange*>& inactive_live_ranges() {
697 return inactive_live_ranges_;
698 }
699 ZoneVector<SpillRange*>& spill_ranges() { return data()->spill_ranges(); }
700 RegisterAllocationData::PhiMap& phi_map() { return data()->phi_map(); }
701
702 RegisterAllocationData* const data_; 675 RegisterAllocationData* const data_;
703 const RegisterKind mode_; 676 const RegisterKind mode_;
704 const int num_registers_; 677 const int num_registers_;
705 678
706 ZoneVector<LiveRange*> unhandled_live_ranges_; 679 ZoneVector<LiveRange*> unhandled_live_ranges_;
707 ZoneVector<LiveRange*> active_live_ranges_; 680 ZoneVector<LiveRange*> active_live_ranges_;
708 ZoneVector<LiveRange*> inactive_live_ranges_; 681 ZoneVector<LiveRange*> inactive_live_ranges_;
709 682
710 #ifdef DEBUG 683 #ifdef DEBUG
711 LifetimePosition allocation_finger_; 684 LifetimePosition allocation_finger_;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 727
755 DISALLOW_COPY_AND_ASSIGN(ReferenceMapPopulator); 728 DISALLOW_COPY_AND_ASSIGN(ReferenceMapPopulator);
756 }; 729 };
757 730
758 731
759 class LiveRangeConnector final : public ZoneObject { 732 class LiveRangeConnector final : public ZoneObject {
760 public: 733 public:
761 explicit LiveRangeConnector(RegisterAllocationData* data); 734 explicit LiveRangeConnector(RegisterAllocationData* data);
762 735
763 // Phase 8: reconnect split ranges with moves. 736 // Phase 8: reconnect split ranges with moves.
764 void ConnectRanges(Zone* temp_zone); 737 void ConnectRanges(Zone* local_zone);
765 738
766 // Phase 9: insert moves to connect ranges across basic blocks. 739 // Phase 9: insert moves to connect ranges across basic blocks.
767 void ResolveControlFlow(); 740 void ResolveControlFlow(Zone* local_zone);
768 741
769 private: 742 private:
770 const InstructionBlock* GetInstructionBlock(LifetimePosition pos) const {
771 return data()->GetInstructionBlock(pos);
772 }
773 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; 743 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const;
774 void ResolveControlFlow(const InstructionBlock* block, 744 void ResolveControlFlow(const InstructionBlock* block,
775 const InstructionOperand& cur_op, 745 const InstructionOperand& cur_op,
776 const InstructionBlock* pred, 746 const InstructionBlock* pred,
777 const InstructionOperand& pred_op); 747 const InstructionOperand& pred_op);
778 InstructionSequence* code() const { return data()->code(); } 748 InstructionSequence* code() const { return data()->code(); }
779 Zone* code_zone() const { return code()->zone(); } 749 Zone* code_zone() const { return code()->zone(); }
780 RegisterAllocationData* data() const { return data_; } 750 RegisterAllocationData* data() const { return data_; }
781 751
782 RegisterAllocationData* const data_; 752 RegisterAllocationData* const data_;
783 753
784 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector); 754 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector);
785 }; 755 };
786 756
787 } // namespace compiler 757 } // namespace compiler
788 } // namespace internal 758 } // namespace internal
789 } // namespace v8 759 } // namespace v8
790 760
791 #endif // V8_REGISTER_ALLOCATOR_H_ 761 #endif // V8_REGISTER_ALLOCATOR_H_
OLDNEW
« no previous file with comments | « src/compiler/pipeline.cc ('k') | src/compiler/register-allocator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698