[turbofan] add RegisterConfiguration to decouple arch specific register layouts from...
authordcarney@chromium.org <dcarney@chromium.org>
Tue, 4 Nov 2014 09:21:12 +0000 (09:21 +0000)
committerdcarney@chromium.org <dcarney@chromium.org>
Tue, 4 Nov 2014 09:22:32 +0000 (09:22 +0000)
R=bmeurer@chromium.org

BUG=

Review URL: https://codereview.chromium.org/694313002

Cr-Commit-Position: refs/heads/master@{#25097}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25097 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

14 files changed:
BUILD.gn
src/compiler/graph-visualizer.cc
src/compiler/instruction.cc
src/compiler/instruction.h
src/compiler/pipeline.cc
src/compiler/register-allocator.cc
src/compiler/register-allocator.h
src/compiler/register-configuration.cc [new file with mode: 0644]
src/compiler/register-configuration.h [new file with mode: 0644]
test/cctest/compiler/test-codegen-deopt.cc
test/cctest/compiler/test-gap-resolver.cc
test/unittests/compiler/instruction-selector-unittest.cc
test/unittests/compiler/register-allocator-unittest.cc
tools/gyp/v8.gyp

index 0b1b06e..bc4d457 100644 (file)
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -571,6 +571,8 @@ source_set("v8_base") {
     "src/compiler/raw-machine-assembler.h",
     "src/compiler/register-allocator.cc",
     "src/compiler/register-allocator.h",
+    "src/compiler/register-configuration.cc",
+    "src/compiler/register-configuration.h",
     "src/compiler/representation-change.h",
     "src/compiler/schedule.cc",
     "src/compiler/schedule.h",
index 559da32..19f24cf 100644 (file)
@@ -680,7 +680,9 @@ void GraphC1Visualizer::PrintSchedule(const char* phase,
       for (int j = instruction_block->first_instruction_index();
            j <= instruction_block->last_instruction_index(); j++) {
         PrintIndent();
-        os_ << j << " " << *instructions->InstructionAt(j) << " <|@\n";
+        PrintableInstruction printable = {RegisterConfiguration::ArchDefault(),
+                                          instructions->InstructionAt(j)};
+        os_ << j << " " << printable << " <|@\n";
       }
     }
   }
index 9705bea..76a6950 100644 (file)
@@ -6,17 +6,15 @@
 #include "src/compiler/generic-node-inl.h"
 #include "src/compiler/graph.h"
 #include "src/compiler/instruction.h"
-#include "src/macro-assembler.h"
 
 namespace v8 {
 namespace internal {
 namespace compiler {
 
-STATIC_ASSERT(kMaxGeneralRegisters >= Register::kNumRegisters);
-STATIC_ASSERT(kMaxDoubleRegisters >= DoubleRegister::kMaxNumRegisters);
-
-
-std::ostream& operator<<(std::ostream& os, const InstructionOperand& op) {
+std::ostream& operator<<(std::ostream& os,
+                         const PrintableInstructionOperand& printable) {
+  const InstructionOperand& op = *printable.op_;
+  const RegisterConfiguration* conf = printable.register_configuration_;
   switch (op.kind()) {
     case InstructionOperand::INVALID:
       return os << "(0)";
@@ -30,10 +28,10 @@ std::ostream& operator<<(std::ostream& os, const InstructionOperand& op) {
         case UnallocatedOperand::NONE:
           return os;
         case UnallocatedOperand::FIXED_REGISTER:
-          return os << "(=" << Register::AllocationIndexToString(
+          return os << "(=" << conf->general_register_name(
                                    unalloc->fixed_register_index()) << ")";
         case UnallocatedOperand::FIXED_DOUBLE_REGISTER:
-          return os << "(=" << DoubleRegister::AllocationIndexToString(
+          return os << "(=" << conf->double_register_name(
                                    unalloc->fixed_register_index()) << ")";
         case UnallocatedOperand::MUST_HAVE_REGISTER:
           return os << "(R)";
@@ -52,11 +50,9 @@ std::ostream& operator<<(std::ostream& os, const InstructionOperand& op) {
     case InstructionOperand::DOUBLE_STACK_SLOT:
       return os << "[double_stack:" << op.index() << "]";
     case InstructionOperand::REGISTER:
-      return os << "[" << Register::AllocationIndexToString(op.index())
-                << "|R]";
+      return os << "[" << conf->general_register_name(op.index()) << "|R]";
     case InstructionOperand::DOUBLE_REGISTER:
-      return os << "[" << DoubleRegister::AllocationIndexToString(op.index())
-                << "|R]";
+      return os << "[" << conf->double_register_name(op.index()) << "|R]";
   }
   UNREACHABLE();
   return os;
@@ -101,9 +97,17 @@ void InstructionOperand::TearDownCaches() {
 }
 
 
-std::ostream& operator<<(std::ostream& os, const MoveOperands& mo) {
-  os << *mo.destination();
-  if (!mo.source()->Equals(mo.destination())) os << " = " << *mo.source();
+std::ostream& operator<<(std::ostream& os,
+                         const PrintableMoveOperands& printable) {
+  const MoveOperands& mo = *printable.move_operands_;
+  PrintableInstructionOperand printable_op = {printable.register_configuration_,
+                                              mo.destination()};
+
+  os << printable_op;
+  if (!mo.source()->Equals(mo.destination())) {
+    printable_op.op_ = mo.source();
+    os << " = " << printable_op;
+  }
   return os << ";";
 }
 
@@ -116,14 +120,17 @@ bool ParallelMove::IsRedundant() const {
 }
 
 
-std::ostream& operator<<(std::ostream& os, const ParallelMove& pm) {
+std::ostream& operator<<(std::ostream& os,
+                         const PrintableParallelMove& printable) {
+  const ParallelMove& pm = *printable.parallel_move_;
   bool first = true;
   for (ZoneList<MoveOperands>::iterator move = pm.move_operands()->begin();
        move != pm.move_operands()->end(); ++move) {
     if (move->IsEliminated()) continue;
     if (!first) os << " ";
     first = false;
-    os << *move;
+    PrintableMoveOperands pmo = {printable.register_configuration_, move};
+    os << pmo;
   }
   return os;
 }
@@ -256,11 +263,16 @@ std::ostream& operator<<(std::ostream& os, const FlagsCondition& fc) {
 }
 
 
-std::ostream& operator<<(std::ostream& os, const Instruction& instr) {
+std::ostream& operator<<(std::ostream& os,
+                         const PrintableInstruction& printable) {
+  const Instruction& instr = *printable.instr_;
+  PrintableInstructionOperand printable_op = {printable.register_configuration_,
+                                              NULL};
   if (instr.OutputCount() > 1) os << "(";
   for (size_t i = 0; i < instr.OutputCount(); i++) {
     if (i > 0) os << ", ";
-    os << *instr.OutputAt(i);
+    printable_op.op_ = instr.OutputAt(i);
+    os << printable_op;
   }
 
   if (instr.OutputCount() > 1) os << ") = ";
@@ -272,7 +284,11 @@ std::ostream& operator<<(std::ostream& os, const Instruction& instr) {
     for (int i = GapInstruction::FIRST_INNER_POSITION;
          i <= GapInstruction::LAST_INNER_POSITION; i++) {
       os << "(";
-      if (gap->parallel_moves_[i] != NULL) os << *gap->parallel_moves_[i];
+      if (gap->parallel_moves_[i] != NULL) {
+        PrintableParallelMove ppm = {printable.register_configuration_,
+                                     gap->parallel_moves_[i]};
+        os << ppm;
+      }
       os << ") ";
     }
   } else if (instr.IsSourcePosition()) {
@@ -293,7 +309,8 @@ std::ostream& operator<<(std::ostream& os, const Instruction& instr) {
   }
   if (instr.InputCount() > 0) {
     for (size_t i = 0; i < instr.InputCount(); i++) {
-      os << " " << *instr.InputAt(i);
+      printable_op.op_ = instr.InputAt(i);
+      os << " " << printable_op;
     }
   }
   return os;
@@ -585,7 +602,9 @@ void FrameStateDescriptor::SetType(size_t index, MachineType type) {
 }
 
 
-std::ostream& operator<<(std::ostream& os, const InstructionSequence& code) {
+std::ostream& operator<<(std::ostream& os,
+                         const PrintableInstructionSequence& printable) {
+  const InstructionSequence& code = *printable.sequence_;
   for (size_t i = 0; i < code.immediates_.size(); ++i) {
     Constant constant = code.immediates_[i];
     os << "IMM#" << i << ": " << constant << "\n";
@@ -626,20 +645,16 @@ std::ostream& operator<<(std::ostream& os, const InstructionSequence& code) {
     }
 
     ScopedVector<char> buf(32);
+    PrintableInstruction printable_instr;
+    printable_instr.register_configuration_ = printable.register_configuration_;
     for (int j = block->first_instruction_index();
          j <= block->last_instruction_index(); j++) {
       // TODO(svenpanne) Add some basic formatting to our streams.
       SNPrintF(buf, "%5d", j);
-      os << "   " << buf.start() << ": " << *code.InstructionAt(j) << "\n";
+      printable_instr.instr_ = code.InstructionAt(j);
+      os << "   " << buf.start() << ": " << printable_instr << "\n";
     }
 
-    // TODO(dcarney): add this back somehow?
-    // os << "  " << block->control();
-
-    // if (block->control_input() != NULL) {
-    //   os << " v" << block->control_input()->id();
-    // }
-
     for (auto succ : block->successors()) {
       const InstructionBlock* succ_block = code.InstructionBlockAt(succ);
       os << " B" << succ_block->id();
index 4f6649f..b42e17b 100644 (file)
@@ -14,6 +14,7 @@
 #include "src/compiler/frame.h"
 #include "src/compiler/instruction-codes.h"
 #include "src/compiler/opcodes.h"
+#include "src/compiler/register-configuration.h"
 #include "src/compiler/schedule.h"
 #include "src/compiler/source-position.h"
 #include "src/zone-allocator.h"
@@ -27,18 +28,13 @@ const InstructionCode kGapInstruction = -1;
 const InstructionCode kBlockStartInstruction = -2;
 const InstructionCode kSourcePositionInstruction = -3;
 
-// Platform independent maxes.
-static const int kMaxGeneralRegisters = 32;
-static const int kMaxDoubleRegisters = 32;
-
-
-#define INSTRUCTION_OPERAND_LIST(V)           \
-  V(Constant, CONSTANT, 0)                    \
-  V(Immediate, IMMEDIATE, 0)                  \
-  V(StackSlot, STACK_SLOT, 128)               \
-  V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128)  \
-  V(Register, REGISTER, kMaxGeneralRegisters) \
-  V(DoubleRegister, DOUBLE_REGISTER, kMaxDoubleRegisters)
+#define INSTRUCTION_OPERAND_LIST(V)                                  \
+  V(Constant, CONSTANT, 0)                                           \
+  V(Immediate, IMMEDIATE, 0)                                         \
+  V(StackSlot, STACK_SLOT, 128)                                      \
+  V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128)                         \
+  V(Register, REGISTER, RegisterConfiguration::kMaxGeneralRegisters) \
+  V(DoubleRegister, DOUBLE_REGISTER, RegisterConfiguration::kMaxDoubleRegisters)
 
 class InstructionOperand : public ZoneObject {
  public:
@@ -87,7 +83,13 @@ class InstructionOperand : public ZoneObject {
 
 typedef ZoneVector<InstructionOperand*> InstructionOperandVector;
 
-std::ostream& operator<<(std::ostream& os, const InstructionOperand& op);
+struct PrintableInstructionOperand {
+  const RegisterConfiguration* register_configuration_;
+  const InstructionOperand* op_;
+};
+
+std::ostream& operator<<(std::ostream& os,
+                         const PrintableInstructionOperand& op);
 
 class UnallocatedOperand : public InstructionOperand {
  public:
@@ -306,7 +308,15 @@ class MoveOperands FINAL {
   InstructionOperand* destination_;
 };
 
-std::ostream& operator<<(std::ostream& os, const MoveOperands& mo);
+
+struct PrintableMoveOperands {
+  const RegisterConfiguration* register_configuration_;
+  const MoveOperands* move_operands_;
+};
+
+
+std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo);
+
 
 template <InstructionOperand::Kind kOperandKind, int kNumCachedOperands>
 class SubKindOperand FINAL : public InstructionOperand {
@@ -359,7 +369,15 @@ class ParallelMove FINAL : public ZoneObject {
   ZoneList<MoveOperands> move_operands_;
 };
 
-std::ostream& operator<<(std::ostream& os, const ParallelMove& pm);
+
+struct PrintableParallelMove {
+  const RegisterConfiguration* register_configuration_;
+  const ParallelMove* parallel_move_;
+};
+
+
+std::ostream& operator<<(std::ostream& os, const PrintableParallelMove& pm);
+
 
 class PointerMap FINAL : public ZoneObject {
  public:
@@ -534,7 +552,13 @@ class Instruction : public ZoneObject {
   InstructionOperand* operands_[1];
 };
 
-std::ostream& operator<<(std::ostream& os, const Instruction& instr);
+
+struct PrintableInstruction {
+  const RegisterConfiguration* register_configuration_;
+  const Instruction* instr_;
+};
+std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr);
+
 
 // Represents moves inserted before an instruction due to register allocation.
 // TODO(titzer): squash GapInstruction back into Instruction, since essentially
@@ -585,7 +609,8 @@ class GapInstruction : public Instruction {
   }
 
  private:
-  friend std::ostream& operator<<(std::ostream& os, const Instruction& instr);
+  friend std::ostream& operator<<(std::ostream& os,
+                                  const PrintableInstruction& instr);
   ParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
 };
 
@@ -847,6 +872,9 @@ typedef ZoneDeque<PointerMap*> PointerMapDeque;
 typedef ZoneVector<FrameStateDescriptor*> DeoptimizationVector;
 typedef ZoneVector<InstructionBlock*> InstructionBlocks;
 
+struct PrintableInstructionSequence;
+
+
 // Represents architecture-specific generated code before, during, and after
 // register allocation.
 // TODO(titzer): s/IsDouble/IsFloat64/
@@ -961,7 +989,7 @@ class InstructionSequence FINAL {
 
  private:
   friend std::ostream& operator<<(std::ostream& os,
-                                  const InstructionSequence& code);
+                                  const PrintableInstructionSequence& code);
 
   typedef std::set<int, std::less<int>, ZoneIntAllocator> VirtualRegisterSet;
 
@@ -977,7 +1005,15 @@ class InstructionSequence FINAL {
   DeoptimizationVector deoptimization_entries_;
 };
 
-std::ostream& operator<<(std::ostream& os, const InstructionSequence& code);
+
+struct PrintableInstructionSequence {
+  const RegisterConfiguration* register_configuration_;
+  const InstructionSequence* sequence_;
+};
+
+
+std::ostream& operator<<(std::ostream& os,
+                         const PrintableInstructionSequence& code);
 
 }  // namespace compiler
 }  // namespace internal
index 5c384c2..f2571e3 100644 (file)
@@ -558,8 +558,10 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) {
 
   if (FLAG_trace_turbo) {
     OFStream os(stdout);
+    PrintableInstructionSequence printable = {
+        RegisterConfiguration::ArchDefault(), &sequence};
     os << "----- Instruction sequence before register allocation -----\n"
-       << sequence;
+       << printable;
     TurboCfgFile tcf(isolate());
     tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(),
                  &sequence);
@@ -587,7 +589,7 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) {
 #endif
 
 
-    RegisterAllocator allocator(RegisterAllocator::PlatformConfig(),
+    RegisterAllocator allocator(RegisterConfiguration::ArchDefault(),
                                 zone_scope.zone(), &frame, &sequence,
                                 debug_name.get());
     if (!allocator.Allocate(data->pipeline_statistics())) {
@@ -602,8 +604,10 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) {
 
   if (FLAG_trace_turbo) {
     OFStream os(stdout);
+    PrintableInstructionSequence printable = {
+        RegisterConfiguration::ArchDefault(), &sequence};
     os << "----- Instruction sequence after register allocation -----\n"
-       << sequence;
+       << printable;
   }
 
   if (data->pipeline_statistics() != NULL) {
index ced88a8..7a82768 100644 (file)
@@ -5,7 +5,6 @@
 #include "src/compiler/linkage.h"
 #include "src/compiler/pipeline-statistics.h"
 #include "src/compiler/register-allocator.h"
-#include "src/macro-assembler.h"  // TODO(dcarney): remove this.
 #include "src/string-stream.h"
 
 namespace v8 {
@@ -507,22 +506,9 @@ LifetimePosition LiveRange::FirstIntersection(LiveRange* other) {
 }
 
 
-RegisterAllocator::Config RegisterAllocator::PlatformConfig() {
-  DCHECK_EQ(Register::kMaxNumAllocatableRegisters,
-            Register::NumAllocatableRegisters());
-  Config config;
-  config.num_general_registers_ = Register::kMaxNumAllocatableRegisters;
-  config.num_double_registers_ = DoubleRegister::kMaxNumAllocatableRegisters;
-  config.num_aliased_double_registers_ =
-      DoubleRegister::NumAllocatableAliasedRegisters();
-  config.GeneralRegisterName = Register::AllocationIndexToString;
-  config.DoubleRegisterName = DoubleRegister::AllocationIndexToString;
-  return config;
-}
-
-
-RegisterAllocator::RegisterAllocator(const Config& config, Zone* local_zone,
-                                     Frame* frame, InstructionSequence* code,
+RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config,
+                                     Zone* local_zone, Frame* frame,
+                                     InstructionSequence* code,
                                      const char* debug_name)
     : zone_(local_zone),
       frame_(frame),
@@ -531,8 +517,8 @@ RegisterAllocator::RegisterAllocator(const Config& config, Zone* local_zone,
       config_(config),
       live_in_sets_(code->InstructionBlockCount(), zone()),
       live_ranges_(code->VirtualRegisterCount() * 2, zone()),
-      fixed_live_ranges_(this->config().num_general_registers_, NULL, zone()),
-      fixed_double_live_ranges_(this->config().num_double_registers_, NULL,
+      fixed_live_ranges_(this->config()->num_general_registers(), NULL, zone()),
+      fixed_double_live_ranges_(this->config()->num_double_registers(), NULL,
                                 zone()),
       unhandled_live_ranges_(code->VirtualRegisterCount() * 2, zone()),
       active_live_ranges_(8, zone()),
@@ -541,12 +527,14 @@ RegisterAllocator::RegisterAllocator(const Config& config, Zone* local_zone,
       mode_(UNALLOCATED_REGISTERS),
       num_registers_(-1),
       allocation_ok_(true) {
-  DCHECK(this->config().num_general_registers_ <= kMaxGeneralRegisters);
-  DCHECK(this->config().num_double_registers_ <= kMaxDoubleRegisters);
+  DCHECK(this->config()->num_general_registers() <=
+         RegisterConfiguration::kMaxGeneralRegisters);
+  DCHECK(this->config()->num_double_registers() <=
+         RegisterConfiguration::kMaxDoubleRegisters);
   // TryAllocateFreeReg and AllocateBlockedReg assume this
   // when allocating local arrays.
-  DCHECK(this->config().num_double_registers_ >=
-         this->config().num_general_registers_);
+  DCHECK(this->config()->num_double_registers() >=
+         this->config()->num_general_registers());
 }
 
 
@@ -603,7 +591,7 @@ void RegisterAllocator::AddInitialIntervals(const InstructionBlock* block,
 
 
 int RegisterAllocator::FixedDoubleLiveRangeID(int index) {
-  return -index - 1 - config().num_general_registers_;
+  return -index - 1 - config()->num_general_registers();
 }
 
 
@@ -635,7 +623,7 @@ InstructionOperand* RegisterAllocator::AllocateFixed(
 
 
 LiveRange* RegisterAllocator::FixedLiveRangeFor(int index) {
-  DCHECK(index < config().num_general_registers_);
+  DCHECK(index < config()->num_general_registers());
   LiveRange* result = fixed_live_ranges_[index];
   if (result == NULL) {
     // TODO(titzer): add a utility method to allocate a new LiveRange:
@@ -653,7 +641,7 @@ LiveRange* RegisterAllocator::FixedLiveRangeFor(int index) {
 
 
 LiveRange* RegisterAllocator::FixedDoubleLiveRangeFor(int index) {
-  DCHECK(index < config().num_aliased_double_registers_);
+  DCHECK(index < config()->num_aliased_double_registers());
   LiveRange* result = fixed_double_live_ranges_[index];
   if (result == NULL) {
     result = new (zone()) LiveRange(FixedDoubleLiveRangeID(index), code_zone());
@@ -1031,7 +1019,7 @@ void RegisterAllocator::ProcessInstructions(const InstructionBlock* block,
       }
 
       if (instr->ClobbersRegisters()) {
-        for (int i = 0; i < config().num_general_registers_; ++i) {
+        for (int i = 0; i < config()->num_general_registers(); ++i) {
           if (!IsOutputRegisterOf(instr, i)) {
             LiveRange* range = FixedLiveRangeFor(i);
             range->AddUseInterval(curr_position, curr_position.InstructionEnd(),
@@ -1041,7 +1029,7 @@ void RegisterAllocator::ProcessInstructions(const InstructionBlock* block,
       }
 
       if (instr->ClobbersDoubleRegisters()) {
-        for (int i = 0; i < config().num_aliased_double_registers_; ++i) {
+        for (int i = 0; i < config()->num_aliased_double_registers(); ++i) {
           if (!IsOutputDoubleRegisterOf(instr, i)) {
             LiveRange* range = FixedDoubleLiveRangeFor(i);
             range->AddUseInterval(curr_position, curr_position.InstructionEnd(),
@@ -1126,10 +1114,10 @@ void RegisterAllocator::ResolvePhis(const InstructionBlock* block) {
 
 
 bool RegisterAllocator::Allocate(PipelineStatistics* stats) {
-  assigned_registers_ =
-      new (code_zone()) BitVector(config().num_general_registers_, code_zone());
+  assigned_registers_ = new (code_zone())
+      BitVector(config()->num_general_registers(), code_zone());
   assigned_double_registers_ = new (code_zone())
-      BitVector(config().num_aliased_double_registers_, code_zone());
+      BitVector(config()->num_aliased_double_registers(), code_zone());
   {
     PhaseScope phase_scope(stats, "meet register constraints");
     MeetRegisterConstraints();
@@ -1535,14 +1523,14 @@ void RegisterAllocator::PopulatePointerMaps() {
 
 
 void RegisterAllocator::AllocateGeneralRegisters() {
-  num_registers_ = config().num_general_registers_;
+  num_registers_ = config()->num_general_registers();
   mode_ = GENERAL_REGISTERS;
   AllocateRegisters();
 }
 
 
 void RegisterAllocator::AllocateDoubleRegisters() {
-  num_registers_ = config().num_aliased_double_registers_;
+  num_registers_ = config()->num_aliased_double_registers();
   mode_ = DOUBLE_REGISTERS;
   AllocateRegisters();
 }
@@ -1566,7 +1554,7 @@ void RegisterAllocator::AllocateRegisters() {
   DCHECK(inactive_live_ranges_.is_empty());
 
   if (mode_ == DOUBLE_REGISTERS) {
-    for (int i = 0; i < config().num_aliased_double_registers_; ++i) {
+    for (int i = 0; i < config()->num_aliased_double_registers(); ++i) {
       LiveRange* current = fixed_double_live_ranges_.at(i);
       if (current != NULL) {
         AddToInactive(current);
@@ -1658,9 +1646,9 @@ void RegisterAllocator::AllocateRegisters() {
 
 const char* RegisterAllocator::RegisterName(int allocation_index) {
   if (mode_ == GENERAL_REGISTERS) {
-    return config().GeneralRegisterName(allocation_index);
+    return config()->general_register_name(allocation_index);
   } else {
-    return config().DoubleRegisterName(allocation_index);
+    return config()->double_register_name(allocation_index);
   }
 }
 
@@ -1805,7 +1793,7 @@ void RegisterAllocator::InactiveToActive(LiveRange* range) {
 
 
 bool RegisterAllocator::TryAllocateFreeReg(LiveRange* current) {
-  LifetimePosition free_until_pos[kMaxDoubleRegisters];
+  LifetimePosition free_until_pos[RegisterConfiguration::kMaxDoubleRegisters];
 
   for (int i = 0; i < num_registers_; i++) {
     free_until_pos[i] = LifetimePosition::MaxPosition();
@@ -1888,8 +1876,8 @@ void RegisterAllocator::AllocateBlockedReg(LiveRange* current) {
     return;
   }
 
-  LifetimePosition use_pos[kMaxGeneralRegisters];
-  LifetimePosition block_pos[kMaxDoubleRegisters];
+  LifetimePosition use_pos[RegisterConfiguration::kMaxGeneralRegisters];
+  LifetimePosition block_pos[RegisterConfiguration::kMaxDoubleRegisters];
 
   for (int i = 0; i < num_registers_; i++) {
     use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition();
index db30f96..b167437 100644 (file)
@@ -319,19 +319,9 @@ class LiveRange FINAL : public ZoneObject {
 
 class RegisterAllocator FINAL {
  public:
-  class Config {
-   public:
-    int num_general_registers_;
-    int num_double_registers_;
-    int num_aliased_double_registers_;
-    const char* (*GeneralRegisterName)(int allocation_index);
-    const char* (*DoubleRegisterName)(int allocation_index);
-  };
-
-  static Config PlatformConfig();
-
-  explicit RegisterAllocator(const Config& config, Zone* local_zone,
-                             Frame* frame, InstructionSequence* code,
+  explicit RegisterAllocator(const RegisterConfiguration* config,
+                             Zone* local_zone, Frame* frame,
+                             InstructionSequence* code,
                              const char* debug_name = nullptr);
 
   bool Allocate(PipelineStatistics* stats = NULL);
@@ -502,14 +492,14 @@ class RegisterAllocator FINAL {
 
   Frame* frame() const { return frame_; }
   const char* debug_name() const { return debug_name_; }
-  const Config& config() const { return config_; }
+  const RegisterConfiguration* config() const { return config_; }
 
   Zone* const zone_;
   Frame* const frame_;
   InstructionSequence* const code_;
   const char* const debug_name_;
 
-  const Config config_;
+  const RegisterConfiguration* config_;
 
   // During liveness analysis keep a mapping from block id to live_in sets
   // for blocks already analyzed.
diff --git a/src/compiler/register-configuration.cc b/src/compiler/register-configuration.cc
new file mode 100644 (file)
index 0000000..e7d8bbd
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/register-configuration.h"
+#include "src/macro-assembler.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+namespace {
+
+STATIC_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >=
+              Register::kNumRegisters);
+STATIC_ASSERT(RegisterConfiguration::kMaxDoubleRegisters >=
+              DoubleRegister::kMaxNumRegisters);
+
+class ArchDefaultRegisterConfiguration : public RegisterConfiguration {
+ public:
+  ArchDefaultRegisterConfiguration()
+      : RegisterConfiguration(Register::kMaxNumAllocatableRegisters,
+                              DoubleRegister::kMaxNumAllocatableRegisters,
+                              DoubleRegister::NumAllocatableAliasedRegisters(),
+                              general_register_name_table_,
+                              double_register_name_table_) {
+    DCHECK_EQ(Register::kMaxNumAllocatableRegisters,
+              Register::NumAllocatableRegisters());
+    for (int i = 0; i < Register::kMaxNumAllocatableRegisters; ++i) {
+      general_register_name_table_[i] = Register::AllocationIndexToString(i);
+    }
+    for (int i = 0; i < DoubleRegister::kMaxNumAllocatableRegisters; ++i) {
+      double_register_name_table_[i] =
+          DoubleRegister::AllocationIndexToString(i);
+    }
+  }
+
+  const char*
+      general_register_name_table_[Register::kMaxNumAllocatableRegisters];
+  const char*
+      double_register_name_table_[DoubleRegister::kMaxNumAllocatableRegisters];
+};
+
+
+static base::LazyInstance<ArchDefaultRegisterConfiguration>::type
+    kDefaultRegisterConfiguration = LAZY_INSTANCE_INITIALIZER;
+
+}  // namepace
+
+
+const RegisterConfiguration* RegisterConfiguration::ArchDefault() {
+  return &kDefaultRegisterConfiguration.Get();
+}
+
+RegisterConfiguration::RegisterConfiguration(
+    int num_general_registers, int num_double_registers,
+    int num_aliased_double_registers, const char* const* general_register_names,
+    const char* const* double_register_names)
+    : num_general_registers_(num_general_registers),
+      num_double_registers_(num_double_registers),
+      num_aliased_double_registers_(num_aliased_double_registers),
+      general_register_names_(general_register_names),
+      double_register_names_(double_register_names) {}
+
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/src/compiler/register-configuration.h b/src/compiler/register-configuration.h
new file mode 100644 (file)
index 0000000..8178ba2
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_REGISTER_CONFIGURATION_H_
+#define V8_COMPILER_REGISTER_CONFIGURATION_H_
+
+#include "src/v8.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// An architecture independent representation of the sets of registers available
+// for instruction creation.
+class RegisterConfiguration {
+ public:
+  // Architecture independent maxes.
+  static const int kMaxGeneralRegisters = 32;
+  static const int kMaxDoubleRegisters = 32;
+
+  static const RegisterConfiguration* ArchDefault();
+
+  RegisterConfiguration(int num_general_registers, int num_double_registers,
+                        int num_aliased_double_registers,
+                        const char* const* general_register_name,
+                        const char* const* double_register_name);
+
+  int num_general_registers() const { return num_general_registers_; }
+  int num_double_registers() const { return num_double_registers_; }
+  int num_aliased_double_registers() const {
+    return num_aliased_double_registers_;
+  }
+
+  const char* general_register_name(int offset) const {
+    DCHECK(offset >= 0 && offset < kMaxGeneralRegisters);
+    return general_register_names_[offset];
+  }
+  const char* double_register_name(int offset) const {
+    DCHECK(offset >= 0 && offset < kMaxDoubleRegisters);
+    return double_register_names_[offset];
+  }
+
+ private:
+  const int num_general_registers_;
+  const int num_double_registers_;
+  const int num_aliased_double_registers_;
+  const char* const* general_register_names_;
+  const char* const* double_register_names_;
+};
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_COMPILER_REGISTER_CONFIGURATION_H_
index c9a033b..974b423 100644 (file)
@@ -75,18 +75,22 @@ class DeoptCodegenTester {
     selector.SelectInstructions();
 
     if (FLAG_trace_turbo) {
+      PrintableInstructionSequence printable = {
+          RegisterConfiguration::ArchDefault(), code};
       os << "----- Instruction sequence before register allocation -----\n"
-         << *code;
+         << printable;
     }
 
     Frame frame;
-    RegisterAllocator allocator(RegisterAllocator::PlatformConfig(),
+    RegisterAllocator allocator(RegisterConfiguration::ArchDefault(),
                                 scope_->main_zone(), &frame, code);
     CHECK(allocator.Allocate());
 
     if (FLAG_trace_turbo) {
+      PrintableInstructionSequence printable = {
+          RegisterConfiguration::ArchDefault(), code};
       os << "----- Instruction sequence after register allocation -----\n"
-         << *code;
+         << printable;
     }
 
     compiler::CodeGenerator generator(&frame, linkage, code, &info);
index aeaf8b9..ea6f4ee 100644 (file)
@@ -65,7 +65,9 @@ class InterpreterState {
       if (it != is.values_.begin()) os << " ";
       InstructionOperand source(it->first.first, it->first.second);
       InstructionOperand destination(it->second.first, it->second.second);
-      os << MoveOperands(&source, &destination);
+      MoveOperands mo(&source, &destination);
+      PrintableMoveOperands pmo = {RegisterConfiguration::ArchDefault(), &mo};
+      os << pmo;
     }
     return os;
   }
index 57ce690..c79a9e4 100644 (file)
@@ -46,8 +46,10 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
   selector.SelectInstructions();
   if (FLAG_trace_turbo) {
     OFStream out(stdout);
+    PrintableInstructionSequence printable = {
+        RegisterConfiguration::ArchDefault(), &sequence};
     out << "=== Code sequence after instruction selection ===" << std::endl
-        << sequence;
+        << printable;
   }
   Stream s;
   // Map virtual registers.
index 5c61708..752999f 100644 (file)
@@ -15,29 +15,22 @@ typedef BasicBlock::RpoNumber Rpo;
 
 namespace {
 
-static const char* general_register_names_[kMaxGeneralRegisters];
-static const char* double_register_names_[kMaxDoubleRegisters];
-static char register_names_[10 * (kMaxGeneralRegisters + kMaxDoubleRegisters)];
-
-
-static const char* GeneralRegisterName(int allocation_index) {
-  return general_register_names_[allocation_index];
-}
-
-
-static const char* DoubleRegisterName(int allocation_index) {
-  return double_register_names_[allocation_index];
-}
+static const char*
+    general_register_names_[RegisterConfiguration::kMaxGeneralRegisters];
+static const char*
+    double_register_names_[RegisterConfiguration::kMaxDoubleRegisters];
+static char register_names_[10 * (RegisterConfiguration::kMaxGeneralRegisters +
+                                  RegisterConfiguration::kMaxDoubleRegisters)];
 
 
 static void InitializeRegisterNames() {
   char* loc = register_names_;
-  for (int i = 0; i < kMaxGeneralRegisters; ++i) {
+  for (int i = 0; i < RegisterConfiguration::kMaxGeneralRegisters; ++i) {
     general_register_names_[i] = loc;
     loc += base::OS::SNPrintF(loc, 100, "gp_%d", i);
     *loc++ = 0;
   }
-  for (int i = 0; i < kMaxDoubleRegisters; ++i) {
+  for (int i = 0; i < RegisterConfiguration::kMaxDoubleRegisters; ++i) {
     double_register_names_[i] = loc;
     loc += base::OS::SNPrintF(loc, 100, "fp_%d", i) + 1;
     *loc++ = 0;
@@ -54,15 +47,21 @@ class RegisterAllocatorTest : public TestWithZone {
   static const int kDefaultNRegs = 4;
 
   RegisterAllocatorTest()
-      : basic_blocks_(zone()),
+      : num_general_registers_(kDefaultNRegs),
+        num_double_registers_(kDefaultNRegs),
+        basic_blocks_(zone()),
         instruction_blocks_(zone()),
         current_block_(NULL) {
     InitializeRegisterNames();
-    config_.num_general_registers_ = kDefaultNRegs;
-    config_.num_double_registers_ = kDefaultNRegs;
-    config_.num_aliased_double_registers_ = kDefaultNRegs;
-    config_.GeneralRegisterName = GeneralRegisterName;
-    config_.DoubleRegisterName = DoubleRegisterName;
+  }
+
+  RegisterConfiguration* config() {
+    if (config_.is_empty()) {
+      config_.Reset(new RegisterConfiguration(
+          num_general_registers_, num_double_registers_, num_double_registers_,
+          general_register_names_, double_register_names_));
+    }
+    return config_.get();
   }
 
   Frame* frame() {
@@ -82,7 +81,7 @@ class RegisterAllocatorTest : public TestWithZone {
   RegisterAllocator* allocator() {
     if (allocator_.is_empty()) {
       allocator_.Reset(
-          new RegisterAllocator(config_, zone(), frame(), sequence()));
+          new RegisterAllocator(config(), zone(), frame(), sequence()));
     }
     return allocator_.get();
   }
@@ -118,12 +117,14 @@ class RegisterAllocatorTest : public TestWithZone {
   void Allocate() {
     if (FLAG_trace_alloc) {
       OFStream os(stdout);
-      os << "Before: " << std::endl << *sequence() << std::endl;
+      PrintableInstructionSequence printable = {config(), sequence()};
+      os << "Before: " << std::endl << printable << std::endl;
     }
     allocator()->Allocate();
     if (FLAG_trace_alloc) {
       OFStream os(stdout);
-      os << "After: " << std::endl << *sequence() << std::endl;
+      PrintableInstructionSequence printable = {config(), sequence()};
+      os << "After: " << std::endl << printable << std::endl;
     }
   }
 
@@ -167,7 +168,9 @@ class RegisterAllocatorTest : public TestWithZone {
     return op;
   }
 
-  RegisterAllocator::Config config_;
+  int num_general_registers_;
+  int num_double_registers_;
+  SmartPointer<RegisterConfiguration> config_;
   ZoneVector<BasicBlock*> basic_blocks_;
   InstructionBlocks instruction_blocks_;
   InstructionBlock* current_block_;
index 4f89bcf..ab81195 100644 (file)
         '../../src/compiler/raw-machine-assembler.h',
         '../../src/compiler/register-allocator.cc',
         '../../src/compiler/register-allocator.h',
+        '../../src/compiler/register-configuration.cc',
+        '../../src/compiler/register-configuration.h',
         '../../src/compiler/representation-change.h',
         '../../src/compiler/schedule.cc',
         '../../src/compiler/schedule.h',