Handle switch effects
authorrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 19 Jul 2013 13:04:41 +0000 (13:04 +0000)
committerrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 19 Jul 2013 13:04:41 +0000 (13:04 +0000)
R=titzer@chromium.org
BUG=

Review URL: https://codereview.chromium.org/18926004

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

src/ast.h
src/typing.cc

index 6feb4b7..d0ea926 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -259,6 +259,7 @@ class Statement: public AstNode {
   Statement() : statement_pos_(RelocInfo::kNoPosition) {}
 
   bool IsEmpty() { return AsEmptyStatement() != NULL; }
+  virtual bool IsJump() const { return false; }
 
   void set_statement_pos(int statement_pos) { statement_pos_ = statement_pos; }
   int statement_pos() const { return statement_pos_; }
@@ -459,6 +460,11 @@ class Block: public BreakableStatement {
   ZoneList<Statement*>* statements() { return &statements_; }
   bool is_initializer_block() const { return is_initializer_block_; }
 
+  virtual bool IsJump() const {
+    return !statements_.is_empty() && statements_.last()->IsJump()
+        && labels() == NULL;  // Good enough as an approximation...
+  }
+
   Scope* scope() const { return scope_; }
   void set_scope(Scope* scope) { scope_ = scope; }
 
@@ -1009,6 +1015,7 @@ class ExpressionStatement: public Statement {
 
   void set_expression(Expression* e) { expression_ = e; }
   Expression* expression() const { return expression_; }
+  virtual bool IsJump() const { return expression_->IsThrow(); }
 
  protected:
   explicit ExpressionStatement(Expression* expression)
@@ -1019,7 +1026,16 @@ class ExpressionStatement: public Statement {
 };
 
 
-class ContinueStatement: public Statement {
+class JumpStatement: public Statement {
+ public:
+  virtual bool IsJump() const { return true; }
+
+ protected:
+  JumpStatement() {}
+};
+
+
+class ContinueStatement: public JumpStatement {
  public:
   DECLARE_NODE_TYPE(ContinueStatement)
 
@@ -1034,7 +1050,7 @@ class ContinueStatement: public Statement {
 };
 
 
-class BreakStatement: public Statement {
+class BreakStatement: public JumpStatement {
  public:
   DECLARE_NODE_TYPE(BreakStatement)
 
@@ -1049,7 +1065,7 @@ class BreakStatement: public Statement {
 };
 
 
-class ReturnStatement: public Statement {
+class ReturnStatement: public JumpStatement {
  public:
   DECLARE_NODE_TYPE(ReturnStatement)
 
@@ -1168,6 +1184,11 @@ class IfStatement: public Statement {
   Statement* then_statement() const { return then_statement_; }
   Statement* else_statement() const { return else_statement_; }
 
+  virtual bool IsJump() const {
+    return HasThenStatement() && then_statement()->IsJump()
+        && HasElseStatement() && else_statement()->IsJump();
+  }
+
   BailoutId IfId() const { return if_id_; }
   BailoutId ThenId() const { return then_id_; }
   BailoutId ElseId() const { return else_id_; }
index fe75eaa..8b381be 100644 (file)
@@ -80,6 +80,7 @@ void AstTyper::VisitStatements(ZoneList<Statement*>* stmts) {
   for (int i = 0; i < stmts->length(); ++i) {
     Statement* stmt = stmts->at(i);
     RECURSE(Visit(stmt));
+    if (stmt->IsJump()) break;
   }
 }
 
@@ -151,8 +152,13 @@ void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
 
   ZoneList<CaseClause*>* clauses = stmt->cases();
   SwitchStatement::SwitchType switch_type = stmt->switch_type();
+  Effects local_effects(zone());
+  bool complex_effects = false;  // True for label effects or fall-through.
+
   for (int i = 0; i < clauses->length(); ++i) {
     CaseClause* clause = clauses->at(i);
+    Effects clause_effects = EnterEffects();
+
     if (!clause->is_default()) {
       Expression* label = clause->label();
       SwitchStatement::SwitchType label_switch_type =
@@ -165,12 +171,24 @@ void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
         switch_type = SwitchStatement::GENERIC_SWITCH;
 
       RECURSE(Visit(label));
+      if (!clause_effects.IsEmpty()) complex_effects = true;
+    }
+
+    ZoneList<Statement*>* stmts = clause->statements();
+    RECURSE(VisitStatements(stmts));
+    ExitEffects();
+    if (stmts->is_empty() || stmts->last()->IsJump()) {
+      local_effects.Alt(clause_effects);
+    } else {
+      complex_effects = true;
     }
-    RECURSE(VisitStatements(clause->statements()));
   }
 
-  // TODO(rossberg): handle switch effects
-  store_.Forget();
+  if (complex_effects) {
+    store_.Forget();  // Reached this in unknown state.
+  } else {
+    store_.Seq(local_effects);
+  }
 
   if (switch_type == SwitchStatement::UNKNOWN_SWITCH)
     switch_type = SwitchStatement::GENERIC_SWITCH;
@@ -380,7 +398,7 @@ void AstTyper::VisitAssignment(Assignment* expr) {
     NarrowType(expr, expr->binary_operation()->bounds());
   } else {
     // Collect type feedback.
-    if (expr->target()->AsProperty()) {
+    if (expr->target()->IsProperty()) {
       expr->RecordTypeFeedback(oracle(), zone());
     }
 
@@ -390,11 +408,9 @@ void AstTyper::VisitAssignment(Assignment* expr) {
     NarrowType(expr, expr->value()->bounds());
   }
 
-  if (expr->target()->AsVariableProxy()) {
-    Variable* var = expr->target()->AsVariableProxy()->var();
-    if (var->IsStackAllocated()) {
-      store_.Seq(variable_index(var), Effect(expr->bounds()));
-    }
+  VariableProxy* proxy = expr->target()->AsVariableProxy();
+  if (proxy != NULL && proxy->var()->IsStackAllocated()) {
+    store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
   }
 }
 
@@ -529,11 +545,9 @@ void AstTyper::VisitCountOperation(CountOperation* expr) {
 
   NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
 
-  if (expr->expression()->AsVariableProxy()) {
-    Variable* var = expr->expression()->AsVariableProxy()->var();
-    if (var->IsStackAllocated()) {
-      store_.Seq(variable_index(var), Effect(expr->bounds()));
-    }
+  VariableProxy* proxy = expr->expression()->AsVariableProxy();
+  if (proxy != NULL && proxy->var()->IsStackAllocated()) {
+    store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
   }
 }