Fast-compiler: Add stack limit checks to back edges of while, do-while and for.
authorlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 25 Nov 2009 09:05:30 +0000 (09:05 +0000)
committerlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 25 Nov 2009 09:05:30 +0000 (09:05 +0000)
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

src/arm/fast-codegen-arm.cc
src/arm/macro-assembler-arm.cc
src/arm/macro-assembler-arm.h
src/fast-codegen.cc
src/heap.h
src/ia32/fast-codegen-ia32.cc
src/ia32/macro-assembler-ia32.cc
src/ia32/macro-assembler-ia32.h
src/x64/fast-codegen-x64.cc
src/x64/macro-assembler-x64.cc
src/x64/macro-assembler-x64.h

index 6d0510e..8147466 100644 (file)
@@ -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);
index a668cb1..57ee26c 100644 (file)
@@ -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);
index 8c247bf..36cb4de 100644 (file)
@@ -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); }
index 53fcf31..20de808 100644 (file)
@@ -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();
 }
index 95e16ae..80cc885 100644 (file)
@@ -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;
index a01d754..deb5099 100644 (file)
@@ -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;
index 010433e..8ed7f55 100644 (file)
@@ -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);
index 248aa77..e283e93 100644 (file)
@@ -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); }
index bb85ef5..968d93b 100644 (file)
@@ -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;
index 9dea616..79733ff 100644 (file)
@@ -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,
index 11cdfc3..e0af1ed 100644 (file)
@@ -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); }