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

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

Issue 1740293002: Remove duplicated ForOfStatement init code code from RewriteSpreads (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebased Created 4 years, 9 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') | no next file » | 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-rewriter.h"
10 #include "src/ast/ast-expression-visitor.h" 10 #include "src/ast/ast-expression-visitor.h"
(...skipping 3232 matching lines...) Expand 10 before | Expand all | Expand 10 after
3243 throw_arguments->Add(result_proxy_again, zone()); 3243 throw_arguments->Add(result_proxy_again, zone());
3244 Expression* throw_call = factory()->NewCallRuntime( 3244 Expression* throw_call = factory()->NewCallRuntime(
3245 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); 3245 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos);
3246 3246
3247 return factory()->NewBinaryOperation( 3247 return factory()->NewBinaryOperation(
3248 Token::AND, 3248 Token::AND,
3249 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), 3249 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos),
3250 throw_call, pos); 3250 throw_call, pos);
3251 } 3251 }
3252 3252
3253
3254 void Parser::InitializeForEachStatement(ForEachStatement* stmt, 3253 void Parser::InitializeForEachStatement(ForEachStatement* stmt,
3255 Expression* each, Expression* subject, 3254 Expression* each, Expression* subject,
3256 Statement* body, 3255 Statement* body) {
3257 bool is_destructuring) {
3258 DCHECK(!is_destructuring || allow_harmony_destructuring_assignment());
3259 ForOfStatement* for_of = stmt->AsForOfStatement(); 3256 ForOfStatement* for_of = stmt->AsForOfStatement();
3260
3261 if (for_of != NULL) { 3257 if (for_of != NULL) {
3262 Variable* iterator = scope_->NewTemporary( 3258 InitializeForOfStatement(for_of, each, subject, body,
3263 ast_value_factory()->dot_iterator_string()); 3259 RelocInfo::kNoPosition);
3264 Variable* result = scope_->NewTemporary(
3265 ast_value_factory()->dot_result_string());
3266
3267 Expression* assign_iterator;
3268 Expression* next_result;
3269 Expression* result_done;
3270 Expression* assign_each;
3271
3272 // iterator = subject[Symbol.iterator]()
3273 // Hackily disambiguate o from o.next and o [Symbol.iterator]().
3274 // TODO(verwaest): Come up with a better solution.
3275 assign_iterator = factory()->NewAssignment(
3276 Token::ASSIGN, factory()->NewVariableProxy(iterator),
3277 GetIterator(subject, factory(), subject->position() - 2),
3278 subject->position());
3279
3280 // !%_IsJSReceiver(result = iterator.next()) &&
3281 // %ThrowIteratorResultNotAnObject(result)
3282 {
3283 // result = iterator.next()
3284 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
3285 // Hackily disambiguate o from o.next and o [Symbol.iterator]().
3286 // TODO(verwaest): Come up with a better solution.
3287 next_result = BuildIteratorNextResult(iterator_proxy, result,
3288 subject->position() - 1);
3289 }
3290
3291 // result.done
3292 {
3293 Expression* done_literal = factory()->NewStringLiteral(
3294 ast_value_factory()->done_string(), RelocInfo::kNoPosition);
3295 Expression* result_proxy = factory()->NewVariableProxy(result);
3296 result_done = factory()->NewProperty(
3297 result_proxy, done_literal, RelocInfo::kNoPosition);
3298 }
3299
3300 // each = result.value
3301 {
3302 Expression* value_literal = factory()->NewStringLiteral(
3303 ast_value_factory()->value_string(), RelocInfo::kNoPosition);
3304 Expression* result_proxy = factory()->NewVariableProxy(result);
3305 Expression* result_value = factory()->NewProperty(
3306 result_proxy, value_literal, RelocInfo::kNoPosition);
3307 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
3308 RelocInfo::kNoPosition);
3309 if (is_destructuring) {
3310 assign_each = PatternRewriter::RewriteDestructuringAssignment(
3311 this, assign_each->AsAssignment(), scope_);
3312 }
3313 }
3314
3315 for_of->Initialize(each, subject, body,
3316 iterator,
3317 assign_iterator,
3318 next_result,
3319 result_done,
3320 assign_each);
3321 } else { 3260 } else {
3322 if (is_destructuring) { 3261 if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
3262 DCHECK(allow_harmony_destructuring_assignment());
3323 Variable* temp = 3263 Variable* temp =
3324 scope_->NewTemporary(ast_value_factory()->empty_string()); 3264 scope_->NewTemporary(ast_value_factory()->empty_string());
3325 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); 3265 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
3326 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment( 3266 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment(
3327 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy, 3267 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy,
3328 RelocInfo::kNoPosition), 3268 RelocInfo::kNoPosition),
3329 scope_); 3269 scope_);
3330 auto block = 3270 auto block =
3331 factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition); 3271 factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition);
3332 block->statements()->Add(factory()->NewExpressionStatement( 3272 block->statements()->Add(factory()->NewExpressionStatement(
3333 assign_each, RelocInfo::kNoPosition), 3273 assign_each, RelocInfo::kNoPosition),
3334 zone()); 3274 zone());
3335 block->statements()->Add(body, zone()); 3275 block->statements()->Add(body, zone());
3336 body = block; 3276 body = block;
3337 each = factory()->NewVariableProxy(temp); 3277 each = factory()->NewVariableProxy(temp);
3338 } 3278 }
3339 stmt->Initialize(each, subject, body); 3279 stmt->Initialize(each, subject, body);
3340 } 3280 }
3341 } 3281 }
3342 3282
3283 void Parser::InitializeForOfStatement(ForOfStatement* for_of, Expression* each,
3284 Expression* iterable, Statement* body,
3285 int iterable_pos) {
3286 Variable* iterator =
3287 scope_->NewTemporary(ast_value_factory()->dot_iterator_string());
3288 Variable* result =
3289 scope_->NewTemporary(ast_value_factory()->dot_result_string());
3290
3291 Expression* assign_iterator;
3292 Expression* next_result;
3293 Expression* result_done;
3294 Expression* assign_each;
3295
3296 // Hackily disambiguate o from o.next and o [Symbol.iterator]().
3297 // TODO(verwaest): Come up with a better solution.
3298 int get_iterator_pos = iterable_pos != RelocInfo::kNoPosition
3299 ? iterable_pos
3300 : iterable->position() - 2;
3301 int next_result_pos = iterable_pos != RelocInfo::kNoPosition
3302 ? iterable_pos
3303 : iterable->position() - 1;
3304
3305 // iterator = iterable[Symbol.iterator]()
3306 assign_iterator = factory()->NewAssignment(
3307 Token::ASSIGN, factory()->NewVariableProxy(iterator),
3308 GetIterator(iterable, factory(), get_iterator_pos), iterable->position());
3309
3310 // !%_IsJSReceiver(result = iterator.next()) &&
3311 // %ThrowIteratorResultNotAnObject(result)
3312 {
3313 // result = iterator.next()
3314 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
3315 next_result =
3316 BuildIteratorNextResult(iterator_proxy, result, next_result_pos);
3317 }
3318
3319 // result.done
3320 {
3321 Expression* done_literal = factory()->NewStringLiteral(
3322 ast_value_factory()->done_string(), RelocInfo::kNoPosition);
3323 Expression* result_proxy = factory()->NewVariableProxy(result);
3324 result_done = factory()->NewProperty(result_proxy, done_literal,
3325 RelocInfo::kNoPosition);
3326 }
3327
3328 // each = result.value
3329 {
3330 Expression* value_literal = factory()->NewStringLiteral(
3331 ast_value_factory()->value_string(), RelocInfo::kNoPosition);
3332 Expression* result_proxy = factory()->NewVariableProxy(result);
3333 Expression* result_value = factory()->NewProperty(
3334 result_proxy, value_literal, RelocInfo::kNoPosition);
3335 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
3336 RelocInfo::kNoPosition);
3337 if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
3338 DCHECK(allow_harmony_destructuring_assignment());
3339 assign_each = PatternRewriter::RewriteDestructuringAssignment(
3340 this, assign_each->AsAssignment(), scope_);
3341 }
3342 }
3343
3344 for_of->Initialize(each, iterable, body, iterator, assign_iterator,
3345 next_result, result_done, assign_each);
3346 }
3347
3343 Statement* Parser::DesugarLexicalBindingsInForStatement( 3348 Statement* Parser::DesugarLexicalBindingsInForStatement(
3344 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names, 3349 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names,
3345 ForStatement* loop, Statement* init, Expression* cond, Statement* next, 3350 ForStatement* loop, Statement* init, Expression* cond, Statement* next,
3346 Statement* body, bool* ok) { 3351 Statement* body, bool* ok) {
3347 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are 3352 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are
3348 // copied into a new environment. Moreover, the "next" statement must be 3353 // copied into a new environment. Moreover, the "next" statement must be
3349 // evaluated not in the environment of the just completed iteration but in 3354 // evaluated not in the environment of the just completed iteration but in
3350 // that of the upcoming one. We achieve this with the following desugaring. 3355 // that of the upcoming one. We achieve this with the following desugaring.
3351 // Extra care is needed to preserve the completion value of the original loop. 3356 // Extra care is needed to preserve the completion value of the original loop.
3352 // 3357 //
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after
3737 each_initialization_block, &descriptor, &decl, 3742 each_initialization_block, &descriptor, &decl,
3738 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings 3743 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings
3739 : nullptr, 3744 : nullptr,
3740 CHECK_OK); 3745 CHECK_OK);
3741 } 3746 }
3742 3747
3743 body_block->statements()->Add(each_initialization_block, zone()); 3748 body_block->statements()->Add(each_initialization_block, zone());
3744 body_block->statements()->Add(body, zone()); 3749 body_block->statements()->Add(body, zone());
3745 VariableProxy* temp_proxy = 3750 VariableProxy* temp_proxy =
3746 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); 3751 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
3747 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block, 3752 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
3748 false);
3749 } 3753 }
3750 body_scope->set_end_position(scanner()->location().end_pos); 3754 body_scope->set_end_position(scanner()->location().end_pos);
3751 body_scope = body_scope->FinalizeBlockScope(); 3755 body_scope = body_scope->FinalizeBlockScope();
3752 body_block->set_scope(body_scope); 3756 body_block->set_scope(body_scope);
3753 3757
3754 // Create a TDZ for any lexically-bound names. 3758 // Create a TDZ for any lexically-bound names.
3755 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { 3759 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) {
3756 DCHECK_NULL(init_block); 3760 DCHECK_NULL(init_block);
3757 3761
3758 init_block = 3762 init_block =
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
3836 RewriteNonPattern(&classifier, CHECK_OK); 3840 RewriteNonPattern(&classifier, CHECK_OK);
3837 } else { 3841 } else {
3838 enumerable = ParseExpression(true, CHECK_OK); 3842 enumerable = ParseExpression(true, CHECK_OK);
3839 } 3843 }
3840 3844
3841 Expect(Token::RPAREN, CHECK_OK); 3845 Expect(Token::RPAREN, CHECK_OK);
3842 3846
3843 // For legacy compat reasons, give for loops similar treatment to 3847 // For legacy compat reasons, give for loops similar treatment to
3844 // if statements in allowing a function declaration for a body 3848 // if statements in allowing a function declaration for a body
3845 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK); 3849 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
3846 InitializeForEachStatement(loop, expression, enumerable, body, 3850 InitializeForEachStatement(loop, expression, enumerable, body);
3847 is_destructuring);
3848 3851
3849 Statement* final_loop = loop->IsForOfStatement() 3852 Statement* final_loop = loop->IsForOfStatement()
3850 ? FinalizeForOfStatement( 3853 ? FinalizeForOfStatement(
3851 loop->AsForOfStatement(), RelocInfo::kNoPosition) 3854 loop->AsForOfStatement(), RelocInfo::kNoPosition)
3852 : loop; 3855 : loop;
3853 3856
3854 for_scope->set_end_position(scanner()->location().end_pos); 3857 for_scope->set_end_position(scanner()->location().end_pos);
3855 for_scope = for_scope->FinalizeBlockScope(); 3858 for_scope = for_scope->FinalizeBlockScope();
3856 DCHECK(for_scope == nullptr); 3859 DCHECK(for_scope == nullptr);
3857 return final_loop; 3860 return final_loop;
(...skipping 1794 matching lines...) Expand 10 before | Expand all | Expand 10 after
5652 factory()->NewCallRuntime(Runtime::kAppendElement, 5655 factory()->NewCallRuntime(Runtime::kAppendElement,
5653 append_element_args, 5656 append_element_args,
5654 RelocInfo::kNoPosition), 5657 RelocInfo::kNoPosition),
5655 RelocInfo::kNoPosition), 5658 RelocInfo::kNoPosition),
5656 zone()); 5659 zone());
5657 } else { 5660 } else {
5658 // If it's a spread, we're adding a for/of loop iterating through it. 5661 // If it's a spread, we're adding a for/of loop iterating through it.
5659 Variable* each = 5662 Variable* each =
5660 scope_->NewTemporary(ast_value_factory()->dot_for_string()); 5663 scope_->NewTemporary(ast_value_factory()->dot_for_string());
5661 Expression* subject = spread->expression(); 5664 Expression* subject = spread->expression();
5662 Variable* iterator =
5663 scope_->NewTemporary(ast_value_factory()->dot_iterator_string());
5664 Variable* element =
5665 scope_->NewTemporary(ast_value_factory()->dot_result_string());
5666 // iterator = subject[Symbol.iterator]()
5667 Expression* assign_iterator = factory()->NewAssignment(
5668 Token::ASSIGN, factory()->NewVariableProxy(iterator),
5669 GetIterator(subject, factory(), spread->expression_position()),
5670 subject->position());
5671 // !%_IsJSReceiver(element = iterator.next()) &&
5672 // %ThrowIteratorResultNotAnObject(element)
5673 Expression* next_element;
5674 {
5675 // element = iterator.next()
5676 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
5677 next_element = BuildIteratorNextResult(iterator_proxy, element,
5678 spread->expression_position());
5679 }
5680 // element.done
5681 Expression* element_done;
5682 {
5683 Expression* done_literal = factory()->NewStringLiteral(
5684 ast_value_factory()->done_string(), RelocInfo::kNoPosition);
5685 Expression* element_proxy = factory()->NewVariableProxy(element);
5686 element_done = factory()->NewProperty(element_proxy, done_literal,
5687 RelocInfo::kNoPosition);
5688 }
5689 // each = element.value
5690 Expression* assign_each;
5691 {
5692 Expression* value_literal = factory()->NewStringLiteral(
5693 ast_value_factory()->value_string(), RelocInfo::kNoPosition);
5694 Expression* element_proxy = factory()->NewVariableProxy(element);
5695 Expression* element_value = factory()->NewProperty(
5696 element_proxy, value_literal, RelocInfo::kNoPosition);
5697 assign_each = factory()->NewAssignment(
5698 Token::ASSIGN, factory()->NewVariableProxy(each), element_value,
5699 RelocInfo::kNoPosition);
5700 }
5701 // %AppendElement($R, each) 5665 // %AppendElement($R, each)
5702 Statement* append_body; 5666 Statement* append_body;
5703 { 5667 {
5704 ZoneList<Expression*>* append_element_args = 5668 ZoneList<Expression*>* append_element_args =
5705 NewExpressionList(2, zone()); 5669 NewExpressionList(2, zone());
5706 append_element_args->Add(factory()->NewVariableProxy(result), zone()); 5670 append_element_args->Add(factory()->NewVariableProxy(result), zone());
5707 append_element_args->Add(factory()->NewVariableProxy(each), zone()); 5671 append_element_args->Add(factory()->NewVariableProxy(each), zone());
5708 append_body = factory()->NewExpressionStatement( 5672 append_body = factory()->NewExpressionStatement(
5709 factory()->NewCallRuntime(Runtime::kAppendElement, 5673 factory()->NewCallRuntime(Runtime::kAppendElement,
5710 append_element_args, 5674 append_element_args,
5711 RelocInfo::kNoPosition), 5675 RelocInfo::kNoPosition),
5712 RelocInfo::kNoPosition); 5676 RelocInfo::kNoPosition);
5713 } 5677 }
5714 // for (each of spread) %AppendElement($R, each) 5678 // for (each of spread) %AppendElement($R, each)
5715 ForEachStatement* loop = factory()->NewForEachStatement( 5679 ForEachStatement* loop = factory()->NewForEachStatement(
5716 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition); 5680 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition);
5717 ForOfStatement* for_of = loop->AsForOfStatement(); 5681 InitializeForOfStatement(loop->AsForOfStatement(),
5718 for_of->Initialize(factory()->NewVariableProxy(each), subject, 5682 factory()->NewVariableProxy(each), subject,
5719 append_body, iterator, assign_iterator, next_element, 5683 append_body, spread->expression_position());
5720 element_done, assign_each); 5684 do_block->statements()->Add(loop, zone());
5721 do_block->statements()->Add(for_of, zone());
5722 } 5685 }
5723 } 5686 }
5724 // Now, rewind the original array literal to truncate everything from the 5687 // Now, rewind the original array literal to truncate everything from the
5725 // first spread (included) until the end. This fixes $R's initialization. 5688 // first spread (included) until the end. This fixes $R's initialization.
5726 lit->RewindSpreads(); 5689 lit->RewindSpreads();
5727 return factory()->NewDoExpression(do_block, result, lit->position()); 5690 return factory()->NewDoExpression(do_block, result, lit->position());
5728 } 5691 }
5729 5692
5730 5693
5731 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { 5694 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) {
(...skipping 1198 matching lines...) Expand 10 before | Expand all | Expand 10 after
6930 Expression* do_each = 6893 Expression* do_each =
6931 factory->NewDoExpression(new_assign_each, var_each, nopos); 6894 factory->NewDoExpression(new_assign_each, var_each, nopos);
6932 loop->set_assign_each(do_each); 6895 loop->set_assign_each(do_each);
6933 6896
6934 return final_loop; 6897 return final_loop;
6935 } 6898 }
6936 6899
6937 6900
6938 } // namespace internal 6901 } // namespace internal
6939 } // namespace v8 6902 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698