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 (IsCodeTarget(rmode_)) { | 116 if (IsCodeTarget(rmode_)) { |
117 uint32_t scope1 = (uint32_t) target_address() & ~kImm28Mask; | 117 uint32_t scope1 = (uint32_t) target_address() & ~kImm28Mask; |
118 uint32_t scope2 = reinterpret_cast<uint32_t>(pc_) & ~kImm28Mask; | 118 uint32_t scope2 = reinterpret_cast<uint32_t>(pc_) & ~kImm28Mask; |
119 | 119 |
120 if (scope1 != scope2) { | 120 if (scope1 != scope2) { |
121 Assembler::JumpLabelToJumpRegister(pc_); | 121 Assembler::JumpLabelToJumpRegister(pc_); |
122 } | 122 } |
123 } | 123 } |
124 if (IsInternalReference(rmode_)) { | 124 if (IsInternalReference(rmode_)) { |
125 // Absolute code pointer inside code object moves with the code object. | 125 // Absolute code pointer inside code object moves with the code object. |
126 byte* p = reinterpret_cast<byte*>(pc_); | 126 byte* p = reinterpret_cast<byte*>(pc_); |
127 int count = Assembler::RelocateInternalReference(p, delta); | 127 int count = Assembler::RelocateInternalReference(p, delta); |
128 CpuFeatures::FlushICache(p, count * sizeof(uint32_t)); | 128 CpuFeatures::FlushICache(p, count * sizeof(uint32_t)); |
129 } | 129 } |
130 } | 130 } |
131 | 131 |
132 | 132 |
133 Address RelocInfo::target_address() { | 133 Address RelocInfo::target_address() { |
134 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 134 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); |
135 return Assembler::target_address_at(pc_, host_); | 135 return Assembler::target_address_at(pc_, host_); |
136 } | 136 } |
137 | 137 |
138 | 138 |
139 Address RelocInfo::target_address_address() { | 139 Address RelocInfo::target_address_address() { |
140 ASSERT(IsCodeTarget(rmode_) || | 140 DCHECK(IsCodeTarget(rmode_) || |
141 IsRuntimeEntry(rmode_) || | 141 IsRuntimeEntry(rmode_) || |
142 rmode_ == EMBEDDED_OBJECT || | 142 rmode_ == EMBEDDED_OBJECT || |
143 rmode_ == EXTERNAL_REFERENCE); | 143 rmode_ == EXTERNAL_REFERENCE); |
144 // Read the address of the word containing the target_address in an | 144 // Read the address of the word containing the target_address in an |
145 // instruction stream. | 145 // instruction stream. |
146 // The only architecture-independent user of this function is the serializer. | 146 // The only architecture-independent user of this function is the serializer. |
147 // The serializer uses it to find out how many raw bytes of instruction to | 147 // The serializer uses it to find out how many raw bytes of instruction to |
148 // output before the next target. | 148 // output before the next target. |
149 // For an instruction like LUI/ORI where the target bits are mixed into the | 149 // For an instruction like LUI/ORI where the target bits are mixed into the |
150 // instruction bits, the size of the target will be zero, indicating that the | 150 // instruction bits, the size of the target will be zero, indicating that the |
(...skipping 16 matching lines...) Expand all Loading... |
167 | 167 |
168 | 168 |
169 int RelocInfo::target_address_size() { | 169 int RelocInfo::target_address_size() { |
170 return Assembler::kSpecialTargetSize; | 170 return Assembler::kSpecialTargetSize; |
171 } | 171 } |
172 | 172 |
173 | 173 |
174 void RelocInfo::set_target_address(Address target, | 174 void RelocInfo::set_target_address(Address target, |
175 WriteBarrierMode write_barrier_mode, | 175 WriteBarrierMode write_barrier_mode, |
176 ICacheFlushMode icache_flush_mode) { | 176 ICacheFlushMode icache_flush_mode) { |
177 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 177 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); |
178 Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode); | 178 Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode); |
179 if (write_barrier_mode == UPDATE_WRITE_BARRIER && | 179 if (write_barrier_mode == UPDATE_WRITE_BARRIER && |
180 host() != NULL && IsCodeTarget(rmode_)) { | 180 host() != NULL && IsCodeTarget(rmode_)) { |
181 Object* target_code = Code::GetCodeFromTargetAddress(target); | 181 Object* target_code = Code::GetCodeFromTargetAddress(target); |
182 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 182 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( |
183 host(), this, HeapObject::cast(target_code)); | 183 host(), this, HeapObject::cast(target_code)); |
184 } | 184 } |
185 } | 185 } |
186 | 186 |
187 | 187 |
188 Address Assembler::target_address_from_return_address(Address pc) { | 188 Address Assembler::target_address_from_return_address(Address pc) { |
189 return pc - kCallTargetAddressOffset; | 189 return pc - kCallTargetAddressOffset; |
190 } | 190 } |
191 | 191 |
192 | 192 |
193 Object* RelocInfo::target_object() { | 193 Object* RelocInfo::target_object() { |
194 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 194 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
195 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_)); | 195 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_)); |
196 } | 196 } |
197 | 197 |
198 | 198 |
199 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { | 199 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { |
200 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 200 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
201 return Handle<Object>(reinterpret_cast<Object**>( | 201 return Handle<Object>(reinterpret_cast<Object**>( |
202 Assembler::target_address_at(pc_, host_))); | 202 Assembler::target_address_at(pc_, host_))); |
203 } | 203 } |
204 | 204 |
205 | 205 |
206 void RelocInfo::set_target_object(Object* target, | 206 void RelocInfo::set_target_object(Object* target, |
207 WriteBarrierMode write_barrier_mode, | 207 WriteBarrierMode write_barrier_mode, |
208 ICacheFlushMode icache_flush_mode) { | 208 ICacheFlushMode icache_flush_mode) { |
209 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 209 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
210 Assembler::set_target_address_at(pc_, host_, | 210 Assembler::set_target_address_at(pc_, host_, |
211 reinterpret_cast<Address>(target), | 211 reinterpret_cast<Address>(target), |
212 icache_flush_mode); | 212 icache_flush_mode); |
213 if (write_barrier_mode == UPDATE_WRITE_BARRIER && | 213 if (write_barrier_mode == UPDATE_WRITE_BARRIER && |
214 host() != NULL && | 214 host() != NULL && |
215 target->IsHeapObject()) { | 215 target->IsHeapObject()) { |
216 host()->GetHeap()->incremental_marking()->RecordWrite( | 216 host()->GetHeap()->incremental_marking()->RecordWrite( |
217 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); | 217 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); |
218 } | 218 } |
219 } | 219 } |
220 | 220 |
221 | 221 |
222 Address RelocInfo::target_reference() { | 222 Address RelocInfo::target_reference() { |
223 ASSERT(rmode_ == EXTERNAL_REFERENCE); | 223 DCHECK(rmode_ == EXTERNAL_REFERENCE); |
224 return Assembler::target_address_at(pc_, host_); | 224 return Assembler::target_address_at(pc_, host_); |
225 } | 225 } |
226 | 226 |
227 | 227 |
228 Address RelocInfo::target_runtime_entry(Assembler* origin) { | 228 Address RelocInfo::target_runtime_entry(Assembler* origin) { |
229 ASSERT(IsRuntimeEntry(rmode_)); | 229 DCHECK(IsRuntimeEntry(rmode_)); |
230 return target_address(); | 230 return target_address(); |
231 } | 231 } |
232 | 232 |
233 | 233 |
234 void RelocInfo::set_target_runtime_entry(Address target, | 234 void RelocInfo::set_target_runtime_entry(Address target, |
235 WriteBarrierMode write_barrier_mode, | 235 WriteBarrierMode write_barrier_mode, |
236 ICacheFlushMode icache_flush_mode) { | 236 ICacheFlushMode icache_flush_mode) { |
237 ASSERT(IsRuntimeEntry(rmode_)); | 237 DCHECK(IsRuntimeEntry(rmode_)); |
238 if (target_address() != target) | 238 if (target_address() != target) |
239 set_target_address(target, write_barrier_mode, icache_flush_mode); | 239 set_target_address(target, write_barrier_mode, icache_flush_mode); |
240 } | 240 } |
241 | 241 |
242 | 242 |
243 Handle<Cell> RelocInfo::target_cell_handle() { | 243 Handle<Cell> RelocInfo::target_cell_handle() { |
244 ASSERT(rmode_ == RelocInfo::CELL); | 244 DCHECK(rmode_ == RelocInfo::CELL); |
245 Address address = Memory::Address_at(pc_); | 245 Address address = Memory::Address_at(pc_); |
246 return Handle<Cell>(reinterpret_cast<Cell**>(address)); | 246 return Handle<Cell>(reinterpret_cast<Cell**>(address)); |
247 } | 247 } |
248 | 248 |
249 | 249 |
250 Cell* RelocInfo::target_cell() { | 250 Cell* RelocInfo::target_cell() { |
251 ASSERT(rmode_ == RelocInfo::CELL); | 251 DCHECK(rmode_ == RelocInfo::CELL); |
252 return Cell::FromValueAddress(Memory::Address_at(pc_)); | 252 return Cell::FromValueAddress(Memory::Address_at(pc_)); |
253 } | 253 } |
254 | 254 |
255 | 255 |
256 void RelocInfo::set_target_cell(Cell* cell, | 256 void RelocInfo::set_target_cell(Cell* cell, |
257 WriteBarrierMode write_barrier_mode, | 257 WriteBarrierMode write_barrier_mode, |
258 ICacheFlushMode icache_flush_mode) { | 258 ICacheFlushMode icache_flush_mode) { |
259 ASSERT(rmode_ == RelocInfo::CELL); | 259 DCHECK(rmode_ == RelocInfo::CELL); |
260 Address address = cell->address() + Cell::kValueOffset; | 260 Address address = cell->address() + Cell::kValueOffset; |
261 Memory::Address_at(pc_) = address; | 261 Memory::Address_at(pc_) = address; |
262 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) { | 262 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) { |
263 // TODO(1550) We are passing NULL as a slot because cell can never be on | 263 // TODO(1550) We are passing NULL as a slot because cell can never be on |
264 // evacuation candidate. | 264 // evacuation candidate. |
265 host()->GetHeap()->incremental_marking()->RecordWrite( | 265 host()->GetHeap()->incremental_marking()->RecordWrite( |
266 host(), NULL, cell); | 266 host(), NULL, cell); |
267 } | 267 } |
268 } | 268 } |
269 | 269 |
270 | 270 |
271 static const int kNoCodeAgeSequenceLength = 7 * Assembler::kInstrSize; | 271 static const int kNoCodeAgeSequenceLength = 7 * Assembler::kInstrSize; |
272 | 272 |
273 | 273 |
274 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { | 274 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { |
275 UNREACHABLE(); // This should never be reached on Arm. | 275 UNREACHABLE(); // This should never be reached on Arm. |
276 return Handle<Object>(); | 276 return Handle<Object>(); |
277 } | 277 } |
278 | 278 |
279 | 279 |
280 Code* RelocInfo::code_age_stub() { | 280 Code* RelocInfo::code_age_stub() { |
281 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 281 DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); |
282 return Code::GetCodeFromTargetAddress( | 282 return Code::GetCodeFromTargetAddress( |
283 Assembler::target_address_at(pc_ + Assembler::kInstrSize, host_)); | 283 Assembler::target_address_at(pc_ + Assembler::kInstrSize, host_)); |
284 } | 284 } |
285 | 285 |
286 | 286 |
287 void RelocInfo::set_code_age_stub(Code* stub, | 287 void RelocInfo::set_code_age_stub(Code* stub, |
288 ICacheFlushMode icache_flush_mode) { | 288 ICacheFlushMode icache_flush_mode) { |
289 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 289 DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); |
290 Assembler::set_target_address_at(pc_ + Assembler::kInstrSize, | 290 Assembler::set_target_address_at(pc_ + Assembler::kInstrSize, |
291 host_, | 291 host_, |
292 stub->instruction_start()); | 292 stub->instruction_start()); |
293 } | 293 } |
294 | 294 |
295 | 295 |
296 Address RelocInfo::call_address() { | 296 Address RelocInfo::call_address() { |
297 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 297 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
298 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 298 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
299 // The pc_ offset of 0 assumes mips patched return sequence per | 299 // The pc_ offset of 0 assumes mips patched return sequence per |
300 // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or | 300 // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or |
301 // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot(). | 301 // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot(). |
302 return Assembler::target_address_at(pc_, host_); | 302 return Assembler::target_address_at(pc_, host_); |
303 } | 303 } |
304 | 304 |
305 | 305 |
306 void RelocInfo::set_call_address(Address target) { | 306 void RelocInfo::set_call_address(Address target) { |
307 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 307 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
308 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 308 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
309 // The pc_ offset of 0 assumes mips patched return sequence per | 309 // The pc_ offset of 0 assumes mips patched return sequence per |
310 // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or | 310 // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or |
311 // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot(). | 311 // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot(). |
312 Assembler::set_target_address_at(pc_, host_, target); | 312 Assembler::set_target_address_at(pc_, host_, target); |
313 if (host() != NULL) { | 313 if (host() != NULL) { |
314 Object* target_code = Code::GetCodeFromTargetAddress(target); | 314 Object* target_code = Code::GetCodeFromTargetAddress(target); |
315 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 315 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( |
316 host(), this, HeapObject::cast(target_code)); | 316 host(), this, HeapObject::cast(target_code)); |
317 } | 317 } |
318 } | 318 } |
319 | 319 |
320 | 320 |
321 Object* RelocInfo::call_object() { | 321 Object* RelocInfo::call_object() { |
322 return *call_object_address(); | 322 return *call_object_address(); |
323 } | 323 } |
324 | 324 |
325 | 325 |
326 Object** RelocInfo::call_object_address() { | 326 Object** RelocInfo::call_object_address() { |
327 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 327 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
328 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 328 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
329 return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); | 329 return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); |
330 } | 330 } |
331 | 331 |
332 | 332 |
333 void RelocInfo::set_call_object(Object* target) { | 333 void RelocInfo::set_call_object(Object* target) { |
334 *call_object_address() = target; | 334 *call_object_address() = target; |
335 } | 335 } |
336 | 336 |
337 | 337 |
338 void RelocInfo::WipeOut() { | 338 void RelocInfo::WipeOut() { |
339 ASSERT(IsEmbeddedObject(rmode_) || | 339 DCHECK(IsEmbeddedObject(rmode_) || |
340 IsCodeTarget(rmode_) || | 340 IsCodeTarget(rmode_) || |
341 IsRuntimeEntry(rmode_) || | 341 IsRuntimeEntry(rmode_) || |
342 IsExternalReference(rmode_)); | 342 IsExternalReference(rmode_)); |
343 Assembler::set_target_address_at(pc_, host_, NULL); | 343 Assembler::set_target_address_at(pc_, host_, NULL); |
344 } | 344 } |
345 | 345 |
346 | 346 |
347 bool RelocInfo::IsPatchedReturnSequence() { | 347 bool RelocInfo::IsPatchedReturnSequence() { |
348 Instr instr0 = Assembler::instr_at(pc_); | 348 Instr instr0 = Assembler::instr_at(pc_); |
349 Instr instr1 = Assembler::instr_at(pc_ + 1 * Assembler::kInstrSize); | 349 Instr instr1 = Assembler::instr_at(pc_ + 1 * Assembler::kInstrSize); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 } | 436 } |
437 *reinterpret_cast<Instr*>(pc_) = x; | 437 *reinterpret_cast<Instr*>(pc_) = x; |
438 pc_ += kInstrSize; | 438 pc_ += kInstrSize; |
439 CheckTrampolinePoolQuick(); | 439 CheckTrampolinePoolQuick(); |
440 } | 440 } |
441 | 441 |
442 | 442 |
443 } } // namespace v8::internal | 443 } } // namespace v8::internal |
444 | 444 |
445 #endif // V8_MIPS_ASSEMBLER_MIPS_INL_H_ | 445 #endif // V8_MIPS_ASSEMBLER_MIPS_INL_H_ |
OLD | NEW |