OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_ARM64_ASSEMBLER_ARM64_H_ | 5 #ifndef V8_ARM64_ASSEMBLER_ARM64_H_ |
6 #define V8_ARM64_ASSEMBLER_ARM64_H_ | 6 #define V8_ARM64_ASSEMBLER_ARM64_H_ |
7 | 7 |
8 #include <deque> | 8 #include <deque> |
9 #include <list> | 9 #include <list> |
10 #include <map> | 10 #include <map> |
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
795 int64_t offset_; | 795 int64_t offset_; |
796 AddrMode addrmode_; | 796 AddrMode addrmode_; |
797 Shift shift_; | 797 Shift shift_; |
798 Extend extend_; | 798 Extend extend_; |
799 unsigned shift_amount_; | 799 unsigned shift_amount_; |
800 }; | 800 }; |
801 | 801 |
802 | 802 |
803 class ConstPool { | 803 class ConstPool { |
804 public: | 804 public: |
805 explicit ConstPool(Assembler* assm) | 805 explicit ConstPool(Assembler* assm) : assm_(assm), first_use_(-1) {} |
806 : assm_(assm), | 806 // Returns true when we need to write RelocInfo and false when we do not. |
807 first_use_(-1), | 807 bool RecordEntry(intptr_t data, RelocInfo::Mode mode); |
808 shared_entries_count(0) {} | 808 int EntryCount() const { return static_cast<int>(entries_.size()); } |
809 void RecordEntry(intptr_t data, RelocInfo::Mode mode); | 809 bool IsEmpty() const { return entries_.empty(); } |
810 int EntryCount() const { | |
811 return shared_entries_count + static_cast<int>(unique_entries_.size()); | |
812 } | |
813 bool IsEmpty() const { | |
814 return shared_entries_.empty() && unique_entries_.empty(); | |
815 } | |
816 // Distance in bytes between the current pc and the first instruction | 810 // Distance in bytes between the current pc and the first instruction |
817 // using the pool. If there are no pending entries return kMaxInt. | 811 // using the pool. If there are no pending entries return kMaxInt. |
818 int DistanceToFirstUse(); | 812 int DistanceToFirstUse(); |
819 // Offset after which instructions using the pool will be out of range. | 813 // Offset after which instructions using the pool will be out of range. |
820 int MaxPcOffset(); | 814 int MaxPcOffset(); |
821 // Maximum size the constant pool can be with current entries. It always | 815 // Maximum size the constant pool can be with current entries. It always |
822 // includes alignment padding and branch over. | 816 // includes alignment padding and branch over. |
823 int WorstCaseSize(); | 817 int WorstCaseSize(); |
824 // Size in bytes of the literal pool *if* it is emitted at the current | 818 // Size in bytes of the literal pool *if* it is emitted at the current |
825 // pc. The size will include the branch over the pool if it was requested. | 819 // pc. The size will include the branch over the pool if it was requested. |
826 int SizeIfEmittedAtCurrentPc(bool require_jump); | 820 int SizeIfEmittedAtCurrentPc(bool require_jump); |
827 // Emit the literal pool at the current pc with a branch over the pool if | 821 // Emit the literal pool at the current pc with a branch over the pool if |
828 // requested. | 822 // requested. |
829 void Emit(bool require_jump); | 823 void Emit(bool require_jump); |
830 // Discard any pending pool entries. | 824 // Discard any pending pool entries. |
831 void Clear(); | 825 void Clear(); |
832 | 826 |
833 private: | 827 private: |
834 bool CanBeShared(RelocInfo::Mode mode); | 828 bool CanBeShared(RelocInfo::Mode mode); |
835 void EmitMarker(); | 829 void EmitMarker(); |
836 void EmitGuard(); | 830 void EmitGuard(); |
837 void EmitEntries(); | 831 void EmitEntries(); |
838 | 832 |
| 833 typedef std::map<uint64_t, int> SharedEntryMap; |
| 834 // Adds a shared entry to entries_, using 'entry_map' to determine whether we |
| 835 // already track this entry. Returns true if this is the first time we add |
| 836 // this entry, false otherwise. |
| 837 bool AddSharedEntry(SharedEntryMap& entry_map, uint64_t data, int offset); |
| 838 |
839 Assembler* assm_; | 839 Assembler* assm_; |
840 // Keep track of the first instruction requiring a constant pool entry | 840 // Keep track of the first instruction requiring a constant pool entry |
841 // since the previous constant pool was emitted. | 841 // since the previous constant pool was emitted. |
842 int first_use_; | 842 int first_use_; |
843 // values, pc offset(s) of entries which can be shared. | 843 |
844 std::multimap<uint64_t, int> shared_entries_; | 844 // Map of data to index in entries_ for shared entries. |
845 // Number of distinct literal in shared entries. | 845 SharedEntryMap shared_entries_; |
846 int shared_entries_count; | 846 |
847 // values, pc offset of entries which cannot be shared. | 847 // Map of address of handle to index in entries_. We need to keep track of |
848 std::vector<std::pair<uint64_t, int> > unique_entries_; | 848 // code targets separately from other shared entries, as they can be |
| 849 // relocated. |
| 850 SharedEntryMap handle_to_index_map_; |
| 851 |
| 852 // Values, pc offset(s) of entries. Use a vector to preserve the order of |
| 853 // insertion, as the serializer expects code target RelocInfo to point to |
| 854 // constant pool addresses in an ascending order. |
| 855 std::vector<std::pair<uint64_t, std::vector<int> > > entries_; |
849 }; | 856 }; |
850 | 857 |
851 | 858 |
852 // ----------------------------------------------------------------------------- | 859 // ----------------------------------------------------------------------------- |
853 // Assembler. | 860 // Assembler. |
854 | 861 |
855 class Assembler : public AssemblerBase { | 862 class Assembler : public AssemblerBase { |
856 public: | 863 public: |
857 // Create an assembler. Instructions and relocation information are emitted | 864 // Create an assembler. Instructions and relocation information are emitted |
858 // into a buffer, with the instructions starting from the beginning and the | 865 // into a buffer, with the instructions starting from the beginning and the |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1000 | 1007 |
1001 static constexpr int kPatchDebugBreakSlotAddressOffset = 0; | 1008 static constexpr int kPatchDebugBreakSlotAddressOffset = 0; |
1002 | 1009 |
1003 // Number of instructions necessary to be able to later patch it to a call. | 1010 // Number of instructions necessary to be able to later patch it to a call. |
1004 static constexpr int kDebugBreakSlotInstructions = 5; | 1011 static constexpr int kDebugBreakSlotInstructions = 5; |
1005 static constexpr int kDebugBreakSlotLength = | 1012 static constexpr int kDebugBreakSlotLength = |
1006 kDebugBreakSlotInstructions * kInstructionSize; | 1013 kDebugBreakSlotInstructions * kInstructionSize; |
1007 | 1014 |
1008 // Prevent contant pool emission until EndBlockConstPool is called. | 1015 // Prevent contant pool emission until EndBlockConstPool is called. |
1009 // Call to this function can be nested but must be followed by an equal | 1016 // Call to this function can be nested but must be followed by an equal |
1010 // number of call to EndBlockConstpool. | 1017 // number of calls to EndBlockConstpool. |
1011 void StartBlockConstPool(); | 1018 void StartBlockConstPool(); |
1012 | 1019 |
1013 // Resume constant pool emission. Need to be called as many time as | 1020 // Resume constant pool emission. Need to be called as many time as |
1014 // StartBlockConstPool to have an effect. | 1021 // StartBlockConstPool to have an effect. |
1015 void EndBlockConstPool(); | 1022 void EndBlockConstPool(); |
1016 | 1023 |
1017 bool is_const_pool_blocked() const; | 1024 bool is_const_pool_blocked() const; |
1018 static bool IsConstantPoolAt(Instruction* instr); | 1025 static bool IsConstantPoolAt(Instruction* instr); |
1019 static int ConstantPoolSizeAt(Instruction* instr); | 1026 static int ConstantPoolSizeAt(Instruction* instr); |
1020 // See Assembler::CheckConstPool for more info. | 1027 // See Assembler::CheckConstPool for more info. |
1021 void EmitPoolGuard(); | 1028 void EmitPoolGuard(); |
1022 | 1029 |
1023 // Prevent veneer pool emission until EndBlockVeneerPool is called. | 1030 // Prevent veneer pool emission until EndBlockVeneerPool is called. |
1024 // Call to this function can be nested but must be followed by an equal | 1031 // Call to this function can be nested but must be followed by an equal |
1025 // number of call to EndBlockConstpool. | 1032 // number of calls to EndBlockConstpool. |
1026 void StartBlockVeneerPool(); | 1033 void StartBlockVeneerPool(); |
1027 | 1034 |
1028 // Resume constant pool emission. Need to be called as many time as | 1035 // Resume constant pool emission. Need to be called as many time as |
1029 // StartBlockVeneerPool to have an effect. | 1036 // StartBlockVeneerPool to have an effect. |
1030 void EndBlockVeneerPool(); | 1037 void EndBlockVeneerPool(); |
1031 | 1038 |
1032 bool is_veneer_pool_blocked() const { | 1039 bool is_veneer_pool_blocked() const { |
1033 return veneer_pool_blocked_nesting_ > 0; | 1040 return veneer_pool_blocked_nesting_ > 0; |
1034 } | 1041 } |
1035 | 1042 |
(...skipping 2140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3176 ~BlockPoolsScope() { | 3183 ~BlockPoolsScope() { |
3177 assem_->EndBlockPools(); | 3184 assem_->EndBlockPools(); |
3178 } | 3185 } |
3179 | 3186 |
3180 private: | 3187 private: |
3181 Assembler* assem_; | 3188 Assembler* assem_; |
3182 | 3189 |
3183 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockPoolsScope); | 3190 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockPoolsScope); |
3184 }; | 3191 }; |
3185 | 3192 |
| 3193 // Class for blocking sharing of code targets in constant pool. |
| 3194 class BlockCodeTargetSharingScope { |
| 3195 public: |
| 3196 explicit BlockCodeTargetSharingScope(Assembler* assem) : assem_(nullptr) { |
| 3197 Open(assem); |
| 3198 } |
| 3199 // This constructor does not initialize the scope. The user needs to |
| 3200 // explicitly call Open() before using it. |
| 3201 BlockCodeTargetSharingScope() : assem_(nullptr) {} |
| 3202 ~BlockCodeTargetSharingScope() { Close(); } |
| 3203 void Open(Assembler* assem) { |
| 3204 DCHECK_NULL(assem_); |
| 3205 DCHECK_NOT_NULL(assem); |
| 3206 assem_ = assem; |
| 3207 assem_->StartBlockCodeTargetSharing(); |
| 3208 } |
| 3209 |
| 3210 private: |
| 3211 void Close() { |
| 3212 if (assem_ != nullptr) { |
| 3213 assem_->EndBlockCodeTargetSharing(); |
| 3214 } |
| 3215 } |
| 3216 Assembler* assem_; |
| 3217 |
| 3218 DISALLOW_COPY_AND_ASSIGN(BlockCodeTargetSharingScope); |
| 3219 }; |
| 3220 |
3186 protected: | 3221 protected: |
3187 inline const Register& AppropriateZeroRegFor(const CPURegister& reg) const; | 3222 inline const Register& AppropriateZeroRegFor(const CPURegister& reg) const; |
3188 | 3223 |
3189 void LoadStore(const CPURegister& rt, | 3224 void LoadStore(const CPURegister& rt, |
3190 const MemOperand& addr, | 3225 const MemOperand& addr, |
3191 LoadStoreOp op); | 3226 LoadStoreOp op); |
3192 void LoadStorePair(const CPURegister& rt, const CPURegister& rt2, | 3227 void LoadStorePair(const CPURegister& rt, const CPURegister& rt2, |
3193 const MemOperand& addr, LoadStorePairOp op); | 3228 const MemOperand& addr, LoadStorePairOp op); |
3194 void LoadStoreStruct(const VRegister& vt, const MemOperand& addr, | 3229 void LoadStoreStruct(const VRegister& vt, const MemOperand& addr, |
3195 NEONLoadStoreMultiStructOp op); | 3230 NEONLoadStoreMultiStructOp op); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3261 const CPURegister& rt2); | 3296 const CPURegister& rt2); |
3262 static inline LoadLiteralOp LoadLiteralOpFor(const CPURegister& rt); | 3297 static inline LoadLiteralOp LoadLiteralOpFor(const CPURegister& rt); |
3263 | 3298 |
3264 // Remove the specified branch from the unbound label link chain. | 3299 // Remove the specified branch from the unbound label link chain. |
3265 // If available, a veneer for this label can be used for other branches in the | 3300 // If available, a veneer for this label can be used for other branches in the |
3266 // chain if the link chain cannot be fixed up without this branch. | 3301 // chain if the link chain cannot be fixed up without this branch. |
3267 void RemoveBranchFromLabelLinkChain(Instruction* branch, | 3302 void RemoveBranchFromLabelLinkChain(Instruction* branch, |
3268 Label* label, | 3303 Label* label, |
3269 Instruction* label_veneer = NULL); | 3304 Instruction* label_veneer = NULL); |
3270 | 3305 |
| 3306 // Prevent sharing of code target constant pool entries until |
| 3307 // EndBlockCodeTargetSharing is called. Calls to this function can be nested |
| 3308 // but must be followed by an equal number of call to |
| 3309 // EndBlockCodeTargetSharing. |
| 3310 void StartBlockCodeTargetSharing() { ++code_target_sharing_blocked_nesting_; } |
| 3311 |
| 3312 // Resume sharing of constant pool code target entries. Needs to be called |
| 3313 // as many times as StartBlockCodeTargetSharing to have an effect. |
| 3314 void EndBlockCodeTargetSharing() { --code_target_sharing_blocked_nesting_; } |
| 3315 |
3271 private: | 3316 private: |
3272 static uint32_t FPToImm8(double imm); | 3317 static uint32_t FPToImm8(double imm); |
3273 | 3318 |
3274 // Instruction helpers. | 3319 // Instruction helpers. |
3275 void MoveWide(const Register& rd, | 3320 void MoveWide(const Register& rd, |
3276 uint64_t imm, | 3321 uint64_t imm, |
3277 int shift, | 3322 int shift, |
3278 MoveWideImmediateOp mov_op); | 3323 MoveWideImmediateOp mov_op); |
3279 void DataProcShiftedRegister(const Register& rd, | 3324 void DataProcShiftedRegister(const Register& rd, |
3280 const Register& rn, | 3325 const Register& rn, |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3442 // pool emission checks are interval based this value is an approximation. | 3487 // pool emission checks are interval based this value is an approximation. |
3443 static constexpr int kApproxMaxPoolEntryCount = 512; | 3488 static constexpr int kApproxMaxPoolEntryCount = 512; |
3444 | 3489 |
3445 // Emission of the constant pool may be blocked in some code sequences. | 3490 // Emission of the constant pool may be blocked in some code sequences. |
3446 int const_pool_blocked_nesting_; // Block emission if this is not zero. | 3491 int const_pool_blocked_nesting_; // Block emission if this is not zero. |
3447 int no_const_pool_before_; // Block emission before this pc offset. | 3492 int no_const_pool_before_; // Block emission before this pc offset. |
3448 | 3493 |
3449 // Emission of the veneer pools may be blocked in some code sequences. | 3494 // Emission of the veneer pools may be blocked in some code sequences. |
3450 int veneer_pool_blocked_nesting_; // Block emission if this is not zero. | 3495 int veneer_pool_blocked_nesting_; // Block emission if this is not zero. |
3451 | 3496 |
| 3497 // Sharing of code target entries may be blocked in some code sequences. |
| 3498 int code_target_sharing_blocked_nesting_; |
| 3499 bool IsCodeTargetSharingAllowed() const { |
| 3500 return code_target_sharing_blocked_nesting_ == 0; |
| 3501 } |
| 3502 |
3452 // Relocation info generation | 3503 // Relocation info generation |
3453 // Each relocation is encoded as a variable size value | 3504 // Each relocation is encoded as a variable size value |
3454 static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize; | 3505 static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize; |
3455 RelocInfoWriter reloc_info_writer; | 3506 RelocInfoWriter reloc_info_writer; |
3456 | 3507 |
3457 // Internal reference positions, required for (potential) patching in | 3508 // Internal reference positions, required for (potential) patching in |
3458 // GrowBuffer(); contains only those internal references whose labels | 3509 // GrowBuffer(); contains only those internal references whose labels |
3459 // are already bound. | 3510 // are already bound. |
3460 std::deque<int> internal_reference_positions_; | 3511 std::deque<int> internal_reference_positions_; |
3461 | 3512 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3627 public: | 3678 public: |
3628 explicit EnsureSpace(Assembler* assembler) { | 3679 explicit EnsureSpace(Assembler* assembler) { |
3629 assembler->CheckBufferSpace(); | 3680 assembler->CheckBufferSpace(); |
3630 } | 3681 } |
3631 }; | 3682 }; |
3632 | 3683 |
3633 } // namespace internal | 3684 } // namespace internal |
3634 } // namespace v8 | 3685 } // namespace v8 |
3635 | 3686 |
3636 #endif // V8_ARM64_ASSEMBLER_ARM64_H_ | 3687 #endif // V8_ARM64_ASSEMBLER_ARM64_H_ |
OLD | NEW |