summaryrefslogtreecommitdiffstats
path: root/src/x64/ic-x64.cc
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-06-13 19:13:29 +0100
committerSteve Block <steveblock@google.com>2011-06-13 19:47:33 +0100
commit053d10c438f14580aaf4ab1b2aad93a5a4fe8b82 (patch)
tree252c105b821e8370a0cc06c168f909e9817a3ebb /src/x64/ic-x64.cc
parent442c3c4c26c4d864ad9a4948f856e706e77c3cd2 (diff)
downloadandroid_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.cc134
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