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 |