Chromium Code Reviews| 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/parser.h" | 5 #include "src/parsing/parser.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "src/api.h" | 9 #include "src/api.h" |
| 10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
| (...skipping 4291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4302 const auto& assignments = | 4302 const auto& assignments = |
| 4303 function_state_->destructuring_assignments_to_rewrite(); | 4303 function_state_->destructuring_assignments_to_rewrite(); |
| 4304 for (int i = assignments.length() - 1; i >= 0; --i) { | 4304 for (int i = assignments.length() - 1; i >= 0; --i) { |
| 4305 // Rewrite list in reverse, so that nested assignment patterns are rewritten | 4305 // Rewrite list in reverse, so that nested assignment patterns are rewritten |
| 4306 // correctly. | 4306 // correctly. |
| 4307 const DestructuringAssignment& pair = assignments.at(i); | 4307 const DestructuringAssignment& pair = assignments.at(i); |
| 4308 RewritableExpression* to_rewrite = | 4308 RewritableExpression* to_rewrite = |
| 4309 pair.assignment->AsRewritableExpression(); | 4309 pair.assignment->AsRewritableExpression(); |
| 4310 DCHECK_NOT_NULL(to_rewrite); | 4310 DCHECK_NOT_NULL(to_rewrite); |
| 4311 if (!to_rewrite->is_rewritten()) { | 4311 if (!to_rewrite->is_rewritten()) { |
| 4312 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, | 4312 // Since this function is called at the end of parsing the program, |
| 4313 pair.scope); | 4313 // pair.scope may already have been removed by FinalizeBlockScope in the |
| 4314 // meantime. In that case, use the first outer non-removed scope. | |
| 4315 Scope* scope = pair.scope; | |
| 4316 while (scope != nullptr && scope->HasBeenRemoved()) { | |
|
Toon Verwaest
2016/11/23 12:20:45
Move to helper function as mentioned before.
| |
| 4317 scope = scope->outer_scope(); | |
| 4318 } | |
| 4319 DCHECK_NOT_NULL(scope); | |
| 4320 | |
| 4321 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope); | |
| 4314 } | 4322 } |
| 4315 } | 4323 } |
| 4316 } | 4324 } |
| 4317 | 4325 |
| 4318 Expression* Parser::RewriteExponentiation(Expression* left, Expression* right, | 4326 Expression* Parser::RewriteExponentiation(Expression* left, Expression* right, |
| 4319 int pos) { | 4327 int pos) { |
| 4320 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); | 4328 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); |
| 4321 args->Add(left, zone()); | 4329 args->Add(left, zone()); |
| 4322 args->Add(right, zone()); | 4330 args->Add(right, zone()); |
| 4323 return factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos); | 4331 return factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos); |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4738 Expression* condition = factory()->NewCompareOperation( | 4746 Expression* condition = factory()->NewCompareOperation( |
| 4739 Token::EQ, factory()->NewVariableProxy(var_throw), | 4747 Token::EQ, factory()->NewVariableProxy(var_throw), |
| 4740 factory()->NewNullLiteral(nopos), nopos); | 4748 factory()->NewNullLiteral(nopos), nopos); |
| 4741 Expression* call = | 4749 Expression* call = |
| 4742 NewThrowTypeError(MessageTemplate::kThrowMethodMissing, | 4750 NewThrowTypeError(MessageTemplate::kThrowMethodMissing, |
| 4743 ast_value_factory()->empty_string(), nopos); | 4751 ast_value_factory()->empty_string(), nopos); |
| 4744 Statement* throw_call = factory()->NewExpressionStatement(call, nopos); | 4752 Statement* throw_call = factory()->NewExpressionStatement(call, nopos); |
| 4745 | 4753 |
| 4746 Block* then = factory()->NewBlock(nullptr, 4 + 1, false, nopos); | 4754 Block* then = factory()->NewBlock(nullptr, 4 + 1, false, nopos); |
| 4747 BuildIteratorCloseForCompletion( | 4755 BuildIteratorCloseForCompletion( |
| 4748 then->statements(), var_iterator, | 4756 scope(), then->statements(), var_iterator, |
| 4749 factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos)); | 4757 factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos)); |
| 4750 then->statements()->Add(throw_call, zone()); | 4758 then->statements()->Add(throw_call, zone()); |
| 4751 check_throw = factory()->NewIfStatement( | 4759 check_throw = factory()->NewIfStatement( |
| 4752 condition, then, factory()->NewEmptyStatement(nopos), nopos); | 4760 condition, then, factory()->NewEmptyStatement(nopos), nopos); |
| 4753 } | 4761 } |
| 4754 | 4762 |
| 4755 // output = %_Call(iteratorThrow, iterator, input); | 4763 // output = %_Call(iteratorThrow, iterator, input); |
| 4756 Statement* call_throw; | 4764 Statement* call_throw; |
| 4757 { | 4765 { |
| 4758 auto args = new (zone()) ZoneList<Expression*>(3, zone()); | 4766 auto args = new (zone()) ZoneList<Expression*>(3, zone()); |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5106 is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call, | 5114 is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call, |
| 5107 nopos); | 5115 nopos); |
| 5108 } | 5116 } |
| 5109 | 5117 |
| 5110 statements->Add(get_return, zone()); | 5118 statements->Add(get_return, zone()); |
| 5111 statements->Add(check_return, zone()); | 5119 statements->Add(check_return, zone()); |
| 5112 statements->Add(call_return, zone()); | 5120 statements->Add(call_return, zone()); |
| 5113 statements->Add(validate_output, zone()); | 5121 statements->Add(validate_output, zone()); |
| 5114 } | 5122 } |
| 5115 | 5123 |
| 5116 void Parser::FinalizeIteratorUse(Variable* completion, Expression* condition, | 5124 void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion, |
| 5117 Variable* iter, Block* iterator_use, | 5125 Expression* condition, Variable* iter, |
| 5118 Block* target) { | 5126 Block* iterator_use, Block* target) { |
| 5119 // | 5127 // |
| 5120 // This function adds two statements to [target], corresponding to the | 5128 // This function adds two statements to [target], corresponding to the |
| 5121 // following code: | 5129 // following code: |
| 5122 // | 5130 // |
| 5123 // completion = kNormalCompletion; | 5131 // completion = kNormalCompletion; |
| 5124 // try { | 5132 // try { |
| 5125 // try { | 5133 // try { |
| 5126 // iterator_use | 5134 // iterator_use |
| 5127 // } catch(e) { | 5135 // } catch(e) { |
| 5128 // if (completion === kAbruptCompletion) completion = kThrowCompletion; | 5136 // if (completion === kAbruptCompletion) completion = kThrowCompletion; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5164 condition, statement, factory()->NewEmptyStatement(nopos), nopos); | 5172 condition, statement, factory()->NewEmptyStatement(nopos), nopos); |
| 5165 } | 5173 } |
| 5166 | 5174 |
| 5167 // if (condition) { | 5175 // if (condition) { |
| 5168 // #BuildIteratorCloseForCompletion(iter, completion) | 5176 // #BuildIteratorCloseForCompletion(iter, completion) |
| 5169 // } | 5177 // } |
| 5170 Block* maybe_close; | 5178 Block* maybe_close; |
| 5171 { | 5179 { |
| 5172 Block* block = factory()->NewBlock(nullptr, 2, true, nopos); | 5180 Block* block = factory()->NewBlock(nullptr, 2, true, nopos); |
| 5173 Expression* proxy = factory()->NewVariableProxy(completion); | 5181 Expression* proxy = factory()->NewVariableProxy(completion); |
| 5174 BuildIteratorCloseForCompletion(block->statements(), iter, proxy); | 5182 BuildIteratorCloseForCompletion(use_scope, block->statements(), iter, |
| 5183 proxy); | |
| 5175 DCHECK(block->statements()->length() == 2); | 5184 DCHECK(block->statements()->length() == 2); |
| 5176 | 5185 |
| 5177 maybe_close = factory()->NewBlock(nullptr, 1, true, nopos); | 5186 maybe_close = factory()->NewBlock(nullptr, 1, true, nopos); |
| 5178 maybe_close->statements()->Add( | 5187 maybe_close->statements()->Add( |
| 5179 factory()->NewIfStatement(condition, block, | 5188 factory()->NewIfStatement(condition, block, |
| 5180 factory()->NewEmptyStatement(nopos), nopos), | 5189 factory()->NewEmptyStatement(nopos), nopos), |
| 5181 zone()); | 5190 zone()); |
| 5182 } | 5191 } |
| 5183 | 5192 |
| 5184 // try { #try_block } | 5193 // try { #try_block } |
| 5185 // catch(e) { | 5194 // catch(e) { |
| 5186 // #set_completion_throw; | 5195 // #set_completion_throw; |
| 5187 // %ReThrow(e); | 5196 // %ReThrow(e); |
| 5188 // } | 5197 // } |
| 5189 Statement* try_catch; | 5198 Statement* try_catch; |
| 5190 { | 5199 { |
| 5191 Scope* catch_scope = NewScopeWithParent(scope(), CATCH_SCOPE); | 5200 Scope* catch_scope = NewScopeWithParent(use_scope, CATCH_SCOPE); |
| 5192 Variable* catch_variable = | 5201 Variable* catch_variable = |
| 5193 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, | 5202 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, |
| 5194 kCreatedInitialized, NORMAL_VARIABLE); | 5203 kCreatedInitialized, NORMAL_VARIABLE); |
| 5195 catch_scope->set_is_hidden(); | 5204 catch_scope->set_is_hidden(); |
| 5196 | 5205 |
| 5197 Statement* rethrow; | 5206 Statement* rethrow; |
| 5198 // We use %ReThrow rather than the ordinary throw because we want to | 5207 // We use %ReThrow rather than the ordinary throw because we want to |
| 5199 // preserve the original exception message. This is also why we create a | 5208 // preserve the original exception message. This is also why we create a |
| 5200 // TryCatchStatementForReThrow below (which does not clear the pending | 5209 // TryCatchStatementForReThrow below (which does not clear the pending |
| 5201 // message), rather than a TryCatchStatement. | 5210 // message), rather than a TryCatchStatement. |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 5221 try_block->statements()->Add(try_catch, zone()); | 5230 try_block->statements()->Add(try_catch, zone()); |
| 5222 | 5231 |
| 5223 try_finally = | 5232 try_finally = |
| 5224 factory()->NewTryFinallyStatement(try_block, maybe_close, nopos); | 5233 factory()->NewTryFinallyStatement(try_block, maybe_close, nopos); |
| 5225 } | 5234 } |
| 5226 | 5235 |
| 5227 target->statements()->Add(initialize_completion, zone()); | 5236 target->statements()->Add(initialize_completion, zone()); |
| 5228 target->statements()->Add(try_finally, zone()); | 5237 target->statements()->Add(try_finally, zone()); |
| 5229 } | 5238 } |
| 5230 | 5239 |
| 5231 void Parser::BuildIteratorCloseForCompletion(ZoneList<Statement*>* statements, | 5240 void Parser::BuildIteratorCloseForCompletion(Scope* scope, |
| 5241 ZoneList<Statement*>* statements, | |
| 5232 Variable* iterator, | 5242 Variable* iterator, |
| 5233 Expression* completion) { | 5243 Expression* completion) { |
| 5234 // | 5244 // |
| 5235 // This function adds two statements to [statements], corresponding to the | 5245 // This function adds two statements to [statements], corresponding to the |
| 5236 // following code: | 5246 // following code: |
| 5237 // | 5247 // |
| 5238 // let iteratorReturn = iterator.return; | 5248 // let iteratorReturn = iterator.return; |
| 5239 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { | 5249 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { |
| 5240 // if (completion === kThrowCompletion) { | 5250 // if (completion === kThrowCompletion) { |
| 5241 // if (!IS_CALLABLE(iteratorReturn)) { | 5251 // if (!IS_CALLABLE(iteratorReturn)) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5287 | 5297 |
| 5288 Expression* call = | 5298 Expression* call = |
| 5289 factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos); | 5299 factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos); |
| 5290 | 5300 |
| 5291 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos); | 5301 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos); |
| 5292 try_block->statements()->Add(factory()->NewExpressionStatement(call, nopos), | 5302 try_block->statements()->Add(factory()->NewExpressionStatement(call, nopos), |
| 5293 zone()); | 5303 zone()); |
| 5294 | 5304 |
| 5295 Block* catch_block = factory()->NewBlock(nullptr, 0, false, nopos); | 5305 Block* catch_block = factory()->NewBlock(nullptr, 0, false, nopos); |
| 5296 | 5306 |
| 5297 Scope* catch_scope = NewScope(CATCH_SCOPE); | 5307 Scope* catch_scope = NewScopeWithParent(scope, CATCH_SCOPE); |
| 5298 Variable* catch_variable = | 5308 Variable* catch_variable = |
| 5299 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, | 5309 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR, |
| 5300 kCreatedInitialized, NORMAL_VARIABLE); | 5310 kCreatedInitialized, NORMAL_VARIABLE); |
| 5301 catch_scope->set_is_hidden(); | 5311 catch_scope->set_is_hidden(); |
| 5302 | 5312 |
| 5303 try_call_return = factory()->NewTryCatchStatement( | 5313 try_call_return = factory()->NewTryCatchStatement( |
| 5304 try_block, catch_scope, catch_variable, catch_block, nopos); | 5314 try_block, catch_scope, catch_variable, catch_block, nopos); |
| 5305 } | 5315 } |
| 5306 | 5316 |
| 5307 // let output = %_Call(iteratorReturn, iterator); | 5317 // let output = %_Call(iteratorReturn, iterator); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5424 closing_condition = factory()->NewUnaryOperation( | 5434 closing_condition = factory()->NewUnaryOperation( |
| 5425 Token::NOT, factory()->NewBinaryOperation(Token::OR, lhs, rhs, nopos), | 5435 Token::NOT, factory()->NewBinaryOperation(Token::OR, lhs, rhs, nopos), |
| 5426 nopos); | 5436 nopos); |
| 5427 } | 5437 } |
| 5428 | 5438 |
| 5429 Block* final_loop = factory()->NewBlock(nullptr, 2, false, nopos); | 5439 Block* final_loop = factory()->NewBlock(nullptr, 2, false, nopos); |
| 5430 { | 5440 { |
| 5431 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos); | 5441 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos); |
| 5432 try_block->statements()->Add(loop, zone()); | 5442 try_block->statements()->Add(loop, zone()); |
| 5433 | 5443 |
| 5434 FinalizeIteratorUse(var_completion, closing_condition, loop->iterator(), | 5444 // The scope in which the parser creates this loop. |
| 5435 try_block, final_loop); | 5445 Scope* loop_scope = scope()->outer_scope(); |
| 5446 DCHECK_EQ(loop_scope->scope_type(), BLOCK_SCOPE); | |
| 5447 DCHECK_EQ(scope()->scope_type(), BLOCK_SCOPE); | |
| 5448 | |
| 5449 FinalizeIteratorUse(loop_scope, var_completion, closing_condition, | |
| 5450 loop->iterator(), try_block, final_loop); | |
| 5436 } | 5451 } |
| 5437 | 5452 |
| 5438 return final_loop; | 5453 return final_loop; |
| 5439 } | 5454 } |
| 5440 | 5455 |
| 5441 #undef CHECK_OK | 5456 #undef CHECK_OK |
| 5442 #undef CHECK_OK_VOID | 5457 #undef CHECK_OK_VOID |
| 5443 #undef CHECK_FAILED | 5458 #undef CHECK_FAILED |
| 5444 | 5459 |
| 5445 } // namespace internal | 5460 } // namespace internal |
| 5446 } // namespace v8 | 5461 } // namespace v8 |
| OLD | NEW |