| OLD | NEW |
| 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
| 2 // All Rights Reserved. | 2 // All Rights Reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
| 6 // are met: | 6 // are met: |
| 7 // | 7 // |
| 8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
| 9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
| 10 // | 10 // |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 static const int kMantissaOffset = 0; | 102 static const int kMantissaOffset = 0; |
| 103 static const int kExponentOffset = 4; | 103 static const int kExponentOffset = 4; |
| 104 #else | 104 #else |
| 105 static const int kMantissaOffset = 4; | 105 static const int kMantissaOffset = 4; |
| 106 static const int kExponentOffset = 0; | 106 static const int kExponentOffset = 0; |
| 107 #endif | 107 #endif |
| 108 | 108 |
| 109 static const int kAllocatableLowRangeBegin = 3; | 109 static const int kAllocatableLowRangeBegin = 3; |
| 110 static const int kAllocatableLowRangeEnd = 10; | 110 static const int kAllocatableLowRangeEnd = 10; |
| 111 static const int kAllocatableHighRangeBegin = 14; | 111 static const int kAllocatableHighRangeBegin = 14; |
| 112 static const int kAllocatableHighRangeEnd = 28; | 112 static const int kAllocatableHighRangeEnd = |
| 113 FLAG_enable_embedded_constant_pool ? 27 : 28; |
| 113 static const int kAllocatableContext = 30; | 114 static const int kAllocatableContext = 30; |
| 114 | 115 |
| 115 static const int kNumAllocatableLow = | 116 static const int kNumAllocatableLow = |
| 116 kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1; | 117 kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1; |
| 117 static const int kNumAllocatableHigh = | 118 static const int kNumAllocatableHigh = |
| 118 kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1; | 119 kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1; |
| 119 static const int kMaxNumAllocatableRegisters = | 120 static const int kMaxNumAllocatableRegisters = |
| 120 kNumAllocatableLow + kNumAllocatableHigh + 1; // cp | 121 kNumAllocatableLow + kNumAllocatableHigh + 1; // cp |
| 121 | 122 |
| 122 static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; } | 123 static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 "r21", | 172 "r21", |
| 172 "r22", | 173 "r22", |
| 173 "r23", | 174 "r23", |
| 174 "r24", | 175 "r24", |
| 175 "r25", | 176 "r25", |
| 176 "r26", | 177 "r26", |
| 177 "r27", | 178 "r27", |
| 178 "r28", | 179 "r28", |
| 179 "cp", | 180 "cp", |
| 180 }; | 181 }; |
| 182 if (FLAG_enable_embedded_constant_pool && |
| 183 (index == kMaxNumAllocatableRegisters - 2)) { |
| 184 return names[index + 1]; |
| 185 } |
| 181 return names[index]; | 186 return names[index]; |
| 182 } | 187 } |
| 183 | 188 |
| 184 static const RegList kAllocatable = | 189 static const RegList kAllocatable = |
| 185 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 9 | 1 << 10 | | 190 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 9 | 1 << 10 | |
| 186 1 << 14 | 1 << 15 | 1 << 16 | 1 << 17 | 1 << 18 | 1 << 19 | 1 << 20 | | 191 1 << 14 | 1 << 15 | 1 << 16 | 1 << 17 | 1 << 18 | 1 << 19 | 1 << 20 | |
| 187 1 << 21 | 1 << 22 | 1 << 23 | 1 << 24 | 1 << 25 | 1 << 26 | 1 << 27 | | 192 1 << 21 | 1 << 22 | 1 << 23 | 1 << 24 | 1 << 25 | 1 << 26 | 1 << 27 | |
| 188 1 << 28 | 1 << 30; | 193 (FLAG_enable_embedded_constant_pool ? 0 : 1 << 28) | 1 << 30; |
| 189 | 194 |
| 190 static Register from_code(int code) { | 195 static Register from_code(int code) { |
| 191 Register r = {code}; | 196 Register r = {code}; |
| 192 return r; | 197 return r; |
| 193 } | 198 } |
| 194 | 199 |
| 195 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } | 200 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } |
| 196 bool is(Register reg) const { return code_ == reg.code_; } | 201 bool is(Register reg) const { return code_ == reg.code_; } |
| 197 int code() const { | 202 int code() const { |
| 198 DCHECK(is_valid()); | 203 DCHECK(is_valid()); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 const int kRegister_r18_Code = 18; | 241 const int kRegister_r18_Code = 18; |
| 237 const int kRegister_r19_Code = 19; | 242 const int kRegister_r19_Code = 19; |
| 238 const int kRegister_r20_Code = 20; | 243 const int kRegister_r20_Code = 20; |
| 239 const int kRegister_r21_Code = 21; | 244 const int kRegister_r21_Code = 21; |
| 240 const int kRegister_r22_Code = 22; | 245 const int kRegister_r22_Code = 22; |
| 241 const int kRegister_r23_Code = 23; | 246 const int kRegister_r23_Code = 23; |
| 242 const int kRegister_r24_Code = 24; | 247 const int kRegister_r24_Code = 24; |
| 243 const int kRegister_r25_Code = 25; | 248 const int kRegister_r25_Code = 25; |
| 244 const int kRegister_r26_Code = 26; | 249 const int kRegister_r26_Code = 26; |
| 245 const int kRegister_r27_Code = 27; | 250 const int kRegister_r27_Code = 27; |
| 246 const int kRegister_r28_Code = 28; | 251 const int kRegister_r28_Code = 28; // constant pool pointer |
| 247 const int kRegister_r29_Code = 29; // roots array pointer | 252 const int kRegister_r29_Code = 29; // roots array pointer |
| 248 const int kRegister_r30_Code = 30; // context pointer | 253 const int kRegister_r30_Code = 30; // context pointer |
| 249 const int kRegister_fp_Code = 31; // frame pointer | 254 const int kRegister_fp_Code = 31; // frame pointer |
| 250 | 255 |
| 251 const Register no_reg = {kRegister_no_reg_Code}; | 256 const Register no_reg = {kRegister_no_reg_Code}; |
| 252 | 257 |
| 253 const Register r0 = {kRegister_r0_Code}; | 258 const Register r0 = {kRegister_r0_Code}; |
| 254 const Register sp = {kRegister_sp_Code}; | 259 const Register sp = {kRegister_sp_Code}; |
| 255 const Register r2 = {kRegister_r2_Code}; | 260 const Register r2 = {kRegister_r2_Code}; |
| 256 const Register r3 = {kRegister_r3_Code}; | 261 const Register r3 = {kRegister_r3_Code}; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 280 const Register r26 = {kRegister_r26_Code}; | 285 const Register r26 = {kRegister_r26_Code}; |
| 281 const Register r27 = {kRegister_r27_Code}; | 286 const Register r27 = {kRegister_r27_Code}; |
| 282 const Register r28 = {kRegister_r28_Code}; | 287 const Register r28 = {kRegister_r28_Code}; |
| 283 const Register r29 = {kRegister_r29_Code}; | 288 const Register r29 = {kRegister_r29_Code}; |
| 284 const Register r30 = {kRegister_r30_Code}; | 289 const Register r30 = {kRegister_r30_Code}; |
| 285 const Register fp = {kRegister_fp_Code}; | 290 const Register fp = {kRegister_fp_Code}; |
| 286 | 291 |
| 287 // Give alias names to registers | 292 // Give alias names to registers |
| 288 const Register cp = {kRegister_r30_Code}; // JavaScript context pointer | 293 const Register cp = {kRegister_r30_Code}; // JavaScript context pointer |
| 289 const Register kRootRegister = {kRegister_r29_Code}; // Roots array pointer. | 294 const Register kRootRegister = {kRegister_r29_Code}; // Roots array pointer. |
| 295 const Register kConstantPoolRegister = {kRegister_r28_Code}; // Constant pool |
| 290 | 296 |
| 291 // Double word FP register. | 297 // Double word FP register. |
| 292 struct DoubleRegister { | 298 struct DoubleRegister { |
| 293 static const int kNumRegisters = 32; | 299 static const int kNumRegisters = 32; |
| 294 static const int kMaxNumRegisters = kNumRegisters; | 300 static const int kMaxNumRegisters = kNumRegisters; |
| 295 static const int kNumVolatileRegisters = 14; // d0-d13 | 301 static const int kNumVolatileRegisters = 14; // d0-d13 |
| 296 static const int kSizeInBytes = 8; | 302 static const int kSizeInBytes = 8; |
| 297 | 303 |
| 298 static const int kAllocatableLowRangeBegin = 1; | 304 static const int kAllocatableLowRangeBegin = 1; |
| 299 static const int kAllocatableLowRangeEnd = 12; | 305 static const int kAllocatableLowRangeEnd = 12; |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 RelocInfo::Mode rmode() const { return rmode_; } | 534 RelocInfo::Mode rmode() const { return rmode_; } |
| 529 intptr_t data() const { return data_; } | 535 intptr_t data() const { return data_; } |
| 530 | 536 |
| 531 private: | 537 private: |
| 532 int position_; | 538 int position_; |
| 533 RelocInfo::Mode rmode_; | 539 RelocInfo::Mode rmode_; |
| 534 intptr_t data_; | 540 intptr_t data_; |
| 535 }; | 541 }; |
| 536 | 542 |
| 537 | 543 |
| 544 // Class used to build a constant pool. |
| 545 class ConstantPoolBuilder BASE_EMBEDDED { |
| 546 public: |
| 547 ConstantPoolBuilder(); |
| 548 void AddEntry(int position, RelocInfo::Mode rmode, intptr_t value, |
| 549 bool sharing_ok) { |
| 550 DCHECK(rmode != RelocInfo::COMMENT && rmode != RelocInfo::POSITION && |
| 551 rmode != RelocInfo::STATEMENT_POSITION); |
| 552 ConstantPoolEntry entry(position, rmode, value); |
| 553 AddEntry(entry, sharing_ok); |
| 554 } |
| 555 void AddEntry(int position, double value) { |
| 556 ConstantPoolEntry entry(position, RelocInfo::NONE64, value); |
| 557 AddEntry(entry, true); |
| 558 } |
| 559 int Emit(Assembler* assm); |
| 560 inline Label* Position() { return &label_; } |
| 561 |
| 562 // This implementation does not currently support an unlimited constant |
| 563 // pool size (which would require a multi-instruction sequence). |
| 564 inline bool IsFull() const { return !is_int16(size_); } |
| 565 inline bool IsEmpty() const { return entries_.size() == 0; } |
| 566 inline bool IsEmitted() const { return label_.is_bound(); } |
| 567 |
| 568 private: |
| 569 enum Type { |
| 570 #if !V8_TARGET_ARCH_PPC64 |
| 571 INT64, |
| 572 #endif |
| 573 PTR, |
| 574 NUMBER_OF_TYPES, |
| 575 }; |
| 576 |
| 577 struct ConstantPoolEntry { |
| 578 ConstantPoolEntry(int position, RelocInfo::Mode rmode, intptr_t value) |
| 579 : position_(position), |
| 580 merged_index_(-1), |
| 581 rmode_(rmode), |
| 582 value_(value) {} |
| 583 ConstantPoolEntry(int position, RelocInfo::Mode rmode, double value) |
| 584 : position_(position), |
| 585 merged_index_(-1), |
| 586 rmode_(rmode), |
| 587 value64_(value) {} |
| 588 |
| 589 bool IsEqual(const ConstantPoolEntry& entry) const { |
| 590 return rmode_ == entry.rmode_ && |
| 591 #if V8_TARGET_ARCH_PPC64 |
| 592 value_ == entry.value_; |
| 593 #else |
| 594 ((rmode_ == RelocInfo::NONE64) ? raw_value64_ == entry.raw_value64_ |
| 595 : value_ == entry.value_); |
| 596 #endif |
| 597 } |
| 598 |
| 599 Type type() { |
| 600 #if !V8_TARGET_ARCH_PPC64 |
| 601 if (rmode_ == RelocInfo::NONE64) { |
| 602 return INT64; |
| 603 } |
| 604 #endif |
| 605 return PTR; |
| 606 } |
| 607 |
| 608 int size() { |
| 609 #if !V8_TARGET_ARCH_PPC64 |
| 610 if (rmode_ == RelocInfo::NONE64) { |
| 611 return kInt64Size; |
| 612 } |
| 613 #endif |
| 614 return kPointerSize; |
| 615 } |
| 616 |
| 617 int position_; |
| 618 int merged_index_; |
| 619 RelocInfo::Mode rmode_; |
| 620 union { |
| 621 intptr_t value_; |
| 622 double value64_; |
| 623 #if !V8_TARGET_ARCH_PPC64 |
| 624 int64_t raw_value64_; |
| 625 #endif |
| 626 }; |
| 627 }; |
| 628 |
| 629 class NumberOfEntries { |
| 630 public: |
| 631 inline NumberOfEntries() { |
| 632 for (int i = 0; i < NUMBER_OF_TYPES; i++) { |
| 633 element_counts_[i] = 0; |
| 634 } |
| 635 } |
| 636 |
| 637 inline void increment(Type type) { |
| 638 DCHECK(type < NUMBER_OF_TYPES); |
| 639 element_counts_[type]++; |
| 640 } |
| 641 |
| 642 inline int count_of(Type type) const { return element_counts_[type]; } |
| 643 |
| 644 inline int size() { |
| 645 int size = count_of(PTR) * kPointerSize; |
| 646 #if !V8_TARGET_ARCH_PPC64 |
| 647 size += count_of(INT64) * kInt64Size; |
| 648 #endif |
| 649 return size; |
| 650 } |
| 651 |
| 652 private: |
| 653 int element_counts_[NUMBER_OF_TYPES]; |
| 654 }; |
| 655 |
| 656 void AddEntry(ConstantPoolEntry& entry, bool sharing_ok); |
| 657 void EmitGroup(Assembler* assm, int entrySize); |
| 658 |
| 659 int size_; |
| 660 std::vector<ConstantPoolEntry> entries_; |
| 661 NumberOfEntries number_of_entries_; |
| 662 Label label_; |
| 663 }; |
| 664 |
| 665 |
| 538 class Assembler : public AssemblerBase { | 666 class Assembler : public AssemblerBase { |
| 539 public: | 667 public: |
| 540 // Create an assembler. Instructions and relocation information are emitted | 668 // Create an assembler. Instructions and relocation information are emitted |
| 541 // into a buffer, with the instructions starting from the beginning and the | 669 // into a buffer, with the instructions starting from the beginning and the |
| 542 // relocation information starting from the end of the buffer. See CodeDesc | 670 // relocation information starting from the end of the buffer. See CodeDesc |
| 543 // for a detailed comment on the layout (globals.h). | 671 // for a detailed comment on the layout (globals.h). |
| 544 // | 672 // |
| 545 // If the provided buffer is NULL, the assembler allocates and grows its own | 673 // If the provided buffer is NULL, the assembler allocates and grows its own |
| 546 // buffer, and buffer_size determines the initial buffer size. The buffer is | 674 // buffer, and buffer_size determines the initial buffer size. The buffer is |
| 547 // owned by the assembler and deallocated upon destruction of the assembler. | 675 // owned by the assembler and deallocated upon destruction of the assembler. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 // Manages the jump elimination optimization if the second parameter is true. | 717 // Manages the jump elimination optimization if the second parameter is true. |
| 590 int branch_offset(Label* L, bool jump_elimination_allowed) { | 718 int branch_offset(Label* L, bool jump_elimination_allowed) { |
| 591 int position = link(L); | 719 int position = link(L); |
| 592 return position - pc_offset(); | 720 return position - pc_offset(); |
| 593 } | 721 } |
| 594 | 722 |
| 595 // Puts a labels target address at the given position. | 723 // Puts a labels target address at the given position. |
| 596 // The high 8 bits are set to zero. | 724 // The high 8 bits are set to zero. |
| 597 void label_at_put(Label* L, int at_offset); | 725 void label_at_put(Label* L, int at_offset); |
| 598 | 726 |
| 727 INLINE(static bool IsConstantPoolLoadStart(Address pc)); |
| 728 INLINE(static bool IsConstantPoolLoadEnd(Address pc)); |
| 729 INLINE(static int GetConstantPoolOffset(Address pc)); |
| 730 INLINE(void SetConstantPoolOffset(int pos, int offset)); |
| 731 |
| 732 // Return the address in the constant pool of the code target address used by |
| 733 // the branch/call instruction at pc, or the object in a mov. |
| 734 INLINE(static Address target_constant_pool_address_at(Address pc, |
| 735 Address constant_pool)); |
| 736 |
| 599 // Read/Modify the code target address in the branch/call instruction at pc. | 737 // Read/Modify the code target address in the branch/call instruction at pc. |
| 600 INLINE(static Address target_address_at(Address pc, | 738 INLINE(static Address target_address_at(Address pc, Address constant_pool)); |
| 601 ConstantPoolArray* constant_pool)); | |
| 602 INLINE(static void set_target_address_at( | 739 INLINE(static void set_target_address_at( |
| 603 Address pc, ConstantPoolArray* constant_pool, Address target, | 740 Address pc, Address constant_pool, Address target, |
| 604 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)); | 741 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)); |
| 605 INLINE(static Address target_address_at(Address pc, Code* code)) { | 742 INLINE(static Address target_address_at(Address pc, Code* code)) { |
| 606 ConstantPoolArray* constant_pool = NULL; | 743 Address constant_pool = code ? code->constant_pool() : NULL; |
| 607 return target_address_at(pc, constant_pool); | 744 return target_address_at(pc, constant_pool); |
| 608 } | 745 } |
| 609 INLINE(static void set_target_address_at( | 746 INLINE(static void set_target_address_at( |
| 610 Address pc, Code* code, Address target, | 747 Address pc, Code* code, Address target, |
| 611 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) { | 748 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) { |
| 612 ConstantPoolArray* constant_pool = NULL; | 749 Address constant_pool = code ? code->constant_pool() : NULL; |
| 613 set_target_address_at(pc, constant_pool, target, icache_flush_mode); | 750 set_target_address_at(pc, constant_pool, target, icache_flush_mode); |
| 614 } | 751 } |
| 615 | 752 |
| 616 // Return the code target address at a call site from the return address | 753 // Return the code target address at a call site from the return address |
| 617 // of that call in the instruction stream. | 754 // of that call in the instruction stream. |
| 618 inline static Address target_address_from_return_address(Address pc); | 755 inline static Address target_address_from_return_address(Address pc); |
| 619 | 756 |
| 620 // Given the address of the beginning of a call, return the address | 757 // Given the address of the beginning of a call, return the address |
| 621 // in the instruction stream that the call will return to. | 758 // in the instruction stream that the call will return to. |
| 622 INLINE(static Address return_address_from_call_start(Address pc)); | 759 INLINE(static Address return_address_from_call_start(Address pc)); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 640 // Here we are patching the address in the LUI/ORI instruction pair. | 777 // Here we are patching the address in the LUI/ORI instruction pair. |
| 641 // These values are used in the serialization process and must be zero for | 778 // These values are used in the serialization process and must be zero for |
| 642 // PPC platform, as Code, Embedded Object or External-reference pointers | 779 // PPC platform, as Code, Embedded Object or External-reference pointers |
| 643 // are split across two consecutive instructions and don't exist separately | 780 // are split across two consecutive instructions and don't exist separately |
| 644 // in the code, so the serializer should not step forwards in memory after | 781 // in the code, so the serializer should not step forwards in memory after |
| 645 // a target is resolved and written. | 782 // a target is resolved and written. |
| 646 static const int kSpecialTargetSize = 0; | 783 static const int kSpecialTargetSize = 0; |
| 647 | 784 |
| 648 // Number of instructions to load an address via a mov sequence. | 785 // Number of instructions to load an address via a mov sequence. |
| 649 #if V8_TARGET_ARCH_PPC64 | 786 #if V8_TARGET_ARCH_PPC64 |
| 650 static const int kMovInstructions = 5; | 787 static const int kMovInstructionsConstantPool = 1; |
| 788 static const int kMovInstructionsNoConstantPool = 5; |
| 651 static const int kTaggedLoadInstructions = 2; | 789 static const int kTaggedLoadInstructions = 2; |
| 652 #else | 790 #else |
| 653 static const int kMovInstructions = 2; | 791 static const int kMovInstructionsConstantPool = 1; |
| 792 static const int kMovInstructionsNoConstantPool = 2; |
| 654 static const int kTaggedLoadInstructions = 1; | 793 static const int kTaggedLoadInstructions = 1; |
| 655 #endif | 794 #endif |
| 795 static const int kMovInstructions = FLAG_enable_embedded_constant_pool |
| 796 ? kMovInstructionsConstantPool |
| 797 : kMovInstructionsNoConstantPool; |
| 656 | 798 |
| 657 // Distance between the instruction referring to the address of the call | 799 // Distance between the instruction referring to the address of the call |
| 658 // target and the return address. | 800 // target and the return address. |
| 659 | 801 |
| 660 // Call sequence is a FIXED_SEQUENCE: | 802 // Call sequence is a FIXED_SEQUENCE: |
| 661 // mov r8, @ call address | 803 // mov r8, @ call address |
| 662 // mtlr r8 | 804 // mtlr r8 |
| 663 // blrl | 805 // blrl |
| 664 // @ return address | 806 // @ return address |
| 665 static const int kCallTargetAddressOffset = | 807 static const int kCallTargetAddressOffset = |
| (...skipping 10 matching lines...) Expand all Loading... |
| 676 // Distance between start of patched debug break slot and the emitted address | 818 // Distance between start of patched debug break slot and the emitted address |
| 677 // to jump to. | 819 // to jump to. |
| 678 // Patched debug break slot code is a FIXED_SEQUENCE: | 820 // Patched debug break slot code is a FIXED_SEQUENCE: |
| 679 // mov r0, <address> | 821 // mov r0, <address> |
| 680 // mtlr r0 | 822 // mtlr r0 |
| 681 // blrl | 823 // blrl |
| 682 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; | 824 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; |
| 683 | 825 |
| 684 // This is the length of the BreakLocation::SetDebugBreakAtReturn() | 826 // This is the length of the BreakLocation::SetDebugBreakAtReturn() |
| 685 // code patch FIXED_SEQUENCE | 827 // code patch FIXED_SEQUENCE |
| 686 static const int kJSReturnSequenceInstructions = kMovInstructions + 3; | 828 static const int kJSReturnSequenceInstructions = |
| 829 kMovInstructionsNoConstantPool + 3; |
| 687 static const int kJSReturnSequenceLength = | 830 static const int kJSReturnSequenceLength = |
| 688 kJSReturnSequenceInstructions * kInstrSize; | 831 kJSReturnSequenceInstructions * kInstrSize; |
| 689 | 832 |
| 690 // This is the length of the code sequence from SetDebugBreakAtSlot() | 833 // This is the length of the code sequence from SetDebugBreakAtSlot() |
| 691 // FIXED_SEQUENCE | 834 // FIXED_SEQUENCE |
| 692 static const int kDebugBreakSlotInstructions = kMovInstructions + 2; | 835 static const int kDebugBreakSlotInstructions = |
| 836 kMovInstructionsNoConstantPool + 2; |
| 693 static const int kDebugBreakSlotLength = | 837 static const int kDebugBreakSlotLength = |
| 694 kDebugBreakSlotInstructions * kInstrSize; | 838 kDebugBreakSlotInstructions * kInstrSize; |
| 695 | 839 |
| 696 static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) { | 840 static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) { |
| 697 return ((cr.code() * CRWIDTH) + crbit); | 841 return ((cr.code() * CRWIDTH) + crbit); |
| 698 } | 842 } |
| 699 | 843 |
| 700 // --------------------------------------------------------------------------- | 844 // --------------------------------------------------------------------------- |
| 701 // Code generation | 845 // Code generation |
| 702 | 846 |
| (...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1195 assem_->StartBlockTrampolinePool(); | 1339 assem_->StartBlockTrampolinePool(); |
| 1196 } | 1340 } |
| 1197 ~BlockTrampolinePoolScope() { assem_->EndBlockTrampolinePool(); } | 1341 ~BlockTrampolinePoolScope() { assem_->EndBlockTrampolinePool(); } |
| 1198 | 1342 |
| 1199 private: | 1343 private: |
| 1200 Assembler* assem_; | 1344 Assembler* assem_; |
| 1201 | 1345 |
| 1202 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope); | 1346 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope); |
| 1203 }; | 1347 }; |
| 1204 | 1348 |
| 1349 // Class for scoping disabling constant pool entry merging |
| 1350 class BlockConstantPoolEntrySharingScope { |
| 1351 public: |
| 1352 explicit BlockConstantPoolEntrySharingScope(Assembler* assem) |
| 1353 : assem_(assem) { |
| 1354 assem_->StartBlockConstantPoolEntrySharing(); |
| 1355 } |
| 1356 ~BlockConstantPoolEntrySharingScope() { |
| 1357 assem_->EndBlockConstantPoolEntrySharing(); |
| 1358 } |
| 1359 |
| 1360 private: |
| 1361 Assembler* assem_; |
| 1362 |
| 1363 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstantPoolEntrySharingScope); |
| 1364 }; |
| 1365 |
| 1205 // Debugging | 1366 // Debugging |
| 1206 | 1367 |
| 1207 // Mark address of the ExitJSFrame code. | 1368 // Mark address of the ExitJSFrame code. |
| 1208 void RecordJSReturn(); | 1369 void RecordJSReturn(); |
| 1209 | 1370 |
| 1210 // Mark address of a debug break slot. | 1371 // Mark address of a debug break slot. |
| 1211 void RecordDebugBreakSlot(); | 1372 void RecordDebugBreakSlot(); |
| 1212 | 1373 |
| 1213 // Record the AST id of the CallIC being compiled, so that it can be placed | 1374 // Record the AST id of the CallIC being compiled, so that it can be placed |
| 1214 // in the relocation information. | 1375 // in the relocation information. |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1278 static bool IsCrSet(Instr instr); | 1439 static bool IsCrSet(Instr instr); |
| 1279 static Register GetCmpImmediateRegister(Instr instr); | 1440 static Register GetCmpImmediateRegister(Instr instr); |
| 1280 static int GetCmpImmediateRawImmediate(Instr instr); | 1441 static int GetCmpImmediateRawImmediate(Instr instr); |
| 1281 static bool IsNop(Instr instr, int type = NON_MARKING_NOP); | 1442 static bool IsNop(Instr instr, int type = NON_MARKING_NOP); |
| 1282 | 1443 |
| 1283 // Postpone the generation of the trampoline pool for the specified number of | 1444 // Postpone the generation of the trampoline pool for the specified number of |
| 1284 // instructions. | 1445 // instructions. |
| 1285 void BlockTrampolinePoolFor(int instructions); | 1446 void BlockTrampolinePoolFor(int instructions); |
| 1286 void CheckTrampolinePool(); | 1447 void CheckTrampolinePool(); |
| 1287 | 1448 |
| 1449 // For mov. Return the number of actual instructions required to |
| 1450 // load the operand into a register. This can be anywhere from |
| 1451 // one (constant pool small section) to five instructions (full |
| 1452 // 64-bit sequence). |
| 1453 // |
| 1454 // The value returned is only valid as long as no entries are added to the |
| 1455 // constant pool between this call and the actual instruction being emitted. |
| 1456 int instructions_required_for_mov(const Operand& x) const; |
| 1457 |
| 1458 // Decide between using the constant pool vs. a mov immediate sequence. |
| 1459 bool use_constant_pool_for_mov(const Operand& x, bool canOptimize) const; |
| 1460 |
| 1288 // The code currently calls CheckBuffer() too often. This has the side | 1461 // The code currently calls CheckBuffer() too often. This has the side |
| 1289 // effect of randomly growing the buffer in the middle of multi-instruction | 1462 // effect of randomly growing the buffer in the middle of multi-instruction |
| 1290 // sequences. | 1463 // sequences. |
| 1291 // | 1464 // |
| 1292 // This function allows outside callers to check and grow the buffer | 1465 // This function allows outside callers to check and grow the buffer |
| 1293 void EnsureSpaceFor(int space_needed); | 1466 void EnsureSpaceFor(int space_needed); |
| 1294 | 1467 |
| 1295 // Allocate a constant pool of the correct size for the generated code. | 1468 // Allocate a constant pool of the correct size for the generated code. |
| 1296 Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate); | 1469 Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate); |
| 1297 | 1470 |
| 1298 // Generate the constant pool for the generated code. | 1471 // Generate the constant pool for the generated code. |
| 1299 void PopulateConstantPool(ConstantPoolArray* constant_pool); | 1472 void PopulateConstantPool(ConstantPoolArray* constant_pool); |
| 1300 | 1473 |
| 1474 int EmitConstantPool() { return constant_pool_builder_.Emit(this); } |
| 1475 |
| 1476 bool is_constant_pool_full() const { return constant_pool_builder_.IsFull(); } |
| 1477 |
| 1478 Label* ConstantPoolPosition() { return constant_pool_builder_.Position(); } |
| 1479 |
| 1301 void EmitRelocations(); | 1480 void EmitRelocations(); |
| 1302 | 1481 |
| 1303 protected: | 1482 protected: |
| 1304 // Relocation for a type-recording IC has the AST id added to it. This | 1483 // Relocation for a type-recording IC has the AST id added to it. This |
| 1305 // member variable is a way to pass the information from the call site to | 1484 // member variable is a way to pass the information from the call site to |
| 1306 // the relocation info. | 1485 // the relocation info. |
| 1307 TypeFeedbackId recorded_ast_id_; | 1486 TypeFeedbackId recorded_ast_id_; |
| 1308 | 1487 |
| 1309 int buffer_space() const { return reloc_info_writer.pos() - pc_; } | 1488 int buffer_space() const { return reloc_info_writer.pos() - pc_; } |
| 1310 | 1489 |
| 1311 // Decode branch instruction at pos and return branch target pos | 1490 // Decode branch instruction at pos and return branch target pos |
| 1312 int target_at(int pos); | 1491 int target_at(int pos); |
| 1313 | 1492 |
| 1314 // Patch branch instruction at pos to branch to given branch target pos | 1493 // Patch branch instruction at pos to branch to given branch target pos |
| 1315 void target_at_put(int pos, int target_pos); | 1494 void target_at_put(int pos, int target_pos); |
| 1316 | 1495 |
| 1317 // Record reloc info for current pc_ | 1496 // Record reloc info for current pc_ |
| 1318 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); | 1497 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); |
| 1319 void RecordRelocInfo(const DeferredRelocInfo& rinfo); | 1498 void RecordRelocInfo(const DeferredRelocInfo& rinfo); |
| 1499 void ConstantPoolAddEntry(RelocInfo::Mode rmode, intptr_t value) { |
| 1500 bool sharing_ok = RelocInfo::IsNone(rmode) || |
| 1501 !(serializer_enabled() || rmode < RelocInfo::CELL || |
| 1502 is_constant_pool_entry_sharing_blocked()); |
| 1503 constant_pool_builder_.AddEntry(pc_offset(), rmode, value, sharing_ok); |
| 1504 } |
| 1505 void ConstantPoolAddEntry(double value) { |
| 1506 constant_pool_builder_.AddEntry(pc_offset(), value); |
| 1507 } |
| 1320 | 1508 |
| 1321 // Block the emission of the trampoline pool before pc_offset. | 1509 // Block the emission of the trampoline pool before pc_offset. |
| 1322 void BlockTrampolinePoolBefore(int pc_offset) { | 1510 void BlockTrampolinePoolBefore(int pc_offset) { |
| 1323 if (no_trampoline_pool_before_ < pc_offset) | 1511 if (no_trampoline_pool_before_ < pc_offset) |
| 1324 no_trampoline_pool_before_ = pc_offset; | 1512 no_trampoline_pool_before_ = pc_offset; |
| 1325 } | 1513 } |
| 1326 | 1514 |
| 1327 void StartBlockTrampolinePool() { trampoline_pool_blocked_nesting_++; } | 1515 void StartBlockTrampolinePool() { trampoline_pool_blocked_nesting_++; } |
| 1328 void EndBlockTrampolinePool() { trampoline_pool_blocked_nesting_--; } | 1516 void EndBlockTrampolinePool() { trampoline_pool_blocked_nesting_--; } |
| 1329 bool is_trampoline_pool_blocked() const { | 1517 bool is_trampoline_pool_blocked() const { |
| 1330 return trampoline_pool_blocked_nesting_ > 0; | 1518 return trampoline_pool_blocked_nesting_ > 0; |
| 1331 } | 1519 } |
| 1332 | 1520 |
| 1521 void StartBlockConstantPoolEntrySharing() { |
| 1522 constant_pool_entry_sharing_blocked_nesting_++; |
| 1523 } |
| 1524 void EndBlockConstantPoolEntrySharing() { |
| 1525 constant_pool_entry_sharing_blocked_nesting_--; |
| 1526 } |
| 1527 bool is_constant_pool_entry_sharing_blocked() const { |
| 1528 return constant_pool_entry_sharing_blocked_nesting_ > 0; |
| 1529 } |
| 1530 |
| 1333 bool has_exception() const { return internal_trampoline_exception_; } | 1531 bool has_exception() const { return internal_trampoline_exception_; } |
| 1334 | 1532 |
| 1335 bool is_trampoline_emitted() const { return trampoline_emitted_; } | 1533 bool is_trampoline_emitted() const { return trampoline_emitted_; } |
| 1336 | 1534 |
| 1337 private: | 1535 private: |
| 1338 // Code generation | 1536 // Code generation |
| 1339 // The relocation writer's position is at least kGap bytes below the end of | 1537 // The relocation writer's position is at least kGap bytes below the end of |
| 1340 // the generated instructions. This is so that multi-instruction sequences do | 1538 // the generated instructions. This is so that multi-instruction sequences do |
| 1341 // not have to check for overflow. The same is true for writes of large | 1539 // not have to check for overflow. The same is true for writes of large |
| 1342 // relocation info entries. | 1540 // relocation info entries. |
| 1343 static const int kGap = 32; | 1541 static const int kGap = 32; |
| 1344 | 1542 |
| 1345 // Repeated checking whether the trampoline pool should be emitted is rather | 1543 // Repeated checking whether the trampoline pool should be emitted is rather |
| 1346 // expensive. By default we only check again once a number of instructions | 1544 // expensive. By default we only check again once a number of instructions |
| 1347 // has been generated. | 1545 // has been generated. |
| 1348 int next_buffer_check_; // pc offset of next buffer check. | 1546 int next_buffer_check_; // pc offset of next buffer check. |
| 1349 | 1547 |
| 1350 // Emission of the trampoline pool may be blocked in some code sequences. | 1548 // Emission of the trampoline pool may be blocked in some code sequences. |
| 1351 int trampoline_pool_blocked_nesting_; // Block emission if this is not zero. | 1549 int trampoline_pool_blocked_nesting_; // Block emission if this is not zero. |
| 1352 int no_trampoline_pool_before_; // Block emission before this pc offset. | 1550 int no_trampoline_pool_before_; // Block emission before this pc offset. |
| 1353 | 1551 |
| 1552 // Do not share constant pool entries. |
| 1553 int constant_pool_entry_sharing_blocked_nesting_; |
| 1554 |
| 1354 // Relocation info generation | 1555 // Relocation info generation |
| 1355 // Each relocation is encoded as a variable size value | 1556 // Each relocation is encoded as a variable size value |
| 1356 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; | 1557 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; |
| 1357 RelocInfoWriter reloc_info_writer; | 1558 RelocInfoWriter reloc_info_writer; |
| 1358 std::vector<DeferredRelocInfo> relocations_; | 1559 std::vector<DeferredRelocInfo> relocations_; |
| 1359 | 1560 |
| 1360 // The bound position, before this we cannot do instruction elimination. | 1561 // The bound position, before this we cannot do instruction elimination. |
| 1361 int last_bound_pos_; | 1562 int last_bound_pos_; |
| 1362 | 1563 |
| 1564 ConstantPoolBuilder constant_pool_builder_; |
| 1565 |
| 1363 // Code emission | 1566 // Code emission |
| 1364 inline void CheckBuffer(); | 1567 inline void CheckBuffer(); |
| 1365 void GrowBuffer(int needed = 0); | 1568 void GrowBuffer(int needed = 0); |
| 1366 inline void emit(Instr x); | 1569 inline void emit(Instr x); |
| 1367 inline void CheckTrampolinePoolQuick(); | 1570 inline void CheckTrampolinePoolQuick(); |
| 1368 | 1571 |
| 1369 // Instruction generation | 1572 // Instruction generation |
| 1370 void a_form(Instr instr, DoubleRegister frt, DoubleRegister fra, | 1573 void a_form(Instr instr, DoubleRegister frt, DoubleRegister fra, |
| 1371 DoubleRegister frb, RCBit r); | 1574 DoubleRegister frb, RCBit r); |
| 1372 void d_form(Instr instr, Register rt, Register ra, const intptr_t val, | 1575 void d_form(Instr instr, Register rt, Register ra, const intptr_t val, |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1443 | 1646 |
| 1444 | 1647 |
| 1445 class EnsureSpace BASE_EMBEDDED { | 1648 class EnsureSpace BASE_EMBEDDED { |
| 1446 public: | 1649 public: |
| 1447 explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); } | 1650 explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); } |
| 1448 }; | 1651 }; |
| 1449 } | 1652 } |
| 1450 } // namespace v8::internal | 1653 } // namespace v8::internal |
| 1451 | 1654 |
| 1452 #endif // V8_PPC_ASSEMBLER_PPC_H_ | 1655 #endif // V8_PPC_ASSEMBLER_PPC_H_ |
| OLD | NEW |