Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(122)

Side by Side Diff: src/arm/assembler-arm-inl.h

Issue 284153004: Avoid flushing the icache unnecessarily when updating target addresses in code. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix intenting Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm64/assembler-arm64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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_
OLDNEW
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm64/assembler-arm64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698