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

Unified Diff: src/arm/assembler-arm-inl.h

Issue 11037023: Use movw/movt instead of constant pool on ARMv7 (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: More fixes and nit fixes Created 8 years, 2 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 side-by-side diff with in-line comments
Download patch
Index: src/arm/assembler-arm-inl.h
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index c47c094756135a1f307631d6967baf5dd9d651e5..59316318df79beabc262c5768ac64e0886aa1fa6 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -97,19 +97,24 @@ void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) {
Object* RelocInfo::target_object() {
ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
- return Memory::Object_at(Assembler::target_address_address_at(pc_));
+ return reinterpret_cast<Object*>(Assembler::target_address_at(pc_));
}
Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
- return Memory::Object_Handle_at(Assembler::target_address_address_at(pc_));
+ return Handle<Object>(reinterpret_cast<Object**>(
+ Assembler::target_address_at(pc_)));
}
Object** RelocInfo::target_object_address() {
+ // Provide a "natural pointer" to the embedded object,
+ // which can be de-referenced during heap iteration.
ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
- return reinterpret_cast<Object**>(Assembler::target_address_address_at(pc_));
+ reconstructed_obj_ptr_ =
+ reinterpret_cast<Object*>(Assembler::target_address_at(pc_));
+ return &reconstructed_obj_ptr_;
}
@@ -127,7 +132,8 @@ void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) {
Address* RelocInfo::target_reference_address() {
ASSERT(rmode_ == EXTERNAL_REFERENCE);
- return reinterpret_cast<Address*>(Assembler::target_address_address_at(pc_));
+ reconstructed_adr_ptr_ = Assembler::target_address_at(pc_);
+ return &reconstructed_adr_ptr_;
}
@@ -357,10 +363,65 @@ Address Assembler::target_address_address_at(Address pc) {
Address Assembler::target_address_at(Address pc) {
+ if (IsMovW(Memory::int32_at(pc))) {
+ ASSERT(IsMovT(Memory::int32_at(pc + 4)));
Please use jfb - chromium.org 2012/10/10 13:56:52 + kInstrSize
danno 2012/10/17 10:04:44 Done.
+ Instruction* instr = Instruction::At(pc);
+ Instruction* next_instr = Instruction::At(pc + 4);
Please use jfb - chromium.org 2012/10/10 13:56:52 + kInstrSize
danno 2012/10/17 10:04:44 Done.
+ return reinterpret_cast<Address>(
+ (next_instr->ImmedMovwMovtValue() << 16) |
+ instr->ImmedMovwMovtValue());
Please use jfb - chromium.org 2012/10/10 13:56:52 The bottom two bits should be zero, which might be
danno 2012/10/17 10:04:44 Done.
+ }
return Memory::Address_at(target_address_address_at(pc));
}
+Address Assembler::target_address_from_return_address(Address pc) {
+ // Returns the address of the call target from the return address that will
+ // be returned to after a call.
+#ifdef USE_BLX
+ // Call sequence on V7 or later is :
+ // movw ip, #... @ call address low 16
+ // movt ip, #... @ call address high 16
+ // blx ip
+ // @ return address
+ // Or pre v8:
Please use jfb - chromium.org 2012/10/10 13:56:52 Pre v8?
danno 2012/10/17 10:04:44 Done.
+ // ldr ip, [pc, #...] @ call address
+ // blx ip
+ // @ return address
+ Address candidate = pc - 2 * Assembler::kInstrSize;
+ Instr candidate_instr(Memory::int32_at(candidate));
+ if (IsLdrPcImmediateOffset(candidate_instr)) {
+ return candidate;
+ }
+ candidate = pc - 3 * Assembler::kInstrSize;
+ ASSERT(IsMovW(Memory::int32_at(candidate)) &&
+ IsMovT(Memory::int32_at(candidate + 4)));
Please use jfb - chromium.org 2012/10/10 13:56:52 + kInstrSize
danno 2012/10/17 10:04:44 Done.
+ return candidate;
+#else
+ // Call sequence is:
+ // mov lr, pc
+ // ldr pc, [pc, #...] @ call address
+ // @ return address
+ return pc - kInstrSize;
+#endif
+}
+
+
+Address Assembler::return_address_from_call_start(Address pc) {
+#ifdef USE_BLX
+ if (IsLdrPcImmediateOffset(Memory::int32_at(pc))) {
+ return pc + kInstrSize * 2;
+ } else {
+ ASSERT(IsMovW(Memory::int32_at(pc)));
+ ASSERT(IsMovT(Memory::int32_at(pc+4)));
+ return pc + kInstrSize * 3;
+ }
+#else
+ return pc + kInstrSize;
+#endif
+}
+
+
void Assembler::deserialization_set_special_target_at(
Address constant_pool_entry, Address target) {
Memory::Address_at(constant_pool_entry) = target;
@@ -373,15 +434,38 @@ void Assembler::set_external_target_at(Address constant_pool_entry,
}
+static Instr EncodeMovwImmediate(uint32_t immediate) {
+ ASSERT(immediate < 0x10000);
+ return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
+}
+
+
void Assembler::set_target_address_at(Address pc, Address target) {
Please use jfb - chromium.org 2012/10/10 13:56:52 As noted above: target &= ~3;
danno 2012/10/17 10:04:44 Done.
- Memory::Address_at(target_address_address_at(pc)) = target;
- // Intuitively, we would think it is necessary to flush the instruction cache
- // after patching a target address in the code as follows:
- // CPU::FlushICache(pc, sizeof(target));
- // However, on ARM, no instruction was actually patched by the assignment
- // above; the target address is not part of an instruction, it is patched in
- // the constant pool and is read via a data access; the instruction accessing
- // this address in the constant pool remains unchanged.
+ if (IsMovW(Memory::int32_at(pc))) {
+ ASSERT(IsMovT(Memory::int32_at(pc + 4)));
Please use jfb - chromium.org 2012/10/10 13:56:52 + kInstrSize
danno 2012/10/17 10:04:44 Done.
+ uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc);
+ uint32_t immediate = reinterpret_cast<uint32_t>(target);
+ uint32_t intermediate = instr_ptr[0];
+ intermediate &= ~EncodeMovwImmediate(0xFFFF);
+ intermediate |= EncodeMovwImmediate(immediate & 0xFFFF);
+ instr_ptr[0] = intermediate;
+ intermediate = instr_ptr[1];
+ intermediate &= ~EncodeMovwImmediate(0xFFFF);
+ intermediate |= EncodeMovwImmediate(immediate >> 16);
+ instr_ptr[1] = intermediate;
+ ASSERT(IsMovW(Memory::int32_at(pc)));
+ ASSERT(IsMovT(Memory::int32_at(pc + 4)));
Please use jfb - chromium.org 2012/10/10 13:56:52 + kInstrSize
danno 2012/10/17 10:04:44 Done.
+ CPU::FlushICache(pc, 2 * kInstrSize);
+ } else {
+ Memory::Address_at(target_address_address_at(pc)) = target;
+ // Intuitively, we would think it is necessary to flush the instruction
+ // cache after patching a target address in the code as follows:
+ // CPU::FlushICache(pc, sizeof(target));
+ // However, on ARM, no instruction was actually patched by the assignment
+ // above; the target address is not part of an instruction, it is patched in
+ // the constant pool and is read via a data access; the instruction
+ // accessing this address in the constant pool remains unchanged.
Please use jfb - chromium.org 2012/10/10 13:56:52 Is this actually true? I can't find a reference to
danno 2012/10/17 10:04:44 Done.
+ }
}
} } // namespace v8::internal

Powered by Google App Engine
This is Rietveld 408576698