| OLD | NEW |
| 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
| 2 // All Rights Reserved. | 2 // All Rights Reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
| 6 // are met: | 6 // are met: |
| 7 // | 7 // |
| 8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
| 9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
| 10 // | 10 // |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 return kNumReservedRegisters; | 64 return kNumReservedRegisters; |
| 65 } | 65 } |
| 66 | 66 |
| 67 | 67 |
| 68 int DwVfpRegister::NumAllocatableRegisters() { | 68 int DwVfpRegister::NumAllocatableRegisters() { |
| 69 return NumRegisters() - kNumReservedRegisters; | 69 return NumRegisters() - kNumReservedRegisters; |
| 70 } | 70 } |
| 71 | 71 |
| 72 | 72 |
| 73 int DwVfpRegister::ToAllocationIndex(DwVfpRegister reg) { | 73 int DwVfpRegister::ToAllocationIndex(DwVfpRegister reg) { |
| 74 ASSERT(!reg.is(kDoubleRegZero)); | 74 DCHECK(!reg.is(kDoubleRegZero)); |
| 75 ASSERT(!reg.is(kScratchDoubleReg)); | 75 DCHECK(!reg.is(kScratchDoubleReg)); |
| 76 if (reg.code() > kDoubleRegZero.code()) { | 76 if (reg.code() > kDoubleRegZero.code()) { |
| 77 return reg.code() - kNumReservedRegisters; | 77 return reg.code() - kNumReservedRegisters; |
| 78 } | 78 } |
| 79 return reg.code(); | 79 return reg.code(); |
| 80 } | 80 } |
| 81 | 81 |
| 82 | 82 |
| 83 DwVfpRegister DwVfpRegister::FromAllocationIndex(int index) { | 83 DwVfpRegister DwVfpRegister::FromAllocationIndex(int index) { |
| 84 ASSERT(index >= 0 && index < NumAllocatableRegisters()); | 84 DCHECK(index >= 0 && index < NumAllocatableRegisters()); |
| 85 ASSERT(kScratchDoubleReg.code() - kDoubleRegZero.code() == | 85 DCHECK(kScratchDoubleReg.code() - kDoubleRegZero.code() == |
| 86 kNumReservedRegisters - 1); | 86 kNumReservedRegisters - 1); |
| 87 if (index >= kDoubleRegZero.code()) { | 87 if (index >= kDoubleRegZero.code()) { |
| 88 return from_code(index + kNumReservedRegisters); | 88 return from_code(index + kNumReservedRegisters); |
| 89 } | 89 } |
| 90 return from_code(index); | 90 return from_code(index); |
| 91 } | 91 } |
| 92 | 92 |
| 93 | 93 |
| 94 void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) { | 94 void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) { |
| 95 if (RelocInfo::IsInternalReference(rmode_)) { | 95 if (RelocInfo::IsInternalReference(rmode_)) { |
| 96 // absolute code pointer inside code object moves with the code object. | 96 // absolute code pointer inside code object moves with the code object. |
| 97 int32_t* p = reinterpret_cast<int32_t*>(pc_); | 97 int32_t* p = reinterpret_cast<int32_t*>(pc_); |
| 98 *p += delta; // relocate entry | 98 *p += delta; // relocate entry |
| 99 } | 99 } |
| 100 // We do not use pc relative addressing on ARM, so there is | 100 // We do not use pc relative addressing on ARM, so there is |
| 101 // nothing else to do. | 101 // nothing else to do. |
| 102 } | 102 } |
| 103 | 103 |
| 104 | 104 |
| 105 Address RelocInfo::target_address() { | 105 Address RelocInfo::target_address() { |
| 106 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 106 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); |
| 107 return Assembler::target_address_at(pc_, host_); | 107 return Assembler::target_address_at(pc_, host_); |
| 108 } | 108 } |
| 109 | 109 |
| 110 | 110 |
| 111 Address RelocInfo::target_address_address() { | 111 Address RelocInfo::target_address_address() { |
| 112 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) | 112 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) |
| 113 || rmode_ == EMBEDDED_OBJECT | 113 || rmode_ == EMBEDDED_OBJECT |
| 114 || rmode_ == EXTERNAL_REFERENCE); | 114 || rmode_ == EXTERNAL_REFERENCE); |
| 115 if (FLAG_enable_ool_constant_pool || | 115 if (FLAG_enable_ool_constant_pool || |
| 116 Assembler::IsMovW(Memory::int32_at(pc_))) { | 116 Assembler::IsMovW(Memory::int32_at(pc_))) { |
| 117 // We return the PC for ool constant pool since this function is used by the | 117 // We return the PC for ool constant pool since this function is used by the |
| 118 // serializerer and expects the address to reside within the code object. | 118 // serializerer and expects the address to reside within the code object. |
| 119 return reinterpret_cast<Address>(pc_); | 119 return reinterpret_cast<Address>(pc_); |
| 120 } else { | 120 } else { |
| 121 ASSERT(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_))); | 121 DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_))); |
| 122 return constant_pool_entry_address(); | 122 return constant_pool_entry_address(); |
| 123 } | 123 } |
| 124 } | 124 } |
| 125 | 125 |
| 126 | 126 |
| 127 Address RelocInfo::constant_pool_entry_address() { | 127 Address RelocInfo::constant_pool_entry_address() { |
| 128 ASSERT(IsInConstantPool()); | 128 DCHECK(IsInConstantPool()); |
| 129 return Assembler::constant_pool_entry_address(pc_, host_->constant_pool()); | 129 return Assembler::constant_pool_entry_address(pc_, host_->constant_pool()); |
| 130 } | 130 } |
| 131 | 131 |
| 132 | 132 |
| 133 int RelocInfo::target_address_size() { | 133 int RelocInfo::target_address_size() { |
| 134 return kPointerSize; | 134 return kPointerSize; |
| 135 } | 135 } |
| 136 | 136 |
| 137 | 137 |
| 138 void RelocInfo::set_target_address(Address target, | 138 void RelocInfo::set_target_address(Address target, |
| 139 WriteBarrierMode write_barrier_mode, | 139 WriteBarrierMode write_barrier_mode, |
| 140 ICacheFlushMode icache_flush_mode) { | 140 ICacheFlushMode icache_flush_mode) { |
| 141 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 141 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); |
| 142 Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode); | 142 Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode); |
| 143 if (write_barrier_mode == UPDATE_WRITE_BARRIER && | 143 if (write_barrier_mode == UPDATE_WRITE_BARRIER && |
| 144 host() != NULL && IsCodeTarget(rmode_)) { | 144 host() != NULL && IsCodeTarget(rmode_)) { |
| 145 Object* target_code = Code::GetCodeFromTargetAddress(target); | 145 Object* target_code = Code::GetCodeFromTargetAddress(target); |
| 146 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 146 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( |
| 147 host(), this, HeapObject::cast(target_code)); | 147 host(), this, HeapObject::cast(target_code)); |
| 148 } | 148 } |
| 149 } | 149 } |
| 150 | 150 |
| 151 | 151 |
| 152 Object* RelocInfo::target_object() { | 152 Object* RelocInfo::target_object() { |
| 153 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 153 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| 154 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_)); | 154 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_)); |
| 155 } | 155 } |
| 156 | 156 |
| 157 | 157 |
| 158 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { | 158 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { |
| 159 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 159 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| 160 return Handle<Object>(reinterpret_cast<Object**>( | 160 return Handle<Object>(reinterpret_cast<Object**>( |
| 161 Assembler::target_address_at(pc_, host_))); | 161 Assembler::target_address_at(pc_, host_))); |
| 162 } | 162 } |
| 163 | 163 |
| 164 | 164 |
| 165 void RelocInfo::set_target_object(Object* target, | 165 void RelocInfo::set_target_object(Object* target, |
| 166 WriteBarrierMode write_barrier_mode, | 166 WriteBarrierMode write_barrier_mode, |
| 167 ICacheFlushMode icache_flush_mode) { | 167 ICacheFlushMode icache_flush_mode) { |
| 168 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 168 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| 169 Assembler::set_target_address_at(pc_, host_, | 169 Assembler::set_target_address_at(pc_, host_, |
| 170 reinterpret_cast<Address>(target), | 170 reinterpret_cast<Address>(target), |
| 171 icache_flush_mode); | 171 icache_flush_mode); |
| 172 if (write_barrier_mode == UPDATE_WRITE_BARRIER && | 172 if (write_barrier_mode == UPDATE_WRITE_BARRIER && |
| 173 host() != NULL && | 173 host() != NULL && |
| 174 target->IsHeapObject()) { | 174 target->IsHeapObject()) { |
| 175 host()->GetHeap()->incremental_marking()->RecordWrite( | 175 host()->GetHeap()->incremental_marking()->RecordWrite( |
| 176 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); | 176 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); |
| 177 } | 177 } |
| 178 } | 178 } |
| 179 | 179 |
| 180 | 180 |
| 181 Address RelocInfo::target_reference() { | 181 Address RelocInfo::target_reference() { |
| 182 ASSERT(rmode_ == EXTERNAL_REFERENCE); | 182 DCHECK(rmode_ == EXTERNAL_REFERENCE); |
| 183 return Assembler::target_address_at(pc_, host_); | 183 return Assembler::target_address_at(pc_, host_); |
| 184 } | 184 } |
| 185 | 185 |
| 186 | 186 |
| 187 Address RelocInfo::target_runtime_entry(Assembler* origin) { | 187 Address RelocInfo::target_runtime_entry(Assembler* origin) { |
| 188 ASSERT(IsRuntimeEntry(rmode_)); | 188 DCHECK(IsRuntimeEntry(rmode_)); |
| 189 return target_address(); | 189 return target_address(); |
| 190 } | 190 } |
| 191 | 191 |
| 192 | 192 |
| 193 void RelocInfo::set_target_runtime_entry(Address target, | 193 void RelocInfo::set_target_runtime_entry(Address target, |
| 194 WriteBarrierMode write_barrier_mode, | 194 WriteBarrierMode write_barrier_mode, |
| 195 ICacheFlushMode icache_flush_mode) { | 195 ICacheFlushMode icache_flush_mode) { |
| 196 ASSERT(IsRuntimeEntry(rmode_)); | 196 DCHECK(IsRuntimeEntry(rmode_)); |
| 197 if (target_address() != target) | 197 if (target_address() != target) |
| 198 set_target_address(target, write_barrier_mode, icache_flush_mode); | 198 set_target_address(target, write_barrier_mode, icache_flush_mode); |
| 199 } | 199 } |
| 200 | 200 |
| 201 | 201 |
| 202 Handle<Cell> RelocInfo::target_cell_handle() { | 202 Handle<Cell> RelocInfo::target_cell_handle() { |
| 203 ASSERT(rmode_ == RelocInfo::CELL); | 203 DCHECK(rmode_ == RelocInfo::CELL); |
| 204 Address address = Memory::Address_at(pc_); | 204 Address address = Memory::Address_at(pc_); |
| 205 return Handle<Cell>(reinterpret_cast<Cell**>(address)); | 205 return Handle<Cell>(reinterpret_cast<Cell**>(address)); |
| 206 } | 206 } |
| 207 | 207 |
| 208 | 208 |
| 209 Cell* RelocInfo::target_cell() { | 209 Cell* RelocInfo::target_cell() { |
| 210 ASSERT(rmode_ == RelocInfo::CELL); | 210 DCHECK(rmode_ == RelocInfo::CELL); |
| 211 return Cell::FromValueAddress(Memory::Address_at(pc_)); | 211 return Cell::FromValueAddress(Memory::Address_at(pc_)); |
| 212 } | 212 } |
| 213 | 213 |
| 214 | 214 |
| 215 void RelocInfo::set_target_cell(Cell* cell, | 215 void RelocInfo::set_target_cell(Cell* cell, |
| 216 WriteBarrierMode write_barrier_mode, | 216 WriteBarrierMode write_barrier_mode, |
| 217 ICacheFlushMode icache_flush_mode) { | 217 ICacheFlushMode icache_flush_mode) { |
| 218 ASSERT(rmode_ == RelocInfo::CELL); | 218 DCHECK(rmode_ == RelocInfo::CELL); |
| 219 Address address = cell->address() + Cell::kValueOffset; | 219 Address address = cell->address() + Cell::kValueOffset; |
| 220 Memory::Address_at(pc_) = address; | 220 Memory::Address_at(pc_) = address; |
| 221 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) { | 221 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) { |
| 222 // TODO(1550) We are passing NULL as a slot because cell can never be on | 222 // TODO(1550) We are passing NULL as a slot because cell can never be on |
| 223 // evacuation candidate. | 223 // evacuation candidate. |
| 224 host()->GetHeap()->incremental_marking()->RecordWrite( | 224 host()->GetHeap()->incremental_marking()->RecordWrite( |
| 225 host(), NULL, cell); | 225 host(), NULL, cell); |
| 226 } | 226 } |
| 227 } | 227 } |
| 228 | 228 |
| 229 | 229 |
| 230 static const int kNoCodeAgeSequenceLength = 3 * Assembler::kInstrSize; | 230 static const int kNoCodeAgeSequenceLength = 3 * Assembler::kInstrSize; |
| 231 | 231 |
| 232 | 232 |
| 233 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { | 233 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { |
| 234 UNREACHABLE(); // This should never be reached on Arm. | 234 UNREACHABLE(); // This should never be reached on Arm. |
| 235 return Handle<Object>(); | 235 return Handle<Object>(); |
| 236 } | 236 } |
| 237 | 237 |
| 238 | 238 |
| 239 Code* RelocInfo::code_age_stub() { | 239 Code* RelocInfo::code_age_stub() { |
| 240 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 240 DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); |
| 241 return Code::GetCodeFromTargetAddress( | 241 return Code::GetCodeFromTargetAddress( |
| 242 Memory::Address_at(pc_ + | 242 Memory::Address_at(pc_ + |
| 243 (kNoCodeAgeSequenceLength - Assembler::kInstrSize))); | 243 (kNoCodeAgeSequenceLength - Assembler::kInstrSize))); |
| 244 } | 244 } |
| 245 | 245 |
| 246 | 246 |
| 247 void RelocInfo::set_code_age_stub(Code* stub, | 247 void RelocInfo::set_code_age_stub(Code* stub, |
| 248 ICacheFlushMode icache_flush_mode) { | 248 ICacheFlushMode icache_flush_mode) { |
| 249 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 249 DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); |
| 250 Memory::Address_at(pc_ + | 250 Memory::Address_at(pc_ + |
| 251 (kNoCodeAgeSequenceLength - Assembler::kInstrSize)) = | 251 (kNoCodeAgeSequenceLength - Assembler::kInstrSize)) = |
| 252 stub->instruction_start(); | 252 stub->instruction_start(); |
| 253 } | 253 } |
| 254 | 254 |
| 255 | 255 |
| 256 Address RelocInfo::call_address() { | 256 Address RelocInfo::call_address() { |
| 257 // The 2 instructions offset assumes patched debug break slot or return | 257 // The 2 instructions offset assumes patched debug break slot or return |
| 258 // sequence. | 258 // sequence. |
| 259 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 259 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
| 260 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 260 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
| 261 return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize); | 261 return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize); |
| 262 } | 262 } |
| 263 | 263 |
| 264 | 264 |
| 265 void RelocInfo::set_call_address(Address target) { | 265 void RelocInfo::set_call_address(Address target) { |
| 266 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 266 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
| 267 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 267 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
| 268 Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target; | 268 Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target; |
| 269 if (host() != NULL) { | 269 if (host() != NULL) { |
| 270 Object* target_code = Code::GetCodeFromTargetAddress(target); | 270 Object* target_code = Code::GetCodeFromTargetAddress(target); |
| 271 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 271 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( |
| 272 host(), this, HeapObject::cast(target_code)); | 272 host(), this, HeapObject::cast(target_code)); |
| 273 } | 273 } |
| 274 } | 274 } |
| 275 | 275 |
| 276 | 276 |
| 277 Object* RelocInfo::call_object() { | 277 Object* RelocInfo::call_object() { |
| 278 return *call_object_address(); | 278 return *call_object_address(); |
| 279 } | 279 } |
| 280 | 280 |
| 281 | 281 |
| 282 void RelocInfo::set_call_object(Object* target) { | 282 void RelocInfo::set_call_object(Object* target) { |
| 283 *call_object_address() = target; | 283 *call_object_address() = target; |
| 284 } | 284 } |
| 285 | 285 |
| 286 | 286 |
| 287 Object** RelocInfo::call_object_address() { | 287 Object** RelocInfo::call_object_address() { |
| 288 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 288 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
| 289 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 289 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
| 290 return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); | 290 return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); |
| 291 } | 291 } |
| 292 | 292 |
| 293 | 293 |
| 294 void RelocInfo::WipeOut() { | 294 void RelocInfo::WipeOut() { |
| 295 ASSERT(IsEmbeddedObject(rmode_) || | 295 DCHECK(IsEmbeddedObject(rmode_) || |
| 296 IsCodeTarget(rmode_) || | 296 IsCodeTarget(rmode_) || |
| 297 IsRuntimeEntry(rmode_) || | 297 IsRuntimeEntry(rmode_) || |
| 298 IsExternalReference(rmode_)); | 298 IsExternalReference(rmode_)); |
| 299 Assembler::set_target_address_at(pc_, host_, NULL); | 299 Assembler::set_target_address_at(pc_, host_, NULL); |
| 300 } | 300 } |
| 301 | 301 |
| 302 | 302 |
| 303 bool RelocInfo::IsPatchedReturnSequence() { | 303 bool RelocInfo::IsPatchedReturnSequence() { |
| 304 Instr current_instr = Assembler::instr_at(pc_); | 304 Instr current_instr = Assembler::instr_at(pc_); |
| 305 Instr next_instr = Assembler::instr_at(pc_ + Assembler::kInstrSize); | 305 Instr next_instr = Assembler::instr_at(pc_ + Assembler::kInstrSize); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 // ldr ip, [pc, ip] @ call address | 439 // ldr ip, [pc, ip] @ call address |
| 440 // blx ip | 440 // blx ip |
| 441 // @ return address | 441 // @ return address |
| 442 Address candidate = pc - 2 * Assembler::kInstrSize; | 442 Address candidate = pc - 2 * Assembler::kInstrSize; |
| 443 Instr candidate_instr(Memory::int32_at(candidate)); | 443 Instr candidate_instr(Memory::int32_at(candidate)); |
| 444 if (IsLdrPcImmediateOffset(candidate_instr) | | 444 if (IsLdrPcImmediateOffset(candidate_instr) | |
| 445 IsLdrPpImmediateOffset(candidate_instr)) { | 445 IsLdrPpImmediateOffset(candidate_instr)) { |
| 446 return candidate; | 446 return candidate; |
| 447 } else if (IsLdrPpRegOffset(candidate_instr)) { | 447 } else if (IsLdrPpRegOffset(candidate_instr)) { |
| 448 candidate = pc - 4 * Assembler::kInstrSize; | 448 candidate = pc - 4 * Assembler::kInstrSize; |
| 449 ASSERT(IsMovW(Memory::int32_at(candidate)) && | 449 DCHECK(IsMovW(Memory::int32_at(candidate)) && |
| 450 IsMovT(Memory::int32_at(candidate + Assembler::kInstrSize))); | 450 IsMovT(Memory::int32_at(candidate + Assembler::kInstrSize))); |
| 451 return candidate; | 451 return candidate; |
| 452 } else { | 452 } else { |
| 453 candidate = pc - 3 * Assembler::kInstrSize; | 453 candidate = pc - 3 * Assembler::kInstrSize; |
| 454 ASSERT(IsMovW(Memory::int32_at(candidate)) && | 454 DCHECK(IsMovW(Memory::int32_at(candidate)) && |
| 455 IsMovT(Memory::int32_at(candidate + kInstrSize))); | 455 IsMovT(Memory::int32_at(candidate + kInstrSize))); |
| 456 return candidate; | 456 return candidate; |
| 457 } | 457 } |
| 458 } | 458 } |
| 459 | 459 |
| 460 | 460 |
| 461 Address Assembler::return_address_from_call_start(Address pc) { | 461 Address Assembler::return_address_from_call_start(Address pc) { |
| 462 if (IsLdrPcImmediateOffset(Memory::int32_at(pc)) | | 462 if (IsLdrPcImmediateOffset(Memory::int32_at(pc)) | |
| 463 IsLdrPpImmediateOffset(Memory::int32_at(pc))) { | 463 IsLdrPpImmediateOffset(Memory::int32_at(pc))) { |
| 464 // Load from constant pool, small section. | 464 // Load from constant pool, small section. |
| 465 return pc + kInstrSize * 2; | 465 return pc + kInstrSize * 2; |
| 466 } else { | 466 } else { |
| 467 ASSERT(IsMovW(Memory::int32_at(pc))); | 467 DCHECK(IsMovW(Memory::int32_at(pc))); |
| 468 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); | 468 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize))); |
| 469 if (IsLdrPpRegOffset(Memory::int32_at(pc + kInstrSize))) { | 469 if (IsLdrPpRegOffset(Memory::int32_at(pc + kInstrSize))) { |
| 470 // Load from constant pool, extended section. | 470 // Load from constant pool, extended section. |
| 471 return pc + kInstrSize * 4; | 471 return pc + kInstrSize * 4; |
| 472 } else { | 472 } else { |
| 473 // A movw / movt load immediate. | 473 // A movw / movt load immediate. |
| 474 return pc + kInstrSize * 3; | 474 return pc + kInstrSize * 3; |
| 475 } | 475 } |
| 476 } | 476 } |
| 477 } | 477 } |
| 478 | 478 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 491 return !Assembler::IsMovW(Memory::int32_at(pc)) || | 491 return !Assembler::IsMovW(Memory::int32_at(pc)) || |
| 492 (FLAG_enable_ool_constant_pool && | 492 (FLAG_enable_ool_constant_pool && |
| 493 Assembler::IsLdrPpRegOffset( | 493 Assembler::IsLdrPpRegOffset( |
| 494 Memory::int32_at(pc + 2 * Assembler::kInstrSize))); | 494 Memory::int32_at(pc + 2 * Assembler::kInstrSize))); |
| 495 } | 495 } |
| 496 | 496 |
| 497 | 497 |
| 498 Address Assembler::constant_pool_entry_address( | 498 Address Assembler::constant_pool_entry_address( |
| 499 Address pc, ConstantPoolArray* constant_pool) { | 499 Address pc, ConstantPoolArray* constant_pool) { |
| 500 if (FLAG_enable_ool_constant_pool) { | 500 if (FLAG_enable_ool_constant_pool) { |
| 501 ASSERT(constant_pool != NULL); | 501 DCHECK(constant_pool != NULL); |
| 502 int cp_offset; | 502 int cp_offset; |
| 503 if (IsMovW(Memory::int32_at(pc))) { | 503 if (IsMovW(Memory::int32_at(pc))) { |
| 504 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize)) && | 504 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)) && |
| 505 IsLdrPpRegOffset(Memory::int32_at(pc + 2 * kInstrSize))); | 505 IsLdrPpRegOffset(Memory::int32_at(pc + 2 * kInstrSize))); |
| 506 // This is an extended constant pool lookup. | 506 // This is an extended constant pool lookup. |
| 507 Instruction* movw_instr = Instruction::At(pc); | 507 Instruction* movw_instr = Instruction::At(pc); |
| 508 Instruction* movt_instr = Instruction::At(pc + kInstrSize); | 508 Instruction* movt_instr = Instruction::At(pc + kInstrSize); |
| 509 cp_offset = (movt_instr->ImmedMovwMovtValue() << 16) | | 509 cp_offset = (movt_instr->ImmedMovwMovtValue() << 16) | |
| 510 movw_instr->ImmedMovwMovtValue(); | 510 movw_instr->ImmedMovwMovtValue(); |
| 511 } else { | 511 } else { |
| 512 // This is a small constant pool lookup. | 512 // This is a small constant pool lookup. |
| 513 ASSERT(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(pc))); | 513 DCHECK(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(pc))); |
| 514 cp_offset = GetLdrRegisterImmediateOffset(Memory::int32_at(pc)); | 514 cp_offset = GetLdrRegisterImmediateOffset(Memory::int32_at(pc)); |
| 515 } | 515 } |
| 516 return reinterpret_cast<Address>(constant_pool) + cp_offset; | 516 return reinterpret_cast<Address>(constant_pool) + cp_offset; |
| 517 } else { | 517 } else { |
| 518 ASSERT(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc))); | 518 DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc))); |
| 519 Instr instr = Memory::int32_at(pc); | 519 Instr instr = Memory::int32_at(pc); |
| 520 return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta; | 520 return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta; |
| 521 } | 521 } |
| 522 } | 522 } |
| 523 | 523 |
| 524 | 524 |
| 525 Address Assembler::target_address_at(Address pc, | 525 Address Assembler::target_address_at(Address pc, |
| 526 ConstantPoolArray* constant_pool) { | 526 ConstantPoolArray* constant_pool) { |
| 527 if (is_constant_pool_load(pc)) { | 527 if (is_constant_pool_load(pc)) { |
| 528 // This is a constant pool lookup. Return the value in the constant pool. | 528 // This is a constant pool lookup. Return the value in the constant pool. |
| 529 return Memory::Address_at(constant_pool_entry_address(pc, constant_pool)); | 529 return Memory::Address_at(constant_pool_entry_address(pc, constant_pool)); |
| 530 } else { | 530 } else { |
| 531 // This is an movw_movt immediate load. Return the immediate. | 531 // This is an movw_movt immediate load. Return the immediate. |
| 532 ASSERT(IsMovW(Memory::int32_at(pc)) && | 532 DCHECK(IsMovW(Memory::int32_at(pc)) && |
| 533 IsMovT(Memory::int32_at(pc + kInstrSize))); | 533 IsMovT(Memory::int32_at(pc + kInstrSize))); |
| 534 Instruction* movw_instr = Instruction::At(pc); | 534 Instruction* movw_instr = Instruction::At(pc); |
| 535 Instruction* movt_instr = Instruction::At(pc + kInstrSize); | 535 Instruction* movt_instr = Instruction::At(pc + kInstrSize); |
| 536 return reinterpret_cast<Address>( | 536 return reinterpret_cast<Address>( |
| 537 (movt_instr->ImmedMovwMovtValue() << 16) | | 537 (movt_instr->ImmedMovwMovtValue() << 16) | |
| 538 movw_instr->ImmedMovwMovtValue()); | 538 movw_instr->ImmedMovwMovtValue()); |
| 539 } | 539 } |
| 540 } | 540 } |
| 541 | 541 |
| 542 | 542 |
| 543 void Assembler::set_target_address_at(Address pc, | 543 void Assembler::set_target_address_at(Address pc, |
| 544 ConstantPoolArray* constant_pool, | 544 ConstantPoolArray* constant_pool, |
| 545 Address target, | 545 Address target, |
| 546 ICacheFlushMode icache_flush_mode) { | 546 ICacheFlushMode icache_flush_mode) { |
| 547 if (is_constant_pool_load(pc)) { | 547 if (is_constant_pool_load(pc)) { |
| 548 // This is a constant pool lookup. Update the entry in the constant pool. | 548 // This is a constant pool lookup. Update the entry in the constant pool. |
| 549 Memory::Address_at(constant_pool_entry_address(pc, constant_pool)) = target; | 549 Memory::Address_at(constant_pool_entry_address(pc, constant_pool)) = target; |
| 550 // Intuitively, we would think it is necessary to always flush the | 550 // Intuitively, we would think it is necessary to always flush the |
| 551 // instruction cache after patching a target address in the code as follows: | 551 // instruction cache after patching a target address in the code as follows: |
| 552 // CpuFeatures::FlushICache(pc, sizeof(target)); | 552 // CpuFeatures::FlushICache(pc, sizeof(target)); |
| 553 // However, on ARM, no instruction is actually patched in the case | 553 // However, on ARM, no instruction is actually patched in the case |
| 554 // of embedded constants of the form: | 554 // of embedded constants of the form: |
| 555 // ldr ip, [pp, #...] | 555 // ldr ip, [pp, #...] |
| 556 // since the instruction accessing this address in the constant pool remains | 556 // since the instruction accessing this address in the constant pool remains |
| 557 // unchanged. | 557 // unchanged. |
| 558 } else { | 558 } else { |
| 559 // This is an movw_movt immediate load. Patch the immediate embedded in the | 559 // This is an movw_movt immediate load. Patch the immediate embedded in the |
| 560 // instructions. | 560 // instructions. |
| 561 ASSERT(IsMovW(Memory::int32_at(pc))); | 561 DCHECK(IsMovW(Memory::int32_at(pc))); |
| 562 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); | 562 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize))); |
| 563 uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc); | 563 uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc); |
| 564 uint32_t immediate = reinterpret_cast<uint32_t>(target); | 564 uint32_t immediate = reinterpret_cast<uint32_t>(target); |
| 565 instr_ptr[0] = PatchMovwImmediate(instr_ptr[0], immediate & 0xFFFF); | 565 instr_ptr[0] = PatchMovwImmediate(instr_ptr[0], immediate & 0xFFFF); |
| 566 instr_ptr[1] = PatchMovwImmediate(instr_ptr[1], immediate >> 16); | 566 instr_ptr[1] = PatchMovwImmediate(instr_ptr[1], immediate >> 16); |
| 567 ASSERT(IsMovW(Memory::int32_at(pc))); | 567 DCHECK(IsMovW(Memory::int32_at(pc))); |
| 568 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); | 568 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize))); |
| 569 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { | 569 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { |
| 570 CpuFeatures::FlushICache(pc, 2 * kInstrSize); | 570 CpuFeatures::FlushICache(pc, 2 * kInstrSize); |
| 571 } | 571 } |
| 572 } | 572 } |
| 573 } | 573 } |
| 574 | 574 |
| 575 | 575 |
| 576 } } // namespace v8::internal | 576 } } // namespace v8::internal |
| 577 | 577 |
| 578 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ | 578 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ |
| OLD | NEW |