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.
}
}
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);
}
}
-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);
}
// 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.
#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).");
(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_ =
// 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;
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);
}
#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);
// 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;
}
set_limits(kIllegalLimit, lock);
} else {
thread_local_.jslimit_ = thread_local_.initial_jslimit_;
+ Heap::SetStackLimit(thread_local_.jslimit_);
thread_local_.climit_ = thread_local_.initial_climit_;
}
}
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_;
}
+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();
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) \
// 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();
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.