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 "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
| 9 #include "src/ast/ast-expression-rewriter.h" | |
| 9 #include "src/ast/ast-expression-visitor.h" | 10 #include "src/ast/ast-expression-visitor.h" |
| 10 #include "src/ast/ast-literal-reindexer.h" | 11 #include "src/ast/ast-literal-reindexer.h" |
| 11 #include "src/ast/scopeinfo.h" | 12 #include "src/ast/scopeinfo.h" |
| 12 #include "src/bailout-reason.h" | 13 #include "src/bailout-reason.h" |
| 13 #include "src/base/platform/platform.h" | 14 #include "src/base/platform/platform.h" |
| 14 #include "src/bootstrapper.h" | 15 #include "src/bootstrapper.h" |
| 15 #include "src/char-predicates-inl.h" | 16 #include "src/char-predicates-inl.h" |
| 16 #include "src/codegen.h" | 17 #include "src/codegen.h" |
| 17 #include "src/compiler.h" | 18 #include "src/compiler.h" |
| 18 #include "src/messages.h" | 19 #include "src/messages.h" |
| (...skipping 5385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5404 | 5405 |
| 5405 | 5406 |
| 5406 ObjectLiteralProperty* ParserTraits::RewriteNonPatternObjectLiteralProperty( | 5407 ObjectLiteralProperty* ParserTraits::RewriteNonPatternObjectLiteralProperty( |
| 5407 ObjectLiteralProperty* property, const ExpressionClassifier* classifier, | 5408 ObjectLiteralProperty* property, const ExpressionClassifier* classifier, |
| 5408 bool* ok) { | 5409 bool* ok) { |
| 5409 return parser_->RewriteNonPatternObjectLiteralProperty(property, classifier, | 5410 return parser_->RewriteNonPatternObjectLiteralProperty(property, classifier, |
| 5410 ok); | 5411 ok); |
| 5411 } | 5412 } |
| 5412 | 5413 |
| 5413 | 5414 |
| 5415 class NonPatternRewriter : public AstExpressionRewriter { | |
| 5416 public: | |
| 5417 NonPatternRewriter(uintptr_t stack_limit, Parser* parser) | |
| 5418 : AstExpressionRewriter(stack_limit), parser_(parser) {} | |
| 5419 ~NonPatternRewriter() override {} | |
| 5420 | |
| 5421 private: | |
| 5422 bool RewriteExpression(Expression* expr) override { | |
| 5423 // Rewrite only what could have been a pattern but is not. | |
| 5424 if (expr->IsArrayLiteral()) { | |
| 5425 // Spread rewriting in array literals. | |
| 5426 ArrayLiteral* lit = expr->AsArrayLiteral(); | |
| 5427 VisitExpressions(lit->values()); | |
| 5428 replacement_ = parser_->RewriteSpreads(lit); | |
| 5429 return false; | |
| 5430 } | |
| 5431 if (expr->IsObjectLiteral()) { | |
| 5432 return true; | |
| 5433 } | |
| 5434 if (expr->IsBinaryOperation() && | |
| 5435 expr->AsBinaryOperation()->op() == Token::COMMA) { | |
| 5436 return true; | |
| 5437 } | |
| 5438 // Everything else does not need rewriting. | |
| 5439 return false; | |
| 5440 } | |
| 5441 | |
| 5442 Parser* parser_; | |
| 5443 }; | |
| 5444 | |
| 5445 | |
| 5414 Expression* Parser::RewriteNonPattern(Expression* expr, | 5446 Expression* Parser::RewriteNonPattern(Expression* expr, |
| 5415 const ExpressionClassifier* classifier, | 5447 const ExpressionClassifier* classifier, |
| 5416 bool* ok) { | 5448 bool* ok) { |
| 5417 // For the time being, this does no rewriting at all. | |
| 5418 ValidateExpression(classifier, ok); | 5449 ValidateExpression(classifier, ok); |
| 5419 return expr; | 5450 if (!*ok) return expr; |
| 5451 NonPatternRewriter rewriter(stack_limit_, this); | |
| 5452 Expression* result = reinterpret_cast<Expression*>(rewriter.Rewrite(expr)); | |
| 5453 DCHECK_NOT_NULL(result); | |
| 5454 return result; | |
|
nickie
2016/01/14 16:35:02
This is almost trivial; rewriting happens after va
| |
| 5420 } | 5455 } |
| 5421 | 5456 |
| 5422 | 5457 |
| 5423 ZoneList<Expression*>* Parser::RewriteNonPatternArguments( | 5458 ZoneList<Expression*>* Parser::RewriteNonPatternArguments( |
| 5424 ZoneList<Expression*>* args, const ExpressionClassifier* classifier, | 5459 ZoneList<Expression*>* args, const ExpressionClassifier* classifier, |
| 5425 bool* ok) { | 5460 bool* ok) { |
| 5426 // For the time being, this does no rewriting at all. | |
| 5427 ValidateExpression(classifier, ok); | 5461 ValidateExpression(classifier, ok); |
| 5462 if (!*ok) return args; | |
| 5463 for (int i = 0; i < args->length(); i++) { | |
| 5464 NonPatternRewriter rewriter(stack_limit_, this); | |
| 5465 Expression* result = | |
| 5466 reinterpret_cast<Expression*>(rewriter.Rewrite(args->at(i))); | |
| 5467 DCHECK_NOT_NULL(result); | |
| 5468 args->Set(i, result); | |
| 5469 } | |
|
nickie
2016/01/14 16:35:02
This is the only non-trivial addition to this reba
| |
| 5428 return args; | 5470 return args; |
| 5429 } | 5471 } |
| 5430 | 5472 |
| 5431 | 5473 |
| 5432 ObjectLiteralProperty* Parser::RewriteNonPatternObjectLiteralProperty( | 5474 ObjectLiteralProperty* Parser::RewriteNonPatternObjectLiteralProperty( |
| 5433 ObjectLiteralProperty* property, const ExpressionClassifier* classifier, | 5475 ObjectLiteralProperty* property, const ExpressionClassifier* classifier, |
| 5434 bool* ok) { | 5476 bool* ok) { |
| 5435 if (property != nullptr) { | 5477 if (property != nullptr) { |
| 5436 Expression* key = RewriteNonPattern(property->key(), classifier, ok); | 5478 Expression* key = RewriteNonPattern(property->key(), classifier, ok); |
| 5437 property->set_key(key); | 5479 property->set_key(key); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 5455 pair.assignment->AsRewritableAssignmentExpression(); | 5497 pair.assignment->AsRewritableAssignmentExpression(); |
| 5456 Scope* scope = pair.scope; | 5498 Scope* scope = pair.scope; |
| 5457 DCHECK_NOT_NULL(to_rewrite); | 5499 DCHECK_NOT_NULL(to_rewrite); |
| 5458 if (!to_rewrite->is_rewritten()) { | 5500 if (!to_rewrite->is_rewritten()) { |
| 5459 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope); | 5501 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope); |
| 5460 } | 5502 } |
| 5461 } | 5503 } |
| 5462 } | 5504 } |
| 5463 | 5505 |
| 5464 | 5506 |
| 5507 Expression* Parser::RewriteSpreads(ArrayLiteral* lit) { | |
| 5508 // Array literals containing spreads are rewritten using do expressions, e.g. | |
| 5509 // [1, 2, 3, ...x, 4, ...y, 5] | |
| 5510 // is roughly rewritten as: | |
| 5511 // do { | |
| 5512 // $R = [1, 2, 3]; | |
| 5513 // for ($i of x) %AppendElement($R, $i); | |
| 5514 // %AppendElement($R, 4); | |
| 5515 // for ($j of y) %AppendElement($R, $j); | |
| 5516 // %AppendElement($R, 5); | |
| 5517 // $R | |
| 5518 // } | |
| 5519 // where $R, $i and $j are fresh temporary variables. | |
| 5520 ZoneList<Expression*>::iterator s = lit->FirstSpread(); | |
| 5521 if (s == lit->EndValue()) return nullptr; // no spread, no rewriting... | |
| 5522 Variable* result = | |
| 5523 scope_->NewTemporary(ast_value_factory()->dot_result_string()); | |
| 5524 // NOTE: The value assigned to R is the whole original array literal, | |
| 5525 // spreads included. This will be fixed before the rewritten AST is returned. | |
| 5526 // $R = lit | |
| 5527 Expression* init_result = | |
| 5528 factory()->NewAssignment(Token::INIT, factory()->NewVariableProxy(result), | |
| 5529 lit, RelocInfo::kNoPosition); | |
| 5530 Block* do_block = | |
| 5531 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition); | |
| 5532 do_block->statements()->Add( | |
| 5533 factory()->NewExpressionStatement(init_result, RelocInfo::kNoPosition), | |
| 5534 zone()); | |
| 5535 // Traverse the array literal starting from the first spread. | |
| 5536 while (s != lit->EndValue()) { | |
| 5537 Expression* value = *s++; | |
| 5538 Spread* spread = value->AsSpread(); | |
| 5539 if (spread == nullptr) { | |
| 5540 // If the element is not a spread, we're adding a single: | |
| 5541 // %AppendElement($R, value) | |
| 5542 ZoneList<Expression*>* append_element_args = NewExpressionList(2, zone()); | |
| 5543 append_element_args->Add(factory()->NewVariableProxy(result), zone()); | |
| 5544 append_element_args->Add(value, zone()); | |
| 5545 do_block->statements()->Add( | |
| 5546 factory()->NewExpressionStatement( | |
| 5547 factory()->NewCallRuntime(Runtime::kAppendElement, | |
| 5548 append_element_args, | |
| 5549 RelocInfo::kNoPosition), | |
| 5550 RelocInfo::kNoPosition), | |
| 5551 zone()); | |
| 5552 } else { | |
| 5553 // If it's a spread, we're adding a for/of loop iterating through it. | |
| 5554 Variable* each = | |
| 5555 scope_->NewTemporary(ast_value_factory()->dot_for_string()); | |
| 5556 Expression* subject = spread->expression(); | |
| 5557 Variable* iterator = | |
| 5558 scope_->NewTemporary(ast_value_factory()->dot_iterator_string()); | |
| 5559 Variable* element = | |
| 5560 scope_->NewTemporary(ast_value_factory()->dot_result_string()); | |
| 5561 // iterator = subject[Symbol.iterator]() | |
| 5562 Expression* assign_iterator = factory()->NewAssignment( | |
| 5563 Token::ASSIGN, factory()->NewVariableProxy(iterator), | |
| 5564 GetIterator(subject, factory(), spread->expression_position()), | |
| 5565 subject->position()); | |
| 5566 // !%_IsJSReceiver(element = iterator.next()) && | |
| 5567 // %ThrowIteratorResultNotAnObject(element) | |
| 5568 Expression* next_element; | |
| 5569 { | |
| 5570 // element = iterator.next() | |
| 5571 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | |
| 5572 next_element = BuildIteratorNextResult(iterator_proxy, element, | |
| 5573 spread->expression_position()); | |
| 5574 } | |
| 5575 // element.done | |
| 5576 Expression* element_done; | |
| 5577 { | |
| 5578 Expression* done_literal = factory()->NewStringLiteral( | |
| 5579 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | |
| 5580 Expression* element_proxy = factory()->NewVariableProxy(element); | |
| 5581 element_done = factory()->NewProperty(element_proxy, done_literal, | |
| 5582 RelocInfo::kNoPosition); | |
| 5583 } | |
| 5584 // each = element.value | |
| 5585 Expression* assign_each; | |
| 5586 { | |
| 5587 Expression* value_literal = factory()->NewStringLiteral( | |
| 5588 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | |
| 5589 Expression* element_proxy = factory()->NewVariableProxy(element); | |
| 5590 Expression* element_value = factory()->NewProperty( | |
| 5591 element_proxy, value_literal, RelocInfo::kNoPosition); | |
| 5592 assign_each = factory()->NewAssignment( | |
| 5593 Token::ASSIGN, factory()->NewVariableProxy(each), element_value, | |
| 5594 RelocInfo::kNoPosition); | |
| 5595 } | |
| 5596 // %AppendElement($R, each) | |
| 5597 Statement* append_body; | |
| 5598 { | |
| 5599 ZoneList<Expression*>* append_element_args = | |
| 5600 NewExpressionList(2, zone()); | |
| 5601 append_element_args->Add(factory()->NewVariableProxy(result), zone()); | |
| 5602 append_element_args->Add(factory()->NewVariableProxy(each), zone()); | |
| 5603 append_body = factory()->NewExpressionStatement( | |
| 5604 factory()->NewCallRuntime(Runtime::kAppendElement, | |
| 5605 append_element_args, | |
| 5606 RelocInfo::kNoPosition), | |
| 5607 RelocInfo::kNoPosition); | |
| 5608 } | |
| 5609 // for (each of spread) %AppendElement($R, each) | |
| 5610 ForEachStatement* loop = factory()->NewForEachStatement( | |
| 5611 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition); | |
| 5612 ForOfStatement* for_of = loop->AsForOfStatement(); | |
| 5613 for_of->Initialize(factory()->NewVariableProxy(each), subject, | |
| 5614 append_body, assign_iterator, next_element, | |
| 5615 element_done, assign_each); | |
| 5616 do_block->statements()->Add(for_of, zone()); | |
| 5617 } | |
| 5618 } | |
| 5619 // Now, rewind the original array literal to truncate everything from the | |
| 5620 // first spread (included) until the end. This fixes $R's initialization. | |
| 5621 lit->RewindSpreads(); | |
| 5622 return factory()->NewDoExpression(do_block, result, lit->position()); | |
| 5623 } | |
| 5624 | |
| 5625 | |
| 5465 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { | 5626 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { |
| 5466 DCHECK(expr->IsRewritableAssignmentExpression()); | 5627 DCHECK(expr->IsRewritableAssignmentExpression()); |
| 5467 parser_->function_state_->AddDestructuringAssignment( | 5628 parser_->function_state_->AddDestructuringAssignment( |
| 5468 Parser::DestructuringAssignment(expr, parser_->scope_)); | 5629 Parser::DestructuringAssignment(expr, parser_->scope_)); |
| 5469 } | 5630 } |
| 5470 | 5631 |
| 5471 | 5632 |
| 5472 void ParserTraits::SetFunctionNameFromPropertyName( | 5633 void ParserTraits::SetFunctionNameFromPropertyName( |
| 5473 ObjectLiteralProperty* property, const AstRawString* name) { | 5634 ObjectLiteralProperty* property, const AstRawString* name) { |
| 5474 Expression* value = property->value(); | 5635 Expression* value = property->value(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5525 auto class_literal = value->AsClassLiteral(); | 5686 auto class_literal = value->AsClassLiteral(); |
| 5526 if (class_literal->raw_name() == nullptr) { | 5687 if (class_literal->raw_name() == nullptr) { |
| 5527 class_literal->set_raw_name(name); | 5688 class_literal->set_raw_name(name); |
| 5528 } | 5689 } |
| 5529 } | 5690 } |
| 5530 } | 5691 } |
| 5531 | 5692 |
| 5532 | 5693 |
| 5533 } // namespace internal | 5694 } // namespace internal |
| 5534 } // namespace v8 | 5695 } // namespace v8 |
| OLD | NEW |