OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 RUNTIME_VM_LOCATIONS_H_ | 5 #ifndef RUNTIME_VM_LOCATIONS_H_ |
6 #define RUNTIME_VM_LOCATIONS_H_ | 6 #define RUNTIME_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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 kPairLocationTag = 2, | 80 kPairLocationTag = 2, |
81 | 81 |
82 // Unallocated location represents a location that is not fixed and can be | 82 // Unallocated location represents a location that is not fixed and can be |
83 // allocated by a register allocator. Each unallocated location has | 83 // allocated by a register allocator. Each unallocated location has |
84 // a policy that specifies what kind of location is suitable. Payload | 84 // a policy that specifies what kind of location is suitable. Payload |
85 // contains register allocation policy. | 85 // contains register allocation policy. |
86 kUnallocated = 3, | 86 kUnallocated = 3, |
87 | 87 |
88 // Spill slots allocated by the register allocator. Payload contains | 88 // Spill slots allocated by the register allocator. Payload contains |
89 // a spill index. | 89 // a spill index. |
90 kStackSlot = 4, // Word size slot. | 90 kStackSlot = 4, // Word size slot. |
91 kDoubleStackSlot = 7, // 64bit stack slot. | 91 kDoubleStackSlot = 7, // 64bit stack slot. |
92 kQuadStackSlot = 11, // 128bit stack slot. | 92 kQuadStackSlot = 11, // 128bit stack slot. |
93 | 93 |
94 // Register location represents a fixed register. Payload contains | 94 // Register location represents a fixed register. Payload contains |
95 // register code. | 95 // register code. |
96 kRegister = 8, | 96 kRegister = 8, |
97 | 97 |
98 // FpuRegister location represents a fixed fpu register. Payload contains | 98 // FpuRegister location represents a fixed fpu register. Payload contains |
99 // its code. | 99 // its code. |
100 kFpuRegister = 12, | 100 kFpuRegister = 12, |
101 }; | 101 }; |
102 | 102 |
(...skipping 22 matching lines...) Expand all Loading... |
125 COMPILE_ASSERT((kFpuRegister & kLocationTagMask) != kPairLocationTag); | 125 COMPILE_ASSERT((kFpuRegister & kLocationTagMask) != kPairLocationTag); |
126 | 126 |
127 // Verify tags and tagmask. | 127 // Verify tags and tagmask. |
128 COMPILE_ASSERT((kConstantTag & kLocationTagMask) == kConstantTag); | 128 COMPILE_ASSERT((kConstantTag & kLocationTagMask) == kConstantTag); |
129 | 129 |
130 COMPILE_ASSERT((kPairLocationTag & kLocationTagMask) == kPairLocationTag); | 130 COMPILE_ASSERT((kPairLocationTag & kLocationTagMask) == kPairLocationTag); |
131 | 131 |
132 ASSERT(IsInvalid()); | 132 ASSERT(IsInvalid()); |
133 } | 133 } |
134 | 134 |
135 Location(const Location& other) : ValueObject(), value_(other.value_) { } | 135 Location(const Location& other) : ValueObject(), value_(other.value_) {} |
136 | 136 |
137 Location& operator=(const Location& other) { | 137 Location& operator=(const Location& other) { |
138 value_ = other.value_; | 138 value_ = other.value_; |
139 return *this; | 139 return *this; |
140 } | 140 } |
141 | 141 |
142 bool IsInvalid() const { | 142 bool IsInvalid() const { return value_ == kInvalidLocation; } |
143 return value_ == kInvalidLocation; | |
144 } | |
145 | 143 |
146 // Constants. | 144 // Constants. |
147 bool IsConstant() const { | 145 bool IsConstant() const { |
148 return (value_ & kLocationTagMask) == kConstantTag; | 146 return (value_ & kLocationTagMask) == kConstantTag; |
149 } | 147 } |
150 | 148 |
151 static Location Constant(const ConstantInstr* obj) { | 149 static Location Constant(const ConstantInstr* obj) { |
152 Location loc(reinterpret_cast<uword>(obj) | kConstantTag); | 150 Location loc(reinterpret_cast<uword>(obj) | kConstantTag); |
153 ASSERT(obj == loc.constant_instruction()); | 151 ASSERT(obj == loc.constant_instruction()); |
154 return loc; | 152 return loc; |
(...skipping 17 matching lines...) Expand all Loading... |
172 // Unallocated locations. | 170 // Unallocated locations. |
173 enum Policy { | 171 enum Policy { |
174 kAny, | 172 kAny, |
175 kPrefersRegister, | 173 kPrefersRegister, |
176 kRequiresRegister, | 174 kRequiresRegister, |
177 kRequiresFpuRegister, | 175 kRequiresFpuRegister, |
178 kWritableRegister, | 176 kWritableRegister, |
179 kSameAsFirstInput, | 177 kSameAsFirstInput, |
180 }; | 178 }; |
181 | 179 |
182 bool IsUnallocated() const { | 180 bool IsUnallocated() const { return kind() == kUnallocated; } |
183 return kind() == kUnallocated; | |
184 } | |
185 | 181 |
186 bool IsRegisterBeneficial() { | 182 bool IsRegisterBeneficial() { return !Equals(Any()); } |
187 return !Equals(Any()); | |
188 } | |
189 | 183 |
190 static Location UnallocatedLocation(Policy policy) { | 184 static Location UnallocatedLocation(Policy policy) { |
191 return Location(kUnallocated, PolicyField::encode(policy)); | 185 return Location(kUnallocated, PolicyField::encode(policy)); |
192 } | 186 } |
193 | 187 |
194 // Any free register is suitable to replace this unallocated location. | 188 // Any free register is suitable to replace this unallocated location. |
195 static Location Any() { | 189 static Location Any() { return UnallocatedLocation(kAny); } |
196 return UnallocatedLocation(kAny); | |
197 } | |
198 | 190 |
199 static Location PrefersRegister() { | 191 static Location PrefersRegister() { |
200 return UnallocatedLocation(kPrefersRegister); | 192 return UnallocatedLocation(kPrefersRegister); |
201 } | 193 } |
202 | 194 |
203 static Location RequiresRegister() { | 195 static Location RequiresRegister() { |
204 return UnallocatedLocation(kRequiresRegister); | 196 return UnallocatedLocation(kRequiresRegister); |
205 } | 197 } |
206 | 198 |
207 static Location RequiresFpuRegister() { | 199 static Location RequiresFpuRegister() { |
208 return UnallocatedLocation(kRequiresFpuRegister); | 200 return UnallocatedLocation(kRequiresFpuRegister); |
209 } | 201 } |
210 | 202 |
211 static Location WritableRegister() { | 203 static Location WritableRegister() { |
212 return UnallocatedLocation(kWritableRegister); | 204 return UnallocatedLocation(kWritableRegister); |
213 } | 205 } |
214 | 206 |
215 // The location of the first input to the instruction will be | 207 // The location of the first input to the instruction will be |
216 // used to replace this unallocated location. | 208 // used to replace this unallocated location. |
217 static Location SameAsFirstInput() { | 209 static Location SameAsFirstInput() { |
218 return UnallocatedLocation(kSameAsFirstInput); | 210 return UnallocatedLocation(kSameAsFirstInput); |
219 } | 211 } |
220 | 212 |
221 // Empty location. Used if there the location should be ignored. | 213 // Empty location. Used if there the location should be ignored. |
222 static Location NoLocation() { | 214 static Location NoLocation() { return Location(); } |
223 return Location(); | |
224 } | |
225 | 215 |
226 Policy policy() const { | 216 Policy policy() const { |
227 ASSERT(IsUnallocated()); | 217 ASSERT(IsUnallocated()); |
228 return PolicyField::decode(payload()); | 218 return PolicyField::decode(payload()); |
229 } | 219 } |
230 | 220 |
231 // Register locations. | 221 // Register locations. |
232 static Location RegisterLocation(Register reg) { | 222 static Location RegisterLocation(Register reg) { |
233 return Location(kRegister, reg); | 223 return Location(kRegister, reg); |
234 } | 224 } |
235 | 225 |
236 bool IsRegister() const { | 226 bool IsRegister() const { return kind() == kRegister; } |
237 return kind() == kRegister; | |
238 } | |
239 | 227 |
240 Register reg() const { | 228 Register reg() const { |
241 ASSERT(IsRegister()); | 229 ASSERT(IsRegister()); |
242 return static_cast<Register>(payload()); | 230 return static_cast<Register>(payload()); |
243 } | 231 } |
244 | 232 |
245 // FpuRegister locations. | 233 // FpuRegister locations. |
246 static Location FpuRegisterLocation(FpuRegister reg) { | 234 static Location FpuRegisterLocation(FpuRegister reg) { |
247 return Location(kFpuRegister, reg); | 235 return Location(kFpuRegister, reg); |
248 } | 236 } |
249 | 237 |
250 bool IsFpuRegister() const { | 238 bool IsFpuRegister() const { return kind() == kFpuRegister; } |
251 return kind() == kFpuRegister; | |
252 } | |
253 | 239 |
254 FpuRegister fpu_reg() const { | 240 FpuRegister fpu_reg() const { |
255 ASSERT(IsFpuRegister()); | 241 ASSERT(IsFpuRegister()); |
256 return static_cast<FpuRegister>(payload()); | 242 return static_cast<FpuRegister>(payload()); |
257 } | 243 } |
258 | 244 |
259 static bool IsMachineRegisterKind(Kind kind) { | 245 static bool IsMachineRegisterKind(Kind kind) { |
260 return (kind == kRegister) || (kind == kFpuRegister); | 246 return (kind == kRegister) || (kind == kFpuRegister); |
261 } | 247 } |
262 | 248 |
263 static Location MachineRegisterLocation(Kind kind, | 249 static Location MachineRegisterLocation(Kind kind, intptr_t reg) { |
264 intptr_t reg) { | |
265 if (kind == kRegister) { | 250 if (kind == kRegister) { |
266 return RegisterLocation(static_cast<Register>(reg)); | 251 return RegisterLocation(static_cast<Register>(reg)); |
267 } else { | 252 } else { |
268 ASSERT(kind == kFpuRegister); | 253 ASSERT(kind == kFpuRegister); |
269 return FpuRegisterLocation(static_cast<FpuRegister>(reg)); | 254 return FpuRegisterLocation(static_cast<FpuRegister>(reg)); |
270 } | 255 } |
271 } | 256 } |
272 | 257 |
273 bool IsMachineRegister() const { | 258 bool IsMachineRegister() const { return IsMachineRegisterKind(kind()); } |
274 return IsMachineRegisterKind(kind()); | |
275 } | |
276 | 259 |
277 intptr_t register_code() const { | 260 intptr_t register_code() const { |
278 ASSERT(IsMachineRegister()); | 261 ASSERT(IsMachineRegister()); |
279 return static_cast<intptr_t>(payload()); | 262 return static_cast<intptr_t>(payload()); |
280 } | 263 } |
281 | 264 |
282 static uword EncodeStackIndex(intptr_t stack_index) { | 265 static uword EncodeStackIndex(intptr_t stack_index) { |
283 ASSERT((-kStackIndexBias <= stack_index) && | 266 ASSERT((-kStackIndexBias <= stack_index) && |
284 (stack_index < kStackIndexBias)); | 267 (stack_index < kStackIndexBias)); |
285 return static_cast<uword>(kStackIndexBias + stack_index); | 268 return static_cast<uword>(kStackIndexBias + stack_index); |
286 } | 269 } |
287 | 270 |
288 // Spill slots. | 271 // Spill slots. |
289 static Location StackSlot(intptr_t stack_index, | 272 static Location StackSlot(intptr_t stack_index, Register base = FPREG) { |
290 Register base = FPREG) { | 273 uword payload = StackSlotBaseField::encode(base) | |
291 uword payload = StackSlotBaseField::encode(base) | 274 StackIndexField::encode(EncodeStackIndex(stack_index)); |
292 | StackIndexField::encode(EncodeStackIndex(stack_index)); | |
293 Location loc(kStackSlot, payload); | 275 Location loc(kStackSlot, payload); |
294 // Ensure that sign is preserved. | 276 // Ensure that sign is preserved. |
295 ASSERT(loc.stack_index() == stack_index); | 277 ASSERT(loc.stack_index() == stack_index); |
296 return loc; | 278 return loc; |
297 } | 279 } |
298 | 280 |
299 bool IsStackSlot() const { | 281 bool IsStackSlot() const { return kind() == kStackSlot; } |
300 return kind() == kStackSlot; | |
301 } | |
302 | 282 |
303 static Location DoubleStackSlot(intptr_t stack_index) { | 283 static Location DoubleStackSlot(intptr_t stack_index) { |
304 uword payload = StackSlotBaseField::encode(FPREG) | 284 uword payload = StackSlotBaseField::encode(FPREG) | |
305 | StackIndexField::encode(EncodeStackIndex(stack_index)); | 285 StackIndexField::encode(EncodeStackIndex(stack_index)); |
306 Location loc(kDoubleStackSlot, payload); | 286 Location loc(kDoubleStackSlot, payload); |
307 // Ensure that sign is preserved. | 287 // Ensure that sign is preserved. |
308 ASSERT(loc.stack_index() == stack_index); | 288 ASSERT(loc.stack_index() == stack_index); |
309 return loc; | 289 return loc; |
310 } | 290 } |
311 | 291 |
312 bool IsDoubleStackSlot() const { | 292 bool IsDoubleStackSlot() const { return kind() == kDoubleStackSlot; } |
313 return kind() == kDoubleStackSlot; | |
314 } | |
315 | 293 |
316 static Location QuadStackSlot(intptr_t stack_index) { | 294 static Location QuadStackSlot(intptr_t stack_index) { |
317 uword payload = StackSlotBaseField::encode(FPREG) | 295 uword payload = StackSlotBaseField::encode(FPREG) | |
318 | StackIndexField::encode(EncodeStackIndex(stack_index)); | 296 StackIndexField::encode(EncodeStackIndex(stack_index)); |
319 Location loc(kQuadStackSlot, payload); | 297 Location loc(kQuadStackSlot, payload); |
320 // Ensure that sign is preserved. | 298 // Ensure that sign is preserved. |
321 ASSERT(loc.stack_index() == stack_index); | 299 ASSERT(loc.stack_index() == stack_index); |
322 return loc; | 300 return loc; |
323 } | 301 } |
324 | 302 |
325 bool IsQuadStackSlot() const { | 303 bool IsQuadStackSlot() const { return kind() == kQuadStackSlot; } |
326 return kind() == kQuadStackSlot; | |
327 } | |
328 | 304 |
329 Register base_reg() const { | 305 Register base_reg() const { |
330 ASSERT(HasStackIndex()); | 306 ASSERT(HasStackIndex()); |
331 return StackSlotBaseField::decode(payload()); | 307 return StackSlotBaseField::decode(payload()); |
332 } | 308 } |
333 | 309 |
334 intptr_t stack_index() const { | 310 intptr_t stack_index() const { |
335 ASSERT(HasStackIndex()); | 311 ASSERT(HasStackIndex()); |
336 // Decode stack index manually to preserve sign. | 312 // Decode stack index manually to preserve sign. |
337 return StackIndexField::decode(payload()) - kStackIndexBias; | 313 return StackIndexField::decode(payload()) - kStackIndexBias; |
338 } | 314 } |
339 | 315 |
340 bool HasStackIndex() const { | 316 bool HasStackIndex() const { |
341 return IsStackSlot() || IsDoubleStackSlot() || IsQuadStackSlot(); | 317 return IsStackSlot() || IsDoubleStackSlot() || IsQuadStackSlot(); |
342 } | 318 } |
343 | 319 |
344 // DBC does not have an notion of 'address' in its instruction set. | 320 // DBC does not have an notion of 'address' in its instruction set. |
345 #if !defined(TARGET_ARCH_DBC) | 321 #if !defined(TARGET_ARCH_DBC) |
346 // Return a memory operand for stack slot locations. | 322 // Return a memory operand for stack slot locations. |
347 Address ToStackSlotAddress() const; | 323 Address ToStackSlotAddress() const; |
348 #endif | 324 #endif |
349 | 325 |
350 // Returns the offset from the frame pointer for stack slot locations. | 326 // Returns the offset from the frame pointer for stack slot locations. |
351 intptr_t ToStackSlotOffset() const; | 327 intptr_t ToStackSlotOffset() const; |
352 | 328 |
353 // Constants. | 329 // Constants. |
354 static Location RegisterOrConstant(Value* value); | 330 static Location RegisterOrConstant(Value* value); |
355 static Location RegisterOrSmiConstant(Value* value); | 331 static Location RegisterOrSmiConstant(Value* value); |
356 static Location WritableRegisterOrSmiConstant(Value* value); | 332 static Location WritableRegisterOrSmiConstant(Value* value); |
357 static Location FixedRegisterOrConstant(Value* value, Register reg); | 333 static Location FixedRegisterOrConstant(Value* value, Register reg); |
358 static Location FixedRegisterOrSmiConstant(Value* value, Register reg); | 334 static Location FixedRegisterOrSmiConstant(Value* value, Register reg); |
359 static Location AnyOrConstant(Value* value); | 335 static Location AnyOrConstant(Value* value); |
360 | 336 |
361 const char* Name() const; | 337 const char* Name() const; |
362 void PrintTo(BufferFormatter* f) const; | 338 void PrintTo(BufferFormatter* f) const; |
363 void Print() const; | 339 void Print() const; |
364 const char* ToCString() const; | 340 const char* ToCString() const; |
365 | 341 |
366 // Compare two locations. | 342 // Compare two locations. |
367 bool Equals(Location other) const { | 343 bool Equals(Location other) const { return value_ == other.value_; } |
368 return value_ == other.value_; | |
369 } | |
370 | 344 |
371 // If current location is constant might return something that | 345 // If current location is constant might return something that |
372 // is not equal to any Kind. | 346 // is not equal to any Kind. |
373 Kind kind() const { | 347 Kind kind() const { return KindField::decode(value_); } |
374 return KindField::decode(value_); | |
375 } | |
376 | 348 |
377 Location Copy() const; | 349 Location Copy() const; |
378 | 350 |
379 Location RemapForSlowPath(Definition* def, | 351 Location RemapForSlowPath(Definition* def, |
380 intptr_t* cpu_reg_slots, | 352 intptr_t* cpu_reg_slots, |
381 intptr_t* fpu_reg_slots) const; | 353 intptr_t* fpu_reg_slots) const; |
382 | 354 |
383 private: | 355 private: |
384 explicit Location(uword value) : value_(value) { } | 356 explicit Location(uword value) : value_(value) {} |
385 | 357 |
386 Location(Kind kind, uword payload) | 358 Location(Kind kind, uword payload) |
387 : value_(KindField::encode(kind) | PayloadField::encode(payload)) { } | 359 : value_(KindField::encode(kind) | PayloadField::encode(payload)) {} |
388 | 360 |
389 uword payload() const { | 361 uword payload() const { return PayloadField::decode(value_); } |
390 return PayloadField::decode(value_); | |
391 } | |
392 | 362 |
393 class KindField : public BitField<uword, Kind, 0, kBitsForKind> {}; | 363 class KindField : public BitField<uword, Kind, 0, kBitsForKind> {}; |
394 class PayloadField : | 364 class PayloadField |
395 public BitField<uword, uword, kBitsForKind, kBitsForPayload> {}; | 365 : public BitField<uword, uword, kBitsForKind, kBitsForPayload> {}; |
396 | 366 |
397 // Layout for kUnallocated locations payload. | 367 // Layout for kUnallocated locations payload. |
398 typedef BitField<uword, Policy, 0, 3> PolicyField; | 368 typedef BitField<uword, Policy, 0, 3> PolicyField; |
399 | 369 |
400 // Layout for stack slots. | 370 // Layout for stack slots. |
401 #if defined(ARCH_IS_64_BIT) | 371 #if defined(ARCH_IS_64_BIT) |
402 static const intptr_t kBitsForBaseReg = 6; | 372 static const intptr_t kBitsForBaseReg = 6; |
403 #else | 373 #else |
404 static const intptr_t kBitsForBaseReg = 5; | 374 static const intptr_t kBitsForBaseReg = 5; |
405 #endif | 375 #endif |
406 static const intptr_t kBitsForStackIndex = kBitsForPayload - kBitsForBaseReg; | 376 static const intptr_t kBitsForStackIndex = kBitsForPayload - kBitsForBaseReg; |
407 class StackSlotBaseField : | 377 class StackSlotBaseField |
408 public BitField<uword, Register, 0, kBitsForBaseReg> {}; | 378 : public BitField<uword, Register, 0, kBitsForBaseReg> {}; |
409 class StackIndexField : | 379 class StackIndexField |
410 public BitField<uword, intptr_t, kBitsForBaseReg, kBitsForStackIndex> {}; | 380 : public BitField<uword, intptr_t, kBitsForBaseReg, kBitsForStackIndex> { |
| 381 }; |
411 COMPILE_ASSERT(1 << kBitsForBaseReg >= kNumberOfCpuRegisters); | 382 COMPILE_ASSERT(1 << kBitsForBaseReg >= kNumberOfCpuRegisters); |
412 | 383 |
413 static const intptr_t kStackIndexBias = | 384 static const intptr_t kStackIndexBias = static_cast<intptr_t>(1) |
414 static_cast<intptr_t>(1) << (kBitsForStackIndex - 1); | 385 << (kBitsForStackIndex - 1); |
415 | 386 |
416 // Location either contains kind and payload fields or a tagged handle for | 387 // Location either contains kind and payload fields or a tagged handle for |
417 // a constant locations. Values of enumeration Kind are selected in such a | 388 // a constant locations. Values of enumeration Kind are selected in such a |
418 // way that none of them can be interpreted as a kConstant tag. | 389 // way that none of them can be interpreted as a kConstant tag. |
419 uword value_; | 390 uword value_; |
420 }; | 391 }; |
421 | 392 |
422 | 393 |
423 class PairLocation : public ZoneAllocated { | 394 class PairLocation : public ZoneAllocated { |
424 public: | 395 public: |
(...skipping 22 matching lines...) Expand all Loading... |
447 ASSERT(i < kPairLength); | 418 ASSERT(i < kPairLength); |
448 return &locations_[i]; | 419 return &locations_[i]; |
449 } | 420 } |
450 | 421 |
451 private: | 422 private: |
452 static const intptr_t kPairLength = 2; | 423 static const intptr_t kPairLength = 2; |
453 Location locations_[kPairLength]; | 424 Location locations_[kPairLength]; |
454 }; | 425 }; |
455 | 426 |
456 | 427 |
457 template<typename T> | 428 template <typename T> |
458 class SmallSet { | 429 class SmallSet { |
459 public: | 430 public: |
460 SmallSet() : data_(0) { } | 431 SmallSet() : data_(0) {} |
461 | 432 |
462 explicit SmallSet(intptr_t data) : data_(data) { } | 433 explicit SmallSet(intptr_t data) : data_(data) {} |
463 | 434 |
464 bool Contains(T value) const { return (data_ & ToMask(value)) != 0; } | 435 bool Contains(T value) const { return (data_ & ToMask(value)) != 0; } |
465 | 436 |
466 void Add(T value) { data_ |= ToMask(value); } | 437 void Add(T value) { data_ |= ToMask(value); } |
467 | 438 |
468 void Remove(T value) { data_ &= ~ToMask(value); } | 439 void Remove(T value) { data_ &= ~ToMask(value); } |
469 | 440 |
470 bool IsEmpty() const { return data_ == 0; } | 441 bool IsEmpty() const { return data_ == 0; } |
471 | 442 |
472 intptr_t data() const { return data_; } | 443 intptr_t data() const { return data_; } |
473 | 444 |
474 private: | 445 private: |
475 static intptr_t ToMask(T value) { | 446 static intptr_t ToMask(T value) { |
476 ASSERT(static_cast<intptr_t>(value) < (kWordSize * kBitsPerByte)); | 447 ASSERT(static_cast<intptr_t>(value) < (kWordSize * kBitsPerByte)); |
477 return 1 << static_cast<intptr_t>(value); | 448 return 1 << static_cast<intptr_t>(value); |
478 } | 449 } |
479 | 450 |
480 intptr_t data_; | 451 intptr_t data_; |
481 }; | 452 }; |
482 | 453 |
483 | 454 |
484 class RegisterSet : public ValueObject { | 455 class RegisterSet : public ValueObject { |
485 public: | 456 public: |
486 RegisterSet() | 457 RegisterSet() |
487 : cpu_registers_(), | 458 : cpu_registers_(), untagged_cpu_registers_(), fpu_registers_() { |
488 untagged_cpu_registers_(), | |
489 fpu_registers_() { | |
490 ASSERT(kNumberOfCpuRegisters <= (kWordSize * kBitsPerByte)); | 459 ASSERT(kNumberOfCpuRegisters <= (kWordSize * kBitsPerByte)); |
491 ASSERT(kNumberOfFpuRegisters <= (kWordSize * kBitsPerByte)); | 460 ASSERT(kNumberOfFpuRegisters <= (kWordSize * kBitsPerByte)); |
492 } | 461 } |
493 | 462 |
494 | 463 |
495 void Add(Location loc, Representation rep = kTagged) { | 464 void Add(Location loc, Representation rep = kTagged) { |
496 if (loc.IsRegister()) { | 465 if (loc.IsRegister()) { |
497 cpu_registers_.Add(loc.reg()); | 466 cpu_registers_.Add(loc.reg()); |
498 if (rep != kTagged) { | 467 if (rep != kTagged) { |
499 // CPU register contains an untagged value. | 468 // CPU register contains an untagged value. |
(...skipping 21 matching lines...) Expand all Loading... |
521 UNREACHABLE(); | 490 UNREACHABLE(); |
522 return false; | 491 return false; |
523 } | 492 } |
524 } | 493 } |
525 | 494 |
526 void DebugPrint() { | 495 void DebugPrint() { |
527 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { | 496 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { |
528 Register r = static_cast<Register>(i); | 497 Register r = static_cast<Register>(i); |
529 if (ContainsRegister(r)) { | 498 if (ContainsRegister(r)) { |
530 THR_Print("%s %s\n", Assembler::RegisterName(r), | 499 THR_Print("%s %s\n", Assembler::RegisterName(r), |
531 IsTagged(r) ? "tagged" : "untagged"); | 500 IsTagged(r) ? "tagged" : "untagged"); |
532 } | 501 } |
533 } | 502 } |
534 | 503 |
535 for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) { | 504 for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) { |
536 FpuRegister r = static_cast<FpuRegister>(i); | 505 FpuRegister r = static_cast<FpuRegister>(i); |
537 if (ContainsFpuRegister(r)) { | 506 if (ContainsFpuRegister(r)) { |
538 THR_Print("%s\n", Assembler::FpuRegisterName(r)); | 507 THR_Print("%s\n", Assembler::FpuRegisterName(r)); |
539 } | 508 } |
540 } | 509 } |
541 } | 510 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
577 SmallSet<Register> untagged_cpu_registers_; | 546 SmallSet<Register> untagged_cpu_registers_; |
578 SmallSet<FpuRegister> fpu_registers_; | 547 SmallSet<FpuRegister> fpu_registers_; |
579 | 548 |
580 DISALLOW_COPY_AND_ASSIGN(RegisterSet); | 549 DISALLOW_COPY_AND_ASSIGN(RegisterSet); |
581 }; | 550 }; |
582 | 551 |
583 | 552 |
584 // Specification of locations for inputs and output. | 553 // Specification of locations for inputs and output. |
585 class LocationSummary : public ZoneAllocated { | 554 class LocationSummary : public ZoneAllocated { |
586 public: | 555 public: |
587 enum ContainsCall { | 556 enum ContainsCall { kNoCall, kCall, kCallOnSlowPath }; |
588 kNoCall, | |
589 kCall, | |
590 kCallOnSlowPath | |
591 }; | |
592 | 557 |
593 LocationSummary(Zone* zone, | 558 LocationSummary(Zone* zone, |
594 intptr_t input_count, | 559 intptr_t input_count, |
595 intptr_t temp_count, | 560 intptr_t temp_count, |
596 LocationSummary::ContainsCall contains_call); | 561 LocationSummary::ContainsCall contains_call); |
597 | 562 |
598 intptr_t input_count() const { | 563 intptr_t input_count() const { return num_inputs_; } |
599 return num_inputs_; | |
600 } | |
601 | 564 |
602 Location in(intptr_t index) const { | 565 Location in(intptr_t index) const { |
603 ASSERT(index >= 0); | 566 ASSERT(index >= 0); |
604 ASSERT(index < num_inputs_); | 567 ASSERT(index < num_inputs_); |
605 return input_locations_[index]; | 568 return input_locations_[index]; |
606 } | 569 } |
607 | 570 |
608 Location* in_slot(intptr_t index) { | 571 Location* in_slot(intptr_t index) { |
609 ASSERT(index >= 0); | 572 ASSERT(index >= 0); |
610 ASSERT(index < num_inputs_); | 573 ASSERT(index < num_inputs_); |
611 return &input_locations_[index]; | 574 return &input_locations_[index]; |
612 } | 575 } |
613 | 576 |
614 void set_in(intptr_t index, Location loc) { | 577 void set_in(intptr_t index, Location loc) { |
615 ASSERT(index >= 0); | 578 ASSERT(index >= 0); |
616 ASSERT(index < num_inputs_); | 579 ASSERT(index < num_inputs_); |
617 ASSERT(!always_calls() || loc.IsMachineRegister()); | 580 ASSERT(!always_calls() || loc.IsMachineRegister()); |
618 input_locations_[index] = loc; | 581 input_locations_[index] = loc; |
619 } | 582 } |
620 | 583 |
621 intptr_t temp_count() const { | 584 intptr_t temp_count() const { return num_temps_; } |
622 return num_temps_; | |
623 } | |
624 | 585 |
625 Location temp(intptr_t index) const { | 586 Location temp(intptr_t index) const { |
626 ASSERT(index >= 0); | 587 ASSERT(index >= 0); |
627 ASSERT(index < num_temps_); | 588 ASSERT(index < num_temps_); |
628 return temp_locations_[index]; | 589 return temp_locations_[index]; |
629 } | 590 } |
630 | 591 |
631 Location* temp_slot(intptr_t index) { | 592 Location* temp_slot(intptr_t index) { |
632 ASSERT(index >= 0); | 593 ASSERT(index >= 0); |
633 ASSERT(index < num_temps_); | 594 ASSERT(index < num_temps_); |
634 return &temp_locations_[index]; | 595 return &temp_locations_[index]; |
635 } | 596 } |
636 | 597 |
637 void set_temp(intptr_t index, Location loc) { | 598 void set_temp(intptr_t index, Location loc) { |
638 ASSERT(index >= 0); | 599 ASSERT(index >= 0); |
639 ASSERT(index < num_temps_); | 600 ASSERT(index < num_temps_); |
640 ASSERT(!always_calls() || loc.IsMachineRegister()); | 601 ASSERT(!always_calls() || loc.IsMachineRegister()); |
641 temp_locations_[index] = loc; | 602 temp_locations_[index] = loc; |
642 } | 603 } |
643 | 604 |
644 intptr_t output_count() const { | 605 intptr_t output_count() const { return 1; } |
645 return 1; | |
646 } | |
647 | 606 |
648 Location out(intptr_t index) const { | 607 Location out(intptr_t index) const { |
649 ASSERT(index == 0); | 608 ASSERT(index == 0); |
650 return output_location_; | 609 return output_location_; |
651 } | 610 } |
652 | 611 |
653 Location* out_slot(intptr_t index) { | 612 Location* out_slot(intptr_t index) { |
654 ASSERT(index == 0); | 613 ASSERT(index == 0); |
655 return &output_location_; | 614 return &output_location_; |
656 } | 615 } |
657 | 616 |
658 void set_out(intptr_t index, Location loc) { | 617 void set_out(intptr_t index, Location loc) { |
659 ASSERT(index == 0); | 618 ASSERT(index == 0); |
660 // DBC calls are different from call on other architectures so this | 619 // DBC calls are different from call on other architectures so this |
661 // assert doesn't make sense. | 620 // assert doesn't make sense. |
662 #if !defined(TARGET_ARCH_DBC) | 621 #if !defined(TARGET_ARCH_DBC) |
663 ASSERT(!always_calls() || | 622 ASSERT(!always_calls() || (loc.IsMachineRegister() || loc.IsInvalid() || |
664 (loc.IsMachineRegister() || loc.IsInvalid() || | 623 loc.IsPairLocation())); |
665 loc.IsPairLocation())); | |
666 #endif | 624 #endif |
667 output_location_ = loc; | 625 output_location_ = loc; |
668 } | 626 } |
669 | 627 |
670 BitmapBuilder* stack_bitmap() { | 628 BitmapBuilder* stack_bitmap() { |
671 if (stack_bitmap_ == NULL) { | 629 if (stack_bitmap_ == NULL) { |
672 stack_bitmap_ = new BitmapBuilder(); | 630 stack_bitmap_ = new BitmapBuilder(); |
673 } | 631 } |
674 return stack_bitmap_; | 632 return stack_bitmap_; |
675 } | 633 } |
676 void SetStackBit(intptr_t index) { | 634 void SetStackBit(intptr_t index) { stack_bitmap()->Set(index, true); } |
677 stack_bitmap()->Set(index, true); | |
678 } | |
679 | 635 |
680 bool always_calls() const { | 636 bool always_calls() const { return contains_call_ == kCall; } |
681 return contains_call_ == kCall; | |
682 } | |
683 | 637 |
684 bool can_call() { | 638 bool can_call() { return contains_call_ != kNoCall; } |
685 return contains_call_ != kNoCall; | |
686 } | |
687 | 639 |
688 bool HasCallOnSlowPath() { | 640 bool HasCallOnSlowPath() { return can_call() && !always_calls(); } |
689 return can_call() && !always_calls(); | |
690 } | |
691 | 641 |
692 void PrintTo(BufferFormatter* f) const; | 642 void PrintTo(BufferFormatter* f) const; |
693 | 643 |
694 static LocationSummary* Make(Zone* zone, | 644 static LocationSummary* Make(Zone* zone, |
695 intptr_t input_count, | 645 intptr_t input_count, |
696 Location out, | 646 Location out, |
697 ContainsCall contains_call); | 647 ContainsCall contains_call); |
698 | 648 |
699 RegisterSet* live_registers() { | 649 RegisterSet* live_registers() { return &live_registers_; } |
700 return &live_registers_; | |
701 } | |
702 | 650 |
703 #if defined(DEBUG) | 651 #if defined(DEBUG) |
704 // Debug only verification that ensures that writable registers are correctly | 652 // Debug only verification that ensures that writable registers are correctly |
705 // preserved on the slow path. | 653 // preserved on the slow path. |
706 void DiscoverWritableInputs(); | 654 void DiscoverWritableInputs(); |
707 void CheckWritableInputs(); | 655 void CheckWritableInputs(); |
708 #endif | 656 #endif |
709 | 657 |
710 private: | 658 private: |
711 const intptr_t num_inputs_; | 659 const intptr_t num_inputs_; |
712 Location* input_locations_; | 660 Location* input_locations_; |
713 const intptr_t num_temps_; | 661 const intptr_t num_temps_; |
714 Location* temp_locations_; | 662 Location* temp_locations_; |
715 Location output_location_; | 663 Location output_location_; |
716 | 664 |
717 BitmapBuilder* stack_bitmap_; | 665 BitmapBuilder* stack_bitmap_; |
718 | 666 |
719 const ContainsCall contains_call_; | 667 const ContainsCall contains_call_; |
720 RegisterSet live_registers_; | 668 RegisterSet live_registers_; |
721 | 669 |
722 #if defined(DEBUG) | 670 #if defined(DEBUG) |
723 intptr_t writable_inputs_; | 671 intptr_t writable_inputs_; |
724 #endif | 672 #endif |
725 }; | 673 }; |
726 | 674 |
727 | 675 |
728 } // namespace dart | 676 } // namespace dart |
729 | 677 |
730 #endif // RUNTIME_VM_LOCATIONS_H_ | 678 #endif // RUNTIME_VM_LOCATIONS_H_ |
OLD | NEW |