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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/ast.h" | 8 #include "src/ast.h" |
9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 | 195 |
196 int ParseData::FunctionCount() { | 196 int ParseData::FunctionCount() { |
197 int functions_size = FunctionsSize(); | 197 int functions_size = FunctionsSize(); |
198 if (functions_size < 0) return 0; | 198 if (functions_size < 0) return 0; |
199 if (functions_size % FunctionEntry::kSize != 0) return 0; | 199 if (functions_size % FunctionEntry::kSize != 0) return 0; |
200 return functions_size / FunctionEntry::kSize; | 200 return functions_size / FunctionEntry::kSize; |
201 } | 201 } |
202 | 202 |
203 | 203 |
204 bool ParseData::IsSane() { | 204 bool ParseData::IsSane() { |
205 if (!IsAligned(script_data_->length(), sizeof(unsigned))) return false; | |
206 // Check that the header data is valid and doesn't specify | 205 // Check that the header data is valid and doesn't specify |
207 // point to positions outside the store. | 206 // point to positions outside the store. |
208 int data_length = Length(); | 207 int data_length = Length(); |
209 if (data_length < PreparseDataConstants::kHeaderSize) return false; | 208 if (data_length < PreparseDataConstants::kHeaderSize) return false; |
210 if (Magic() != PreparseDataConstants::kMagicNumber) return false; | 209 if (Magic() != PreparseDataConstants::kMagicNumber) return false; |
211 if (Version() != PreparseDataConstants::kCurrentVersion) return false; | 210 if (Version() != PreparseDataConstants::kCurrentVersion) return false; |
212 if (HasError()) return false; | 211 if (HasError()) return false; |
213 // Check that the space allocated for function entries is sane. | 212 // Check that the space allocated for function entries is sane. |
214 int functions_size = FunctionsSize(); | 213 int functions_size = FunctionsSize(); |
215 if (functions_size < 0) return false; | 214 if (functions_size < 0) return false; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]); | 249 return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]); |
251 } | 250 } |
252 | 251 |
253 | 252 |
254 void Parser::SetCachedData() { | 253 void Parser::SetCachedData() { |
255 if (compile_options() == ScriptCompiler::kNoCompileOptions) { | 254 if (compile_options() == ScriptCompiler::kNoCompileOptions) { |
256 cached_parse_data_ = NULL; | 255 cached_parse_data_ = NULL; |
257 } else { | 256 } else { |
258 DCHECK(info_->cached_data() != NULL); | 257 DCHECK(info_->cached_data() != NULL); |
259 if (compile_options() == ScriptCompiler::kConsumeParserCache) { | 258 if (compile_options() == ScriptCompiler::kConsumeParserCache) { |
260 cached_parse_data_ = ParseData::FromCachedData(*info_->cached_data()); | 259 cached_parse_data_ = new ParseData(*info_->cached_data()); |
261 } | 260 } |
262 } | 261 } |
263 } | 262 } |
264 | 263 |
265 | 264 |
266 Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) { | 265 Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) { |
267 DCHECK(ast_value_factory()); | 266 DCHECK(ast_value_factory()); |
268 Scope* result = | 267 Scope* result = |
269 new (zone()) Scope(parent, scope_type, ast_value_factory(), zone()); | 268 new (zone()) Scope(parent, scope_type, ast_value_factory(), zone()); |
270 result->Initialize(); | 269 result->Initialize(); |
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
838 base::ElapsedTimer timer; | 837 base::ElapsedTimer timer; |
839 if (FLAG_trace_parse) { | 838 if (FLAG_trace_parse) { |
840 timer.Start(); | 839 timer.Start(); |
841 } | 840 } |
842 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); | 841 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); |
843 | 842 |
844 // Initialize parser state. | 843 // Initialize parser state. |
845 CompleteParserRecorder recorder; | 844 CompleteParserRecorder recorder; |
846 | 845 |
847 debug_saved_compile_options_ = compile_options(); | 846 debug_saved_compile_options_ = compile_options(); |
848 if (produce_cached_parse_data()) { | 847 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
849 log_ = &recorder; | 848 log_ = &recorder; |
850 } else if (consume_cached_parse_data()) { | 849 } else if (compile_options() == ScriptCompiler::kConsumeParserCache) { |
851 cached_parse_data_->Initialize(); | 850 cached_parse_data_->Initialize(); |
852 } | 851 } |
853 | 852 |
854 source = String::Flatten(source); | 853 source = String::Flatten(source); |
855 FunctionLiteral* result; | 854 FunctionLiteral* result; |
856 | 855 |
857 Scope* top_scope = NULL; | 856 Scope* top_scope = NULL; |
858 Scope* eval_scope = NULL; | 857 Scope* eval_scope = NULL; |
859 if (source->IsExternalTwoByteString()) { | 858 if (source->IsExternalTwoByteString()) { |
860 // Notice that the stream is destroyed at the end of the branch block. | 859 // Notice that the stream is destroyed at the end of the branch block. |
(...skipping 20 matching lines...) Expand all Loading... |
881 PrintF("[parsing eval"); | 880 PrintF("[parsing eval"); |
882 } else if (info()->script()->name()->IsString()) { | 881 } else if (info()->script()->name()->IsString()) { |
883 String* name = String::cast(info()->script()->name()); | 882 String* name = String::cast(info()->script()->name()); |
884 SmartArrayPointer<char> name_chars = name->ToCString(); | 883 SmartArrayPointer<char> name_chars = name->ToCString(); |
885 PrintF("[parsing script: %s", name_chars.get()); | 884 PrintF("[parsing script: %s", name_chars.get()); |
886 } else { | 885 } else { |
887 PrintF("[parsing script"); | 886 PrintF("[parsing script"); |
888 } | 887 } |
889 PrintF(" - took %0.3f ms]\n", ms); | 888 PrintF(" - took %0.3f ms]\n", ms); |
890 } | 889 } |
891 if (produce_cached_parse_data()) { | 890 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
892 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); | 891 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); |
893 log_ = NULL; | 892 log_ = NULL; |
894 } | 893 } |
895 return result; | 894 return result; |
896 } | 895 } |
897 | 896 |
898 | 897 |
899 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope, | 898 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope, |
900 Scope** eval_scope) { | 899 Scope** eval_scope) { |
901 DCHECK(scope_ == NULL); | 900 DCHECK(scope_ == NULL); |
(...skipping 2853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3755 int* materialized_literal_count, | 3754 int* materialized_literal_count, |
3756 int* expected_property_count, | 3755 int* expected_property_count, |
3757 bool* ok) { | 3756 bool* ok) { |
3758 // Temporary debugging code for tracking down a mystery crash which should | 3757 // Temporary debugging code for tracking down a mystery crash which should |
3759 // never happen. The crash happens on the line where we log the function in | 3758 // never happen. The crash happens on the line where we log the function in |
3760 // the preparse data: log_->LogFunction(...). TODO(marja): remove this once | 3759 // the preparse data: log_->LogFunction(...). TODO(marja): remove this once |
3761 // done. | 3760 // done. |
3762 CHECK(materialized_literal_count); | 3761 CHECK(materialized_literal_count); |
3763 CHECK(expected_property_count); | 3762 CHECK(expected_property_count); |
3764 CHECK(debug_saved_compile_options_ == compile_options()); | 3763 CHECK(debug_saved_compile_options_ == compile_options()); |
3765 if (produce_cached_parse_data()) CHECK(log_); | 3764 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
| 3765 CHECK(log_); |
| 3766 } |
3766 | 3767 |
3767 int function_block_pos = position(); | 3768 int function_block_pos = position(); |
3768 if (consume_cached_parse_data()) { | 3769 if (compile_options() == ScriptCompiler::kConsumeParserCache) { |
3769 // If we have cached data, we use it to skip parsing the function body. The | 3770 // If we have cached data, we use it to skip parsing the function body. The |
3770 // data contains the information we need to construct the lazy function. | 3771 // data contains the information we need to construct the lazy function. |
3771 FunctionEntry entry = | 3772 FunctionEntry entry = |
3772 cached_parse_data_->GetFunctionEntry(function_block_pos); | 3773 cached_parse_data_->GetFunctionEntry(function_block_pos); |
3773 // Check that cached data is valid. | 3774 // Check that cached data is valid. |
3774 CHECK(entry.is_valid()); | 3775 CHECK(entry.is_valid()); |
3775 // End position greater than end of stream is safe, and hard to check. | 3776 // End position greater than end of stream is safe, and hard to check. |
3776 CHECK(entry.end_pos() > function_block_pos); | 3777 CHECK(entry.end_pos() > function_block_pos); |
3777 scanner()->SeekForward(entry.end_pos() - 1); | 3778 scanner()->SeekForward(entry.end_pos() - 1); |
3778 | 3779 |
(...skipping 27 matching lines...) Expand all Loading... |
3806 } | 3807 } |
3807 scope_->set_end_position(logger.end()); | 3808 scope_->set_end_position(logger.end()); |
3808 Expect(Token::RBRACE, ok); | 3809 Expect(Token::RBRACE, ok); |
3809 if (!*ok) { | 3810 if (!*ok) { |
3810 return; | 3811 return; |
3811 } | 3812 } |
3812 total_preparse_skipped_ += scope_->end_position() - function_block_pos; | 3813 total_preparse_skipped_ += scope_->end_position() - function_block_pos; |
3813 *materialized_literal_count = logger.literals(); | 3814 *materialized_literal_count = logger.literals(); |
3814 *expected_property_count = logger.properties(); | 3815 *expected_property_count = logger.properties(); |
3815 scope_->SetStrictMode(logger.strict_mode()); | 3816 scope_->SetStrictMode(logger.strict_mode()); |
3816 if (produce_cached_parse_data()) { | 3817 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
3817 DCHECK(log_); | 3818 DCHECK(log_); |
3818 // Position right after terminal '}'. | 3819 // Position right after terminal '}'. |
3819 int body_end = scanner()->location().end_pos; | 3820 int body_end = scanner()->location().end_pos; |
3820 log_->LogFunction(function_block_pos, body_end, | 3821 log_->LogFunction(function_block_pos, body_end, |
3821 *materialized_literal_count, | 3822 *materialized_literal_count, |
3822 *expected_property_count, | 3823 *expected_property_count, |
3823 scope_->strict_mode()); | 3824 scope_->strict_mode()); |
3824 } | 3825 } |
3825 } | 3826 } |
3826 } | 3827 } |
(...skipping 1155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4982 } | 4983 } |
4983 | 4984 |
4984 | 4985 |
4985 void Parser::ParseOnBackground() { | 4986 void Parser::ParseOnBackground() { |
4986 DCHECK(info()->function() == NULL); | 4987 DCHECK(info()->function() == NULL); |
4987 FunctionLiteral* result = NULL; | 4988 FunctionLiteral* result = NULL; |
4988 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); | 4989 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); |
4989 | 4990 |
4990 CompleteParserRecorder recorder; | 4991 CompleteParserRecorder recorder; |
4991 debug_saved_compile_options_ = compile_options(); | 4992 debug_saved_compile_options_ = compile_options(); |
4992 if (produce_cached_parse_data()) log_ = &recorder; | 4993 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
| 4994 log_ = &recorder; |
| 4995 } |
4993 | 4996 |
4994 DCHECK(info()->source_stream() != NULL); | 4997 DCHECK(info()->source_stream() != NULL); |
4995 ExternalStreamingStream stream(info()->source_stream(), | 4998 ExternalStreamingStream stream(info()->source_stream(), |
4996 info()->source_stream_encoding()); | 4999 info()->source_stream_encoding()); |
4997 scanner_.Initialize(&stream); | 5000 scanner_.Initialize(&stream); |
4998 DCHECK(info()->context().is_null() || info()->context()->IsNativeContext()); | 5001 DCHECK(info()->context().is_null() || info()->context()->IsNativeContext()); |
4999 | 5002 |
5000 // When streaming, we don't know the length of the source until we have parsed | 5003 // When streaming, we don't know the length of the source until we have parsed |
5001 // it. The raw data can be UTF-8, so we wouldn't know the source length until | 5004 // it. The raw data can be UTF-8, so we wouldn't know the source length until |
5002 // we have decoded it anyway even if we knew the raw data length (which we | 5005 // we have decoded it anyway even if we knew the raw data length (which we |
5003 // don't). We work around this by storing all the scopes which need their end | 5006 // don't). We work around this by storing all the scopes which need their end |
5004 // position set at the end of the script (the top scope and possible eval | 5007 // position set at the end of the script (the top scope and possible eval |
5005 // scopes) and set their end position after we know the script length. | 5008 // scopes) and set their end position after we know the script length. |
5006 Scope* top_scope = NULL; | 5009 Scope* top_scope = NULL; |
5007 Scope* eval_scope = NULL; | 5010 Scope* eval_scope = NULL; |
5008 result = DoParseProgram(info(), &top_scope, &eval_scope); | 5011 result = DoParseProgram(info(), &top_scope, &eval_scope); |
5009 | 5012 |
5010 top_scope->set_end_position(scanner()->location().end_pos); | 5013 top_scope->set_end_position(scanner()->location().end_pos); |
5011 if (eval_scope != NULL) { | 5014 if (eval_scope != NULL) { |
5012 eval_scope->set_end_position(scanner()->location().end_pos); | 5015 eval_scope->set_end_position(scanner()->location().end_pos); |
5013 } | 5016 } |
5014 | 5017 |
5015 info()->SetFunction(result); | 5018 info()->SetFunction(result); |
5016 | 5019 |
5017 // We cannot internalize on a background thread; a foreground task will take | 5020 // We cannot internalize on a background thread; a foreground task will take |
5018 // care of calling Parser::Internalize just before compilation. | 5021 // care of calling Parser::Internalize just before compilation. |
5019 | 5022 |
5020 if (produce_cached_parse_data()) { | 5023 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
5021 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); | 5024 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); |
5022 log_ = NULL; | 5025 log_ = NULL; |
5023 } | 5026 } |
5024 } | 5027 } |
5025 } } // namespace v8::internal | 5028 } } // namespace v8::internal |
OLD | NEW |