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

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

Issue 2322243002: Preparse inner functions. (Closed)
Patch Set: fixes Created 4 years 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 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 public: 115 public:
116 DiscardableZoneScope(Parser* parser, Zone* temp_zone, bool use_temp_zone) 116 DiscardableZoneScope(Parser* parser, Zone* temp_zone, bool use_temp_zone)
117 : ast_node_factory_scope_(parser->factory(), temp_zone, use_temp_zone), 117 : ast_node_factory_scope_(parser->factory(), temp_zone, use_temp_zone),
118 fni_(parser->ast_value_factory_, temp_zone), 118 fni_(parser->ast_value_factory_, temp_zone),
119 parser_(parser), 119 parser_(parser),
120 prev_fni_(parser->fni_), 120 prev_fni_(parser->fni_),
121 prev_zone_(parser->zone_) { 121 prev_zone_(parser->zone_) {
122 if (use_temp_zone) { 122 if (use_temp_zone) {
123 parser_->fni_ = &fni_; 123 parser_->fni_ = &fni_;
124 parser_->zone_ = temp_zone; 124 parser_->zone_ = temp_zone;
125 if (parser_->reusable_preparser_ != nullptr) {
126 parser_->reusable_preparser_->zone_ = temp_zone;
127 }
125 } 128 }
126 } 129 }
127 ~DiscardableZoneScope() { 130 ~DiscardableZoneScope() {
128 parser_->fni_ = prev_fni_; 131 parser_->fni_ = prev_fni_;
129 parser_->zone_ = prev_zone_; 132 parser_->zone_ = prev_zone_;
133 if (parser_->reusable_preparser_ != nullptr) {
134 parser_->reusable_preparser_->zone_ = prev_zone_;
135 }
130 } 136 }
131 137
132 private: 138 private:
133 AstNodeFactory::BodyScope ast_node_factory_scope_; 139 AstNodeFactory::BodyScope ast_node_factory_scope_;
134 FuncNameInferrer fni_; 140 FuncNameInferrer fni_;
135 Parser* parser_; 141 Parser* parser_;
136 FuncNameInferrer* prev_fni_; 142 FuncNameInferrer* prev_fni_;
137 Zone* prev_zone_; 143 Zone* prev_zone_;
138 144
139 DISALLOW_COPY_AND_ASSIGN(DiscardableZoneScope); 145 DISALLOW_COPY_AND_ASSIGN(DiscardableZoneScope);
(...skipping 2847 matching lines...) Expand 10 before | Expand all | Expand 10 after
2987 // - It must not have been prohibited by the caller to Parse (some callers 2993 // - It must not have been prohibited by the caller to Parse (some callers
2988 // need a full AST). 2994 // need a full AST).
2989 // - The outer scope must allow lazy compilation of inner functions. 2995 // - The outer scope must allow lazy compilation of inner functions.
2990 // - The function mustn't be a function expression with an open parenthesis 2996 // - The function mustn't be a function expression with an open parenthesis
2991 // before; we consider that a hint that the function will be called 2997 // before; we consider that a hint that the function will be called
2992 // immediately, and it would be a waste of time to make it lazily 2998 // immediately, and it would be a waste of time to make it lazily
2993 // compiled. 2999 // compiled.
2994 // These are all things we can know at this point, without looking at the 3000 // These are all things we can know at this point, without looking at the
2995 // function itself. 3001 // function itself.
2996 3002
2997 // In addition, we need to distinguish between these cases: 3003 // We separate between lazy parsing top level functions and lazy parsing inner
3004 // functions, because the latter needs to do more work. In particular, we need
3005 // to track unresolved variables to distinguish between these cases:
2998 // (function foo() { 3006 // (function foo() {
2999 // bar = function() { return 1; } 3007 // bar = function() { return 1; }
3000 // })(); 3008 // })();
3001 // and 3009 // and
3002 // (function foo() { 3010 // (function foo() {
3003 // var a = 1; 3011 // var a = 1;
3004 // bar = function() { return a; } 3012 // bar = function() { return a; }
3005 // })(); 3013 // })();
3006 3014
3007 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume 3015 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
3008 // parenthesis before the function means that it will be called 3016 // parenthesis before the function means that it will be called
3009 // immediately). The inner function *must* be parsed eagerly to resolve the 3017 // immediately). bar can be parsed lazily, but we need to parse it in a mode
3010 // possible reference to the variable in foo's scope. However, it's possible 3018 // that tracks unresolved variables.
3011 // that it will be compiled lazily. 3019 DCHECK_IMPLIES(mode() == PARSE_LAZILY, FLAG_lazy);
3020 DCHECK_IMPLIES(mode() == PARSE_LAZILY, allow_lazy());
3021 DCHECK_IMPLIES(mode() == PARSE_LAZILY, !allow_natives());
3022 DCHECK_IMPLIES(mode() == PARSE_LAZILY, extension_ == nullptr);
3012 3023
3013 // To make this additional case work, both Parser and PreParser implement a 3024 bool is_lazy_top_level_function =
3014 // logic where only top-level functions will be parsed lazily. 3025 mode() == PARSE_LAZILY &&
3015 bool is_lazily_parsed = mode() == PARSE_LAZILY && 3026 eager_compile_hint == FunctionLiteral::kShouldLazyCompile &&
3016 scope()->AllowsLazyParsing() && 3027 scope()->AllowsLazyParsingWithoutUnresolvedVariables();
3017 !function_state_->next_function_is_parenthesized();
3018 3028
3019 // Determine whether the function body can be discarded after parsing. 3029 // Determine whether we can still do the inner function lazy parsing.
3020 // The preconditions are: 3030 // The preconditions are:
3021 // - Lazy compilation has to be enabled. 3031 // - Lazy compilation has to be enabled.
3022 // - Neither V8 natives nor native function declarations can be allowed, 3032 // - Neither V8 natives nor native function declarations can be allowed,
3023 // since parsing one would retroactively force the function to be 3033 // since parsing one would retroactively force the function to be
3024 // eagerly compiled. 3034 // eagerly compiled.
3025 // - The invoker of this parser can't depend on the AST being eagerly 3035 // - The invoker of this parser can't depend on the AST being eagerly
3026 // built (either because the function is about to be compiled, or 3036 // built (either because the function is about to be compiled, or
3027 // because the AST is going to be inspected for some reason). 3037 // because the AST is going to be inspected for some reason).
3028 // - Because of the above, we can't be attempting to parse a 3038 // - Because of the above, we can't be attempting to parse a
3029 // FunctionExpression; even without enclosing parentheses it might be 3039 // FunctionExpression; even without enclosing parentheses it might be
3030 // immediately invoked. 3040 // immediately invoked.
3031 // - The function literal shouldn't be hinted to eagerly compile. 3041 // - The function literal shouldn't be hinted to eagerly compile.
3032 // - For asm.js functions the body needs to be available when module 3042 // - For asm.js functions the body needs to be available when module
3033 // validation is active, because we examine the entire module at once. 3043 // validation is active, because we examine the entire module at once.
3034 bool use_temp_zone = 3044
3035 !is_lazily_parsed && FLAG_lazy && !allow_natives() && 3045 // Inner functions will be parsed by using a temporary Zone. After parsing, we
3046 // will migrate unresolved variable into a Scope in the main Zone.
3047 // TODO(marja): Refactor parsing modes: simplify this.
3048 bool is_lazy_inner_function =
3049 !is_lazy_top_level_function && FLAG_lazy && !allow_natives() &&
3036 extension_ == NULL && allow_lazy() && 3050 extension_ == NULL && allow_lazy() &&
3037 function_type == FunctionLiteral::kDeclaration && 3051 function_type == FunctionLiteral::kDeclaration &&
3038 eager_compile_hint != FunctionLiteral::kShouldEagerCompile && 3052 eager_compile_hint != FunctionLiteral::kShouldEagerCompile &&
3039 !(FLAG_validate_asm && scope()->IsAsmModule()); 3053 !(FLAG_validate_asm && scope()->IsAsmModule());
3040 3054
3041 DeclarationScope* main_scope = nullptr; 3055 DeclarationScope* main_scope = nullptr;
3042 if (use_temp_zone) { 3056 if (is_lazy_inner_function) {
3043 // This Scope lives in the main Zone; we'll migrate data into it later. 3057 // This Scope lives in the main Zone; we'll migrate data into it later.
3044 main_scope = NewFunctionScope(kind); 3058 main_scope = NewFunctionScope(kind);
3045 } 3059 }
3046 3060
3047 ZoneList<Statement*>* body = nullptr; 3061 ZoneList<Statement*>* body = nullptr;
3048 int arity = -1; 3062 int arity = -1;
3049 int materialized_literal_count = -1; 3063 int materialized_literal_count = -1;
3050 int expected_property_count = -1; 3064 int expected_property_count = -1;
3051 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); 3065 DuplicateFinder duplicate_finder(scanner()->unicode_cache());
3052 bool should_be_used_once_hint = false; 3066 bool should_be_used_once_hint = false;
3053 bool has_duplicate_parameters; 3067 bool has_duplicate_parameters;
3054 3068
3055 { 3069 {
3056 // Temporary zones can nest. When we migrate free variables (see below), we 3070 // Temporary zones can nest. When we migrate free variables (see below), we
3057 // need to recreate them in the previous Zone. 3071 // need to recreate them in the previous Zone.
3058 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory()); 3072 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory());
3059 previous_zone_ast_node_factory.set_zone(zone()); 3073 previous_zone_ast_node_factory.set_zone(zone());
3060 3074
3061 // Open a new zone scope, which sets our AstNodeFactory to allocate in the 3075 // Open a new zone scope, which sets our AstNodeFactory to allocate in the
3062 // new temporary zone if the preconditions are satisfied, and ensures that 3076 // new temporary zone if the preconditions are satisfied, and ensures that
3063 // the previous zone is always restored after parsing the body. To be able 3077 // the previous zone is always restored after parsing the body. To be able
3064 // to do scope analysis correctly after full parsing, we migrate needed 3078 // to do scope analysis correctly after full parsing, we migrate needed
3065 // information from scope into main_scope when the function has been parsed. 3079 // information from scope into main_scope when the function has been parsed.
3066 Zone temp_zone(zone()->allocator()); 3080 Zone temp_zone(zone()->allocator());
3067 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone); 3081 DiscardableZoneScope zone_scope(this, &temp_zone, is_lazy_inner_function);
3068 3082
3069 DeclarationScope* scope = NewFunctionScope(kind); 3083 DeclarationScope* scope = NewFunctionScope(kind);
3070 SetLanguageMode(scope, language_mode); 3084 SetLanguageMode(scope, language_mode);
3071 if (!use_temp_zone) { 3085 if (!is_lazy_inner_function) {
3072 main_scope = scope; 3086 main_scope = scope;
3073 } else { 3087 } else {
3074 DCHECK(main_scope->zone() != scope->zone()); 3088 DCHECK(main_scope->zone() != scope->zone());
3075 } 3089 }
3076 3090
3077 FunctionState function_state(&function_state_, &scope_state_, scope, kind); 3091 FunctionState function_state(&function_state_, &scope_state_, scope, kind);
3078 #ifdef DEBUG 3092 #ifdef DEBUG
3079 scope->SetScopeName(function_name); 3093 scope->SetScopeName(function_name);
3080 #endif 3094 #endif
3081 ExpressionClassifier formals_classifier(this, &duplicate_finder); 3095 ExpressionClassifier formals_classifier(this, &duplicate_finder);
(...skipping 23 matching lines...) Expand all
3105 int formals_end_position = scanner()->location().end_pos; 3119 int formals_end_position = scanner()->location().end_pos;
3106 3120
3107 CheckArityRestrictions(arity, kind, formals.has_rest, start_position, 3121 CheckArityRestrictions(arity, kind, formals.has_rest, start_position,
3108 formals_end_position, CHECK_OK); 3122 formals_end_position, CHECK_OK);
3109 Expect(Token::LBRACE, CHECK_OK); 3123 Expect(Token::LBRACE, CHECK_OK);
3110 // Don't include the rest parameter into the function's formal parameter 3124 // Don't include the rest parameter into the function's formal parameter
3111 // count (esp. the SharedFunctionInfo::internal_formal_parameter_count, 3125 // count (esp. the SharedFunctionInfo::internal_formal_parameter_count,
3112 // which says whether we need to create an arguments adaptor frame). 3126 // which says whether we need to create an arguments adaptor frame).
3113 if (formals.has_rest) arity--; 3127 if (formals.has_rest) arity--;
3114 3128
3115 // Eager or lazy parse? 3129 // Eager or lazy parse? If is_lazy_top_level_function, we'll parse
3116 // If is_lazily_parsed, we'll parse lazily. We'll call SkipLazyFunctionBody, 3130 // lazily. We'll call SkipLazyFunctionBody, which may decide to abort lazy
3117 // which may decide to abort lazy parsing if it suspects that wasn't a good 3131 // parsing if it suspects that wasn't a good idea. If so (in which case the
3118 // idea. If so (in which case the parser is expected to have backtracked), 3132 // parser is expected to have backtracked), or if we didn't try to lazy
3119 // or if we didn't try to lazy parse in the first place, we'll have to parse 3133 // parse in the first place, we'll have to parse eagerly.
3120 // eagerly. 3134 if (is_lazy_top_level_function) {
3121 if (is_lazily_parsed) {
3122 Scanner::BookmarkScope bookmark(scanner()); 3135 Scanner::BookmarkScope bookmark(scanner());
3123 bool may_abort = bookmark.Set(); 3136 bool may_abort = bookmark.Set();
3124 LazyParsingResult result = 3137 LazyParsingResult result = SkipLazyFunctionBody(
3125 SkipLazyFunctionBody(&materialized_literal_count, 3138 &materialized_literal_count, &expected_property_count, false,
3126 &expected_property_count, may_abort, CHECK_OK); 3139 may_abort, CHECK_OK);
3127 3140
3128 materialized_literal_count += formals.materialized_literals_count + 3141 materialized_literal_count += formals.materialized_literals_count +
3129 function_state.materialized_literal_count(); 3142 function_state.materialized_literal_count();
3130 3143
3131 if (result == kLazyParsingAborted) { 3144 if (result == kLazyParsingAborted) {
3132 bookmark.Reset(); 3145 bookmark.Reset();
3133 // Trigger eager (re-)parsing, just below this block. 3146 // Trigger eager (re-)parsing, just below this block.
3134 is_lazily_parsed = false; 3147 is_lazy_top_level_function = false;
3135 3148
3136 // This is probably an initialization function. Inform the compiler it 3149 // This is probably an initialization function. Inform the compiler it
3137 // should also eager-compile this function, and that we expect it to be 3150 // should also eager-compile this function, and that we expect it to be
3138 // used once. 3151 // used once.
3139 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; 3152 eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
3140 should_be_used_once_hint = true; 3153 should_be_used_once_hint = true;
3141 } 3154 }
3142 } 3155 }
3143 if (!is_lazily_parsed) { 3156 if (is_lazy_inner_function) {
3157 if (FLAG_lazy_inner_functions) {
3158 LazyParsingResult result = SkipLazyFunctionBody(
3159 &materialized_literal_count, &expected_property_count, true, false,
3160 CHECK_OK);
3161 materialized_literal_count +=
3162 formals.materialized_literals_count +
3163 function_state.materialized_literal_count();
3164 DCHECK(result != kLazyParsingAborted);
3165 USE(result);
3166 } else {
3167 ParseEagerFunctionBody(function_name, pos, formals, kind, function_type,
3168 CHECK_OK);
3169 materialized_literal_count =
3170 function_state.materialized_literal_count();
3171 expected_property_count = function_state.expected_property_count();
3172 }
3173 } else if (!is_lazy_top_level_function) {
3144 body = ParseEagerFunctionBody(function_name, pos, formals, kind, 3174 body = ParseEagerFunctionBody(function_name, pos, formals, kind,
3145 function_type, CHECK_OK); 3175 function_type, CHECK_OK);
3146 3176
3147 materialized_literal_count = function_state.materialized_literal_count(); 3177 materialized_literal_count = function_state.materialized_literal_count();
3148 expected_property_count = function_state.expected_property_count(); 3178 expected_property_count = function_state.expected_property_count();
3149 if (use_temp_zone) {
3150 // If the preconditions are correct the function body should never be
3151 // accessed, but do this anyway for better behaviour if they're wrong.
3152 body = nullptr;
3153 }
3154 } 3179 }
3155 3180
3156 // Parsing the body may change the language mode in our scope. 3181 // Parsing the body may change the language mode in our scope.
3157 language_mode = scope->language_mode(); 3182 language_mode = scope->language_mode();
3158 scope->DeclareArguments(ast_value_factory()); 3183 scope->DeclareArguments(ast_value_factory());
3159 if (main_scope != scope) { 3184 if (main_scope != scope) {
3160 main_scope->DeclareArguments(ast_value_factory()); 3185 main_scope->DeclareArguments(ast_value_factory());
3161 } 3186 }
3162 3187
3163 // Validate name and parameter names. We can do this only after parsing the 3188 // Validate name and parameter names. We can do this only after parsing the
(...skipping 13 matching lines...) Expand all
3177 } 3202 }
3178 CheckConflictingVarDeclarations(scope, CHECK_OK); 3203 CheckConflictingVarDeclarations(scope, CHECK_OK);
3179 3204
3180 if (body) { 3205 if (body) {
3181 // If body can be inspected, rewrite queued destructuring assignments 3206 // If body can be inspected, rewrite queued destructuring assignments
3182 RewriteDestructuringAssignments(); 3207 RewriteDestructuringAssignments();
3183 } 3208 }
3184 has_duplicate_parameters = 3209 has_duplicate_parameters =
3185 !classifier()->is_valid_formal_parameter_list_without_duplicates(); 3210 !classifier()->is_valid_formal_parameter_list_without_duplicates();
3186 3211
3187 if (use_temp_zone) { 3212 if (is_lazy_inner_function) {
3188 DCHECK(main_scope != scope); 3213 DCHECK(main_scope != scope);
3189 scope->AnalyzePartially(main_scope, &previous_zone_ast_node_factory); 3214 scope->AnalyzePartially(main_scope, &previous_zone_ast_node_factory);
3190 } 3215 }
3191 } // DiscardableZoneScope goes out of scope. 3216 } // DiscardableZoneScope goes out of scope.
3192 3217
3193 FunctionLiteral::ParameterFlag duplicate_parameters = 3218 FunctionLiteral::ParameterFlag duplicate_parameters =
3194 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters 3219 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters
3195 : FunctionLiteral::kNoDuplicateParameters; 3220 : FunctionLiteral::kNoDuplicateParameters;
3196 3221
3197 // Note that the FunctionLiteral needs to be created in the main Zone again. 3222 // Note that the FunctionLiteral needs to be created in the main Zone again.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3231 } 3256 }
3232 return ParseFunctionLiteral(name, scanner()->location(), 3257 return ParseFunctionLiteral(name, scanner()->location(),
3233 is_strict_reserved ? kFunctionNameIsStrictReserved 3258 is_strict_reserved ? kFunctionNameIsStrictReserved
3234 : kFunctionNameValidityUnknown, 3259 : kFunctionNameValidityUnknown,
3235 FunctionKind::kAsyncFunction, pos, type, 3260 FunctionKind::kAsyncFunction, pos, type,
3236 language_mode(), CHECK_OK); 3261 language_mode(), CHECK_OK);
3237 } 3262 }
3238 3263
3239 Parser::LazyParsingResult Parser::SkipLazyFunctionBody( 3264 Parser::LazyParsingResult Parser::SkipLazyFunctionBody(
3240 int* materialized_literal_count, int* expected_property_count, 3265 int* materialized_literal_count, int* expected_property_count,
3241 bool may_abort, bool* ok) { 3266 bool is_inner_function, bool may_abort, bool* ok) {
3242 if (produce_cached_parse_data()) CHECK(log_); 3267 if (produce_cached_parse_data()) CHECK(log_);
3243 3268
3244 int function_block_pos = position(); 3269 int function_block_pos = position();
3245 DeclarationScope* scope = this->scope()->AsDeclarationScope(); 3270 DeclarationScope* scope = this->scope()->AsDeclarationScope();
3246 DCHECK(scope->is_function_scope()); 3271 DCHECK(scope->is_function_scope());
3247 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { 3272 // Inner functions are not part of the cached data.
3273 if (!is_inner_function && consume_cached_parse_data() &&
3274 !cached_parse_data_->rejected()) {
3248 // If we have cached data, we use it to skip parsing the function body. The 3275 // If we have cached data, we use it to skip parsing the function body. The
3249 // data contains the information we need to construct the lazy function. 3276 // data contains the information we need to construct the lazy function.
3250 FunctionEntry entry = 3277 FunctionEntry entry =
3251 cached_parse_data_->GetFunctionEntry(function_block_pos); 3278 cached_parse_data_->GetFunctionEntry(function_block_pos);
3252 // Check that cached data is valid. If not, mark it as invalid (the embedder 3279 // Check that cached data is valid. If not, mark it as invalid (the embedder
3253 // handles it). Note that end position greater than end of stream is safe, 3280 // handles it). Note that end position greater than end of stream is safe,
3254 // and hard to check. 3281 // and hard to check.
3255 if (entry.is_valid() && entry.end_pos() > function_block_pos) { 3282 if (entry.is_valid() && entry.end_pos() > function_block_pos) {
3256 scanner()->SeekForward(entry.end_pos() - 1); 3283 scanner()->SeekForward(entry.end_pos() - 1);
3257 3284
3258 scope->set_end_position(entry.end_pos()); 3285 scope->set_end_position(entry.end_pos());
3259 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete)); 3286 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
3260 total_preparse_skipped_ += scope->end_position() - function_block_pos; 3287 total_preparse_skipped_ += scope->end_position() - function_block_pos;
3261 *materialized_literal_count = entry.literal_count(); 3288 *materialized_literal_count = entry.literal_count();
3262 *expected_property_count = entry.property_count(); 3289 *expected_property_count = entry.property_count();
3263 SetLanguageMode(scope, entry.language_mode()); 3290 SetLanguageMode(scope, entry.language_mode());
3264 if (entry.uses_super_property()) scope->RecordSuperPropertyUsage(); 3291 if (entry.uses_super_property()) scope->RecordSuperPropertyUsage();
3265 if (entry.calls_eval()) scope->RecordEvalCall(); 3292 if (entry.calls_eval()) scope->RecordEvalCall();
3266 return kLazyParsingComplete; 3293 return kLazyParsingComplete;
3267 } 3294 }
3268 cached_parse_data_->Reject(); 3295 cached_parse_data_->Reject();
3269 } 3296 }
3270 // With no cached data, we partially parse the function, without building an 3297 // With no cached data, we partially parse the function, without building an
3271 // AST. This gathers the data needed to build a lazy function. 3298 // AST. This gathers the data needed to build a lazy function.
3272 SingletonLogger logger; 3299 SingletonLogger logger;
3273 PreParser::PreParseResult result = 3300 PreParser::PreParseResult result =
3274 ParseLazyFunctionBodyWithPreParser(&logger, may_abort); 3301 ParseLazyFunctionBodyWithPreParser(&logger, is_inner_function, may_abort);
3275 // Return immediately if pre-parser decided to abort parsing. 3302 // Return immediately if pre-parser decided to abort parsing.
3276 if (result == PreParser::kPreParseAbort) { 3303 if (result == PreParser::kPreParseAbort) {
3277 return kLazyParsingAborted; 3304 return kLazyParsingAborted;
3278 } 3305 }
3279 if (result == PreParser::kPreParseStackOverflow) { 3306 if (result == PreParser::kPreParseStackOverflow) {
3280 // Propagate stack overflow. 3307 // Propagate stack overflow.
3281 set_stack_overflow(); 3308 set_stack_overflow();
3282 *ok = false; 3309 *ok = false;
3283 return kLazyParsingComplete; 3310 return kLazyParsingComplete;
3284 } 3311 }
3285 if (logger.has_error()) { 3312 if (logger.has_error()) {
3286 ReportMessageAt(Scanner::Location(logger.start(), logger.end()), 3313 ReportMessageAt(Scanner::Location(logger.start(), logger.end()),
3287 logger.message(), logger.argument_opt(), 3314 logger.message(), logger.argument_opt(),
3288 logger.error_type()); 3315 logger.error_type());
3289 *ok = false; 3316 *ok = false;
3290 return kLazyParsingComplete; 3317 return kLazyParsingComplete;
3291 } 3318 }
3292 scope->set_end_position(logger.end()); 3319 scope->set_end_position(logger.end());
3293 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete)); 3320 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
3294 total_preparse_skipped_ += scope->end_position() - function_block_pos; 3321 total_preparse_skipped_ += scope->end_position() - function_block_pos;
3295 *materialized_literal_count = logger.literals(); 3322 *materialized_literal_count = logger.literals();
3296 *expected_property_count = logger.properties(); 3323 *expected_property_count = logger.properties();
3297 SetLanguageMode(scope, logger.language_mode()); 3324 SetLanguageMode(scope, logger.language_mode());
3298 if (logger.uses_super_property()) scope->RecordSuperPropertyUsage(); 3325 if (logger.uses_super_property()) scope->RecordSuperPropertyUsage();
3299 if (logger.calls_eval()) scope->RecordEvalCall(); 3326 if (logger.calls_eval()) scope->RecordEvalCall();
3300 if (produce_cached_parse_data()) { 3327 if (!is_inner_function && produce_cached_parse_data()) {
3301 DCHECK(log_); 3328 DCHECK(log_);
3302 // Position right after terminal '}'. 3329 // Position right after terminal '}'.
3303 int body_end = scanner()->location().end_pos; 3330 int body_end = scanner()->location().end_pos;
3304 log_->LogFunction(function_block_pos, body_end, *materialized_literal_count, 3331 log_->LogFunction(function_block_pos, body_end, *materialized_literal_count,
3305 *expected_property_count, language_mode(), 3332 *expected_property_count, language_mode(),
3306 scope->uses_super_property(), scope->calls_eval()); 3333 scope->uses_super_property(), scope->calls_eval());
3307 } 3334 }
3308 return kLazyParsingComplete; 3335 return kLazyParsingComplete;
3309 } 3336 }
3310 3337
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
3592 } 3619 }
3593 3620
3594 VariableProxy* Parser::BuildDotDebugIsActive() { 3621 VariableProxy* Parser::BuildDotDebugIsActive() {
3595 return NewUnresolved(ast_value_factory()->dot_debug_is_active_string(), VAR); 3622 return NewUnresolved(ast_value_factory()->dot_debug_is_active_string(), VAR);
3596 } 3623 }
3597 3624
3598 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( 3625 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
3599 const AstRawString* function_name, int pos, 3626 const AstRawString* function_name, int pos,
3600 const ParserFormalParameters& parameters, FunctionKind kind, 3627 const ParserFormalParameters& parameters, FunctionKind kind,
3601 FunctionLiteral::FunctionType function_type, bool* ok) { 3628 FunctionLiteral::FunctionType function_type, bool* ok) {
3602 // Everything inside an eagerly parsed function will be parsed eagerly 3629 // Everything inside an eagerly parsed function will be parsed eagerly (see
3603 // (see comment above). 3630 // comment above). Lazy inner functions are handled separately and they won't
3631 // require the mode to be PARSE_LAZILY (see ParseFunctionLiteral).
3632 // TODO(marja): Refactor parsing modes: remove this.
3604 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); 3633 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
3605 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); 3634 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
3606
3607 static const int kFunctionNameAssignmentIndex = 0; 3635 static const int kFunctionNameAssignmentIndex = 0;
3608 if (function_type == FunctionLiteral::kNamedExpression) { 3636 if (function_type == FunctionLiteral::kNamedExpression) {
3609 DCHECK(function_name != NULL); 3637 DCHECK(function_name != NULL);
3610 // If we have a named function expression, we add a local variable 3638 // If we have a named function expression, we add a local variable
3611 // declaration to the body of the function with the name of the 3639 // declaration to the body of the function with the name of the
3612 // function and let it refer to the function itself (closure). 3640 // function and let it refer to the function itself (closure).
3613 // Not having parsed the function body, the language mode may still change, 3641 // Not having parsed the function body, the language mode may still change,
3614 // so we reserve a spot and create the actual const assignment later. 3642 // so we reserve a spot and create the actual const assignment later.
3615 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length()); 3643 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length());
3616 result->Add(NULL, zone()); 3644 result->Add(NULL, zone());
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
3752 factory()->NewThisFunction(pos), 3780 factory()->NewThisFunction(pos),
3753 kNoSourcePosition), 3781 kNoSourcePosition),
3754 kNoSourcePosition)); 3782 kNoSourcePosition));
3755 } 3783 }
3756 3784
3757 MarkCollectedTailCallExpressions(); 3785 MarkCollectedTailCallExpressions();
3758 return result; 3786 return result;
3759 } 3787 }
3760 3788
3761 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( 3789 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
3762 SingletonLogger* logger, bool may_abort) { 3790 SingletonLogger* logger, bool is_inner_function, bool may_abort) {
3763 // This function may be called on a background thread too; record only the 3791 // This function may be called on a background thread too; record only the
3764 // main thread preparse times. 3792 // main thread preparse times.
3765 if (pre_parse_timer_ != NULL) { 3793 if (pre_parse_timer_ != NULL) {
3766 pre_parse_timer_->Start(); 3794 pre_parse_timer_->Start();
3767 } 3795 }
3768 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse"); 3796 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse");
3769 3797
3770 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); 3798 DCHECK_EQ(Token::LBRACE, scanner()->current_token());
3771 3799
3772 if (reusable_preparser_ == NULL) { 3800 if (reusable_preparser_ == NULL) {
3773 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), 3801 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
3774 NULL, stack_limit_); 3802 NULL, stack_limit_);
3775 reusable_preparser_->set_allow_lazy(true); 3803 reusable_preparser_->set_allow_lazy(true);
3776 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); 3804 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
3777 SET_ALLOW(natives); 3805 SET_ALLOW(natives);
3778 SET_ALLOW(harmony_do_expressions); 3806 SET_ALLOW(harmony_do_expressions);
3779 SET_ALLOW(harmony_for_in); 3807 SET_ALLOW(harmony_for_in);
3780 SET_ALLOW(harmony_function_sent); 3808 SET_ALLOW(harmony_function_sent);
3781 SET_ALLOW(harmony_restrictive_declarations); 3809 SET_ALLOW(harmony_restrictive_declarations);
3782 SET_ALLOW(harmony_async_await); 3810 SET_ALLOW(harmony_async_await);
3783 SET_ALLOW(harmony_trailing_commas); 3811 SET_ALLOW(harmony_trailing_commas);
3784 SET_ALLOW(harmony_class_fields); 3812 SET_ALLOW(harmony_class_fields);
3785 #undef SET_ALLOW 3813 #undef SET_ALLOW
3786 } 3814 }
3787 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( 3815 // Aborting inner function preparsing would leave scopes in an inconsistent
3788 language_mode(), function_state_->kind(), 3816 // state; we don't parse inner functions in the abortable mode anyway.
3789 scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_, 3817 DCHECK(!is_inner_function || !may_abort);
3790 logger, may_abort, use_counts_); 3818
3819 FunctionKind kind = function_state_->kind();
3820 PreParser::PreParseResult result;
3821 if (!is_inner_function) {
3822 // If we don't need to look at the scope, construct a dummy scope chain
3823 // which is not connected to the real scope chain.
3824 LanguageMode mode = language_mode();
3825 bool has_simple_parameters =
3826 scope()->AsDeclarationScope()->has_simple_parameters();
3827 DeclarationScope* top_scope = NewScriptScope();
3828 top_scope->SetLanguageMode(mode);
3829 FunctionState top_state(&function_state_, &scope_state_, top_scope,
3830 kNormalFunction);
3831 DeclarationScope* function_scope = NewFunctionScope(kind);
3832 if (!has_simple_parameters) {
3833 function_scope->SetHasNonSimpleParameters();
3834 }
3835 result = reusable_preparser_->PreParseLazyFunction(
3836 kind, function_scope, parsing_module_, logger, is_inner_function,
3837 may_abort, use_counts_);
3838 } else {
3839 // Detaching the scopes created by PreParser from the Scope chain must be
3840 // done above (see ParseFunctionLiteral & AnalyzePartially).
3841 result = reusable_preparser_->PreParseLazyFunction(
3842 kind, scope()->AsDeclarationScope(), parsing_module_, logger,
3843 is_inner_function, may_abort, use_counts_);
3844 }
3791 if (pre_parse_timer_ != NULL) { 3845 if (pre_parse_timer_ != NULL) {
3792 pre_parse_timer_->Stop(); 3846 pre_parse_timer_->Stop();
3793 } 3847 }
3794 return result; 3848 return result;
3795 } 3849 }
3796 3850
3797 Expression* Parser::InstallHomeObject(Expression* function_literal, 3851 Expression* Parser::InstallHomeObject(Expression* function_literal,
3798 Expression* home_object) { 3852 Expression* home_object) {
3799 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); 3853 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
3800 Variable* result_var = 3854 Variable* result_var =
(...skipping 2092 matching lines...) Expand 10 before | Expand all | Expand 10 after
5893 node->Print(Isolate::Current()); 5947 node->Print(Isolate::Current());
5894 } 5948 }
5895 #endif // DEBUG 5949 #endif // DEBUG
5896 5950
5897 #undef CHECK_OK 5951 #undef CHECK_OK
5898 #undef CHECK_OK_VOID 5952 #undef CHECK_OK_VOID
5899 #undef CHECK_FAILED 5953 #undef CHECK_FAILED
5900 5954
5901 } // namespace internal 5955 } // namespace internal
5902 } // namespace v8 5956 } // 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