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_CODE_STUBS_ARM64_H_ | 5 #ifndef V8_ARM64_CODE_STUBS_ARM64_H_ |
6 #define V8_ARM64_CODE_STUBS_ARM64_H_ | 6 #define V8_ARM64_CODE_STUBS_ARM64_H_ |
7 | 7 |
8 #include "src/ic-inl.h" | 8 #include "src/ic-inl.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 | 113 |
114 virtual bool SometimesSetsUpAFrame() { return false; } | 114 virtual bool SometimesSetsUpAFrame() { return false; } |
115 | 115 |
116 static Mode GetMode(Code* stub) { | 116 static Mode GetMode(Code* stub) { |
117 // Find the mode depending on the first two instructions. | 117 // Find the mode depending on the first two instructions. |
118 Instruction* instr1 = | 118 Instruction* instr1 = |
119 reinterpret_cast<Instruction*>(stub->instruction_start()); | 119 reinterpret_cast<Instruction*>(stub->instruction_start()); |
120 Instruction* instr2 = instr1->following(); | 120 Instruction* instr2 = instr1->following(); |
121 | 121 |
122 if (instr1->IsUncondBranchImm()) { | 122 if (instr1->IsUncondBranchImm()) { |
123 ASSERT(instr2->IsPCRelAddressing() && (instr2->Rd() == xzr.code())); | 123 DCHECK(instr2->IsPCRelAddressing() && (instr2->Rd() == xzr.code())); |
124 return INCREMENTAL; | 124 return INCREMENTAL; |
125 } | 125 } |
126 | 126 |
127 ASSERT(instr1->IsPCRelAddressing() && (instr1->Rd() == xzr.code())); | 127 DCHECK(instr1->IsPCRelAddressing() && (instr1->Rd() == xzr.code())); |
128 | 128 |
129 if (instr2->IsUncondBranchImm()) { | 129 if (instr2->IsUncondBranchImm()) { |
130 return INCREMENTAL_COMPACTION; | 130 return INCREMENTAL_COMPACTION; |
131 } | 131 } |
132 | 132 |
133 ASSERT(instr2->IsPCRelAddressing()); | 133 DCHECK(instr2->IsPCRelAddressing()); |
134 | 134 |
135 return STORE_BUFFER_ONLY; | 135 return STORE_BUFFER_ONLY; |
136 } | 136 } |
137 | 137 |
138 // We patch the two first instructions of the stub back and forth between an | 138 // We patch the two first instructions of the stub back and forth between an |
139 // adr and branch when we start and stop incremental heap marking. | 139 // adr and branch when we start and stop incremental heap marking. |
140 // The branch is | 140 // The branch is |
141 // b label | 141 // b label |
142 // The adr is | 142 // The adr is |
143 // adr xzr label | 143 // adr xzr label |
144 // so effectively a nop. | 144 // so effectively a nop. |
145 static void Patch(Code* stub, Mode mode) { | 145 static void Patch(Code* stub, Mode mode) { |
146 // We are going to patch the two first instructions of the stub. | 146 // We are going to patch the two first instructions of the stub. |
147 PatchingAssembler patcher( | 147 PatchingAssembler patcher( |
148 reinterpret_cast<Instruction*>(stub->instruction_start()), 2); | 148 reinterpret_cast<Instruction*>(stub->instruction_start()), 2); |
149 Instruction* instr1 = patcher.InstructionAt(0); | 149 Instruction* instr1 = patcher.InstructionAt(0); |
150 Instruction* instr2 = patcher.InstructionAt(kInstructionSize); | 150 Instruction* instr2 = patcher.InstructionAt(kInstructionSize); |
151 // Instructions must be either 'adr' or 'b'. | 151 // Instructions must be either 'adr' or 'b'. |
152 ASSERT(instr1->IsPCRelAddressing() || instr1->IsUncondBranchImm()); | 152 DCHECK(instr1->IsPCRelAddressing() || instr1->IsUncondBranchImm()); |
153 ASSERT(instr2->IsPCRelAddressing() || instr2->IsUncondBranchImm()); | 153 DCHECK(instr2->IsPCRelAddressing() || instr2->IsUncondBranchImm()); |
154 // Retrieve the offsets to the labels. | 154 // Retrieve the offsets to the labels. |
155 int32_t offset_to_incremental_noncompacting = instr1->ImmPCOffset(); | 155 int32_t offset_to_incremental_noncompacting = instr1->ImmPCOffset(); |
156 int32_t offset_to_incremental_compacting = instr2->ImmPCOffset(); | 156 int32_t offset_to_incremental_compacting = instr2->ImmPCOffset(); |
157 | 157 |
158 switch (mode) { | 158 switch (mode) { |
159 case STORE_BUFFER_ONLY: | 159 case STORE_BUFFER_ONLY: |
160 ASSERT(GetMode(stub) == INCREMENTAL || | 160 DCHECK(GetMode(stub) == INCREMENTAL || |
161 GetMode(stub) == INCREMENTAL_COMPACTION); | 161 GetMode(stub) == INCREMENTAL_COMPACTION); |
162 patcher.adr(xzr, offset_to_incremental_noncompacting); | 162 patcher.adr(xzr, offset_to_incremental_noncompacting); |
163 patcher.adr(xzr, offset_to_incremental_compacting); | 163 patcher.adr(xzr, offset_to_incremental_compacting); |
164 break; | 164 break; |
165 case INCREMENTAL: | 165 case INCREMENTAL: |
166 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY); | 166 DCHECK(GetMode(stub) == STORE_BUFFER_ONLY); |
167 patcher.b(offset_to_incremental_noncompacting >> kInstructionSizeLog2); | 167 patcher.b(offset_to_incremental_noncompacting >> kInstructionSizeLog2); |
168 patcher.adr(xzr, offset_to_incremental_compacting); | 168 patcher.adr(xzr, offset_to_incremental_compacting); |
169 break; | 169 break; |
170 case INCREMENTAL_COMPACTION: | 170 case INCREMENTAL_COMPACTION: |
171 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY); | 171 DCHECK(GetMode(stub) == STORE_BUFFER_ONLY); |
172 patcher.adr(xzr, offset_to_incremental_noncompacting); | 172 patcher.adr(xzr, offset_to_incremental_noncompacting); |
173 patcher.b(offset_to_incremental_compacting >> kInstructionSizeLog2); | 173 patcher.b(offset_to_incremental_compacting >> kInstructionSizeLog2); |
174 break; | 174 break; |
175 } | 175 } |
176 ASSERT(GetMode(stub) == mode); | 176 DCHECK(GetMode(stub) == mode); |
177 } | 177 } |
178 | 178 |
179 private: | 179 private: |
180 // This is a helper class to manage the registers associated with the stub. | 180 // This is a helper class to manage the registers associated with the stub. |
181 // The 'object' and 'address' registers must be preserved. | 181 // The 'object' and 'address' registers must be preserved. |
182 class RegisterAllocation { | 182 class RegisterAllocation { |
183 public: | 183 public: |
184 RegisterAllocation(Register object, | 184 RegisterAllocation(Register object, |
185 Register address, | 185 Register address, |
186 Register scratch) | 186 Register scratch) |
187 : object_(object), | 187 : object_(object), |
188 address_(address), | 188 address_(address), |
189 scratch0_(scratch), | 189 scratch0_(scratch), |
190 saved_regs_(kCallerSaved), | 190 saved_regs_(kCallerSaved), |
191 saved_fp_regs_(kCallerSavedFP) { | 191 saved_fp_regs_(kCallerSavedFP) { |
192 ASSERT(!AreAliased(scratch, object, address)); | 192 DCHECK(!AreAliased(scratch, object, address)); |
193 | 193 |
194 // The SaveCallerSaveRegisters method needs to save caller-saved | 194 // The SaveCallerSaveRegisters method needs to save caller-saved |
195 // registers, but we don't bother saving MacroAssembler scratch registers. | 195 // registers, but we don't bother saving MacroAssembler scratch registers. |
196 saved_regs_.Remove(MacroAssembler::DefaultTmpList()); | 196 saved_regs_.Remove(MacroAssembler::DefaultTmpList()); |
197 saved_fp_regs_.Remove(MacroAssembler::DefaultFPTmpList()); | 197 saved_fp_regs_.Remove(MacroAssembler::DefaultFPTmpList()); |
198 | 198 |
199 // We would like to require more scratch registers for this stub, | 199 // We would like to require more scratch registers for this stub, |
200 // but the number of registers comes down to the ones used in | 200 // but the number of registers comes down to the ones used in |
201 // FullCodeGen::SetVar(), which is architecture independent. | 201 // FullCodeGen::SetVar(), which is architecture independent. |
202 // We allocate 2 extra scratch registers that we'll save on the stack. | 202 // We allocate 2 extra scratch registers that we'll save on the stack. |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 int MinorKey() const { | 306 int MinorKey() const { |
307 return MinorKeyFor(object_, value_, address_, remembered_set_action_, | 307 return MinorKeyFor(object_, value_, address_, remembered_set_action_, |
308 save_fp_regs_mode_); | 308 save_fp_regs_mode_); |
309 } | 309 } |
310 | 310 |
311 static int MinorKeyFor(Register object, | 311 static int MinorKeyFor(Register object, |
312 Register value, | 312 Register value, |
313 Register address, | 313 Register address, |
314 RememberedSetAction action, | 314 RememberedSetAction action, |
315 SaveFPRegsMode fp_mode) { | 315 SaveFPRegsMode fp_mode) { |
316 ASSERT(object.Is64Bits()); | 316 DCHECK(object.Is64Bits()); |
317 ASSERT(value.Is64Bits()); | 317 DCHECK(value.Is64Bits()); |
318 ASSERT(address.Is64Bits()); | 318 DCHECK(address.Is64Bits()); |
319 return ObjectBits::encode(object.code()) | | 319 return ObjectBits::encode(object.code()) | |
320 ValueBits::encode(value.code()) | | 320 ValueBits::encode(value.code()) | |
321 AddressBits::encode(address.code()) | | 321 AddressBits::encode(address.code()) | |
322 RememberedSetActionBits::encode(action) | | 322 RememberedSetActionBits::encode(action) | |
323 SaveFPRegsModeBits::encode(fp_mode); | 323 SaveFPRegsModeBits::encode(fp_mode); |
324 } | 324 } |
325 | 325 |
326 void Activate(Code* code) { | 326 void Activate(Code* code) { |
327 code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code); | 327 code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code); |
328 } | 328 } |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 TargetAddressStorageMode storage_mode() { return storage_mode_; } | 466 TargetAddressStorageMode storage_mode() { return storage_mode_; } |
467 | 467 |
468 private: | 468 private: |
469 TargetAddressStorageMode storage_mode_; | 469 TargetAddressStorageMode storage_mode_; |
470 }; | 470 }; |
471 | 471 |
472 | 472 |
473 } } // namespace v8::internal | 473 } } // namespace v8::internal |
474 | 474 |
475 #endif // V8_ARM64_CODE_STUBS_ARM64_H_ | 475 #endif // V8_ARM64_CODE_STUBS_ARM64_H_ |
OLD | NEW |