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

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 3239 matching lines...) Expand 10 before | Expand all | Expand 10 after
3250 throw_arguments->Add(result_proxy_again, zone()); 3250 throw_arguments->Add(result_proxy_again, zone());
3251 Expression* throw_call = factory()->NewCallRuntime( 3251 Expression* throw_call = factory()->NewCallRuntime(
3252 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); 3252 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos);
3253 3253
3254 return factory()->NewBinaryOperation( 3254 return factory()->NewBinaryOperation(
3255 Token::AND, 3255 Token::AND,
3256 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), 3256 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos),
3257 throw_call, pos); 3257 throw_call, pos);
3258 } 3258 }
3259 3259
3260
3261 void Parser::InitializeForEachStatement(ForEachStatement* stmt, 3260 void Parser::InitializeForEachStatement(ForEachStatement* stmt,
3262 Expression* each, Expression* subject, 3261 Expression* each, Expression* subject,
3263 Statement* body, 3262 Statement* body) {
3264 bool is_destructuring) {
3265 DCHECK(!is_destructuring || allow_harmony_destructuring_assignment());
3266 ForOfStatement* for_of = stmt->AsForOfStatement(); 3263 ForOfStatement* for_of = stmt->AsForOfStatement();
3267
3268 if (for_of != NULL) { 3264 if (for_of != NULL) {
3269 Variable* iterator = scope_->NewTemporary( 3265 InitializeForOfStatement(for_of, each, subject, body, true);
3270 ast_value_factory()->dot_iterator_string());
3271 Variable* result = scope_->NewTemporary(
3272 ast_value_factory()->dot_result_string());
3273
3274 Expression* assign_iterator;
3275 Expression* next_result;
3276 Expression* result_done;
3277 Expression* assign_each;
3278
3279 // iterator = subject[Symbol.iterator]()
3280 // Hackily disambiguate o from o.next and o [Symbol.iterator]().
3281 // TODO(verwaest): Come up with a better solution.
3282 assign_iterator = factory()->NewAssignment(
3283 Token::ASSIGN, factory()->NewVariableProxy(iterator),
3284 GetIterator(subject, factory(), subject->position() - 2),
3285 subject->position());
3286
3287 // !%_IsJSReceiver(result = iterator.next()) &&
3288 // %ThrowIteratorResultNotAnObject(result)
3289 {
3290 // result = iterator.next()
3291 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
3292 // Hackily disambiguate o from o.next and o [Symbol.iterator]().
3293 // TODO(verwaest): Come up with a better solution.
3294 next_result = BuildIteratorNextResult(iterator_proxy, result,
3295 subject->position() - 1);
3296 }
3297
3298 // result.done
3299 {
3300 Expression* done_literal = factory()->NewStringLiteral(
3301 ast_value_factory()->done_string(), RelocInfo::kNoPosition);
3302 Expression* result_proxy = factory()->NewVariableProxy(result);
3303 result_done = factory()->NewProperty(
3304 result_proxy, done_literal, RelocInfo::kNoPosition);
3305 }
3306
3307 // each = result.value
3308 {
3309 Expression* value_literal = factory()->NewStringLiteral(
3310 ast_value_factory()->value_string(), RelocInfo::kNoPosition);
3311 Expression* result_proxy = factory()->NewVariableProxy(result);
3312 Expression* result_value = factory()->NewProperty(
3313 result_proxy, value_literal, RelocInfo::kNoPosition);
3314 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
3315 RelocInfo::kNoPosition);
3316 if (is_destructuring) {
3317 assign_each = PatternRewriter::RewriteDestructuringAssignment(
3318 this, assign_each->AsAssignment(), scope_);
3319 }
3320 }
3321
3322 for_of->Initialize(each, subject, body,
3323 iterator,
3324 assign_iterator,
3325 next_result,
3326 result_done,
3327 assign_each);
3328 } else { 3266 } else {
3329 if (is_destructuring) { 3267 if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
3268 DCHECK(allow_harmony_destructuring_assignment());
3330 Variable* temp = 3269 Variable* temp =
3331 scope_->NewTemporary(ast_value_factory()->empty_string()); 3270 scope_->NewTemporary(ast_value_factory()->empty_string());
3332 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); 3271 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
3333 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment( 3272 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment(
3334 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy, 3273 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy,
3335 RelocInfo::kNoPosition), 3274 RelocInfo::kNoPosition),
3336 scope_); 3275 scope_);
3337 auto block = 3276 auto block =
3338 factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition); 3277 factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition);
3339 block->statements()->Add(factory()->NewExpressionStatement( 3278 block->statements()->Add(factory()->NewExpressionStatement(
3340 assign_each, RelocInfo::kNoPosition), 3279 assign_each, RelocInfo::kNoPosition),
3341 zone()); 3280 zone());
3342 block->statements()->Add(body, zone()); 3281 block->statements()->Add(body, zone());
3343 body = block; 3282 body = block;
3344 each = factory()->NewVariableProxy(temp); 3283 each = factory()->NewVariableProxy(temp);
3345 } 3284 }
3346 stmt->Initialize(each, subject, body); 3285 stmt->Initialize(each, subject, body);
3347 } 3286 }
3348 } 3287 }
3349 3288
3289 void Parser::InitializeForOfStatement(ForOfStatement* for_of, Expression* each,
3290 Expression* subject, Statement* body,
3291 bool use_position_hack) {
nickie 2016/03/04 14:15:13 As a fix, I suggest that you replace "bool use_pos
3292 Variable* iterator =
3293 scope_->NewTemporary(ast_value_factory()->dot_iterator_string());
3294 Variable* result =
3295 scope_->NewTemporary(ast_value_factory()->dot_result_string());
3296
3297 Expression* assign_iterator;
3298 Expression* next_result;
3299 Expression* result_done;
3300 Expression* assign_each;
3301
3302 // Hackily disambiguate o from o.next and o [Symbol.iterator]().
3303 // TODO(verwaest): Come up with a better solution.
3304 int get_iterator_pos = subject->position() - (use_position_hack * 2);
3305 int next_result_pos = subject->position() - (use_position_hack * 1);
nickie 2016/03/04 14:15:13 These two would become: int get_iterator_pos =
3306
3307 // iterator = subject[Symbol.iterator]()
3308 assign_iterator = factory()->NewAssignment(
3309 Token::ASSIGN, factory()->NewVariableProxy(iterator),
3310 GetIterator(subject, factory(), get_iterator_pos), subject->position());
3311
3312 // !%_IsJSReceiver(result = iterator.next()) &&
3313 // %ThrowIteratorResultNotAnObject(result)
3314 {
3315 // result = iterator.next()
3316 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
3317 next_result =
3318 BuildIteratorNextResult(iterator_proxy, result, next_result_pos);
3319 }
3320
3321 // result.done
3322 {
3323 Expression* done_literal = factory()->NewStringLiteral(
3324 ast_value_factory()->done_string(), RelocInfo::kNoPosition);
3325 Expression* result_proxy = factory()->NewVariableProxy(result);
3326 result_done = factory()->NewProperty(result_proxy, done_literal,
3327 RelocInfo::kNoPosition);
3328 }
3329
3330 // each = result.value
3331 {
3332 Expression* value_literal = factory()->NewStringLiteral(
3333 ast_value_factory()->value_string(), RelocInfo::kNoPosition);
3334 Expression* result_proxy = factory()->NewVariableProxy(result);
3335 Expression* result_value = factory()->NewProperty(
3336 result_proxy, value_literal, RelocInfo::kNoPosition);
3337 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
3338 RelocInfo::kNoPosition);
3339 if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
3340 DCHECK(allow_harmony_destructuring_assignment());
3341 assign_each = PatternRewriter::RewriteDestructuringAssignment(
3342 this, assign_each->AsAssignment(), scope_);
3343 }
3344 }
3345
3346 for_of->Initialize(each, subject, body, iterator, assign_iterator,
3347 next_result, result_done, assign_each);
3348 }
3349
3350 Statement* Parser::DesugarLexicalBindingsInForStatement( 3350 Statement* Parser::DesugarLexicalBindingsInForStatement(
3351 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names, 3351 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names,
3352 ForStatement* loop, Statement* init, Expression* cond, Statement* next, 3352 ForStatement* loop, Statement* init, Expression* cond, Statement* next,
3353 Statement* body, bool* ok) { 3353 Statement* body, bool* ok) {
3354 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are 3354 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are
3355 // copied into a new environment. Moreover, the "next" statement must be 3355 // copied into a new environment. Moreover, the "next" statement must be
3356 // evaluated not in the environment of the just completed iteration but in 3356 // evaluated not in the environment of the just completed iteration but in
3357 // that of the upcoming one. We achieve this with the following desugaring. 3357 // that of the upcoming one. We achieve this with the following desugaring.
3358 // Extra care is needed to preserve the completion value of the original loop. 3358 // Extra care is needed to preserve the completion value of the original loop.
3359 // 3359 //
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
3722 each_initialization_block, &descriptor, &decl, 3722 each_initialization_block, &descriptor, &decl,
3723 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings 3723 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings
3724 : nullptr, 3724 : nullptr,
3725 CHECK_OK); 3725 CHECK_OK);
3726 } 3726 }
3727 3727
3728 body_block->statements()->Add(each_initialization_block, zone()); 3728 body_block->statements()->Add(each_initialization_block, zone());
3729 body_block->statements()->Add(body, zone()); 3729 body_block->statements()->Add(body, zone());
3730 VariableProxy* temp_proxy = 3730 VariableProxy* temp_proxy =
3731 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); 3731 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
3732 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block, 3732 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
3733 false);
3734 } 3733 }
3735 body_scope->set_end_position(scanner()->location().end_pos); 3734 body_scope->set_end_position(scanner()->location().end_pos);
3736 body_scope = body_scope->FinalizeBlockScope(); 3735 body_scope = body_scope->FinalizeBlockScope();
3737 body_block->set_scope(body_scope); 3736 body_block->set_scope(body_scope);
3738 3737
3739 // Create a TDZ for any lexically-bound names. 3738 // Create a TDZ for any lexically-bound names.
3740 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { 3739 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) {
3741 DCHECK_NULL(init_block); 3740 DCHECK_NULL(init_block);
3742 3741
3743 init_block = 3742 init_block =
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
3831 // lexical binding is introduced which overlaps with the for-in/of, 3830 // lexical binding is introduced which overlaps with the for-in/of,
3832 // expressions in head of the loop should actually have variables 3831 // expressions in head of the loop should actually have variables
3833 // resolved in the outer scope. 3832 // resolved in the outer scope.
3834 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE); 3833 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE);
3835 { 3834 {
3836 BlockState block_state(&scope_, body_scope); 3835 BlockState block_state(&scope_, body_scope);
3837 Block* block = 3836 Block* block =
3838 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); 3837 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
3839 Statement* body = ParseSubStatement(NULL, CHECK_OK); 3838 Statement* body = ParseSubStatement(NULL, CHECK_OK);
3840 block->statements()->Add(body, zone()); 3839 block->statements()->Add(body, zone());
3841 InitializeForEachStatement(loop, expression, enumerable, block, 3840 InitializeForEachStatement(loop, expression, enumerable, block);
3842 is_destructuring);
3843 body_scope->set_end_position(scanner()->location().end_pos); 3841 body_scope->set_end_position(scanner()->location().end_pos);
3844 body_scope = body_scope->FinalizeBlockScope(); 3842 body_scope = body_scope->FinalizeBlockScope();
3845 block->set_scope(body_scope); 3843 block->set_scope(body_scope);
3846 } 3844 }
3847 3845
3848 Statement* final_loop = loop->IsForOfStatement() 3846 Statement* final_loop = loop->IsForOfStatement()
3849 ? FinalizeForOfStatement( 3847 ? FinalizeForOfStatement(
3850 loop->AsForOfStatement(), RelocInfo::kNoPosition) 3848 loop->AsForOfStatement(), RelocInfo::kNoPosition)
3851 : loop; 3849 : loop;
3852 3850
(...skipping 1807 matching lines...) Expand 10 before | Expand all | Expand 10 after
5660 factory()->NewCallRuntime(Runtime::kAppendElement, 5658 factory()->NewCallRuntime(Runtime::kAppendElement,
5661 append_element_args, 5659 append_element_args,
5662 RelocInfo::kNoPosition), 5660 RelocInfo::kNoPosition),
5663 RelocInfo::kNoPosition), 5661 RelocInfo::kNoPosition),
5664 zone()); 5662 zone());
5665 } else { 5663 } else {
5666 // If it's a spread, we're adding a for/of loop iterating through it. 5664 // If it's a spread, we're adding a for/of loop iterating through it.
5667 Variable* each = 5665 Variable* each =
5668 scope_->NewTemporary(ast_value_factory()->dot_for_string()); 5666 scope_->NewTemporary(ast_value_factory()->dot_for_string());
5669 Expression* subject = spread->expression(); 5667 Expression* subject = spread->expression();
5670 Variable* iterator =
5671 scope_->NewTemporary(ast_value_factory()->dot_iterator_string());
5672 Variable* element =
5673 scope_->NewTemporary(ast_value_factory()->dot_result_string());
5674 // iterator = subject[Symbol.iterator]()
5675 Expression* assign_iterator = factory()->NewAssignment(
5676 Token::ASSIGN, factory()->NewVariableProxy(iterator),
5677 GetIterator(subject, factory(), spread->expression_position()),
nickie 2016/03/04 14:15:13 There was another tricky point but it was a bit hi
5678 subject->position());
5679 // !%_IsJSReceiver(element = iterator.next()) &&
5680 // %ThrowIteratorResultNotAnObject(element)
5681 Expression* next_element;
5682 {
5683 // element = iterator.next()
5684 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
5685 next_element = BuildIteratorNextResult(iterator_proxy, element,
5686 spread->expression_position());
nickie 2016/03/04 14:15:13 Here too...
5687 }
5688 // element.done
5689 Expression* element_done;
5690 {
5691 Expression* done_literal = factory()->NewStringLiteral(
5692 ast_value_factory()->done_string(), RelocInfo::kNoPosition);
5693 Expression* element_proxy = factory()->NewVariableProxy(element);
5694 element_done = factory()->NewProperty(element_proxy, done_literal,
5695 RelocInfo::kNoPosition);
5696 }
5697 // each = element.value
5698 Expression* assign_each;
5699 {
5700 Expression* value_literal = factory()->NewStringLiteral(
5701 ast_value_factory()->value_string(), RelocInfo::kNoPosition);
5702 Expression* element_proxy = factory()->NewVariableProxy(element);
5703 Expression* element_value = factory()->NewProperty(
5704 element_proxy, value_literal, RelocInfo::kNoPosition);
5705 assign_each = factory()->NewAssignment(
5706 Token::ASSIGN, factory()->NewVariableProxy(each), element_value,
5707 RelocInfo::kNoPosition);
5708 }
5709 // %AppendElement($R, each) 5668 // %AppendElement($R, each)
5710 Statement* append_body; 5669 Statement* append_body;
5711 { 5670 {
5712 ZoneList<Expression*>* append_element_args = 5671 ZoneList<Expression*>* append_element_args =
5713 NewExpressionList(2, zone()); 5672 NewExpressionList(2, zone());
5714 append_element_args->Add(factory()->NewVariableProxy(result), zone()); 5673 append_element_args->Add(factory()->NewVariableProxy(result), zone());
5715 append_element_args->Add(factory()->NewVariableProxy(each), zone()); 5674 append_element_args->Add(factory()->NewVariableProxy(each), zone());
5716 append_body = factory()->NewExpressionStatement( 5675 append_body = factory()->NewExpressionStatement(
5717 factory()->NewCallRuntime(Runtime::kAppendElement, 5676 factory()->NewCallRuntime(Runtime::kAppendElement,
5718 append_element_args, 5677 append_element_args,
5719 RelocInfo::kNoPosition), 5678 RelocInfo::kNoPosition),
5720 RelocInfo::kNoPosition); 5679 RelocInfo::kNoPosition);
5721 } 5680 }
5722 // for (each of spread) %AppendElement($R, each) 5681 // for (each of spread) %AppendElement($R, each)
5723 ForEachStatement* loop = factory()->NewForEachStatement( 5682 ForEachStatement* loop = factory()->NewForEachStatement(
5724 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition); 5683 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition);
5725 ForOfStatement* for_of = loop->AsForOfStatement(); 5684 InitializeForOfStatement(loop->AsForOfStatement(),
5726 for_of->Initialize(factory()->NewVariableProxy(each), subject, 5685 factory()->NewVariableProxy(each), subject,
5727 append_body, iterator, assign_iterator, next_element, 5686 append_body);
5728 element_done, assign_each); 5687 do_block->statements()->Add(loop, zone());
5729 do_block->statements()->Add(for_of, zone());
5730 } 5688 }
5731 } 5689 }
5732 // Now, rewind the original array literal to truncate everything from the 5690 // Now, rewind the original array literal to truncate everything from the
5733 // first spread (included) until the end. This fixes $R's initialization. 5691 // first spread (included) until the end. This fixes $R's initialization.
5734 lit->RewindSpreads(); 5692 lit->RewindSpreads();
5735 return factory()->NewDoExpression(do_block, result, lit->position()); 5693 return factory()->NewDoExpression(do_block, result, lit->position());
5736 } 5694 }
5737 5695
5738 5696
5739 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { 5697 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) {
(...skipping 1200 matching lines...) Expand 10 before | Expand all | Expand 10 after
6940 Expression* do_each = 6898 Expression* do_each =
6941 factory->NewDoExpression(new_assign_each, var_each, nopos); 6899 factory->NewDoExpression(new_assign_each, var_each, nopos);
6942 loop->set_assign_each(do_each); 6900 loop->set_assign_each(do_each);
6943 6901
6944 return final_loop; 6902 return final_loop;
6945 } 6903 }
6946 6904
6947 6905
6948 } // namespace internal 6906 } // namespace internal
6949 } // namespace v8 6907 } // 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