Reviewers: Søren Gjesse,

Description:
ARM: Implement PatchStackCheckCodeAt and RevertStackCheckCode.

This patch also adds platform independent CPU instruction cache flushing.

BUG=none
TEST=none

Please review this at http://codereview.chromium.org/6410029/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/arm/deoptimizer-arm.cc
  M src/deoptimizer.cc


Index: src/arm/deoptimizer-arm.cc
diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc
index e05001f3c38fe228bd7ee7e6ff9b926c39a3af20..44f207a64ce4432ffc2dbdc8eea9d954d76b36da 100644
--- a/src/arm/deoptimizer-arm.cc
+++ b/src/arm/deoptimizer-arm.cc
@@ -124,14 +124,57 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
 void Deoptimizer::PatchStackCheckCodeAt(Address pc_after,
                                         Code* check_code,
                                         Code* replacement_code) {
-  UNIMPLEMENTED();
+  // The call of the stack guard check has the following form:
+  //  e1 5d 00 0c       cmp sp, <limit>
+  //  2a ?? ?? ??       bcs ok
+  //  e5 9f c? ??       ldr ip, [pc, <stack guard address>]
+  //  e1 2f ff 3c       blx ip
+  ASSERT(Memory::uint32_at(pc_after - 4) == 0xe12fff3c);
+  ASSERT(Memory::uint8_at(pc_after - 5) == 0xe5);
+  ASSERT(Memory::uint8_at(pc_after - 6) == 0x9f);
+
+  // We patch the code to the following form:
+  //  e1 5d 00 0c       cmp sp, <limit>
+  //  e1 a0 00 00       mov r0, r0 (NOP)
+  //  e5 9f c? ??       ldr ip, [pc, <on-stack replacement address>]
+  //  e1 2f ff 3c       blx ip
+  // and overwrite the constant containing the
+  // address of the stack check stub.
+
+  // Replace conditional jump with NOP.
+  Memory::uint32_at(pc_after - 12) = 0xe1a00000;
+
+  // Replace the stack check address in the constant pool
+  // with the entry address of the replacement code.
+  uint32_t stack_check_address_offset = Memory::uint16_at(pc_after - 8) &
+      0xfff;
+ Address stack_check_address_pointer = pc_after + stack_check_address_offset;
+  ASSERT(Memory::uint32_at(stack_check_address_pointer) ==
+         reinterpret_cast<uint32_t>(check_code->entry()));
+  Memory::uint32_at(stack_check_address_pointer) =
+      reinterpret_cast<uint32_t>(replacement_code->entry());
 }


 void Deoptimizer::RevertStackCheckCodeAt(Address pc_after,
                                          Code* check_code,
                                          Code* replacement_code) {
-  UNIMPLEMENTED();
+  ASSERT(Memory::uint32_at(pc_after - 4) == 0xe12fff3c);
+  ASSERT(Memory::uint8_at(pc_after - 5) == 0xe5);
+  ASSERT(Memory::uint8_at(pc_after - 6) == 0x9f);
+
+  // Replace NOP with conditional jump.
+  Memory::uint32_at(pc_after - 12) = 0x2a000001;
+
+  // Replace the stack check address in the constant pool
+  // with the entry address of the replacement code.
+  uint32_t stack_check_address_offset = Memory::uint16_at(pc_after - 8) &
+      0xfff;
+ Address stack_check_address_pointer = pc_after + stack_check_address_offset;
+  ASSERT(Memory::uint32_at(stack_check_address_pointer) ==
+         reinterpret_cast<uint32_t>(replacement_code->entry()));
+  Memory::uint32_at(stack_check_address_pointer) =
+      reinterpret_cast<uint32_t>(check_code->entry());
 }


Index: src/deoptimizer.cc
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index 00e7d0ee2cab70655ebdf3613f34cc93de44d049..7f0781cd550e1f151905a02b005508963d1ed04f 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -820,11 +820,22 @@ void Deoptimizer::PatchStackCheckCode(Code* unoptimized_code,
       unoptimized_code->stack_check_table_offset();
   uint32_t table_length = Memory::uint32_at(stack_check_cursor);
   stack_check_cursor += kIntSize;
+  Address first_site = 0;
+  Address last_site = 0;
   for (uint32_t i = 0; i < table_length; ++i) {
     uint32_t pc_offset = Memory::uint32_at(stack_check_cursor + kIntSize);
     Address pc_after = unoptimized_code->instruction_start() + pc_offset;
     PatchStackCheckCodeAt(pc_after, check_code, replacement_code);
     stack_check_cursor += 2 * kIntSize;
+    if (first_site == 0) {
+      first_site = pc_after;
+    }
+    last_site = pc_after;
+  }
+  if (table_length > 0) {
+    // Flush instruction cache for the patched code blocks.
+    uint32_t length = last_site - first_site + patch_size();
+    CPU::FlushICache(first_site - patch_size(), length);
   }
 }

@@ -839,11 +850,22 @@ void Deoptimizer::RevertStackCheckCode(Code* unoptimized_code,
       unoptimized_code->stack_check_table_offset();
   uint32_t table_length = Memory::uint32_at(stack_check_cursor);
   stack_check_cursor += kIntSize;
+  Address first_site = 0;
+  Address last_site = 0;
   for (uint32_t i = 0; i < table_length; ++i) {
     uint32_t pc_offset = Memory::uint32_at(stack_check_cursor + kIntSize);
     Address pc_after = unoptimized_code->instruction_start() + pc_offset;
     RevertStackCheckCodeAt(pc_after, check_code, replacement_code);
     stack_check_cursor += 2 * kIntSize;
+    if (first_site == 0) {
+      first_site = pc_after;
+    }
+    last_site = pc_after;
+  }
+  if (table_length > 0) {
+    // Flush instruction cache for the patched code blocks.
+    uint32_t length = last_site - first_site + patch_size();
+    CPU::FlushICache(first_site - patch_size(), length);
   }
 }



--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to