Commit d4d2277e authored by lrn@chromium.org's avatar lrn@chromium.org

Fast-compiler: Add stack limit checks to back edges of while, do-while and for.

A few other tweaks.

Review URL: http://codereview.chromium.org/435020


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3355 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 8dbedbb3
......@@ -376,26 +376,26 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
__ mov(r0, Operand(Factory::the_hole_value()));
if (FLAG_debug_code) {
// Check if we have the correct context pointer.
__ ldr(r1, CodeGenerator::ContextOperand(
cp, Context::FCONTEXT_INDEX));
__ ldr(r1, CodeGenerator::ContextOperand(cp,
Context::FCONTEXT_INDEX));
__ cmp(r1, cp);
__ Check(eq, "Unexpected declaration in current context.");
}
__ str(r0, CodeGenerator::ContextOperand(cp, slot->index()));
// No write barrier since the_hole_value is in old space.
ASSERT(Heap::InNewSpace(*Factory::the_hole_value()));
ASSERT(!Heap::InNewSpace(*Factory::the_hole_value()));
} else if (decl->fun() != NULL) {
Visit(decl->fun());
__ pop(r0);
if (FLAG_debug_code) {
// Check if we have the correct context pointer.
__ ldr(r1, CodeGenerator::ContextOperand(
cp, Context::FCONTEXT_INDEX));
__ ldr(r1, CodeGenerator::ContextOperand(cp,
Context::FCONTEXT_INDEX));
__ cmp(r1, cp);
__ Check(eq, "Unexpected declaration in current context.");
}
__ str(r0, CodeGenerator::ContextOperand(cp, slot->index()));
int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
int offset = Context::SlotOffset(slot->index());
__ mov(r2, Operand(offset));
// We know that we have written a function, which is not a smi.
__ RecordWrite(cp, r2, r0);
......
......@@ -155,6 +155,15 @@ void MacroAssembler::Ret(Condition cond) {
}
void MacroAssembler::StackLimitCheck(Label* on_stack_overflow) {
LoadRoot(ip, Heap::kStackLimitRootIndex);
cmp(sp, Operand(ip));
b(lo, on_stack_overflow);
}
void MacroAssembler::SmiJumpTable(Register index, Vector<Label*> targets) {
// Empty the const pool.
CheckConstPool(true, true);
......
......@@ -78,6 +78,11 @@ class MacroAssembler: public Assembler {
// well as the ip register.
void RecordWrite(Register object, Register offset, Register scratch);
// ---------------------------------------------------------------------------
// Stack limit support
void StackLimitCheck(Label* on_stack_limit_hit);
// ---------------------------------------------------------------------------
// Activation frames
......
......@@ -305,12 +305,15 @@ void FastCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
Comment cmnt(masm_, "[ DoWhileStatement");
increment_loop_depth();
Label body, exit;
Label body, exit, stack_limit_hit, stack_check_success;
// Emit the test at the bottom of the loop.
__ bind(&body);
Visit(stmt->body());
// Check stack before looping.
__ StackLimitCheck(&stack_limit_hit);
__ bind(&stack_check_success);
// We are not in an expression context because we have been compiling
// statements. Set up a test expression context for the condition.
ASSERT_EQ(NULL, true_label_);
......@@ -322,6 +325,11 @@ void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
true_label_ = NULL;
false_label_ = NULL;
__ bind(&stack_limit_hit);
StackCheckStub stack_stub;
__ CallStub(&stack_stub);
__ jmp(&stack_check_success);
__ bind(&exit);
decrement_loop_depth();
......@@ -331,7 +339,7 @@ void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
Comment cmnt(masm_, "[ WhileStatement");
increment_loop_depth();
Label test, body, exit;
Label test, body, exit, stack_limit_hit, stack_check_success;
// Emit the test at the bottom of the loop.
__ jmp(&test);
......@@ -340,6 +348,10 @@ void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
Visit(stmt->body());
__ bind(&test);
// Check stack before looping.
__ StackLimitCheck(&stack_limit_hit);
__ bind(&stack_check_success);
// We are not in an expression context because we have been compiling
// statements. Set up a test expression context for the condition.
ASSERT_EQ(NULL, true_label_);
......@@ -351,6 +363,11 @@ void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
true_label_ = NULL;
false_label_ = NULL;
__ bind(&stack_limit_hit);
StackCheckStub stack_stub;
__ CallStub(&stack_stub);
__ jmp(&stack_check_success);
__ bind(&exit);
decrement_loop_depth();
......@@ -359,7 +376,7 @@ void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
void FastCodeGenerator::VisitForStatement(ForStatement* stmt) {
Comment cmnt(masm_, "[ ForStatement");
Label test, body, exit;
Label test, body, exit, stack_limit_hit, stack_check_success;
if (stmt->init() != NULL) Visit(stmt->init());
increment_loop_depth();
......@@ -367,9 +384,15 @@ void FastCodeGenerator::VisitForStatement(ForStatement* stmt) {
__ jmp(&test);
__ bind(&body);
Visit(stmt->body());
// Check stack before looping.
__ StackLimitCheck(&stack_limit_hit);
__ bind(&stack_check_success);
if (stmt->next() != NULL) Visit(stmt->next());
__ bind(&test);
if (stmt->cond() == NULL) {
// For an empty test jump to the top of the loop.
__ jmp(&body);
......@@ -378,6 +401,7 @@ void FastCodeGenerator::VisitForStatement(ForStatement* stmt) {
// statements. Set up a test expression context for the condition.
ASSERT_EQ(NULL, true_label_);
ASSERT_EQ(NULL, false_label_);
true_label_ = &body;
false_label_ = &exit;
ASSERT(stmt->cond()->context() == Expression::kTest);
......@@ -386,6 +410,11 @@ void FastCodeGenerator::VisitForStatement(ForStatement* stmt) {
false_label_ = NULL;
}
__ bind(&stack_limit_hit);
StackCheckStub stack_stub;
__ CallStub(&stack_stub);
__ jmp(&stack_check_success);
__ bind(&exit);
decrement_loop_depth();
}
......
......@@ -880,7 +880,10 @@ class Heap : public AllStatic {
static int linear_allocation_scope_depth_;
static bool context_disposed_pending_;
static const int kMaxMapSpaceSize = 8*MB;
// The number of MapSpace pages is limited by the way we pack
// Map pointers during GC.
static const int kMaxMapSpaceSize =
(1 << MapWord::kMapPageIndexBits) * Page::kPageSize;
#if defined(V8_TARGET_ARCH_X64)
static const int kMaxObjectSizeInNewSpace = 512*KB;
......
......@@ -380,6 +380,7 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
}
__ mov(CodeGenerator::ContextOperand(esi, slot->index()), eax);
// No write barrier since the_hole_value is in old space.
ASSERT(!Heap::InNewSpace(*Factory::the_hole_value()));
} else if (decl->fun() != NULL) {
Visit(decl->fun());
__ pop(eax);
......@@ -391,7 +392,7 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
__ Check(equal, "Unexpected declaration in current context.");
}
__ mov(CodeGenerator::ContextOperand(esi, slot->index()), eax);
int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
int offset = Context::SlotOffset(slot->index());
__ RecordWrite(esi, offset, eax, ecx);
}
break;
......
......@@ -213,6 +213,13 @@ void MacroAssembler::RecordWrite(Register object, int offset,
}
void MacroAssembler::StackLimitCheck(Label* on_stack_overflow) {
cmp(esp,
Operand::StaticVariable(ExternalReference::address_of_stack_limit()));
j(below, on_stack_overflow);
}
#ifdef ENABLE_DEBUGGER_SUPPORT
void MacroAssembler::SaveRegistersToMemory(RegList regs) {
ASSERT((regs & ~kJSCallerSaved) == 0);
......
......@@ -68,6 +68,12 @@ class MacroAssembler: public Assembler {
RegList regs);
#endif
// ---------------------------------------------------------------------------
// Stack limit support
// Do simple test for stack overflow. This doesn't handle an overflow.
void StackLimitCheck(Label* on_stack_limit_hit);
// ---------------------------------------------------------------------------
// Activation frames
......
......@@ -382,26 +382,26 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
__ Move(rax, Factory::the_hole_value());
if (FLAG_debug_code) {
// Check if we have the correct context pointer.
__ movq(rbx, CodeGenerator::ContextOperand(
rsi, Context::FCONTEXT_INDEX));
__ movq(rbx, CodeGenerator::ContextOperand(rsi,
Context::FCONTEXT_INDEX));
__ cmpq(rbx, rsi);
__ Check(equal, "Unexpected declaration in current context.");
}
__ movq(CodeGenerator::ContextOperand(rsi, slot->index()), rax);
// No write barrier since the_hole_value is in old space.
ASSERT(Heap::InNewSpace(*Factory::the_hole_value()));
ASSERT(!Heap::InNewSpace(*Factory::the_hole_value()));
} else if (decl->fun() != NULL) {
Visit(decl->fun());
__ pop(rax);
if (FLAG_debug_code) {
// Check if we have the correct context pointer.
__ movq(rbx, CodeGenerator::ContextOperand(
rsi, Context::FCONTEXT_INDEX));
__ movq(rbx, CodeGenerator::ContextOperand(rsi,
Context::FCONTEXT_INDEX));
__ cmpq(rbx, rsi);
__ Check(equal, "Unexpected declaration in current context.");
}
__ movq(CodeGenerator::ContextOperand(rsi, slot->index()), rax);
int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
int offset = Context::SlotOffset(slot->index());
__ RecordWrite(rsi, offset, rax, rcx);
}
break;
......
......@@ -67,6 +67,12 @@ void MacroAssembler::CompareRoot(Operand with, Heap::RootListIndex index) {
}
void MacroAssembler::StackLimitCheck(Label* on_stack_overflow) {
CompareRoot(rsp, Heap::kStackLimitRootIndex);
j(below, on_stack_overflow);
}
static void RecordWriteHelper(MacroAssembler* masm,
Register object,
Register addr,
......
......@@ -97,6 +97,12 @@ class MacroAssembler: public Assembler {
RegList regs);
#endif
// ---------------------------------------------------------------------------
// Stack limit support
// Do simple test for stack overflow. This doesn't handle an overflow.
void StackLimitCheck(Label* on_stack_limit_hit);
// ---------------------------------------------------------------------------
// Activation frames
......
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