OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 939 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 | 950 |
951 const bool enabled_; | 951 const bool enabled_; |
952 Assignment* first_in_block_; | 952 Assignment* first_in_block_; |
953 Assignment* last_in_block_; | 953 Assignment* last_in_block_; |
954 int block_size_; | 954 int block_size_; |
955 | 955 |
956 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder); | 956 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder); |
957 }; | 957 }; |
958 | 958 |
959 | 959 |
960 // A ThisNamedPropertyAssigmentFinder finds and marks statements of the form | 960 // A ThisNamedPropertyAssignmentFinder finds and marks statements of the form |
961 // this.x = ...;, where x is a named property. It also determines whether a | 961 // this.x = ...;, where x is a named property. It also determines whether a |
962 // function contains only assignments of this type. | 962 // function contains only assignments of this type. |
963 class ThisNamedPropertyAssigmentFinder : public ParserFinder { | 963 class ThisNamedPropertyAssignmentFinder : public ParserFinder { |
964 public: | 964 public: |
965 explicit ThisNamedPropertyAssigmentFinder(Isolate* isolate) | 965 explicit ThisNamedPropertyAssignmentFinder(Isolate* isolate) |
966 : isolate_(isolate), | 966 : isolate_(isolate), |
967 only_simple_this_property_assignments_(true), | 967 only_simple_this_property_assignments_(true), |
968 names_(NULL), | 968 names_(0), |
969 assigned_arguments_(NULL), | 969 assigned_arguments_(0), |
970 assigned_constants_(NULL) {} | 970 assigned_constants_(0) { |
| 971 } |
971 | 972 |
972 void Update(Scope* scope, Statement* stat) { | 973 void Update(Scope* scope, Statement* stat) { |
973 // Bail out if function already has property assignment that are | 974 // Bail out if function already has property assignment that are |
974 // not simple this property assignments. | 975 // not simple this property assignments. |
975 if (!only_simple_this_property_assignments_) { | 976 if (!only_simple_this_property_assignments_) { |
976 return; | 977 return; |
977 } | 978 } |
978 | 979 |
979 // Check whether this statement is of the form this.x = ...; | 980 // Check whether this statement is of the form this.x = ...; |
980 Assignment* assignment = AsAssignment(stat); | 981 Assignment* assignment = AsAssignment(stat); |
981 if (IsThisPropertyAssignment(assignment)) { | 982 if (IsThisPropertyAssignment(assignment)) { |
982 HandleThisPropertyAssignment(scope, assignment); | 983 HandleThisPropertyAssignment(scope, assignment); |
983 } else { | 984 } else { |
984 only_simple_this_property_assignments_ = false; | 985 only_simple_this_property_assignments_ = false; |
985 } | 986 } |
986 } | 987 } |
987 | 988 |
988 // Returns whether only statements of the form this.x = y; where y is either a | 989 // Returns whether only statements of the form this.x = y; where y is either a |
989 // constant or a function argument was encountered. | 990 // constant or a function argument was encountered. |
990 bool only_simple_this_property_assignments() { | 991 bool only_simple_this_property_assignments() { |
991 return only_simple_this_property_assignments_; | 992 return only_simple_this_property_assignments_; |
992 } | 993 } |
993 | 994 |
994 // Returns a fixed array containing three elements for each assignment of the | 995 // Returns a fixed array containing three elements for each assignment of the |
995 // form this.x = y; | 996 // form this.x = y; |
996 Handle<FixedArray> GetThisPropertyAssignments() { | 997 Handle<FixedArray> GetThisPropertyAssignments() { |
997 if (names_ == NULL) { | 998 if (names_.is_empty()) { |
998 return isolate_->factory()->empty_fixed_array(); | 999 return isolate_->factory()->empty_fixed_array(); |
999 } | 1000 } |
1000 ASSERT(names_ != NULL); | 1001 ASSERT_EQ(names_.length(), assigned_arguments_.length()); |
1001 ASSERT(assigned_arguments_ != NULL); | 1002 ASSERT_EQ(names_.length(), assigned_constants_.length()); |
1002 ASSERT_EQ(names_->length(), assigned_arguments_->length()); | |
1003 ASSERT_EQ(names_->length(), assigned_constants_->length()); | |
1004 Handle<FixedArray> assignments = | 1003 Handle<FixedArray> assignments = |
1005 isolate_->factory()->NewFixedArray(names_->length() * 3); | 1004 isolate_->factory()->NewFixedArray(names_.length() * 3); |
1006 for (int i = 0; i < names_->length(); i++) { | 1005 for (int i = 0; i < names_.length(); ++i) { |
1007 assignments->set(i * 3, *names_->at(i)); | 1006 assignments->set(i * 3, *names_[i]); |
1008 assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_->at(i))); | 1007 assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_[i])); |
1009 assignments->set(i * 3 + 2, *assigned_constants_->at(i)); | 1008 assignments->set(i * 3 + 2, *assigned_constants_[i]); |
1010 } | 1009 } |
1011 return assignments; | 1010 return assignments; |
1012 } | 1011 } |
1013 | 1012 |
1014 private: | 1013 private: |
1015 bool IsThisPropertyAssignment(Assignment* assignment) { | 1014 bool IsThisPropertyAssignment(Assignment* assignment) { |
1016 if (assignment != NULL) { | 1015 if (assignment != NULL) { |
1017 Property* property = assignment->target()->AsProperty(); | 1016 Property* property = assignment->target()->AsProperty(); |
1018 return assignment->op() == Token::ASSIGN | 1017 return assignment->op() == Token::ASSIGN |
1019 && property != NULL | 1018 && property != NULL |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1056 return; | 1055 return; |
1057 } | 1056 } |
1058 } | 1057 } |
1059 } | 1058 } |
1060 } | 1059 } |
1061 // It is not a simple "this.x = value;" assignment with a constant | 1060 // It is not a simple "this.x = value;" assignment with a constant |
1062 // or parameter value. | 1061 // or parameter value. |
1063 AssignmentFromSomethingElse(); | 1062 AssignmentFromSomethingElse(); |
1064 } | 1063 } |
1065 | 1064 |
| 1065 |
| 1066 |
| 1067 |
| 1068 // We will potentially reorder the property assignments, so they must be |
| 1069 // simple enough that the ordering does not matter. |
1066 void AssignmentFromParameter(Handle<String> name, int index) { | 1070 void AssignmentFromParameter(Handle<String> name, int index) { |
1067 EnsureAllocation(); | 1071 EnsureInitialized(); |
1068 names_->Add(name); | 1072 for (int i = 0; i < names_.length(); ++i) { |
1069 assigned_arguments_->Add(index); | 1073 if (name->Equals(*names_[i])) { |
1070 assigned_constants_->Add(isolate_->factory()->undefined_value()); | 1074 assigned_arguments_[i] = index; |
| 1075 assigned_constants_[i] = isolate_->factory()->undefined_value(); |
| 1076 return; |
| 1077 } |
| 1078 } |
| 1079 names_.Add(name); |
| 1080 assigned_arguments_.Add(index); |
| 1081 assigned_constants_.Add(isolate_->factory()->undefined_value()); |
1071 } | 1082 } |
1072 | 1083 |
1073 void AssignmentFromConstant(Handle<String> name, Handle<Object> value) { | 1084 void AssignmentFromConstant(Handle<String> name, Handle<Object> value) { |
1074 EnsureAllocation(); | 1085 EnsureInitialized(); |
1075 names_->Add(name); | 1086 for (int i = 0; i < names_.length(); ++i) { |
1076 assigned_arguments_->Add(-1); | 1087 if (name->Equals(*names_[i])) { |
1077 assigned_constants_->Add(value); | 1088 assigned_arguments_[i] = -1; |
| 1089 assigned_constants_[i] = value; |
| 1090 return; |
| 1091 } |
| 1092 } |
| 1093 names_.Add(name); |
| 1094 assigned_arguments_.Add(-1); |
| 1095 assigned_constants_.Add(value); |
1078 } | 1096 } |
1079 | 1097 |
1080 void AssignmentFromSomethingElse() { | 1098 void AssignmentFromSomethingElse() { |
1081 // The this assignment is not a simple one. | 1099 // The this assignment is not a simple one. |
1082 only_simple_this_property_assignments_ = false; | 1100 only_simple_this_property_assignments_ = false; |
1083 } | 1101 } |
1084 | 1102 |
1085 void EnsureAllocation() { | 1103 void EnsureInitialized() { |
1086 if (names_ == NULL) { | 1104 if (names_.capacity() == 0) { |
1087 ASSERT(assigned_arguments_ == NULL); | 1105 ASSERT(assigned_arguments_.capacity() == 0); |
1088 ASSERT(assigned_constants_ == NULL); | 1106 ASSERT(assigned_constants_.capacity() == 0); |
1089 Zone* zone = isolate_->zone(); | 1107 names_.Initialize(4); |
1090 names_ = new(zone) ZoneStringList(4); | 1108 assigned_arguments_.Initialize(4); |
1091 assigned_arguments_ = new(zone) ZoneList<int>(4); | 1109 assigned_constants_.Initialize(4); |
1092 assigned_constants_ = new(zone) ZoneObjectList(4); | |
1093 } | 1110 } |
1094 } | 1111 } |
1095 | 1112 |
1096 Isolate* isolate_; | 1113 Isolate* isolate_; |
1097 bool only_simple_this_property_assignments_; | 1114 bool only_simple_this_property_assignments_; |
1098 ZoneStringList* names_; | 1115 ZoneStringList names_; |
1099 ZoneList<int>* assigned_arguments_; | 1116 ZoneList<int> assigned_arguments_; |
1100 ZoneObjectList* assigned_constants_; | 1117 ZoneObjectList assigned_constants_; |
1101 }; | 1118 }; |
1102 | 1119 |
1103 | 1120 |
1104 Statement* Parser::ParseSourceElement(ZoneStringList* labels, | 1121 Statement* Parser::ParseSourceElement(ZoneStringList* labels, |
1105 bool* ok) { | 1122 bool* ok) { |
1106 // (Ecma 262 5th Edition, clause 14): | 1123 // (Ecma 262 5th Edition, clause 14): |
1107 // SourceElement: | 1124 // SourceElement: |
1108 // Statement | 1125 // Statement |
1109 // FunctionDeclaration | 1126 // FunctionDeclaration |
1110 // | 1127 // |
(...skipping 18 matching lines...) Expand all Loading... |
1129 // (SourceElement)* <end_token> | 1146 // (SourceElement)* <end_token> |
1130 | 1147 |
1131 // Allocate a target stack to use for this set of source | 1148 // Allocate a target stack to use for this set of source |
1132 // elements. This way, all scripts and functions get their own | 1149 // elements. This way, all scripts and functions get their own |
1133 // target stack thus avoiding illegal breaks and continues across | 1150 // target stack thus avoiding illegal breaks and continues across |
1134 // functions. | 1151 // functions. |
1135 TargetScope scope(&this->target_stack_); | 1152 TargetScope scope(&this->target_stack_); |
1136 | 1153 |
1137 ASSERT(processor != NULL); | 1154 ASSERT(processor != NULL); |
1138 InitializationBlockFinder block_finder(top_scope_, target_stack_); | 1155 InitializationBlockFinder block_finder(top_scope_, target_stack_); |
1139 ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate()); | 1156 ThisNamedPropertyAssignmentFinder this_property_assignment_finder(isolate()); |
1140 bool directive_prologue = true; // Parsing directive prologue. | 1157 bool directive_prologue = true; // Parsing directive prologue. |
1141 | 1158 |
1142 while (peek() != end_token) { | 1159 while (peek() != end_token) { |
1143 if (directive_prologue && peek() != Token::STRING) { | 1160 if (directive_prologue && peek() != Token::STRING) { |
1144 directive_prologue = false; | 1161 directive_prologue = false; |
1145 } | 1162 } |
1146 | 1163 |
1147 Scanner::Location token_loc = scanner().peek_location(); | 1164 Scanner::Location token_loc = scanner().peek_location(); |
1148 Statement* stat = ParseSourceElement(NULL, CHECK_OK); | 1165 Statement* stat = ParseSourceElement(NULL, CHECK_OK); |
1149 if (stat == NULL || stat->IsEmpty()) { | 1166 if (stat == NULL || stat->IsEmpty()) { |
(...skipping 4068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5218 result = parser.ParseProgram(source, | 5235 result = parser.ParseProgram(source, |
5219 info->is_global(), | 5236 info->is_global(), |
5220 info->StrictMode()); | 5237 info->StrictMode()); |
5221 } | 5238 } |
5222 } | 5239 } |
5223 info->SetFunction(result); | 5240 info->SetFunction(result); |
5224 return (result != NULL); | 5241 return (result != NULL); |
5225 } | 5242 } |
5226 | 5243 |
5227 } } // namespace v8::internal | 5244 } } // namespace v8::internal |
OLD | NEW |