Chromium Code Reviews| Index: src/rewriter.cc |
| diff --git a/src/rewriter.cc b/src/rewriter.cc |
| index 11af2bd26246d6fb44ee3fa5cd734f87071dff29..854621ed63ade4718a7ccf57f21860c9f2a15a11 100644 |
| --- a/src/rewriter.cc |
| +++ b/src/rewriter.cc |
| @@ -13,12 +13,13 @@ namespace internal { |
| class Processor: public AstVisitor { |
| public: |
| - Processor(Isolate* isolate, Variable* result, |
| + Processor(Isolate* isolate, Scope* scope, Variable* result, |
| AstValueFactory* ast_value_factory) |
| : result_(result), |
| result_assigned_(false), |
| replacement_(nullptr), |
| is_set_(false), |
| + scope_(scope), |
| factory_(ast_value_factory) { |
| InitializeAstVisitor(isolate, ast_value_factory->zone()); |
| } |
| @@ -28,6 +29,7 @@ class Processor: public AstVisitor { |
| void Process(ZoneList<Statement*>* statements); |
| bool result_assigned() const { return result_assigned_; } |
| + Scope* scope() { return scope_; } |
| AstNodeFactory* factory() { return &factory_; } |
| private: |
| @@ -49,8 +51,10 @@ class Processor: public AstVisitor { |
| // was hoping for. |
| bool is_set_; |
| + Scope* scope_; |
| AstNodeFactory factory_; |
| + // Returns ".result = value" |
| Expression* SetResult(Expression* value) { |
| result_assigned_ = true; |
| VariableProxy* result_proxy = factory()->NewVariableProxy(result_); |
| @@ -58,6 +62,9 @@ class Processor: public AstVisitor { |
| Token::ASSIGN, result_proxy, value, RelocInfo::kNoPosition); |
| } |
| + // Changes b to ".backup = .result; b; .result = .backup" |
| + void BackupAndRestore(Block* b); |
|
rossberg
2015/10/01 09:59:24
Nit: SaveAndRestore would sound more like the typi
neis
2015/10/01 10:56:48
Did that, but I don't think it improved readabilit
|
| + |
| // Node visitors. |
| #define DEF_VISIT(type) virtual void Visit##type(type* node) override; |
| AST_NODE_LIST(DEF_VISIT) |
| @@ -69,6 +76,24 @@ class Processor: public AstVisitor { |
| }; |
| +void Processor::BackupAndRestore(Block* b) { |
| + Variable* backup = scope()->NewTemporary( |
| + factory()->ast_value_factory()->dot_result_string()); |
| + Expression* backup_proxy = factory()->NewVariableProxy(backup); |
| + Expression* result_proxy = factory()->NewVariableProxy(result_); |
| + Expression* assignment1 = factory()->NewAssignment( |
| + Token::ASSIGN, backup_proxy, result_proxy, RelocInfo::kNoPosition); |
| + Expression* assignment2 = factory()->NewAssignment( |
| + Token::ASSIGN, result_proxy, backup_proxy, RelocInfo::kNoPosition); |
| + b->InsertStatementAt( |
| + 0, factory()->NewExpressionStatement(assignment1, RelocInfo::kNoPosition), |
| + zone()); |
| + b->AddStatement( |
| + factory()->NewExpressionStatement(assignment2, RelocInfo::kNoPosition), |
| + zone()); |
| +} |
| + |
| + |
| void Processor::Process(ZoneList<Statement*>* statements) { |
| for (int i = statements->length() - 1; i >= 0; --i) { |
| Visit(statements->at(i)); |
| @@ -167,9 +192,13 @@ void Processor::VisitTryCatchStatement(TryCatchStatement* node) { |
| 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()); |
| - Visit(node->try_block()); // Exception will not be caught. |
| + BackupAndRestore(node->finally_block()); |
| + is_set_ = set_after; |
| + Visit(node->try_block()); |
| node->set_try_block(replacement_->AsBlock()); |
| replacement_ = node; |
| } |
| @@ -260,7 +289,8 @@ bool Rewriter::Rewrite(ParseInfo* info) { |
| scope->NewTemporary(info->ast_value_factory()->dot_result_string()); |
| // The name string must be internalized at this point. |
| DCHECK(!result->name().is_null()); |
| - Processor processor(info->isolate(), result, info->ast_value_factory()); |
| + Processor processor(info->isolate(), scope, result, |
| + info->ast_value_factory()); |
| processor.Process(body); |
| if (processor.HasStackOverflow()) return false; |