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_; }
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; }
void set_expression(Expression* e) { expression_ = e; }
Expression* expression() const { return expression_; }
+ virtual bool IsJump() const { return expression_->IsThrow(); }
protected:
explicit ExpressionStatement(Expression* expression)
};
-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)
};
-class BreakStatement: public Statement {
+class BreakStatement: public JumpStatement {
public:
DECLARE_NODE_TYPE(BreakStatement)
};
-class ReturnStatement: public Statement {
+class ReturnStatement: public JumpStatement {
public:
DECLARE_NODE_TYPE(ReturnStatement)
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_; }
for (int i = 0; i < stmts->length(); ++i) {
Statement* stmt = stmts->at(i);
RECURSE(Visit(stmt));
+ if (stmt->IsJump()) break;
}
}
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 =
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;
NarrowType(expr, expr->binary_operation()->bounds());
} else {
// Collect type feedback.
- if (expr->target()->AsProperty()) {
+ if (expr->target()->IsProperty()) {
expr->RecordTypeFeedback(oracle(), zone());
}
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()));
}
}
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()));
}
}