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
This commit is contained in:
parent
8dbedbb30e
commit
d4d2277e2e
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user