| 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 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 base::ElapsedTimer timer; | 834 base::ElapsedTimer timer; |
| 836 if (FLAG_trace_parse) { | 835 if (FLAG_trace_parse) { |
| 837 timer.Start(); | 836 timer.Start(); |
| 838 } | 837 } |
| 839 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); | 838 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); |
| 840 | 839 |
| 841 // Initialize parser state. | 840 // Initialize parser state. |
| 842 CompleteParserRecorder recorder; | 841 CompleteParserRecorder recorder; |
| 843 | 842 |
| 844 debug_saved_compile_options_ = compile_options(); | 843 debug_saved_compile_options_ = compile_options(); |
| 845 if (produce_cached_parse_data()) { | 844 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
| 846 log_ = &recorder; | 845 log_ = &recorder; |
| 847 } else if (consume_cached_parse_data()) { | 846 } else if (compile_options() == ScriptCompiler::kConsumeParserCache) { |
| 848 cached_parse_data_->Initialize(); | 847 cached_parse_data_->Initialize(); |
| 849 } | 848 } |
| 850 | 849 |
| 851 source = String::Flatten(source); | 850 source = String::Flatten(source); |
| 852 FunctionLiteral* result; | 851 FunctionLiteral* result; |
| 853 | 852 |
| 854 Scope* top_scope = NULL; | 853 Scope* top_scope = NULL; |
| 855 Scope* eval_scope = NULL; | 854 Scope* eval_scope = NULL; |
| 856 if (source->IsExternalTwoByteString()) { | 855 if (source->IsExternalTwoByteString()) { |
| 857 // Notice that the stream is destroyed at the end of the branch block. | 856 // Notice that the stream is destroyed at the end of the branch block. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 878 PrintF("[parsing eval"); | 877 PrintF("[parsing eval"); |
| 879 } else if (info()->script()->name()->IsString()) { | 878 } else if (info()->script()->name()->IsString()) { |
| 880 String* name = String::cast(info()->script()->name()); | 879 String* name = String::cast(info()->script()->name()); |
| 881 SmartArrayPointer<char> name_chars = name->ToCString(); | 880 SmartArrayPointer<char> name_chars = name->ToCString(); |
| 882 PrintF("[parsing script: %s", name_chars.get()); | 881 PrintF("[parsing script: %s", name_chars.get()); |
| 883 } else { | 882 } else { |
| 884 PrintF("[parsing script"); | 883 PrintF("[parsing script"); |
| 885 } | 884 } |
| 886 PrintF(" - took %0.3f ms]\n", ms); | 885 PrintF(" - took %0.3f ms]\n", ms); |
| 887 } | 886 } |
| 888 if (produce_cached_parse_data()) { | 887 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
| 889 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); | 888 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); |
| 890 log_ = NULL; | 889 log_ = NULL; |
| 891 } | 890 } |
| 892 return result; | 891 return result; |
| 893 } | 892 } |
| 894 | 893 |
| 895 | 894 |
| 896 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope, | 895 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope, |
| 897 Scope** eval_scope) { | 896 Scope** eval_scope) { |
| 898 DCHECK(scope_ == NULL); | 897 DCHECK(scope_ == NULL); |
| (...skipping 2848 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3747 int* materialized_literal_count, | 3746 int* materialized_literal_count, |
| 3748 int* expected_property_count, | 3747 int* expected_property_count, |
| 3749 bool* ok) { | 3748 bool* ok) { |
| 3750 // Temporary debugging code for tracking down a mystery crash which should | 3749 // Temporary debugging code for tracking down a mystery crash which should |
| 3751 // never happen. The crash happens on the line where we log the function in | 3750 // never happen. The crash happens on the line where we log the function in |
| 3752 // the preparse data: log_->LogFunction(...). TODO(marja): remove this once | 3751 // the preparse data: log_->LogFunction(...). TODO(marja): remove this once |
| 3753 // done. | 3752 // done. |
| 3754 CHECK(materialized_literal_count); | 3753 CHECK(materialized_literal_count); |
| 3755 CHECK(expected_property_count); | 3754 CHECK(expected_property_count); |
| 3756 CHECK(debug_saved_compile_options_ == compile_options()); | 3755 CHECK(debug_saved_compile_options_ == compile_options()); |
| 3757 if (produce_cached_parse_data()) CHECK(log_); | 3756 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
| 3757 CHECK(log_); |
| 3758 } |
| 3758 | 3759 |
| 3759 int function_block_pos = position(); | 3760 int function_block_pos = position(); |
| 3760 if (consume_cached_parse_data()) { | 3761 if (compile_options() == ScriptCompiler::kConsumeParserCache) { |
| 3761 // If we have cached data, we use it to skip parsing the function body. The | 3762 // If we have cached data, we use it to skip parsing the function body. The |
| 3762 // data contains the information we need to construct the lazy function. | 3763 // data contains the information we need to construct the lazy function. |
| 3763 FunctionEntry entry = | 3764 FunctionEntry entry = |
| 3764 cached_parse_data_->GetFunctionEntry(function_block_pos); | 3765 cached_parse_data_->GetFunctionEntry(function_block_pos); |
| 3765 // Check that cached data is valid. | 3766 // Check that cached data is valid. |
| 3766 CHECK(entry.is_valid()); | 3767 CHECK(entry.is_valid()); |
| 3767 // End position greater than end of stream is safe, and hard to check. | 3768 // End position greater than end of stream is safe, and hard to check. |
| 3768 CHECK(entry.end_pos() > function_block_pos); | 3769 CHECK(entry.end_pos() > function_block_pos); |
| 3769 scanner()->SeekForward(entry.end_pos() - 1); | 3770 scanner()->SeekForward(entry.end_pos() - 1); |
| 3770 | 3771 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3798 } | 3799 } |
| 3799 scope_->set_end_position(logger.end()); | 3800 scope_->set_end_position(logger.end()); |
| 3800 Expect(Token::RBRACE, ok); | 3801 Expect(Token::RBRACE, ok); |
| 3801 if (!*ok) { | 3802 if (!*ok) { |
| 3802 return; | 3803 return; |
| 3803 } | 3804 } |
| 3804 total_preparse_skipped_ += scope_->end_position() - function_block_pos; | 3805 total_preparse_skipped_ += scope_->end_position() - function_block_pos; |
| 3805 *materialized_literal_count = logger.literals(); | 3806 *materialized_literal_count = logger.literals(); |
| 3806 *expected_property_count = logger.properties(); | 3807 *expected_property_count = logger.properties(); |
| 3807 scope_->SetStrictMode(logger.strict_mode()); | 3808 scope_->SetStrictMode(logger.strict_mode()); |
| 3808 if (produce_cached_parse_data()) { | 3809 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
| 3809 DCHECK(log_); | 3810 DCHECK(log_); |
| 3810 // Position right after terminal '}'. | 3811 // Position right after terminal '}'. |
| 3811 int body_end = scanner()->location().end_pos; | 3812 int body_end = scanner()->location().end_pos; |
| 3812 log_->LogFunction(function_block_pos, body_end, | 3813 log_->LogFunction(function_block_pos, body_end, |
| 3813 *materialized_literal_count, | 3814 *materialized_literal_count, |
| 3814 *expected_property_count, | 3815 *expected_property_count, |
| 3815 scope_->strict_mode()); | 3816 scope_->strict_mode()); |
| 3816 } | 3817 } |
| 3817 } | 3818 } |
| 3818 } | 3819 } |
| (...skipping 1155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4974 } | 4975 } |
| 4975 | 4976 |
| 4976 | 4977 |
| 4977 void Parser::ParseOnBackground() { | 4978 void Parser::ParseOnBackground() { |
| 4978 DCHECK(info()->function() == NULL); | 4979 DCHECK(info()->function() == NULL); |
| 4979 FunctionLiteral* result = NULL; | 4980 FunctionLiteral* result = NULL; |
| 4980 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); | 4981 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); |
| 4981 | 4982 |
| 4982 CompleteParserRecorder recorder; | 4983 CompleteParserRecorder recorder; |
| 4983 debug_saved_compile_options_ = compile_options(); | 4984 debug_saved_compile_options_ = compile_options(); |
| 4984 if (produce_cached_parse_data()) log_ = &recorder; | 4985 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
| 4986 log_ = &recorder; |
| 4987 } |
| 4985 | 4988 |
| 4986 DCHECK(info()->source_stream() != NULL); | 4989 DCHECK(info()->source_stream() != NULL); |
| 4987 ExternalStreamingStream stream(info()->source_stream(), | 4990 ExternalStreamingStream stream(info()->source_stream(), |
| 4988 info()->source_stream_encoding()); | 4991 info()->source_stream_encoding()); |
| 4989 scanner_.Initialize(&stream); | 4992 scanner_.Initialize(&stream); |
| 4990 DCHECK(info()->context().is_null() || info()->context()->IsNativeContext()); | 4993 DCHECK(info()->context().is_null() || info()->context()->IsNativeContext()); |
| 4991 | 4994 |
| 4992 // When streaming, we don't know the length of the source until we have parsed | 4995 // When streaming, we don't know the length of the source until we have parsed |
| 4993 // it. The raw data can be UTF-8, so we wouldn't know the source length until | 4996 // it. The raw data can be UTF-8, so we wouldn't know the source length until |
| 4994 // we have decoded it anyway even if we knew the raw data length (which we | 4997 // we have decoded it anyway even if we knew the raw data length (which we |
| 4995 // don't). We work around this by storing all the scopes which need their end | 4998 // don't). We work around this by storing all the scopes which need their end |
| 4996 // position set at the end of the script (the top scope and possible eval | 4999 // position set at the end of the script (the top scope and possible eval |
| 4997 // scopes) and set their end position after we know the script length. | 5000 // scopes) and set their end position after we know the script length. |
| 4998 Scope* top_scope = NULL; | 5001 Scope* top_scope = NULL; |
| 4999 Scope* eval_scope = NULL; | 5002 Scope* eval_scope = NULL; |
| 5000 result = DoParseProgram(info(), &top_scope, &eval_scope); | 5003 result = DoParseProgram(info(), &top_scope, &eval_scope); |
| 5001 | 5004 |
| 5002 top_scope->set_end_position(scanner()->location().end_pos); | 5005 top_scope->set_end_position(scanner()->location().end_pos); |
| 5003 if (eval_scope != NULL) { | 5006 if (eval_scope != NULL) { |
| 5004 eval_scope->set_end_position(scanner()->location().end_pos); | 5007 eval_scope->set_end_position(scanner()->location().end_pos); |
| 5005 } | 5008 } |
| 5006 | 5009 |
| 5007 info()->SetFunction(result); | 5010 info()->SetFunction(result); |
| 5008 | 5011 |
| 5009 // We cannot internalize on a background thread; a foreground task will take | 5012 // We cannot internalize on a background thread; a foreground task will take |
| 5010 // care of calling Parser::Internalize just before compilation. | 5013 // care of calling Parser::Internalize just before compilation. |
| 5011 | 5014 |
| 5012 if (produce_cached_parse_data()) { | 5015 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
| 5013 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); | 5016 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); |
| 5014 log_ = NULL; | 5017 log_ = NULL; |
| 5015 } | 5018 } |
| 5016 } | 5019 } |
| 5017 } } // namespace v8::internal | 5020 } } // namespace v8::internal |
| OLD | NEW |