OLD | NEW |
1 | 1 |
2 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 2 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
3 // All Rights Reserved. | 3 // All Rights Reserved. |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // - Redistributions of source code must retain the above copyright notice, | 9 // - Redistributions of source code must retain the above copyright notice, |
10 // this list of conditions and the following disclaimer. | 10 // this list of conditions and the following disclaimer. |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 return FPURegister::kMaxNumRegisters; | 93 return FPURegister::kMaxNumRegisters; |
94 } | 94 } |
95 | 95 |
96 | 96 |
97 int DoubleRegister::NumAllocatableRegisters() { | 97 int DoubleRegister::NumAllocatableRegisters() { |
98 return FPURegister::kMaxNumAllocatableRegisters; | 98 return FPURegister::kMaxNumAllocatableRegisters; |
99 } | 99 } |
100 | 100 |
101 | 101 |
102 int FPURegister::ToAllocationIndex(FPURegister reg) { | 102 int FPURegister::ToAllocationIndex(FPURegister reg) { |
103 ASSERT(reg.code() % 2 == 0); | 103 DCHECK(reg.code() % 2 == 0); |
104 ASSERT(reg.code() / 2 < kMaxNumAllocatableRegisters); | 104 DCHECK(reg.code() / 2 < kMaxNumAllocatableRegisters); |
105 ASSERT(reg.is_valid()); | 105 DCHECK(reg.is_valid()); |
106 ASSERT(!reg.is(kDoubleRegZero)); | 106 DCHECK(!reg.is(kDoubleRegZero)); |
107 ASSERT(!reg.is(kLithiumScratchDouble)); | 107 DCHECK(!reg.is(kLithiumScratchDouble)); |
108 return (reg.code() / 2); | 108 return (reg.code() / 2); |
109 } | 109 } |
110 | 110 |
111 | 111 |
112 // ----------------------------------------------------------------------------- | 112 // ----------------------------------------------------------------------------- |
113 // RelocInfo. | 113 // RelocInfo. |
114 | 114 |
115 void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) { | 115 void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) { |
116 if (IsInternalReference(rmode_)) { | 116 if (IsInternalReference(rmode_)) { |
117 // Absolute code pointer inside code object moves with the code object. | 117 // Absolute code pointer inside code object moves with the code object. |
118 byte* p = reinterpret_cast<byte*>(pc_); | 118 byte* p = reinterpret_cast<byte*>(pc_); |
119 int count = Assembler::RelocateInternalReference(p, delta); | 119 int count = Assembler::RelocateInternalReference(p, delta); |
120 CpuFeatures::FlushICache(p, count * sizeof(uint32_t)); | 120 CpuFeatures::FlushICache(p, count * sizeof(uint32_t)); |
121 } | 121 } |
122 } | 122 } |
123 | 123 |
124 | 124 |
125 Address RelocInfo::target_address() { | 125 Address RelocInfo::target_address() { |
126 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 126 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); |
127 return Assembler::target_address_at(pc_, host_); | 127 return Assembler::target_address_at(pc_, host_); |
128 } | 128 } |
129 | 129 |
130 | 130 |
131 Address RelocInfo::target_address_address() { | 131 Address RelocInfo::target_address_address() { |
132 ASSERT(IsCodeTarget(rmode_) || | 132 DCHECK(IsCodeTarget(rmode_) || |
133 IsRuntimeEntry(rmode_) || | 133 IsRuntimeEntry(rmode_) || |
134 rmode_ == EMBEDDED_OBJECT || | 134 rmode_ == EMBEDDED_OBJECT || |
135 rmode_ == EXTERNAL_REFERENCE); | 135 rmode_ == EXTERNAL_REFERENCE); |
136 // Read the address of the word containing the target_address in an | 136 // Read the address of the word containing the target_address in an |
137 // instruction stream. | 137 // instruction stream. |
138 // The only architecture-independent user of this function is the serializer. | 138 // The only architecture-independent user of this function is the serializer. |
139 // The serializer uses it to find out how many raw bytes of instruction to | 139 // The serializer uses it to find out how many raw bytes of instruction to |
140 // output before the next target. | 140 // output before the next target. |
141 // For an instruction like LUI/ORI where the target bits are mixed into the | 141 // For an instruction like LUI/ORI where the target bits are mixed into the |
142 // instruction bits, the size of the target will be zero, indicating that the | 142 // instruction bits, the size of the target will be zero, indicating that the |
(...skipping 18 matching lines...) Expand all Loading... |
161 | 161 |
162 | 162 |
163 int RelocInfo::target_address_size() { | 163 int RelocInfo::target_address_size() { |
164 return Assembler::kSpecialTargetSize; | 164 return Assembler::kSpecialTargetSize; |
165 } | 165 } |
166 | 166 |
167 | 167 |
168 void RelocInfo::set_target_address(Address target, | 168 void RelocInfo::set_target_address(Address target, |
169 WriteBarrierMode write_barrier_mode, | 169 WriteBarrierMode write_barrier_mode, |
170 ICacheFlushMode icache_flush_mode) { | 170 ICacheFlushMode icache_flush_mode) { |
171 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 171 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); |
172 Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode); | 172 Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode); |
173 if (write_barrier_mode == UPDATE_WRITE_BARRIER && | 173 if (write_barrier_mode == UPDATE_WRITE_BARRIER && |
174 host() != NULL && IsCodeTarget(rmode_)) { | 174 host() != NULL && IsCodeTarget(rmode_)) { |
175 Object* target_code = Code::GetCodeFromTargetAddress(target); | 175 Object* target_code = Code::GetCodeFromTargetAddress(target); |
176 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 176 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( |
177 host(), this, HeapObject::cast(target_code)); | 177 host(), this, HeapObject::cast(target_code)); |
178 } | 178 } |
179 } | 179 } |
180 | 180 |
181 | 181 |
182 Address Assembler::target_address_from_return_address(Address pc) { | 182 Address Assembler::target_address_from_return_address(Address pc) { |
183 return pc - kCallTargetAddressOffset; | 183 return pc - kCallTargetAddressOffset; |
184 } | 184 } |
185 | 185 |
186 | 186 |
187 Object* RelocInfo::target_object() { | 187 Object* RelocInfo::target_object() { |
188 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 188 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
189 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_)); | 189 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_)); |
190 } | 190 } |
191 | 191 |
192 | 192 |
193 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { | 193 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { |
194 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 194 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
195 return Handle<Object>(reinterpret_cast<Object**>( | 195 return Handle<Object>(reinterpret_cast<Object**>( |
196 Assembler::target_address_at(pc_, host_))); | 196 Assembler::target_address_at(pc_, host_))); |
197 } | 197 } |
198 | 198 |
199 | 199 |
200 void RelocInfo::set_target_object(Object* target, | 200 void RelocInfo::set_target_object(Object* target, |
201 WriteBarrierMode write_barrier_mode, | 201 WriteBarrierMode write_barrier_mode, |
202 ICacheFlushMode icache_flush_mode) { | 202 ICacheFlushMode icache_flush_mode) { |
203 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 203 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
204 Assembler::set_target_address_at(pc_, host_, | 204 Assembler::set_target_address_at(pc_, host_, |
205 reinterpret_cast<Address>(target), | 205 reinterpret_cast<Address>(target), |
206 icache_flush_mode); | 206 icache_flush_mode); |
207 if (write_barrier_mode == UPDATE_WRITE_BARRIER && | 207 if (write_barrier_mode == UPDATE_WRITE_BARRIER && |
208 host() != NULL && | 208 host() != NULL && |
209 target->IsHeapObject()) { | 209 target->IsHeapObject()) { |
210 host()->GetHeap()->incremental_marking()->RecordWrite( | 210 host()->GetHeap()->incremental_marking()->RecordWrite( |
211 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); | 211 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); |
212 } | 212 } |
213 } | 213 } |
214 | 214 |
215 | 215 |
216 Address RelocInfo::target_reference() { | 216 Address RelocInfo::target_reference() { |
217 ASSERT(rmode_ == EXTERNAL_REFERENCE); | 217 DCHECK(rmode_ == EXTERNAL_REFERENCE); |
218 return Assembler::target_address_at(pc_, host_); | 218 return Assembler::target_address_at(pc_, host_); |
219 } | 219 } |
220 | 220 |
221 | 221 |
222 Address RelocInfo::target_runtime_entry(Assembler* origin) { | 222 Address RelocInfo::target_runtime_entry(Assembler* origin) { |
223 ASSERT(IsRuntimeEntry(rmode_)); | 223 DCHECK(IsRuntimeEntry(rmode_)); |
224 return target_address(); | 224 return target_address(); |
225 } | 225 } |
226 | 226 |
227 | 227 |
228 void RelocInfo::set_target_runtime_entry(Address target, | 228 void RelocInfo::set_target_runtime_entry(Address target, |
229 WriteBarrierMode write_barrier_mode, | 229 WriteBarrierMode write_barrier_mode, |
230 ICacheFlushMode icache_flush_mode) { | 230 ICacheFlushMode icache_flush_mode) { |
231 ASSERT(IsRuntimeEntry(rmode_)); | 231 DCHECK(IsRuntimeEntry(rmode_)); |
232 if (target_address() != target) | 232 if (target_address() != target) |
233 set_target_address(target, write_barrier_mode, icache_flush_mode); | 233 set_target_address(target, write_barrier_mode, icache_flush_mode); |
234 } | 234 } |
235 | 235 |
236 | 236 |
237 Handle<Cell> RelocInfo::target_cell_handle() { | 237 Handle<Cell> RelocInfo::target_cell_handle() { |
238 ASSERT(rmode_ == RelocInfo::CELL); | 238 DCHECK(rmode_ == RelocInfo::CELL); |
239 Address address = Memory::Address_at(pc_); | 239 Address address = Memory::Address_at(pc_); |
240 return Handle<Cell>(reinterpret_cast<Cell**>(address)); | 240 return Handle<Cell>(reinterpret_cast<Cell**>(address)); |
241 } | 241 } |
242 | 242 |
243 | 243 |
244 Cell* RelocInfo::target_cell() { | 244 Cell* RelocInfo::target_cell() { |
245 ASSERT(rmode_ == RelocInfo::CELL); | 245 DCHECK(rmode_ == RelocInfo::CELL); |
246 return Cell::FromValueAddress(Memory::Address_at(pc_)); | 246 return Cell::FromValueAddress(Memory::Address_at(pc_)); |
247 } | 247 } |
248 | 248 |
249 | 249 |
250 void RelocInfo::set_target_cell(Cell* cell, | 250 void RelocInfo::set_target_cell(Cell* cell, |
251 WriteBarrierMode write_barrier_mode, | 251 WriteBarrierMode write_barrier_mode, |
252 ICacheFlushMode icache_flush_mode) { | 252 ICacheFlushMode icache_flush_mode) { |
253 ASSERT(rmode_ == RelocInfo::CELL); | 253 DCHECK(rmode_ == RelocInfo::CELL); |
254 Address address = cell->address() + Cell::kValueOffset; | 254 Address address = cell->address() + Cell::kValueOffset; |
255 Memory::Address_at(pc_) = address; | 255 Memory::Address_at(pc_) = address; |
256 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) { | 256 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) { |
257 // TODO(1550) We are passing NULL as a slot because cell can never be on | 257 // TODO(1550) We are passing NULL as a slot because cell can never be on |
258 // evacuation candidate. | 258 // evacuation candidate. |
259 host()->GetHeap()->incremental_marking()->RecordWrite( | 259 host()->GetHeap()->incremental_marking()->RecordWrite( |
260 host(), NULL, cell); | 260 host(), NULL, cell); |
261 } | 261 } |
262 } | 262 } |
263 | 263 |
264 | 264 |
265 static const int kNoCodeAgeSequenceLength = 9 * Assembler::kInstrSize; | 265 static const int kNoCodeAgeSequenceLength = 9 * Assembler::kInstrSize; |
266 | 266 |
267 | 267 |
268 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { | 268 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { |
269 UNREACHABLE(); // This should never be reached on Arm. | 269 UNREACHABLE(); // This should never be reached on Arm. |
270 return Handle<Object>(); | 270 return Handle<Object>(); |
271 } | 271 } |
272 | 272 |
273 | 273 |
274 Code* RelocInfo::code_age_stub() { | 274 Code* RelocInfo::code_age_stub() { |
275 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 275 DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); |
276 return Code::GetCodeFromTargetAddress( | 276 return Code::GetCodeFromTargetAddress( |
277 Assembler::target_address_at(pc_ + Assembler::kInstrSize, host_)); | 277 Assembler::target_address_at(pc_ + Assembler::kInstrSize, host_)); |
278 } | 278 } |
279 | 279 |
280 | 280 |
281 void RelocInfo::set_code_age_stub(Code* stub, | 281 void RelocInfo::set_code_age_stub(Code* stub, |
282 ICacheFlushMode icache_flush_mode) { | 282 ICacheFlushMode icache_flush_mode) { |
283 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 283 DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); |
284 Assembler::set_target_address_at(pc_ + Assembler::kInstrSize, | 284 Assembler::set_target_address_at(pc_ + Assembler::kInstrSize, |
285 host_, | 285 host_, |
286 stub->instruction_start()); | 286 stub->instruction_start()); |
287 } | 287 } |
288 | 288 |
289 | 289 |
290 Address RelocInfo::call_address() { | 290 Address RelocInfo::call_address() { |
291 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 291 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
292 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 292 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
293 // The pc_ offset of 0 assumes mips patched return sequence per | 293 // The pc_ offset of 0 assumes mips patched return sequence per |
294 // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or | 294 // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or |
295 // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot(). | 295 // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot(). |
296 return Assembler::target_address_at(pc_, host_); | 296 return Assembler::target_address_at(pc_, host_); |
297 } | 297 } |
298 | 298 |
299 | 299 |
300 void RelocInfo::set_call_address(Address target) { | 300 void RelocInfo::set_call_address(Address target) { |
301 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 301 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
302 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 302 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
303 // The pc_ offset of 0 assumes mips patched return sequence per | 303 // The pc_ offset of 0 assumes mips patched return sequence per |
304 // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or | 304 // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or |
305 // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot(). | 305 // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot(). |
306 Assembler::set_target_address_at(pc_, host_, target); | 306 Assembler::set_target_address_at(pc_, host_, target); |
307 if (host() != NULL) { | 307 if (host() != NULL) { |
308 Object* target_code = Code::GetCodeFromTargetAddress(target); | 308 Object* target_code = Code::GetCodeFromTargetAddress(target); |
309 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 309 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( |
310 host(), this, HeapObject::cast(target_code)); | 310 host(), this, HeapObject::cast(target_code)); |
311 } | 311 } |
312 } | 312 } |
313 | 313 |
314 | 314 |
315 Object* RelocInfo::call_object() { | 315 Object* RelocInfo::call_object() { |
316 return *call_object_address(); | 316 return *call_object_address(); |
317 } | 317 } |
318 | 318 |
319 | 319 |
320 Object** RelocInfo::call_object_address() { | 320 Object** RelocInfo::call_object_address() { |
321 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 321 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
322 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 322 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
323 return reinterpret_cast<Object**>(pc_ + 6 * Assembler::kInstrSize); | 323 return reinterpret_cast<Object**>(pc_ + 6 * Assembler::kInstrSize); |
324 } | 324 } |
325 | 325 |
326 | 326 |
327 void RelocInfo::set_call_object(Object* target) { | 327 void RelocInfo::set_call_object(Object* target) { |
328 *call_object_address() = target; | 328 *call_object_address() = target; |
329 } | 329 } |
330 | 330 |
331 | 331 |
332 void RelocInfo::WipeOut() { | 332 void RelocInfo::WipeOut() { |
333 ASSERT(IsEmbeddedObject(rmode_) || | 333 DCHECK(IsEmbeddedObject(rmode_) || |
334 IsCodeTarget(rmode_) || | 334 IsCodeTarget(rmode_) || |
335 IsRuntimeEntry(rmode_) || | 335 IsRuntimeEntry(rmode_) || |
336 IsExternalReference(rmode_)); | 336 IsExternalReference(rmode_)); |
337 Assembler::set_target_address_at(pc_, host_, NULL); | 337 Assembler::set_target_address_at(pc_, host_, NULL); |
338 } | 338 } |
339 | 339 |
340 | 340 |
341 bool RelocInfo::IsPatchedReturnSequence() { | 341 bool RelocInfo::IsPatchedReturnSequence() { |
342 Instr instr0 = Assembler::instr_at(pc_); // lui. | 342 Instr instr0 = Assembler::instr_at(pc_); // lui. |
343 Instr instr1 = Assembler::instr_at(pc_ + 1 * Assembler::kInstrSize); // ori. | 343 Instr instr1 = Assembler::instr_at(pc_ + 1 * Assembler::kInstrSize); // ori. |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 } | 443 } |
444 *reinterpret_cast<uint64_t*>(pc_) = x; | 444 *reinterpret_cast<uint64_t*>(pc_) = x; |
445 pc_ += kInstrSize * 2; | 445 pc_ += kInstrSize * 2; |
446 CheckTrampolinePoolQuick(); | 446 CheckTrampolinePoolQuick(); |
447 } | 447 } |
448 | 448 |
449 | 449 |
450 } } // namespace v8::internal | 450 } } // namespace v8::internal |
451 | 451 |
452 #endif // V8_MIPS_ASSEMBLER_MIPS_INL_H_ | 452 #endif // V8_MIPS_ASSEMBLER_MIPS_INL_H_ |
OLD | NEW |