Index: src/ia32/ic-ia32.cc |
=================================================================== |
--- src/ia32/ic-ia32.cc (revision 5101) |
+++ src/ia32/ic-ia32.cc (working copy) |
@@ -1644,37 +1644,6 @@ |
// One byte opcode for test eax,0xXXXXXXXX. |
static const byte kTestEaxByte = 0xA9; |
- |
-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(), kMaxInt); |
-} |
- |
- |
-void KeyedLoadIC::ClearInlinedVersion(Address address) { |
- // Insert null as the map to check for to make sure the map check fails |
- // sending control flow to the IC instead of the inlined version. |
- PatchInlinedLoad(address, Heap::null_value()); |
-} |
- |
- |
-void KeyedStoreIC::ClearInlinedVersion(Address address) { |
- // Insert null as the elements map to check for. This will make |
- // sure that the elements fast-case map check fails so that control |
- // flows to the IC instead of the inlined version. |
- PatchInlinedStore(address, Heap::null_value()); |
-} |
- |
- |
-void KeyedStoreIC::RestoreInlinedVersion(Address address) { |
- // Restore the fast-case elements map check so that the inlined |
- // version can be used again. |
- PatchInlinedStore(address, Heap::fixed_array_map()); |
-} |
- |
- |
bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { |
// The address of the instruction following the call. |
Address test_instruction_address = |
@@ -1703,6 +1672,52 @@ |
} |
+bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { |
+ // The address of the instruction following the call. |
+ Address test_instruction_address = |
+ address + Assembler::kCallTargetAddressOffset; |
+ |
+ // If the instruction following the call is not a test eax, nothing |
+ // was inlined. |
+ if (*test_instruction_address != kTestEaxByte) return false; |
+ |
+ // Extract the encoded deltas from the test eax instruction. |
+ Address encoded_offsets_address = test_instruction_address + 1; |
+ int encoded_offsets = *reinterpret_cast<int*>(encoded_offsets_address); |
+ int delta_to_map_check = -(encoded_offsets & 0xFFFF); |
+ int delta_to_record_write = encoded_offsets >> 16; |
+ |
+ // Patch the map to check. The map address is the last 4 bytes of |
+ // the 7-byte operand-immediate compare instruction. |
+ Address map_check_address = test_instruction_address + delta_to_map_check; |
+ Address map_address = map_check_address + 3; |
+ *(reinterpret_cast<Object**>(map_address)) = map; |
+ |
+ // Patch the offset in the store instruction. The offset is in the |
+ // last 4 bytes of a six byte register-to-memory move instruction. |
+ Address offset_address = |
+ map_check_address + StoreIC::kOffsetToStoreInstruction + 2; |
+ // The offset should have initial value (kMaxInt - 1), cleared value |
+ // (-1) or we should be clearing the inlined version. |
+ ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt - 1 || |
+ *reinterpret_cast<int*>(offset_address) == -1 || |
+ (offset == 0 && map == Heap::null_value())); |
+ *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; |
+ |
+ // Patch the offset in the write-barrier code. The offset is the |
+ // last 4 bytes of a six byte lea instruction. |
+ offset_address = map_check_address + delta_to_record_write + 2; |
+ // The offset should have initial value (kMaxInt), cleared value |
+ // (-1) or we should be clearing the inlined version. |
+ ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || |
+ *reinterpret_cast<int*>(offset_address) == -1 || |
+ (offset == 0 && map == Heap::null_value())); |
+ *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; |
+ |
+ return true; |
+} |
+ |
+ |
static bool PatchInlinedMapCheck(Address address, Object* map) { |
Address test_instruction_address = |
address + Assembler::kCallTargetAddressOffset; |
@@ -1814,6 +1829,12 @@ |
} |
+// The offset from the inlined patch site to the start of the inlined |
+// store instruction. It is 7 bytes (test reg, imm) plus 6 bytes (jne |
+// slow_label). |
+const int StoreIC::kOffsetToStoreInstruction = 13; |
+ |
+ |
void StoreIC::GenerateArrayLength(MacroAssembler* masm) { |
// ----------- S t a t e ------------- |
// -- eax : value |