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