OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 946 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
957 Object* value, | 957 Object* value, |
958 PropertyAttributes attributes) { | 958 PropertyAttributes attributes) { |
959 // Normalize the object if the name is not a real identifier. | 959 // Normalize the object if the name is not a real identifier. |
960 StringInputBuffer buffer(name); | 960 StringInputBuffer buffer(name); |
961 if (!Scanner::IsIdentifier(&buffer)) { | 961 if (!Scanner::IsIdentifier(&buffer)) { |
962 Object* obj = NormalizeProperties(); | 962 Object* obj = NormalizeProperties(); |
963 if (obj->IsFailure()) return obj; | 963 if (obj->IsFailure()) return obj; |
964 return AddSlowProperty(name, value, attributes); | 964 return AddSlowProperty(name, value, attributes); |
965 } | 965 } |
966 | 966 |
967 // Replace a CONSTANT_TRANSITION flag with a transition. | |
968 // Do this by removing it, and the standard code for adding a map transition | |
969 // will then run. | |
970 DescriptorArray* old_descriptors = map()->instance_descriptors(); | 967 DescriptorArray* old_descriptors = map()->instance_descriptors(); |
971 int old_name_index = old_descriptors->Search(name); | |
972 bool constant_transition = false; // Only used in assertions. | |
973 if (old_name_index != DescriptorArray::kNotFound && CONSTANT_TRANSITION == | |
974 PropertyDetails(old_descriptors->GetDetails(old_name_index)).type()) { | |
975 constant_transition = true; | |
976 Object* r = old_descriptors->CopyRemove(name); | |
977 if (r->IsFailure()) return r; | |
978 old_descriptors = DescriptorArray::cast(r); | |
979 old_name_index = DescriptorArray::kNotFound; | |
980 } | |
981 | |
982 // Compute the new index for new field. | 968 // Compute the new index for new field. |
983 int index = map()->NextFreePropertyIndex(); | 969 int index = map()->NextFreePropertyIndex(); |
984 | 970 |
985 // Allocate new instance descriptors with (name, index) added | 971 // Allocate new instance descriptors with (name, index) added |
986 FieldDescriptor new_field(name, index, attributes); | 972 FieldDescriptor new_field(name, index, attributes); |
987 Object* new_descriptors = | 973 Object* new_descriptors = |
988 old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS); | 974 old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS); |
989 if (new_descriptors->IsFailure()) return new_descriptors; | 975 if (new_descriptors->IsFailure()) return new_descriptors; |
990 | 976 |
991 // Only allow map transition if the object's map is NOT equal to the | 977 // Only allow map transition if the object's map is NOT equal to the |
992 // global object_function's map and there is not a transition for name. | 978 // global object_function's map and there is not a transition for name. |
993 bool allow_map_transition = | 979 bool allow_map_transition = |
994 !old_descriptors->Contains(name) && | 980 !old_descriptors->Contains(name) && |
995 (Top::context()->global_context()->object_function()->map() != map()); | 981 (Top::context()->global_context()->object_function()->map() != map()); |
996 ASSERT(allow_map_transition || !constant_transition); | |
997 | 982 |
998 if (map()->unused_property_fields() > 0) { | 983 ASSERT(index < properties()->length() || |
999 ASSERT(index < properties()->length()); | 984 map()->unused_property_fields() == 0); |
1000 // Allocate a new map for the object. | 985 // Allocate a new map for the object. |
1001 Object* r = map()->Copy(); | 986 Object* r = map()->Copy(); |
| 987 if (r->IsFailure()) return r; |
| 988 Map* new_map = Map::cast(r); |
| 989 if (allow_map_transition) { |
| 990 // Allocate new instance descriptors for the old map with map transition. |
| 991 MapTransitionDescriptor d(name, Map::cast(new_map), attributes); |
| 992 Object* r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS); |
1002 if (r->IsFailure()) return r; | 993 if (r->IsFailure()) return r; |
1003 Map* new_map = Map::cast(r); | 994 old_descriptors = DescriptorArray::cast(r); |
1004 if (allow_map_transition) { | 995 } |
1005 // Allocate new instance descriptors for the old map with map transition. | |
1006 MapTransitionDescriptor d(name, Map::cast(new_map), attributes); | |
1007 Object* r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS); | |
1008 if (r->IsFailure()) return r; | |
1009 old_descriptors = DescriptorArray::cast(r); | |
1010 } | |
1011 // We have now allocated all the necessary objects. | |
1012 // All the changes can be applied at once, so they are atomic. | |
1013 map()->set_instance_descriptors(old_descriptors); | |
1014 new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); | |
1015 new_map->set_unused_property_fields(map()->unused_property_fields() - 1); | |
1016 set_map(new_map); | |
1017 properties()->set(index, value); | |
1018 } else { | |
1019 ASSERT(map()->unused_property_fields() == 0); | |
1020 | 996 |
| 997 |
| 998 if (map()->unused_property_fields() == 0) { |
1021 if (properties()->length() > kMaxFastProperties) { | 999 if (properties()->length() > kMaxFastProperties) { |
1022 Object* obj = NormalizeProperties(); | 1000 Object* obj = NormalizeProperties(); |
1023 if (obj->IsFailure()) return obj; | 1001 if (obj->IsFailure()) return obj; |
1024 return AddSlowProperty(name, value, attributes); | 1002 return AddSlowProperty(name, value, attributes); |
1025 } | 1003 } |
1026 | |
1027 static const int kExtraFields = 3; | |
1028 // Make room for the new value | 1004 // Make room for the new value |
1029 Object* values = | 1005 Object* values = |
1030 properties()->CopySize(properties()->length() + kExtraFields); | 1006 properties()->CopySize(properties()->length() + kFieldsAdded); |
1031 if (values->IsFailure()) return values; | 1007 if (values->IsFailure()) return values; |
1032 FixedArray::cast(values)->set(index, value); | |
1033 | |
1034 // Allocate a new map for the object. | |
1035 Object* r = map()->Copy(); | |
1036 if (r->IsFailure()) return r; | |
1037 Map* new_map = Map::cast(r); | |
1038 | |
1039 if (allow_map_transition) { | |
1040 MapTransitionDescriptor d(name, Map::cast(new_map), attributes); | |
1041 // Allocate new instance descriptors for the old map with map transition. | |
1042 Object* r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS); | |
1043 if (r->IsFailure()) return r; | |
1044 old_descriptors = DescriptorArray::cast(r); | |
1045 } | |
1046 // We have now allocated all the necessary objects. | |
1047 // All changes can be done at once, atomically. | |
1048 map()->set_instance_descriptors(old_descriptors); | |
1049 new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); | |
1050 new_map->set_unused_property_fields(kExtraFields - 1); | |
1051 set_map(new_map); | |
1052 set_properties(FixedArray::cast(values)); | 1008 set_properties(FixedArray::cast(values)); |
| 1009 new_map->set_unused_property_fields(kFieldsAdded - 1); |
| 1010 } else { |
| 1011 new_map->set_unused_property_fields(map()->unused_property_fields() - 1); |
1053 } | 1012 } |
| 1013 // We have now allocated all the necessary objects. |
| 1014 // All the changes can be applied at once, so they are atomic. |
| 1015 map()->set_instance_descriptors(old_descriptors); |
| 1016 new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); |
| 1017 set_map(new_map); |
| 1018 properties()->set(index, value); |
1054 | 1019 |
1055 return value; | 1020 return value; |
1056 } | 1021 } |
1057 | 1022 |
1058 | 1023 |
1059 Object* JSObject::AddConstantFunctionProperty(String* name, | 1024 Object* JSObject::AddConstantFunctionProperty(String* name, |
1060 JSFunction* function, | 1025 JSFunction* function, |
1061 PropertyAttributes attributes) { | 1026 PropertyAttributes attributes) { |
1062 // Allocate new instance descriptors with (name, function) added | 1027 // Allocate new instance descriptors with (name, function) added |
1063 ConstantFunctionDescriptor d(name, function, attributes); | 1028 ConstantFunctionDescriptor d(name, function, attributes); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1097 old_map->instance_descriptors()->CopyInsert(&mark, KEEP_TRANSITIONS); | 1062 old_map->instance_descriptors()->CopyInsert(&mark, KEEP_TRANSITIONS); |
1098 if (new_descriptors->IsFailure()) { | 1063 if (new_descriptors->IsFailure()) { |
1099 return function; // We have accomplished the main goal, so return success. | 1064 return function; // We have accomplished the main goal, so return success. |
1100 } | 1065 } |
1101 old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); | 1066 old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); |
1102 | 1067 |
1103 return function; | 1068 return function; |
1104 } | 1069 } |
1105 | 1070 |
1106 | 1071 |
1107 Object* JSObject::ReplaceConstantFunctionProperty(String* name, | |
1108 Object* value) { | |
1109 // There are two situations to handle here: | |
1110 // 1: Replace a constant function with another function. | |
1111 // 2: Replace a constant function with an object. | |
1112 if (value->IsJSFunction()) { | |
1113 JSFunction* function = JSFunction::cast(value); | |
1114 | |
1115 Object* new_map = map()->CopyDropTransitions(); | |
1116 if (new_map->IsFailure()) return new_map; | |
1117 set_map(Map::cast(new_map)); | |
1118 | |
1119 // Replace the function entry | |
1120 int index = map()->instance_descriptors()->Search(name); | |
1121 ASSERT(index != DescriptorArray::kNotFound); | |
1122 map()->instance_descriptors()->ReplaceConstantFunction(index, function); | |
1123 } else { | |
1124 // Allocate new instance descriptors with updated property index. | |
1125 int index = map()->NextFreePropertyIndex(); | |
1126 Object* new_descriptors = | |
1127 map()->instance_descriptors()->CopyReplace(name, index, NONE); | |
1128 if (new_descriptors->IsFailure()) return new_descriptors; | |
1129 | |
1130 if (map()->unused_property_fields() > 0) { | |
1131 ASSERT(index < properties()->length()); | |
1132 | |
1133 // Allocate a new map for the object. | |
1134 Object* new_map = map()->Copy(); | |
1135 if (new_map->IsFailure()) return new_map; | |
1136 | |
1137 Map::cast(new_map)-> | |
1138 set_instance_descriptors(DescriptorArray::cast(new_descriptors)); | |
1139 Map::cast(new_map)-> | |
1140 set_unused_property_fields(map()->unused_property_fields()-1); | |
1141 set_map(Map::cast(new_map)); | |
1142 properties()->set(index, value); | |
1143 } else { | |
1144 ASSERT(map()->unused_property_fields() == 0); | |
1145 static const int kFastNofProperties = 20; | |
1146 if (properties()->length() > kFastNofProperties) { | |
1147 Object* obj = NormalizeProperties(); | |
1148 if (obj->IsFailure()) return obj; | |
1149 return SetProperty(name, value, NONE); | |
1150 } | |
1151 | |
1152 static const int kExtraFields = 5; | |
1153 // Make room for the more properties. | |
1154 Object* values = | |
1155 properties()->CopySize(properties()->length() + kExtraFields); | |
1156 if (values->IsFailure()) return values; | |
1157 FixedArray::cast(values)->set(index, value); | |
1158 | |
1159 // Allocate a new map for the object. | |
1160 Object* new_map = map()->Copy(); | |
1161 if (new_map->IsFailure()) return new_map; | |
1162 | |
1163 Map::cast(new_map)-> | |
1164 set_instance_descriptors(DescriptorArray::cast(new_descriptors)); | |
1165 Map::cast(new_map)-> | |
1166 set_unused_property_fields(kExtraFields - 1); | |
1167 set_map(Map::cast(new_map)); | |
1168 set_properties(FixedArray::cast(values)); | |
1169 } | |
1170 } | |
1171 return value; | |
1172 } | |
1173 | |
1174 | |
1175 // Add property in slow mode | 1072 // Add property in slow mode |
1176 Object* JSObject::AddSlowProperty(String* name, | 1073 Object* JSObject::AddSlowProperty(String* name, |
1177 Object* value, | 1074 Object* value, |
1178 PropertyAttributes attributes) { | 1075 PropertyAttributes attributes) { |
1179 PropertyDetails details = PropertyDetails(attributes, NORMAL); | 1076 PropertyDetails details = PropertyDetails(attributes, NORMAL); |
1180 Object* result = property_dictionary()->AddStringEntry(name, value, details); | 1077 Object* result = property_dictionary()->AddStringEntry(name, value, details); |
1181 if (result->IsFailure()) return result; | 1078 if (result->IsFailure()) return result; |
1182 if (property_dictionary() != result) { | 1079 if (property_dictionary() != result) { |
1183 set_properties(Dictionary::cast(result)); | 1080 set_properties(Dictionary::cast(result)); |
1184 } | 1081 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1216 PropertyAttributes attributes) { | 1113 PropertyAttributes attributes) { |
1217 // Check local property, ignore interceptor. | 1114 // Check local property, ignore interceptor. |
1218 LookupResult result; | 1115 LookupResult result; |
1219 LocalLookupRealNamedProperty(name, &result); | 1116 LocalLookupRealNamedProperty(name, &result); |
1220 if (result.IsValid()) return SetProperty(&result, name, value, attributes); | 1117 if (result.IsValid()) return SetProperty(&result, name, value, attributes); |
1221 // Add real property. | 1118 // Add real property. |
1222 return AddProperty(name, value, attributes); | 1119 return AddProperty(name, value, attributes); |
1223 } | 1120 } |
1224 | 1121 |
1225 | 1122 |
| 1123 Object* JSObject::ReplaceSlowProperty(String* name, |
| 1124 Object* value, |
| 1125 PropertyAttributes attributes) { |
| 1126 Dictionary* dictionary = property_dictionary(); |
| 1127 PropertyDetails old_details = |
| 1128 dictionary->DetailsAt(dictionary->FindStringEntry(name)); |
| 1129 int new_index = old_details.index(); |
| 1130 if (old_details.IsTransition()) new_index = 0; |
| 1131 |
| 1132 PropertyDetails new_details(attributes, NORMAL, old_details.index()); |
| 1133 Object* result = |
| 1134 property_dictionary()->SetOrAddStringEntry(name, value, new_details); |
| 1135 if (result->IsFailure()) return result; |
| 1136 if (property_dictionary() != result) { |
| 1137 set_properties(Dictionary::cast(result)); |
| 1138 } |
| 1139 return value; |
| 1140 } |
| 1141 |
| 1142 Object* JSObject::ConvertDescriptorToFieldAndMapTransition( |
| 1143 String* name, |
| 1144 Object* new_value, |
| 1145 PropertyAttributes attributes) { |
| 1146 Map* old_map = map(); |
| 1147 Object* result = ConvertDescriptorToField(name, new_value, attributes); |
| 1148 if (result->IsFailure()) return result; |
| 1149 // If we get to this point we have succeeded - do not return failure |
| 1150 // after this point. Later stuff is optional. |
| 1151 if (!HasFastProperties()) { |
| 1152 return result; |
| 1153 } |
| 1154 // Do not add transitions to the map of "new Object()". |
| 1155 if (map() == Top::context()->global_context()->object_function()->map()) { |
| 1156 return result; |
| 1157 } |
| 1158 |
| 1159 MapTransitionDescriptor transition(name, |
| 1160 map(), |
| 1161 attributes); |
| 1162 Object* new_descriptors = |
| 1163 old_map->instance_descriptors()-> |
| 1164 CopyInsert(&transition, KEEP_TRANSITIONS); |
| 1165 if (new_descriptors->IsFailure()) return result; // Yes, return _result_. |
| 1166 old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); |
| 1167 return result; |
| 1168 } |
| 1169 |
| 1170 |
| 1171 Object* JSObject::ConvertDescriptorToField(String* name, |
| 1172 Object* new_value, |
| 1173 PropertyAttributes attributes) { |
| 1174 if (map()->unused_property_fields() == 0 && |
| 1175 properties()->length() > kMaxFastProperties) { |
| 1176 Object* obj = NormalizeProperties(); |
| 1177 if (obj->IsFailure()) return obj; |
| 1178 return ReplaceSlowProperty(name, new_value, attributes); |
| 1179 } |
| 1180 |
| 1181 int index = map()->NextFreePropertyIndex(); |
| 1182 FieldDescriptor new_field(name, index, attributes); |
| 1183 // Make a new DescriptorArray replacing an entry with FieldDescriptor. |
| 1184 Object* descriptors_unchecked = map()->instance_descriptors()-> |
| 1185 CopyInsert(&new_field, REMOVE_TRANSITIONS); |
| 1186 if (descriptors_unchecked->IsFailure()) return descriptors_unchecked; |
| 1187 DescriptorArray* new_descriptors = |
| 1188 DescriptorArray::cast(descriptors_unchecked); |
| 1189 |
| 1190 // Make a new map for the object. |
| 1191 Object* new_map_unchecked = map()->Copy(); |
| 1192 if (new_map_unchecked->IsFailure()) return new_map_unchecked; |
| 1193 Map* new_map = Map::cast(new_map_unchecked); |
| 1194 new_map->set_instance_descriptors(new_descriptors); |
| 1195 |
| 1196 // Make new properties array if necessary. |
| 1197 FixedArray* new_properties = 0; // Will always be NULL or a valid pointer. |
| 1198 int new_unused_property_fields = map()->unused_property_fields() - 1; |
| 1199 if (map()->unused_property_fields() == 0) { |
| 1200 new_unused_property_fields = kFieldsAdded - 1; |
| 1201 Object* new_properties_unchecked = |
| 1202 properties()->CopySize(properties()->length() + kFieldsAdded); |
| 1203 if (new_properties_unchecked->IsFailure()) return new_properties_unchecked; |
| 1204 new_properties = FixedArray::cast(new_properties_unchecked); |
| 1205 } |
| 1206 |
| 1207 // Update pointers to commit changes. |
| 1208 // Object points to the new map. |
| 1209 new_map->set_unused_property_fields(new_unused_property_fields); |
| 1210 set_map(new_map); |
| 1211 if (new_properties) { |
| 1212 set_properties(FixedArray::cast(new_properties)); |
| 1213 } |
| 1214 properties()->set(index, new_value); |
| 1215 return new_value; |
| 1216 } |
| 1217 |
| 1218 |
| 1219 |
1226 Object* JSObject::SetPropertyWithInterceptor(String* name, | 1220 Object* JSObject::SetPropertyWithInterceptor(String* name, |
1227 Object* value, | 1221 Object* value, |
1228 PropertyAttributes attributes) { | 1222 PropertyAttributes attributes) { |
1229 HandleScope scope; | 1223 HandleScope scope; |
1230 Handle<JSObject> this_handle(this); | 1224 Handle<JSObject> this_handle(this); |
1231 Handle<String> name_handle(name); | 1225 Handle<String> name_handle(name); |
1232 Handle<Object> value_handle(value); | 1226 Handle<Object> value_handle(value); |
1233 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | 1227 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
1234 if (!interceptor->setter()->IsUndefined()) { | 1228 if (!interceptor->setter()->IsUndefined()) { |
1235 Handle<Object> data_handle(interceptor->data()); | 1229 Handle<Object> data_handle(interceptor->data()); |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1521 return value; | 1515 return value; |
1522 case FIELD: | 1516 case FIELD: |
1523 properties()->set(result->GetFieldIndex(), value); | 1517 properties()->set(result->GetFieldIndex(), value); |
1524 return value; | 1518 return value; |
1525 case MAP_TRANSITION: | 1519 case MAP_TRANSITION: |
1526 if (attributes == result->GetAttributes()) { | 1520 if (attributes == result->GetAttributes()) { |
1527 // Only use map transition if the attributes match. | 1521 // Only use map transition if the attributes match. |
1528 return AddFastPropertyUsingMap(result->GetTransitionMap(), | 1522 return AddFastPropertyUsingMap(result->GetTransitionMap(), |
1529 name, | 1523 name, |
1530 value); | 1524 value); |
1531 } else { | |
1532 return AddFastProperty(name, value, attributes); | |
1533 } | 1525 } |
| 1526 return ConvertDescriptorToField(name, value, attributes); |
1534 case CONSTANT_FUNCTION: | 1527 case CONSTANT_FUNCTION: |
1535 if (value == result->GetConstantFunction()) return value; | 1528 if (value == result->GetConstantFunction()) return value; |
1536 // Only replace the function if necessary. | 1529 // Only replace the function if necessary. |
1537 return ReplaceConstantFunctionProperty(name, value); | 1530 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
1538 case CALLBACKS: | 1531 case CALLBACKS: |
1539 return SetPropertyWithCallback(result->GetCallbackObject(), | 1532 return SetPropertyWithCallback(result->GetCallbackObject(), |
1540 name, | 1533 name, |
1541 value, | 1534 value, |
1542 result->holder()); | 1535 result->holder()); |
1543 case INTERCEPTOR: | 1536 case INTERCEPTOR: |
1544 return SetPropertyWithInterceptor(name, value, attributes); | 1537 return SetPropertyWithInterceptor(name, value, attributes); |
1545 case CONSTANT_TRANSITION: | 1538 case CONSTANT_TRANSITION: |
1546 // Replace with a MAP_TRANSITION to a new map with a FIELD, even | 1539 // Replace with a MAP_TRANSITION to a new map with a FIELD, even |
1547 // if the value is a function. | 1540 // if the value is a function. |
1548 // AddProperty has been extended to do this, in this case. | 1541 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
1549 return AddFastProperty(name, value, attributes); | |
1550 case NULL_DESCRIPTOR: | 1542 case NULL_DESCRIPTOR: |
1551 UNREACHABLE(); | 1543 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
1552 default: | 1544 default: |
1553 UNREACHABLE(); | 1545 UNREACHABLE(); |
1554 } | 1546 } |
1555 UNREACHABLE(); | 1547 UNREACHABLE(); |
1556 return value; | 1548 return value; |
1557 } | 1549 } |
1558 | 1550 |
1559 | 1551 |
1560 // Set a real local property, even if it is READ_ONLY. If the property is not | 1552 // Set a real local property, even if it is READ_ONLY. If the property is not |
1561 // present, add it with attributes NONE. This code is an exact clone of | 1553 // present, add it with attributes NONE. This code is an exact clone of |
(...skipping 11 matching lines...) Expand all Loading... |
1573 // ADDED TO CLONE | 1565 // ADDED TO CLONE |
1574 LookupResult result_struct; | 1566 LookupResult result_struct; |
1575 LocalLookup(name, &result_struct); | 1567 LocalLookup(name, &result_struct); |
1576 LookupResult* result = &result_struct; | 1568 LookupResult* result = &result_struct; |
1577 // END ADDED TO CLONE | 1569 // END ADDED TO CLONE |
1578 // Check access rights if needed. | 1570 // Check access rights if needed. |
1579 if (IsAccessCheckNeeded() | 1571 if (IsAccessCheckNeeded() |
1580 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 1572 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { |
1581 return SetPropertyWithFailedAccessCheck(result, name, value); | 1573 return SetPropertyWithFailedAccessCheck(result, name, value); |
1582 } | 1574 } |
1583 /* | 1575 // Check for accessor in prototype chain removed here in clone. |
1584 REMOVED FROM CLONE | |
1585 if (result->IsNotFound() || !result->IsProperty()) { | |
1586 // We could not find a local property so let's check whether there is an | |
1587 // accessor that wants to handle the property. | |
1588 LookupResult accessor_result; | |
1589 LookupCallbackSetterInPrototypes(name, &accessor_result); | |
1590 if (accessor_result.IsValid()) { | |
1591 return SetPropertyWithCallback(accessor_result.GetCallbackObject(), | |
1592 name, | |
1593 value, | |
1594 accessor_result.holder()); | |
1595 } | |
1596 } | |
1597 */ | |
1598 if (result->IsNotFound()) { | 1576 if (result->IsNotFound()) { |
1599 return AddProperty(name, value, attributes); | 1577 return AddProperty(name, value, attributes); |
1600 } | 1578 } |
1601 if (!result->IsLoaded()) { | 1579 if (!result->IsLoaded()) { |
1602 return SetLazyProperty(result, name, value, attributes); | 1580 return SetLazyProperty(result, name, value, attributes); |
1603 } | 1581 } |
1604 /* | 1582 // Check of IsReadOnly removed from here in clone. |
1605 REMOVED FROM CLONE | |
1606 if (result->IsReadOnly() && result->IsProperty()) return value; | |
1607 */ | |
1608 // This is a real property that is not read-only, or it is a | |
1609 // transition or null descriptor and there are no setters in the prototypes. | |
1610 switch (result->type()) { | 1583 switch (result->type()) { |
1611 case NORMAL: | 1584 case NORMAL: |
1612 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); | 1585 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); |
1613 return value; | 1586 return value; |
1614 case FIELD: | 1587 case FIELD: |
1615 properties()->set(result->GetFieldIndex(), value); | 1588 properties()->set(result->GetFieldIndex(), value); |
1616 return value; | 1589 return value; |
1617 case MAP_TRANSITION: | 1590 case MAP_TRANSITION: |
1618 if (attributes == result->GetAttributes()) { | 1591 if (attributes == result->GetAttributes()) { |
1619 // Only use map transition if the attributes match. | 1592 // Only use map transition if the attributes match. |
1620 return AddFastPropertyUsingMap(result->GetTransitionMap(), | 1593 return AddFastPropertyUsingMap(result->GetTransitionMap(), |
1621 name, | 1594 name, |
1622 value); | 1595 value); |
1623 } else { | 1596 } else { |
1624 return AddFastProperty(name, value, attributes); | 1597 return ConvertDescriptorToField(name, value, attributes); |
1625 } | 1598 } |
1626 case CONSTANT_FUNCTION: | 1599 case CONSTANT_FUNCTION: |
1627 if (value == result->GetConstantFunction()) return value; | 1600 if (value == result->GetConstantFunction()) return value; |
1628 // Only replace the function if necessary. | 1601 // Only replace the function if necessary. |
1629 return ReplaceConstantFunctionProperty(name, value); | 1602 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
1630 case CALLBACKS: | 1603 case CALLBACKS: |
1631 return SetPropertyWithCallback(result->GetCallbackObject(), | 1604 return SetPropertyWithCallback(result->GetCallbackObject(), |
1632 name, | 1605 name, |
1633 value, | 1606 value, |
1634 result->holder()); | 1607 result->holder()); |
1635 case INTERCEPTOR: | 1608 case INTERCEPTOR: |
1636 return SetPropertyWithInterceptor(name, value, attributes); | 1609 return SetPropertyWithInterceptor(name, value, attributes); |
1637 case CONSTANT_TRANSITION: | 1610 case CONSTANT_TRANSITION: |
1638 // Replace with a MAP_TRANSITION to a new map with a FIELD, even | 1611 // Replace with a MAP_TRANSITION to a new map with a FIELD, even |
1639 // if the value is a function. | 1612 // if the value is a function. |
1640 // AddProperty has been extended to do this, in this case. | 1613 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
1641 return AddFastProperty(name, value, attributes); | |
1642 case NULL_DESCRIPTOR: | 1614 case NULL_DESCRIPTOR: |
1643 UNREACHABLE(); | 1615 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
1644 default: | 1616 default: |
1645 UNREACHABLE(); | 1617 UNREACHABLE(); |
1646 } | 1618 } |
1647 UNREACHABLE(); | 1619 UNREACHABLE(); |
1648 return value; | 1620 return value; |
1649 } | 1621 } |
1650 | 1622 |
1651 | 1623 |
1652 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( | 1624 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( |
1653 JSObject* receiver, | 1625 JSObject* receiver, |
(...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2656 FixedArray::cast(bridge_storage)-> | 2628 FixedArray::cast(bridge_storage)-> |
2657 set(kEnumCacheBridgeCacheIndex, new_cache); | 2629 set(kEnumCacheBridgeCacheIndex, new_cache); |
2658 fast_set(FixedArray::cast(bridge_storage), | 2630 fast_set(FixedArray::cast(bridge_storage), |
2659 kEnumCacheBridgeEnumIndex, | 2631 kEnumCacheBridgeEnumIndex, |
2660 get(kEnumerationIndexIndex)); | 2632 get(kEnumerationIndexIndex)); |
2661 set(kEnumerationIndexIndex, bridge_storage); | 2633 set(kEnumerationIndexIndex, bridge_storage); |
2662 } | 2634 } |
2663 } | 2635 } |
2664 | 2636 |
2665 | 2637 |
2666 void DescriptorArray::ReplaceConstantFunction(int descriptor_number, | |
2667 JSFunction* value) { | |
2668 ASSERT(!Heap::InNewSpace(value)); | |
2669 FixedArray* content_array = GetContentArray(); | |
2670 fast_set(content_array, ToValueIndex(descriptor_number), value); | |
2671 } | |
2672 | |
2673 | |
2674 Object* DescriptorArray::CopyInsert(Descriptor* descriptor, | 2638 Object* DescriptorArray::CopyInsert(Descriptor* descriptor, |
2675 TransitionFlag transition_flag) { | 2639 TransitionFlag transition_flag) { |
2676 // Transitions are only kept when inserting another transition. | 2640 // Transitions are only kept when inserting another transition. |
2677 // This precondition is not required by this function's implementation, but | 2641 // This precondition is not required by this function's implementation, but |
2678 // is currently required by the semantics of maps, so we check it. | 2642 // is currently required by the semantics of maps, so we check it. |
2679 // Conversely, we filter after replacing, so replacing a transition and | 2643 // Conversely, we filter after replacing, so replacing a transition and |
2680 // removing all other transitions is not supported. | 2644 // removing all other transitions is not supported. |
2681 bool remove_transitions = transition_flag == REMOVE_TRANSITIONS; | 2645 bool remove_transitions = transition_flag == REMOVE_TRANSITIONS; |
2682 ASSERT(remove_transitions == !descriptor->GetDetails().IsTransition()); | 2646 ASSERT(remove_transitions == !descriptor->GetDetails().IsTransition()); |
2683 ASSERT(descriptor->GetDetails().type() != NULL_DESCRIPTOR); | 2647 ASSERT(descriptor->GetDetails().type() != NULL_DESCRIPTOR); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2764 if (r.IsNullDescriptor()) continue; | 2728 if (r.IsNullDescriptor()) continue; |
2765 if (remove_transitions && r.IsTransition()) continue; | 2729 if (remove_transitions && r.IsTransition()) continue; |
2766 w.WriteFrom(&r); | 2730 w.WriteFrom(&r); |
2767 } | 2731 } |
2768 ASSERT(w.eos()); | 2732 ASSERT(w.eos()); |
2769 | 2733 |
2770 return new_descriptors; | 2734 return new_descriptors; |
2771 } | 2735 } |
2772 | 2736 |
2773 | 2737 |
2774 Object* DescriptorArray::CopyReplace(String* name, | |
2775 int index, | |
2776 PropertyAttributes attributes) { | |
2777 // Allocate the new descriptor array. | |
2778 Object* result = DescriptorArray::Allocate(number_of_descriptors()); | |
2779 if (result->IsFailure()) return result; | |
2780 | |
2781 // Make sure only symbols are added to the instance descriptor. | |
2782 if (!name->IsSymbol()) { | |
2783 Object* result = Heap::LookupSymbol(name); | |
2784 if (result->IsFailure()) return result; | |
2785 name = String::cast(result); | |
2786 } | |
2787 | |
2788 DescriptorWriter w(DescriptorArray::cast(result)); | |
2789 for (DescriptorReader r(this); !r.eos(); r.advance()) { | |
2790 if (r.Equals(name)) { | |
2791 FieldDescriptor d(name, index, attributes); | |
2792 d.SetEnumerationIndex(r.GetDetails().index()); | |
2793 w.Write(&d); | |
2794 } else { | |
2795 w.WriteFrom(&r); | |
2796 } | |
2797 } | |
2798 | |
2799 // Copy the next enumeration index. | |
2800 DescriptorArray::cast(result)-> | |
2801 SetNextEnumerationIndex(NextEnumerationIndex()); | |
2802 | |
2803 ASSERT(w.eos()); | |
2804 return result; | |
2805 } | |
2806 | |
2807 | |
2808 Object* DescriptorArray::CopyRemove(String* name) { | |
2809 if (!name->IsSymbol()) { | |
2810 Object* result = Heap::LookupSymbol(name); | |
2811 if (result->IsFailure()) return result; | |
2812 name = String::cast(result); | |
2813 } | |
2814 ASSERT(name->IsSymbol()); | |
2815 Object* result = Allocate(number_of_descriptors() - 1); | |
2816 if (result->IsFailure()) return result; | |
2817 DescriptorArray* new_descriptors = DescriptorArray::cast(result); | |
2818 | |
2819 // Set the enumeration index in the descriptors and set the enumeration index | |
2820 // in the result. | |
2821 new_descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); | |
2822 // Write the old content and the descriptor information | |
2823 DescriptorWriter w(new_descriptors); | |
2824 DescriptorReader r(this); | |
2825 while (!r.eos()) { | |
2826 if (r.GetKey() != name) { // Both are symbols; object identity suffices. | |
2827 w.WriteFrom(&r); | |
2828 } | |
2829 r.advance(); | |
2830 } | |
2831 ASSERT(w.eos()); | |
2832 | |
2833 return new_descriptors; | |
2834 } | |
2835 | |
2836 | |
2837 Object* DescriptorArray::RemoveTransitions() { | 2738 Object* DescriptorArray::RemoveTransitions() { |
2838 // Remove all transitions. Return a copy of the array with all transitions | 2739 // Remove all transitions. Return a copy of the array with all transitions |
2839 // removed, or a Failure object if the new array could not be allocated. | 2740 // removed, or a Failure object if the new array could not be allocated. |
2840 | 2741 |
2841 // Compute the size of the map transition entries to be removed. | 2742 // Compute the size of the map transition entries to be removed. |
2842 int count_transitions = 0; | 2743 int count_transitions = 0; |
2843 for (DescriptorReader r(this); !r.eos(); r.advance()) { | 2744 for (DescriptorReader r(this); !r.eos(); r.advance()) { |
2844 if (r.IsTransition()) count_transitions++; | 2745 if (r.IsTransition()) count_transitions++; |
2845 } | 2746 } |
2846 | 2747 |
(...skipping 3695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6542 // No break point. | 6443 // No break point. |
6543 if (break_point_objects()->IsUndefined()) return 0; | 6444 if (break_point_objects()->IsUndefined()) return 0; |
6544 // Single beak point. | 6445 // Single beak point. |
6545 if (!break_point_objects()->IsFixedArray()) return 1; | 6446 if (!break_point_objects()->IsFixedArray()) return 1; |
6546 // Multiple break points. | 6447 // Multiple break points. |
6547 return FixedArray::cast(break_point_objects())->length(); | 6448 return FixedArray::cast(break_point_objects())->length(); |
6548 } | 6449 } |
6549 | 6450 |
6550 | 6451 |
6551 } } // namespace v8::internal | 6452 } } // namespace v8::internal |
OLD | NEW |