Index: src/rewriter.cc |
diff --git a/src/rewriter.cc b/src/rewriter.cc |
index 3f329e5e72a9896042df5a13935e30c146002be3..11af2bd26246d6fb44ee3fa5cd734f87071dff29 100644 |
--- a/src/rewriter.cc |
+++ b/src/rewriter.cc |
@@ -17,6 +17,7 @@ class Processor: public AstVisitor { |
AstValueFactory* ast_value_factory) |
: result_(result), |
result_assigned_(false), |
+ replacement_(nullptr), |
is_set_(false), |
factory_(ast_value_factory) { |
InitializeAstVisitor(isolate, ast_value_factory->zone()); |
@@ -38,6 +39,10 @@ class Processor: public AstVisitor { |
// there was ever an assignment to result_. |
bool result_assigned_; |
+ // When visiting a node, we "return" a replacement for that node in |
+ // [replacement_]. In many cases this will just be the original node. |
+ Statement* replacement_; |
+ |
// To avoid storing to .result all the time, we eliminate some of |
// the stores by keeping track of whether or not we're sure .result |
// will be overwritten anyway. This is a bit more tricky than what I |
@@ -67,6 +72,7 @@ class Processor: public AstVisitor { |
void Processor::Process(ZoneList<Statement*>* statements) { |
for (int i = statements->length() - 1; i >= 0; --i) { |
Visit(statements->at(i)); |
+ statements->Set(i, replacement_); |
} |
} |
@@ -81,6 +87,7 @@ void Processor::VisitBlock(Block* node) { |
// returns 'undefined'. To obtain the same behavior with v8, we need |
// to prevent rewriting in that case. |
if (!node->ignore_completion_value()) Process(node->statements()); |
+ replacement_ = node; |
} |
@@ -90,6 +97,7 @@ void Processor::VisitExpressionStatement(ExpressionStatement* node) { |
node->set_expression(SetResult(node->expression())); |
is_set_ = true; |
} |
+ replacement_ = node; |
} |
@@ -97,10 +105,13 @@ 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; |
} |
@@ -109,7 +120,9 @@ void Processor::VisitIterationStatement(IterationStatement* node) { |
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; |
} |
@@ -142,17 +155,23 @@ 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; |
} |
void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) { |
// Rewrite both try and finally block (in reverse order). |
Visit(node->finally_block()); |
- Visit(node->try_block()); |
+ node->set_finally_block(replacement_->AsBlock()); |
+ Visit(node->try_block()); // Exception will not be caught. |
+ node->set_try_block(replacement_->AsBlock()); |
+ replacement_ = node; |
} |
@@ -165,36 +184,51 @@ void Processor::VisitSwitchStatement(SwitchStatement* node) { |
Process(clause->statements()); |
} |
is_set_ = is_set_ && set_after; |
+ replacement_ = node; |
} |
void Processor::VisitContinueStatement(ContinueStatement* node) { |
is_set_ = false; |
+ replacement_ = node; |
} |
void Processor::VisitBreakStatement(BreakStatement* node) { |
is_set_ = false; |
+ replacement_ = node; |
} |
void Processor::VisitWithStatement(WithStatement* node) { |
Visit(node->statement()); |
+ node->set_statement(replacement_); |
+ replacement_ = node; |
} |
void Processor::VisitSloppyBlockFunctionStatement( |
SloppyBlockFunctionStatement* node) { |
Visit(node->statement()); |
+ node->set_statement(replacement_); |
+ replacement_ = node; |
} |
-void Processor::VisitReturnStatement(ReturnStatement* node) { is_set_ = true; } |
+void Processor::VisitEmptyStatement(EmptyStatement* node) { |
+ replacement_ = node; |
+} |
-// Do nothing: |
-void Processor::VisitEmptyStatement(EmptyStatement* node) {} |
-void Processor::VisitDebuggerStatement(DebuggerStatement* node) {} |
+void Processor::VisitReturnStatement(ReturnStatement* node) { |
+ is_set_ = true; |
+ replacement_ = node; |
+} |
+ |
+ |
+void Processor::VisitDebuggerStatement(DebuggerStatement* node) { |
+ replacement_ = node; |
+} |
// Expressions are never visited. |