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

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: Update SKIP_ICACHE_FLUSH_IF_ATOMIC to only skip when patching a single instruction. 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/assembler.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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 void Assembler::deserialization_set_special_target_at( 503 void Assembler::deserialization_set_special_target_at(
494 Address constant_pool_entry, Code* code, Address target) { 504 Address constant_pool_entry, Code* code, Address target) {
495 if (FLAG_enable_ool_constant_pool) { 505 if (FLAG_enable_ool_constant_pool) {
496 set_target_address_at(constant_pool_entry, code, target); 506 set_target_address_at(constant_pool_entry, code, target);
497 } else { 507 } else {
498 Memory::Address_at(constant_pool_entry) = target; 508 Memory::Address_at(constant_pool_entry) = target;
499 } 509 }
500 } 510 }
501 511
502 512
513 static uint32_t ExtractMovwImmediate(Instr instruction) {
Rodolph Perfetta 2014/05/19 12:38:38 the Instruction class has a ImmedMovwMovtValue met
rmcilroy 2014/05/19 16:52:16 Ack (no longer applicable).
514 ASSERT(Assembler::IsMovW(instruction) || Assembler::IsMovT(instruction));
515 return ((instruction & 0xf0000) >> 4) | (instruction & 0xfff);
516 }
517
518
503 static Instr EncodeMovwImmediate(uint32_t immediate) { 519 static Instr EncodeMovwImmediate(uint32_t immediate) {
504 ASSERT(immediate < 0x10000); 520 ASSERT(immediate < 0x10000);
505 return ((immediate & 0xf000) << 4) | (immediate & 0xfff); 521 return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
506 } 522 }
507 523
508 524
525 static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate) {
526 instruction &= ~EncodeMovwImmediate(0xffff);
527 return instruction | EncodeMovwImmediate(immediate);
528 }
529
530
509 void Assembler::set_target_address_at(Address pc, 531 void Assembler::set_target_address_at(Address pc,
510 ConstantPoolArray* constant_pool, 532 ConstantPoolArray* constant_pool,
511 Address target) { 533 Address target,
534 ICacheFlushMode icache_flush_mode) {
512 if (IsMovW(Memory::int32_at(pc))) { 535 if (IsMovW(Memory::int32_at(pc))) {
513 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); 536 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize)));
514 uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc); 537 uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc);
515 uint32_t immediate = reinterpret_cast<uint32_t>(target); 538 uint32_t immediate_high = reinterpret_cast<uint32_t>(target) >> 16;
516 uint32_t intermediate = instr_ptr[0]; 539 uint32_t immediate_low = reinterpret_cast<uint32_t>(target) & 0xFFFF;
517 intermediate &= ~EncodeMovwImmediate(0xFFFF); 540 int instructions_patched = 0;
518 intermediate |= EncodeMovwImmediate(immediate & 0xFFFF); 541 if (ExtractMovwImmediate(instr_ptr[0]) != immediate_low) {
519 instr_ptr[0] = intermediate; 542 instr_ptr[0] = PatchMovwImmediate(instr_ptr[0], immediate_low);
520 intermediate = instr_ptr[1]; 543 instructions_patched++;
521 intermediate &= ~EncodeMovwImmediate(0xFFFF); 544 }
522 intermediate |= EncodeMovwImmediate(immediate >> 16); 545 if (ExtractMovwImmediate(instr_ptr[1]) != immediate_high) {
523 instr_ptr[1] = intermediate; 546 instr_ptr[1] = PatchMovwImmediate(instr_ptr[1], immediate_high);
547 instructions_patched++;
548 }
524 ASSERT(IsMovW(Memory::int32_at(pc))); 549 ASSERT(IsMovW(Memory::int32_at(pc)));
525 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); 550 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize)));
526 CPU::FlushICache(pc, 2 * kInstrSize); 551 if (icache_flush_mode == SKIP_ICACHE_FLUSH ||
552 (icache_flush_mode == SKIP_ICACHE_FLUSH_IF_ATOMIC &&
553 instructions_patched <= 1)) {
554 // We can skip the icache flush in these cases.
555 } else {
556 CPU::FlushICache(pc, 2 * kInstrSize);
557 }
527 } else if (FLAG_enable_ool_constant_pool) { 558 } else if (FLAG_enable_ool_constant_pool) {
528 ASSERT(IsLdrPpImmediateOffset(Memory::int32_at(pc))); 559 ASSERT(IsLdrPpImmediateOffset(Memory::int32_at(pc)));
529 Memory::Address_at( 560 Memory::Address_at(
530 target_constant_pool_address_at(pc, constant_pool)) = target; 561 target_constant_pool_address_at(pc, constant_pool)) = target;
531 } else { 562 } else {
532 ASSERT(IsLdrPcImmediateOffset(Memory::int32_at(pc))); 563 ASSERT(IsLdrPcImmediateOffset(Memory::int32_at(pc)));
533 Memory::Address_at(target_pointer_address_at(pc)) = target; 564 Memory::Address_at(target_pointer_address_at(pc)) = target;
534 // Intuitively, we would think it is necessary to always flush the 565 // Intuitively, we would think it is necessary to always flush the
535 // instruction cache after patching a target address in the code as follows: 566 // instruction cache after patching a target address in the code as follows:
536 // CPU::FlushICache(pc, sizeof(target)); 567 // CPU::FlushICache(pc, sizeof(target));
537 // However, on ARM, no instruction is actually patched in the case 568 // However, on ARM, no instruction is actually patched in the case
538 // of embedded constants of the form: 569 // of embedded constants of the form:
539 // ldr ip, [pc, #...] 570 // ldr ip, [pc, #...]
540 // since the instruction accessing this address in the constant pool remains 571 // since the instruction accessing this address in the constant pool remains
541 // unchanged. 572 // unchanged.
542 } 573 }
543 } 574 }
544 575
545 576
546 } } // namespace v8::internal 577 } } // namespace v8::internal
547 578
548 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ 579 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_
OLDNEW
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698