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