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, |