| 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 |