OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 | 860 |
861 private: | 861 private: |
862 bool is_pre_parsing_; | 862 bool is_pre_parsing_; |
863 }; | 863 }; |
864 | 864 |
865 | 865 |
866 class ParserLog BASE_EMBEDDED { | 866 class ParserLog BASE_EMBEDDED { |
867 public: | 867 public: |
868 virtual ~ParserLog() { } | 868 virtual ~ParserLog() { } |
869 | 869 |
870 // Records the occurrence of a function. The returned object is | 870 // Records the occurrence of a function. |
871 // only guaranteed to be valid until the next function has been | |
872 // logged. | |
873 virtual FunctionEntry LogFunction(int start) { return FunctionEntry(); } | 871 virtual FunctionEntry LogFunction(int start) { return FunctionEntry(); } |
874 | 872 // Return the current position in the function entry log. |
| 873 virtual int position() { return 0; } |
875 virtual void LogError() { } | 874 virtual void LogError() { } |
876 }; | 875 }; |
877 | 876 |
878 | 877 |
879 class AstBuildingParserFactory : public ParserFactory { | 878 class AstBuildingParserFactory : public ParserFactory { |
880 public: | 879 public: |
881 AstBuildingParserFactory() : ParserFactory(false) { } | 880 AstBuildingParserFactory() : ParserFactory(false) { } |
882 | 881 |
883 virtual Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with); | 882 virtual Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with); |
884 | 883 |
(...skipping 21 matching lines...) Expand all Loading... |
906 | 905 |
907 class ParserRecorder: public ParserLog { | 906 class ParserRecorder: public ParserLog { |
908 public: | 907 public: |
909 ParserRecorder(); | 908 ParserRecorder(); |
910 virtual FunctionEntry LogFunction(int start); | 909 virtual FunctionEntry LogFunction(int start); |
911 virtual void LogError() { } | 910 virtual void LogError() { } |
912 virtual void LogMessage(Scanner::Location loc, | 911 virtual void LogMessage(Scanner::Location loc, |
913 const char* message, | 912 const char* message, |
914 Vector<const char*> args); | 913 Vector<const char*> args); |
915 Vector<unsigned> ExtractData() { | 914 Vector<unsigned> ExtractData() { |
916 return store_.ToVector(); | 915 int total_size = ScriptDataImpl::kHeaderSize + store_.size(); |
| 916 Vector<unsigned> data = Vector<unsigned>::New(total_size); |
| 917 memcpy(data.start(), preamble_, sizeof(preamble_)); |
| 918 if (ScriptDataImpl::kHeaderSize < total_size) { |
| 919 store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize, total_size)); |
| 920 } |
| 921 return data; |
917 } | 922 } |
| 923 virtual int position() { return store_.size(); } |
918 private: | 924 private: |
919 bool has_error_; | |
920 Collector<unsigned> store_; | 925 Collector<unsigned> store_; |
921 Vector<unsigned> preamble_; | 926 unsigned preamble_[ScriptDataImpl::kHeaderSize]; |
| 927 #ifdef DEBUG |
| 928 int prev_start; |
| 929 #endif |
922 | 930 |
923 Collector<unsigned>* store() { return &store_; } | 931 bool has_error() { |
| 932 return static_cast<bool>(preamble_[ScriptDataImpl::kHasErrorOffset]); |
| 933 } |
924 void WriteString(Vector<const char> str); | 934 void WriteString(Vector<const char> str); |
925 }; | 935 }; |
926 | 936 |
927 | 937 |
928 FunctionEntry ScriptDataImpl::GetFunctionEnd(int start) { | 938 void ScriptDataImpl::SkipFunctionEntry(int start) { |
929 if (nth(last_entry_).start_pos() > start) { | 939 ASSERT(index_ + FunctionEntry::kSize <= store_.length()); |
930 // If the last entry we looked up is higher than what we're | 940 ASSERT(static_cast<int>(store_[index_]) == start); |
931 // looking for then it's useless and we reset it. | 941 index_ += FunctionEntry::kSize; |
932 last_entry_ = 0; | 942 } |
933 } | 943 |
934 for (int i = last_entry_; i < EntryCount(); i++) { | 944 |
935 FunctionEntry entry = nth(i); | 945 FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) { |
936 if (entry.start_pos() == start) { | 946 // The current pre-data entry must be a FunctionEntry with the given |
937 last_entry_ = i; | 947 // start position. |
938 return entry; | 948 if ((index_ + FunctionEntry::kSize <= store_.length()) |
939 } | 949 && (static_cast<int>(store_[index_]) == start)) { |
| 950 int index = index_; |
| 951 index_ += FunctionEntry::kSize; |
| 952 return FunctionEntry(store_.SubVector(index, |
| 953 index + FunctionEntry::kSize)); |
940 } | 954 } |
941 return FunctionEntry(); | 955 return FunctionEntry(); |
942 } | 956 } |
943 | 957 |
944 | 958 |
945 bool ScriptDataImpl::SanityCheck() { | 959 bool ScriptDataImpl::SanityCheck() { |
946 if (store_.length() < static_cast<int>(ScriptDataImpl::kHeaderSize)) { | 960 if (store_.length() < static_cast<int>(ScriptDataImpl::kHeaderSize)) { |
947 return false; | 961 return false; |
948 } | 962 } |
949 if (magic() != ScriptDataImpl::kMagicNumber) return false; | 963 if (magic() != ScriptDataImpl::kMagicNumber) return false; |
950 if (version() != ScriptDataImpl::kCurrentVersion) return false; | 964 if (version() != ScriptDataImpl::kCurrentVersion) return false; |
951 return true; | 965 return true; |
952 } | 966 } |
953 | 967 |
954 | 968 |
955 int ScriptDataImpl::EntryCount() { | |
956 return (store_.length() - kHeaderSize) / FunctionEntry::kSize; | |
957 } | |
958 | |
959 | |
960 FunctionEntry ScriptDataImpl::nth(int n) { | |
961 int offset = kHeaderSize + n * FunctionEntry::kSize; | |
962 return FunctionEntry(Vector<unsigned>(store_.start() + offset, | |
963 FunctionEntry::kSize)); | |
964 } | |
965 | |
966 | |
967 ParserRecorder::ParserRecorder() | 969 ParserRecorder::ParserRecorder() |
968 : has_error_(false), store_(ScriptDataImpl::kHeaderSize) { | 970 : store_(0) { |
969 preamble_ = store()->AddBlock(ScriptDataImpl::kHeaderSize, 0); | 971 #ifdef DEBUG |
| 972 prev_start = -1; |
| 973 #endif |
970 preamble_[ScriptDataImpl::kMagicOffset] = ScriptDataImpl::kMagicNumber; | 974 preamble_[ScriptDataImpl::kMagicOffset] = ScriptDataImpl::kMagicNumber; |
971 preamble_[ScriptDataImpl::kVersionOffset] = ScriptDataImpl::kCurrentVersion; | 975 preamble_[ScriptDataImpl::kVersionOffset] = ScriptDataImpl::kCurrentVersion; |
972 preamble_[ScriptDataImpl::kHasErrorOffset] = false; | 976 preamble_[ScriptDataImpl::kHasErrorOffset] = false; |
| 977 preamble_[ScriptDataImpl::kSizeOffset] = 0; |
| 978 ASSERT_EQ(4, ScriptDataImpl::kHeaderSize); |
973 } | 979 } |
974 | 980 |
975 | 981 |
976 void ParserRecorder::WriteString(Vector<const char> str) { | 982 void ParserRecorder::WriteString(Vector<const char> str) { |
977 store()->Add(str.length()); | 983 store_.Add(str.length()); |
978 for (int i = 0; i < str.length(); i++) { | 984 for (int i = 0; i < str.length(); i++) { |
979 store()->Add(str[i]); | 985 store_.Add(str[i]); |
980 } | 986 } |
981 } | 987 } |
982 | 988 |
983 | 989 |
984 const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) { | 990 const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) { |
985 int length = start[0]; | 991 int length = start[0]; |
986 char* result = NewArray<char>(length + 1); | 992 char* result = NewArray<char>(length + 1); |
987 for (int i = 0; i < length; i++) { | 993 for (int i = 0; i < length; i++) { |
988 result[i] = start[i + 1]; | 994 result[i] = start[i + 1]; |
989 } | 995 } |
990 result[length] = '\0'; | 996 result[length] = '\0'; |
991 if (chars != NULL) *chars = length; | 997 if (chars != NULL) *chars = length; |
992 return result; | 998 return result; |
993 } | 999 } |
994 | 1000 |
995 | 1001 |
996 void ParserRecorder::LogMessage(Scanner::Location loc, const char* message, | 1002 void ParserRecorder::LogMessage(Scanner::Location loc, const char* message, |
997 Vector<const char*> args) { | 1003 Vector<const char*> args) { |
998 if (has_error_) return; | 1004 if (has_error()) return; |
999 store()->Reset(); | |
1000 preamble_ = store()->AddBlock(ScriptDataImpl::kHeaderSize, 0); | |
1001 preamble_[ScriptDataImpl::kMagicOffset] = ScriptDataImpl::kMagicNumber; | |
1002 preamble_[ScriptDataImpl::kVersionOffset] = ScriptDataImpl::kCurrentVersion; | |
1003 preamble_[ScriptDataImpl::kHasErrorOffset] = true; | 1005 preamble_[ScriptDataImpl::kHasErrorOffset] = true; |
1004 store()->Add(loc.beg_pos); | 1006 store_.Reset(); |
1005 store()->Add(loc.end_pos); | 1007 store_.Add(loc.beg_pos); |
1006 store()->Add(args.length()); | 1008 store_.Add(loc.end_pos); |
| 1009 store_.Add(args.length()); |
1007 WriteString(CStrVector(message)); | 1010 WriteString(CStrVector(message)); |
1008 for (int i = 0; i < args.length(); i++) { | 1011 for (int i = 0; i < args.length(); i++) { |
1009 WriteString(CStrVector(args[i])); | 1012 WriteString(CStrVector(args[i])); |
1010 } | 1013 } |
1011 } | 1014 } |
1012 | 1015 |
1013 | 1016 |
1014 Scanner::Location ScriptDataImpl::MessageLocation() { | 1017 Scanner::Location ScriptDataImpl::MessageLocation() { |
1015 int beg_pos = Read(0); | 1018 int beg_pos = Read(0); |
1016 int end_pos = Read(1); | 1019 int end_pos = Read(1); |
(...skipping 22 matching lines...) Expand all Loading... |
1039 | 1042 |
1040 unsigned ScriptDataImpl::Read(int position) { | 1043 unsigned ScriptDataImpl::Read(int position) { |
1041 return store_[ScriptDataImpl::kHeaderSize + position]; | 1044 return store_[ScriptDataImpl::kHeaderSize + position]; |
1042 } | 1045 } |
1043 | 1046 |
1044 | 1047 |
1045 unsigned* ScriptDataImpl::ReadAddress(int position) { | 1048 unsigned* ScriptDataImpl::ReadAddress(int position) { |
1046 return &store_[ScriptDataImpl::kHeaderSize + position]; | 1049 return &store_[ScriptDataImpl::kHeaderSize + position]; |
1047 } | 1050 } |
1048 | 1051 |
| 1052 void ScriptDataImpl::FindStart(int position) { |
| 1053 // Only search forwards, and linearly for now. |
| 1054 while ((index_ < store_.length()) |
| 1055 && (static_cast<int>(store_[index_])) < position) { |
| 1056 index_ += FunctionEntry::kSize; |
| 1057 } |
| 1058 } |
| 1059 |
1049 | 1060 |
1050 FunctionEntry ParserRecorder::LogFunction(int start) { | 1061 FunctionEntry ParserRecorder::LogFunction(int start) { |
1051 if (has_error_) return FunctionEntry(); | 1062 #ifdef DEBUG |
1052 FunctionEntry result(store()->AddBlock(FunctionEntry::kSize, 0)); | 1063 ASSERT(start > prev_start); |
| 1064 prev_start = start; |
| 1065 #endif |
| 1066 if (has_error()) return FunctionEntry(); |
| 1067 FunctionEntry result(store_.AddBlock(FunctionEntry::kSize, 0)); |
1053 result.set_start_pos(start); | 1068 result.set_start_pos(start); |
1054 return result; | 1069 return result; |
1055 } | 1070 } |
1056 | 1071 |
1057 | 1072 |
1058 class AstBuildingParser : public Parser { | 1073 class AstBuildingParser : public Parser { |
1059 public: | 1074 public: |
1060 AstBuildingParser(Handle<Script> script, bool allow_natives_syntax, | 1075 AstBuildingParser(Handle<Script> script, bool allow_natives_syntax, |
1061 v8::Extension* extension, ScriptDataImpl* pre_data) | 1076 v8::Extension* extension, ScriptDataImpl* pre_data) |
1062 : Parser(script, allow_natives_syntax, extension, PARSE, | 1077 : Parser(script, allow_natives_syntax, extension, PARSE, |
(...skipping 2869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3932 new Assignment(Token::INIT_CONST, fproxy, | 3947 new Assignment(Token::INIT_CONST, fproxy, |
3933 NEW(ThisFunction()), | 3948 NEW(ThisFunction()), |
3934 RelocInfo::kNoPosition))); | 3949 RelocInfo::kNoPosition))); |
3935 } | 3950 } |
3936 | 3951 |
3937 // Determine if the function will be lazily compiled. The mode can | 3952 // Determine if the function will be lazily compiled. The mode can |
3938 // only be PARSE_LAZILY if the --lazy flag is true. | 3953 // only be PARSE_LAZILY if the --lazy flag is true. |
3939 bool is_lazily_compiled = | 3954 bool is_lazily_compiled = |
3940 mode() == PARSE_LAZILY && top_scope_->HasTrivialOuterContext(); | 3955 mode() == PARSE_LAZILY && top_scope_->HasTrivialOuterContext(); |
3941 | 3956 |
| 3957 int function_block_pos = scanner_.location().beg_pos; |
3942 int materialized_literal_count; | 3958 int materialized_literal_count; |
3943 int expected_property_count; | 3959 int expected_property_count; |
| 3960 int end_pos; |
3944 bool only_simple_this_property_assignments; | 3961 bool only_simple_this_property_assignments; |
3945 Handle<FixedArray> this_property_assignments; | 3962 Handle<FixedArray> this_property_assignments; |
3946 if (is_lazily_compiled && pre_data() != NULL) { | 3963 if (is_lazily_compiled && pre_data() != NULL) { |
3947 FunctionEntry entry = pre_data()->GetFunctionEnd(start_pos); | 3964 FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos); |
3948 if (!entry.is_valid()) { | 3965 if (!entry.is_valid()) { |
3949 ReportInvalidPreparseData(name, CHECK_OK); | 3966 ReportInvalidPreparseData(name, CHECK_OK); |
3950 } | 3967 } |
3951 int end_pos = entry.end_pos(); | 3968 end_pos = entry.end_pos(); |
3952 if (end_pos <= start_pos) { | 3969 if (end_pos <= function_block_pos) { |
3953 // End position greater than end of stream is safe, and hard to check. | 3970 // End position greater than end of stream is safe, and hard to check. |
3954 ReportInvalidPreparseData(name, CHECK_OK); | 3971 ReportInvalidPreparseData(name, CHECK_OK); |
3955 } | 3972 } |
3956 Counters::total_preparse_skipped.Increment(end_pos - start_pos); | 3973 Counters::total_preparse_skipped.Increment(end_pos - function_block_pos); |
3957 scanner_.SeekForward(end_pos); | 3974 scanner_.SeekForward(end_pos); |
| 3975 pre_data()->Skip(entry.predata_skip()); |
3958 materialized_literal_count = entry.literal_count(); | 3976 materialized_literal_count = entry.literal_count(); |
3959 expected_property_count = entry.property_count(); | 3977 expected_property_count = entry.property_count(); |
3960 only_simple_this_property_assignments = false; | 3978 only_simple_this_property_assignments = false; |
3961 this_property_assignments = Factory::empty_fixed_array(); | 3979 this_property_assignments = Factory::empty_fixed_array(); |
| 3980 Expect(Token::RBRACE, CHECK_OK); |
3962 } else { | 3981 } else { |
| 3982 if (pre_data() != NULL) { |
| 3983 // Skip pre-data entry for non-lazily compiled function. |
| 3984 pre_data()->SkipFunctionEntry(function_block_pos); |
| 3985 } |
| 3986 FunctionEntry entry = log()->LogFunction(function_block_pos); |
| 3987 int predata_position_before = log()->position(); |
3963 ParseSourceElements(&body, Token::RBRACE, CHECK_OK); | 3988 ParseSourceElements(&body, Token::RBRACE, CHECK_OK); |
3964 materialized_literal_count = temp_scope.materialized_literal_count(); | 3989 materialized_literal_count = temp_scope.materialized_literal_count(); |
3965 expected_property_count = temp_scope.expected_property_count(); | 3990 expected_property_count = temp_scope.expected_property_count(); |
3966 only_simple_this_property_assignments = | 3991 only_simple_this_property_assignments = |
3967 temp_scope.only_simple_this_property_assignments(); | 3992 temp_scope.only_simple_this_property_assignments(); |
3968 this_property_assignments = temp_scope.this_property_assignments(); | 3993 this_property_assignments = temp_scope.this_property_assignments(); |
3969 } | |
3970 | 3994 |
3971 Expect(Token::RBRACE, CHECK_OK); | 3995 Expect(Token::RBRACE, CHECK_OK); |
3972 int end_pos = scanner_.location().end_pos; | 3996 end_pos = scanner_.location().end_pos; |
3973 | 3997 if (entry.is_valid()) { |
3974 FunctionEntry entry = log()->LogFunction(start_pos); | 3998 entry.set_end_pos(end_pos); |
3975 if (entry.is_valid()) { | 3999 entry.set_literal_count(materialized_literal_count); |
3976 entry.set_end_pos(end_pos); | 4000 entry.set_property_count(expected_property_count); |
3977 entry.set_literal_count(materialized_literal_count); | 4001 entry.set_predata_skip(log()->position() - predata_position_before); |
3978 entry.set_property_count(expected_property_count); | 4002 } |
3979 } | 4003 } |
3980 | 4004 |
3981 FunctionLiteral* function_literal = | 4005 FunctionLiteral* function_literal = |
3982 NEW(FunctionLiteral(name, | 4006 NEW(FunctionLiteral(name, |
3983 top_scope_, | 4007 top_scope_, |
3984 body.elements(), | 4008 body.elements(), |
3985 materialized_literal_count, | 4009 materialized_literal_count, |
3986 expected_property_count, | 4010 expected_property_count, |
3987 only_simple_this_property_assignments, | 4011 only_simple_this_property_assignments, |
3988 this_property_assignments, | 4012 this_property_assignments, |
(...skipping 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5330 parser.ParseLazy(script_source, name, | 5354 parser.ParseLazy(script_source, name, |
5331 start_position, end_position, is_expression); | 5355 start_position, end_position, is_expression); |
5332 return result; | 5356 return result; |
5333 } | 5357 } |
5334 | 5358 |
5335 | 5359 |
5336 #undef NEW | 5360 #undef NEW |
5337 | 5361 |
5338 | 5362 |
5339 } } // namespace v8::internal | 5363 } } // namespace v8::internal |
OLD | NEW |