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

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

Issue 2322243002: Preparse inner functions. (Closed)
Patch Set: flag on again Created 4 years, 3 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 <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 2801 matching lines...) Expand 10 before | Expand all | Expand 10 after
2941 // - It must not have been prohibited by the caller to Parse (some callers 2947 // - It must not have been prohibited by the caller to Parse (some callers
2942 // need a full AST). 2948 // need a full AST).
2943 // - The outer scope must allow lazy compilation of inner functions. 2949 // - The outer scope must allow lazy compilation of inner functions.
2944 // - The function mustn't be a function expression with an open parenthesis 2950 // - The function mustn't be a function expression with an open parenthesis
2945 // before; we consider that a hint that the function will be called 2951 // before; we consider that a hint that the function will be called
2946 // immediately, and it would be a waste of time to make it lazily 2952 // immediately, and it would be a waste of time to make it lazily
2947 // compiled. 2953 // compiled.
2948 // These are all things we can know at this point, without looking at the 2954 // These are all things we can know at this point, without looking at the
2949 // function itself. 2955 // function itself.
2950 2956
2951 // In addition, we need to distinguish between these cases: 2957 // We separate between lazy parsing top level functions and lazy parsing inner
2958 // functions, because the latter needs to do more work. In particular, we need
2959 // to track unresolved variables to distinguish between these cases:
2952 // (function foo() { 2960 // (function foo() {
2953 // bar = function() { return 1; } 2961 // bar = function() { return 1; }
2954 // })(); 2962 // })();
2955 // and 2963 // and
2956 // (function foo() { 2964 // (function foo() {
2957 // var a = 1; 2965 // var a = 1;
2958 // bar = function() { return a; } 2966 // bar = function() { return a; }
2959 // })(); 2967 // })();
2960 2968
2961 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume 2969 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
2962 // parenthesis before the function means that it will be called 2970 // parenthesis before the function means that it will be called
2963 // immediately). The inner function *must* be parsed eagerly to resolve the 2971 // immediately). bar can be parsed lazily, but we need to parse it in a mode
2964 // possible reference to the variable in foo's scope. However, it's possible 2972 // that tracks unresolved variables.
2965 // that it will be compiled lazily. 2973 DCHECK_IMPLIES(mode() == PARSE_LAZILY, FLAG_lazy);
2974 DCHECK_IMPLIES(mode() == PARSE_LAZILY, allow_lazy());
2975 DCHECK_IMPLIES(mode() == PARSE_LAZILY, !allow_natives());
2976 DCHECK_IMPLIES(mode() == PARSE_LAZILY, extension_ == nullptr);
2966 2977
2967 // To make this additional case work, both Parser and PreParser implement a 2978 bool is_lazy_top_level_function =
2968 // logic where only top-level functions will be parsed lazily. 2979 mode() == PARSE_LAZILY &&
2969 bool is_lazily_parsed = mode() == PARSE_LAZILY && 2980 eager_compile_hint == FunctionLiteral::kShouldLazyCompile &&
2970 scope()->AllowsLazyParsing() && 2981 scope()->AllowsLazyParsingWithoutUnresolvedVariables();
vogelheim 2016/09/16 08:13:04 Does this eliminate the force-eager-compile-for-pa
marja 2016/09/16 08:38:15 As discussed offline, the logic is intact (eager_c
2971 !function_state_->next_function_is_parenthesized();
2972 2982
2973 // Determine whether the function body can be discarded after parsing. 2983 // Determine whether we can still do the inner function lazy parsing.
2974 // The preconditions are: 2984 // The preconditions are:
2975 // - Lazy compilation has to be enabled. 2985 // - Lazy compilation has to be enabled.
2976 // - Neither V8 natives nor native function declarations can be allowed, 2986 // - Neither V8 natives nor native function declarations can be allowed,
2977 // since parsing one would retroactively force the function to be 2987 // since parsing one would retroactively force the function to be
2978 // eagerly compiled. 2988 // eagerly compiled.
2979 // - The invoker of this parser can't depend on the AST being eagerly 2989 // - The invoker of this parser can't depend on the AST being eagerly
2980 // built (either because the function is about to be compiled, or 2990 // built (either because the function is about to be compiled, or
2981 // because the AST is going to be inspected for some reason). 2991 // because the AST is going to be inspected for some reason).
2982 // - Because of the above, we can't be attempting to parse a 2992 // - Because of the above, we can't be attempting to parse a
2983 // FunctionExpression; even without enclosing parentheses it might be 2993 // FunctionExpression; even without enclosing parentheses it might be
2984 // immediately invoked. 2994 // immediately invoked.
2985 // - The function literal shouldn't be hinted to eagerly compile. 2995 // - The function literal shouldn't be hinted to eagerly compile.
2986 // - For asm.js functions the body needs to be available when module 2996 // - For asm.js functions the body needs to be available when module
2987 // validation is active, because we examine the entire module at once. 2997 // validation is active, because we examine the entire module at once.
2988 bool use_temp_zone = 2998
2989 !is_lazily_parsed && FLAG_lazy && !allow_natives() && 2999 // Inner functions will be parsed by using a temporary Zone. After parsing, we
3000 // will migrate unresolved variable into a Scope in the main Zone.
3001 // TODO(marja): Refactor parsing modes: simplify this.
3002 bool is_lazy_inner_function =
3003 !is_lazy_top_level_function && FLAG_lazy && !allow_natives() &&
2990 extension_ == NULL && allow_lazy() && 3004 extension_ == NULL && allow_lazy() &&
2991 function_type == FunctionLiteral::kDeclaration && 3005 function_type == FunctionLiteral::kDeclaration &&
2992 eager_compile_hint != FunctionLiteral::kShouldEagerCompile && 3006 eager_compile_hint != FunctionLiteral::kShouldEagerCompile &&
2993 !(FLAG_validate_asm && scope()->IsAsmModule()); 3007 !(FLAG_validate_asm && scope()->IsAsmModule());
2994 3008
2995 DeclarationScope* main_scope = nullptr; 3009 DeclarationScope* main_scope = nullptr;
2996 if (use_temp_zone) { 3010 if (is_lazy_inner_function) {
2997 // This Scope lives in the main Zone; we'll migrate data into it later. 3011 // This Scope lives in the main Zone; we'll migrate data into it later.
2998 main_scope = NewFunctionScope(kind); 3012 main_scope = NewFunctionScope(kind);
2999 } 3013 }
3000 3014
3001 ZoneList<Statement*>* body = nullptr; 3015 ZoneList<Statement*>* body = nullptr;
3002 int arity = -1; 3016 int arity = -1;
3003 int materialized_literal_count = -1; 3017 int materialized_literal_count = -1;
3004 int expected_property_count = -1; 3018 int expected_property_count = -1;
3005 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); 3019 DuplicateFinder duplicate_finder(scanner()->unicode_cache());
3006 bool should_be_used_once_hint = false; 3020 bool should_be_used_once_hint = false;
3007 bool has_duplicate_parameters; 3021 bool has_duplicate_parameters;
3008 3022
3009 { 3023 {
3010 // Temporary zones can nest. When we migrate free variables (see below), we 3024 // Temporary zones can nest. When we migrate free variables (see below), we
3011 // need to recreate them in the previous Zone. 3025 // need to recreate them in the previous Zone.
3012 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory()); 3026 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory());
3013 previous_zone_ast_node_factory.set_zone(zone()); 3027 previous_zone_ast_node_factory.set_zone(zone());
3014 3028
3015 // Open a new zone scope, which sets our AstNodeFactory to allocate in the 3029 // Open a new zone scope, which sets our AstNodeFactory to allocate in the
3016 // new temporary zone if the preconditions are satisfied, and ensures that 3030 // new temporary zone if the preconditions are satisfied, and ensures that
3017 // the previous zone is always restored after parsing the body. To be able 3031 // the previous zone is always restored after parsing the body. To be able
3018 // to do scope analysis correctly after full parsing, we migrate needed 3032 // to do scope analysis correctly after full parsing, we migrate needed
3019 // information from scope into main_scope when the function has been parsed. 3033 // information from scope into main_scope when the function has been parsed.
3020 Zone temp_zone(zone()->allocator()); 3034 Zone temp_zone(zone()->allocator());
3021 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone); 3035 DiscardableZoneScope zone_scope(this, &temp_zone, is_lazy_inner_function);
3022 3036
3023 DeclarationScope* scope = NewFunctionScope(kind); 3037 DeclarationScope* scope = NewFunctionScope(kind);
3024 SetLanguageMode(scope, language_mode); 3038 SetLanguageMode(scope, language_mode);
3025 if (!use_temp_zone) { 3039 if (!is_lazy_inner_function) {
3026 main_scope = scope; 3040 main_scope = scope;
3027 } else { 3041 } else {
3028 DCHECK(main_scope->zone() != scope->zone()); 3042 DCHECK(main_scope->zone() != scope->zone());
3029 } 3043 }
3030 3044
3031 FunctionState function_state(&function_state_, &scope_state_, scope, kind); 3045 FunctionState function_state(&function_state_, &scope_state_, scope, kind);
3032 #ifdef DEBUG 3046 #ifdef DEBUG
3033 scope->SetScopeName(function_name); 3047 scope->SetScopeName(function_name);
3034 #endif 3048 #endif
3035 ExpressionClassifier formals_classifier(this, &duplicate_finder); 3049 ExpressionClassifier formals_classifier(this, &duplicate_finder);
(...skipping 23 matching lines...) Expand all
3059 int formals_end_position = scanner()->location().end_pos; 3073 int formals_end_position = scanner()->location().end_pos;
3060 3074
3061 CheckArityRestrictions(arity, kind, formals.has_rest, start_position, 3075 CheckArityRestrictions(arity, kind, formals.has_rest, start_position,
3062 formals_end_position, CHECK_OK); 3076 formals_end_position, CHECK_OK);
3063 Expect(Token::LBRACE, CHECK_OK); 3077 Expect(Token::LBRACE, CHECK_OK);
3064 // Don't include the rest parameter into the function's formal parameter 3078 // Don't include the rest parameter into the function's formal parameter
3065 // count (esp. the SharedFunctionInfo::internal_formal_parameter_count, 3079 // count (esp. the SharedFunctionInfo::internal_formal_parameter_count,
3066 // which says whether we need to create an arguments adaptor frame). 3080 // which says whether we need to create an arguments adaptor frame).
3067 if (formals.has_rest) arity--; 3081 if (formals.has_rest) arity--;
3068 3082
3069 // Eager or lazy parse? 3083 // Eager or lazy parse? If is_lazy_top_level_function, we'll parse
3070 // If is_lazily_parsed, we'll parse lazily. We'll call SkipLazyFunctionBody, 3084 // lazily. We'll call SkipLazyFunctionBody, which may decide to abort lazy
3071 // which may decide to abort lazy parsing if it suspects that wasn't a good 3085 // parsing if it suspects that wasn't a good idea. If so (in which case the
3072 // idea. If so (in which case the parser is expected to have backtracked), 3086 // parser is expected to have backtracked), or if we didn't try to lazy
3073 // or if we didn't try to lazy parse in the first place, we'll have to parse 3087 // parse in the first place, we'll have to parse eagerly.
3074 // eagerly. 3088 if (is_lazy_top_level_function) {
vogelheim 2016/09/16 08:13:04 For my understanding.. this: DCHECK(is_lazy_top_l
marja 2016/09/16 08:38:15 The latter will work. It's also possible both are
3075 if (is_lazily_parsed) {
3076 Scanner::BookmarkScope bookmark(scanner()); 3089 Scanner::BookmarkScope bookmark(scanner());
3077 bool may_abort = bookmark.Set(); 3090 bool may_abort = bookmark.Set();
3078 LazyParsingResult result = 3091 LazyParsingResult result = SkipLazyFunctionBody(
3079 SkipLazyFunctionBody(&materialized_literal_count, 3092 &materialized_literal_count, &expected_property_count, false,
3080 &expected_property_count, may_abort, CHECK_OK); 3093 may_abort, CHECK_OK);
3081 3094
3082 materialized_literal_count += formals.materialized_literals_count + 3095 materialized_literal_count += formals.materialized_literals_count +
3083 function_state.materialized_literal_count(); 3096 function_state.materialized_literal_count();
3084 3097
3085 if (result == kLazyParsingAborted) { 3098 if (result == kLazyParsingAborted) {
3086 bookmark.Reset(); 3099 bookmark.Reset();
3087 // Trigger eager (re-)parsing, just below this block. 3100 // Trigger eager (re-)parsing, just below this block.
3088 is_lazily_parsed = false; 3101 is_lazy_top_level_function = false;
3089 3102
3090 // This is probably an initialization function. Inform the compiler it 3103 // This is probably an initialization function. Inform the compiler it
3091 // should also eager-compile this function, and that we expect it to be 3104 // should also eager-compile this function, and that we expect it to be
3092 // used once. 3105 // used once.
3093 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; 3106 eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
3094 should_be_used_once_hint = true; 3107 should_be_used_once_hint = true;
3095 } 3108 }
3096 } 3109 }
3097 if (!is_lazily_parsed) { 3110 if (is_lazy_inner_function) {
3111 if (FLAG_lazy_inner_functions) {
3112 LazyParsingResult result = SkipLazyFunctionBody(
3113 &materialized_literal_count, &expected_property_count, true, false,
3114 CHECK_OK);
3115 materialized_literal_count +=
3116 formals.materialized_literals_count +
3117 function_state.materialized_literal_count();
3118 DCHECK(result != kLazyParsingAborted);
3119 USE(result);
3120 } else {
3121 ParseEagerFunctionBody(function_name, pos, formals, kind, function_type,
3122 CHECK_OK);
3123 materialized_literal_count =
3124 function_state.materialized_literal_count();
3125 expected_property_count = function_state.expected_property_count();
3126 }
3127 } else if (!is_lazy_top_level_function) {
vogelheim 2016/09/16 08:13:04 style nitpick: This code was awkward before, since
marja 2016/09/16 08:38:15 Will be changed after the flag is gone.
3098 body = ParseEagerFunctionBody(function_name, pos, formals, kind, 3128 body = ParseEagerFunctionBody(function_name, pos, formals, kind,
3099 function_type, CHECK_OK); 3129 function_type, CHECK_OK);
3100 3130
3101 materialized_literal_count = function_state.materialized_literal_count(); 3131 materialized_literal_count = function_state.materialized_literal_count();
3102 expected_property_count = function_state.expected_property_count(); 3132 expected_property_count = function_state.expected_property_count();
3103 if (use_temp_zone) {
3104 // If the preconditions are correct the function body should never be
3105 // accessed, but do this anyway for better behaviour if they're wrong.
3106 body = nullptr;
3107 }
3108 } 3133 }
3109 3134
3110 // Parsing the body may change the language mode in our scope. 3135 // Parsing the body may change the language mode in our scope.
3111 language_mode = scope->language_mode(); 3136 language_mode = scope->language_mode();
3112 scope->DeclareArguments(ast_value_factory()); 3137 scope->DeclareArguments(ast_value_factory());
3113 if (main_scope != scope) { 3138 if (main_scope != scope) {
3114 main_scope->DeclareArguments(ast_value_factory()); 3139 main_scope->DeclareArguments(ast_value_factory());
3115 } 3140 }
3116 3141
3117 // Validate name and parameter names. We can do this only after parsing the 3142 // Validate name and parameter names. We can do this only after parsing the
(...skipping 13 matching lines...) Expand all
3131 } 3156 }
3132 CheckConflictingVarDeclarations(scope, CHECK_OK); 3157 CheckConflictingVarDeclarations(scope, CHECK_OK);
3133 3158
3134 if (body) { 3159 if (body) {
3135 // If body can be inspected, rewrite queued destructuring assignments 3160 // If body can be inspected, rewrite queued destructuring assignments
3136 RewriteDestructuringAssignments(); 3161 RewriteDestructuringAssignments();
3137 } 3162 }
3138 has_duplicate_parameters = 3163 has_duplicate_parameters =
3139 !classifier()->is_valid_formal_parameter_list_without_duplicates(); 3164 !classifier()->is_valid_formal_parameter_list_without_duplicates();
3140 3165
3141 if (use_temp_zone) { 3166 if (is_lazy_inner_function) {
3142 DCHECK(main_scope != scope); 3167 DCHECK(main_scope != scope);
3143 scope->AnalyzePartially(main_scope, &previous_zone_ast_node_factory); 3168 scope->AnalyzePartially(main_scope, &previous_zone_ast_node_factory);
3144 } 3169 }
3145 } // DiscardableZoneScope goes out of scope. 3170 } // DiscardableZoneScope goes out of scope.
3146 3171
3147 FunctionLiteral::ParameterFlag duplicate_parameters = 3172 FunctionLiteral::ParameterFlag duplicate_parameters =
3148 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters 3173 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters
3149 : FunctionLiteral::kNoDuplicateParameters; 3174 : FunctionLiteral::kNoDuplicateParameters;
3150 3175
3151 // Note that the FunctionLiteral needs to be created in the main Zone again. 3176 // 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
3185 } 3210 }
3186 return ParseFunctionLiteral(name, scanner()->location(), 3211 return ParseFunctionLiteral(name, scanner()->location(),
3187 is_strict_reserved ? kFunctionNameIsStrictReserved 3212 is_strict_reserved ? kFunctionNameIsStrictReserved
3188 : kFunctionNameValidityUnknown, 3213 : kFunctionNameValidityUnknown,
3189 FunctionKind::kAsyncFunction, pos, type, 3214 FunctionKind::kAsyncFunction, pos, type,
3190 language_mode(), CHECK_OK); 3215 language_mode(), CHECK_OK);
3191 } 3216 }
3192 3217
3193 Parser::LazyParsingResult Parser::SkipLazyFunctionBody( 3218 Parser::LazyParsingResult Parser::SkipLazyFunctionBody(
3194 int* materialized_literal_count, int* expected_property_count, 3219 int* materialized_literal_count, int* expected_property_count,
3195 bool may_abort, bool* ok) { 3220 bool is_inner_function, bool may_abort, bool* ok) {
3196 if (produce_cached_parse_data()) CHECK(log_); 3221 if (produce_cached_parse_data()) CHECK(log_);
3197 3222
3198 int function_block_pos = position(); 3223 int function_block_pos = position();
3199 DeclarationScope* scope = this->scope()->AsDeclarationScope(); 3224 DeclarationScope* scope = this->scope()->AsDeclarationScope();
3200 DCHECK(scope->is_function_scope()); 3225 DCHECK(scope->is_function_scope());
3201 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { 3226 // Inner functions are not part of the cached data.
3227 if (!is_inner_function && consume_cached_parse_data() &&
3228 !cached_parse_data_->rejected()) {
3202 // If we have cached data, we use it to skip parsing the function body. The 3229 // If we have cached data, we use it to skip parsing the function body. The
3203 // data contains the information we need to construct the lazy function. 3230 // data contains the information we need to construct the lazy function.
3204 FunctionEntry entry = 3231 FunctionEntry entry =
3205 cached_parse_data_->GetFunctionEntry(function_block_pos); 3232 cached_parse_data_->GetFunctionEntry(function_block_pos);
3206 // Check that cached data is valid. If not, mark it as invalid (the embedder 3233 // Check that cached data is valid. If not, mark it as invalid (the embedder
3207 // handles it). Note that end position greater than end of stream is safe, 3234 // handles it). Note that end position greater than end of stream is safe,
3208 // and hard to check. 3235 // and hard to check.
3209 if (entry.is_valid() && entry.end_pos() > function_block_pos) { 3236 if (entry.is_valid() && entry.end_pos() > function_block_pos) {
3210 scanner()->SeekForward(entry.end_pos() - 1); 3237 scanner()->SeekForward(entry.end_pos() - 1);
3211 3238
3212 scope->set_end_position(entry.end_pos()); 3239 scope->set_end_position(entry.end_pos());
3213 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete)); 3240 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
3214 total_preparse_skipped_ += scope->end_position() - function_block_pos; 3241 total_preparse_skipped_ += scope->end_position() - function_block_pos;
3215 *materialized_literal_count = entry.literal_count(); 3242 *materialized_literal_count = entry.literal_count();
3216 *expected_property_count = entry.property_count(); 3243 *expected_property_count = entry.property_count();
3217 SetLanguageMode(scope, entry.language_mode()); 3244 SetLanguageMode(scope, entry.language_mode());
3218 if (entry.uses_super_property()) scope->RecordSuperPropertyUsage(); 3245 if (entry.uses_super_property()) scope->RecordSuperPropertyUsage();
3219 if (entry.calls_eval()) scope->RecordEvalCall(); 3246 if (entry.calls_eval()) scope->RecordEvalCall();
3220 return kLazyParsingComplete; 3247 return kLazyParsingComplete;
3221 } 3248 }
3222 cached_parse_data_->Reject(); 3249 cached_parse_data_->Reject();
3223 } 3250 }
3224 // With no cached data, we partially parse the function, without building an 3251 // With no cached data, we partially parse the function, without building an
3225 // AST. This gathers the data needed to build a lazy function. 3252 // AST. This gathers the data needed to build a lazy function.
3226 SingletonLogger logger; 3253 SingletonLogger logger;
3227 PreParser::PreParseResult result = 3254 PreParser::PreParseResult result =
3228 ParseLazyFunctionBodyWithPreParser(&logger, may_abort); 3255 ParseLazyFunctionBodyWithPreParser(&logger, is_inner_function, may_abort);
3229 // Return immediately if pre-parser decided to abort parsing. 3256 // Return immediately if pre-parser decided to abort parsing.
3230 if (result == PreParser::kPreParseAbort) { 3257 if (result == PreParser::kPreParseAbort) {
3231 return kLazyParsingAborted; 3258 return kLazyParsingAborted;
3232 } 3259 }
3233 if (result == PreParser::kPreParseStackOverflow) { 3260 if (result == PreParser::kPreParseStackOverflow) {
3234 // Propagate stack overflow. 3261 // Propagate stack overflow.
3235 set_stack_overflow(); 3262 set_stack_overflow();
3236 *ok = false; 3263 *ok = false;
3237 return kLazyParsingComplete; 3264 return kLazyParsingComplete;
3238 } 3265 }
3239 if (logger.has_error()) { 3266 if (logger.has_error()) {
3240 ReportMessageAt(Scanner::Location(logger.start(), logger.end()), 3267 ReportMessageAt(Scanner::Location(logger.start(), logger.end()),
3241 logger.message(), logger.argument_opt(), 3268 logger.message(), logger.argument_opt(),
3242 logger.error_type()); 3269 logger.error_type());
3243 *ok = false; 3270 *ok = false;
3244 return kLazyParsingComplete; 3271 return kLazyParsingComplete;
3245 } 3272 }
3246 scope->set_end_position(logger.end()); 3273 scope->set_end_position(logger.end());
3247 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete)); 3274 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
3248 total_preparse_skipped_ += scope->end_position() - function_block_pos; 3275 total_preparse_skipped_ += scope->end_position() - function_block_pos;
3249 *materialized_literal_count = logger.literals(); 3276 *materialized_literal_count = logger.literals();
3250 *expected_property_count = logger.properties(); 3277 *expected_property_count = logger.properties();
3251 SetLanguageMode(scope, logger.language_mode()); 3278 SetLanguageMode(scope, logger.language_mode());
3252 if (logger.uses_super_property()) scope->RecordSuperPropertyUsage(); 3279 if (logger.uses_super_property()) scope->RecordSuperPropertyUsage();
3253 if (logger.calls_eval()) scope->RecordEvalCall(); 3280 if (logger.calls_eval()) scope->RecordEvalCall();
3254 if (produce_cached_parse_data()) { 3281 if (!is_inner_function && produce_cached_parse_data()) {
3255 DCHECK(log_); 3282 DCHECK(log_);
3256 // Position right after terminal '}'. 3283 // Position right after terminal '}'.
3257 int body_end = scanner()->location().end_pos; 3284 int body_end = scanner()->location().end_pos;
3258 log_->LogFunction(function_block_pos, body_end, *materialized_literal_count, 3285 log_->LogFunction(function_block_pos, body_end, *materialized_literal_count,
3259 *expected_property_count, language_mode(), 3286 *expected_property_count, language_mode(),
3260 scope->uses_super_property(), scope->calls_eval()); 3287 scope->uses_super_property(), scope->calls_eval());
3261 } 3288 }
3262 return kLazyParsingComplete; 3289 return kLazyParsingComplete;
3263 } 3290 }
3264 3291
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
3546 } 3573 }
3547 3574
3548 VariableProxy* Parser::BuildDotDebugIsActive() { 3575 VariableProxy* Parser::BuildDotDebugIsActive() {
3549 return NewUnresolved(ast_value_factory()->dot_debug_is_active_string(), VAR); 3576 return NewUnresolved(ast_value_factory()->dot_debug_is_active_string(), VAR);
3550 } 3577 }
3551 3578
3552 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( 3579 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
3553 const AstRawString* function_name, int pos, 3580 const AstRawString* function_name, int pos,
3554 const ParserFormalParameters& parameters, FunctionKind kind, 3581 const ParserFormalParameters& parameters, FunctionKind kind,
3555 FunctionLiteral::FunctionType function_type, bool* ok) { 3582 FunctionLiteral::FunctionType function_type, bool* ok) {
3556 // Everything inside an eagerly parsed function will be parsed eagerly 3583 // Everything inside an eagerly parsed function will be parsed eagerly (see
3557 // (see comment above). 3584 // comment above). Lazy inner functions are handled separately and they won't
3585 // require the mode to be PARSE_LAZILY (see ParseFunctionLiteral).
3586 // TODO(marja): Refactor parsing modes: remove this.
3558 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); 3587 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
3559 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); 3588 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
3560
3561 static const int kFunctionNameAssignmentIndex = 0; 3589 static const int kFunctionNameAssignmentIndex = 0;
3562 if (function_type == FunctionLiteral::kNamedExpression) { 3590 if (function_type == FunctionLiteral::kNamedExpression) {
3563 DCHECK(function_name != NULL); 3591 DCHECK(function_name != NULL);
3564 // If we have a named function expression, we add a local variable 3592 // If we have a named function expression, we add a local variable
3565 // declaration to the body of the function with the name of the 3593 // declaration to the body of the function with the name of the
3566 // function and let it refer to the function itself (closure). 3594 // function and let it refer to the function itself (closure).
3567 // Not having parsed the function body, the language mode may still change, 3595 // Not having parsed the function body, the language mode may still change,
3568 // so we reserve a spot and create the actual const assignment later. 3596 // so we reserve a spot and create the actual const assignment later.
3569 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length()); 3597 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length());
3570 result->Add(NULL, zone()); 3598 result->Add(NULL, zone());
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
3706 factory()->NewThisFunction(pos), 3734 factory()->NewThisFunction(pos),
3707 kNoSourcePosition), 3735 kNoSourcePosition),
3708 kNoSourcePosition)); 3736 kNoSourcePosition));
3709 } 3737 }
3710 3738
3711 MarkCollectedTailCallExpressions(); 3739 MarkCollectedTailCallExpressions();
3712 return result; 3740 return result;
3713 } 3741 }
3714 3742
3715 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( 3743 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
3716 SingletonLogger* logger, bool may_abort) { 3744 SingletonLogger* logger, bool is_inner_function, bool may_abort) {
3717 // This function may be called on a background thread too; record only the 3745 // This function may be called on a background thread too; record only the
3718 // main thread preparse times. 3746 // main thread preparse times.
3719 if (pre_parse_timer_ != NULL) { 3747 if (pre_parse_timer_ != NULL) {
3720 pre_parse_timer_->Start(); 3748 pre_parse_timer_->Start();
3721 } 3749 }
3722 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse"); 3750 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse");
3723 3751
3724 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); 3752 DCHECK_EQ(Token::LBRACE, scanner()->current_token());
3725 3753
3726 if (reusable_preparser_ == NULL) { 3754 if (reusable_preparser_ == NULL) {
3727 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), 3755 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
3728 NULL, stack_limit_); 3756 NULL, stack_limit_);
3729 reusable_preparser_->set_allow_lazy(true); 3757 reusable_preparser_->set_allow_lazy(true);
3730 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); 3758 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
3731 SET_ALLOW(natives); 3759 SET_ALLOW(natives);
3732 SET_ALLOW(harmony_do_expressions); 3760 SET_ALLOW(harmony_do_expressions);
3733 SET_ALLOW(harmony_for_in); 3761 SET_ALLOW(harmony_for_in);
3734 SET_ALLOW(harmony_function_sent); 3762 SET_ALLOW(harmony_function_sent);
3735 SET_ALLOW(harmony_restrictive_declarations); 3763 SET_ALLOW(harmony_restrictive_declarations);
3736 SET_ALLOW(harmony_async_await); 3764 SET_ALLOW(harmony_async_await);
3737 SET_ALLOW(harmony_trailing_commas); 3765 SET_ALLOW(harmony_trailing_commas);
3738 #undef SET_ALLOW 3766 #undef SET_ALLOW
3739 } 3767 }
3740 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( 3768 // Aborting inner function preparsing would leave scopes in an inconsistent
3741 language_mode(), function_state_->kind(), 3769 // state; we don't parse inner functions in the abortable mode anyway.
3742 scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_, 3770 DCHECK(!is_inner_function || !may_abort);
3743 logger, may_abort, use_counts_); 3771
3772 FunctionKind kind = function_state_->kind();
3773 PreParser::PreParseResult result;
3774 if (!is_inner_function) {
3775 // If we don't need to look at the scope, construct a dummy scope chain
3776 // which is not connected to the real scope chain.
3777 LanguageMode mode = language_mode();
3778 bool has_simple_parameters =
3779 scope()->AsDeclarationScope()->has_simple_parameters();
3780 DeclarationScope* top_scope = NewScriptScope();
3781 top_scope->SetLanguageMode(mode);
3782 FunctionState top_state(&function_state_, &scope_state_, top_scope,
3783 kNormalFunction);
3784 DeclarationScope* function_scope = NewFunctionScope(kind);
3785 if (!has_simple_parameters) {
3786 function_scope->SetHasNonSimpleParameters();
3787 }
3788 result = reusable_preparser_->PreParseLazyFunction(
3789 kind, function_scope, parsing_module_, logger, is_inner_function,
3790 may_abort, use_counts_);
3791 } else {
3792 // Detaching the scopes created by PreParser from the Scope chain must be
3793 // done above (see ParseFunctionLiteral & AnalyzePartially).
3794 result = reusable_preparser_->PreParseLazyFunction(
3795 kind, scope()->AsDeclarationScope(), parsing_module_, logger,
3796 is_inner_function, may_abort, use_counts_);
3797 }
3744 if (pre_parse_timer_ != NULL) { 3798 if (pre_parse_timer_ != NULL) {
3745 pre_parse_timer_->Stop(); 3799 pre_parse_timer_->Stop();
3746 } 3800 }
3747 return result; 3801 return result;
3748 } 3802 }
3749 3803
3750 Expression* Parser::ParseClassLiteral(const AstRawString* name, 3804 Expression* Parser::ParseClassLiteral(const AstRawString* name,
3751 Scanner::Location class_name_location, 3805 Scanner::Location class_name_location,
3752 bool name_is_strict_reserved, int pos, 3806 bool name_is_strict_reserved, int pos,
3753 bool* ok) { 3807 bool* ok) {
(...skipping 1873 matching lines...) Expand 10 before | Expand all | Expand 10 after
5627 node->Print(Isolate::Current()); 5681 node->Print(Isolate::Current());
5628 } 5682 }
5629 #endif // DEBUG 5683 #endif // DEBUG
5630 5684
5631 #undef CHECK_OK 5685 #undef CHECK_OK
5632 #undef CHECK_OK_VOID 5686 #undef CHECK_OK_VOID
5633 #undef CHECK_FAILED 5687 #undef CHECK_FAILED
5634 5688
5635 } // namespace internal 5689 } // namespace internal
5636 } // namespace v8 5690 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698