Chromium Code Reviews| 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); |
|
titzer
2013/07/15 09:18:18
I'm not sure this is quite right. Did you define I
rossberg
2013/07/15 09:44:59
Yes, see ast.h. The idea is to give up on non-triv
titzer
2013/07/15 13:30:42
So you actually have 5 different types of control
rossberg
2013/07/15 14:21:56
There's also 'return', and a 'continue' in a 'for'
|
| + } 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())); |
| } |
| } |