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 |