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

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

Issue 1094063002: [turbofan] split register allocator into little pieces (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 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 333
334 // Add a new interval or a new use position to this live range. 334 // Add a new interval or a new use position to this live range.
335 void EnsureInterval(LifetimePosition start, LifetimePosition end, Zone* zone); 335 void EnsureInterval(LifetimePosition start, LifetimePosition end, Zone* zone);
336 void AddUseInterval(LifetimePosition start, LifetimePosition end, Zone* zone); 336 void AddUseInterval(LifetimePosition start, LifetimePosition end, Zone* zone);
337 void AddUsePosition(LifetimePosition pos, InstructionOperand* operand, 337 void AddUsePosition(LifetimePosition pos, InstructionOperand* operand,
338 InstructionOperand* hint, Zone* zone); 338 InstructionOperand* hint, Zone* zone);
339 339
340 // Shorten the most recently added interval by setting a new start. 340 // Shorten the most recently added interval by setting a new start.
341 void ShortenTo(LifetimePosition start); 341 void ShortenTo(LifetimePosition start);
342 342
343 #ifdef DEBUG
344 // True if target overlaps an existing interval. 343 // True if target overlaps an existing interval.
345 bool HasOverlap(UseInterval* target) const; 344 bool HasOverlap(UseInterval* target) const;
346 void Verify() const; 345 void Verify() const;
347 #endif 346
347 void ConvertUsesToOperand(const InstructionOperand& op,
348 InstructionOperand* spill_op);
349
350 void set_kind(RegisterKind kind) { kind_ = kind; }
348 351
349 private: 352 private:
350 struct SpillAtDefinitionList; 353 struct SpillAtDefinitionList;
351 354
352 void ConvertUsesToOperand(const InstructionOperand& op,
353 InstructionOperand* spill_op);
354 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const; 355 UseInterval* FirstSearchIntervalForPosition(LifetimePosition position) const;
355 void AdvanceLastProcessedMarker(UseInterval* to_start_of, 356 void AdvanceLastProcessedMarker(UseInterval* to_start_of,
356 LifetimePosition but_not_past) const; 357 LifetimePosition but_not_past) const;
357 358
358 // TODO(dcarney): pack this structure better. 359 // TODO(dcarney): pack this structure better.
359 int id_; 360 int id_;
360 bool spilled_ : 1; 361 bool spilled_ : 1;
361 bool has_slot_use_ : 1; // Relevant only for parent. 362 bool has_slot_use_ : 1; // Relevant only for parent.
362 bool is_phi_ : 1; 363 bool is_phi_ : 1;
363 bool is_non_loop_phi_ : 1; 364 bool is_non_loop_phi_ : 1;
(...skipping 10 matching lines...) Expand all
374 // This is used as a cache, it's invalid outside of BuildLiveRanges. 375 // This is used as a cache, it's invalid outside of BuildLiveRanges.
375 InstructionOperand* current_hint_operand_; 376 InstructionOperand* current_hint_operand_;
376 int spill_start_index_; 377 int spill_start_index_;
377 SpillType spill_type_; 378 SpillType spill_type_;
378 union { 379 union {
379 InstructionOperand* spill_operand_; 380 InstructionOperand* spill_operand_;
380 SpillRange* spill_range_; 381 SpillRange* spill_range_;
381 }; 382 };
382 SpillAtDefinitionList* spills_at_definition_; 383 SpillAtDefinitionList* spills_at_definition_;
383 384
384 friend class RegisterAllocator; // Assigns to kind_.
385
386 DISALLOW_COPY_AND_ASSIGN(LiveRange); 385 DISALLOW_COPY_AND_ASSIGN(LiveRange);
387 }; 386 };
388 387
389 388
390 class SpillRange FINAL : public ZoneObject { 389 class SpillRange FINAL : public ZoneObject {
391 public: 390 public:
392 SpillRange(LiveRange* range, Zone* zone); 391 SpillRange(LiveRange* range, Zone* zone);
393 392
394 UseInterval* interval() const { return use_interval_; } 393 UseInterval* interval() const { return use_interval_; }
395 RegisterKind Kind() const { return live_ranges_[0]->Kind(); } 394 RegisterKind Kind() const { return live_ranges_[0]->Kind(); }
396 bool IsEmpty() const { return live_ranges_.empty(); } 395 bool IsEmpty() const { return live_ranges_.empty(); }
397 bool TryMerge(SpillRange* other); 396 bool TryMerge(SpillRange* other);
398 void SetOperand(AllocatedOperand* op); 397 void SetOperand(AllocatedOperand* op);
399 398
400 private: 399 private:
401 LifetimePosition End() const { return end_position_; } 400 LifetimePosition End() const { return end_position_; }
402 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; } 401 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; }
403 bool IsIntersectingWith(SpillRange* other) const; 402 bool IsIntersectingWith(SpillRange* other) const;
404 // Merge intervals, making sure the use intervals are sorted 403 // Merge intervals, making sure the use intervals are sorted
405 void MergeDisjointIntervals(UseInterval* other); 404 void MergeDisjointIntervals(UseInterval* other);
406 405
407 ZoneVector<LiveRange*> live_ranges_; 406 ZoneVector<LiveRange*> live_ranges_;
408 UseInterval* use_interval_; 407 UseInterval* use_interval_;
409 LifetimePosition end_position_; 408 LifetimePosition end_position_;
410 409
411 DISALLOW_COPY_AND_ASSIGN(SpillRange); 410 DISALLOW_COPY_AND_ASSIGN(SpillRange);
412 }; 411 };
413 412
414 413
415 class RegisterAllocator FINAL : public ZoneObject { 414 class LiveRangeBuilder FINAL : public ZoneObject {
416 public: 415 public:
417 explicit RegisterAllocator(const RegisterConfiguration* config, 416 class PhiMapValue : public ZoneObject {
418 Zone* local_zone, Frame* frame, 417 public:
419 InstructionSequence* code, 418 PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone)
420 const char* debug_name = nullptr); 419 : phi(phi), block(block), incoming_moves(zone) {
420 incoming_moves.reserve(phi->operands().size());
421 }
422 PhiInstruction* const phi;
423 const InstructionBlock* const block;
424 ZoneVector<MoveOperands*> incoming_moves;
425 };
426 typedef ZoneMap<int, PhiMapValue*> PhiMap;
421 427
422 const ZoneVector<LiveRange*>& live_ranges() const { return live_ranges_; } 428 LiveRangeBuilder(const RegisterConfiguration* config, Zone* local_zone,
423 const ZoneVector<LiveRange*>& fixed_live_ranges() const { 429 Frame* frame, InstructionSequence* code,
424 return fixed_live_ranges_; 430 const char* debug_name = nullptr);
425 }
426 const ZoneVector<LiveRange*>& fixed_double_live_ranges() const {
427 return fixed_double_live_ranges_;
428 }
429 InstructionSequence* code() const { return code_; }
430 // This zone is for datastructures only needed during register allocation.
431 Zone* local_zone() const { return local_zone_; }
432 431
433 // Phase 1 : insert moves to account for fixed register operands. 432 // Phase 1 : insert moves to account for fixed register operands.
434 void MeetRegisterConstraints(); 433 void MeetRegisterConstraints();
435 434
436 // Phase 2: deconstruct SSA by inserting moves in successors and the headers 435 // Phase 2: deconstruct SSA by inserting moves in successors and the headers
437 // of blocks containing phis. 436 // of blocks containing phis.
438 void ResolvePhis(); 437 void ResolvePhis();
439 438
440 // Phase 3: compute liveness of all virtual register. 439 // Phase 3: compute liveness of all virtual register.
441 void BuildLiveRanges(); 440 void BuildLiveRanges();
442 bool ExistsUseWithoutDefinition(); 441 bool ExistsUseWithoutDefinition();
443 442
444 // Phase 4: compute register assignments. 443 const ZoneVector<LiveRange*>& live_ranges() const { return live_ranges_; }
445 void AllocateGeneralRegisters(); 444 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; }
446 void AllocateDoubleRegisters(); 445 const ZoneVector<LiveRange*>& fixed_live_ranges() const {
447 446 return fixed_live_ranges_;
448 // Phase 5: assign spill splots. 447 }
449 void AssignSpillSlots(); 448 ZoneVector<LiveRange*>& fixed_live_ranges() { return fixed_live_ranges_; }
450 449 ZoneVector<LiveRange*>& fixed_double_live_ranges() {
451 // Phase 6: commit assignment. 450 return fixed_double_live_ranges_;
452 void CommitAssignment(); 451 }
453 452 const ZoneVector<LiveRange*>& fixed_double_live_ranges() const {
454 // Phase 7: compute values for pointer maps. 453 return fixed_double_live_ranges_;
455 void PopulateReferenceMaps(); 454 }
456 455 const ZoneVector<BitVector*>& live_in_sets() const { return live_in_sets_; }
457 // Phase 8: reconnect split ranges with moves. 456 ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; }
458 void ConnectRanges(); 457 const ZoneVector<SpillRange*>& spill_ranges() const { return spill_ranges_; }
459 458 InstructionSequence* code() const { return code_; }
460 // Phase 9: insert moves to connect ranges across basic blocks. 459 // This zone is for datastructures only needed during register allocation
461 void ResolveControlFlow(); 460 // phases.
462 461 Zone* local_zone() const { return local_zone_; }
463 private:
464 int GetVirtualRegister() { return code()->NextVirtualRegister(); }
465
466 // Checks whether the value of a given virtual register is a reference.
467 // TODO(titzer): rename this to IsReference.
468 bool HasTaggedValue(int virtual_register) const;
469
470 // Returns the register kind required by the given virtual register.
471 RegisterKind RequiredRegisterKind(int virtual_register) const;
472
473 // Creates a new live range.
474 LiveRange* NewLiveRange(int index);
475
476 // This zone is for InstructionOperands and moves that live beyond register 462 // This zone is for InstructionOperands and moves that live beyond register
477 // allocation. 463 // allocation.
478 Zone* code_zone() const { return code()->zone(); } 464 Zone* code_zone() const { return code()->zone(); }
465 const PhiMap& phi_map() const { return phi_map_; }
466 PhiMap& phi_map() { return phi_map_; }
467 Frame* frame() const { return frame_; }
468 const char* debug_name() const { return debug_name_; }
469 const RegisterConfiguration* config() const { return config_; }
479 470
480 BitVector* assigned_registers() { return assigned_registers_; } 471 void SetLiveRangeAssignedRegister(LiveRange* range, int reg);
481 BitVector* assigned_double_registers() { return assigned_double_registers_; } 472 LiveRange* LiveRangeFor(int index);
473 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); }
482 474
483 #ifdef DEBUG 475 void AssignPhiInput(LiveRange* range, const InstructionOperand& assignment);
476 SpillRange* AssignSpillRangeToLiveRange(LiveRange* range);
477
478 MoveOperands* AddGapMove(int index, Instruction::GapPosition position,
479 const InstructionOperand& from,
480 const InstructionOperand& to);
481
482 bool IsBlockBoundary(LifetimePosition pos);
483
484 const InstructionBlock* GetInstructionBlock(LifetimePosition pos) const {
485 return code()->GetInstructionBlock(pos.ToInstructionIndex());
486 }
487
484 void Verify() const; 488 void Verify() const;
485 #endif
486 489
487 void AllocateRegisters(); 490 bool IsReference(int virtual_register) const {
488 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const; 491 return code()->IsReference(virtual_register);
489 bool SafePointsAreInOrder() const; 492 }
490 493
494 private:
491 // Liveness analysis support. 495 // Liveness analysis support.
492 BitVector* ComputeLiveOut(const InstructionBlock* block); 496 BitVector* ComputeLiveOut(const InstructionBlock* block);
493 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out); 497 void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out);
494 bool IsOutputRegisterOf(Instruction* instr, int index); 498 bool IsOutputRegisterOf(Instruction* instr, int index);
495 bool IsOutputDoubleRegisterOf(Instruction* instr, int index); 499 bool IsOutputDoubleRegisterOf(Instruction* instr, int index);
496 void ProcessInstructions(const InstructionBlock* block, BitVector* live); 500 void ProcessInstructions(const InstructionBlock* block, BitVector* live);
497 void MeetRegisterConstraints(const InstructionBlock* block); 501 void MeetRegisterConstraints(const InstructionBlock* block);
498 void MeetConstraintsBefore(int index); 502 void MeetConstraintsBefore(int index);
499 void MeetConstraintsAfter(int index); 503 void MeetConstraintsAfter(int index);
500 void MeetRegisterConstraintsForLastInstructionInBlock( 504 void MeetRegisterConstraintsForLastInstructionInBlock(
501 const InstructionBlock* block); 505 const InstructionBlock* block);
502 void ResolvePhis(const InstructionBlock* block); 506 void ResolvePhis(const InstructionBlock* block);
503 507
508 static int FixedLiveRangeID(int index) { return -index - 1; }
509 int FixedDoubleLiveRangeID(int index);
510 LiveRange* FixedLiveRangeFor(int index);
511 LiveRange* FixedDoubleLiveRangeFor(int index);
512 Instruction* GetLastInstruction(const InstructionBlock* block);
513
514 // Returns the register kind required by the given virtual register.
515 RegisterKind RequiredRegisterKind(int virtual_register) const;
516
517 // Creates a new live range.
518 LiveRange* NewLiveRange(int index);
519
504 // Helper methods for building intervals. 520 // Helper methods for building intervals.
505 InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos, 521 InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos,
506 bool is_tagged); 522 bool is_tagged);
507 LiveRange* LiveRangeFor(InstructionOperand* operand); 523 LiveRange* LiveRangeFor(InstructionOperand* operand);
508 void Define(LifetimePosition position, InstructionOperand* operand, 524 void Define(LifetimePosition position, InstructionOperand* operand,
509 InstructionOperand* hint); 525 InstructionOperand* hint);
510 void Use(LifetimePosition block_start, LifetimePosition position, 526 void Use(LifetimePosition block_start, LifetimePosition position,
511 InstructionOperand* operand, InstructionOperand* hint); 527 InstructionOperand* operand, InstructionOperand* hint);
512 MoveOperands* AddGapMove(int index, Instruction::GapPosition position, 528
513 const InstructionOperand& from, 529 Zone* const local_zone_;
514 const InstructionOperand& to); 530 Frame* const frame_;
531 InstructionSequence* const code_;
532 const char* const debug_name_;
533 const RegisterConfiguration* const config_;
titzer 2015/04/20 13:33:53 Can we split the output of the LiveRangeBuilder in
534 PhiMap phi_map_;
535 ZoneVector<BitVector*> live_in_sets_;
536 ZoneVector<LiveRange*> live_ranges_;
537 ZoneVector<LiveRange*> fixed_live_ranges_;
538 ZoneVector<LiveRange*> fixed_double_live_ranges_;
539 ZoneVector<SpillRange*> spill_ranges_;
540 BitVector* assigned_registers_;
541 BitVector* assigned_double_registers_;
542
543 DISALLOW_COPY_AND_ASSIGN(LiveRangeBuilder);
544 };
545
546
547 class LinearScanAllocator FINAL : public ZoneObject {
548 public:
549 explicit LinearScanAllocator(LiveRangeBuilder* live_range_builder,
550 RegisterKind kind);
551
552 // Phase 4: compute register assignments.
553 void AllocateRegisters();
554
555 private:
556 LiveRangeBuilder* live_range_builder() const { return live_range_builder_; }
557
558 InstructionSequence* code() const { return live_range_builder()->code(); }
559 // This zone is for datastructures only needed during register allocation.
560 Zone* local_zone() const { return live_range_builder()->local_zone(); }
561
562 // This zone is for InstructionOperands and moves that live beyond register
563 // allocation.
564 Zone* code_zone() const { return code()->zone(); }
565
566 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); }
567
568 int GetVirtualRegister() { return code()->NextVirtualRegister(); }
569
570 bool IsReference(int virtual_register) const {
571 return live_range_builder()->IsReference(virtual_register);
572 }
573
574 LiveRange* LiveRangeFor(int index) {
575 return live_range_builder()->LiveRangeFor(index);
576 }
515 577
516 // Helper methods for updating the life range lists. 578 // Helper methods for updating the life range lists.
517 void AddToActive(LiveRange* range); 579 void AddToActive(LiveRange* range);
518 void AddToInactive(LiveRange* range); 580 void AddToInactive(LiveRange* range);
519 void AddToUnhandledSorted(LiveRange* range); 581 void AddToUnhandledSorted(LiveRange* range);
520 void AddToUnhandledUnsorted(LiveRange* range); 582 void AddToUnhandledUnsorted(LiveRange* range);
521 void SortUnhandled(); 583 void SortUnhandled();
522 bool UnhandledIsSorted(); 584 bool UnhandledIsSorted();
523 void ActiveToHandled(LiveRange* range); 585 void ActiveToHandled(LiveRange* range);
524 void ActiveToInactive(LiveRange* range); 586 void ActiveToInactive(LiveRange* range);
525 void InactiveToHandled(LiveRange* range); 587 void InactiveToHandled(LiveRange* range);
526 void InactiveToActive(LiveRange* range); 588 void InactiveToActive(LiveRange* range);
527 589
528 // Helper methods for allocating registers. 590 // Helper methods for allocating registers.
529 bool TryReuseSpillForPhi(LiveRange* range); 591 bool TryReuseSpillForPhi(LiveRange* range);
530 bool TryAllocateFreeReg(LiveRange* range); 592 bool TryAllocateFreeReg(LiveRange* range);
531 void AllocateBlockedReg(LiveRange* range); 593 void AllocateBlockedReg(LiveRange* range);
532 SpillRange* AssignSpillRangeToLiveRange(LiveRange* range);
533 594
534 // Live range splitting helpers. 595 // Live range splitting helpers.
535 596
536 // Split the given range at the given position. 597 // Split the given range at the given position.
537 // If range starts at or after the given position then the 598 // If range starts at or after the given position then the
538 // original range is returned. 599 // original range is returned.
539 // Otherwise returns the live range that starts at pos and contains 600 // Otherwise returns the live range that starts at pos and contains
540 // all uses from the original range that follow pos. Uses at pos will 601 // all uses from the original range that follow pos. Uses at pos will
541 // still be owned by the original range after splitting. 602 // still be owned by the original range after splitting.
542 LiveRange* SplitRangeAt(LiveRange* range, LifetimePosition pos); 603 LiveRange* SplitRangeAt(LiveRange* range, LifetimePosition pos);
(...skipping 21 matching lines...) Expand all
564 LifetimePosition until, LifetimePosition end); 625 LifetimePosition until, LifetimePosition end);
565 626
566 void SplitAndSpillIntersecting(LiveRange* range); 627 void SplitAndSpillIntersecting(LiveRange* range);
567 628
568 // If we are trying to spill a range inside the loop try to 629 // If we are trying to spill a range inside the loop try to
569 // hoist spill position out to the point just before the loop. 630 // hoist spill position out to the point just before the loop.
570 LifetimePosition FindOptimalSpillingPos(LiveRange* range, 631 LifetimePosition FindOptimalSpillingPos(LiveRange* range,
571 LifetimePosition pos); 632 LifetimePosition pos);
572 633
573 void Spill(LiveRange* range); 634 void Spill(LiveRange* range);
574 bool IsBlockBoundary(LifetimePosition pos);
575
576 // Helper methods for resolving control flow.
577 void ResolveControlFlow(const InstructionBlock* block,
578 const InstructionOperand& cur_op,
579 const InstructionBlock* pred,
580 const InstructionOperand& pred_op);
581
582 void SetLiveRangeAssignedRegister(LiveRange* range, int reg);
583 635
584 // Return the block which contains give lifetime position. 636 // Return the block which contains give lifetime position.
585 const InstructionBlock* GetInstructionBlock(LifetimePosition pos); 637 const InstructionBlock* GetInstructionBlock(LifetimePosition pos) const {
638 return live_range_builder()->GetInstructionBlock(pos);
639 }
640
641 void SetLiveRangeAssignedRegister(LiveRange* range, int reg) {
642 live_range_builder()->SetLiveRangeAssignedRegister(range, reg);
643 }
586 644
587 // Helper methods for the fixed registers. 645 // Helper methods for the fixed registers.
588 int RegisterCount() const; 646 int RegisterCount() const { return num_registers_; }
589 static int FixedLiveRangeID(int index) { return -index - 1; }
590 int FixedDoubleLiveRangeID(int index);
591 LiveRange* FixedLiveRangeFor(int index);
592 LiveRange* FixedDoubleLiveRangeFor(int index);
593 LiveRange* LiveRangeFor(int index);
594 Instruction* GetLastInstruction(const InstructionBlock* block);
595
596 const char* RegisterName(int allocation_index); 647 const char* RegisterName(int allocation_index);
597 648
598 Instruction* InstructionAt(int index) { return code()->InstructionAt(index); } 649 const RegisterConfiguration* config() const {
599 void AssignPhiInput(LiveRange* range, const InstructionOperand& assignment); 650 return live_range_builder()->config();
600 651 }
601 Frame* frame() const { return frame_; } 652 ZoneVector<LiveRange*>& live_ranges() {
602 const char* debug_name() const { return debug_name_; } 653 return live_range_builder()->live_ranges();
603 const RegisterConfiguration* config() const { return config_; } 654 }
604 ZoneVector<LiveRange*>& live_ranges() { return live_ranges_; } 655 ZoneVector<LiveRange*>& fixed_live_ranges() {
605 ZoneVector<LiveRange*>& fixed_live_ranges() { return fixed_live_ranges_; } 656 return live_range_builder()->fixed_live_ranges();
657 }
606 ZoneVector<LiveRange*>& fixed_double_live_ranges() { 658 ZoneVector<LiveRange*>& fixed_double_live_ranges() {
607 return fixed_double_live_ranges_; 659 return live_range_builder()->fixed_double_live_ranges();
608 } 660 }
609 ZoneVector<LiveRange*>& unhandled_live_ranges() { 661 ZoneVector<LiveRange*>& unhandled_live_ranges() {
610 return unhandled_live_ranges_; 662 return unhandled_live_ranges_;
611 } 663 }
612 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; } 664 ZoneVector<LiveRange*>& active_live_ranges() { return active_live_ranges_; }
613 ZoneVector<LiveRange*>& inactive_live_ranges() { 665 ZoneVector<LiveRange*>& inactive_live_ranges() {
614 return inactive_live_ranges_; 666 return inactive_live_ranges_;
615 } 667 }
616 ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; } 668 ZoneVector<SpillRange*>& spill_ranges() {
669 return live_range_builder()->spill_ranges();
670 }
671 LiveRangeBuilder::PhiMap& phi_map() {
672 return live_range_builder()->phi_map();
673 }
617 674
618 class PhiMapValue : public ZoneObject { 675 LiveRangeBuilder* const live_range_builder_;
619 public: 676 const RegisterKind mode_;
620 PhiMapValue(PhiInstruction* phi, const InstructionBlock* block, Zone* zone) 677 const int num_registers_;
621 : phi(phi), block(block), incoming_moves(zone) {
622 incoming_moves.reserve(phi->operands().size());
623 }
624 PhiInstruction* const phi;
625 const InstructionBlock* const block;
626 ZoneVector<MoveOperands*> incoming_moves;
627 };
628 typedef ZoneMap<int, PhiMapValue*> PhiMap;
629 678
630 Zone* const local_zone_;
631 Frame* const frame_;
632 InstructionSequence* const code_;
633 const char* const debug_name_;
634
635 const RegisterConfiguration* config_;
636 PhiMap phi_map_;
637
638 // During liveness analysis keep a mapping from block id to live_in sets
639 // for blocks already analyzed.
640 ZoneVector<BitVector*> live_in_sets_;
641
642 // Liveness analysis results.
643 ZoneVector<LiveRange*> live_ranges_;
644
645 // Lists of live ranges
646 ZoneVector<LiveRange*> fixed_live_ranges_;
647 ZoneVector<LiveRange*> fixed_double_live_ranges_;
648 ZoneVector<LiveRange*> unhandled_live_ranges_; 679 ZoneVector<LiveRange*> unhandled_live_ranges_;
649 ZoneVector<LiveRange*> active_live_ranges_; 680 ZoneVector<LiveRange*> active_live_ranges_;
650 ZoneVector<LiveRange*> inactive_live_ranges_; 681 ZoneVector<LiveRange*> inactive_live_ranges_;
651 ZoneVector<SpillRange*> spill_ranges_;
652
653 RegisterKind mode_;
654 int num_registers_;
655
656 BitVector* assigned_registers_;
657 BitVector* assigned_double_registers_;
658 682
659 #ifdef DEBUG 683 #ifdef DEBUG
660 LifetimePosition allocation_finger_; 684 LifetimePosition allocation_finger_;
661 #endif 685 #endif
662 686
663 DISALLOW_COPY_AND_ASSIGN(RegisterAllocator); 687 DISALLOW_COPY_AND_ASSIGN(LinearScanAllocator);
688 };
689
690
691 class OperandAssigner : public ZoneObject {
692 public:
693 explicit OperandAssigner(LiveRangeBuilder* live_range_builder);
694
695 // Phase 5: assign spill splots.
696 void AssignSpillSlots();
697
698 // Phase 6: commit assignment.
699 void CommitAssignment();
700
701 private:
702 LiveRangeBuilder* live_range_builder() const { return live_range_builder_; }
703
704 LiveRangeBuilder* const live_range_builder_;
705
706 DISALLOW_COPY_AND_ASSIGN(OperandAssigner);
707 };
708
709
710 class ReferenceMapPopulator : public ZoneObject {
711 public:
712 explicit ReferenceMapPopulator(LiveRangeBuilder* live_range_builder);
713
714 // Phase 7: compute values for pointer maps.
715 void PopulateReferenceMaps();
716
717 private:
718 bool SafePointsAreInOrder() const;
719
720 bool IsReference(int virtual_register) const {
721 return live_range_builder()->IsReference(virtual_register);
722 }
723
724 LiveRangeBuilder* live_range_builder() const { return live_range_builder_; }
725
726 LiveRangeBuilder* const live_range_builder_;
727
728 DISALLOW_COPY_AND_ASSIGN(ReferenceMapPopulator);
729 };
730
731
732 class LiveRangeConnector : public ZoneObject {
733 public:
734 explicit LiveRangeConnector(LiveRangeBuilder* live_range_builder);
735
736 // Phase 8: reconnect split ranges with moves.
737 void ConnectRanges(Zone* temp_zone);
738
739 // Phase 9: insert moves to connect ranges across basic blocks.
740 void ResolveControlFlow();
741
742 private:
743 const InstructionBlock* GetInstructionBlock(LifetimePosition pos) const {
744 return live_range_builder()->GetInstructionBlock(pos);
745 }
746 bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const;
747 void ResolveControlFlow(const InstructionBlock* block,
748 const InstructionOperand& cur_op,
749 const InstructionBlock* pred,
750 const InstructionOperand& pred_op);
751 InstructionSequence* code() const { return live_range_builder()->code(); }
752 Zone* code_zone() const { return code()->zone(); }
753 LiveRangeBuilder* live_range_builder() const { return live_range_builder_; }
754
755 LiveRangeBuilder* const live_range_builder_;
756
757 DISALLOW_COPY_AND_ASSIGN(LiveRangeConnector);
664 }; 758 };
665 759
666 } // namespace compiler 760 } // namespace compiler
667 } // namespace internal 761 } // namespace internal
668 } // namespace v8 762 } // namespace v8
669 763
670 #endif // V8_REGISTER_ALLOCATOR_H_ 764 #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