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" |
11 #include "vm/log.h" | 11 #include "vm/log.h" |
12 | 12 |
13 namespace dart { | 13 namespace dart { |
14 | 14 |
15 | |
16 class BufferFormatter; | 15 class BufferFormatter; |
17 class ConstantInstr; | 16 class ConstantInstr; |
18 class Definition; | 17 class Definition; |
19 class PairLocation; | 18 class PairLocation; |
20 class Value; | 19 class Value; |
21 | 20 |
22 | |
23 enum Representation { | 21 enum Representation { |
24 kNoRepresentation, | 22 kNoRepresentation, |
25 kTagged, | 23 kTagged, |
26 kUntagged, | 24 kUntagged, |
27 kUnboxedDouble, | 25 kUnboxedDouble, |
28 kUnboxedInt32, | 26 kUnboxedInt32, |
29 kUnboxedUint32, | 27 kUnboxedUint32, |
30 kUnboxedMint, | 28 kUnboxedMint, |
31 kUnboxedFloat32x4, | 29 kUnboxedFloat32x4, |
32 kUnboxedInt32x4, | 30 kUnboxedInt32x4, |
33 kUnboxedFloat64x2, | 31 kUnboxedFloat64x2, |
34 kPairOfTagged, | 32 kPairOfTagged, |
35 kNumRepresentations | 33 kNumRepresentations |
36 }; | 34 }; |
37 | 35 |
38 | |
39 // Location objects are used to connect register allocator and code generator. | 36 // Location objects are used to connect register allocator and code generator. |
40 // Instruction templates used by code generator have a corresponding | 37 // Instruction templates used by code generator have a corresponding |
41 // LocationSummary object which specifies expected location for every input | 38 // LocationSummary object which specifies expected location for every input |
42 // and output. | 39 // and output. |
43 // Each location is encoded as a single word: for non-constant locations | 40 // Each location is encoded as a single word: for non-constant locations |
44 // low 4 bits denote location kind, rest is kind specific location payload | 41 // low 4 bits denote location kind, rest is kind specific location payload |
45 // e.g. for REGISTER kind payload is register code (value of the Register | 42 // e.g. for REGISTER kind payload is register code (value of the Register |
46 // enumeration), constant locations contain a tagged (low 2 bits are set to 01) | 43 // enumeration), constant locations contain a tagged (low 2 bits are set to 01) |
47 // Object handle. | 44 // Object handle. |
48 // | 45 // |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 | 379 |
383 static const intptr_t kStackIndexBias = static_cast<intptr_t>(1) | 380 static const intptr_t kStackIndexBias = static_cast<intptr_t>(1) |
384 << (kBitsForStackIndex - 1); | 381 << (kBitsForStackIndex - 1); |
385 | 382 |
386 // Location either contains kind and payload fields or a tagged handle for | 383 // Location either contains kind and payload fields or a tagged handle for |
387 // a constant locations. Values of enumeration Kind are selected in such a | 384 // a constant locations. Values of enumeration Kind are selected in such a |
388 // way that none of them can be interpreted as a kConstant tag. | 385 // way that none of them can be interpreted as a kConstant tag. |
389 uword value_; | 386 uword value_; |
390 }; | 387 }; |
391 | 388 |
392 | |
393 class PairLocation : public ZoneAllocated { | 389 class PairLocation : public ZoneAllocated { |
394 public: | 390 public: |
395 PairLocation() { | 391 PairLocation() { |
396 for (intptr_t i = 0; i < kPairLength; i++) { | 392 for (intptr_t i = 0; i < kPairLength; i++) { |
397 ASSERT(locations_[i].IsInvalid()); | 393 ASSERT(locations_[i].IsInvalid()); |
398 } | 394 } |
399 } | 395 } |
400 | 396 |
401 intptr_t length() const { return kPairLength; } | 397 intptr_t length() const { return kPairLength; } |
402 | 398 |
(...skipping 13 matching lines...) Expand all Loading... |
416 ASSERT(i >= 0); | 412 ASSERT(i >= 0); |
417 ASSERT(i < kPairLength); | 413 ASSERT(i < kPairLength); |
418 return &locations_[i]; | 414 return &locations_[i]; |
419 } | 415 } |
420 | 416 |
421 private: | 417 private: |
422 static const intptr_t kPairLength = 2; | 418 static const intptr_t kPairLength = 2; |
423 Location locations_[kPairLength]; | 419 Location locations_[kPairLength]; |
424 }; | 420 }; |
425 | 421 |
426 | |
427 template <typename T> | 422 template <typename T> |
428 class SmallSet { | 423 class SmallSet { |
429 public: | 424 public: |
430 SmallSet() : data_(0) {} | 425 SmallSet() : data_(0) {} |
431 | 426 |
432 explicit SmallSet(intptr_t data) : data_(data) {} | 427 explicit SmallSet(intptr_t data) : data_(data) {} |
433 | 428 |
434 bool Contains(T value) const { return (data_ & ToMask(value)) != 0; } | 429 bool Contains(T value) const { return (data_ & ToMask(value)) != 0; } |
435 | 430 |
436 void Add(T value) { data_ |= ToMask(value); } | 431 void Add(T value) { data_ |= ToMask(value); } |
437 | 432 |
438 void Remove(T value) { data_ &= ~ToMask(value); } | 433 void Remove(T value) { data_ &= ~ToMask(value); } |
439 | 434 |
440 bool IsEmpty() const { return data_ == 0; } | 435 bool IsEmpty() const { return data_ == 0; } |
441 | 436 |
442 intptr_t data() const { return data_; } | 437 intptr_t data() const { return data_; } |
443 | 438 |
444 private: | 439 private: |
445 static intptr_t ToMask(T value) { | 440 static intptr_t ToMask(T value) { |
446 ASSERT(static_cast<intptr_t>(value) < (kWordSize * kBitsPerByte)); | 441 ASSERT(static_cast<intptr_t>(value) < (kWordSize * kBitsPerByte)); |
447 return 1 << static_cast<intptr_t>(value); | 442 return 1 << static_cast<intptr_t>(value); |
448 } | 443 } |
449 | 444 |
450 intptr_t data_; | 445 intptr_t data_; |
451 }; | 446 }; |
452 | 447 |
453 | |
454 class RegisterSet : public ValueObject { | 448 class RegisterSet : public ValueObject { |
455 public: | 449 public: |
456 RegisterSet() | 450 RegisterSet() |
457 : cpu_registers_(), untagged_cpu_registers_(), fpu_registers_() { | 451 : cpu_registers_(), untagged_cpu_registers_(), fpu_registers_() { |
458 ASSERT(kNumberOfCpuRegisters <= (kWordSize * kBitsPerByte)); | 452 ASSERT(kNumberOfCpuRegisters <= (kWordSize * kBitsPerByte)); |
459 ASSERT(kNumberOfFpuRegisters <= (kWordSize * kBitsPerByte)); | 453 ASSERT(kNumberOfFpuRegisters <= (kWordSize * kBitsPerByte)); |
460 } | 454 } |
461 | 455 |
462 | |
463 void Add(Location loc, Representation rep = kTagged) { | 456 void Add(Location loc, Representation rep = kTagged) { |
464 if (loc.IsRegister()) { | 457 if (loc.IsRegister()) { |
465 cpu_registers_.Add(loc.reg()); | 458 cpu_registers_.Add(loc.reg()); |
466 if (rep != kTagged) { | 459 if (rep != kTagged) { |
467 // CPU register contains an untagged value. | 460 // CPU register contains an untagged value. |
468 MarkUntagged(loc); | 461 MarkUntagged(loc); |
469 } | 462 } |
470 } else if (loc.IsFpuRegister()) { | 463 } else if (loc.IsFpuRegister()) { |
471 fpu_registers_.Add(loc.fpu_reg()); | 464 fpu_registers_.Add(loc.fpu_reg()); |
472 } | 465 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 intptr_t fpu_registers() const { return fpu_registers_.data(); } | 534 intptr_t fpu_registers() const { return fpu_registers_.data(); } |
542 | 535 |
543 private: | 536 private: |
544 SmallSet<Register> cpu_registers_; | 537 SmallSet<Register> cpu_registers_; |
545 SmallSet<Register> untagged_cpu_registers_; | 538 SmallSet<Register> untagged_cpu_registers_; |
546 SmallSet<FpuRegister> fpu_registers_; | 539 SmallSet<FpuRegister> fpu_registers_; |
547 | 540 |
548 DISALLOW_COPY_AND_ASSIGN(RegisterSet); | 541 DISALLOW_COPY_AND_ASSIGN(RegisterSet); |
549 }; | 542 }; |
550 | 543 |
551 | |
552 // Specification of locations for inputs and output. | 544 // Specification of locations for inputs and output. |
553 class LocationSummary : public ZoneAllocated { | 545 class LocationSummary : public ZoneAllocated { |
554 public: | 546 public: |
555 enum ContainsCall { | 547 enum ContainsCall { |
556 kNoCall, // Used registers must be reserved as tmp. | 548 kNoCall, // Used registers must be reserved as tmp. |
557 kCall, // Registers have been saved and can be used without reservation. | 549 kCall, // Registers have been saved and can be used without reservation. |
558 kCallOnSlowPath // Used registers must be reserved as tmp. | 550 kCallOnSlowPath // Used registers must be reserved as tmp. |
559 }; | 551 }; |
560 | 552 |
561 LocationSummary(Zone* zone, | 553 LocationSummary(Zone* zone, |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 BitmapBuilder* stack_bitmap_; | 660 BitmapBuilder* stack_bitmap_; |
669 | 661 |
670 const ContainsCall contains_call_; | 662 const ContainsCall contains_call_; |
671 RegisterSet live_registers_; | 663 RegisterSet live_registers_; |
672 | 664 |
673 #if defined(DEBUG) | 665 #if defined(DEBUG) |
674 intptr_t writable_inputs_; | 666 intptr_t writable_inputs_; |
675 #endif | 667 #endif |
676 }; | 668 }; |
677 | 669 |
678 | |
679 } // namespace dart | 670 } // namespace dart |
680 | 671 |
681 #endif // RUNTIME_VM_LOCATIONS_H_ | 672 #endif // RUNTIME_VM_LOCATIONS_H_ |
OLD | NEW |