OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |