From: lrn@chromium.org Date: Wed, 25 Nov 2009 09:05:30 +0000 (+0000) Subject: Fast-compiler: Add stack limit checks to back edges of while, do-while and for. X-Git-Tag: upstream/4.7.83~22900 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d4d2277e2eca51d0f911c321b18705de8eb59cdf;p=platform%2Fupstream%2Fv8.git 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 --- diff --git a/src/arm/fast-codegen-arm.cc b/src/arm/fast-codegen-arm.cc index 6d0510e..8147466 100644 --- a/src/arm/fast-codegen-arm.cc +++ b/src/arm/fast-codegen-arm.cc @@ -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); diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index a668cb1..57ee26c 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -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 targets) { // Empty the const pool. CheckConstPool(true, true); diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h index 8c247bf..36cb4de 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h @@ -79,6 +79,11 @@ class MacroAssembler: public Assembler { void RecordWrite(Register object, Register offset, Register scratch); // --------------------------------------------------------------------------- + // Stack limit support + + void StackLimitCheck(Label* on_stack_limit_hit); + + // --------------------------------------------------------------------------- // Activation frames void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); } diff --git a/src/fast-codegen.cc b/src/fast-codegen.cc index 53fcf31..20de808 100644 --- a/src/fast-codegen.cc +++ b/src/fast-codegen.cc @@ -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(); } diff --git a/src/heap.h b/src/heap.h index 95e16ae..80cc885 100644 --- a/src/heap.h +++ b/src/heap.h @@ -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; diff --git a/src/ia32/fast-codegen-ia32.cc b/src/ia32/fast-codegen-ia32.cc index a01d754..deb5099 100644 --- a/src/ia32/fast-codegen-ia32.cc +++ b/src/ia32/fast-codegen-ia32.cc @@ -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; diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index 010433e..8ed7f55 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -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); diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h index 248aa77..e283e93 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h @@ -69,6 +69,12 @@ class MacroAssembler: public Assembler { #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 void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); } diff --git a/src/x64/fast-codegen-x64.cc b/src/x64/fast-codegen-x64.cc index bb85ef5..968d93b 100644 --- a/src/x64/fast-codegen-x64.cc +++ b/src/x64/fast-codegen-x64.cc @@ -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; diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 9dea616..79733ff 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -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, diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h index 11cdfc3..e0af1ed 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h @@ -98,6 +98,12 @@ class MacroAssembler: public Assembler { #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 void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }