| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/parsing/rewriter.h" | 5 #include "src/parsing/rewriter.h" |
| 6 | 6 |
| 7 #include "src/ast/ast.h" | 7 #include "src/ast/ast.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/parsing/parse-info.h" | 9 #include "src/parsing/parse-info.h" |
| 10 #include "src/parsing/parser.h" | 10 #include "src/parsing/parser.h" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 replacement_(nullptr), | 35 replacement_(nullptr), |
| 36 is_set_(false), | 36 is_set_(false), |
| 37 breakable_(false), | 37 breakable_(false), |
| 38 zone_(ast_value_factory->zone()), | 38 zone_(ast_value_factory->zone()), |
| 39 closure_scope_(closure_scope), | 39 closure_scope_(closure_scope), |
| 40 factory_(ast_value_factory) { | 40 factory_(ast_value_factory) { |
| 41 DCHECK_EQ(closure_scope, closure_scope->GetClosureScope()); | 41 DCHECK_EQ(closure_scope, closure_scope->GetClosureScope()); |
| 42 InitializeAstVisitor(parser->stack_limit()); | 42 InitializeAstVisitor(parser->stack_limit()); |
| 43 } | 43 } |
| 44 | 44 |
| 45 void Process(ZoneList<Statement*>* statements); | 45 void Process(ZoneChunkList<Statement*>* statements); |
| 46 bool result_assigned() const { return result_assigned_; } | 46 bool result_assigned() const { return result_assigned_; } |
| 47 | 47 |
| 48 Zone* zone() { return zone_; } | 48 Zone* zone() { return zone_; } |
| 49 DeclarationScope* closure_scope() { return closure_scope_; } | 49 DeclarationScope* closure_scope() { return closure_scope_; } |
| 50 AstNodeFactory* factory() { return &factory_; } | 50 AstNodeFactory* factory() { return &factory_; } |
| 51 | 51 |
| 52 // Returns ".result = value" | 52 // Returns ".result = value" |
| 53 Expression* SetResult(Expression* value) { | 53 Expression* SetResult(Expression* value) { |
| 54 result_assigned_ = true; | 54 result_assigned_ = true; |
| 55 VariableProxy* result_proxy = factory()->NewVariableProxy(result_); | 55 VariableProxy* result_proxy = factory()->NewVariableProxy(result_); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 | 108 |
| 109 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 109 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
| 110 }; | 110 }; |
| 111 | 111 |
| 112 | 112 |
| 113 Statement* Processor::AssignUndefinedBefore(Statement* s) { | 113 Statement* Processor::AssignUndefinedBefore(Statement* s) { |
| 114 Expression* result_proxy = factory()->NewVariableProxy(result_); | 114 Expression* result_proxy = factory()->NewVariableProxy(result_); |
| 115 Expression* undef = factory()->NewUndefinedLiteral(kNoSourcePosition); | 115 Expression* undef = factory()->NewUndefinedLiteral(kNoSourcePosition); |
| 116 Expression* assignment = factory()->NewAssignment(Token::ASSIGN, result_proxy, | 116 Expression* assignment = factory()->NewAssignment(Token::ASSIGN, result_proxy, |
| 117 undef, kNoSourcePosition); | 117 undef, kNoSourcePosition); |
| 118 Block* b = factory()->NewBlock(NULL, 2, false, kNoSourcePosition); | 118 Block* b = factory()->NewBlock(NULL, false, kNoSourcePosition); |
| 119 b->statements()->Add( | 119 b->statements()->push_back( |
| 120 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone()); | 120 factory()->NewExpressionStatement(assignment, kNoSourcePosition)); |
| 121 b->statements()->Add(s, zone()); | 121 b->statements()->push_back(s); |
| 122 return b; | 122 return b; |
| 123 } | 123 } |
| 124 | 124 |
| 125 | 125 void Processor::Process(ZoneChunkList<Statement*>* statements) { |
| 126 void Processor::Process(ZoneList<Statement*>* statements) { | |
| 127 // If we're in a breakable scope (named block, iteration, or switch), we walk | 126 // If we're in a breakable scope (named block, iteration, or switch), we walk |
| 128 // all statements. The last value producing statement before the break needs | 127 // all statements. The last value producing statement before the break needs |
| 129 // to assign to .result. If we're not in a breakable scope, only the last | 128 // to assign to .result. If we're not in a breakable scope, only the last |
| 130 // value producing statement in the block assigns to .result, so we can stop | 129 // value producing statement in the block assigns to .result, so we can stop |
| 131 // early. | 130 // early. |
| 132 for (int i = statements->length() - 1; i >= 0 && (breakable_ || !is_set_); | 131 for (auto it = statements->rbegin(); |
| 133 --i) { | 132 it != statements->rend() && (breakable_ || !is_set_); ++it) { |
| 134 Visit(statements->at(i)); | 133 Visit(*it); |
| 135 statements->Set(i, replacement_); | 134 *it = replacement_; |
| 136 } | 135 } |
| 137 } | 136 } |
| 138 | 137 |
| 139 | 138 |
| 140 void Processor::VisitBlock(Block* node) { | 139 void Processor::VisitBlock(Block* node) { |
| 141 // An initializer block is the rewritten form of a variable declaration | 140 // An initializer block is the rewritten form of a variable declaration |
| 142 // with initialization expressions. The initializer block contains the | 141 // with initialization expressions. The initializer block contains the |
| 143 // list of assignments corresponding to the initialization expressions. | 142 // list of assignments corresponding to the initialization expressions. |
| 144 // While unclear from the spec (ECMA-262, 3rd., 12.2), the value of | 143 // While unclear from the spec (ECMA-262, 3rd., 12.2), the value of |
| 145 // a variable declaration with initialization expression is 'undefined' | 144 // a variable declaration with initialization expression is 'undefined' |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 // to the completion value. | 253 // to the completion value. |
| 255 CHECK_NOT_NULL(closure_scope()); | 254 CHECK_NOT_NULL(closure_scope()); |
| 256 Variable* backup = closure_scope()->NewTemporary( | 255 Variable* backup = closure_scope()->NewTemporary( |
| 257 factory()->ast_value_factory()->dot_result_string()); | 256 factory()->ast_value_factory()->dot_result_string()); |
| 258 Expression* backup_proxy = factory()->NewVariableProxy(backup); | 257 Expression* backup_proxy = factory()->NewVariableProxy(backup); |
| 259 Expression* result_proxy = factory()->NewVariableProxy(result_); | 258 Expression* result_proxy = factory()->NewVariableProxy(result_); |
| 260 Expression* save = factory()->NewAssignment( | 259 Expression* save = factory()->NewAssignment( |
| 261 Token::ASSIGN, backup_proxy, result_proxy, kNoSourcePosition); | 260 Token::ASSIGN, backup_proxy, result_proxy, kNoSourcePosition); |
| 262 Expression* restore = factory()->NewAssignment( | 261 Expression* restore = factory()->NewAssignment( |
| 263 Token::ASSIGN, result_proxy, backup_proxy, kNoSourcePosition); | 262 Token::ASSIGN, result_proxy, backup_proxy, kNoSourcePosition); |
| 264 node->finally_block()->statements()->InsertAt( | 263 node->finally_block()->statements()->push_front( |
| 265 0, factory()->NewExpressionStatement(save, kNoSourcePosition), zone()); | 264 factory()->NewExpressionStatement(save, kNoSourcePosition)); |
| 266 node->finally_block()->statements()->Add( | 265 node->finally_block()->statements()->push_back( |
| 267 factory()->NewExpressionStatement(restore, kNoSourcePosition), zone()); | 266 factory()->NewExpressionStatement(restore, kNoSourcePosition)); |
| 268 is_set_ = set_after; | 267 is_set_ = set_after; |
| 269 } | 268 } |
| 270 Visit(node->try_block()); | 269 Visit(node->try_block()); |
| 271 node->set_try_block(replacement_->AsBlock()); | 270 node->set_try_block(replacement_->AsBlock()); |
| 272 | 271 |
| 273 replacement_ = is_set_ ? node : AssignUndefinedBefore(node); | 272 replacement_ = is_set_ ? node : AssignUndefinedBefore(node); |
| 274 is_set_ = true; | 273 is_set_ = true; |
| 275 } | 274 } |
| 276 | 275 |
| 277 | 276 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 // Assumes code has been parsed. Mutates the AST, so the AST should not | 355 // Assumes code has been parsed. Mutates the AST, so the AST should not |
| 357 // continue to be used in the case of failure. | 356 // continue to be used in the case of failure. |
| 358 bool Rewriter::Rewrite(ParseInfo* info) { | 357 bool Rewriter::Rewrite(ParseInfo* info) { |
| 359 FunctionLiteral* function = info->literal(); | 358 FunctionLiteral* function = info->literal(); |
| 360 DCHECK_NOT_NULL(function); | 359 DCHECK_NOT_NULL(function); |
| 361 Scope* scope = function->scope(); | 360 Scope* scope = function->scope(); |
| 362 DCHECK_NOT_NULL(scope); | 361 DCHECK_NOT_NULL(scope); |
| 363 if (!scope->is_script_scope() && !scope->is_eval_scope()) return true; | 362 if (!scope->is_script_scope() && !scope->is_eval_scope()) return true; |
| 364 DeclarationScope* closure_scope = scope->GetClosureScope(); | 363 DeclarationScope* closure_scope = scope->GetClosureScope(); |
| 365 | 364 |
| 366 ZoneList<Statement*>* body = function->body(); | 365 ZoneChunkList<Statement*>* body = function->body(); |
| 367 if (!body->is_empty()) { | 366 if (body->size() > 0) { |
| 368 Variable* result = closure_scope->NewTemporary( | 367 Variable* result = closure_scope->NewTemporary( |
| 369 info->ast_value_factory()->dot_result_string()); | 368 info->ast_value_factory()->dot_result_string()); |
| 370 // The name string must be internalized at this point. | 369 // The name string must be internalized at this point. |
| 371 info->ast_value_factory()->Internalize(info->isolate()); | 370 info->ast_value_factory()->Internalize(info->isolate()); |
| 372 DCHECK(!result->name().is_null()); | 371 DCHECK(!result->name().is_null()); |
| 373 Processor processor(info->isolate(), closure_scope, result, | 372 Processor processor(info->isolate(), closure_scope, result, |
| 374 info->ast_value_factory()); | 373 info->ast_value_factory()); |
| 375 processor.Process(body); | 374 processor.Process(body); |
| 376 // Internalize any values created during rewriting. | 375 // Internalize any values created during rewriting. |
| 377 info->ast_value_factory()->Internalize(info->isolate()); | 376 info->ast_value_factory()->Internalize(info->isolate()); |
| 378 if (processor.HasStackOverflow()) return false; | 377 if (processor.HasStackOverflow()) return false; |
| 379 | 378 |
| 380 if (processor.result_assigned()) { | 379 if (processor.result_assigned()) { |
| 381 int pos = kNoSourcePosition; | 380 int pos = kNoSourcePosition; |
| 382 VariableProxy* result_proxy = | 381 VariableProxy* result_proxy = |
| 383 processor.factory()->NewVariableProxy(result, pos); | 382 processor.factory()->NewVariableProxy(result, pos); |
| 384 Statement* result_statement = | 383 Statement* result_statement = |
| 385 processor.factory()->NewReturnStatement(result_proxy, pos); | 384 processor.factory()->NewReturnStatement(result_proxy, pos); |
| 386 body->Add(result_statement, info->zone()); | 385 body->push_back(result_statement); |
| 387 } | 386 } |
| 388 } | 387 } |
| 389 | 388 |
| 390 return true; | 389 return true; |
| 391 } | 390 } |
| 392 | 391 |
| 393 bool Rewriter::Rewrite(Parser* parser, DeclarationScope* closure_scope, | 392 bool Rewriter::Rewrite(Parser* parser, DeclarationScope* closure_scope, |
| 394 DoExpression* expr, AstValueFactory* factory) { | 393 DoExpression* expr, AstValueFactory* factory) { |
| 395 Block* block = expr->block(); | 394 Block* block = expr->block(); |
| 396 DCHECK_EQ(closure_scope, closure_scope->GetClosureScope()); | 395 DCHECK_EQ(closure_scope, closure_scope->GetClosureScope()); |
| 397 DCHECK(block->scope() == nullptr || | 396 DCHECK(block->scope() == nullptr || |
| 398 block->scope()->GetClosureScope() == closure_scope); | 397 block->scope()->GetClosureScope() == closure_scope); |
| 399 ZoneList<Statement*>* body = block->statements(); | 398 ZoneChunkList<Statement*>* body = block->statements(); |
| 400 VariableProxy* result = expr->result(); | 399 VariableProxy* result = expr->result(); |
| 401 Variable* result_var = result->var(); | 400 Variable* result_var = result->var(); |
| 402 | 401 |
| 403 if (!body->is_empty()) { | 402 if (body->size() > 0) { |
| 404 Processor processor(parser, closure_scope, result_var, factory); | 403 Processor processor(parser, closure_scope, result_var, factory); |
| 405 processor.Process(body); | 404 processor.Process(body); |
| 406 if (processor.HasStackOverflow()) return false; | 405 if (processor.HasStackOverflow()) return false; |
| 407 | 406 |
| 408 if (!processor.result_assigned()) { | 407 if (!processor.result_assigned()) { |
| 409 AstNodeFactory* node_factory = processor.factory(); | 408 AstNodeFactory* node_factory = processor.factory(); |
| 410 Expression* undef = node_factory->NewUndefinedLiteral(kNoSourcePosition); | 409 Expression* undef = node_factory->NewUndefinedLiteral(kNoSourcePosition); |
| 411 Statement* completion = node_factory->NewExpressionStatement( | 410 Statement* completion = node_factory->NewExpressionStatement( |
| 412 processor.SetResult(undef), expr->position()); | 411 processor.SetResult(undef), expr->position()); |
| 413 body->Add(completion, factory->zone()); | 412 body->push_back(completion); |
| 414 } | 413 } |
| 415 } | 414 } |
| 416 return true; | 415 return true; |
| 417 } | 416 } |
| 418 | 417 |
| 419 | 418 |
| 420 } // namespace internal | 419 } // namespace internal |
| 421 } // namespace v8 | 420 } // namespace v8 |
| OLD | NEW |