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