From a29d4e676264c10c32cbdd8a8c1aa925efe9afa0 Mon Sep 17 00:00:00 2001 From: "erik.corry@gmail.com" Date: Wed, 26 Aug 2009 10:27:32 +0000 Subject: [PATCH] * Make stack/preemption guard faster on ARM by putting stack 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 | 10 +++------- src/arm/macro-assembler-arm.cc | 4 ++-- src/arm/macro-assembler-arm.h | 2 +- src/arm/virtual-frame-arm.cc | 3 ++- src/execution.cc | 7 +++++-- src/execution.h | 22 +++++++++++++++------- src/heap.cc | 7 +++++++ src/heap.h | 8 +++++++- src/v8.cc | 4 ++++ 9 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index 12d828d7e..f98458b9b 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -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); } diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index 4e337c4bb..65c2a3ebd 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -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); } diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h index a35c98a20..e4758cc39 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h @@ -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. diff --git a/src/arm/virtual-frame-arm.cc b/src/arm/virtual-frame-arm.cc index 91952f375..97958606e 100644 --- a/src/arm/virtual-frame-arm.cc +++ b/src/arm/virtual-frame-arm.cc @@ -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)."); diff --git a/src/execution.cc b/src/execution.cc index 7c42e5e74..18c5bb81c 100644 --- a/src/execution.cc +++ b/src/execution.cc @@ -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(&thread_local_), from, sizeof(ThreadLocal)); + Heap::SetStackLimit(thread_local_.jslimit_); return from + sizeof(ThreadLocal); } diff --git a/src/execution.h b/src/execution.h index 456cbe74d..4cdfd2be6 100644 --- a/src/execution.h +++ b/src/execution.h @@ -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_; diff --git a/src/heap.cc b/src/heap.cc index 7e73eae69..4e3529b69 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -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(); diff --git a/src/heap.h b/src/heap.h index be15fca7f..212dfa7a7 100644 --- a/src/heap.h +++ b/src/heap.h @@ -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(); diff --git a/src/v8.cc b/src/v8.cc index bbcc9d1f1..a20415875 100644 --- 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. -- 2.34.1