| Index: runtime/vm/locations.h
 | 
| diff --git a/runtime/vm/locations.h b/runtime/vm/locations.h
 | 
| index 8a869b3d0c2f416673896692ea14f916571122b9..8336d2712b2fb9f676824fb1dffb20d8017b01b0 100644
 | 
| --- a/runtime/vm/locations.h
 | 
| +++ b/runtime/vm/locations.h
 | 
| @@ -11,6 +11,7 @@
 | 
|  
 | 
|  namespace dart {
 | 
|  
 | 
| +class BufferFormatter;
 | 
|  
 | 
|  // Location objects are used to connect register allocator and code generator.
 | 
|  // Instruction templates used by code generator have a corresponding
 | 
| @@ -21,21 +22,50 @@ namespace dart {
 | 
|  // register code (value of the Register enumeration).
 | 
|  class Location : public ValueObject {
 | 
|   public:
 | 
| +  // Constant payload can overlap with kind field so Kind values
 | 
| +  // have to be chosen in a way that their last 2 bits are never
 | 
| +  // the same as kConstant.
 | 
|    enum Kind {
 | 
| -    kInvalid,
 | 
| +    kInvalid = 0,
 | 
| +
 | 
| +    kConstant = 1,
 | 
|  
 | 
|      // Unallocated location represents a location that is not fixed and can be
 | 
|      // allocated by a register allocator.  Each unallocated location has
 | 
|      // a policy that specifies what kind of location is suitable.
 | 
| -    kUnallocated,
 | 
| +    kUnallocated = 2,
 | 
|  
 | 
|      // Register location represents a fixed register.
 | 
| -    kRegister
 | 
| +    kRegister = 3
 | 
|    };
 | 
|  
 | 
| -  Location() : value_(KindField::encode(kInvalid)) { }
 | 
| +  static const uword kInvalidLocation = 0;
 | 
| +  static const uword kConstantMask = 0x3;
 | 
| +
 | 
| +  Location() : value_(kInvalidLocation) {
 | 
| +    ASSERT(IsInvalid());
 | 
| +  }
 | 
| +
 | 
| +  bool IsInvalid() const {
 | 
| +    return value_ == kInvalidLocation;
 | 
| +  }
 | 
| +
 | 
| +  // Constants.
 | 
| +  bool IsConstant() const {
 | 
| +    ASSERT((kConstant & kConstantMask) == kConstant);
 | 
| +    return (value_ & kConstantMask) == kConstant;
 | 
| +  }
 | 
| +
 | 
| +  static Location Constant(const Object& obj) {
 | 
| +    Location loc(reinterpret_cast<uword>(&obj) | kConstant);
 | 
| +    ASSERT(&obj == &loc.constant());
 | 
| +    return loc;
 | 
| +  }
 | 
|  
 | 
| -  Kind kind() const { return KindField::decode(value_); }
 | 
| +  const Object& constant() {
 | 
| +    ASSERT(IsConstant());
 | 
| +    return *reinterpret_cast<const Object*>(value_ & ~kConstantMask);
 | 
| +  }
 | 
|  
 | 
|    // Unallocated locations.
 | 
|    enum Policy {
 | 
| @@ -43,6 +73,10 @@ class Location : public ValueObject {
 | 
|      kSameAsFirstInput,
 | 
|    };
 | 
|  
 | 
| +  bool IsUnallocated() const {
 | 
| +    return kind() == kUnallocated;
 | 
| +  }
 | 
| +
 | 
|    static Location UnallocatedLocation(Policy policy) {
 | 
|      return Location(kUnallocated, PolicyField::encode(policy));
 | 
|    }
 | 
| @@ -64,7 +98,7 @@ class Location : public ValueObject {
 | 
|    }
 | 
|  
 | 
|    Policy policy() const {
 | 
| -    ASSERT(kind() == kUnallocated);
 | 
| +    ASSERT(IsUnallocated());
 | 
|      return PolicyField::decode(payload());
 | 
|    }
 | 
|  
 | 
| @@ -73,12 +107,26 @@ class Location : public ValueObject {
 | 
|      return Location(kRegister, static_cast<uword>(reg));
 | 
|    }
 | 
|  
 | 
| +  bool IsRegister() const {
 | 
| +    return kind() == kRegister;
 | 
| +  }
 | 
| +
 | 
|    Register reg() const {
 | 
| -    ASSERT(kind() == kRegister);
 | 
| +    ASSERT(IsRegister());
 | 
|      return static_cast<Register>(payload());
 | 
|    }
 | 
|  
 | 
| +  const char* Name() const;
 | 
| +
 | 
| +  // Compare two non-constant locations.
 | 
| +  bool Equals(Location other) const {
 | 
| +    ASSERT(!IsConstant() && !other.IsConstant());
 | 
| +    return value_ == other.value_;
 | 
| +  }
 | 
| +
 | 
|   private:
 | 
| +  explicit Location(uword value) : value_(value) { }
 | 
| +
 | 
|    Location(Kind kind, uword payload)
 | 
|        : value_(KindField::encode(kind) | PayloadField::encode(payload)) { }
 | 
|  
 | 
| @@ -86,13 +134,21 @@ class Location : public ValueObject {
 | 
|      return PayloadField::decode(value_);
 | 
|    }
 | 
|  
 | 
| +  // If current location is constant might return something that
 | 
| +  // is not equal to any Kind.
 | 
| +  Kind kind() const {
 | 
| +    return KindField::decode(value_);
 | 
| +  }
 | 
| +
 | 
|    typedef BitField<Kind, 0, 2> KindField;
 | 
|    typedef BitField<uword, 2, kWordSize * kBitsPerByte - 2> PayloadField;
 | 
|  
 | 
|    // Layout for kUnallocated locations payload.
 | 
|    typedef BitField<Policy, 0, 1> PolicyField;
 | 
|  
 | 
| -  // TODO(vegorov): choose fixed size for this field.
 | 
| +  // Location either contains kind and payload fields or a tagged handle for
 | 
| +  // a constant locations. Values of enumeration Kind are selected in such a
 | 
| +  // way that none of them can be interpreted as a kConstant tag.
 | 
|    uword value_;
 | 
|  };
 | 
|  
 | 
| @@ -136,6 +192,10 @@ class LocationSummary : public ZoneAllocated {
 | 
|      return input_locations_[index];
 | 
|    }
 | 
|  
 | 
| +  Location* in_slot(intptr_t index) {
 | 
| +    return &input_locations_[index];
 | 
| +  }
 | 
| +
 | 
|    void set_in(intptr_t index, Location loc) {
 | 
|      input_locations_[index] = loc;
 | 
|    }
 | 
| @@ -148,6 +208,10 @@ class LocationSummary : public ZoneAllocated {
 | 
|      return temp_locations_[index];
 | 
|    }
 | 
|  
 | 
| +  Location* temp_slot(intptr_t index) {
 | 
| +    return &temp_locations_[index];
 | 
| +  }
 | 
| +
 | 
|    void set_temp(intptr_t index, Location loc) {
 | 
|      temp_locations_[index] = loc;
 | 
|    }
 | 
| @@ -156,6 +220,11 @@ class LocationSummary : public ZoneAllocated {
 | 
|      return output_location_;
 | 
|    }
 | 
|  
 | 
| +  Location* out_slot() {
 | 
| +    return &output_location_;
 | 
| +  }
 | 
| +
 | 
| +
 | 
|    void set_out(Location loc) {
 | 
|      output_location_ = loc;
 | 
|    }
 | 
| @@ -171,6 +240,8 @@ class LocationSummary : public ZoneAllocated {
 | 
|      return is_branch_;
 | 
|    }
 | 
|  
 | 
| +  void PrintTo(BufferFormatter* f) const;
 | 
| +
 | 
|    static LocationSummary* Make(intptr_t input_count,
 | 
|                                 Location out,
 | 
|                                 ContainsCall contains_call = kNoCall,
 | 
| 
 |