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 |