| 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" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 // Number of bits required to encode Kind value. | 28 // Number of bits required to encode Kind value. |
| 29 kBitsForKind = 3, | 29 kBitsForKind = 3, |
| 30 kBitsForPayload = kWordSize * kBitsPerByte - kBitsForKind, | 30 kBitsForPayload = kWordSize * kBitsPerByte - kBitsForKind, |
| 31 }; | 31 }; |
| 32 | 32 |
| 33 static const uword kInvalidLocation = 0; | 33 static const uword kInvalidLocation = 0; |
| 34 static const uword kConstantMask = 0x3; | 34 static const uword kConstantMask = 0x3; |
| 35 static const intptr_t kStackIndexBias = | 35 static const intptr_t kStackIndexBias = |
| 36 static_cast<intptr_t>(1) << (kBitsForPayload - 1); | 36 static_cast<intptr_t>(1) << (kBitsForPayload - 1); |
| 37 | 37 |
| 38 static const intptr_t kMachineRegisterMask = 0x6; |
| 39 static const intptr_t kMachineRegister = 0x6; |
| 40 |
| 38 public: | 41 public: |
| 39 // Constant payload can overlap with kind field so Kind values | 42 // Constant payload can overlap with kind field so Kind values |
| 40 // have to be chosen in a way that their last 2 bits are never | 43 // have to be chosen in a way that their last 2 bits are never |
| 41 // the same as kConstant. | 44 // the same as kConstant. |
| 42 enum Kind { | 45 enum Kind { |
| 43 // This location is invalid. Payload must be zero. | 46 // This location is invalid. Payload must be zero. |
| 44 kInvalid = 0, | 47 kInvalid = 0, |
| 45 | 48 |
| 46 // Constant value. This location contains a tagged Object handle. | 49 // Constant value. This location contains a tagged Object handle. |
| 47 kConstant = 1, | 50 kConstant = 1, |
| 48 | 51 |
| 49 // Unallocated location represents a location that is not fixed and can be | 52 // Unallocated location represents a location that is not fixed and can be |
| 50 // allocated by a register allocator. Each unallocated location has | 53 // allocated by a register allocator. Each unallocated location has |
| 51 // a policy that specifies what kind of location is suitable. Payload | 54 // a policy that specifies what kind of location is suitable. Payload |
| 52 // contains register allocation policy. | 55 // contains register allocation policy. |
| 53 kUnallocated = 2, | 56 kUnallocated = 2, |
| 54 | 57 |
| 58 // Spill slot allocated by the register allocator. Payload contains |
| 59 // a spill index. |
| 60 kStackSlot = 3, |
| 61 kDoubleStackSlot = 4, |
| 62 |
| 55 // Register location represents a fixed register. Payload contains | 63 // Register location represents a fixed register. Payload contains |
| 56 // register code. | 64 // register code. |
| 57 kRegister = 3, | 65 kRegister = 6, |
| 58 | 66 |
| 59 // Spill slot allocated by the register allocator. Payload contains | 67 // XmmRegister location represents a fixed xmm register. Payload contains |
| 60 // a spill index. | 68 // its code. |
| 61 kStackSlot = 4, | 69 kXmmRegister = 7, |
| 62 }; | 70 }; |
| 63 | 71 |
| 64 Location() : value_(kInvalidLocation) { | 72 Location() : value_(kInvalidLocation) { |
| 65 ASSERT(IsInvalid()); | 73 ASSERT(IsInvalid()); |
| 66 } | 74 } |
| 67 | 75 |
| 68 bool IsInvalid() const { | 76 bool IsInvalid() const { |
| 69 return value_ == kInvalidLocation; | 77 return value_ == kInvalidLocation; |
| 70 } | 78 } |
| 71 | 79 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 85 ASSERT(IsConstant()); | 93 ASSERT(IsConstant()); |
| 86 return *reinterpret_cast<const Object*>(value_ & ~kConstantMask); | 94 return *reinterpret_cast<const Object*>(value_ & ~kConstantMask); |
| 87 } | 95 } |
| 88 | 96 |
| 89 // Unallocated locations. | 97 // Unallocated locations. |
| 90 // TODO(vegorov): writable register policy? | 98 // TODO(vegorov): writable register policy? |
| 91 enum Policy { | 99 enum Policy { |
| 92 kAny, | 100 kAny, |
| 93 kPrefersRegister, | 101 kPrefersRegister, |
| 94 kRequiresRegister, | 102 kRequiresRegister, |
| 103 kRequiresXmmRegister, |
| 95 kSameAsFirstInput, | 104 kSameAsFirstInput, |
| 96 }; | 105 }; |
| 97 | 106 |
| 98 bool IsUnallocated() const { | 107 bool IsUnallocated() const { |
| 99 return kind() == kUnallocated; | 108 return kind() == kUnallocated; |
| 100 } | 109 } |
| 101 | 110 |
| 102 bool IsRegisterBeneficial() { | 111 bool IsRegisterBeneficial() { |
| 103 return !Equals(Any()); | 112 return !Equals(Any()); |
| 104 } | 113 } |
| 105 | 114 |
| 106 static Location UnallocatedLocation(Policy policy) { | 115 static Location UnallocatedLocation(Policy policy) { |
| 107 return Location(kUnallocated, PolicyField::encode(policy)); | 116 return Location(kUnallocated, PolicyField::encode(policy)); |
| 108 } | 117 } |
| 109 | 118 |
| 110 // Any free register is suitable to replace this unallocated location. | 119 // Any free register is suitable to replace this unallocated location. |
| 111 static Location Any() { | 120 static Location Any() { |
| 112 return UnallocatedLocation(kAny); | 121 return UnallocatedLocation(kAny); |
| 113 } | 122 } |
| 114 | 123 |
| 115 static Location PrefersRegister() { | 124 static Location PrefersRegister() { |
| 116 return UnallocatedLocation(kPrefersRegister); | 125 return UnallocatedLocation(kPrefersRegister); |
| 117 } | 126 } |
| 118 | 127 |
| 119 static Location RequiresRegister() { | 128 static Location RequiresRegister() { |
| 120 return UnallocatedLocation(kRequiresRegister); | 129 return UnallocatedLocation(kRequiresRegister); |
| 121 } | 130 } |
| 122 | 131 |
| 132 static Location RequiresXmmRegister() { |
| 133 return UnallocatedLocation(kRequiresXmmRegister); |
| 134 } |
| 135 |
| 123 // The location of the first input to the instruction will be | 136 // The location of the first input to the instruction will be |
| 124 // used to replace this unallocated location. | 137 // used to replace this unallocated location. |
| 125 static Location SameAsFirstInput() { | 138 static Location SameAsFirstInput() { |
| 126 return UnallocatedLocation(kSameAsFirstInput); | 139 return UnallocatedLocation(kSameAsFirstInput); |
| 127 } | 140 } |
| 128 | 141 |
| 129 // Empty location. Used if there the location should be ignored. | 142 // Empty location. Used if there the location should be ignored. |
| 130 static Location NoLocation() { | 143 static Location NoLocation() { |
| 131 return Location(); | 144 return Location(); |
| 132 } | 145 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 143 | 156 |
| 144 bool IsRegister() const { | 157 bool IsRegister() const { |
| 145 return kind() == kRegister; | 158 return kind() == kRegister; |
| 146 } | 159 } |
| 147 | 160 |
| 148 Register reg() const { | 161 Register reg() const { |
| 149 ASSERT(IsRegister()); | 162 ASSERT(IsRegister()); |
| 150 return static_cast<Register>(payload()); | 163 return static_cast<Register>(payload()); |
| 151 } | 164 } |
| 152 | 165 |
| 166 // XmmRegister locations. |
| 167 static Location XmmRegisterLocation(XmmRegister reg) { |
| 168 return Location(kXmmRegister, static_cast<uword>(reg)); |
| 169 } |
| 170 |
| 171 bool IsXmmRegister() const { |
| 172 return kind() == kXmmRegister; |
| 173 } |
| 174 |
| 175 XmmRegister xmm_reg() const { |
| 176 ASSERT(IsXmmRegister()); |
| 177 return static_cast<XmmRegister>(payload()); |
| 178 } |
| 179 |
| 180 static bool IsMachineRegisterKind(Kind kind) { |
| 181 return (kind & kMachineRegisterMask) == kMachineRegister; |
| 182 } |
| 183 |
| 184 static Location MachineRegisterLocation(Kind kind, intptr_t reg) { |
| 185 return Location(kind, reg); |
| 186 } |
| 187 |
| 188 bool IsMachineRegister() const { |
| 189 return IsMachineRegisterKind(kind()); |
| 190 } |
| 191 |
| 192 intptr_t register_code() const { |
| 193 ASSERT(IsMachineRegister()); |
| 194 return static_cast<intptr_t>(payload()); |
| 195 } |
| 196 |
| 153 // Spill slots. | 197 // Spill slots. |
| 154 static Location StackSlot(intptr_t stack_index) { | 198 static Location StackSlot(intptr_t stack_index) { |
| 155 ASSERT((-kStackIndexBias <= stack_index) && | 199 ASSERT((-kStackIndexBias <= stack_index) && |
| 156 (stack_index < kStackIndexBias)); | 200 (stack_index < kStackIndexBias)); |
| 157 Location loc(kStackSlot, static_cast<uword>(kStackIndexBias + stack_index)); | 201 Location loc(kStackSlot, static_cast<uword>(kStackIndexBias + stack_index)); |
| 158 // Ensure that sign is preserved. | 202 // Ensure that sign is preserved. |
| 159 ASSERT(loc.stack_index() == stack_index); | 203 ASSERT(loc.stack_index() == stack_index); |
| 160 return loc; | 204 return loc; |
| 161 } | 205 } |
| 162 | 206 |
| 163 bool IsStackSlot() const { | 207 bool IsStackSlot() const { |
| 164 return kind() == kStackSlot; | 208 return kind() == kStackSlot; |
| 165 } | 209 } |
| 166 | 210 |
| 211 static Location DoubleStackSlot(intptr_t stack_index) { |
| 212 ASSERT((-kStackIndexBias <= stack_index) && |
| 213 (stack_index < kStackIndexBias)); |
| 214 Location loc(kDoubleStackSlot, |
| 215 static_cast<uword>(kStackIndexBias + stack_index)); |
| 216 // Ensure that sign is preserved. |
| 217 ASSERT(loc.stack_index() == stack_index); |
| 218 return loc; |
| 219 } |
| 220 |
| 221 bool IsDoubleStackSlot() const { |
| 222 return kind() == kDoubleStackSlot; |
| 223 } |
| 224 |
| 225 |
| 167 intptr_t stack_index() const { | 226 intptr_t stack_index() const { |
| 168 ASSERT(IsStackSlot()); | 227 ASSERT(IsStackSlot() || IsDoubleStackSlot()); |
| 169 // Decode stack index manually to preserve sign. | 228 // Decode stack index manually to preserve sign. |
| 170 return payload() - kStackIndexBias; | 229 return payload() - kStackIndexBias; |
| 171 } | 230 } |
| 172 | 231 |
| 173 const char* Name() const; | 232 const char* Name() const; |
| 174 void PrintTo(BufferFormatter* f) const; | 233 void PrintTo(BufferFormatter* f) const; |
| 175 void Print() const; | 234 void Print() const; |
| 176 | 235 |
| 177 // Compare two locations. | 236 // Compare two locations. |
| 178 bool Equals(Location other) const { | 237 bool Equals(Location other) const { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 192 // If current location is constant might return something that | 251 // If current location is constant might return something that |
| 193 // is not equal to any Kind. | 252 // is not equal to any Kind. |
| 194 Kind kind() const { | 253 Kind kind() const { |
| 195 return KindField::decode(value_); | 254 return KindField::decode(value_); |
| 196 } | 255 } |
| 197 | 256 |
| 198 typedef BitField<Kind, 0, kBitsForKind> KindField; | 257 typedef BitField<Kind, 0, kBitsForKind> KindField; |
| 199 typedef BitField<uword, kBitsForKind, kBitsForPayload> PayloadField; | 258 typedef BitField<uword, kBitsForKind, kBitsForPayload> PayloadField; |
| 200 | 259 |
| 201 // Layout for kUnallocated locations payload. | 260 // Layout for kUnallocated locations payload. |
| 202 typedef BitField<Policy, 0, 2> PolicyField; | 261 typedef BitField<Policy, 0, 3> PolicyField; |
| 203 | 262 |
| 204 // Location either contains kind and payload fields or a tagged handle for | 263 // Location either contains kind and payload fields or a tagged handle for |
| 205 // a constant locations. Values of enumeration Kind are selected in such a | 264 // a constant locations. Values of enumeration Kind are selected in such a |
| 206 // way that none of them can be interpreted as a kConstant tag. | 265 // way that none of them can be interpreted as a kConstant tag. |
| 207 uword value_; | 266 uword value_; |
| 208 }; | 267 }; |
| 209 | 268 |
| 210 | 269 |
| 211 class RegisterSet : public ValueObject { | 270 class RegisterSet : public ValueObject { |
| 212 public: | 271 public: |
| 213 RegisterSet() : registers_(0) { | 272 RegisterSet() : cpu_registers_(0), xmm_registers_(0) { |
| 214 ASSERT(kNumberOfCpuRegisters < (kWordSize * kBitsPerByte)); | 273 ASSERT(kNumberOfCpuRegisters < (kWordSize * kBitsPerByte)); |
| 274 ASSERT(kNumberOfXmmRegisters < (kWordSize * kBitsPerByte)); |
| 215 } | 275 } |
| 216 | 276 |
| 217 void Add(Register reg) { | 277 |
| 218 registers_ |= (1 << reg); | 278 void Add(Location loc) { |
| 279 if (loc.IsRegister()) { |
| 280 cpu_registers_ |= (1 << loc.reg()); |
| 281 } else if (loc.IsXmmRegister()) { |
| 282 xmm_registers_ |= (1 << loc.xmm_reg()); |
| 283 } |
| 219 } | 284 } |
| 220 | 285 |
| 221 bool Contains(Register reg) { | 286 void Remove(Location loc) { |
| 222 return (registers_ & (1 << reg)) != 0; | 287 if (loc.IsRegister()) { |
| 288 cpu_registers_ &= ~(1 << loc.reg()); |
| 289 } else if (loc.IsXmmRegister()) { |
| 290 xmm_registers_ &= ~(1 << loc.xmm_reg()); |
| 291 } |
| 292 } |
| 293 |
| 294 bool ContainsRegister(Register reg) { |
| 295 return (cpu_registers_ & (1 << reg)) != 0; |
| 296 } |
| 297 |
| 298 bool ContainsXmmRegister(XmmRegister xmm_reg) { |
| 299 return (xmm_registers_ & (1 << xmm_reg)) != 0; |
| 300 } |
| 301 |
| 302 intptr_t xmm_regs_count() { |
| 303 intptr_t count = 0; |
| 304 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; reg_idx++) { |
| 305 if (ContainsXmmRegister(static_cast<XmmRegister>(reg_idx))) { |
| 306 count++; |
| 307 } |
| 308 } |
| 309 return count; |
| 223 } | 310 } |
| 224 | 311 |
| 225 private: | 312 private: |
| 226 intptr_t registers_; | 313 intptr_t cpu_registers_; |
| 314 intptr_t xmm_registers_; |
| 227 | 315 |
| 228 DISALLOW_COPY_AND_ASSIGN(RegisterSet); | 316 DISALLOW_COPY_AND_ASSIGN(RegisterSet); |
| 229 }; | 317 }; |
| 230 | 318 |
| 231 | 319 |
| 232 // Specification of locations for inputs and output. | 320 // Specification of locations for inputs and output. |
| 233 class LocationSummary : public ZoneAllocated { | 321 class LocationSummary : public ZoneAllocated { |
| 234 public: | 322 public: |
| 235 enum ContainsCall { | 323 enum ContainsCall { |
| 236 kNoCall, | 324 kNoCall, |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 BitmapBuilder* stack_bitmap_; | 405 BitmapBuilder* stack_bitmap_; |
| 318 | 406 |
| 319 const ContainsCall contains_call_; | 407 const ContainsCall contains_call_; |
| 320 RegisterSet live_registers_; | 408 RegisterSet live_registers_; |
| 321 }; | 409 }; |
| 322 | 410 |
| 323 | 411 |
| 324 } // namespace dart | 412 } // namespace dart |
| 325 | 413 |
| 326 #endif // VM_LOCATIONS_H_ | 414 #endif // VM_LOCATIONS_H_ |
| OLD | NEW |