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