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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 ASSERT(index >= 0 && index < NumAllocatableRegisters()); | 84 ASSERT(index >= 0 && index < NumAllocatableRegisters()); |
85 ASSERT(kScratchDoubleReg.code() - kDoubleRegZero.code() == | 85 ASSERT(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) { | 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 |
(...skipping 30 matching lines...) Expand all Loading... |
135 return Assembler::target_pointer_address_at(pc_); | 135 return Assembler::target_pointer_address_at(pc_); |
136 } | 136 } |
137 } | 137 } |
138 | 138 |
139 | 139 |
140 int RelocInfo::target_address_size() { | 140 int RelocInfo::target_address_size() { |
141 return kPointerSize; | 141 return kPointerSize; |
142 } | 142 } |
143 | 143 |
144 | 144 |
145 void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) { | 145 void RelocInfo::set_target_address(Address target, |
| 146 WriteBarrierMode write_barrier_mode, |
| 147 ICacheFlushMode icache_flush_mode) { |
146 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 148 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); |
147 Assembler::set_target_address_at(pc_, host_, target); | 149 Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode); |
148 if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) { | 150 if (write_barrier_mode == UPDATE_WRITE_BARRIER && |
| 151 host() != NULL && IsCodeTarget(rmode_)) { |
149 Object* target_code = Code::GetCodeFromTargetAddress(target); | 152 Object* target_code = Code::GetCodeFromTargetAddress(target); |
150 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 153 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( |
151 host(), this, HeapObject::cast(target_code)); | 154 host(), this, HeapObject::cast(target_code)); |
152 } | 155 } |
153 } | 156 } |
154 | 157 |
155 | 158 |
156 Object* RelocInfo::target_object() { | 159 Object* RelocInfo::target_object() { |
157 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 160 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
158 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_)); | 161 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_)); |
159 } | 162 } |
160 | 163 |
161 | 164 |
162 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { | 165 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { |
163 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 166 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
164 return Handle<Object>(reinterpret_cast<Object**>( | 167 return Handle<Object>(reinterpret_cast<Object**>( |
165 Assembler::target_address_at(pc_, host_))); | 168 Assembler::target_address_at(pc_, host_))); |
166 } | 169 } |
167 | 170 |
168 | 171 |
169 void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) { | 172 void RelocInfo::set_target_object(Object* target, |
| 173 WriteBarrierMode write_barrier_mode, |
| 174 ICacheFlushMode icache_flush_mode) { |
170 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 175 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
171 ASSERT(!target->IsConsString()); | 176 ASSERT(!target->IsConsString()); |
172 Assembler::set_target_address_at(pc_, host_, | 177 Assembler::set_target_address_at(pc_, host_, |
173 reinterpret_cast<Address>(target)); | 178 reinterpret_cast<Address>(target), |
174 if (mode == UPDATE_WRITE_BARRIER && | 179 icache_flush_mode); |
| 180 if (write_barrier_mode == UPDATE_WRITE_BARRIER && |
175 host() != NULL && | 181 host() != NULL && |
176 target->IsHeapObject()) { | 182 target->IsHeapObject()) { |
177 host()->GetHeap()->incremental_marking()->RecordWrite( | 183 host()->GetHeap()->incremental_marking()->RecordWrite( |
178 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); | 184 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); |
179 } | 185 } |
180 } | 186 } |
181 | 187 |
182 | 188 |
183 Address RelocInfo::target_reference() { | 189 Address RelocInfo::target_reference() { |
184 ASSERT(rmode_ == EXTERNAL_REFERENCE); | 190 ASSERT(rmode_ == EXTERNAL_REFERENCE); |
185 return Assembler::target_address_at(pc_, host_); | 191 return Assembler::target_address_at(pc_, host_); |
186 } | 192 } |
187 | 193 |
188 | 194 |
189 Address RelocInfo::target_runtime_entry(Assembler* origin) { | 195 Address RelocInfo::target_runtime_entry(Assembler* origin) { |
190 ASSERT(IsRuntimeEntry(rmode_)); | 196 ASSERT(IsRuntimeEntry(rmode_)); |
191 return target_address(); | 197 return target_address(); |
192 } | 198 } |
193 | 199 |
194 | 200 |
195 void RelocInfo::set_target_runtime_entry(Address target, | 201 void RelocInfo::set_target_runtime_entry(Address target, |
196 WriteBarrierMode mode) { | 202 WriteBarrierMode write_barrier_mode, |
| 203 ICacheFlushMode icache_flush_mode) { |
197 ASSERT(IsRuntimeEntry(rmode_)); | 204 ASSERT(IsRuntimeEntry(rmode_)); |
198 if (target_address() != target) set_target_address(target, mode); | 205 if (target_address() != target) |
| 206 set_target_address(target, write_barrier_mode, icache_flush_mode); |
199 } | 207 } |
200 | 208 |
201 | 209 |
202 Handle<Cell> RelocInfo::target_cell_handle() { | 210 Handle<Cell> RelocInfo::target_cell_handle() { |
203 ASSERT(rmode_ == RelocInfo::CELL); | 211 ASSERT(rmode_ == RelocInfo::CELL); |
204 Address address = Memory::Address_at(pc_); | 212 Address address = Memory::Address_at(pc_); |
205 return Handle<Cell>(reinterpret_cast<Cell**>(address)); | 213 return Handle<Cell>(reinterpret_cast<Cell**>(address)); |
206 } | 214 } |
207 | 215 |
208 | 216 |
209 Cell* RelocInfo::target_cell() { | 217 Cell* RelocInfo::target_cell() { |
210 ASSERT(rmode_ == RelocInfo::CELL); | 218 ASSERT(rmode_ == RelocInfo::CELL); |
211 return Cell::FromValueAddress(Memory::Address_at(pc_)); | 219 return Cell::FromValueAddress(Memory::Address_at(pc_)); |
212 } | 220 } |
213 | 221 |
214 | 222 |
215 void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode mode) { | 223 void RelocInfo::set_target_cell(Cell* cell, |
| 224 WriteBarrierMode write_barrier_mode, |
| 225 ICacheFlushMode icache_flush_mode) { |
216 ASSERT(rmode_ == RelocInfo::CELL); | 226 ASSERT(rmode_ == RelocInfo::CELL); |
217 Address address = cell->address() + Cell::kValueOffset; | 227 Address address = cell->address() + Cell::kValueOffset; |
218 Memory::Address_at(pc_) = address; | 228 Memory::Address_at(pc_) = address; |
219 if (mode == UPDATE_WRITE_BARRIER && host() != NULL) { | 229 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) { |
220 // TODO(1550) We are passing NULL as a slot because cell can never be on | 230 // TODO(1550) We are passing NULL as a slot because cell can never be on |
221 // evacuation candidate. | 231 // evacuation candidate. |
222 host()->GetHeap()->incremental_marking()->RecordWrite( | 232 host()->GetHeap()->incremental_marking()->RecordWrite( |
223 host(), NULL, cell); | 233 host(), NULL, cell); |
224 } | 234 } |
225 } | 235 } |
226 | 236 |
227 | 237 |
228 static const int kNoCodeAgeSequenceLength = 3 * Assembler::kInstrSize; | 238 static const int kNoCodeAgeSequenceLength = 3 * Assembler::kInstrSize; |
229 | 239 |
230 | 240 |
231 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { | 241 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { |
232 UNREACHABLE(); // This should never be reached on Arm. | 242 UNREACHABLE(); // This should never be reached on Arm. |
233 return Handle<Object>(); | 243 return Handle<Object>(); |
234 } | 244 } |
235 | 245 |
236 | 246 |
237 Code* RelocInfo::code_age_stub() { | 247 Code* RelocInfo::code_age_stub() { |
238 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 248 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); |
239 return Code::GetCodeFromTargetAddress( | 249 return Code::GetCodeFromTargetAddress( |
240 Memory::Address_at(pc_ + | 250 Memory::Address_at(pc_ + |
241 (kNoCodeAgeSequenceLength - Assembler::kInstrSize))); | 251 (kNoCodeAgeSequenceLength - Assembler::kInstrSize))); |
242 } | 252 } |
243 | 253 |
244 | 254 |
245 void RelocInfo::set_code_age_stub(Code* stub) { | 255 void RelocInfo::set_code_age_stub(Code* stub, |
| 256 ICacheFlushMode icache_flush_mode) { |
246 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 257 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); |
247 Memory::Address_at(pc_ + | 258 Memory::Address_at(pc_ + |
248 (kNoCodeAgeSequenceLength - Assembler::kInstrSize)) = | 259 (kNoCodeAgeSequenceLength - Assembler::kInstrSize)) = |
249 stub->instruction_start(); | 260 stub->instruction_start(); |
250 } | 261 } |
251 | 262 |
252 | 263 |
253 Address RelocInfo::call_address() { | 264 Address RelocInfo::call_address() { |
254 // The 2 instructions offset assumes patched debug break slot or return | 265 // The 2 instructions offset assumes patched debug break slot or return |
255 // sequence. | 266 // sequence. |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 } | 510 } |
500 } | 511 } |
501 | 512 |
502 | 513 |
503 static Instr EncodeMovwImmediate(uint32_t immediate) { | 514 static Instr EncodeMovwImmediate(uint32_t immediate) { |
504 ASSERT(immediate < 0x10000); | 515 ASSERT(immediate < 0x10000); |
505 return ((immediate & 0xf000) << 4) | (immediate & 0xfff); | 516 return ((immediate & 0xf000) << 4) | (immediate & 0xfff); |
506 } | 517 } |
507 | 518 |
508 | 519 |
| 520 static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate) { |
| 521 instruction &= ~EncodeMovwImmediate(0xffff); |
| 522 return instruction | EncodeMovwImmediate(immediate); |
| 523 } |
| 524 |
| 525 |
509 void Assembler::set_target_address_at(Address pc, | 526 void Assembler::set_target_address_at(Address pc, |
510 ConstantPoolArray* constant_pool, | 527 ConstantPoolArray* constant_pool, |
511 Address target) { | 528 Address target, |
| 529 ICacheFlushMode icache_flush_mode) { |
512 if (IsMovW(Memory::int32_at(pc))) { | 530 if (IsMovW(Memory::int32_at(pc))) { |
513 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); | 531 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); |
514 uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc); | 532 uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc); |
515 uint32_t immediate = reinterpret_cast<uint32_t>(target); | 533 uint32_t immediate = reinterpret_cast<uint32_t>(target); |
516 uint32_t intermediate = instr_ptr[0]; | 534 instr_ptr[0] = PatchMovwImmediate(instr_ptr[0], immediate & 0xFFFF); |
517 intermediate &= ~EncodeMovwImmediate(0xFFFF); | 535 instr_ptr[1] = PatchMovwImmediate(instr_ptr[1], immediate >> 16); |
518 intermediate |= EncodeMovwImmediate(immediate & 0xFFFF); | |
519 instr_ptr[0] = intermediate; | |
520 intermediate = instr_ptr[1]; | |
521 intermediate &= ~EncodeMovwImmediate(0xFFFF); | |
522 intermediate |= EncodeMovwImmediate(immediate >> 16); | |
523 instr_ptr[1] = intermediate; | |
524 ASSERT(IsMovW(Memory::int32_at(pc))); | 536 ASSERT(IsMovW(Memory::int32_at(pc))); |
525 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); | 537 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); |
526 CPU::FlushICache(pc, 2 * kInstrSize); | 538 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { |
| 539 CPU::FlushICache(pc, 2 * kInstrSize); |
| 540 } |
527 } else if (FLAG_enable_ool_constant_pool) { | 541 } else if (FLAG_enable_ool_constant_pool) { |
528 ASSERT(IsLdrPpImmediateOffset(Memory::int32_at(pc))); | 542 ASSERT(IsLdrPpImmediateOffset(Memory::int32_at(pc))); |
529 Memory::Address_at( | 543 Memory::Address_at( |
530 target_constant_pool_address_at(pc, constant_pool)) = target; | 544 target_constant_pool_address_at(pc, constant_pool)) = target; |
531 } else { | 545 } else { |
532 ASSERT(IsLdrPcImmediateOffset(Memory::int32_at(pc))); | 546 ASSERT(IsLdrPcImmediateOffset(Memory::int32_at(pc))); |
533 Memory::Address_at(target_pointer_address_at(pc)) = target; | 547 Memory::Address_at(target_pointer_address_at(pc)) = target; |
534 // Intuitively, we would think it is necessary to always flush the | 548 // Intuitively, we would think it is necessary to always flush the |
535 // instruction cache after patching a target address in the code as follows: | 549 // instruction cache after patching a target address in the code as follows: |
536 // CPU::FlushICache(pc, sizeof(target)); | 550 // CPU::FlushICache(pc, sizeof(target)); |
537 // However, on ARM, no instruction is actually patched in the case | 551 // However, on ARM, no instruction is actually patched in the case |
538 // of embedded constants of the form: | 552 // of embedded constants of the form: |
539 // ldr ip, [pc, #...] | 553 // ldr ip, [pc, #...] |
540 // since the instruction accessing this address in the constant pool remains | 554 // since the instruction accessing this address in the constant pool remains |
541 // unchanged. | 555 // unchanged. |
542 } | 556 } |
543 } | 557 } |
544 | 558 |
545 | 559 |
546 } } // namespace v8::internal | 560 } } // namespace v8::internal |
547 | 561 |
548 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ | 562 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ |
OLD | NEW |