Index: src/typing.cc |
diff --git a/src/typing.cc b/src/typing.cc |
index dd4abcfd7d1718a0224086e35a649f91ad464e9a..804d6b79ac4ad06b6b8cb84c95d73d82d94495f3 100644 |
--- a/src/typing.cc |
+++ b/src/typing.cc |
@@ -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; |
@@ -379,7 +397,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()); |
} |
@@ -389,11 +407,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())); |
} |
} |
@@ -528,11 +544,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())); |
} |
} |