Index: src/arm/ic-arm.cc |
=================================================================== |
--- src/arm/ic-arm.cc (revision 4459) |
+++ src/arm/ic-arm.cc (working copy) |
@@ -27,7 +27,9 @@ |
#include "v8.h" |
+#include "assembler-arm.h" |
#include "codegen-inl.h" |
+#include "disasm.h" |
#include "ic-inl.h" |
#include "runtime.h" |
#include "stub-cache.h" |
@@ -561,21 +563,64 @@ |
} |
-// TODO(181): Implement map patching once loop nesting is tracked on the |
-// ARM platform so we can generate inlined fast-case code loads in |
-// loops. |
-void LoadIC::ClearInlinedVersion(Address address) {} |
+void LoadIC::ClearInlinedVersion(Address address) { |
+ // Reset the map check of the inlined inobject property load (if present) to |
+ // guarantee failure by holding an invalid map (the null value). The offset |
+ // can be patched to anything. |
+ PatchInlinedLoad(address, Heap::null_value(), 0); |
+} |
+ |
+ |
bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { |
- return false; |
+ // If the instruction after the call site is not a B instruction then this is |
+ // not related to an inlined in-object property load. The B instructions is |
+ // located just after the call to the IC in the deferred code handling the |
+ // miss in the inlined code. All other calls to a load IC should ensure there |
+ // in no B instruction directly following the call. |
+ Address address_after_call = address + Assembler::kCallTargetAddressOffset; |
+ Instr instr_after_call = Assembler::instr_at(address_after_call); |
+ if (!Assembler::IsB(instr_after_call)) return false; |
+ |
+ // Find the end of the inlined code for handling the load. |
+ int b_offset = |
+ Assembler::GetBOffset(instr_after_call) + Assembler::kPcLoadDelta; |
+ ASSERT(b_offset < 0); // Jumping back from deferred code. |
+ Address inline_end_address = address_after_call + b_offset; |
+ |
+ // Patch the offset of the property load instruction (ldr r0, [r1, #+XXX]). |
+ Address ldr_property_instr_address = inline_end_address - 4; |
+ ASSERT(Assembler::IsLdrRegisterImmediate( |
+ Assembler::instr_at(ldr_property_instr_address))); |
+ Instr ldr_property_instr = Assembler::instr_at(ldr_property_instr_address); |
+ ldr_property_instr = Assembler::SetLdrRegisterImmediateOffset( |
+ ldr_property_instr, offset - kHeapObjectTag); |
Erik Corry
2010/04/22 20:10:41
What if the offset doesn't fit in the immediate fi
|
+ Assembler::instr_at_put(ldr_property_instr_address, ldr_property_instr); |
+ |
+ // Indicate that code has changed. |
+ CPU::FlushICache(ldr_property_instr_address, 1 * Assembler::kInstrSize); |
+ |
+ // Patch the map check. |
+ Address ldr_map_instr_address = inline_end_address - 16; |
+ Assembler::set_target_address_at(ldr_map_instr_address, |
+ reinterpret_cast<Address>(map)); |
+ return true; |
} |
+ |
void KeyedLoadIC::ClearInlinedVersion(Address address) {} |
+ |
+ |
bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { |
return false; |
} |
+ |
void KeyedStoreIC::ClearInlinedVersion(Address address) {} |
+ |
+ |
void KeyedStoreIC::RestoreInlinedVersion(Address address) {} |
+ |
+ |
bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { |
return false; |
} |