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