OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // | 2 // |
3 // Redistribution and use in source and binary forms, with or without | 3 // Redistribution and use in source and binary forms, with or without |
4 // modification, are permitted provided that the following conditions are | 4 // modification, are permitted provided that the following conditions are |
5 // met: | 5 // met: |
6 // | 6 // |
7 // * Redistributions of source code must retain the above copyright | 7 // * Redistributions of source code must retain the above copyright |
8 // notice, this list of conditions and the following disclaimer. | 8 // notice, this list of conditions and the following disclaimer. |
9 // * Redistributions in binary form must reproduce the above | 9 // * Redistributions in binary form must reproduce the above |
10 // copyright notice, this list of conditions and the following | 10 // copyright notice, this list of conditions and the following |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 // Add the link register (x30) to the safepoint list. | 164 // Add the link register (x30) to the safepoint list. |
165 list.Combine(30); | 165 list.Combine(30); |
166 | 166 |
167 return list; | 167 return list; |
168 } | 168 } |
169 | 169 |
170 | 170 |
171 // ----------------------------------------------------------------------------- | 171 // ----------------------------------------------------------------------------- |
172 // Implementation of RelocInfo | 172 // Implementation of RelocInfo |
173 | 173 |
174 const int RelocInfo::kApplyMask = 0; | 174 const int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE; |
175 | 175 |
176 | 176 |
177 bool RelocInfo::IsCodedSpecially() { | 177 bool RelocInfo::IsCodedSpecially() { |
178 // The deserializer needs to know whether a pointer is specially coded. Being | 178 // The deserializer needs to know whether a pointer is specially coded. Being |
179 // specially coded on ARM64 means that it is a movz/movk sequence. We don't | 179 // specially coded on ARM64 means that it is a movz/movk sequence. We don't |
180 // generate those for relocatable pointers. | 180 // generate those for relocatable pointers. |
181 return false; | 181 return false; |
182 } | 182 } |
183 | 183 |
184 | 184 |
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 | 725 |
726 CheckLabelLinkChain(label); | 726 CheckLabelLinkChain(label); |
727 | 727 |
728 DCHECK(linkoffset >= 0); | 728 DCHECK(linkoffset >= 0); |
729 DCHECK(linkoffset < pc_offset()); | 729 DCHECK(linkoffset < pc_offset()); |
730 DCHECK((linkoffset > prevlinkoffset) || | 730 DCHECK((linkoffset > prevlinkoffset) || |
731 (linkoffset - prevlinkoffset == kStartOfLabelLinkChain)); | 731 (linkoffset - prevlinkoffset == kStartOfLabelLinkChain)); |
732 DCHECK(prevlinkoffset >= 0); | 732 DCHECK(prevlinkoffset >= 0); |
733 | 733 |
734 // Update the link to point to the label. | 734 // Update the link to point to the label. |
735 link->SetImmPCOffsetTarget(reinterpret_cast<Instruction*>(pc_)); | 735 if (link->IsUnresolvedInternalReference()) { |
| 736 // Internal references do not get patched to an instruction but directly |
| 737 // to an address. |
| 738 internal_reference_positions_.push_back(linkoffset); |
| 739 PatchingAssembler patcher(link, 2); |
| 740 patcher.dc64(reinterpret_cast<uintptr_t>(pc_)); |
| 741 } else { |
| 742 link->SetImmPCOffsetTarget(reinterpret_cast<Instruction*>(pc_)); |
| 743 } |
736 | 744 |
737 // Link the label to the previous link in the chain. | 745 // Link the label to the previous link in the chain. |
738 if (linkoffset - prevlinkoffset == kStartOfLabelLinkChain) { | 746 if (linkoffset - prevlinkoffset == kStartOfLabelLinkChain) { |
739 // We hit kStartOfLabelLinkChain, so the chain is fully processed. | 747 // We hit kStartOfLabelLinkChain, so the chain is fully processed. |
740 label->Unuse(); | 748 label->Unuse(); |
741 } else { | 749 } else { |
742 // Update the label for the next iteration. | 750 // Update the label for the next iteration. |
743 label->link_to(prevlinkoffset); | 751 label->link_to(prevlinkoffset); |
744 } | 752 } |
745 } | 753 } |
(...skipping 1307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2053 unsigned fbits) { | 2061 unsigned fbits) { |
2054 if (fbits == 0) { | 2062 if (fbits == 0) { |
2055 Emit(SF(rn) | FPType(fd) | UCVTF | Rn(rn) | Rd(fd)); | 2063 Emit(SF(rn) | FPType(fd) | UCVTF | Rn(rn) | Rd(fd)); |
2056 } else { | 2064 } else { |
2057 Emit(SF(rn) | FPType(fd) | UCVTF_fixed | FPScale(64 - fbits) | Rn(rn) | | 2065 Emit(SF(rn) | FPType(fd) | UCVTF_fixed | FPScale(64 - fbits) | Rn(rn) | |
2058 Rd(fd)); | 2066 Rd(fd)); |
2059 } | 2067 } |
2060 } | 2068 } |
2061 | 2069 |
2062 | 2070 |
| 2071 void Assembler::dcptr(Label* label) { |
| 2072 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
| 2073 if (label->is_bound()) { |
| 2074 // The label is bound, so it does not need to be updated and the internal |
| 2075 // reference should be emitted. |
| 2076 // |
| 2077 // In this case, label->pos() returns the offset of the label from the |
| 2078 // start of the buffer. |
| 2079 internal_reference_positions_.push_back(pc_offset()); |
| 2080 dc64(reinterpret_cast<uintptr_t>(buffer_ + label->pos())); |
| 2081 } else { |
| 2082 int32_t offset; |
| 2083 if (label->is_linked()) { |
| 2084 // The label is linked, so the internal reference should be added |
| 2085 // onto the end of the label's link chain. |
| 2086 // |
| 2087 // In this case, label->pos() returns the offset of the last linked |
| 2088 // instruction from the start of the buffer. |
| 2089 offset = label->pos() - pc_offset(); |
| 2090 DCHECK(offset != kStartOfLabelLinkChain); |
| 2091 } else { |
| 2092 // The label is unused, so it now becomes linked and the internal |
| 2093 // reference is at the start of the new link chain. |
| 2094 offset = kStartOfLabelLinkChain; |
| 2095 } |
| 2096 // The instruction at pc is now the last link in the label's chain. |
| 2097 label->link_to(pc_offset()); |
| 2098 |
| 2099 // Traditionally the offset to the previous instruction in the chain is |
| 2100 // encoded in the instruction payload (e.g. branch range) but internal |
| 2101 // references are not instructions so while unbound they are encoded as |
| 2102 // two consecutive brk instructions. The two 16-bit immediates are used |
| 2103 // to encode the offset. |
| 2104 offset >>= kInstructionSizeLog2; |
| 2105 DCHECK(is_int32(offset)); |
| 2106 uint32_t high16 = unsigned_bitextract_32(31, 16, offset); |
| 2107 uint32_t low16 = unsigned_bitextract_32(15, 0, offset); |
| 2108 |
| 2109 brk(high16); |
| 2110 brk(low16); |
| 2111 } |
| 2112 } |
| 2113 |
| 2114 |
2063 // Note: | 2115 // Note: |
2064 // Below, a difference in case for the same letter indicates a | 2116 // Below, a difference in case for the same letter indicates a |
2065 // negated bit. | 2117 // negated bit. |
2066 // If b is 1, then B is 0. | 2118 // If b is 1, then B is 0. |
2067 Instr Assembler::ImmFP32(float imm) { | 2119 Instr Assembler::ImmFP32(float imm) { |
2068 DCHECK(IsImmFP32(imm)); | 2120 DCHECK(IsImmFP32(imm)); |
2069 // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000 | 2121 // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000 |
2070 uint32_t bits = float_to_rawbits(imm); | 2122 uint32_t bits = float_to_rawbits(imm); |
2071 // bit7: a000.0000 | 2123 // bit7: a000.0000 |
2072 uint32_t bit7 = ((bits >> 31) & 0x1) << 7; | 2124 uint32_t bit7 = ((bits >> 31) & 0x1) << 7; |
(...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2812 buffer_ = desc.buffer; | 2864 buffer_ = desc.buffer; |
2813 buffer_size_ = desc.buffer_size; | 2865 buffer_size_ = desc.buffer_size; |
2814 pc_ = reinterpret_cast<byte*>(pc_) + pc_delta; | 2866 pc_ = reinterpret_cast<byte*>(pc_) + pc_delta; |
2815 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, | 2867 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, |
2816 reloc_info_writer.last_pc() + pc_delta); | 2868 reloc_info_writer.last_pc() + pc_delta); |
2817 | 2869 |
2818 // None of our relocation types are pc relative pointing outside the code | 2870 // None of our relocation types are pc relative pointing outside the code |
2819 // buffer nor pc absolute pointing inside the code buffer, so there is no need | 2871 // buffer nor pc absolute pointing inside the code buffer, so there is no need |
2820 // to relocate any emitted relocation entries. | 2872 // to relocate any emitted relocation entries. |
2821 | 2873 |
| 2874 // Relocate internal references. |
| 2875 for (auto pos : internal_reference_positions_) { |
| 2876 intptr_t* p = reinterpret_cast<intptr_t*>(buffer_ + pos); |
| 2877 *p += pc_delta; |
| 2878 } |
| 2879 |
2822 // Pending relocation entries are also relative, no need to relocate. | 2880 // Pending relocation entries are also relative, no need to relocate. |
2823 } | 2881 } |
2824 | 2882 |
2825 | 2883 |
2826 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { | 2884 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { |
2827 // We do not try to reuse pool constants. | 2885 // We do not try to reuse pool constants. |
2828 RelocInfo rinfo(reinterpret_cast<byte*>(pc_), rmode, data, NULL); | 2886 RelocInfo rinfo(reinterpret_cast<byte*>(pc_), rmode, data, NULL); |
2829 if (((rmode >= RelocInfo::JS_RETURN) && | 2887 if (((rmode >= RelocInfo::JS_RETURN) && |
2830 (rmode <= RelocInfo::DEBUG_BREAK_SLOT)) || | 2888 (rmode <= RelocInfo::DEBUG_BREAK_SLOT)) || |
| 2889 (rmode == RelocInfo::INTERNAL_REFERENCE) || |
2831 (rmode == RelocInfo::CONST_POOL) || | 2890 (rmode == RelocInfo::CONST_POOL) || |
2832 (rmode == RelocInfo::VENEER_POOL) || | 2891 (rmode == RelocInfo::VENEER_POOL) || |
2833 (rmode == RelocInfo::DEOPT_REASON)) { | 2892 (rmode == RelocInfo::DEOPT_REASON)) { |
2834 // Adjust code for new modes. | 2893 // Adjust code for new modes. |
2835 DCHECK(RelocInfo::IsDebugBreakSlot(rmode) | 2894 DCHECK(RelocInfo::IsDebugBreakSlot(rmode) |
2836 || RelocInfo::IsJSReturn(rmode) | 2895 || RelocInfo::IsJSReturn(rmode) |
2837 || RelocInfo::IsComment(rmode) | 2896 || RelocInfo::IsComment(rmode) |
2838 || RelocInfo::IsDeoptReason(rmode) | 2897 || RelocInfo::IsDeoptReason(rmode) |
2839 || RelocInfo::IsPosition(rmode) | 2898 || RelocInfo::IsPosition(rmode) |
| 2899 || RelocInfo::IsInternalReference(rmode) |
2840 || RelocInfo::IsConstPool(rmode) | 2900 || RelocInfo::IsConstPool(rmode) |
2841 || RelocInfo::IsVeneerPool(rmode)); | 2901 || RelocInfo::IsVeneerPool(rmode)); |
2842 // These modes do not need an entry in the constant pool. | 2902 // These modes do not need an entry in the constant pool. |
2843 } else { | 2903 } else { |
2844 constpool_.RecordEntry(data, rmode); | 2904 constpool_.RecordEntry(data, rmode); |
2845 // Make sure the constant pool is not emitted in place of the next | 2905 // Make sure the constant pool is not emitted in place of the next |
2846 // instruction for which we just recorded relocation info. | 2906 // instruction for which we just recorded relocation info. |
2847 BlockConstPoolFor(1); | 2907 BlockConstPoolFor(1); |
2848 } | 2908 } |
2849 | 2909 |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3107 movz(scratch, (target_offset >> 16) & 0xFFFF, 16); | 3167 movz(scratch, (target_offset >> 16) & 0xFFFF, 16); |
3108 movk(scratch, (target_offset >> 32) & 0xFFFF, 32); | 3168 movk(scratch, (target_offset >> 32) & 0xFFFF, 32); |
3109 DCHECK((target_offset >> 48) == 0); | 3169 DCHECK((target_offset >> 48) == 0); |
3110 add(rd, rd, scratch); | 3170 add(rd, rd, scratch); |
3111 } | 3171 } |
3112 | 3172 |
3113 | 3173 |
3114 } } // namespace v8::internal | 3174 } } // namespace v8::internal |
3115 | 3175 |
3116 #endif // V8_TARGET_ARCH_ARM64 | 3176 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |