| 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 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 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 // Ensure that sign is preserved. | 324 // Ensure that sign is preserved. |
| 325 ASSERT(loc.stack_index() == stack_index); | 325 ASSERT(loc.stack_index() == stack_index); |
| 326 return loc; | 326 return loc; |
| 327 } | 327 } |
| 328 | 328 |
| 329 bool IsQuadStackSlot() const { | 329 bool IsQuadStackSlot() const { |
| 330 return kind() == kQuadStackSlot; | 330 return kind() == kQuadStackSlot; |
| 331 } | 331 } |
| 332 | 332 |
| 333 intptr_t stack_index() const { | 333 intptr_t stack_index() const { |
| 334 ASSERT(IsStackSlot() || IsDoubleStackSlot() || IsQuadStackSlot()); | 334 ASSERT(HasStackIndex()); |
| 335 // Decode stack index manually to preserve sign. | 335 // Decode stack index manually to preserve sign. |
| 336 return payload() - kStackIndexBias; | 336 return payload() - kStackIndexBias; |
| 337 } | 337 } |
| 338 | 338 |
| 339 bool HasStackIndex() const { |
| 340 return IsStackSlot() || IsDoubleStackSlot() || IsQuadStackSlot(); |
| 341 } |
| 342 |
| 339 // Return a memory operand for stack slot locations. | 343 // Return a memory operand for stack slot locations. |
| 340 Address ToStackSlotAddress() const; | 344 Address ToStackSlotAddress() const; |
| 341 | 345 |
| 342 // Returns the offset from the frame pointer for stack slot locations. | 346 // Returns the offset from the frame pointer for stack slot locations. |
| 343 intptr_t ToStackSlotOffset() const; | 347 intptr_t ToStackSlotOffset() const; |
| 344 | 348 |
| 345 // Constants. | 349 // Constants. |
| 346 static Location RegisterOrConstant(Value* value); | 350 static Location RegisterOrConstant(Value* value); |
| 347 static Location RegisterOrSmiConstant(Value* value); | 351 static Location RegisterOrSmiConstant(Value* value); |
| 348 static Location FixedRegisterOrConstant(Value* value, Register reg); | 352 static Location FixedRegisterOrConstant(Value* value, Register reg); |
| 349 static Location FixedRegisterOrSmiConstant(Value* value, Register reg); | 353 static Location FixedRegisterOrSmiConstant(Value* value, Register reg); |
| 350 static Location AnyOrConstant(Value* value); | 354 static Location AnyOrConstant(Value* value); |
| 351 | 355 |
| 352 const char* Name() const; | 356 const char* Name() const; |
| 353 void PrintTo(BufferFormatter* f) const; | 357 void PrintTo(BufferFormatter* f) const; |
| 354 void Print() const; | 358 void Print() const; |
| 355 const char* ToCString() const; | 359 const char* ToCString() const; |
| 356 | 360 |
| 357 // Compare two locations. | 361 // Compare two locations. |
| 358 bool Equals(Location other) const { | 362 bool Equals(Location other) const { |
| 359 return value_ == other.value_; | 363 return value_ == other.value_; |
| 360 } | 364 } |
| 361 | 365 |
| 362 // If current location is constant might return something that | 366 // If current location is constant might return something that |
| 363 // is not equal to any Kind. | 367 // is not equal to any Kind. |
| 364 Kind kind() const { | 368 Kind kind() const { |
| 365 return KindField::decode(value_); | 369 return KindField::decode(value_); |
| 366 } | 370 } |
| 367 | 371 |
| 372 Location Copy() const; |
| 373 |
| 368 private: | 374 private: |
| 369 explicit Location(uword value) : value_(value) { } | 375 explicit Location(uword value) : value_(value) { } |
| 370 | 376 |
| 371 Location(Kind kind, uword payload) | 377 Location(Kind kind, uword payload) |
| 372 : value_(KindField::encode(kind) | PayloadField::encode(payload)) { } | 378 : value_(KindField::encode(kind) | PayloadField::encode(payload)) { } |
| 373 | 379 |
| 374 uword payload() const { | 380 uword payload() const { |
| 375 return PayloadField::decode(value_); | 381 return PayloadField::decode(value_); |
| 376 } | 382 } |
| 377 | 383 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 } | 427 } |
| 422 | 428 |
| 423 private: | 429 private: |
| 424 static const intptr_t kPairLength = 2; | 430 static const intptr_t kPairLength = 2; |
| 425 Location locations_[kPairLength]; | 431 Location locations_[kPairLength]; |
| 426 }; | 432 }; |
| 427 | 433 |
| 428 | 434 |
| 429 class RegisterSet : public ValueObject { | 435 class RegisterSet : public ValueObject { |
| 430 public: | 436 public: |
| 431 RegisterSet() : cpu_registers_(0), fpu_registers_(0) { | 437 RegisterSet() : cpu_registers_(0), untagged_cpu_registers_(0), |
| 438 fpu_registers_(0) { |
| 432 ASSERT(kNumberOfCpuRegisters <= (kWordSize * kBitsPerByte)); | 439 ASSERT(kNumberOfCpuRegisters <= (kWordSize * kBitsPerByte)); |
| 433 ASSERT(kNumberOfFpuRegisters <= (kWordSize * kBitsPerByte)); | 440 ASSERT(kNumberOfFpuRegisters <= (kWordSize * kBitsPerByte)); |
| 434 } | 441 } |
| 435 | 442 |
| 436 | 443 |
| 437 void Add(Location loc) { | 444 void Add(Location loc, Representation rep = kTagged) { |
| 438 if (loc.IsRegister()) { | 445 if (loc.IsRegister()) { |
| 439 cpu_registers_ |= (1 << loc.reg()); | 446 cpu_registers_ |= (1 << loc.reg()); |
| 447 if (rep != kTagged) { |
| 448 // CPU register contains an untagged value. |
| 449 MarkUntagged(loc); |
| 450 } |
| 440 } else if (loc.IsFpuRegister()) { | 451 } else if (loc.IsFpuRegister()) { |
| 441 fpu_registers_ |= (1 << loc.fpu_reg()); | 452 fpu_registers_ |= (1 << loc.fpu_reg()); |
| 442 } | 453 } |
| 443 } | 454 } |
| 444 | 455 |
| 445 void Remove(Location loc) { | 456 void Remove(Location loc) { |
| 446 if (loc.IsRegister()) { | 457 if (loc.IsRegister()) { |
| 447 cpu_registers_ &= ~(1 << loc.reg()); | 458 cpu_registers_ &= ~(1 << loc.reg()); |
| 448 } else if (loc.IsFpuRegister()) { | 459 } else if (loc.IsFpuRegister()) { |
| 449 fpu_registers_ &= ~(1 << loc.fpu_reg()); | 460 fpu_registers_ &= ~(1 << loc.fpu_reg()); |
| 450 } | 461 } |
| 451 } | 462 } |
| 452 | 463 |
| 464 void DebugPrint() { |
| 465 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { |
| 466 Register r = static_cast<Register>(i); |
| 467 if (ContainsRegister(r)) { |
| 468 OS::Print("%s %s\n", Assembler::RegisterName(r), |
| 469 IsTagged(r) ? "tagged" : "untagged"); |
| 470 } |
| 471 } |
| 472 |
| 473 for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) { |
| 474 FpuRegister r = static_cast<FpuRegister>(i); |
| 475 if (ContainsFpuRegister(r)) { |
| 476 OS::Print("%s\n", Assembler::FpuRegisterName(r)); |
| 477 } |
| 478 } |
| 479 } |
| 480 |
| 481 void MarkUntagged(Location loc) { |
| 482 ASSERT(loc.IsRegister()); |
| 483 untagged_cpu_registers_ |= (1 << loc.reg()); |
| 484 } |
| 485 |
| 486 bool IsTagged(Register reg) const { |
| 487 return (untagged_cpu_registers_ & (1 << reg)) == 0; |
| 488 } |
| 489 |
| 453 bool ContainsRegister(Register reg) const { | 490 bool ContainsRegister(Register reg) const { |
| 454 return (cpu_registers_ & (1 << reg)) != 0; | 491 return (cpu_registers_ & (1 << reg)) != 0; |
| 455 } | 492 } |
| 456 | 493 |
| 457 bool ContainsFpuRegister(FpuRegister fpu_reg) const { | 494 bool ContainsFpuRegister(FpuRegister fpu_reg) const { |
| 458 return (fpu_registers_ & (1 << fpu_reg)) != 0; | 495 return (fpu_registers_ & (1 << fpu_reg)) != 0; |
| 459 } | 496 } |
| 460 | 497 |
| 461 intptr_t CpuRegisterCount() const { return RegisterCount(cpu_registers_); } | 498 intptr_t CpuRegisterCount() const { return RegisterCount(cpu_registers_); } |
| 462 intptr_t FpuRegisterCount() const { return RegisterCount(fpu_registers_); } | 499 intptr_t FpuRegisterCount() const { return RegisterCount(fpu_registers_); } |
| 463 | 500 |
| 464 static intptr_t RegisterCount(intptr_t registers); | 501 static intptr_t RegisterCount(intptr_t registers); |
| 465 | 502 |
| 466 intptr_t cpu_registers() const { return cpu_registers_; } | 503 intptr_t cpu_registers() const { return cpu_registers_; } |
| 467 intptr_t fpu_registers() const { return fpu_registers_; } | 504 intptr_t fpu_registers() const { return fpu_registers_; } |
| 468 | 505 |
| 469 private: | 506 private: |
| 470 intptr_t cpu_registers_; | 507 intptr_t cpu_registers_; |
| 508 intptr_t untagged_cpu_registers_; |
| 471 intptr_t fpu_registers_; | 509 intptr_t fpu_registers_; |
| 472 | 510 |
| 473 DISALLOW_COPY_AND_ASSIGN(RegisterSet); | 511 DISALLOW_COPY_AND_ASSIGN(RegisterSet); |
| 474 }; | 512 }; |
| 475 | 513 |
| 476 | 514 |
| 477 // Specification of locations for inputs and output. | 515 // Specification of locations for inputs and output. |
| 478 class LocationSummary : public ZoneAllocated { | 516 class LocationSummary : public ZoneAllocated { |
| 479 public: | 517 public: |
| 480 enum ContainsCall { | 518 enum ContainsCall { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 BitmapBuilder* stack_bitmap() const { return stack_bitmap_; } | 592 BitmapBuilder* stack_bitmap() const { return stack_bitmap_; } |
| 555 | 593 |
| 556 bool always_calls() const { | 594 bool always_calls() const { |
| 557 return contains_call_ == kCall; | 595 return contains_call_ == kCall; |
| 558 } | 596 } |
| 559 | 597 |
| 560 bool can_call() { | 598 bool can_call() { |
| 561 return contains_call_ != kNoCall; | 599 return contains_call_ != kNoCall; |
| 562 } | 600 } |
| 563 | 601 |
| 602 bool HasCallOnSlowPath() { |
| 603 return can_call() && !always_calls(); |
| 604 } |
| 605 |
| 564 void PrintTo(BufferFormatter* f) const; | 606 void PrintTo(BufferFormatter* f) const; |
| 565 | 607 |
| 566 static LocationSummary* Make(intptr_t input_count, | 608 static LocationSummary* Make(intptr_t input_count, |
| 567 Location out, | 609 Location out, |
| 568 ContainsCall contains_call); | 610 ContainsCall contains_call); |
| 569 | 611 |
| 570 RegisterSet* live_registers() { | 612 RegisterSet* live_registers() { |
| 571 return &live_registers_; | 613 return &live_registers_; |
| 572 } | 614 } |
| 573 | 615 |
| 574 private: | 616 private: |
| 575 ZoneGrowableArray<Location> input_locations_; | 617 ZoneGrowableArray<Location> input_locations_; |
| 576 ZoneGrowableArray<Location> temp_locations_; | 618 ZoneGrowableArray<Location> temp_locations_; |
| 577 ZoneGrowableArray<Location> output_locations_; | 619 ZoneGrowableArray<Location> output_locations_; |
| 578 | 620 |
| 579 BitmapBuilder* stack_bitmap_; | 621 BitmapBuilder* stack_bitmap_; |
| 580 | 622 |
| 581 const ContainsCall contains_call_; | 623 const ContainsCall contains_call_; |
| 582 RegisterSet live_registers_; | 624 RegisterSet live_registers_; |
| 583 }; | 625 }; |
| 584 | 626 |
| 585 | 627 |
| 586 } // namespace dart | 628 } // namespace dart |
| 587 | 629 |
| 588 #endif // VM_LOCATIONS_H_ | 630 #endif // VM_LOCATIONS_H_ |
| OLD | NEW |