diff options
author | Steve Block <steveblock@google.com> | 2011-06-13 19:13:29 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-06-13 19:47:33 +0100 |
commit | 053d10c438f14580aaf4ab1b2aad93a5a4fe8b82 (patch) | |
tree | 252c105b821e8370a0cc06c168f909e9817a3ebb /src/x64/ic-x64.cc | |
parent | 442c3c4c26c4d864ad9a4948f856e706e77c3cd2 (diff) | |
download | android_external_v8-053d10c438f14580aaf4ab1b2aad93a5a4fe8b82.tar.gz android_external_v8-053d10c438f14580aaf4ab1b2aad93a5a4fe8b82.tar.bz2 android_external_v8-053d10c438f14580aaf4ab1b2aad93a5a4fe8b82.zip |
Merge V8 at branches/3.2 r8200: Initial merge by Git
Change-Id: I5c434306e98132997e9c5f6024b6ce200b255edf
Diffstat (limited to 'src/x64/ic-x64.cc')
-rw-r--r-- | src/x64/ic-x64.cc | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc index 5ed89b5d..5ca56ac7 100644 --- a/src/x64/ic-x64.cc +++ b/src/x64/ic-x64.cc @@ -381,6 +381,11 @@ static void GenerateNumberDictionaryLoad(MacroAssembler* masm, } +// The offset from the inlined patch site to the start of the inlined +// load instruction. +const int LoadIC::kOffsetToLoadInstruction = 20; + + void LoadIC::GenerateArrayLength(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- rax : receiver @@ -1292,6 +1297,130 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) { } +bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { + if (V8::UseCrankshaft()) return false; + + // 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 rax, nothing + // was inlined. + if (*test_instruction_address != Assembler::kTestEaxByte) return false; + + Address delta_address = test_instruction_address + 1; + // The delta to the start of the map check instruction. + int delta = *reinterpret_cast<int*>(delta_address); + + // The map address is the last 8 bytes of the 10-byte + // immediate move instruction, so we add 2 to get the + // offset to the last 8 bytes. + Address map_address = test_instruction_address + delta + 2; + *(reinterpret_cast<Object**>(map_address)) = map; + + // The offset is in the 32-bit displacement of a seven byte + // memory-to-register move instruction (REX.W 0x88 ModR/M disp32), + // so we add 3 to get the offset of the displacement. + Address offset_address = + test_instruction_address + delta + kOffsetToLoadInstruction + 3; + *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; + return true; +} + + +bool LoadIC::PatchInlinedContextualLoad(Address address, + Object* map, + Object* cell, + bool is_dont_delete) { + // TODO(<bug#>): implement this. + return false; +} + + +bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { + if (V8::UseCrankshaft()) return false; + + // 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 rax, nothing + // was inlined. + if (*test_instruction_address != Assembler::kTestEaxByte) return false; + + // Extract the encoded deltas from the test rax 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 8 bytes of + // the 10-byte immediate move instruction. + Address map_check_address = test_instruction_address + delta_to_map_check; + Address map_address = map_check_address + 2; + *(reinterpret_cast<Object**>(map_address)) = map; + + // Patch the offset in the store instruction. The offset is in the + // last 4 bytes of a 7 byte register-to-memory move instruction. + Address offset_address = + map_check_address + StoreIC::kOffsetToStoreInstruction + 3; + // 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 7 byte lea instruction. + offset_address = map_check_address + delta_to_record_write + 3; + // 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) { + if (V8::UseCrankshaft()) return false; + + // Arguments are address of start of call sequence that called + // the IC, + Address test_instruction_address = + address + Assembler::kCallTargetAddressOffset; + // The keyed load has a fast inlined case if the IC call instruction + // is immediately followed by a test instruction. + if (*test_instruction_address != Assembler::kTestEaxByte) return false; + + // Fetch the offset from the test instruction to the map compare + // instructions (starting with the 64-bit immediate mov of the map + // address). 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 8 bytes + // of the 10-byte immediate mov instruction (incl. REX prefix), so we add 2 + // to the offset to get the map address. + Address map_address = test_instruction_address + delta + 2; + // Patch the map check. + *(reinterpret_cast<Object**>(map_address)) = map; + return true; +} + + +bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { + return PatchInlinedMapCheck(address, map); +} + + +bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { + return PatchInlinedMapCheck(address, map); +} + + void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- rax : key @@ -1374,6 +1503,11 @@ void StoreIC::GenerateMiss(MacroAssembler* masm) { } +// The offset from the inlined patch site to the start of the inlined +// store instruction. +const int StoreIC::kOffsetToStoreInstruction = 20; + + void StoreIC::GenerateArrayLength(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- rax : value |