| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_LOCATIONS_H_ | 5 #ifndef VM_LOCATIONS_H_ |
| 6 #define VM_LOCATIONS_H_ | 6 #define VM_LOCATIONS_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
| 10 #include "vm/bitfield.h" | 10 #include "vm/bitfield.h" |
| 11 | 11 |
| 12 namespace dart { | 12 namespace dart { |
| 13 | 13 |
| 14 class BufferFormatter; |
| 14 | 15 |
| 15 // Location objects are used to connect register allocator and code generator. | 16 // Location objects are used to connect register allocator and code generator. |
| 16 // Instruction templates used by code generator have a corresponding | 17 // Instruction templates used by code generator have a corresponding |
| 17 // LocationSummary object which specifies expected location for every input | 18 // LocationSummary object which specifies expected location for every input |
| 18 // and output. | 19 // and output. |
| 19 // Each location is encoded as a single word: low 2 bits denote location kind, | 20 // Each location is encoded as a single word: low 2 bits denote location kind, |
| 20 // rest is kind specific location payload e.g. for REGISTER kind payload is | 21 // rest is kind specific location payload e.g. for REGISTER kind payload is |
| 21 // register code (value of the Register enumeration). | 22 // register code (value of the Register enumeration). |
| 22 class Location : public ValueObject { | 23 class Location : public ValueObject { |
| 23 public: | 24 public: |
| 25 // Constant payload can overlap with kind field so Kind values |
| 26 // have to be chosen in a way that their last 2 bits are never |
| 27 // the same as kConstant. |
| 24 enum Kind { | 28 enum Kind { |
| 25 kInvalid, | 29 kInvalid = 0, |
| 30 |
| 31 kConstant = 1, |
| 26 | 32 |
| 27 // Unallocated location represents a location that is not fixed and can be | 33 // Unallocated location represents a location that is not fixed and can be |
| 28 // allocated by a register allocator. Each unallocated location has | 34 // allocated by a register allocator. Each unallocated location has |
| 29 // a policy that specifies what kind of location is suitable. | 35 // a policy that specifies what kind of location is suitable. |
| 30 kUnallocated, | 36 kUnallocated = 2, |
| 31 | 37 |
| 32 // Register location represents a fixed register. | 38 // Register location represents a fixed register. |
| 33 kRegister | 39 kRegister = 3 |
| 34 }; | 40 }; |
| 35 | 41 |
| 36 Location() : value_(KindField::encode(kInvalid)) { } | 42 static const uword kInvalidLocation = 0; |
| 43 static const uword kConstantMask = 0x3; |
| 37 | 44 |
| 38 Kind kind() const { return KindField::decode(value_); } | 45 Location() : value_(kInvalidLocation) { |
| 46 ASSERT(IsInvalid()); |
| 47 } |
| 48 |
| 49 bool IsInvalid() const { |
| 50 return value_ == kInvalidLocation; |
| 51 } |
| 52 |
| 53 // Constants. |
| 54 bool IsConstant() const { |
| 55 ASSERT((kConstant & kConstantMask) == kConstant); |
| 56 return (value_ & kConstantMask) == kConstant; |
| 57 } |
| 58 |
| 59 static Location Constant(const Object& obj) { |
| 60 Location loc(reinterpret_cast<uword>(&obj) | kConstant); |
| 61 ASSERT(&obj == &loc.constant()); |
| 62 return loc; |
| 63 } |
| 64 |
| 65 const Object& constant() { |
| 66 ASSERT(IsConstant()); |
| 67 return *reinterpret_cast<const Object*>(value_ & ~kConstantMask); |
| 68 } |
| 39 | 69 |
| 40 // Unallocated locations. | 70 // Unallocated locations. |
| 41 enum Policy { | 71 enum Policy { |
| 42 kRequiresRegister, | 72 kRequiresRegister, |
| 43 kSameAsFirstInput, | 73 kSameAsFirstInput, |
| 44 }; | 74 }; |
| 45 | 75 |
| 76 bool IsUnallocated() const { |
| 77 return kind() == kUnallocated; |
| 78 } |
| 79 |
| 46 static Location UnallocatedLocation(Policy policy) { | 80 static Location UnallocatedLocation(Policy policy) { |
| 47 return Location(kUnallocated, PolicyField::encode(policy)); | 81 return Location(kUnallocated, PolicyField::encode(policy)); |
| 48 } | 82 } |
| 49 | 83 |
| 50 // Any free register is suitable to replace this unallocated location. | 84 // Any free register is suitable to replace this unallocated location. |
| 51 static Location RequiresRegister() { | 85 static Location RequiresRegister() { |
| 52 return UnallocatedLocation(kRequiresRegister); | 86 return UnallocatedLocation(kRequiresRegister); |
| 53 } | 87 } |
| 54 | 88 |
| 55 // The location of the first input to the instruction will be | 89 // The location of the first input to the instruction will be |
| 56 // used to replace this unallocated location. | 90 // used to replace this unallocated location. |
| 57 static Location SameAsFirstInput() { | 91 static Location SameAsFirstInput() { |
| 58 return UnallocatedLocation(kSameAsFirstInput); | 92 return UnallocatedLocation(kSameAsFirstInput); |
| 59 } | 93 } |
| 60 | 94 |
| 61 // Empty location. Used if there the location should be ignored. | 95 // Empty location. Used if there the location should be ignored. |
| 62 static Location NoLocation() { | 96 static Location NoLocation() { |
| 63 return Location(); | 97 return Location(); |
| 64 } | 98 } |
| 65 | 99 |
| 66 Policy policy() const { | 100 Policy policy() const { |
| 67 ASSERT(kind() == kUnallocated); | 101 ASSERT(IsUnallocated()); |
| 68 return PolicyField::decode(payload()); | 102 return PolicyField::decode(payload()); |
| 69 } | 103 } |
| 70 | 104 |
| 71 // Register locations. | 105 // Register locations. |
| 72 static Location RegisterLocation(Register reg) { | 106 static Location RegisterLocation(Register reg) { |
| 73 return Location(kRegister, static_cast<uword>(reg)); | 107 return Location(kRegister, static_cast<uword>(reg)); |
| 74 } | 108 } |
| 75 | 109 |
| 110 bool IsRegister() const { |
| 111 return kind() == kRegister; |
| 112 } |
| 113 |
| 76 Register reg() const { | 114 Register reg() const { |
| 77 ASSERT(kind() == kRegister); | 115 ASSERT(IsRegister()); |
| 78 return static_cast<Register>(payload()); | 116 return static_cast<Register>(payload()); |
| 79 } | 117 } |
| 80 | 118 |
| 119 const char* Name() const; |
| 120 |
| 121 // Compare two non-constant locations. |
| 122 bool Equals(Location other) const { |
| 123 ASSERT(!IsConstant() && !other.IsConstant()); |
| 124 return value_ == other.value_; |
| 125 } |
| 126 |
| 81 private: | 127 private: |
| 128 explicit Location(uword value) : value_(value) { } |
| 129 |
| 82 Location(Kind kind, uword payload) | 130 Location(Kind kind, uword payload) |
| 83 : value_(KindField::encode(kind) | PayloadField::encode(payload)) { } | 131 : value_(KindField::encode(kind) | PayloadField::encode(payload)) { } |
| 84 | 132 |
| 85 uword payload() const { | 133 uword payload() const { |
| 86 return PayloadField::decode(value_); | 134 return PayloadField::decode(value_); |
| 87 } | 135 } |
| 88 | 136 |
| 137 // If current location is constant might return something that |
| 138 // is not equal to any Kind. |
| 139 Kind kind() const { |
| 140 return KindField::decode(value_); |
| 141 } |
| 142 |
| 89 typedef BitField<Kind, 0, 2> KindField; | 143 typedef BitField<Kind, 0, 2> KindField; |
| 90 typedef BitField<uword, 2, kWordSize * kBitsPerByte - 2> PayloadField; | 144 typedef BitField<uword, 2, kWordSize * kBitsPerByte - 2> PayloadField; |
| 91 | 145 |
| 92 // Layout for kUnallocated locations payload. | 146 // Layout for kUnallocated locations payload. |
| 93 typedef BitField<Policy, 0, 1> PolicyField; | 147 typedef BitField<Policy, 0, 1> PolicyField; |
| 94 | 148 |
| 95 // TODO(vegorov): choose fixed size for this field. | 149 // Location either contains kind and payload fields or a tagged handle for |
| 150 // a constant locations. Values of enumeration Kind are selected in such a |
| 151 // way that none of them can be interpreted as a kConstant tag. |
| 96 uword value_; | 152 uword value_; |
| 97 }; | 153 }; |
| 98 | 154 |
| 99 | 155 |
| 100 // Specification of locations for inputs and output. | 156 // Specification of locations for inputs and output. |
| 101 class LocationSummary : public ZoneAllocated { | 157 class LocationSummary : public ZoneAllocated { |
| 102 public: | 158 public: |
| 103 enum ContainsCall { | 159 enum ContainsCall { |
| 104 kNoCall, | 160 kNoCall, |
| 105 kCall, | 161 kCall, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 129 } | 185 } |
| 130 | 186 |
| 131 intptr_t input_count() const { | 187 intptr_t input_count() const { |
| 132 return input_locations_.length(); | 188 return input_locations_.length(); |
| 133 } | 189 } |
| 134 | 190 |
| 135 Location in(intptr_t index) const { | 191 Location in(intptr_t index) const { |
| 136 return input_locations_[index]; | 192 return input_locations_[index]; |
| 137 } | 193 } |
| 138 | 194 |
| 195 Location* in_slot(intptr_t index) { |
| 196 return &input_locations_[index]; |
| 197 } |
| 198 |
| 139 void set_in(intptr_t index, Location loc) { | 199 void set_in(intptr_t index, Location loc) { |
| 140 input_locations_[index] = loc; | 200 input_locations_[index] = loc; |
| 141 } | 201 } |
| 142 | 202 |
| 143 intptr_t temp_count() const { | 203 intptr_t temp_count() const { |
| 144 return temp_locations_.length(); | 204 return temp_locations_.length(); |
| 145 } | 205 } |
| 146 | 206 |
| 147 Location temp(intptr_t index) const { | 207 Location temp(intptr_t index) const { |
| 148 return temp_locations_[index]; | 208 return temp_locations_[index]; |
| 149 } | 209 } |
| 150 | 210 |
| 211 Location* temp_slot(intptr_t index) { |
| 212 return &temp_locations_[index]; |
| 213 } |
| 214 |
| 151 void set_temp(intptr_t index, Location loc) { | 215 void set_temp(intptr_t index, Location loc) { |
| 152 temp_locations_[index] = loc; | 216 temp_locations_[index] = loc; |
| 153 } | 217 } |
| 154 | 218 |
| 155 Location out() const { | 219 Location out() const { |
| 156 return output_location_; | 220 return output_location_; |
| 157 } | 221 } |
| 158 | 222 |
| 223 Location* out_slot() { |
| 224 return &output_location_; |
| 225 } |
| 226 |
| 227 |
| 159 void set_out(Location loc) { | 228 void set_out(Location loc) { |
| 160 output_location_ = loc; | 229 output_location_ = loc; |
| 161 } | 230 } |
| 162 | 231 |
| 163 bool is_call() const { | 232 bool is_call() const { |
| 164 return is_call_; | 233 return is_call_; |
| 165 } | 234 } |
| 166 | 235 |
| 167 // TODO(vegorov): this is a temporary solution. Once we will start removing | 236 // TODO(vegorov): this is a temporary solution. Once we will start removing |
| 168 // comparison operations from the flow graph when they are fused with a branch | 237 // comparison operations from the flow graph when they are fused with a branch |
| 169 // we should eliminate this. | 238 // we should eliminate this. |
| 170 bool is_branch() const { | 239 bool is_branch() const { |
| 171 return is_branch_; | 240 return is_branch_; |
| 172 } | 241 } |
| 173 | 242 |
| 243 void PrintTo(BufferFormatter* f) const; |
| 244 |
| 174 static LocationSummary* Make(intptr_t input_count, | 245 static LocationSummary* Make(intptr_t input_count, |
| 175 Location out, | 246 Location out, |
| 176 ContainsCall contains_call = kNoCall, | 247 ContainsCall contains_call = kNoCall, |
| 177 ContainsBranch contains_branch = kNoBranch); | 248 ContainsBranch contains_branch = kNoBranch); |
| 178 | 249 |
| 179 private: | 250 private: |
| 180 // TODO(vegorov): replace with ZoneArray. | 251 // TODO(vegorov): replace with ZoneArray. |
| 181 GrowableArray<Location> input_locations_; | 252 GrowableArray<Location> input_locations_; |
| 182 GrowableArray<Location> temp_locations_; | 253 GrowableArray<Location> temp_locations_; |
| 183 Location output_location_; | 254 Location output_location_; |
| 184 | 255 |
| 185 const bool is_call_; | 256 const bool is_call_; |
| 186 const bool is_branch_; | 257 const bool is_branch_; |
| 187 }; | 258 }; |
| 188 | 259 |
| 189 | 260 |
| 190 } // namespace dart | 261 } // namespace dart |
| 191 | 262 |
| 192 #endif // VM_LOCATIONS_H_ | 263 #endif // VM_LOCATIONS_H_ |
| OLD | NEW |