Chromium Code Reviews| 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; |
| } |