Chromium Code Reviews| Index: src/ia32/ic-ia32.cc |
| =================================================================== |
| --- src/ia32/ic-ia32.cc (revision 1804) |
| +++ src/ia32/ic-ia32.cc (working copy) |
| @@ -729,36 +729,66 @@ |
| static const byte kTestEaxByte = 0xA9; |
| -bool KeyedLoadIC::HasInlinedVersion(Address address) { |
| - Address test_instruction_address = address + 4; // 4 = stub address |
| - return *test_instruction_address == kTestEaxByte; |
| +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. |
| - PatchInlinedMapCheck(address, Heap::null_value()); |
| + PatchInlinedLoad(address, Heap::null_value()); |
| } |
| -void KeyedLoadIC::PatchInlinedMapCheck(Address address, Object* value) { |
| +bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { |
| + // The address of the instruction following the call. |
| + Address test_instruction_address = address + 4; |
| + // If the instruction following the call is not a test eax, nothing |
| + // was inlined. |
| + if (*test_instruction_address != kTestEaxByte) return false; |
| + |
| + Address delta_address = test_instruction_address + 1; |
| + // The delta to the start of the map chack instruction. |
|
Mads Ager (chromium)
2009/04/28 09:53:54
chack -> check.
|
| + int delta = *reinterpret_cast<int*>(delta_address); |
| + |
| + // The map address is the last 4 bytes of the 7-byte |
| + // operand-immediate compare instruction, so we add 3 to get the |
| + // offset to the last 4 bytes. |
| + Address map_address = test_instruction_address + delta + 3; |
| + *(reinterpret_cast<Object**>(map_address)) = map; |
| + |
| + // The offset is in the last 4 bytes of a six byte |
| + // memory-to-register move instruction, so we add 2 to get the |
| + // offset to the last 4 bytes. |
| + Address offset_address = |
| + test_instruction_address + delta + kOffsetToLoadInstruction + 2; |
| + *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; |
| + return true; |
| +} |
| + |
| + |
| +bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { |
| Address test_instruction_address = address + 4; // 4 = stub address |
| // The keyed load has a fast inlined case if the IC call instruction |
| // is immediately followed by a test instruction. |
| - if (*test_instruction_address == kTestEaxByte) { |
| - // Fetch the offset from the test instruction to the map cmp |
| - // instruction. This offset is stored in the last 4 bytes of the |
| - // 5 byte test instruction. |
| - Address offset_address = test_instruction_address + 1; |
| - int offset_value = *(reinterpret_cast<int*>(offset_address)); |
| - // Compute the map address. The map address is in the last 4 |
| - // bytes of the 7-byte operand-immediate compare instruction, so |
| - // we add 3 to the offset to get the map address. |
| - Address map_address = test_instruction_address + offset_value + 3; |
| - // Patch the map check. |
| - (*(reinterpret_cast<Object**>(map_address))) = value; |
| - } |
| + if (*test_instruction_address != kTestEaxByte) return false; |
| + |
| + // Fetch the offset from the test instruction to the map cmp |
| + // instruction. This offset is stored in the last 4 bytes of the 5 |
| + // byte test instruction. |
| + Address delta_address = test_instruction_address + 1; |
| + int delta = *reinterpret_cast<int*>(delta_address); |
| + // Compute the map address. The map address is in the last 4 bytes |
| + // of the 7-byte operand-immediate compare instruction, so we add 3 |
| + // to the offset to get the map address. |
| + Address map_address = test_instruction_address + delta + 3; |
| + // Patch the map check. |
| + *(reinterpret_cast<Object**>(map_address)) = map; |
| + return true; |
| } |