Chromium Code Reviews| 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 static const intptr_t kInvalidLocation = 0; | |
| 26 | |
| 27 // Contant payload can overlap with kind field so Kind values | |
| 28 // have to be choosen in a way that their last 2 bits are never | |
| 29 // the same as kConstant. | |
| 24 enum Kind { | 30 enum Kind { |
| 25 kInvalid, | 31 kInvalid = 0, |
| 32 | |
| 33 kConstant = 1, | |
| 26 | 34 |
| 27 // Unallocated location represents a location that is not fixed and can be | 35 // Unallocated location represents a location that is not fixed and can be |
| 28 // allocated by a register allocator. Each unallocated location has | 36 // allocated by a register allocator. Each unallocated location has |
| 29 // a policy that specifies what kind of location is suitable. | 37 // a policy that specifies what kind of location is suitable. |
| 30 kUnallocated, | 38 kUnallocated = 2, |
| 31 | 39 |
| 32 // Register location represents a fixed register. | 40 // Register location represents a fixed register. |
| 33 kRegister | 41 kRegister = 3 |
| 34 }; | 42 }; |
| 35 | 43 |
| 36 Location() : value_(KindField::encode(kInvalid)) { } | 44 Location() : value_(kInvalidLocation) { |
| 45 ASSERT(IsInvalid()); | |
| 46 } | |
| 37 | 47 |
| 38 Kind kind() const { return KindField::decode(value_); } | 48 bool IsInvalid() const { |
| 49 return value_ == 0; | |
|
srdjan
2012/07/10 23:27:54
s/0/kInvalidLocation/
Vyacheslav Egorov (Google)
2012/07/11 13:27:58
Done.
| |
| 50 } | |
| 51 | |
| 52 // Constants. | |
| 53 static const intptr_t kConstantMask = 0x3; | |
|
srdjan
2012/07/10 23:27:54
Eventually move this definition between the commen
Vyacheslav Egorov (Google)
2012/07/11 13:27:58
Done.
| |
| 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<intptr_t>(&obj) | kConstant); | |
|
srdjan
2012/07/10 23:27:54
Why no uword instead of intptr_t?
Vyacheslav Egorov (Google)
2012/07/11 13:27:58
Fixed! Thanks.
| |
| 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 bool Equals(Location other) const { | |
| 122 return value_ == other.value_; | |
|
srdjan
2012/07/10 23:27:54
This does not work for kConstant. Should two const
Vyacheslav Egorov (Google)
2012/07/11 13:27:58
Added a comment and assertion. Constants are reall
| |
| 123 } | |
| 124 | |
| 81 private: | 125 private: |
| 126 explicit Location(intptr_t value) : value_(value) { } | |
|
srdjan
2012/07/10 23:27:54
Why not uword value?
Vyacheslav Egorov (Google)
2012/07/11 13:27:58
Mea culpa! Compiler did not complain and I already
| |
| 127 | |
| 82 Location(Kind kind, uword payload) | 128 Location(Kind kind, uword payload) |
| 83 : value_(KindField::encode(kind) | PayloadField::encode(payload)) { } | 129 : value_(KindField::encode(kind) | PayloadField::encode(payload)) { } |
| 84 | 130 |
| 85 uword payload() const { | 131 uword payload() const { |
| 86 return PayloadField::decode(value_); | 132 return PayloadField::decode(value_); |
| 87 } | 133 } |
| 88 | 134 |
| 135 // If current location is constant might return something that | |
| 136 // is not equal to any Kind. | |
| 137 Kind kind() const { | |
| 138 return KindField::decode(value_); | |
| 139 } | |
| 140 | |
| 89 typedef BitField<Kind, 0, 2> KindField; | 141 typedef BitField<Kind, 0, 2> KindField; |
| 90 typedef BitField<uword, 2, kWordSize * kBitsPerByte - 2> PayloadField; | 142 typedef BitField<uword, 2, kWordSize * kBitsPerByte - 2> PayloadField; |
| 91 | 143 |
| 92 // Layout for kUnallocated locations payload. | 144 // Layout for kUnallocated locations payload. |
| 93 typedef BitField<Policy, 0, 1> PolicyField; | 145 typedef BitField<Policy, 0, 1> PolicyField; |
| 94 | 146 |
| 95 // TODO(vegorov): choose fixed size for this field. | 147 // TODO(vegorov): choose fixed size for this field. |
| 96 uword value_; | 148 uword value_; |
|
srdjan
2012/07/10 23:27:54
Explain that this can be Kind or an encoded Object
Vyacheslav Egorov (Google)
2012/07/11 13:27:58
Done.
| |
| 97 }; | 149 }; |
| 98 | 150 |
| 99 | 151 |
| 100 // Specification of locations for inputs and output. | 152 // Specification of locations for inputs and output. |
| 101 class LocationSummary : public ZoneAllocated { | 153 class LocationSummary : public ZoneAllocated { |
| 102 public: | 154 public: |
| 103 enum ContainsCall { | 155 enum ContainsCall { |
| 104 kNoCall, | 156 kNoCall, |
| 105 kCall, | 157 kCall, |
| 106 }; | 158 }; |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 129 } | 181 } |
| 130 | 182 |
| 131 intptr_t input_count() const { | 183 intptr_t input_count() const { |
| 132 return input_locations_.length(); | 184 return input_locations_.length(); |
| 133 } | 185 } |
| 134 | 186 |
| 135 Location in(intptr_t index) const { | 187 Location in(intptr_t index) const { |
| 136 return input_locations_[index]; | 188 return input_locations_[index]; |
| 137 } | 189 } |
| 138 | 190 |
| 191 Location* in_slot(intptr_t index) { | |
| 192 return &input_locations_[index]; | |
| 193 } | |
| 194 | |
| 139 void set_in(intptr_t index, Location loc) { | 195 void set_in(intptr_t index, Location loc) { |
| 140 input_locations_[index] = loc; | 196 input_locations_[index] = loc; |
| 141 } | 197 } |
| 142 | 198 |
| 143 intptr_t temp_count() const { | 199 intptr_t temp_count() const { |
| 144 return temp_locations_.length(); | 200 return temp_locations_.length(); |
| 145 } | 201 } |
| 146 | 202 |
| 147 Location temp(intptr_t index) const { | 203 Location temp(intptr_t index) const { |
| 148 return temp_locations_[index]; | 204 return temp_locations_[index]; |
| 149 } | 205 } |
| 150 | 206 |
| 207 Location* temp_slot(intptr_t index) { | |
| 208 return &temp_locations_[index]; | |
| 209 } | |
| 210 | |
| 151 void set_temp(intptr_t index, Location loc) { | 211 void set_temp(intptr_t index, Location loc) { |
| 152 temp_locations_[index] = loc; | 212 temp_locations_[index] = loc; |
| 153 } | 213 } |
| 154 | 214 |
| 155 Location out() const { | 215 Location out() const { |
| 156 return output_location_; | 216 return output_location_; |
| 157 } | 217 } |
| 158 | 218 |
| 219 Location* out_slot() { | |
| 220 return &output_location_; | |
| 221 } | |
| 222 | |
| 223 | |
| 159 void set_out(Location loc) { | 224 void set_out(Location loc) { |
| 160 output_location_ = loc; | 225 output_location_ = loc; |
| 161 } | 226 } |
| 162 | 227 |
| 163 bool is_call() const { | 228 bool is_call() const { |
| 164 return is_call_; | 229 return is_call_; |
| 165 } | 230 } |
| 166 | 231 |
| 167 // TODO(vegorov): this is a temporary solution. Once we will start removing | 232 // 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 | 233 // comparison operations from the flow graph when they are fused with a branch |
| 169 // we should eliminate this. | 234 // we should eliminate this. |
| 170 bool is_branch() const { | 235 bool is_branch() const { |
| 171 return is_branch_; | 236 return is_branch_; |
| 172 } | 237 } |
| 173 | 238 |
| 239 void PrintTo(BufferFormatter* f) const; | |
| 240 | |
| 174 static LocationSummary* Make(intptr_t input_count, | 241 static LocationSummary* Make(intptr_t input_count, |
| 175 Location out, | 242 Location out, |
| 176 ContainsCall contains_call = kNoCall, | 243 ContainsCall contains_call = kNoCall, |
| 177 ContainsBranch contains_branch = kNoBranch); | 244 ContainsBranch contains_branch = kNoBranch); |
| 178 | 245 |
| 179 private: | 246 private: |
| 180 // TODO(vegorov): replace with ZoneArray. | 247 // TODO(vegorov): replace with ZoneArray. |
| 181 GrowableArray<Location> input_locations_; | 248 GrowableArray<Location> input_locations_; |
| 182 GrowableArray<Location> temp_locations_; | 249 GrowableArray<Location> temp_locations_; |
| 183 Location output_location_; | 250 Location output_location_; |
| 184 | 251 |
| 185 const bool is_call_; | 252 const bool is_call_; |
| 186 const bool is_branch_; | 253 const bool is_branch_; |
| 187 }; | 254 }; |
| 188 | 255 |
| 189 | 256 |
| 190 } // namespace dart | 257 } // namespace dart |
| 191 | 258 |
| 192 #endif // VM_LOCATIONS_H_ | 259 #endif // VM_LOCATIONS_H_ |
| OLD | NEW |