Commit a29d4e67 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

* 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
parent e7cc9fbc
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -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.
......
......@@ -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).");
......
......@@ -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);
}
......
......@@ -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_;
......
......@@ -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();
......
......@@ -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();
......
......@@ -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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment