| 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 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 | 671 |
| 672 FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { | 672 FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { |
| 673 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here, | 673 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here, |
| 674 // see comment for HistogramTimerScope class. | 674 // see comment for HistogramTimerScope class. |
| 675 | 675 |
| 676 // It's OK to use the Isolate & counters here, since this function is only | 676 // It's OK to use the Isolate & counters here, since this function is only |
| 677 // called in the main thread. | 677 // called in the main thread. |
| 678 DCHECK(parsing_on_main_thread_); | 678 DCHECK(parsing_on_main_thread_); |
| 679 | 679 |
| 680 HistogramTimerScope timer_scope(isolate->counters()->parse(), true); | 680 HistogramTimerScope timer_scope(isolate->counters()->parse(), true); |
| 681 RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::Parse); | 681 RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::ParseProgram); |
| 682 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.Parse"); | 682 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseProgram"); |
| 683 Handle<String> source(String::cast(info->script()->source())); | 683 Handle<String> source(String::cast(info->script()->source())); |
| 684 isolate->counters()->total_parse_size()->Increment(source->length()); | 684 isolate->counters()->total_parse_size()->Increment(source->length()); |
| 685 base::ElapsedTimer timer; | 685 base::ElapsedTimer timer; |
| 686 if (FLAG_trace_parse) { | 686 if (FLAG_trace_parse) { |
| 687 timer.Start(); | 687 timer.Start(); |
| 688 } | 688 } |
| 689 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); | 689 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); |
| 690 | 690 |
| 691 // Initialize parser state. | 691 // Initialize parser state. |
| 692 CompleteParserRecorder recorder; | 692 CompleteParserRecorder recorder; |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 830 function_state.expected_property_count(), parameter_count); | 830 function_state.expected_property_count(), parameter_count); |
| 831 } | 831 } |
| 832 } | 832 } |
| 833 | 833 |
| 834 // Make sure the target stack is empty. | 834 // Make sure the target stack is empty. |
| 835 DCHECK(target_stack_ == NULL); | 835 DCHECK(target_stack_ == NULL); |
| 836 | 836 |
| 837 return result; | 837 return result; |
| 838 } | 838 } |
| 839 | 839 |
| 840 | 840 FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info) { |
| 841 FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) { | |
| 842 // It's OK to use the Isolate & counters here, since this function is only | 841 // It's OK to use the Isolate & counters here, since this function is only |
| 843 // called in the main thread. | 842 // called in the main thread. |
| 844 DCHECK(parsing_on_main_thread_); | 843 DCHECK(parsing_on_main_thread_); |
| 845 RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::ParseLazy); | 844 RuntimeCallTimerScope runtime_timer(isolate, |
| 845 &RuntimeCallStats::ParseFunction); |
| 846 HistogramTimerScope timer_scope(isolate->counters()->parse_lazy()); | 846 HistogramTimerScope timer_scope(isolate->counters()->parse_lazy()); |
| 847 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseLazy"); | 847 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseFunction"); |
| 848 Handle<String> source(String::cast(info->script()->source())); | 848 Handle<String> source(String::cast(info->script()->source())); |
| 849 isolate->counters()->total_parse_size()->Increment(source->length()); | 849 isolate->counters()->total_parse_size()->Increment(source->length()); |
| 850 base::ElapsedTimer timer; | 850 base::ElapsedTimer timer; |
| 851 if (FLAG_trace_parse) { | 851 if (FLAG_trace_parse) { |
| 852 timer.Start(); | 852 timer.Start(); |
| 853 } | 853 } |
| 854 Handle<SharedFunctionInfo> shared_info = info->shared_info(); | 854 Handle<SharedFunctionInfo> shared_info = info->shared_info(); |
| 855 DeserializeScopeChain(info, info->maybe_outer_scope_info()); | 855 DeserializeScopeChain(info, info->maybe_outer_scope_info()); |
| 856 | 856 |
| 857 // Initialize parser state. | 857 // Initialize parser state. |
| 858 source = String::Flatten(source); | 858 source = String::Flatten(source); |
| 859 FunctionLiteral* result; | 859 FunctionLiteral* result; |
| 860 { | 860 { |
| 861 std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For( | 861 std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For( |
| 862 source, shared_info->start_position(), shared_info->end_position())); | 862 source, shared_info->start_position(), shared_info->end_position())); |
| 863 Handle<String> name(String::cast(shared_info->name())); | 863 Handle<String> name(String::cast(shared_info->name())); |
| 864 result = | 864 result = DoParseFunction(info, ast_value_factory()->GetString(name), |
| 865 DoParseLazy(info, ast_value_factory()->GetString(name), stream.get()); | 865 stream.get()); |
| 866 if (result != nullptr) { | 866 if (result != nullptr) { |
| 867 Handle<String> inferred_name(shared_info->inferred_name()); | 867 Handle<String> inferred_name(shared_info->inferred_name()); |
| 868 result->set_inferred_name(inferred_name); | 868 result->set_inferred_name(inferred_name); |
| 869 } | 869 } |
| 870 } | 870 } |
| 871 | 871 |
| 872 if (FLAG_trace_parse && result != NULL) { | 872 if (FLAG_trace_parse && result != NULL) { |
| 873 double ms = timer.Elapsed().InMillisecondsF(); | 873 double ms = timer.Elapsed().InMillisecondsF(); |
| 874 // We need to make sure that the debug-name is available. | 874 // We need to make sure that the debug-name is available. |
| 875 ast_value_factory()->Internalize(isolate); | 875 ast_value_factory()->Internalize(isolate); |
| 876 std::unique_ptr<char[]> name_chars = result->debug_name()->ToCString(); | 876 std::unique_ptr<char[]> name_chars = result->debug_name()->ToCString(); |
| 877 PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms); | 877 PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms); |
| 878 } | 878 } |
| 879 return result; | 879 return result; |
| 880 } | 880 } |
| 881 | 881 |
| 882 static FunctionLiteral::FunctionType ComputeFunctionType(ParseInfo* info) { | 882 static FunctionLiteral::FunctionType ComputeFunctionType(ParseInfo* info) { |
| 883 if (info->is_declaration()) { | 883 if (info->is_declaration()) { |
| 884 return FunctionLiteral::kDeclaration; | 884 return FunctionLiteral::kDeclaration; |
| 885 } else if (info->is_named_expression()) { | 885 } else if (info->is_named_expression()) { |
| 886 return FunctionLiteral::kNamedExpression; | 886 return FunctionLiteral::kNamedExpression; |
| 887 } else if (IsConciseMethod(info->function_kind()) || | 887 } else if (IsConciseMethod(info->function_kind()) || |
| 888 IsAccessorFunction(info->function_kind())) { | 888 IsAccessorFunction(info->function_kind())) { |
| 889 return FunctionLiteral::kAccessorOrMethod; | 889 return FunctionLiteral::kAccessorOrMethod; |
| 890 } | 890 } |
| 891 return FunctionLiteral::kAnonymousExpression; | 891 return FunctionLiteral::kAnonymousExpression; |
| 892 } | 892 } |
| 893 | 893 |
| 894 FunctionLiteral* Parser::DoParseLazy(ParseInfo* info, | 894 FunctionLiteral* Parser::DoParseFunction(ParseInfo* info, |
| 895 const AstRawString* raw_name, | 895 const AstRawString* raw_name, |
| 896 Utf16CharacterStream* source) { | 896 Utf16CharacterStream* source) { |
| 897 scanner_.Initialize(source); | 897 scanner_.Initialize(source); |
| 898 DCHECK_NULL(scope_state_); | 898 DCHECK_NULL(scope_state_); |
| 899 DCHECK_NULL(target_stack_); | 899 DCHECK_NULL(target_stack_); |
| 900 | 900 |
| 901 DCHECK(ast_value_factory()); | 901 DCHECK(ast_value_factory()); |
| 902 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); | 902 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); |
| 903 fni_->PushEnclosingName(raw_name); | 903 fni_->PushEnclosingName(raw_name); |
| 904 | 904 |
| 905 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | 905 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); |
| 906 | 906 |
| (...skipping 1875 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2782 if (entry.uses_super_property()) scope->RecordSuperPropertyUsage(); | 2782 if (entry.uses_super_property()) scope->RecordSuperPropertyUsage(); |
| 2783 if (entry.calls_eval()) scope->RecordEvalCall(); | 2783 if (entry.calls_eval()) scope->RecordEvalCall(); |
| 2784 return kLazyParsingComplete; | 2784 return kLazyParsingComplete; |
| 2785 } | 2785 } |
| 2786 cached_parse_data_->Reject(); | 2786 cached_parse_data_->Reject(); |
| 2787 } | 2787 } |
| 2788 // With no cached data, we partially parse the function, without building an | 2788 // With no cached data, we partially parse the function, without building an |
| 2789 // AST. This gathers the data needed to build a lazy function. | 2789 // AST. This gathers the data needed to build a lazy function. |
| 2790 SingletonLogger logger; | 2790 SingletonLogger logger; |
| 2791 PreParser::PreParseResult result = | 2791 PreParser::PreParseResult result = |
| 2792 ParseLazyFunctionBodyWithPreParser(&logger, is_inner_function, may_abort); | 2792 ParseFunctionBodyWithPreParser(&logger, is_inner_function, may_abort); |
| 2793 | 2793 |
| 2794 // Return immediately if pre-parser decided to abort parsing. | 2794 // Return immediately if pre-parser decided to abort parsing. |
| 2795 if (result == PreParser::kPreParseAbort) return kLazyParsingAborted; | 2795 if (result == PreParser::kPreParseAbort) return kLazyParsingAborted; |
| 2796 if (result == PreParser::kPreParseStackOverflow) { | 2796 if (result == PreParser::kPreParseStackOverflow) { |
| 2797 // Propagate stack overflow. | 2797 // Propagate stack overflow. |
| 2798 set_stack_overflow(); | 2798 set_stack_overflow(); |
| 2799 *ok = false; | 2799 *ok = false; |
| 2800 return kLazyParsingComplete; | 2800 return kLazyParsingComplete; |
| 2801 } | 2801 } |
| 2802 if (logger.has_error()) { | 2802 if (logger.has_error()) { |
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3242 } else { | 3242 } else { |
| 3243 statement = factory()->NewEmptyStatement(kNoSourcePosition); | 3243 statement = factory()->NewEmptyStatement(kNoSourcePosition); |
| 3244 } | 3244 } |
| 3245 result->Set(kFunctionNameAssignmentIndex, statement); | 3245 result->Set(kFunctionNameAssignmentIndex, statement); |
| 3246 } | 3246 } |
| 3247 | 3247 |
| 3248 MarkCollectedTailCallExpressions(); | 3248 MarkCollectedTailCallExpressions(); |
| 3249 return result; | 3249 return result; |
| 3250 } | 3250 } |
| 3251 | 3251 |
| 3252 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( | 3252 PreParser::PreParseResult Parser::ParseFunctionBodyWithPreParser( |
| 3253 SingletonLogger* logger, bool is_inner_function, bool may_abort) { | 3253 SingletonLogger* logger, bool is_inner_function, bool may_abort) { |
| 3254 // This function may be called on a background thread too; record only the | 3254 // This function may be called on a background thread too; record only the |
| 3255 // main thread preparse times. | 3255 // main thread preparse times. |
| 3256 if (pre_parse_timer_ != NULL) { | 3256 if (pre_parse_timer_ != NULL) { |
| 3257 pre_parse_timer_->Start(); | 3257 pre_parse_timer_->Start(); |
| 3258 } | 3258 } |
| 3259 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse"); | 3259 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse"); |
| 3260 | 3260 |
| 3261 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); | 3261 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); |
| 3262 | 3262 |
| 3263 if (reusable_preparser_ == NULL) { | 3263 if (reusable_preparser_ == NULL) { |
| 3264 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), | 3264 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), |
| 3265 NULL, stack_limit_); | 3265 NULL, stack_limit_); |
| 3266 reusable_preparser_->set_allow_lazy(true); | 3266 reusable_preparser_->set_allow_lazy(true); |
| 3267 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); | 3267 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); |
| 3268 SET_ALLOW(natives); | 3268 SET_ALLOW(natives); |
| 3269 SET_ALLOW(harmony_do_expressions); | 3269 SET_ALLOW(harmony_do_expressions); |
| 3270 SET_ALLOW(harmony_function_sent); | 3270 SET_ALLOW(harmony_function_sent); |
| 3271 SET_ALLOW(harmony_restrictive_declarations); | 3271 SET_ALLOW(harmony_restrictive_declarations); |
| 3272 SET_ALLOW(harmony_async_await); | 3272 SET_ALLOW(harmony_async_await); |
| 3273 SET_ALLOW(harmony_trailing_commas); | 3273 SET_ALLOW(harmony_trailing_commas); |
| 3274 SET_ALLOW(harmony_class_fields); | 3274 SET_ALLOW(harmony_class_fields); |
| 3275 #undef SET_ALLOW | 3275 #undef SET_ALLOW |
| 3276 } | 3276 } |
| 3277 // Aborting inner function preparsing would leave scopes in an inconsistent | 3277 // Aborting inner function preparsing would leave scopes in an inconsistent |
| 3278 // state; we don't parse inner functions in the abortable mode anyway. | 3278 // state; we don't parse inner functions in the abortable mode anyway. |
| 3279 DCHECK(!is_inner_function || !may_abort); | 3279 DCHECK(!is_inner_function || !may_abort); |
| 3280 | 3280 |
| 3281 DeclarationScope* function_scope = function_state_->scope(); | 3281 DeclarationScope* function_scope = function_state_->scope(); |
| 3282 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( | 3282 PreParser::PreParseResult result = reusable_preparser_->PreParseFunction( |
| 3283 function_scope, parsing_module_, logger, is_inner_function, may_abort, | 3283 function_scope, parsing_module_, logger, is_inner_function, may_abort, |
| 3284 use_counts_); | 3284 use_counts_); |
| 3285 if (pre_parse_timer_ != NULL) { | 3285 if (pre_parse_timer_ != NULL) { |
| 3286 pre_parse_timer_->Stop(); | 3286 pre_parse_timer_->Stop(); |
| 3287 } | 3287 } |
| 3288 return result; | 3288 return result; |
| 3289 } | 3289 } |
| 3290 | 3290 |
| 3291 Expression* Parser::InstallHomeObject(Expression* function_literal, | 3291 Expression* Parser::InstallHomeObject(Expression* function_literal, |
| 3292 Expression* home_object) { | 3292 Expression* home_object) { |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3764 FunctionLiteral* result = NULL; | 3764 FunctionLiteral* result = NULL; |
| 3765 // Ok to use Isolate here; this function is only called in the main thread. | 3765 // Ok to use Isolate here; this function is only called in the main thread. |
| 3766 DCHECK(parsing_on_main_thread_); | 3766 DCHECK(parsing_on_main_thread_); |
| 3767 Isolate* isolate = info->isolate(); | 3767 Isolate* isolate = info->isolate(); |
| 3768 pre_parse_timer_ = isolate->counters()->pre_parse(); | 3768 pre_parse_timer_ = isolate->counters()->pre_parse(); |
| 3769 | 3769 |
| 3770 if (info->is_toplevel()) { | 3770 if (info->is_toplevel()) { |
| 3771 SetCachedData(info); | 3771 SetCachedData(info); |
| 3772 result = ParseProgram(isolate, info); | 3772 result = ParseProgram(isolate, info); |
| 3773 } else { | 3773 } else { |
| 3774 result = ParseLazy(isolate, info); | 3774 result = ParseFunction(isolate, info); |
| 3775 } | 3775 } |
| 3776 info->set_literal(result); | 3776 info->set_literal(result); |
| 3777 | 3777 |
| 3778 Internalize(isolate, info->script(), result == NULL); | 3778 Internalize(isolate, info->script(), result == NULL); |
| 3779 return (result != NULL); | 3779 return (result != NULL); |
| 3780 } | 3780 } |
| 3781 | 3781 |
| 3782 | 3782 |
| 3783 void Parser::ParseOnBackground(ParseInfo* info) { | 3783 void Parser::ParseOnBackground(ParseInfo* info) { |
| 3784 parsing_on_main_thread_ = false; | 3784 parsing_on_main_thread_ = false; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3808 // it. The raw data can be UTF-8, so we wouldn't know the source length until | 3808 // it. The raw data can be UTF-8, so we wouldn't know the source length until |
| 3809 // we have decoded it anyway even if we knew the raw data length (which we | 3809 // we have decoded it anyway even if we knew the raw data length (which we |
| 3810 // don't). We work around this by storing all the scopes which need their end | 3810 // don't). We work around this by storing all the scopes which need their end |
| 3811 // position set at the end of the script (the top scope and possible eval | 3811 // position set at the end of the script (the top scope and possible eval |
| 3812 // scopes) and set their end position after we know the script length. | 3812 // scopes) and set their end position after we know the script length. |
| 3813 if (info->is_toplevel()) { | 3813 if (info->is_toplevel()) { |
| 3814 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); | 3814 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); |
| 3815 scanner_.Initialize(stream_ptr); | 3815 scanner_.Initialize(stream_ptr); |
| 3816 result = DoParseProgram(info); | 3816 result = DoParseProgram(info); |
| 3817 } else { | 3817 } else { |
| 3818 result = DoParseLazy(info, info->function_name(), stream_ptr); | 3818 result = DoParseFunction(info, info->function_name(), stream_ptr); |
| 3819 } | 3819 } |
| 3820 | 3820 |
| 3821 info->set_literal(result); | 3821 info->set_literal(result); |
| 3822 | 3822 |
| 3823 // We cannot internalize on a background thread; a foreground task will take | 3823 // We cannot internalize on a background thread; a foreground task will take |
| 3824 // care of calling Parser::Internalize just before compilation. | 3824 // care of calling Parser::Internalize just before compilation. |
| 3825 | 3825 |
| 3826 if (produce_cached_parse_data()) { | 3826 if (produce_cached_parse_data()) { |
| 3827 if (result != NULL) *info->cached_data() = recorder.GetScriptData(); | 3827 if (result != NULL) *info->cached_data() = recorder.GetScriptData(); |
| 3828 log_ = NULL; | 3828 log_ = NULL; |
| (...skipping 1569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5398 | 5398 |
| 5399 return final_loop; | 5399 return final_loop; |
| 5400 } | 5400 } |
| 5401 | 5401 |
| 5402 #undef CHECK_OK | 5402 #undef CHECK_OK |
| 5403 #undef CHECK_OK_VOID | 5403 #undef CHECK_OK_VOID |
| 5404 #undef CHECK_FAILED | 5404 #undef CHECK_FAILED |
| 5405 | 5405 |
| 5406 } // namespace internal | 5406 } // namespace internal |
| 5407 } // namespace v8 | 5407 } // namespace v8 |
| OLD | NEW |