| 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 |