Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: src/objects.cc

Issue 6528: This change rewrites some of the code to add properties to an object.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698