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 | |
Florian Schneider
2012/08/24 11:09:28
-1 line.
| |
181 static bool IsMachineRegisterKind(Kind kind) { | |
182 return (kind & kMachineRegisterMask) == kMachineRegister; | |
183 } | |
184 | |
185 static Location MachineRegisterLocation(Kind kind, intptr_t reg) { | |
186 return Location(kind, reg); | |
187 } | |
188 | |
189 bool IsMachineRegister() const { | |
190 return IsMachineRegisterKind(kind()); | |
191 } | |
192 | |
193 intptr_t register_code() const { | |
194 ASSERT(IsMachineRegister()); | |
195 return static_cast<intptr_t>(payload()); | |
196 } | |
197 | |
153 // Spill slots. | 198 // Spill slots. |
154 static Location StackSlot(intptr_t stack_index) { | 199 static Location StackSlot(intptr_t stack_index) { |
155 ASSERT((-kStackIndexBias <= stack_index) && | 200 ASSERT((-kStackIndexBias <= stack_index) && |
156 (stack_index < kStackIndexBias)); | 201 (stack_index < kStackIndexBias)); |
157 Location loc(kStackSlot, static_cast<uword>(kStackIndexBias + stack_index)); | 202 Location loc(kStackSlot, static_cast<uword>(kStackIndexBias + stack_index)); |
158 // Ensure that sign is preserved. | 203 // Ensure that sign is preserved. |
159 ASSERT(loc.stack_index() == stack_index); | 204 ASSERT(loc.stack_index() == stack_index); |
160 return loc; | 205 return loc; |
161 } | 206 } |
162 | 207 |
163 bool IsStackSlot() const { | 208 bool IsStackSlot() const { |
164 return kind() == kStackSlot; | 209 return kind() == kStackSlot; |
165 } | 210 } |
166 | 211 |
212 static Location DoubleStackSlot(intptr_t stack_index) { | |
213 ASSERT((-kStackIndexBias <= stack_index) && | |
214 (stack_index < kStackIndexBias)); | |
215 Location loc(kDoubleStackSlot, | |
216 static_cast<uword>(kStackIndexBias + stack_index)); | |
217 // Ensure that sign is preserved. | |
218 ASSERT(loc.stack_index() == stack_index); | |
219 return loc; | |
220 } | |
221 | |
222 bool IsDoubleStackSlot() const { | |
223 return kind() == kDoubleStackSlot; | |
224 } | |
225 | |
226 | |
167 intptr_t stack_index() const { | 227 intptr_t stack_index() const { |
168 ASSERT(IsStackSlot()); | 228 ASSERT(IsStackSlot() || IsDoubleStackSlot()); |
169 // Decode stack index manually to preserve sign. | 229 // Decode stack index manually to preserve sign. |
170 return payload() - kStackIndexBias; | 230 return payload() - kStackIndexBias; |
171 } | 231 } |
172 | 232 |
173 const char* Name() const; | 233 const char* Name() const; |
174 void PrintTo(BufferFormatter* f) const; | 234 void PrintTo(BufferFormatter* f) const; |
175 void Print() const; | 235 void Print() const; |
176 | 236 |
177 // Compare two locations. | 237 // Compare two locations. |
178 bool Equals(Location other) const { | 238 bool Equals(Location other) const { |
(...skipping 13 matching lines...) Expand all Loading... | |
192 // If current location is constant might return something that | 252 // If current location is constant might return something that |
193 // is not equal to any Kind. | 253 // is not equal to any Kind. |
194 Kind kind() const { | 254 Kind kind() const { |
195 return KindField::decode(value_); | 255 return KindField::decode(value_); |
196 } | 256 } |
197 | 257 |
198 typedef BitField<Kind, 0, kBitsForKind> KindField; | 258 typedef BitField<Kind, 0, kBitsForKind> KindField; |
199 typedef BitField<uword, kBitsForKind, kBitsForPayload> PayloadField; | 259 typedef BitField<uword, kBitsForKind, kBitsForPayload> PayloadField; |
200 | 260 |
201 // Layout for kUnallocated locations payload. | 261 // Layout for kUnallocated locations payload. |
202 typedef BitField<Policy, 0, 2> PolicyField; | 262 typedef BitField<Policy, 0, 3> PolicyField; |
203 | 263 |
204 // Location either contains kind and payload fields or a tagged handle for | 264 // 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 | 265 // 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. | 266 // way that none of them can be interpreted as a kConstant tag. |
207 uword value_; | 267 uword value_; |
208 }; | 268 }; |
209 | 269 |
210 | 270 |
211 class RegisterSet : public ValueObject { | 271 class RegisterSet : public ValueObject { |
212 public: | 272 public: |
213 RegisterSet() : registers_(0) { | 273 RegisterSet() : cpu_registers_(0), xmm_registers_(0) { |
214 ASSERT(kNumberOfCpuRegisters < (kWordSize * kBitsPerByte)); | 274 ASSERT(kNumberOfCpuRegisters < (kWordSize * kBitsPerByte)); |
275 ASSERT(kNumberOfXmmRegisters < (kWordSize * kBitsPerByte)); | |
215 } | 276 } |
216 | 277 |
217 void Add(Register reg) { | 278 |
218 registers_ |= (1 << reg); | 279 void Add(Location loc) { |
280 if (loc.IsRegister()) { | |
281 cpu_registers_ |= (1 << loc.reg()); | |
282 } else if (loc.IsXmmRegister()) { | |
283 xmm_registers_ |= (1 << loc.xmm_reg()); | |
284 } | |
219 } | 285 } |
220 | 286 |
221 bool Contains(Register reg) { | 287 void Remove(Location loc) { |
222 return (registers_ & (1 << reg)) != 0; | 288 if (loc.IsRegister()) { |
289 cpu_registers_ &= ~(1 << loc.reg()); | |
290 } else if (loc.IsXmmRegister()) { | |
291 xmm_registers_ &= ~(1 << loc.xmm_reg()); | |
292 } | |
293 } | |
294 | |
295 bool ContainsRegister(Register reg) { | |
296 return (cpu_registers_ & (1 << reg)) != 0; | |
297 } | |
298 | |
299 bool ContainsXmmRegister(XmmRegister xmm_reg) { | |
300 return (xmm_registers_ & (1 << xmm_reg)) != 0; | |
301 } | |
302 | |
303 intptr_t xmm_regs_count() { | |
304 intptr_t count = 0; | |
305 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; reg_idx++) { | |
306 if (ContainsXmmRegister(static_cast<XmmRegister>(reg_idx))) { | |
307 count++; | |
308 } | |
309 } | |
310 return count; | |
223 } | 311 } |
224 | 312 |
225 private: | 313 private: |
226 intptr_t registers_; | 314 intptr_t cpu_registers_; |
315 intptr_t xmm_registers_; | |
227 | 316 |
228 DISALLOW_COPY_AND_ASSIGN(RegisterSet); | 317 DISALLOW_COPY_AND_ASSIGN(RegisterSet); |
229 }; | 318 }; |
230 | 319 |
231 | 320 |
232 // Specification of locations for inputs and output. | 321 // Specification of locations for inputs and output. |
233 class LocationSummary : public ZoneAllocated { | 322 class LocationSummary : public ZoneAllocated { |
234 public: | 323 public: |
235 enum ContainsCall { | 324 enum ContainsCall { |
236 kNoCall, | 325 kNoCall, |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
317 BitmapBuilder* stack_bitmap_; | 406 BitmapBuilder* stack_bitmap_; |
318 | 407 |
319 const ContainsCall contains_call_; | 408 const ContainsCall contains_call_; |
320 RegisterSet live_registers_; | 409 RegisterSet live_registers_; |
321 }; | 410 }; |
322 | 411 |
323 | 412 |
324 } // namespace dart | 413 } // namespace dart |
325 | 414 |
326 #endif // VM_LOCATIONS_H_ | 415 #endif // VM_LOCATIONS_H_ |
OLD | NEW |