Chromium Code Reviews| 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.h" | 10 #include "src/ast/ast.h" |
| (...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 850 } | 850 } |
| 851 if (info->ast_value_factory() == NULL) { | 851 if (info->ast_value_factory() == NULL) { |
| 852 // info takes ownership of AstValueFactory. | 852 // info takes ownership of AstValueFactory. |
| 853 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed())); | 853 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed())); |
| 854 info->set_ast_value_factory_owned(); | 854 info->set_ast_value_factory_owned(); |
| 855 ast_value_factory_ = info->ast_value_factory(); | 855 ast_value_factory_ = info->ast_value_factory(); |
| 856 ast_node_factory_.set_ast_value_factory(ast_value_factory_); | 856 ast_node_factory_.set_ast_value_factory(ast_value_factory_); |
| 857 } | 857 } |
| 858 } | 858 } |
| 859 | 859 |
| 860 void Parser::DeserializeScopeChain( | |
| 861 ParseInfo* info, Handle<Context> context, | |
| 862 Scope::DeserializationMode deserialization_mode) { | |
| 863 // TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native | |
| 864 // context, which will have the "this" binding for script scopes. | |
| 865 Scope* scope = NewScriptScope(); | |
| 866 info->set_script_scope(scope); | |
| 867 if (!context.is_null() && !context->IsNativeContext()) { | |
| 868 scope = | |
| 869 Scope::DeserializeScopeChain(info->isolate(), zone(), *context, scope, | |
| 870 ast_value_factory(), deserialization_mode); | |
| 871 if (info->context().is_null()) { | |
| 872 DCHECK(deserialization_mode == | |
| 873 Scope::DeserializationMode::kDeserializeOffHeap); | |
| 874 } else { | |
| 875 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this | |
| 876 // means the Parser cannot operate independent of the V8 heap. Tell the | |
| 877 // string table to internalize strings and values right after they're | |
| 878 // created. This kind of parsing can only be done in the main thread. | |
| 879 DCHECK(parsing_on_main_thread_); | |
| 880 ast_value_factory()->Internalize(info->isolate()); | |
| 881 } | |
| 882 } | |
| 883 original_scope_ = scope; | |
| 884 } | |
| 860 | 885 |
| 861 FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { | 886 FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { |
| 862 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here, | 887 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here, |
| 863 // see comment for HistogramTimerScope class. | 888 // see comment for HistogramTimerScope class. |
| 864 | 889 |
| 865 // It's OK to use the Isolate & counters here, since this function is only | 890 // It's OK to use the Isolate & counters here, since this function is only |
| 866 // called in the main thread. | 891 // called in the main thread. |
| 867 DCHECK(parsing_on_main_thread_); | 892 DCHECK(parsing_on_main_thread_); |
| 868 | 893 |
| 869 HistogramTimerScope timer_scope(isolate->counters()->parse(), true); | 894 HistogramTimerScope timer_scope(isolate->counters()->parse(), true); |
| 870 RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::Parse); | 895 RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::Parse); |
| 871 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.Parse"); | 896 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.Parse"); |
| 872 Handle<String> source(String::cast(info->script()->source())); | 897 Handle<String> source(String::cast(info->script()->source())); |
| 873 isolate->counters()->total_parse_size()->Increment(source->length()); | 898 isolate->counters()->total_parse_size()->Increment(source->length()); |
| 874 base::ElapsedTimer timer; | 899 base::ElapsedTimer timer; |
| 875 if (FLAG_trace_parse) { | 900 if (FLAG_trace_parse) { |
| 876 timer.Start(); | 901 timer.Start(); |
| 877 } | 902 } |
| 878 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); | 903 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); |
| 879 | 904 |
| 880 // Initialize parser state. | 905 // Initialize parser state. |
| 881 CompleteParserRecorder recorder; | 906 CompleteParserRecorder recorder; |
| 882 | 907 |
| 883 if (produce_cached_parse_data()) { | 908 if (produce_cached_parse_data()) { |
| 884 log_ = &recorder; | 909 log_ = &recorder; |
| 885 } else if (consume_cached_parse_data()) { | 910 } else if (consume_cached_parse_data()) { |
| 886 cached_parse_data_->Initialize(); | 911 cached_parse_data_->Initialize(); |
| 887 } | 912 } |
| 888 | 913 |
| 914 DeserializeScopeChain(info, info->context(), | |
| 915 Scope::DeserializationMode::kKeepScopeInfo); | |
| 916 | |
| 889 source = String::Flatten(source); | 917 source = String::Flatten(source); |
| 890 FunctionLiteral* result; | 918 FunctionLiteral* result; |
| 891 | 919 |
| 892 { | 920 { |
| 893 std::unique_ptr<Utf16CharacterStream> stream; | 921 std::unique_ptr<Utf16CharacterStream> stream; |
| 894 if (source->IsExternalTwoByteString()) { | 922 if (source->IsExternalTwoByteString()) { |
| 895 stream.reset(new ExternalTwoByteStringUtf16CharacterStream( | 923 stream.reset(new ExternalTwoByteStringUtf16CharacterStream( |
| 896 Handle<ExternalTwoByteString>::cast(source), 0, source->length())); | 924 Handle<ExternalTwoByteString>::cast(source), 0, source->length())); |
| 897 } else if (source->IsExternalOneByteString()) { | 925 } else if (source->IsExternalOneByteString()) { |
| 898 stream.reset(new ExternalOneByteStringUtf16CharacterStream( | 926 stream.reset(new ExternalOneByteStringUtf16CharacterStream( |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 935 // background thread. We should not access anything Isolate / heap dependent | 963 // background thread. We should not access anything Isolate / heap dependent |
| 936 // via ParseInfo, and also not pass it forward. | 964 // via ParseInfo, and also not pass it forward. |
| 937 DCHECK_NULL(scope_state_); | 965 DCHECK_NULL(scope_state_); |
| 938 DCHECK_NULL(target_stack_); | 966 DCHECK_NULL(target_stack_); |
| 939 | 967 |
| 940 Mode parsing_mode = FLAG_lazy && allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY; | 968 Mode parsing_mode = FLAG_lazy && allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY; |
| 941 if (allow_natives() || extension_ != NULL) parsing_mode = PARSE_EAGERLY; | 969 if (allow_natives() || extension_ != NULL) parsing_mode = PARSE_EAGERLY; |
| 942 | 970 |
| 943 FunctionLiteral* result = NULL; | 971 FunctionLiteral* result = NULL; |
| 944 { | 972 { |
| 945 // TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native | 973 Scope* scope = original_scope_; |
| 946 // context, which will have the "this" binding for script scopes. | 974 DCHECK(scope); |
| 947 Scope* scope = NewScriptScope(); | |
| 948 info->set_script_scope(scope); | |
| 949 if (!info->context().is_null() && !info->context()->IsNativeContext()) { | |
| 950 scope = Scope::DeserializeScopeChain(info->isolate(), zone(), | |
| 951 *info->context(), scope, | |
| 952 ast_value_factory()); | |
| 953 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this | |
| 954 // means the Parser cannot operate independent of the V8 heap. Tell the | |
| 955 // string table to internalize strings and values right after they're | |
| 956 // created. This kind of parsing can only be done in the main thread. | |
| 957 DCHECK(parsing_on_main_thread_); | |
| 958 ast_value_factory()->Internalize(info->isolate()); | |
| 959 } | |
| 960 original_scope_ = scope; | |
| 961 if (info->is_eval()) { | 975 if (info->is_eval()) { |
| 962 if (!scope->is_script_scope() || is_strict(info->language_mode())) { | 976 if (!scope->is_script_scope() || is_strict(info->language_mode())) { |
| 963 parsing_mode = PARSE_EAGERLY; | 977 parsing_mode = PARSE_EAGERLY; |
| 964 } | 978 } |
| 965 scope = NewScopeWithParent(scope, EVAL_SCOPE); | 979 scope = NewScopeWithParent(scope, EVAL_SCOPE); |
| 966 } else if (info->is_module()) { | 980 } else if (info->is_module()) { |
| 967 scope = NewScopeWithParent(scope, MODULE_SCOPE); | 981 scope = NewScopeWithParent(scope, MODULE_SCOPE); |
| 968 } | 982 } |
| 969 | 983 |
| 970 scope->set_start_position(0); | 984 scope->set_start_position(0); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1041 RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::ParseLazy); | 1055 RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::ParseLazy); |
| 1042 HistogramTimerScope timer_scope(isolate->counters()->parse_lazy()); | 1056 HistogramTimerScope timer_scope(isolate->counters()->parse_lazy()); |
| 1043 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseLazy"); | 1057 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseLazy"); |
| 1044 Handle<String> source(String::cast(info->script()->source())); | 1058 Handle<String> source(String::cast(info->script()->source())); |
| 1045 isolate->counters()->total_parse_size()->Increment(source->length()); | 1059 isolate->counters()->total_parse_size()->Increment(source->length()); |
| 1046 base::ElapsedTimer timer; | 1060 base::ElapsedTimer timer; |
| 1047 if (FLAG_trace_parse) { | 1061 if (FLAG_trace_parse) { |
| 1048 timer.Start(); | 1062 timer.Start(); |
| 1049 } | 1063 } |
| 1050 Handle<SharedFunctionInfo> shared_info = info->shared_info(); | 1064 Handle<SharedFunctionInfo> shared_info = info->shared_info(); |
| 1065 DeserializeScopeChain(info, info->context(), | |
| 1066 Scope::DeserializationMode::kKeepScopeInfo); | |
| 1051 | 1067 |
| 1052 // Initialize parser state. | 1068 // Initialize parser state. |
| 1053 source = String::Flatten(source); | 1069 source = String::Flatten(source); |
| 1054 FunctionLiteral* result; | 1070 FunctionLiteral* result; |
| 1055 { | 1071 { |
| 1056 std::unique_ptr<Utf16CharacterStream> stream; | 1072 std::unique_ptr<Utf16CharacterStream> stream; |
| 1057 if (source->IsExternalTwoByteString()) { | 1073 if (source->IsExternalTwoByteString()) { |
| 1058 stream.reset(new ExternalTwoByteStringUtf16CharacterStream( | 1074 stream.reset(new ExternalTwoByteStringUtf16CharacterStream( |
| 1059 Handle<ExternalTwoByteString>::cast(source), | 1075 Handle<ExternalTwoByteString>::cast(source), |
| 1060 shared_info->start_position(), shared_info->end_position())); | 1076 shared_info->start_position(), shared_info->end_position())); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1103 const AstRawString* raw_name = ast_value_factory()->GetString(name); | 1119 const AstRawString* raw_name = ast_value_factory()->GetString(name); |
| 1104 fni_->PushEnclosingName(raw_name); | 1120 fni_->PushEnclosingName(raw_name); |
| 1105 | 1121 |
| 1106 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | 1122 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); |
| 1107 | 1123 |
| 1108 // Place holder for the result. | 1124 // Place holder for the result. |
| 1109 FunctionLiteral* result = nullptr; | 1125 FunctionLiteral* result = nullptr; |
| 1110 | 1126 |
| 1111 { | 1127 { |
| 1112 // Parse the function literal. | 1128 // Parse the function literal. |
| 1113 Scope* scope = NewScriptScope(); | 1129 Scope* scope = original_scope_; |
| 1114 info->set_script_scope(scope); | 1130 DCHECK(scope); |
| 1115 if (!info->context().is_null()) { | |
| 1116 // Ok to use Isolate here, since lazy function parsing is only done in the | |
| 1117 // main thread. | |
| 1118 DCHECK(parsing_on_main_thread_); | |
| 1119 scope = Scope::DeserializeScopeChain(isolate, zone(), *info->context(), | |
| 1120 scope, ast_value_factory()); | |
| 1121 } | |
| 1122 original_scope_ = scope; | |
| 1123 FunctionState function_state(&function_state_, &scope_state_, scope, | 1131 FunctionState function_state(&function_state_, &scope_state_, scope, |
| 1124 shared_info->kind()); | 1132 shared_info->kind()); |
| 1125 DCHECK(is_sloppy(scope->language_mode()) || | 1133 DCHECK(is_sloppy(scope->language_mode()) || |
| 1126 is_strict(info->language_mode())); | 1134 is_strict(info->language_mode())); |
| 1127 DCHECK(info->language_mode() == shared_info->language_mode()); | 1135 DCHECK(info->language_mode() == shared_info->language_mode()); |
| 1128 FunctionLiteral::FunctionType function_type = | 1136 FunctionLiteral::FunctionType function_type = |
| 1129 ComputeFunctionType(shared_info); | 1137 ComputeFunctionType(shared_info); |
| 1130 bool ok = true; | 1138 bool ok = true; |
| 1131 | 1139 |
| 1132 if (shared_info->is_arrow()) { | 1140 if (shared_info->is_arrow()) { |
| (...skipping 4329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5462 stream_ptr = info->character_stream(); | 5470 stream_ptr = info->character_stream(); |
| 5463 } else { | 5471 } else { |
| 5464 DCHECK(info->character_stream() == nullptr); | 5472 DCHECK(info->character_stream() == nullptr); |
| 5465 stream.reset(new ExternalStreamingStream(info->source_stream(), | 5473 stream.reset(new ExternalStreamingStream(info->source_stream(), |
| 5466 info->source_stream_encoding())); | 5474 info->source_stream_encoding())); |
| 5467 stream_ptr = stream.get(); | 5475 stream_ptr = stream.get(); |
| 5468 } | 5476 } |
| 5469 scanner_.Initialize(stream_ptr); | 5477 scanner_.Initialize(stream_ptr); |
| 5470 DCHECK(info->context().is_null() || info->context()->IsNativeContext()); | 5478 DCHECK(info->context().is_null() || info->context()->IsNativeContext()); |
| 5471 | 5479 |
| 5480 if (!original_scope_) { | |
|
Toon Verwaest
2016/08/03 12:31:46
Add a comment why we might (not) have original_sco
| |
| 5481 DeserializeScopeChain(info, info->context(), | |
| 5482 Scope::DeserializationMode::kDeserializeOffHeap); | |
| 5483 } | |
| 5484 | |
| 5472 // When streaming, we don't know the length of the source until we have parsed | 5485 // When streaming, we don't know the length of the source until we have parsed |
| 5473 // it. The raw data can be UTF-8, so we wouldn't know the source length until | 5486 // it. The raw data can be UTF-8, so we wouldn't know the source length until |
| 5474 // we have decoded it anyway even if we knew the raw data length (which we | 5487 // we have decoded it anyway even if we knew the raw data length (which we |
| 5475 // don't). We work around this by storing all the scopes which need their end | 5488 // don't). We work around this by storing all the scopes which need their end |
| 5476 // position set at the end of the script (the top scope and possible eval | 5489 // position set at the end of the script (the top scope and possible eval |
| 5477 // scopes) and set their end position after we know the script length. | 5490 // scopes) and set their end position after we know the script length. |
| 5478 result = DoParseProgram(info); | 5491 result = DoParseProgram(info); |
| 5479 | 5492 |
| 5480 info->set_literal(result); | 5493 info->set_literal(result); |
| 5481 | 5494 |
| (...skipping 1605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7087 node->Print(Isolate::Current()); | 7100 node->Print(Isolate::Current()); |
| 7088 } | 7101 } |
| 7089 #endif // DEBUG | 7102 #endif // DEBUG |
| 7090 | 7103 |
| 7091 #undef CHECK_OK | 7104 #undef CHECK_OK |
| 7092 #undef CHECK_OK_VOID | 7105 #undef CHECK_OK_VOID |
| 7093 #undef CHECK_FAILED | 7106 #undef CHECK_FAILED |
| 7094 | 7107 |
| 7095 } // namespace internal | 7108 } // namespace internal |
| 7096 } // namespace v8 | 7109 } // namespace v8 |
| OLD | NEW |