Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Side by Side Diff: src/parsing/parser.cc

Issue 1564083002: Add spread rewriting (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase (just see comments) Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698