| 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 |