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

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

Issue 1695393003: [es6] Implement for-of iterator finalization (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Remove some debug left-overs Created 4 years, 10 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
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 3318 matching lines...) Expand 10 before | Expand all | Expand 10 after
3329 result_proxy, value_literal, RelocInfo::kNoPosition); 3329 result_proxy, value_literal, RelocInfo::kNoPosition);
3330 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, 3330 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
3331 RelocInfo::kNoPosition); 3331 RelocInfo::kNoPosition);
3332 if (is_destructuring) { 3332 if (is_destructuring) {
3333 assign_each = PatternRewriter::RewriteDestructuringAssignment( 3333 assign_each = PatternRewriter::RewriteDestructuringAssignment(
3334 this, assign_each->AsAssignment(), scope_); 3334 this, assign_each->AsAssignment(), scope_);
3335 } 3335 }
3336 } 3336 }
3337 3337
3338 for_of->Initialize(each, subject, body, 3338 for_of->Initialize(each, subject, body,
3339 iterator,
3339 assign_iterator, 3340 assign_iterator,
3340 next_result, 3341 next_result,
3341 result_done, 3342 result_done,
3342 assign_each); 3343 assign_each);
3343 } else { 3344 } else {
3344 if (is_destructuring) { 3345 if (is_destructuring) {
3345 Variable* temp = 3346 Variable* temp =
3346 scope_->NewTemporary(ast_value_factory()->empty_string()); 3347 scope_->NewTemporary(ast_value_factory()->empty_string());
3347 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); 3348 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
3348 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment( 3349 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment(
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
3606 inner_block->set_scope(inner_scope); 3607 inner_block->set_scope(inner_scope);
3607 } 3608 }
3608 3609
3609 outer_loop->Initialize(NULL, NULL, NULL, inner_block); 3610 outer_loop->Initialize(NULL, NULL, NULL, inner_block);
3610 return outer_block; 3611 return outer_block;
3611 } 3612 }
3612 3613
3613 3614
3614 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, 3615 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
3615 bool* ok) { 3616 bool* ok) {
3616 // ForStatement ::
3617 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
3618
3619 int stmt_pos = peek_position(); 3617 int stmt_pos = peek_position();
3620 Statement* init = NULL; 3618 Statement* init = NULL;
3621 ZoneList<const AstRawString*> lexical_bindings(1, zone()); 3619 ZoneList<const AstRawString*> lexical_bindings(1, zone());
3622 3620
3623 // Create an in-between scope for let-bound iteration variables. 3621 // Create an in-between scope for let-bound iteration variables.
3624 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); 3622 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
3625 3623
3626 BlockState block_state(&scope_, for_scope); 3624 BlockState block_state(&scope_, for_scope);
3627 Expect(Token::FOR, CHECK_OK); 3625 Expect(Token::FOR, CHECK_OK);
3628 Expect(Token::LPAREN, CHECK_OK); 3626 Expect(Token::LPAREN, CHECK_OK);
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
3745 3743
3746 body_block->statements()->Add(each_initialization_block, zone()); 3744 body_block->statements()->Add(each_initialization_block, zone());
3747 body_block->statements()->Add(body, zone()); 3745 body_block->statements()->Add(body, zone());
3748 VariableProxy* temp_proxy = 3746 VariableProxy* temp_proxy =
3749 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); 3747 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
3750 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block, 3748 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block,
3751 false); 3749 false);
3752 } 3750 }
3753 body_scope->set_end_position(scanner()->location().end_pos); 3751 body_scope->set_end_position(scanner()->location().end_pos);
3754 body_scope = body_scope->FinalizeBlockScope(); 3752 body_scope = body_scope->FinalizeBlockScope();
3755 body_block->set_scope(body_scope); 3753 body_block->set_scope(body_scope);
3756 3754
3757 // Create a TDZ for any lexically-bound names. 3755 // Create a TDZ for any lexically-bound names.
3758 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { 3756 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) {
3759 DCHECK_NULL(init_block); 3757 DCHECK_NULL(init_block);
3760 3758
3761 init_block = 3759 init_block =
3762 factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition); 3760 factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);
3763 3761
3764 for (int i = 0; i < lexical_bindings.length(); ++i) { 3762 for (int i = 0; i < lexical_bindings.length(); ++i) {
3765 // TODO(adamk): This needs to be some sort of special 3763 // TODO(adamk): This needs to be some sort of special
3766 // INTERNAL variable that's invisible to the debugger 3764 // INTERNAL variable that's invisible to the debugger
3767 // but visible to everything else. 3765 // but visible to everything else.
3768 VariableProxy* tdz_proxy = 3766 VariableProxy* tdz_proxy =
3769 NewUnresolved(lexical_bindings[i], LET); 3767 NewUnresolved(lexical_bindings[i], LET);
3770 Declaration* tdz_decl = factory()->NewVariableDeclaration( 3768 Declaration* tdz_decl = factory()->NewVariableDeclaration(
3771 tdz_proxy, LET, scope_, RelocInfo::kNoPosition); 3769 tdz_proxy, LET, scope_, RelocInfo::kNoPosition);
3772 Variable* tdz_var = Declare( 3770 Variable* tdz_var = Declare(
3773 tdz_decl, DeclarationDescriptor::NORMAL, true, CHECK_OK); 3771 tdz_decl, DeclarationDescriptor::NORMAL, true, CHECK_OK);
3774 tdz_var->set_initializer_position(position()); 3772 tdz_var->set_initializer_position(position());
3775 }
3776 } 3773 }
3774 }
3775
3776 Statement* final_loop = loop->IsForOfStatement()
3777 ? FinalizeForOfStatement(
3778 loop->AsForOfStatement(), RelocInfo::kNoPosition)
3779 : loop;
Dan Ehrenberg 2016/02/16 21:18:30 I'm not sure if any of this is risky (the nopos pa
rossberg 2016/02/17 12:54:45 Good point, added flag.
3777 3780
3778 for_scope->set_end_position(scanner()->location().end_pos); 3781 for_scope->set_end_position(scanner()->location().end_pos);
3779 for_scope = for_scope->FinalizeBlockScope(); 3782 for_scope = for_scope->FinalizeBlockScope();
3780 // Parsed for-in loop w/ variable declarations. 3783 // Parsed for-in loop w/ variable declarations.
3781 if (init_block != nullptr) { 3784 if (init_block != nullptr) {
3782 init_block->statements()->Add(loop, zone()); 3785 init_block->statements()->Add(final_loop, zone());
3783 init_block->set_scope(for_scope); 3786 init_block->set_scope(for_scope);
3784 return init_block; 3787 return init_block;
3785 } else { 3788 } else {
3786 DCHECK_NULL(for_scope); 3789 DCHECK_NULL(for_scope);
3787 return loop; 3790 return final_loop;
3788 } 3791 }
3789 } else { 3792 } else {
3790 init = parsing_result.BuildInitializationBlock( 3793 init = parsing_result.BuildInitializationBlock(
3791 IsLexicalVariableMode(parsing_result.descriptor.mode) 3794 IsLexicalVariableMode(parsing_result.descriptor.mode)
3792 ? &lexical_bindings 3795 ? &lexical_bindings
3793 : nullptr, 3796 : nullptr,
3794 CHECK_OK); 3797 CHECK_OK);
3795 } 3798 }
3796 } else { 3799 } else {
3797 int lhs_beg_pos = peek_position(); 3800 int lhs_beg_pos = peek_position();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3840 3843
3841 Expect(Token::RPAREN, CHECK_OK); 3844 Expect(Token::RPAREN, CHECK_OK);
3842 3845
3843 // Make a block around the statement in case a lexical binding 3846 // Make a block around the statement in case a lexical binding
3844 // is introduced, e.g. by a FunctionDeclaration. 3847 // is introduced, e.g. by a FunctionDeclaration.
3845 // This block must not use for_scope as its scope because if a 3848 // This block must not use for_scope as its scope because if a
3846 // lexical binding is introduced which overlaps with the for-in/of, 3849 // lexical binding is introduced which overlaps with the for-in/of,
3847 // expressions in head of the loop should actually have variables 3850 // expressions in head of the loop should actually have variables
3848 // resolved in the outer scope. 3851 // resolved in the outer scope.
3849 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE); 3852 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE);
3850 BlockState block_state(&scope_, body_scope); 3853 {
3851 Block* block = 3854 BlockState block_state(&scope_, body_scope);
3852 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); 3855 Block* block =
3853 Statement* body = ParseSubStatement(NULL, CHECK_OK); 3856 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
3854 block->statements()->Add(body, zone()); 3857 Statement* body = ParseSubStatement(NULL, CHECK_OK);
3855 InitializeForEachStatement(loop, expression, enumerable, block, 3858 block->statements()->Add(body, zone());
3856 is_destructuring); 3859 InitializeForEachStatement(loop, expression, enumerable, block,
3857 body_scope->set_end_position(scanner()->location().end_pos); 3860 is_destructuring);
3858 body_scope = body_scope->FinalizeBlockScope(); 3861 body_scope->set_end_position(scanner()->location().end_pos);
3859 block->set_scope(body_scope); 3862 body_scope = body_scope->FinalizeBlockScope();
3863 block->set_scope(body_scope);
3864 }
3865
3866 Statement* final_loop = loop->IsForOfStatement()
3867 ? FinalizeForOfStatement(
3868 loop->AsForOfStatement(), RelocInfo::kNoPosition)
3869 : loop;
3870
3860 for_scope->set_end_position(scanner()->location().end_pos); 3871 for_scope->set_end_position(scanner()->location().end_pos);
3861 for_scope = for_scope->FinalizeBlockScope(); 3872 for_scope = for_scope->FinalizeBlockScope();
3862 DCHECK(for_scope == nullptr); 3873 DCHECK(for_scope == nullptr);
3863 // Parsed for-in loop. 3874 return final_loop;
3864 return loop;
3865 3875
3866 } else { 3876 } else {
3867 init = factory()->NewExpressionStatement(expression, lhs_beg_pos); 3877 init = factory()->NewExpressionStatement(expression, lhs_beg_pos);
3868 } 3878 }
3869 } 3879 }
3870 } 3880 }
3871 3881
3872 // Standard 'for' loop 3882 // Standard 'for' loop
3873 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos); 3883 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos);
3874 Target target(&this->target_stack_, loop); 3884 Target target(&this->target_stack_, loop);
(...skipping 1859 matching lines...) Expand 10 before | Expand all | Expand 10 after
5734 factory()->NewCallRuntime(Runtime::kAppendElement, 5744 factory()->NewCallRuntime(Runtime::kAppendElement,
5735 append_element_args, 5745 append_element_args,
5736 RelocInfo::kNoPosition), 5746 RelocInfo::kNoPosition),
5737 RelocInfo::kNoPosition); 5747 RelocInfo::kNoPosition);
5738 } 5748 }
5739 // for (each of spread) %AppendElement($R, each) 5749 // for (each of spread) %AppendElement($R, each)
5740 ForEachStatement* loop = factory()->NewForEachStatement( 5750 ForEachStatement* loop = factory()->NewForEachStatement(
5741 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition); 5751 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition);
5742 ForOfStatement* for_of = loop->AsForOfStatement(); 5752 ForOfStatement* for_of = loop->AsForOfStatement();
5743 for_of->Initialize(factory()->NewVariableProxy(each), subject, 5753 for_of->Initialize(factory()->NewVariableProxy(each), subject,
5744 append_body, assign_iterator, next_element, 5754 append_body, iterator, assign_iterator, next_element,
5745 element_done, assign_each); 5755 element_done, assign_each);
5746 do_block->statements()->Add(for_of, zone()); 5756 do_block->statements()->Add(for_of, zone());
5747 } 5757 }
5748 } 5758 }
5749 // Now, rewind the original array literal to truncate everything from the 5759 // Now, rewind the original array literal to truncate everything from the
5750 // first spread (included) until the end. This fixes $R's initialization. 5760 // first spread (included) until the end. This fixes $R's initialization.
5751 lit->RewindSpreads(); 5761 lit->RewindSpreads();
5752 return factory()->NewDoExpression(do_block, result, lit->position()); 5762 return factory()->NewDoExpression(do_block, result, lit->position());
5753 } 5763 }
5754 5764
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
5892 Expression* ParserTraits::RewriteYieldStar( 5902 Expression* ParserTraits::RewriteYieldStar(
5893 Expression* generator, Expression* iterable, int pos) { 5903 Expression* generator, Expression* iterable, int pos) {
5894 5904
5895 const int nopos = RelocInfo::kNoPosition; 5905 const int nopos = RelocInfo::kNoPosition;
5896 5906
5897 auto factory = parser_->factory(); 5907 auto factory = parser_->factory();
5898 auto avfactory = parser_->ast_value_factory(); 5908 auto avfactory = parser_->ast_value_factory();
5899 auto scope = parser_->scope_; 5909 auto scope = parser_->scope_;
5900 auto zone = parser_->zone(); 5910 auto zone = parser_->zone();
5901 5911
5902 Statement* skip = factory->NewEmptyStatement(nopos);
5903 5912
5904 // Forward definition for break/continue statements. 5913 // Forward definition for break/continue statements.
5905 WhileStatement* loop = factory->NewWhileStatement(nullptr, nopos); 5914 WhileStatement* loop = factory->NewWhileStatement(nullptr, nopos);
5906 5915
5907 5916
5908 // let input = undefined; 5917 // let input = undefined;
5909 Variable* var_input = scope->NewTemporary(avfactory->empty_string()); 5918 Variable* var_input = scope->NewTemporary(avfactory->empty_string());
5910 Statement* initialize_input; 5919 Statement* initialize_input;
5911 { 5920 {
5912 Expression* input_proxy = factory->NewVariableProxy(var_input); 5921 Expression* input_proxy = factory->NewVariableProxy(var_input);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
5964 } 5973 }
5965 5974
5966 Statement* throw_call; 5975 Statement* throw_call;
5967 { 5976 {
5968 Expression* call = NewThrowTypeError( 5977 Expression* call = NewThrowTypeError(
5969 MessageTemplate::kSymbolIteratorInvalid, avfactory->empty_string(), 5978 MessageTemplate::kSymbolIteratorInvalid, avfactory->empty_string(),
5970 nopos); 5979 nopos);
5971 throw_call = factory->NewExpressionStatement(call, nopos); 5980 throw_call = factory->NewExpressionStatement(call, nopos);
5972 } 5981 }
5973 5982
5974 validate_iterator = 5983 validate_iterator = factory->NewIfStatement(
5975 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); 5984 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
5976 } 5985 }
5977 5986
5978 5987
5979 // output = iterator.next(input); 5988 // output = iterator.next(input);
5980 Statement* call_next; 5989 Statement* call_next;
5981 { 5990 {
5982 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator); 5991 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
5983 Expression* literal = 5992 Expression* literal =
5984 factory->NewStringLiteral(avfactory->next_string(), nopos); 5993 factory->NewStringLiteral(avfactory->next_string(), nopos);
5985 Expression* next_property = 5994 Expression* next_property =
(...skipping 22 matching lines...) Expand all
6008 6017
6009 Statement* throw_call; 6018 Statement* throw_call;
6010 { 6019 {
6011 auto args = new (zone) ZoneList<Expression*>(1, zone); 6020 auto args = new (zone) ZoneList<Expression*>(1, zone);
6012 args->Add(factory->NewVariableProxy(var_output), zone); 6021 args->Add(factory->NewVariableProxy(var_output), zone);
6013 Expression* call = factory->NewCallRuntime( 6022 Expression* call = factory->NewCallRuntime(
6014 Runtime::kThrowIteratorResultNotAnObject, args, nopos); 6023 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6015 throw_call = factory->NewExpressionStatement(call, nopos); 6024 throw_call = factory->NewExpressionStatement(call, nopos);
6016 } 6025 }
6017 6026
6018 validate_next_output = 6027 validate_next_output = factory->NewIfStatement(
6019 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); 6028 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6020 } 6029 }
6021 6030
6022 6031
6023 // let iteratorThrow = iterator.throw; 6032 // let iteratorThrow = iterator.throw;
6024 Variable* var_throw = scope->NewTemporary(avfactory->empty_string()); 6033 Variable* var_throw = scope->NewTemporary(avfactory->empty_string());
6025 Statement* get_throw; 6034 Statement* get_throw;
6026 { 6035 {
6027 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator); 6036 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
6028 Expression* literal = 6037 Expression* literal =
6029 factory->NewStringLiteral(avfactory->throw_string(), nopos); 6038 factory->NewStringLiteral(avfactory->throw_string(), nopos);
(...skipping 15 matching lines...) Expand all
6045 Expression* condition = factory->NewCompareOperation( 6054 Expression* condition = factory->NewCompareOperation(
6046 Token::EQ, factory->NewVariableProxy(var_throw), 6055 Token::EQ, factory->NewVariableProxy(var_throw),
6047 factory->NewNullLiteral(nopos), nopos); 6056 factory->NewNullLiteral(nopos), nopos);
6048 6057
6049 Expression* call = NewThrowTypeError( 6058 Expression* call = NewThrowTypeError(
6050 MessageTemplate::kThrowMethodMissing, 6059 MessageTemplate::kThrowMethodMissing,
6051 avfactory->empty_string(), nopos); 6060 avfactory->empty_string(), nopos);
6052 Statement* throw_call = factory->NewExpressionStatement(call, nopos); 6061 Statement* throw_call = factory->NewExpressionStatement(call, nopos);
6053 6062
6054 Block* then = factory->NewBlock(nullptr, 4+1, false, nopos); 6063 Block* then = factory->NewBlock(nullptr, 4+1, false, nopos);
6055 BuildIteratorClose(then->statements(), var_iterator, Nothing<Variable*>(), 6064 Variable* var_tmp = scope->NewTemporary(avfactory->empty_string());
6056 Nothing<Variable*>()); 6065 BuildIteratorClose(
6066 then->statements(), var_iterator, Nothing<Variable*>(), var_tmp);
6057 then->statements()->Add(throw_call, zone); 6067 then->statements()->Add(throw_call, zone);
6058 check_throw = 6068 check_throw = factory->NewIfStatement(
6059 factory->NewIfStatement(condition, then, skip, nopos); 6069 condition, then, factory->NewEmptyStatement(nopos), nopos);
6060 } 6070 }
6061 6071
6062 6072
6063 // output = %_Call(iteratorThrow, iterator, input); 6073 // output = %_Call(iteratorThrow, iterator, input);
6064 Statement* call_throw; 6074 Statement* call_throw;
6065 { 6075 {
6066 auto args = new (zone) ZoneList<Expression*>(3, zone); 6076 auto args = new (zone) ZoneList<Expression*>(3, zone);
6067 args->Add(factory->NewVariableProxy(var_throw), zone); 6077 args->Add(factory->NewVariableProxy(var_throw), zone);
6068 args->Add(factory->NewVariableProxy(var_iterator), zone); 6078 args->Add(factory->NewVariableProxy(var_iterator), zone);
6069 args->Add(factory->NewVariableProxy(var_input), zone); 6079 args->Add(factory->NewVariableProxy(var_input), zone);
(...skipping 18 matching lines...) Expand all
6088 6098
6089 Statement* throw_call; 6099 Statement* throw_call;
6090 { 6100 {
6091 auto args = new (zone) ZoneList<Expression*>(1, zone); 6101 auto args = new (zone) ZoneList<Expression*>(1, zone);
6092 args->Add(factory->NewVariableProxy(var_output), zone); 6102 args->Add(factory->NewVariableProxy(var_output), zone);
6093 Expression* call = factory->NewCallRuntime( 6103 Expression* call = factory->NewCallRuntime(
6094 Runtime::kThrowIteratorResultNotAnObject, args, nopos); 6104 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6095 throw_call = factory->NewExpressionStatement(call, nopos); 6105 throw_call = factory->NewExpressionStatement(call, nopos);
6096 } 6106 }
6097 6107
6098 validate_throw_output = 6108 validate_throw_output = factory->NewIfStatement(
6099 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); 6109 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6100 } 6110 }
6101 6111
6102 6112
6103 // if (output.done) break; 6113 // if (output.done) break;
6104 Statement* if_done; 6114 Statement* if_done;
6105 { 6115 {
6106 Expression* output_proxy = factory->NewVariableProxy(var_output); 6116 Expression* output_proxy = factory->NewVariableProxy(var_output);
6107 Expression* literal = 6117 Expression* literal =
6108 factory->NewStringLiteral(avfactory->done_string(), nopos); 6118 factory->NewStringLiteral(avfactory->done_string(), nopos);
6109 Expression* property = factory->NewProperty(output_proxy, literal, nopos); 6119 Expression* property = factory->NewProperty(output_proxy, literal, nopos);
6110 BreakStatement* break_loop = factory->NewBreakStatement(loop, nopos); 6120 BreakStatement* break_loop = factory->NewBreakStatement(loop, nopos);
6111 if_done = factory->NewIfStatement(property, break_loop, skip, nopos); 6121 if_done = factory->NewIfStatement(
6122 property, break_loop, factory->NewEmptyStatement(nopos), nopos);
6112 } 6123 }
6113 6124
6114 6125
6115 // mode = kReturn; 6126 // mode = kReturn;
6116 Statement* set_mode_return; 6127 Statement* set_mode_return;
6117 { 6128 {
6118 Expression* mode_proxy = factory->NewVariableProxy(var_mode); 6129 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
6119 Expression* kreturn = 6130 Expression* kreturn =
6120 factory->NewSmiLiteral(JSGeneratorObject::RETURN, nopos); 6131 factory->NewSmiLiteral(JSGeneratorObject::RETURN, nopos);
6121 Expression* assignment = 6132 Expression* assignment =
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
6220 6231
6221 // switch (mode) { ... } 6232 // switch (mode) { ... }
6222 SwitchStatement* switch_mode = factory->NewSwitchStatement(nullptr, nopos); 6233 SwitchStatement* switch_mode = factory->NewSwitchStatement(nullptr, nopos);
6223 { 6234 {
6224 auto case_next = new (zone) ZoneList<Statement*>(3, zone); 6235 auto case_next = new (zone) ZoneList<Statement*>(3, zone);
6225 case_next->Add(call_next, zone); 6236 case_next->Add(call_next, zone);
6226 case_next->Add(validate_next_output, zone); 6237 case_next->Add(validate_next_output, zone);
6227 case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone); 6238 case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
6228 6239
6229 auto case_return = new (zone) ZoneList<Statement*>(5, zone); 6240 auto case_return = new (zone) ZoneList<Statement*>(5, zone);
6230 BuildIteratorClose( 6241 BuildIteratorClose(case_return, var_iterator, Just(var_input), var_output);
6231 case_return, var_iterator, Just(var_input), Just(var_output));
6232 case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone); 6242 case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
6233 6243
6234 auto case_throw = new (zone) ZoneList<Statement*>(5, zone); 6244 auto case_throw = new (zone) ZoneList<Statement*>(5, zone);
6235 case_throw->Add(get_throw, zone); 6245 case_throw->Add(get_throw, zone);
6236 case_throw->Add(check_throw, zone); 6246 case_throw->Add(check_throw, zone);
6237 case_throw->Add(call_throw, zone); 6247 case_throw->Add(call_throw, zone);
6238 case_throw->Add(validate_throw_output, zone); 6248 case_throw->Add(validate_throw_output, zone);
6239 case_throw->Add(factory->NewBreakStatement(switch_mode, nopos), zone); 6249 case_throw->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
6240 6250
6241 auto cases = new (zone) ZoneList<CaseClause*>(3, zone); 6251 auto cases = new (zone) ZoneList<CaseClause*>(3, zone);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
6288 Rewriter::Rewrite(parser_, yield_star, avfactory); 6298 Rewriter::Rewrite(parser_, yield_star, avfactory);
6289 } 6299 }
6290 6300
6291 return yield_star; 6301 return yield_star;
6292 } 6302 }
6293 6303
6294 6304
6295 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements, 6305 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements,
6296 Variable* iterator, 6306 Variable* iterator,
6297 Maybe<Variable*> input, 6307 Maybe<Variable*> input,
6298 Maybe<Variable*> output) { 6308 Variable* var_output) {
6309 //
6310 // This function adds four statements to [statements], corresponding to the
6311 // following code:
6312 //
6313 // let iteratorReturn = iterator.return;
6314 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return |input|;
6315 // output = %_Call(iteratorReturn, iterator|, input|);
6316 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
6317 //
6318 // Here, |...| denotes optional parts, depending on the presence of the
Dan Ehrenberg 2016/02/16 21:18:30 Given the below comment (iteratorReturn shouldn't
rossberg 2016/02/17 12:54:45 Done.
6319 // input variable.
6320 //
6321
6299 const int nopos = RelocInfo::kNoPosition; 6322 const int nopos = RelocInfo::kNoPosition;
6300 auto factory = parser_->factory(); 6323 auto factory = parser_->factory();
6301 auto avfactory = parser_->ast_value_factory(); 6324 auto avfactory = parser_->ast_value_factory();
6302 auto scope = parser_->scope_;
6303 auto zone = parser_->zone(); 6325 auto zone = parser_->zone();
6304 Statement* skip = factory->NewEmptyStatement(nopos); 6326
6305 6327
6306 // let iteratorReturn = iterator.return; 6328 // let iteratorReturn = iterator.return;
6307 Variable* var = scope->NewTemporary(avfactory->empty_string()); 6329 Variable* var_return = var_output; // Reusing the output variable.
6308 Statement* get_return; 6330 Statement* get_return;
6309 { 6331 {
6310 Expression* iterator_proxy = factory->NewVariableProxy(iterator); 6332 Expression* iterator_proxy = factory->NewVariableProxy(iterator);
6311 Expression* literal = 6333 Expression* literal =
6312 factory->NewStringLiteral(avfactory->return_string(), nopos); 6334 factory->NewStringLiteral(avfactory->return_string(), nopos);
6313 Expression* property = 6335 Expression* property =
6314 factory->NewProperty(iterator_proxy, literal, nopos); 6336 factory->NewProperty(iterator_proxy, literal, nopos);
6315 Expression* return_proxy = factory->NewVariableProxy(var); 6337 Expression* return_proxy = factory->NewVariableProxy(var_return);
6316 Expression* assignment = factory->NewAssignment( 6338 Expression* assignment = factory->NewAssignment(
6317 Token::ASSIGN, return_proxy, property, nopos); 6339 Token::ASSIGN, return_proxy, property, nopos);
6318 get_return = factory->NewExpressionStatement(assignment, nopos); 6340 get_return = factory->NewExpressionStatement(assignment, nopos);
6319 } 6341 }
6320 6342
6321 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return; OR 6343
6322 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return input; 6344 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return |input|;
6323 Statement* check_return; 6345 Statement* check_return;
6324 { 6346 {
6325 Expression* condition = factory->NewCompareOperation( 6347 Expression* condition = factory->NewCompareOperation(
6326 Token::EQ, factory->NewVariableProxy(var), 6348 Token::EQ, factory->NewVariableProxy(var_return),
6327 factory->NewNullLiteral(nopos), nopos); 6349 factory->NewNullLiteral(nopos), nopos);
6328 6350
6329 Expression* value = input.IsJust() ? 6351 Expression* value = input.IsJust() ?
6330 static_cast<Expression*>(factory->NewVariableProxy(input.FromJust())) : 6352 static_cast<Expression*>(factory->NewVariableProxy(input.FromJust())) :
6331 factory->NewUndefinedLiteral(nopos); 6353 factory->NewUndefinedLiteral(nopos);
6332 6354
6333 Statement* return_undefined = factory->NewReturnStatement(value, nopos); 6355 Statement* return_undefined = factory->NewReturnStatement(value, nopos);
6334 6356
6335 check_return = 6357 check_return = factory->NewIfStatement(
6336 factory->NewIfStatement(condition, return_undefined, skip, nopos); 6358 condition, return_undefined, factory->NewEmptyStatement(nopos), nopos);
6337 } 6359 }
6338 6360
6339 // let output = %_Call(iteratorReturn, iterator); OR 6361
6340 // output = %_Call(iteratorReturn, iterator, input); 6362 // output = %_Call(iteratorReturn, iterator|, input|);
Dan Ehrenberg 2016/02/16 21:18:30 Not sure why you're passing input to return. This
rossberg 2016/02/17 12:54:45 Fixed.
6341 Statement* call_return; 6363 Statement* call_return;
6342 { 6364 {
6343 auto args = new (zone) ZoneList<Expression*>(3, zone); 6365 auto args = new (zone) ZoneList<Expression*>(3, zone);
6344 args->Add(factory->NewVariableProxy(var), zone); 6366 args->Add(factory->NewVariableProxy(var_return), zone);
6345 args->Add(factory->NewVariableProxy(iterator), zone); 6367 args->Add(factory->NewVariableProxy(iterator), zone);
6346 if (input.IsJust()) { 6368 if (input.IsJust()) {
6347 args->Add(factory->NewVariableProxy(input.FromJust()), zone); 6369 args->Add(factory->NewVariableProxy(input.FromJust()), zone);
6348 } 6370 }
6349 6371
6350 Expression* call = 6372 Expression* call =
6351 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos); 6373 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6352 Expression* output_proxy = factory->NewVariableProxy( 6374 Expression* output_proxy = factory->NewVariableProxy(var_output);
6353 output.IsJust() ? output.FromJust() : var);
6354 Expression* assignment = factory->NewAssignment( 6375 Expression* assignment = factory->NewAssignment(
6355 Token::ASSIGN, output_proxy, call, nopos); 6376 Token::ASSIGN, output_proxy, call, nopos);
6356 call_return = factory->NewExpressionStatement(assignment, nopos); 6377 call_return = factory->NewExpressionStatement(assignment, nopos);
6357 } 6378 }
6358 6379
6359 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output); 6380
6381 // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output);
6360 Statement* validate_output; 6382 Statement* validate_output;
6361 { 6383 {
6362 Expression* is_receiver_call; 6384 Expression* is_receiver_call;
6363 { 6385 {
6364 auto args = new (zone) ZoneList<Expression*>(1, zone); 6386 auto args = new (zone) ZoneList<Expression*>(1, zone);
6365 args->Add(factory->NewVariableProxy(var), zone); 6387 args->Add(factory->NewVariableProxy(var_output), zone);
6366 is_receiver_call = 6388 is_receiver_call =
6367 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos); 6389 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6368 } 6390 }
6369 6391
6370 Statement* throw_call; 6392 Statement* throw_call;
6371 { 6393 {
6372 auto args = new (zone) ZoneList<Expression*>(1, zone); 6394 auto args = new (zone) ZoneList<Expression*>(1, zone);
6373 args->Add(factory->NewVariableProxy(var), zone); 6395 args->Add(factory->NewVariableProxy(var_output), zone);
6374 Expression* call = factory->NewCallRuntime( 6396 Expression* call = factory->NewCallRuntime(
6375 Runtime::kThrowIteratorResultNotAnObject, args, nopos); 6397 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6376 throw_call = factory->NewExpressionStatement(call, nopos); 6398 throw_call = factory->NewExpressionStatement(call, nopos);
6377 } 6399 }
6378 6400
6379 validate_output = 6401 validate_output = factory->NewIfStatement(
6380 factory->NewIfStatement(is_receiver_call, skip, throw_call, nopos); 6402 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6381 } 6403 }
6382 6404
6405
6383 statements->Add(get_return, zone); 6406 statements->Add(get_return, zone);
6384 statements->Add(check_return, zone); 6407 statements->Add(check_return, zone);
6385 statements->Add(call_return, zone); 6408 statements->Add(call_return, zone);
6386 statements->Add(validate_output, zone); 6409 statements->Add(validate_output, zone);
6387 } 6410 }
6388 6411
6389 6412
6413 // Runtime encoding of different completion modes.
6414 enum ForOfLoopCompletion { THROW, RETURN_OR_BREAK, NORMAL };
Dan Ehrenberg 2016/02/16 21:18:30 This seems to correspond to JSGeneratorObject::Res
rossberg 2016/02/17 12:54:45 Here it only talks about the completion of the loo
6415
6416 void ParserTraits::BuildIteratorCloseForCompletion(
6417 ZoneList<Statement*>* statements, Variable* iterator,
6418 Variable* completion) {
6419 //
6420 // This function adds two statements to [statements], corresponding to the
6421 // following code:
6422 //
6423 // let iteratorReturn = iterator.return;
6424 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
6425 // let output;
6426 // if (completion === THROW) {
6427 // if (!IS_CALLABLE(iteratorReturn)) {
6428 // throw MakeTypeError(kReturnMethodNotCallable);
6429 // }
6430 // try { output = %_Call(iteratorReturn, iterator) } catch (_) { }
6431 // } else {
6432 // output = %_Call(iteratorReturn, iterator);
6433 // }
6434 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
6435 // }
6436 //
6437
6438 const int nopos = RelocInfo::kNoPosition;
6439 auto factory = parser_->factory();
6440 auto avfactory = parser_->ast_value_factory();
6441 auto scope = parser_->scope_;
6442 auto zone = parser_->zone();
6443
6444
6445 // let output;
6446 Variable* var_output = scope->NewTemporary(avfactory->empty_string());
6447
6448
6449 // let iteratorReturn = iterator.return;
6450 Variable* var_return = var_output; // Reusing the output variable.
6451 Statement* get_return;
6452 {
6453 Expression* iterator_proxy = factory->NewVariableProxy(iterator);
6454 Expression* literal =
6455 factory->NewStringLiteral(avfactory->return_string(), nopos);
6456 Expression* property =
6457 factory->NewProperty(iterator_proxy, literal, nopos);
6458 Expression* return_proxy = factory->NewVariableProxy(var_return);
6459 Expression* assignment = factory->NewAssignment(
6460 Token::ASSIGN, return_proxy, property, nopos);
6461 get_return = factory->NewExpressionStatement(assignment, nopos);
6462 }
6463
6464
6465 // if (!IS_CALLABLE(iteratorReturn)) {
6466 // throw MakeTypeError(kReturnMethodNotCallable);
6467 // }
6468 Statement* check_return_callable;
6469 {
6470 Expression* type_of = factory->NewUnaryOperation(
6471 Token::TYPEOF, factory->NewVariableProxy(var_return), nopos);
6472 Expression* function_literal = factory->NewStringLiteral(
6473 avfactory->function_string(), nopos);
6474 Expression* condition = factory->NewCompareOperation(
6475 Token::EQ_STRICT, type_of, function_literal, nopos);
Dan Ehrenberg 2016/02/16 21:18:30 FYI mvstanton@: Here's how you can do IsCallable i
mvstanton 2016/02/16 22:55:46 Thanks Dan! Over in my CL I'll put this into a met
rossberg 2016/02/17 12:54:45 Makes sense. Okay, whoever lands second should rem
6476
6477 Expression* call = NewThrowTypeError(
6478 MessageTemplate::kReturnMethodNotCallable,
6479 avfactory->empty_string(), nopos);
6480 Statement* throw_call = factory->NewExpressionStatement(call, nopos);
6481
6482 check_return_callable = factory->NewIfStatement(
6483 condition, factory->NewEmptyStatement(nopos), throw_call, nopos);
6484 }
6485
6486
6487 // output = %_Call(iteratorReturn, iterator);
6488 Statement* call_return;
6489 {
6490 auto args = new (zone) ZoneList<Expression*>(2, zone);
6491 args->Add(factory->NewVariableProxy(var_return), zone);
6492 args->Add(factory->NewVariableProxy(iterator), zone);
6493 Expression* call =
6494 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6495
6496 Expression* output_proxy = factory->NewVariableProxy(var_output);
6497 Expression* assignment = factory->NewAssignment(
6498 Token::ASSIGN, output_proxy, call, nopos);
6499 call_return = factory->NewExpressionStatement(assignment, nopos);
6500 }
6501
6502
6503 // try { output = %_Call(iteratorReturn, iterator) } catch (_) { }
6504 Statement* try_call_return;
6505 {
6506 auto args = new (zone) ZoneList<Expression*>(2, zone);
6507 args->Add(factory->NewVariableProxy(var_return), zone);
6508 args->Add(factory->NewVariableProxy(iterator), zone);
6509
6510 Expression* call =
6511 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6512 Expression* assignment = factory->NewAssignment(
6513 Token::ASSIGN, factory->NewVariableProxy(var_output), call, nopos);
6514
6515 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6516 try_block->statements()->Add(
6517 factory->NewExpressionStatement(assignment, nopos), zone);
6518
6519 Block* catch_block = factory->NewBlock(nullptr, 0, false, nopos);
6520
6521 Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
6522 Variable* catch_variable = catch_scope->DeclareLocal(
6523 avfactory->dot_catch_string(), VAR, kCreatedInitialized,
6524 Variable::NORMAL);
6525
6526 try_call_return = factory->NewTryCatchStatement(
6527 try_block, catch_scope, catch_variable, catch_block, nopos);
6528 }
6529
6530
6531 // if (completion === THROW) {
6532 // #check_return_callable;
6533 // #try_call_return;
6534 // } else {
6535 // #call_return;
6536 // }
6537 Statement* call_return_carefully;
6538 {
6539 Expression* condition = factory->NewCompareOperation(
6540 Token::EQ_STRICT, factory->NewVariableProxy(completion),
6541 factory->NewSmiLiteral(THROW, nopos), nopos);
6542
6543 Block* then_block = factory->NewBlock(nullptr, 2, false, nopos);
6544 then_block->statements()->Add(check_return_callable, zone);
6545 then_block->statements()->Add(try_call_return, zone);
6546
6547 call_return_carefully =
6548 factory->NewIfStatement(condition, then_block, call_return, nopos);
6549 }
6550
6551
6552 // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output);
6553 Statement* validate_output;
6554 {
6555 Expression* is_receiver_call;
6556 {
6557 auto args = new (zone) ZoneList<Expression*>(1, zone);
6558 args->Add(factory->NewVariableProxy(var_output), zone);
6559 is_receiver_call =
6560 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6561 }
6562
6563 Statement* throw_call;
6564 {
6565 auto args = new (zone) ZoneList<Expression*>(1, zone);
6566 args->Add(factory->NewVariableProxy(var_output), zone);
6567 Expression* call = factory->NewCallRuntime(
6568 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6569 throw_call = factory->NewExpressionStatement(call, nopos);
6570 }
6571
6572 validate_output = factory->NewIfStatement(
6573 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6574 }
6575
6576
6577 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { ... }
Dan Ehrenberg 2016/02/16 21:18:30 Nit: All your other comments fully say what statem
rossberg 2016/02/17 12:54:45 Actually, not true. The convention (see also Rewri
6578 Statement* maybe_call_return;
6579 {
6580 Expression* condition = factory->NewCompareOperation(
6581 Token::EQ, factory->NewVariableProxy(var_return),
6582 factory->NewNullLiteral(nopos), nopos);
6583
6584 Block* block = factory->NewBlock(nullptr, 2, false, nopos);
6585 block->statements()->Add(call_return_carefully, zone);
6586 block->statements()->Add(validate_output, zone); // GAGA
Dan Ehrenberg 2016/02/16 21:18:30 GAGA? I don't really see anything funny about this
rossberg 2016/02/17 12:54:45 I missed that one, removed. You'll have to ask Geo
6587
6588 maybe_call_return = factory->NewIfStatement(
6589 condition, factory->NewEmptyStatement(nopos), block, nopos);
6590 }
6591
6592
6593 statements->Add(get_return, zone);
6594 statements->Add(maybe_call_return, zone);
6595 }
6596
6597
6598 Statement* ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) {
6599 //
6600 // This function replaces the loop with the following wrapping:
6601 //
6602 // let completion = RETURN_OR_BREAK;
6603 // try {
6604 // #loop;
6605 // } catch(e) {
6606 // completion = THROW;
6607 // throw e;
6608 // } finally {
6609 // if (!(completion === NORMAL || IS_UNDEFINED(#iterator))) {
6610 // #BuildIteratorClose(#iterator, completion) // See above.
6611 // }
6612 // }
6613 //
6614 // where the loop's body is wrapped as follows:
6615 //
6616 // {
6617 // {{completion = RETURN_OR_BREAK;}}
6618 // #loop-body
6619 // {{completion = NORMAL;}}
6620 // }
6621
6622 const int nopos = RelocInfo::kNoPosition;
Dan Ehrenberg 2016/02/16 21:18:30 This desugaring uses nopos for everything. Is that
rossberg 2016/02/17 12:54:45 This is done in various other functions already. I
6623 auto factory = parser_->factory();
6624 auto avfactory = parser_->ast_value_factory();
6625 auto scope = parser_->scope_;
6626 auto zone = parser_->zone();
6627
6628 // let completion = RETURN_OR_BREAK;
6629 Variable* var_completion = scope->NewTemporary(avfactory->empty_string());
6630 Statement* initialize_completion;
6631 {
6632 Expression* proxy = factory->NewVariableProxy(var_completion);
6633 Expression* assignment = factory->NewAssignment(
6634 Token::ASSIGN, proxy,
6635 factory->NewSmiLiteral(RETURN_OR_BREAK, nopos), nopos);
6636 initialize_completion =
6637 factory->NewExpressionStatement(assignment, nopos);
6638 }
6639
6640 // completion = THROW;
6641 Statement* set_completion_throw;
6642 {
6643 Expression* proxy = factory->NewVariableProxy(var_completion);
6644 Expression* assignment = factory->NewAssignment(
6645 Token::ASSIGN, proxy, factory->NewSmiLiteral(THROW, nopos), nopos);
6646 set_completion_throw = factory->NewExpressionStatement(assignment, nopos);
6647 }
6648
6649 // if (!(completion === NORMAL || IS_UNDEFINED(#iterator))) {
6650 // #BuildIteratorClose(#iterator, completion)
6651 // }
6652 Block* maybe_close;
6653 {
6654 Expression* condition1 = factory->NewCompareOperation(
6655 Token::EQ_STRICT, factory->NewVariableProxy(var_completion),
6656 factory->NewSmiLiteral(NORMAL, nopos), nopos);
6657 Expression* condition2 = factory->NewCompareOperation(
6658 Token::EQ_STRICT, factory->NewVariableProxy(loop->iterator()),
6659 factory->NewUndefinedLiteral(nopos), nopos);
6660 Expression* condition = factory->NewBinaryOperation(
6661 Token::OR, condition1, condition2, nopos);
6662
6663 Block* block = factory->NewBlock(nullptr, 2, false, nopos);
6664 BuildIteratorClose(
6665 block->statements(), loop->iterator(), var_completion);
6666 DCHECK(block->statements()->length() == 2);
6667
6668 maybe_close = factory->NewBlock(nullptr, 1, false, nopos);
6669 maybe_close->statements()->Add(factory->NewIfStatement(
6670 condition, factory->NewEmptyStatement(nopos), block, nopos), zone);
6671 }
6672
6673 // try { #try_block }
6674 // catch(e) {
6675 // #set_completion_throw;
6676 // throw e;
6677 // }
6678 Statement* try_catch;
6679 {
6680 Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
6681 Variable* catch_variable = catch_scope->DeclareLocal(
6682 avfactory->dot_catch_string(), VAR, kCreatedInitialized,
6683 Variable::NORMAL);
6684
6685 Statement* rethrow;
6686 {
6687 Expression* proxy = factory->NewVariableProxy(catch_variable);
6688 rethrow = factory->NewExpressionStatement(
6689 factory->NewThrow(proxy, nopos), nopos);
6690 }
6691
6692 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6693 try_block->statements()->Add(loop, zone);
6694
6695 Block* catch_block = factory->NewBlock(nullptr, 2, false, nopos);
6696 catch_block->statements()->Add(set_completion_throw, zone);
6697 catch_block->statements()->Add(rethrow, zone);
6698
6699 try_catch = factory->NewTryCatchStatement(
6700 try_block, catch_scope, catch_variable, catch_block, nopos);
6701 }
6702
6703 // try { #try_catch } finally { #maybe_close }
6704 Statement* try_finally;
6705 {
6706 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6707 try_block->statements()->Add(try_catch, zone);
6708
6709 try_finally =
6710 factory->NewTryFinallyStatement(try_block, maybe_close, nopos);
6711 }
6712
6713 // #initialize_completion;
6714 // #try_finally;
6715 Statement* final_loop;
6716 {
6717 Block* block = factory->NewBlock(nullptr, 2, false, nopos);
6718 block->statements()->Add(initialize_completion, zone);
6719 block->statements()->Add(try_finally, zone);
6720 final_loop = block;
6721 }
6722
6723 // {{completion = RETURN_OR_BREAK;}}
6724 Statement* set_completion_break;
6725 {
6726 Expression* proxy = factory->NewVariableProxy(var_completion);
6727 Expression* assignment = factory->NewAssignment(
6728 Token::ASSIGN, proxy,
6729 factory->NewSmiLiteral(RETURN_OR_BREAK, nopos), nopos);
6730
6731 Block* block = factory->NewBlock(nullptr, 1, true, nopos);
6732 block->statements()->Add(
6733 factory->NewExpressionStatement(assignment, nopos), zone);
6734 set_completion_break = block;
6735 }
6736
6737 // {{completion = NORMAL;}}
6738 Statement* set_completion_normal;
6739 {
6740 Expression* proxy = factory->NewVariableProxy(var_completion);
6741 Expression* assignment = factory->NewAssignment(
6742 Token::ASSIGN, proxy, factory->NewSmiLiteral(NORMAL, nopos), nopos);
6743
6744 Block* block = factory->NewBlock(nullptr, 1, true, nopos);
6745 block->statements()->Add(
6746 factory->NewExpressionStatement(assignment, nopos), zone);
6747 set_completion_normal = block;
6748 }
6749
6750 // { #set_completion_break; #loop-body; #set_completion_normal }
6751 Block* new_body = factory->NewBlock(nullptr, 2, false, nopos);
6752 new_body->statements()->Add(set_completion_break, zone);
6753 new_body->statements()->Add(loop->body(), zone);
6754 new_body->statements()->Add(set_completion_normal, zone);
6755
6756 loop->set_body(new_body);
6757 return final_loop;
6758 }
6759
6760
6390 } // namespace internal 6761 } // namespace internal
6391 } // namespace v8 6762 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698