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