Fix issue 268 by explicitly calling Unuse (to deallocate all contained
authorkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 11 Mar 2009 10:25:48 +0000 (10:25 +0000)
committerkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 11 Mar 2009 10:25:48 +0000 (10:25 +0000)
virtual frames) on zone-allocated jump targets.  These include jump
targets in AST nodes and the entry and exit targets of deferred code.

See http://code.google.com/p/v8/issues/detail?id=268

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1486 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/codegen-arm.cc
src/codegen-arm.h
src/codegen-ia32.cc
src/codegen-ia32.h
src/codegen.cc
src/codegen.h

index 9902894..8d9052a 100644 (file)
@@ -284,7 +284,11 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
   DeleteFrame();
 
   // Process any deferred code using the register allocator.
-  ProcessDeferred();
+  if (HasStackOverflow()) {
+    ClearDeferred();
+  } else {
+    ProcessDeferred();
+  }
 
   allocator_ = NULL;
   scope_ = NULL;
@@ -1133,6 +1137,7 @@ void CodeGenerator::VisitBlock(Block* node) {
   if (node->break_target()->is_linked()) {
     node->break_target()->Bind();
   }
+  node->break_target()->Unuse();
   ASSERT(!has_valid_frame() || frame_->height() == original_height);
 }
 
@@ -1594,6 +1599,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
   if (node->break_target()->is_linked()) {
     node->break_target()->Bind();
   }
+  node->break_target()->Unuse();
   ASSERT(!has_valid_frame() || frame_->height() == original_height);
 }
 
@@ -1781,6 +1787,8 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
   if (node->break_target()->is_linked()) {
     node->break_target()->Bind();
   }
+  node->continue_target()->Unuse();
+  node->break_target()->Unuse();
   ASSERT(!has_valid_frame() || frame_->height() == original_height);
 }
 
@@ -1971,6 +1979,8 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
 
   // Exit.
   exit.Bind();
+  node->continue_target()->Unuse();
+  node->break_target()->Unuse();
   ASSERT(frame_->height() == original_height);
 }
 
index e648141..29fe2d4 100644 (file)
@@ -195,6 +195,8 @@ class CodeGenerator: public AstVisitor {
   // Accessors
   Scope* scope() const { return scope_; }
 
+  // Clearing and generating deferred code.
+  void ClearDeferred();
   void ProcessDeferred();
 
   bool is_eval() { return is_eval_; }
index ec5813b..f13af68 100644 (file)
@@ -307,7 +307,11 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
   DeleteFrame();
 
   // Process any deferred code using the register allocator.
-  ProcessDeferred();
+  if (HasStackOverflow()) {
+    ClearDeferred();
+  } else {
+    ProcessDeferred();
+  }
 
   // There is no need to delete the register allocator, it is a
   // stack-allocated local.
@@ -1567,6 +1571,7 @@ void CodeGenerator::VisitBlock(Block* node) {
   if (node->break_target()->is_linked()) {
     node->break_target()->Bind();
   }
+  node->break_target()->Unuse();
 }
 
 
@@ -2094,37 +2099,39 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
 
     // There are two ways to reach the body: from the corresponding
     // test or as the fall through of the previous body.
-    if (!clause->body_target()->is_linked() && !has_valid_frame()) {
-      // If we have neither, skip this body.
-      continue;
-    } else if (clause->body_target()->is_linked() && has_valid_frame()) {
-      // If we have both, put a jump on the fall through path to avoid
-      // the dropping of the switch value on the test path.  The
-      // exception is the default which has already had the switch
-      // value dropped.
-      if (clause->is_default()) {
-        clause->body_target()->Bind();
+    if (clause->body_target()->is_linked() || has_valid_frame()) {
+      if (clause->body_target()->is_linked()) {
+        if (has_valid_frame()) {
+          // If we have both a jump to the test and a fall through, put
+          // a jump on the fall through path to avoid the dropping of
+          // the switch value on the test path.  The exception is the
+          // default which has already had the switch value dropped.
+          if (clause->is_default()) {
+            clause->body_target()->Bind();
+          } else {
+            JumpTarget body(this);
+            body.Jump();
+            clause->body_target()->Bind();
+            frame_->Drop();
+            body.Bind();
+          }
+        } else {
+          // No fall through to worry about.
+          clause->body_target()->Bind();
+          if (!clause->is_default()) {
+            frame_->Drop();
+          }
+        }
       } else {
-        JumpTarget body(this);
-        body.Jump();
-        clause->body_target()->Bind();
-        frame_->Drop();
-        body.Bind();
-      }
-    } else if (clause->body_target()->is_linked()) {
-      // No fall through to worry about.
-      clause->body_target()->Bind();
-      if (!clause->is_default()) {
-        frame_->Drop();
+        // Otherwise, we have only fall through.
+        ASSERT(has_valid_frame());
       }
-    } else {
-      // Otherwise, we have only fall through.
-      ASSERT(has_valid_frame());
-    }
 
-    // We are now prepared to compile the body.
-    Comment cmnt(masm_, "[ Case body");
-    VisitStatements(clause->statements());
+      // We are now prepared to compile the body.
+      Comment cmnt(masm_, "[ Case body");
+      VisitStatements(clause->statements());
+    }
+    clause->body_target()->Unuse();
   }
 
   // We may not have a valid frame here so bind the break target only
@@ -2132,6 +2139,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
   if (node->break_target()->is_linked()) {
     node->break_target()->Bind();
   }
+  node->break_target()->Unuse();
 }
 
 
@@ -2452,6 +2460,8 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
   }
 
   DecrementLoopNesting();
+  node->continue_target()->Unuse();
+  node->break_target()->Unuse();
 }
 
 
@@ -2636,6 +2646,9 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
 
   // Exit.
   exit.Bind();
+
+  node->continue_target()->Unuse();
+  node->break_target()->Unuse();
 }
 
 
index af248d9..dfa5978 100644 (file)
@@ -340,6 +340,8 @@ class CodeGenerator: public AstVisitor {
   // Accessors
   Scope* scope() const { return scope_; }
 
+  // Clearing and generating deferred code.
+  void ClearDeferred();
   void ProcessDeferred();
 
   bool is_eval() { return is_eval_; }
index f43e01c..558e854 100644 (file)
@@ -53,6 +53,13 @@ DeferredCode::DeferredCode(CodeGenerator* generator)
 }
 
 
+void CodeGenerator::ClearDeferred() {
+  for (int i = 0; i < deferred_.length(); i++) {
+    deferred_[i]->Clear();
+  }
+}
+
+
 void CodeGenerator::ProcessDeferred() {
   while (!deferred_.is_empty()) {
     DeferredCode* code = deferred_.RemoveLast();
@@ -66,6 +73,7 @@ void CodeGenerator::ProcessDeferred() {
     Comment cmnt(masm, code->comment());
     code->Generate();
     ASSERT(code->enter()->is_bound());
+    code->Clear();
   }
 }
 
index 1bfebdc..3086638 100644 (file)
@@ -52,6 +52,7 @@
 // CodeGenerator::CodeGenerator
 // CodeGenerator::~CodeGenerator
 // CodeGenerator::ProcessDeferred
+// CodeGenerator::ClearDeferred
 // CodeGenerator::GenCode
 // CodeGenerator::BuildBoilerplate
 // CodeGenerator::ComputeCallInitialize
@@ -92,6 +93,14 @@ class DeferredCode: public ZoneObject {
 
   virtual void Generate() = 0;
 
+  // Unuse the entry and exit targets, deallocating all virtual frames
+  // held by them.  It will be impossible to emit a (correct) jump
+  // into or out of the deferred code after clearing.
+  void Clear() {
+    enter_.Unuse();
+    exit_.Unuse();
+  }
+
   MacroAssembler* masm() const { return masm_; }
   CodeGenerator* generator() const { return generator_; }