| Index: src/lithium-allocator.h
 | 
| ===================================================================
 | 
| --- src/lithium-allocator.h	(revision 6389)
 | 
| +++ src/lithium-allocator.h	(working copy)
 | 
| @@ -48,6 +48,8 @@
 | 
|  
 | 
|  class LArgument;
 | 
|  class LChunk;
 | 
| +class LOperand;
 | 
| +class LUnallocated;
 | 
|  class LConstantOperand;
 | 
|  class LGap;
 | 
|  class LParallelMove;
 | 
| @@ -149,355 +151,6 @@
 | 
|  };
 | 
|  
 | 
|  
 | 
| -class LOperand: public ZoneObject {
 | 
| - public:
 | 
| -  enum Kind {
 | 
| -    INVALID,
 | 
| -    UNALLOCATED,
 | 
| -    CONSTANT_OPERAND,
 | 
| -    STACK_SLOT,
 | 
| -    DOUBLE_STACK_SLOT,
 | 
| -    REGISTER,
 | 
| -    DOUBLE_REGISTER,
 | 
| -    ARGUMENT
 | 
| -  };
 | 
| -
 | 
| -  LOperand() : value_(KindField::encode(INVALID)) { }
 | 
| -
 | 
| -  Kind kind() const { return KindField::decode(value_); }
 | 
| -  int index() const { return static_cast<int>(value_) >> kKindFieldWidth; }
 | 
| -  bool IsConstantOperand() const { return kind() == CONSTANT_OPERAND; }
 | 
| -  bool IsStackSlot() const { return kind() == STACK_SLOT; }
 | 
| -  bool IsDoubleStackSlot() const { return kind() == DOUBLE_STACK_SLOT; }
 | 
| -  bool IsRegister() const { return kind() == REGISTER; }
 | 
| -  bool IsDoubleRegister() const { return kind() == DOUBLE_REGISTER; }
 | 
| -  bool IsArgument() const { return kind() == ARGUMENT; }
 | 
| -  bool IsUnallocated() const { return kind() == UNALLOCATED; }
 | 
| -  bool Equals(LOperand* other) const { return value_ == other->value_; }
 | 
| -  int VirtualRegister();
 | 
| -
 | 
| -  void PrintTo(StringStream* stream);
 | 
| -  void ConvertTo(Kind kind, int index) {
 | 
| -    value_ = KindField::encode(kind);
 | 
| -    value_ |= index << kKindFieldWidth;
 | 
| -    ASSERT(this->index() == index);
 | 
| -  }
 | 
| -
 | 
| - protected:
 | 
| -  static const int kKindFieldWidth = 3;
 | 
| -  class KindField : public BitField<Kind, 0, kKindFieldWidth> { };
 | 
| -
 | 
| -  LOperand(Kind kind, int index) { ConvertTo(kind, index); }
 | 
| -
 | 
| -  unsigned value_;
 | 
| -};
 | 
| -
 | 
| -
 | 
| -class LUnallocated: public LOperand {
 | 
| - public:
 | 
| -  enum Policy {
 | 
| -    NONE,
 | 
| -    ANY,
 | 
| -    FIXED_REGISTER,
 | 
| -    FIXED_DOUBLE_REGISTER,
 | 
| -    FIXED_SLOT,
 | 
| -    MUST_HAVE_REGISTER,
 | 
| -    WRITABLE_REGISTER,
 | 
| -    SAME_AS_FIRST_INPUT,
 | 
| -    IGNORE
 | 
| -  };
 | 
| -
 | 
| -  // Lifetime of operand inside the instruction.
 | 
| -  enum Lifetime {
 | 
| -    // USED_AT_START operand is guaranteed to be live only at
 | 
| -    // instruction start. Register allocator is free to assign the same register
 | 
| -    // to some other operand used inside instruction (i.e. temporary or
 | 
| -    // output).
 | 
| -    USED_AT_START,
 | 
| -
 | 
| -    // USED_AT_END operand is treated as live until the end of
 | 
| -    // instruction. This means that register allocator will not reuse it's
 | 
| -    // register for any other operand inside instruction.
 | 
| -    USED_AT_END
 | 
| -  };
 | 
| -
 | 
| -  explicit LUnallocated(Policy policy) : LOperand(UNALLOCATED, 0) {
 | 
| -    Initialize(policy, 0, USED_AT_END);
 | 
| -  }
 | 
| -
 | 
| -  LUnallocated(Policy policy, int fixed_index) : LOperand(UNALLOCATED, 0) {
 | 
| -    Initialize(policy, fixed_index, USED_AT_END);
 | 
| -  }
 | 
| -
 | 
| -  LUnallocated(Policy policy, Lifetime lifetime) : LOperand(UNALLOCATED, 0) {
 | 
| -    Initialize(policy, 0, lifetime);
 | 
| -  }
 | 
| -
 | 
| -  // The superclass has a KindField.  Some policies have a signed fixed
 | 
| -  // index in the upper bits.
 | 
| -  static const int kPolicyWidth = 4;
 | 
| -  static const int kLifetimeWidth = 1;
 | 
| -  static const int kVirtualRegisterWidth = 17;
 | 
| -
 | 
| -  static const int kPolicyShift = kKindFieldWidth;
 | 
| -  static const int kLifetimeShift = kPolicyShift + kPolicyWidth;
 | 
| -  static const int kVirtualRegisterShift = kLifetimeShift + kLifetimeWidth;
 | 
| -  static const int kFixedIndexShift =
 | 
| -      kVirtualRegisterShift + kVirtualRegisterWidth;
 | 
| -
 | 
| -  class PolicyField : public BitField<Policy, kPolicyShift, kPolicyWidth> { };
 | 
| -
 | 
| -  class LifetimeField
 | 
| -      : public BitField<Lifetime, kLifetimeShift, kLifetimeWidth> {
 | 
| -  };
 | 
| -
 | 
| -  class VirtualRegisterField
 | 
| -      : public BitField<unsigned,
 | 
| -                        kVirtualRegisterShift,
 | 
| -                        kVirtualRegisterWidth> {
 | 
| -  };
 | 
| -
 | 
| -  static const int kMaxVirtualRegisters = 1 << (kVirtualRegisterWidth + 1);
 | 
| -  static const int kMaxFixedIndices = 128;
 | 
| -
 | 
| -  bool HasIgnorePolicy() const { return policy() == IGNORE; }
 | 
| -  bool HasNoPolicy() const { return policy() == NONE; }
 | 
| -  bool HasAnyPolicy() const {
 | 
| -    return policy() == ANY;
 | 
| -  }
 | 
| -  bool HasFixedPolicy() const {
 | 
| -    return policy() == FIXED_REGISTER ||
 | 
| -        policy() == FIXED_DOUBLE_REGISTER ||
 | 
| -        policy() == FIXED_SLOT;
 | 
| -  }
 | 
| -  bool HasRegisterPolicy() const {
 | 
| -    return policy() == WRITABLE_REGISTER || policy() == MUST_HAVE_REGISTER;
 | 
| -  }
 | 
| -  bool HasSameAsInputPolicy() const {
 | 
| -    return policy() == SAME_AS_FIRST_INPUT;
 | 
| -  }
 | 
| -  Policy policy() const { return PolicyField::decode(value_); }
 | 
| -  void set_policy(Policy policy) {
 | 
| -    value_ &= ~PolicyField::mask();
 | 
| -    value_ |= PolicyField::encode(policy);
 | 
| -  }
 | 
| -  int fixed_index() const {
 | 
| -    return static_cast<int>(value_) >> kFixedIndexShift;
 | 
| -  }
 | 
| -
 | 
| -  unsigned virtual_register() const {
 | 
| -    return VirtualRegisterField::decode(value_);
 | 
| -  }
 | 
| -
 | 
| -  void set_virtual_register(unsigned id) {
 | 
| -    value_ &= ~VirtualRegisterField::mask();
 | 
| -    value_ |= VirtualRegisterField::encode(id);
 | 
| -  }
 | 
| -
 | 
| -  LUnallocated* CopyUnconstrained() {
 | 
| -    LUnallocated* result = new LUnallocated(ANY);
 | 
| -    result->set_virtual_register(virtual_register());
 | 
| -    return result;
 | 
| -  }
 | 
| -
 | 
| -  static LUnallocated* cast(LOperand* op) {
 | 
| -    ASSERT(op->IsUnallocated());
 | 
| -    return reinterpret_cast<LUnallocated*>(op);
 | 
| -  }
 | 
| -
 | 
| -  bool IsUsedAtStart() {
 | 
| -    return LifetimeField::decode(value_) == USED_AT_START;
 | 
| -  }
 | 
| -
 | 
| - private:
 | 
| -  void Initialize(Policy policy, int fixed_index, Lifetime lifetime) {
 | 
| -    value_ |= PolicyField::encode(policy);
 | 
| -    value_ |= LifetimeField::encode(lifetime);
 | 
| -    value_ |= fixed_index << kFixedIndexShift;
 | 
| -    ASSERT(this->fixed_index() == fixed_index);
 | 
| -  }
 | 
| -};
 | 
| -
 | 
| -
 | 
| -class LMoveOperands BASE_EMBEDDED {
 | 
| - public:
 | 
| -  LMoveOperands(LOperand* source, LOperand* destination)
 | 
| -      : source_(source), destination_(destination) {
 | 
| -  }
 | 
| -
 | 
| -  LOperand* source() const { return source_; }
 | 
| -  void set_source(LOperand* operand) { source_ = operand; }
 | 
| -
 | 
| -  LOperand* destination() const { return destination_; }
 | 
| -  void set_destination(LOperand* operand) { destination_ = operand; }
 | 
| -
 | 
| -  // The gap resolver marks moves as "in-progress" by clearing the
 | 
| -  // destination (but not the source).
 | 
| -  bool IsPending() const {
 | 
| -    return destination_ == NULL && source_ != NULL;
 | 
| -  }
 | 
| -
 | 
| -  // True if this move a move into the given destination operand.
 | 
| -  bool Blocks(LOperand* operand) const {
 | 
| -    return !IsEliminated() && source()->Equals(operand);
 | 
| -  }
 | 
| -
 | 
| -  // A move is redundant if it's been eliminated, if its source and
 | 
| -  // destination are the same, or if its destination is unneeded.
 | 
| -  bool IsRedundant() const {
 | 
| -    return IsEliminated() || source_->Equals(destination_) || IsIgnored();
 | 
| -  }
 | 
| -
 | 
| -  bool IsIgnored() const {
 | 
| -    return destination_ != NULL &&
 | 
| -        destination_->IsUnallocated() &&
 | 
| -        LUnallocated::cast(destination_)->HasIgnorePolicy();
 | 
| -  }
 | 
| -
 | 
| -  // We clear both operands to indicate move that's been eliminated.
 | 
| -  void Eliminate() { source_ = destination_ = NULL; }
 | 
| -  bool IsEliminated() const {
 | 
| -    ASSERT(source_ != NULL || destination_ == NULL);
 | 
| -    return source_ == NULL;
 | 
| -  }
 | 
| -
 | 
| - private:
 | 
| -  LOperand* source_;
 | 
| -  LOperand* destination_;
 | 
| -};
 | 
| -
 | 
| -
 | 
| -class LConstantOperand: public LOperand {
 | 
| - public:
 | 
| -  static LConstantOperand* Create(int index) {
 | 
| -    ASSERT(index >= 0);
 | 
| -    if (index < kNumCachedOperands) return &cache[index];
 | 
| -    return new LConstantOperand(index);
 | 
| -  }
 | 
| -
 | 
| -  static LConstantOperand* cast(LOperand* op) {
 | 
| -    ASSERT(op->IsConstantOperand());
 | 
| -    return reinterpret_cast<LConstantOperand*>(op);
 | 
| -  }
 | 
| -
 | 
| -  static void SetupCache();
 | 
| -
 | 
| - private:
 | 
| -  static const int kNumCachedOperands = 128;
 | 
| -  static LConstantOperand cache[];
 | 
| -
 | 
| -  LConstantOperand() : LOperand() { }
 | 
| -  explicit LConstantOperand(int index) : LOperand(CONSTANT_OPERAND, index) { }
 | 
| -};
 | 
| -
 | 
| -
 | 
| -class LArgument: public LOperand {
 | 
| - public:
 | 
| -  explicit LArgument(int index) : LOperand(ARGUMENT, index) { }
 | 
| -
 | 
| -  static LArgument* cast(LOperand* op) {
 | 
| -    ASSERT(op->IsArgument());
 | 
| -    return reinterpret_cast<LArgument*>(op);
 | 
| -  }
 | 
| -};
 | 
| -
 | 
| -
 | 
| -class LStackSlot: public LOperand {
 | 
| - public:
 | 
| -  static LStackSlot* Create(int index) {
 | 
| -    ASSERT(index >= 0);
 | 
| -    if (index < kNumCachedOperands) return &cache[index];
 | 
| -    return new LStackSlot(index);
 | 
| -  }
 | 
| -
 | 
| -  static LStackSlot* cast(LOperand* op) {
 | 
| -    ASSERT(op->IsStackSlot());
 | 
| -    return reinterpret_cast<LStackSlot*>(op);
 | 
| -  }
 | 
| -
 | 
| -  static void SetupCache();
 | 
| -
 | 
| - private:
 | 
| -  static const int kNumCachedOperands = 128;
 | 
| -  static LStackSlot cache[];
 | 
| -
 | 
| -  LStackSlot() : LOperand() { }
 | 
| -  explicit LStackSlot(int index) : LOperand(STACK_SLOT, index) { }
 | 
| -};
 | 
| -
 | 
| -
 | 
| -class LDoubleStackSlot: public LOperand {
 | 
| - public:
 | 
| -  static LDoubleStackSlot* Create(int index) {
 | 
| -    ASSERT(index >= 0);
 | 
| -    if (index < kNumCachedOperands) return &cache[index];
 | 
| -    return new LDoubleStackSlot(index);
 | 
| -  }
 | 
| -
 | 
| -  static LDoubleStackSlot* cast(LOperand* op) {
 | 
| -    ASSERT(op->IsStackSlot());
 | 
| -    return reinterpret_cast<LDoubleStackSlot*>(op);
 | 
| -  }
 | 
| -
 | 
| -  static void SetupCache();
 | 
| -
 | 
| - private:
 | 
| -  static const int kNumCachedOperands = 128;
 | 
| -  static LDoubleStackSlot cache[];
 | 
| -
 | 
| -  LDoubleStackSlot() : LOperand() { }
 | 
| -  explicit LDoubleStackSlot(int index) : LOperand(DOUBLE_STACK_SLOT, index) { }
 | 
| -};
 | 
| -
 | 
| -
 | 
| -class LRegister: public LOperand {
 | 
| - public:
 | 
| -  static LRegister* Create(int index) {
 | 
| -    ASSERT(index >= 0);
 | 
| -    if (index < kNumCachedOperands) return &cache[index];
 | 
| -    return new LRegister(index);
 | 
| -  }
 | 
| -
 | 
| -  static LRegister* cast(LOperand* op) {
 | 
| -    ASSERT(op->IsRegister());
 | 
| -    return reinterpret_cast<LRegister*>(op);
 | 
| -  }
 | 
| -
 | 
| -  static void SetupCache();
 | 
| -
 | 
| - private:
 | 
| -  static const int kNumCachedOperands = 16;
 | 
| -  static LRegister cache[];
 | 
| -
 | 
| -  LRegister() : LOperand() { }
 | 
| -  explicit LRegister(int index) : LOperand(REGISTER, index) { }
 | 
| -};
 | 
| -
 | 
| -
 | 
| -class LDoubleRegister: public LOperand {
 | 
| - public:
 | 
| -  static LDoubleRegister* Create(int index) {
 | 
| -    ASSERT(index >= 0);
 | 
| -    if (index < kNumCachedOperands) return &cache[index];
 | 
| -    return new LDoubleRegister(index);
 | 
| -  }
 | 
| -
 | 
| -  static LDoubleRegister* cast(LOperand* op) {
 | 
| -    ASSERT(op->IsDoubleRegister());
 | 
| -    return reinterpret_cast<LDoubleRegister*>(op);
 | 
| -  }
 | 
| -
 | 
| -  static void SetupCache();
 | 
| -
 | 
| - private:
 | 
| -  static const int kNumCachedOperands = 16;
 | 
| -  static LDoubleRegister cache[];
 | 
| -
 | 
| -  LDoubleRegister() : LOperand() { }
 | 
| -  explicit LDoubleRegister(int index) : LOperand(DOUBLE_REGISTER, index) { }
 | 
| -};
 | 
| -
 | 
| -
 | 
|  // A register-allocator view of a Lithium instruction. It contains the id of
 | 
|  // the output operand and a list of input operand uses.
 | 
|  class InstructionSummary: public ZoneObject {
 | 
| @@ -588,27 +241,14 @@
 | 
|  // Representation of a use position.
 | 
|  class UsePosition: public ZoneObject {
 | 
|   public:
 | 
| -  UsePosition(LifetimePosition pos, LOperand* operand)
 | 
| -      : operand_(operand),
 | 
| -        hint_(NULL),
 | 
| -        pos_(pos),
 | 
| -        next_(NULL),
 | 
| -        requires_reg_(false),
 | 
| -        register_beneficial_(true) {
 | 
| -    if (operand_ != NULL && operand_->IsUnallocated()) {
 | 
| -      LUnallocated* unalloc = LUnallocated::cast(operand_);
 | 
| -      requires_reg_ = unalloc->HasRegisterPolicy();
 | 
| -      register_beneficial_ = !unalloc->HasAnyPolicy();
 | 
| -    }
 | 
| -    ASSERT(pos_.IsValid());
 | 
| -  }
 | 
| +  UsePosition(LifetimePosition pos, LOperand* operand);
 | 
|  
 | 
|    LOperand* operand() const { return operand_; }
 | 
|    bool HasOperand() const { return operand_ != NULL; }
 | 
|  
 | 
|    LOperand* hint() const { return hint_; }
 | 
|    void set_hint(LOperand* hint) { hint_ = hint; }
 | 
| -  bool HasHint() const { return hint_ != NULL && !hint_->IsUnallocated(); }
 | 
| +  bool HasHint() const;
 | 
|    bool RequiresRegister() const;
 | 
|    bool RegisterIsBeneficial() const;
 | 
|  
 | 
| @@ -634,21 +274,7 @@
 | 
|   public:
 | 
|    static const int kInvalidAssignment = 0x7fffffff;
 | 
|  
 | 
| -  explicit LiveRange(int id)
 | 
| -      : id_(id),
 | 
| -        spilled_(false),
 | 
| -        assigned_register_(kInvalidAssignment),
 | 
| -        assigned_register_kind_(NONE),
 | 
| -        last_interval_(NULL),
 | 
| -        first_interval_(NULL),
 | 
| -        first_pos_(NULL),
 | 
| -        parent_(NULL),
 | 
| -        next_(NULL),
 | 
| -        current_interval_(NULL),
 | 
| -        last_processed_use_(NULL),
 | 
| -        spill_start_index_(kMaxInt) {
 | 
| -    spill_operand_ = new LUnallocated(LUnallocated::IGNORE);
 | 
| -  }
 | 
| +  explicit LiveRange(int id);
 | 
|  
 | 
|    UseInterval* first_interval() const { return first_interval_; }
 | 
|    UsePosition* first_pos() const { return first_pos_; }
 | 
| @@ -663,19 +289,8 @@
 | 
|    LOperand* CreateAssignedOperand();
 | 
|    int assigned_register() const { return assigned_register_; }
 | 
|    int spill_start_index() const { return spill_start_index_; }
 | 
| -  void set_assigned_register(int reg, RegisterKind register_kind) {
 | 
| -    ASSERT(!HasRegisterAssigned() && !IsSpilled());
 | 
| -    assigned_register_ = reg;
 | 
| -    assigned_register_kind_ = register_kind;
 | 
| -    ConvertOperands();
 | 
| -  }
 | 
| -  void MakeSpilled() {
 | 
| -    ASSERT(!IsSpilled());
 | 
| -    ASSERT(TopLevel()->HasAllocatedSpillOperand());
 | 
| -    spilled_ = true;
 | 
| -    assigned_register_ = kInvalidAssignment;
 | 
| -    ConvertOperands();
 | 
| -  }
 | 
| +  void set_assigned_register(int reg, RegisterKind register_kind);
 | 
| +  void MakeSpilled();
 | 
|  
 | 
|    // Returns use position in this live range that follows both start
 | 
|    // and last processed use position.
 | 
| @@ -724,17 +339,9 @@
 | 
|      return last_interval_->end();
 | 
|    }
 | 
|  
 | 
| -  bool HasAllocatedSpillOperand() const {
 | 
| -    return spill_operand_ != NULL && !spill_operand_->IsUnallocated();
 | 
| -  }
 | 
| -
 | 
| +  bool HasAllocatedSpillOperand() const;
 | 
|    LOperand* GetSpillOperand() const { return spill_operand_; }
 | 
| -  void SetSpillOperand(LOperand* operand) {
 | 
| -    ASSERT(!operand->IsUnallocated());
 | 
| -    ASSERT(spill_operand_ != NULL);
 | 
| -    ASSERT(spill_operand_->IsUnallocated());
 | 
| -    spill_operand_->ConvertTo(operand->kind(), operand->index());
 | 
| -  }
 | 
| +  void SetSpillOperand(LOperand* operand);
 | 
|  
 | 
|    void SetSpillStartIndex(int start) {
 | 
|      spill_start_index_ = Min(start, spill_start_index_);
 | 
| 
 |