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

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

Issue 2638333002: Parsing:Create the same scopes for non-simple params in PreParser & Parser. (Closed)
Patch Set: rest of the impl Created 3 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 <memory> 7 #include <memory>
8 8
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/ast/ast-expression-rewriter.h" 10 #include "src/ast/ast-expression-rewriter.h"
(...skipping 1736 matching lines...) Expand 10 before | Expand all | Expand 10 after
1747 DCHECK_NOT_NULL(catch_info.scope); 1747 DCHECK_NOT_NULL(catch_info.scope);
1748 DCHECK_NOT_NULL(catch_info.variable); 1748 DCHECK_NOT_NULL(catch_info.variable);
1749 return factory()->NewTryCatchStatement( 1749 return factory()->NewTryCatchStatement(
1750 try_block, catch_info.scope, catch_info.variable, catch_block, pos); 1750 try_block, catch_info.scope, catch_info.variable, catch_block, pos);
1751 } else { 1751 } else {
1752 DCHECK_NOT_NULL(finally_block); 1752 DCHECK_NOT_NULL(finally_block);
1753 return factory()->NewTryFinallyStatement(try_block, finally_block, pos); 1753 return factory()->NewTryFinallyStatement(try_block, finally_block, pos);
1754 } 1754 }
1755 } 1755 }
1756 1756
1757 void Parser::ParseAndRewriteGeneratorFunctionBody(int pos, FunctionKind kind,
1758 ZoneList<Statement*>* body,
1759 bool* ok) {
1760 // We produce:
1761 //
1762 // try { InitialYield; ...body...; return {value: undefined, done: true} }
1763 // finally { %_GeneratorClose(generator) }
1764 //
1765 // - InitialYield yields the actual generator object.
1766 // - Any return statement inside the body will have its argument wrapped
1767 // in a "done" iterator result object.
1768 // - If the generator terminates for whatever reason, we must close it.
1769 // Hence the finally clause.
1770
1771 Block* try_block = factory()->NewBlock(nullptr, 3, false, kNoSourcePosition);
1772 Expression* initial_yield = BuildInitialYield(pos, kind);
1773 try_block->statements()->Add(
1774 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition),
1775 zone());
1776 ParseStatementList(try_block->statements(), Token::RBRACE, ok);
1777 if (!*ok) return;
1778
1779 Statement* final_return = factory()->NewReturnStatement(
1780 BuildIteratorResult(nullptr, true), kNoSourcePosition);
1781 try_block->statements()->Add(final_return, zone());
1782
1783 Block* finally_block =
1784 factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
1785 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
1786 VariableProxy* call_proxy =
1787 factory()->NewVariableProxy(function_state_->generator_object_variable());
1788 args->Add(call_proxy, zone());
1789 Expression* call = factory()->NewCallRuntime(Runtime::kInlineGeneratorClose,
1790 args, kNoSourcePosition);
1791 finally_block->statements()->Add(
1792 factory()->NewExpressionStatement(call, kNoSourcePosition), zone());
1793
1794 body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
1795 kNoSourcePosition),
1796 zone());
1797 }
1798
1799 void Parser::CreateFunctionNameAssignment(
1800 const AstRawString* function_name, int pos,
1801 FunctionLiteral::FunctionType function_type,
1802 DeclarationScope* function_scope, ZoneList<Statement*>* result, int index) {
1803 if (function_type == FunctionLiteral::kNamedExpression) {
1804 StatementT statement = factory()->NewEmptyStatement(kNoSourcePosition);
1805 if (function_scope->LookupLocal(function_name) == nullptr) {
1806 // Now that we know the language mode, we can create the const assignment
1807 // in the previously reserved spot.
1808 DCHECK_EQ(function_scope, scope());
1809 Variable* fvar = function_scope->DeclareFunctionVar(function_name);
1810 VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
1811 statement = factory()->NewExpressionStatement(
1812 factory()->NewAssignment(Token::INIT, fproxy,
1813 factory()->NewThisFunction(pos),
1814 kNoSourcePosition),
1815 kNoSourcePosition);
1816 }
1817 result->Set(index, statement);
1818 }
1819 }
1820
1757 // !%_IsJSReceiver(result = iterator.next()) && 1821 // !%_IsJSReceiver(result = iterator.next()) &&
1758 // %ThrowIteratorResultNotAnObject(result) 1822 // %ThrowIteratorResultNotAnObject(result)
1759 Expression* Parser::BuildIteratorNextResult(Expression* iterator, 1823 Expression* Parser::BuildIteratorNextResult(Expression* iterator,
1760 Variable* result, int pos) { 1824 Variable* result, int pos) {
1761 Expression* next_literal = factory()->NewStringLiteral( 1825 Expression* next_literal = factory()->NewStringLiteral(
1762 ast_value_factory()->next_string(), kNoSourcePosition); 1826 ast_value_factory()->next_string(), kNoSourcePosition);
1763 Expression* next_property = 1827 Expression* next_property =
1764 factory()->NewProperty(iterator, next_literal, kNoSourcePosition); 1828 factory()->NewProperty(iterator, next_literal, kNoSourcePosition);
1765 ZoneList<Expression*>* next_arguments = 1829 ZoneList<Expression*>* next_arguments =
1766 new (zone()) ZoneList<Expression*>(0, zone()); 1830 new (zone()) ZoneList<Expression*>(0, zone());
(...skipping 1146 matching lines...) Expand 10 before | Expand all | Expand 10 after
2913 if (param_scope != nullptr) { 2977 if (param_scope != nullptr) {
2914 CheckConflictingVarDeclarations(param_scope, CHECK_OK); 2978 CheckConflictingVarDeclarations(param_scope, CHECK_OK);
2915 } 2979 }
2916 init_block->statements()->Add(param_block, zone()); 2980 init_block->statements()->Add(param_block, zone());
2917 } 2981 }
2918 ++index; 2982 ++index;
2919 } 2983 }
2920 return init_block; 2984 return init_block;
2921 } 2985 }
2922 2986
2923 Block* Parser::BuildRejectPromiseOnException(Block* inner_block, bool* ok) { 2987 Block* Parser::BuildRejectPromiseOnException(Block* inner_block) {
2924 // .promise = %AsyncFunctionPromiseCreate(); 2988 // .promise = %AsyncFunctionPromiseCreate();
2925 // try { 2989 // try {
2926 // <inner_block> 2990 // <inner_block>
2927 // } catch (.catch) { 2991 // } catch (.catch) {
2928 // %RejectPromise(.promise, .catch); 2992 // %RejectPromise(.promise, .catch);
2929 // return .promise; 2993 // return .promise;
2930 // } finally { 2994 // } finally {
2931 // %AsyncFunctionPromiseRelease(.promise); 2995 // %AsyncFunctionPromiseRelease(.promise);
2932 // } 2996 // }
2933 Block* result = factory()->NewBlock(nullptr, 2, true, kNoSourcePosition); 2997 Block* result = factory()->NewBlock(nullptr, 2, true, kNoSourcePosition);
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
3075 Expect(Token::RPAREN, CHECK_OK); 3139 Expect(Token::RPAREN, CHECK_OK);
3076 int formals_end_position = scanner()->location().end_pos; 3140 int formals_end_position = scanner()->location().end_pos;
3077 *num_parameters = formals.num_parameters(); 3141 *num_parameters = formals.num_parameters();
3078 *function_length = formals.function_length; 3142 *function_length = formals.function_length;
3079 3143
3080 CheckArityRestrictions(formals.arity, kind, formals.has_rest, 3144 CheckArityRestrictions(formals.arity, kind, formals.has_rest,
3081 function_scope->start_position(), formals_end_position, 3145 function_scope->start_position(), formals_end_position,
3082 CHECK_OK); 3146 CHECK_OK);
3083 Expect(Token::LBRACE, CHECK_OK); 3147 Expect(Token::LBRACE, CHECK_OK);
3084 3148
3085 ZoneList<Statement*>* body = ParseEagerFunctionBody( 3149 ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(8, zone());
3086 function_name, pos, formals, kind, function_type, ok); 3150 ParseFunctionBody(body, function_name, pos, formals, kind, function_type, ok);
3087 3151
3088 // Validate parameter names. We can do this only after parsing the function, 3152 // Validate parameter names. We can do this only after parsing the function,
3089 // since the function can declare itself strict. 3153 // since the function can declare itself strict.
3090 const bool allow_duplicate_parameters = 3154 const bool allow_duplicate_parameters =
3091 is_sloppy(function_scope->language_mode()) && formals.is_simple && 3155 is_sloppy(function_scope->language_mode()) && formals.is_simple &&
3092 !IsConciseMethod(kind); 3156 !IsConciseMethod(kind);
3093 ValidateFormalParameters(function_scope->language_mode(), 3157 ValidateFormalParameters(function_scope->language_mode(),
3094 allow_duplicate_parameters, CHECK_OK); 3158 allow_duplicate_parameters, CHECK_OK);
3095 3159
3096 RewriteDestructuringAssignments(); 3160 RewriteDestructuringAssignments();
3097 3161
3098 *has_duplicate_parameters = 3162 *has_duplicate_parameters =
3099 !classifier()->is_valid_formal_parameter_list_without_duplicates(); 3163 !classifier()->is_valid_formal_parameter_list_without_duplicates();
3100 3164
3101 *materialized_literal_count = function_state.materialized_literal_count(); 3165 *materialized_literal_count = function_state.materialized_literal_count();
3102 *expected_property_count = function_state.expected_property_count(); 3166 *expected_property_count = function_state.expected_property_count();
3103 return body; 3167 return body;
3104 } 3168 }
3105 3169
3106 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
3107 const AstRawString* function_name, int pos,
3108 const ParserFormalParameters& parameters, FunctionKind kind,
3109 FunctionLiteral::FunctionType function_type, bool* ok) {
3110 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
3111
3112 static const int kFunctionNameAssignmentIndex = 0;
3113 if (function_type == FunctionLiteral::kNamedExpression) {
3114 DCHECK(function_name != NULL);
3115 // If we have a named function expression, we add a local variable
3116 // declaration to the body of the function with the name of the
3117 // function and let it refer to the function itself (closure).
3118 // Not having parsed the function body, the language mode may still change,
3119 // so we reserve a spot and create the actual const assignment later.
3120 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length());
3121 result->Add(NULL, zone());
3122 }
3123
3124 ZoneList<Statement*>* body = result;
3125 DeclarationScope* function_scope = scope()->AsDeclarationScope();
3126 DeclarationScope* inner_scope = function_scope;
3127 Block* inner_block = nullptr;
3128 if (!parameters.is_simple) {
3129 inner_scope = NewVarblockScope();
3130 inner_scope->set_start_position(scanner()->location().beg_pos);
3131 inner_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition);
3132 inner_block->set_scope(inner_scope);
3133 body = inner_block->statements();
3134 }
3135
3136 {
3137 BlockState block_state(&scope_state_, inner_scope);
3138
3139 if (IsGeneratorFunction(kind)) {
3140 // We produce:
3141 //
3142 // try { InitialYield; ...body...; return {value: undefined, done: true} }
3143 // finally { %_GeneratorClose(generator) }
3144 //
3145 // - InitialYield yields the actual generator object.
3146 // - Any return statement inside the body will have its argument wrapped
3147 // in a "done" iterator result object.
3148 // - If the generator terminates for whatever reason, we must close it.
3149 // Hence the finally clause.
3150
3151 Block* try_block =
3152 factory()->NewBlock(nullptr, 3, false, kNoSourcePosition);
3153 Expression* initial_yield = BuildInitialYield(pos, kind);
3154 try_block->statements()->Add(
3155 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition),
3156 zone());
3157 ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK);
3158
3159 Statement* final_return = factory()->NewReturnStatement(
3160 BuildIteratorResult(nullptr, true), kNoSourcePosition);
3161 try_block->statements()->Add(final_return, zone());
3162
3163 Block* finally_block =
3164 factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
3165 ZoneList<Expression*>* args =
3166 new (zone()) ZoneList<Expression*>(1, zone());
3167 VariableProxy* call_proxy = factory()->NewVariableProxy(
3168 function_state_->generator_object_variable());
3169 args->Add(call_proxy, zone());
3170 Expression* call = factory()->NewCallRuntime(
3171 Runtime::kInlineGeneratorClose, args, kNoSourcePosition);
3172 finally_block->statements()->Add(
3173 factory()->NewExpressionStatement(call, kNoSourcePosition), zone());
3174
3175 body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
3176 kNoSourcePosition),
3177 zone());
3178 } else if (IsAsyncFunction(kind)) {
3179 const bool accept_IN = true;
3180 ParseAsyncFunctionBody(inner_scope, body, kind, FunctionBodyType::kNormal,
3181 accept_IN, pos, CHECK_OK);
3182 } else {
3183 ParseStatementList(body, Token::RBRACE, CHECK_OK);
3184 }
3185
3186 if (IsDerivedConstructor(kind)) {
3187 body->Add(factory()->NewReturnStatement(ThisExpression(kNoSourcePosition),
3188 kNoSourcePosition),
3189 zone());
3190 }
3191 }
3192
3193 Expect(Token::RBRACE, CHECK_OK);
3194 scope()->set_end_position(scanner()->location().end_pos);
3195
3196 if (!parameters.is_simple) {
3197 DCHECK_NOT_NULL(inner_scope);
3198 DCHECK_EQ(function_scope, scope());
3199 DCHECK_EQ(function_scope, inner_scope->outer_scope());
3200 DCHECK_EQ(body, inner_block->statements());
3201 SetLanguageMode(function_scope, inner_scope->language_mode());
3202 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
3203
3204 if (is_sloppy(inner_scope->language_mode())) {
3205 InsertSloppyBlockFunctionVarBindings(inner_scope);
3206 }
3207
3208 // TODO(littledan): Merge the two rejection blocks into one
3209 if (IsAsyncFunction(kind)) {
3210 init_block = BuildRejectPromiseOnException(init_block, CHECK_OK);
3211 }
3212
3213 DCHECK_NOT_NULL(init_block);
3214
3215 inner_scope->set_end_position(scanner()->location().end_pos);
3216 if (inner_scope->FinalizeBlockScope() != nullptr) {
3217 CheckConflictingVarDeclarations(inner_scope, CHECK_OK);
3218 InsertShadowingVarBindingInitializers(inner_block);
3219 }
3220 inner_scope = nullptr;
3221
3222 result->Add(init_block, zone());
3223 result->Add(inner_block, zone());
3224 } else {
3225 DCHECK_EQ(inner_scope, function_scope);
3226 if (is_sloppy(function_scope->language_mode())) {
3227 InsertSloppyBlockFunctionVarBindings(function_scope);
3228 }
3229 }
3230
3231 if (!IsArrowFunction(kind)) {
3232 // Declare arguments after parsing the function since lexical 'arguments'
3233 // masks the arguments object. Declare arguments before declaring the
3234 // function var since the arguments object masks 'function arguments'.
3235 function_scope->DeclareArguments(ast_value_factory());
3236 }
3237
3238 if (function_type == FunctionLiteral::kNamedExpression) {
3239 Statement* statement;
3240 if (function_scope->LookupLocal(function_name) == nullptr) {
3241 // Now that we know the language mode, we can create the const assignment
3242 // in the previously reserved spot.
3243 DCHECK_EQ(function_scope, scope());
3244 Variable* fvar = function_scope->DeclareFunctionVar(function_name);
3245 VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
3246 statement = factory()->NewExpressionStatement(
3247 factory()->NewAssignment(Token::INIT, fproxy,
3248 factory()->NewThisFunction(pos),
3249 kNoSourcePosition),
3250 kNoSourcePosition);
3251 } else {
3252 statement = factory()->NewEmptyStatement(kNoSourcePosition);
3253 }
3254 result->Set(kFunctionNameAssignmentIndex, statement);
3255 }
3256
3257 MarkCollectedTailCallExpressions();
3258 return result;
3259 }
3260
3261 void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope, 3170 void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope,
3262 ClassInfo* class_info, int class_token_pos, 3171 ClassInfo* class_info, int class_token_pos,
3263 bool* ok) { 3172 bool* ok) {
3264 #ifdef DEBUG 3173 #ifdef DEBUG
3265 scope()->SetScopeName(name); 3174 scope()->SetScopeName(name);
3266 #endif 3175 #endif
3267 3176
3268 if (name != nullptr) { 3177 if (name != nullptr) {
3269 class_info->proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); 3178 class_info->proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE);
3270 Declaration* declaration = factory()->NewVariableDeclaration( 3179 Declaration* declaration = factory()->NewVariableDeclaration(
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after
3873 // BuildRejectPromiseOnException({ 3782 // BuildRejectPromiseOnException({
3874 // ... block ... 3783 // ... block ...
3875 // return %ResolvePromise(.promise, expr), .promise; 3784 // return %ResolvePromise(.promise, expr), .promise;
3876 // }) 3785 // })
3877 // } 3786 // }
3878 3787
3879 return_value = BuildResolvePromise(return_value, return_value->position()); 3788 return_value = BuildResolvePromise(return_value, return_value->position());
3880 block->statements()->Add( 3789 block->statements()->Add(
3881 factory()->NewReturnStatement(return_value, return_value->position()), 3790 factory()->NewReturnStatement(return_value, return_value->position()),
3882 zone()); 3791 zone());
3883 block = BuildRejectPromiseOnException(block, CHECK_OK_VOID); 3792 block = BuildRejectPromiseOnException(block);
3884 body->Add(block, zone()); 3793 body->Add(block, zone());
3885 } 3794 }
3886 3795
3887 Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) { 3796 Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) {
3888 // yield do { 3797 // yield do {
3889 // tmp = <operand>; 3798 // tmp = <operand>;
3890 // %AsyncFunctionAwait(.generator_object, tmp, .promise); 3799 // %AsyncFunctionAwait(.generator_object, tmp, .promise);
3891 // .promise 3800 // .promise
3892 // } 3801 // }
3893 // The value of the expression is returned to the caller of the async 3802 // The value of the expression is returned to the caller of the async
(...skipping 1222 matching lines...) Expand 10 before | Expand all | Expand 10 after
5116 5025
5117 return final_loop; 5026 return final_loop;
5118 } 5027 }
5119 5028
5120 #undef CHECK_OK 5029 #undef CHECK_OK
5121 #undef CHECK_OK_VOID 5030 #undef CHECK_OK_VOID
5122 #undef CHECK_FAILED 5031 #undef CHECK_FAILED
5123 5032
5124 } // namespace internal 5033 } // namespace internal
5125 } // namespace v8 5034 } // 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