* Make stack/preemption guard faster on ARM by putting stack
authorerik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 26 Aug 2009 10:27:32 +0000 (10:27 +0000)
committererik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 26 Aug 2009 10:27:32 +0000 (10:27 +0000)
limit in the roots array.
Review URL: http://codereview.chromium.org/174517

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2760 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/codegen-arm.cc
src/arm/macro-assembler-arm.cc
src/arm/macro-assembler-arm.h
src/arm/virtual-frame-arm.cc
src/execution.cc
src/execution.h
src/heap.cc
src/heap.h
src/v8.cc

index 12d828d7ee21dd50ca057262675681a2865c73f1..f98458b9b43f2799e70ccb54f11047f81a9da482 100644 (file)
@@ -1110,8 +1110,10 @@ void CodeGenerator::CheckStack() {
   VirtualFrame::SpilledScope spilled_scope;
   if (FLAG_check_stack) {
     Comment cmnt(masm_, "[ check stack");
+    __ LoadRoot(ip, Heap::kStackLimitRootIndex);
+    __ cmp(sp, Operand(ip));
     StackCheckStub stub;
-    frame_->CallStub(&stub, 0);
+    __ CallStub(&stub, lo);  // Call the stub if lower.
   }
 }
 
@@ -5623,17 +5625,11 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
 
 
 void StackCheckStub::Generate(MacroAssembler* masm) {
-  Label within_limit;
-  __ mov(ip, Operand(ExternalReference::address_of_stack_guard_limit()));
-  __ ldr(ip, MemOperand(ip));
-  __ cmp(sp, Operand(ip));
-  __ b(hs, &within_limit);
   // Do tail-call to runtime routine.  Runtime routines expect at least one
   // argument, so give it a Smi.
   __ mov(r0, Operand(Smi::FromInt(0)));
   __ push(r0);
   __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1);
-  __ bind(&within_limit);
 
   __ StubReturn(1);
 }
index 4e337c4bb6ebbeb645d8f978c7b47f8866046168..65c2a3ebd90283639e57739d82266405dd446a3d 100644 (file)
@@ -825,9 +825,9 @@ void MacroAssembler::TryGetFunctionPrototype(Register function,
 }
 
 
-void MacroAssembler::CallStub(CodeStub* stub) {
+void MacroAssembler::CallStub(CodeStub* stub, Condition cond) {
   ASSERT(allow_stub_calls());  // stub calls are not allowed in some stubs
-  Call(stub->GetCode(), RelocInfo::CODE_TARGET);
+  Call(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
 }
 
 
index a35c98a205e162fbc4549ac5ce01ad7ea6336dce..e4758cc39cfa04969d7151943de2e0601fc6b979 100644 (file)
@@ -231,7 +231,7 @@ class MacroAssembler: public Assembler {
   // Runtime calls
 
   // Call a code stub.
-  void CallStub(CodeStub* stub);
+  void CallStub(CodeStub* stub, Condition cond = al);
   void CallJSExitStub(CodeStub* stub);
 
   // Return from a code stub after popping its arguments.
index 91952f375b324b62cf96d7d1e29615fcfc69cfee..97958606e7b79d1bb246f866c2128cc82880c85f 100644 (file)
@@ -102,7 +102,8 @@ void VirtualFrame::Enter() {
 #ifdef DEBUG
   // Verify that r1 contains a JS function.  The following code relies
   // on r2 being available for use.
-  { Label map_check, done;
+  if (FLAG_debug_code) {
+    Label map_check, done;
     __ tst(r1, Operand(kSmiTagMask));
     __ b(ne, &map_check);
     __ stop("VirtualFrame::Enter - r1 is not a function (smi check).");
index 7c42e5e74bf69f4d032fd981210463448c3445e4..18c5bb81c4c907a92a949117d638c46597c31d1a 100644 (file)
@@ -234,8 +234,9 @@ StackGuard::StackGuard() {
            (thread_local_.climit_ == kInterruptLimit &&
             thread_local_.interrupt_flags_ != 0));
 
-    thread_local_.initial_jslimit_ = thread_local_.jslimit_ =
-        GENERATED_CODE_STACK_LIMIT(kLimitSize);
+    uintptr_t limit = GENERATED_CODE_STACK_LIMIT(kLimitSize);
+    thread_local_.initial_jslimit_ = thread_local_.jslimit_ = limit;
+    Heap::SetStackLimit(limit);
     // NOTE: The check for overflow is not safe as there is no guarantee that
     // the running thread has its stack in all memory up to address 0x00000000.
     thread_local_.initial_climit_ = thread_local_.climit_ =
@@ -283,6 +284,7 @@ void StackGuard::SetStackLimit(uintptr_t limit) {
   // leave them alone.
   if (thread_local_.jslimit_ == thread_local_.initial_jslimit_) {
     thread_local_.jslimit_ = limit;
+    Heap::SetStackLimit(limit);
   }
   if (thread_local_.climit_ == thread_local_.initial_climit_) {
     thread_local_.climit_ = limit;
@@ -397,6 +399,7 @@ char* StackGuard::ArchiveStackGuard(char* to) {
 char* StackGuard::RestoreStackGuard(char* from) {
   ExecutionAccess access;
   memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
+  Heap::SetStackLimit(thread_local_.jslimit_);
   return from + sizeof(ThreadLocal);
 }
 
index 456cbe74d6786a0a74d92f0edae2d4bab17e2d87..4cdfd2be6a1391ff2c6ecd8de32804bf516b91b1 100644 (file)
@@ -175,6 +175,10 @@ class StackGuard BASE_EMBEDDED {
 #endif
   static void Continue(InterruptFlag after_what);
 
+  static uintptr_t jslimit() {
+    return thread_local_.jslimit_;
+  }
+
  private:
   // You should hold the ExecutionAccess lock when calling this method.
   static bool IsSet(const ExecutionAccess& lock);
@@ -188,6 +192,7 @@ class StackGuard BASE_EMBEDDED {
 
   // You should hold the ExecutionAccess lock when calling this method.
   static void set_limits(uintptr_t value, const ExecutionAccess& lock) {
+    Heap::SetStackLimit(value);
     thread_local_.jslimit_ = value;
     thread_local_.climit_ = value;
   }
@@ -200,6 +205,7 @@ class StackGuard BASE_EMBEDDED {
       set_limits(kIllegalLimit, lock);
     } else {
       thread_local_.jslimit_ = thread_local_.initial_jslimit_;
+      Heap::SetStackLimit(thread_local_.jslimit_);
       thread_local_.climit_ = thread_local_.initial_climit_;
     }
   }
@@ -220,13 +226,15 @@ class StackGuard BASE_EMBEDDED {
   class ThreadLocal {
    public:
     ThreadLocal()
-     : initial_jslimit_(kIllegalLimit),
-       jslimit_(kIllegalLimit),
-       initial_climit_(kIllegalLimit),
-       climit_(kIllegalLimit),
-       nesting_(0),
-       postpone_interrupts_nesting_(0),
-       interrupt_flags_(0) {}
+      : initial_jslimit_(kIllegalLimit),
+        jslimit_(kIllegalLimit),
+        initial_climit_(kIllegalLimit),
+        climit_(kIllegalLimit),
+        nesting_(0),
+        postpone_interrupts_nesting_(0),
+        interrupt_flags_(0) {
+      Heap::SetStackLimit(kIllegalLimit);
+    }
     uintptr_t initial_jslimit_;
     uintptr_t jslimit_;
     uintptr_t initial_climit_;
index 7e73eae69831aaf8a8c3edc418997b5119d3f3a3..4e3529b6924638e9b1080db9ccb4e1ccea186b36 100644 (file)
@@ -3256,6 +3256,13 @@ bool Heap::Setup(bool create_heap_objects) {
 }
 
 
+void Heap::SetStackLimit(intptr_t limit) {
+  // Set up the special root array entry containing the stack guard.
+  // This is actually an address, but the tag makes the GC ignore it.
+  set_stack_limit(Smi::FromInt(limit >> kSmiTagSize));
+}
+
+
 void Heap::TearDown() {
   GlobalHandles::TearDown();
 
index be15fca7f1741e8df8c9765ae7f5f92c95f46d9b..212dfa7a7c2d52dd7c25dea253f639fa21740f00 100644 (file)
@@ -132,7 +132,8 @@ namespace internal {
   V(FixedArray, number_string_cache, NumberStringCache)                        \
   V(FixedArray, single_character_string_cache, SingleCharacterStringCache)     \
   V(FixedArray, natives_source_cache, NativesSourceCache)                      \
-  V(Object, last_script_id, LastScriptId)
+  V(Object, last_script_id, LastScriptId)                                      \
+  V(Smi, stack_limit, StackLimit)
 
 
 #define ROOT_LIST(V)                                  \
@@ -227,6 +228,11 @@ class Heap : public AllStatic {
   // Destroys all memory allocated by the heap.
   static void TearDown();
 
+  // Sets the stack limit in the roots_ array.  Some architectures generate code
+  // that looks here, because it is faster than loading from the static jslimit_
+  // variable.
+  static void SetStackLimit(intptr_t limit);
+
   // Returns whether Setup has been called.
   static bool HasBeenSetup();
 
index bbcc9d1f1d9005d8b6a9099a689456d19201a709..a20415875efc555b099f88130a6066e41f0206b6 100644 (file)
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -98,6 +98,10 @@ bool V8::Initialize(Deserializer *des) {
     StubCache::Clear();
   }
 
+  // Deserializing may put strange things in the root array's copy of the
+  // stack guard.
+  Heap::SetStackLimit(StackGuard::jslimit());
+
   // Setup the CPU support. Must be done after heap setup and after
   // any deserialization because we have to have the initial heap
   // objects in place for creating the code object used for probing.