Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(351)

Unified Diff: src/parsing/rewriter.cc

Issue 2427253003: Simplify and fix the rewriter (Closed)
Patch Set: Fix and add tests Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | test/mjsunit/es6/completion.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parsing/rewriter.cc
diff --git a/src/parsing/rewriter.cc b/src/parsing/rewriter.cc
index 19e9e4cd80d05d9cc07138f6c61e91d16a06c8d3..69ac4171c273eef7aa0aa14d1524a1944c04e203 100644
--- a/src/parsing/rewriter.cc
+++ b/src/parsing/rewriter.cc
@@ -167,36 +167,33 @@ void Processor::VisitExpressionStatement(ExpressionStatement* node) {
void Processor::VisitIfStatement(IfStatement* node) {
// Rewrite both branches.
bool set_after = is_set_;
+
Visit(node->then_statement());
node->set_then_statement(replacement_);
bool set_in_then = is_set_;
+
is_set_ = set_after;
Visit(node->else_statement());
node->set_else_statement(replacement_);
- is_set_ = is_set_ && set_in_then;
- replacement_ = node;
- if (!is_set_) {
- is_set_ = true;
- replacement_ = AssignUndefinedBefore(node);
- }
+ replacement_ = set_in_then && is_set_ ? node : AssignUndefinedBefore(node);
+ is_set_ = true;
}
void Processor::VisitIterationStatement(IterationStatement* node) {
+ // The statement may have to produce a value, so always assign undefined
+ // before.
+ // TODO(verwaest): Omit it if we know that there's no break/continue leaving
+ // it early.
+ DCHECK(breakable_ || !is_set_);
BreakableScope scope(this);
- // Rewrite the body.
- bool set_after = is_set_;
- is_set_ = false; // We are in a loop, so we can't rely on [set_after].
+
Visit(node->body());
node->set_body(replacement_);
- is_set_ = is_set_ && set_after;
- replacement_ = node;
- if (!is_set_) {
- is_set_ = true;
- replacement_ = AssignUndefinedBefore(node);
- }
+ replacement_ = AssignUndefinedBefore(node);
+ is_set_ = true;
}
@@ -228,74 +225,72 @@ void Processor::VisitForOfStatement(ForOfStatement* node) {
void Processor::VisitTryCatchStatement(TryCatchStatement* node) {
// Rewrite both try and catch block.
bool set_after = is_set_;
+
Visit(node->try_block());
node->set_try_block(static_cast<Block*>(replacement_));
bool set_in_try = is_set_;
+
is_set_ = set_after;
Visit(node->catch_block());
node->set_catch_block(static_cast<Block*>(replacement_));
- is_set_ = is_set_ && set_in_try;
- replacement_ = node;
- if (!is_set_) {
- is_set_ = true;
- replacement_ = AssignUndefinedBefore(node);
- }
+ replacement_ = is_set_ && set_in_try ? node : AssignUndefinedBefore(node);
+ is_set_ = true;
}
void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) {
- // Rewrite both try and finally block (in reverse order).
- bool set_after = is_set_;
- is_set_ = true; // Don't normally need to assign in finally block.
- Visit(node->finally_block());
- node->set_finally_block(replacement_->AsBlock());
- { // Save .result value at the beginning of the finally block and restore it
- // at the end again: ".backup = .result; ...; .result = .backup"
- // This is necessary because the finally block does not normally contribute
- // to the completion value.
- CHECK_NOT_NULL(closure_scope());
- Variable* backup = closure_scope()->NewTemporary(
- factory()->ast_value_factory()->dot_result_string());
- Expression* backup_proxy = factory()->NewVariableProxy(backup);
- Expression* result_proxy = factory()->NewVariableProxy(result_);
- Expression* save = factory()->NewAssignment(
- Token::ASSIGN, backup_proxy, result_proxy, kNoSourcePosition);
- Expression* restore = factory()->NewAssignment(
- Token::ASSIGN, result_proxy, backup_proxy, kNoSourcePosition);
- node->finally_block()->statements()->InsertAt(
- 0, factory()->NewExpressionStatement(save, kNoSourcePosition), zone());
- node->finally_block()->statements()->Add(
- factory()->NewExpressionStatement(restore, kNoSourcePosition), zone());
+ // Only rewrite finally if it could contain 'break' or 'continue'. Always
+ // rewrite try.
+ if (breakable_) {
+ bool set_after = is_set_;
+ // Only set result before a 'break' or 'continue'.
+ is_set_ = true;
+ Visit(node->finally_block());
+ node->set_finally_block(replacement_->AsBlock());
+ // Save .result value at the beginning of the finally block and restore it
+ // at the end again: ".backup = .result; ...; .result = .backup"
+ // This is necessary because the finally block does not normally contribute
+ // to the completion value.
+ CHECK_NOT_NULL(closure_scope());
+ Variable* backup = closure_scope()->NewTemporary(
+ factory()->ast_value_factory()->dot_result_string());
+ Expression* backup_proxy = factory()->NewVariableProxy(backup);
+ Expression* result_proxy = factory()->NewVariableProxy(result_);
+ Expression* save = factory()->NewAssignment(
+ Token::ASSIGN, backup_proxy, result_proxy, kNoSourcePosition);
+ Expression* restore = factory()->NewAssignment(
+ Token::ASSIGN, result_proxy, backup_proxy, kNoSourcePosition);
+ node->finally_block()->statements()->InsertAt(
+ 0, factory()->NewExpressionStatement(save, kNoSourcePosition), zone());
+ node->finally_block()->statements()->Add(
+ factory()->NewExpressionStatement(restore, kNoSourcePosition), zone());
+ is_set_ = set_after;
}
- is_set_ = set_after;
Visit(node->try_block());
node->set_try_block(replacement_->AsBlock());
- replacement_ = node;
- if (!is_set_) {
- is_set_ = true;
- replacement_ = AssignUndefinedBefore(node);
- }
+ replacement_ = is_set_ ? node : AssignUndefinedBefore(node);
+ is_set_ = true;
}
void Processor::VisitSwitchStatement(SwitchStatement* node) {
+ // The statement may have to produce a value, so always assign undefined
+ // before.
+ // TODO(verwaest): Omit it if we know that there's no break/continue leaving
+ // it early.
+ DCHECK(breakable_ || !is_set_);
BreakableScope scope(this);
- // Rewrite statements in all case clauses (in reverse order).
+ // Rewrite statements in all case clauses.
ZoneList<CaseClause*>* clauses = node->cases();
- bool set_after = is_set_;
for (int i = clauses->length() - 1; i >= 0; --i) {
CaseClause* clause = clauses->at(i);
Process(clause->statements());
}
- is_set_ = is_set_ && set_after;
- replacement_ = node;
- if (!is_set_) {
- is_set_ = true;
- replacement_ = AssignUndefinedBefore(node);
- }
+ replacement_ = AssignUndefinedBefore(node);
+ is_set_ = true;
}
@@ -314,12 +309,9 @@ void Processor::VisitBreakStatement(BreakStatement* node) {
void Processor::VisitWithStatement(WithStatement* node) {
Visit(node->statement());
node->set_statement(replacement_);
- replacement_ = node;
- if (!is_set_) {
- is_set_ = true;
- replacement_ = AssignUndefinedBefore(node);
- }
+ replacement_ = is_set_ ? node : AssignUndefinedBefore(node);
+ is_set_ = true;
}
« no previous file with comments | « no previous file | test/mjsunit/es6/completion.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698