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 |