OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 1226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1237 } | 1237 } |
1238 | 1238 |
1239 | 1239 |
1240 Object* JSObject::AddFastProperty(String* name, | 1240 Object* JSObject::AddFastProperty(String* name, |
1241 Object* value, | 1241 Object* value, |
1242 PropertyAttributes attributes) { | 1242 PropertyAttributes attributes) { |
1243 // Normalize the object if the name is an actual string (not the | 1243 // Normalize the object if the name is an actual string (not the |
1244 // hidden symbols) and is not a real identifier. | 1244 // hidden symbols) and is not a real identifier. |
1245 StringInputBuffer buffer(name); | 1245 StringInputBuffer buffer(name); |
1246 if (!Scanner::IsIdentifier(&buffer) && name != Heap::hidden_symbol()) { | 1246 if (!Scanner::IsIdentifier(&buffer) && name != Heap::hidden_symbol()) { |
1247 Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); | 1247 Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1248 if (obj->IsFailure()) return obj; | 1248 if (obj->IsFailure()) return obj; |
1249 return AddSlowProperty(name, value, attributes); | 1249 return AddSlowProperty(name, value, attributes); |
1250 } | 1250 } |
1251 | 1251 |
1252 DescriptorArray* old_descriptors = map()->instance_descriptors(); | 1252 DescriptorArray* old_descriptors = map()->instance_descriptors(); |
1253 // Compute the new index for new field. | 1253 // Compute the new index for new field. |
1254 int index = map()->NextFreePropertyIndex(); | 1254 int index = map()->NextFreePropertyIndex(); |
1255 | 1255 |
1256 // Allocate new instance descriptors with (name, index) added | 1256 // Allocate new instance descriptors with (name, index) added |
1257 FieldDescriptor new_field(name, index, attributes); | 1257 FieldDescriptor new_field(name, index, attributes); |
(...skipping 17 matching lines...) Expand all Loading... |
1275 if (allow_map_transition) { | 1275 if (allow_map_transition) { |
1276 // Allocate new instance descriptors for the old map with map transition. | 1276 // Allocate new instance descriptors for the old map with map transition. |
1277 MapTransitionDescriptor d(name, Map::cast(new_map), attributes); | 1277 MapTransitionDescriptor d(name, Map::cast(new_map), attributes); |
1278 Object* r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS); | 1278 Object* r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS); |
1279 if (r->IsFailure()) return r; | 1279 if (r->IsFailure()) return r; |
1280 old_descriptors = DescriptorArray::cast(r); | 1280 old_descriptors = DescriptorArray::cast(r); |
1281 } | 1281 } |
1282 | 1282 |
1283 if (map()->unused_property_fields() == 0) { | 1283 if (map()->unused_property_fields() == 0) { |
1284 if (properties()->length() > kMaxFastProperties) { | 1284 if (properties()->length() > kMaxFastProperties) { |
1285 Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); | 1285 Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1286 if (obj->IsFailure()) return obj; | 1286 if (obj->IsFailure()) return obj; |
1287 return AddSlowProperty(name, value, attributes); | 1287 return AddSlowProperty(name, value, attributes); |
1288 } | 1288 } |
1289 // Make room for the new value | 1289 // Make room for the new value |
1290 Object* values = | 1290 Object* values = |
1291 properties()->CopySize(properties()->length() + kFieldsAdded); | 1291 properties()->CopySize(properties()->length() + kFieldsAdded); |
1292 if (values->IsFailure()) return values; | 1292 if (values->IsFailure()) return values; |
1293 set_properties(FixedArray::cast(values)); | 1293 set_properties(FixedArray::cast(values)); |
1294 new_map->set_unused_property_fields(kFieldsAdded - 1); | 1294 new_map->set_unused_property_fields(kFieldsAdded - 1); |
1295 } else { | 1295 } else { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 if (value->IsJSFunction()) { | 1396 if (value->IsJSFunction()) { |
1397 return AddConstantFunctionProperty(name, | 1397 return AddConstantFunctionProperty(name, |
1398 JSFunction::cast(value), | 1398 JSFunction::cast(value), |
1399 attributes); | 1399 attributes); |
1400 } else { | 1400 } else { |
1401 return AddFastProperty(name, value, attributes); | 1401 return AddFastProperty(name, value, attributes); |
1402 } | 1402 } |
1403 } else { | 1403 } else { |
1404 // Normalize the object to prevent very large instance descriptors. | 1404 // Normalize the object to prevent very large instance descriptors. |
1405 // This eliminates unwanted N^2 allocation and lookup behavior. | 1405 // This eliminates unwanted N^2 allocation and lookup behavior. |
1406 Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); | 1406 Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1407 if (obj->IsFailure()) return obj; | 1407 if (obj->IsFailure()) return obj; |
1408 } | 1408 } |
1409 } | 1409 } |
1410 return AddSlowProperty(name, value, attributes); | 1410 return AddSlowProperty(name, value, attributes); |
1411 } | 1411 } |
1412 | 1412 |
1413 | 1413 |
1414 Object* JSObject::SetPropertyPostInterceptor(String* name, | 1414 Object* JSObject::SetPropertyPostInterceptor(String* name, |
1415 Object* value, | 1415 Object* value, |
1416 PropertyAttributes attributes) { | 1416 PropertyAttributes attributes) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1466 old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); | 1466 old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); |
1467 return result; | 1467 return result; |
1468 } | 1468 } |
1469 | 1469 |
1470 | 1470 |
1471 Object* JSObject::ConvertDescriptorToField(String* name, | 1471 Object* JSObject::ConvertDescriptorToField(String* name, |
1472 Object* new_value, | 1472 Object* new_value, |
1473 PropertyAttributes attributes) { | 1473 PropertyAttributes attributes) { |
1474 if (map()->unused_property_fields() == 0 && | 1474 if (map()->unused_property_fields() == 0 && |
1475 properties()->length() > kMaxFastProperties) { | 1475 properties()->length() > kMaxFastProperties) { |
1476 Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); | 1476 Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1477 if (obj->IsFailure()) return obj; | 1477 if (obj->IsFailure()) return obj; |
1478 return ReplaceSlowProperty(name, new_value, attributes); | 1478 return ReplaceSlowProperty(name, new_value, attributes); |
1479 } | 1479 } |
1480 | 1480 |
1481 int index = map()->NextFreePropertyIndex(); | 1481 int index = map()->NextFreePropertyIndex(); |
1482 FieldDescriptor new_field(name, index, attributes); | 1482 FieldDescriptor new_field(name, index, attributes); |
1483 // Make a new DescriptorArray replacing an entry with FieldDescriptor. | 1483 // Make a new DescriptorArray replacing an entry with FieldDescriptor. |
1484 Object* descriptors_unchecked = map()->instance_descriptors()-> | 1484 Object* descriptors_unchecked = map()->instance_descriptors()-> |
1485 CopyInsert(&new_field, REMOVE_TRANSITIONS); | 1485 CopyInsert(&new_field, REMOVE_TRANSITIONS); |
1486 if (descriptors_unchecked->IsFailure()) return descriptors_unchecked; | 1486 if (descriptors_unchecked->IsFailure()) return descriptors_unchecked; |
(...skipping 630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2117 if (HasLocalElement(index)) return NONE; | 2117 if (HasLocalElement(index)) return NONE; |
2118 return ABSENT; | 2118 return ABSENT; |
2119 } | 2119 } |
2120 // Named property. | 2120 // Named property. |
2121 LookupResult result; | 2121 LookupResult result; |
2122 LocalLookup(name, &result); | 2122 LocalLookup(name, &result); |
2123 return GetPropertyAttribute(this, &result, name, false); | 2123 return GetPropertyAttribute(this, &result, name, false); |
2124 } | 2124 } |
2125 | 2125 |
2126 | 2126 |
2127 Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) { | 2127 Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode, |
| 2128 int expected_additional_properties) { |
2128 if (!HasFastProperties()) return this; | 2129 if (!HasFastProperties()) return this; |
2129 | 2130 |
2130 // The global object is always normalized. | 2131 // The global object is always normalized. |
2131 ASSERT(!IsGlobalObject()); | 2132 ASSERT(!IsGlobalObject()); |
2132 | 2133 |
2133 // Allocate new content. | 2134 // Allocate new content. |
| 2135 int property_count = map()->NumberOfDescribedProperties(); |
| 2136 if (expected_additional_properties > 0) { |
| 2137 property_count += expected_additional_properties; |
| 2138 } else { |
| 2139 property_count += 2; // Make space for two more properties. |
| 2140 } |
2134 Object* obj = | 2141 Object* obj = |
2135 StringDictionary::Allocate(map()->NumberOfDescribedProperties() * 2 + 4); | 2142 StringDictionary::Allocate(property_count * 2); |
2136 if (obj->IsFailure()) return obj; | 2143 if (obj->IsFailure()) return obj; |
2137 StringDictionary* dictionary = StringDictionary::cast(obj); | 2144 StringDictionary* dictionary = StringDictionary::cast(obj); |
2138 | 2145 |
2139 DescriptorArray* descs = map()->instance_descriptors(); | 2146 DescriptorArray* descs = map()->instance_descriptors(); |
2140 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 2147 for (int i = 0; i < descs->number_of_descriptors(); i++) { |
2141 PropertyDetails details = descs->GetDetails(i); | 2148 PropertyDetails details = descs->GetDetails(i); |
2142 switch (details.type()) { | 2149 switch (details.type()) { |
2143 case CONSTANT_FUNCTION: { | 2150 case CONSTANT_FUNCTION: { |
2144 PropertyDetails d = | 2151 PropertyDetails d = |
2145 PropertyDetails(details.attributes(), NORMAL, details.index()); | 2152 PropertyDetails(details.attributes(), NORMAL, details.index()); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2265 } | 2272 } |
2266 | 2273 |
2267 | 2274 |
2268 Object* JSObject::DeletePropertyPostInterceptor(String* name, DeleteMode mode) { | 2275 Object* JSObject::DeletePropertyPostInterceptor(String* name, DeleteMode mode) { |
2269 // Check local property, ignore interceptor. | 2276 // Check local property, ignore interceptor. |
2270 LookupResult result; | 2277 LookupResult result; |
2271 LocalLookupRealNamedProperty(name, &result); | 2278 LocalLookupRealNamedProperty(name, &result); |
2272 if (!result.IsValid()) return Heap::true_value(); | 2279 if (!result.IsValid()) return Heap::true_value(); |
2273 | 2280 |
2274 // Normalize object if needed. | 2281 // Normalize object if needed. |
2275 Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); | 2282 Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
2276 if (obj->IsFailure()) return obj; | 2283 if (obj->IsFailure()) return obj; |
2277 | 2284 |
2278 return DeleteNormalizedProperty(name, mode); | 2285 return DeleteNormalizedProperty(name, mode); |
2279 } | 2286 } |
2280 | 2287 |
2281 | 2288 |
2282 Object* JSObject::DeletePropertyWithInterceptor(String* name) { | 2289 Object* JSObject::DeletePropertyWithInterceptor(String* name) { |
2283 HandleScope scope; | 2290 HandleScope scope; |
2284 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | 2291 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
2285 Handle<String> name_handle(name); | 2292 Handle<String> name_handle(name); |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2462 return DeletePropertyPostInterceptor(name, mode); | 2469 return DeletePropertyPostInterceptor(name, mode); |
2463 } | 2470 } |
2464 return DeletePropertyWithInterceptor(name); | 2471 return DeletePropertyWithInterceptor(name); |
2465 } | 2472 } |
2466 if (!result.IsLoaded()) { | 2473 if (!result.IsLoaded()) { |
2467 return JSObject::cast(this)->DeleteLazyProperty(&result, | 2474 return JSObject::cast(this)->DeleteLazyProperty(&result, |
2468 name, | 2475 name, |
2469 mode); | 2476 mode); |
2470 } | 2477 } |
2471 // Normalize object if needed. | 2478 // Normalize object if needed. |
2472 Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); | 2479 Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
2473 if (obj->IsFailure()) return obj; | 2480 if (obj->IsFailure()) return obj; |
2474 // Make sure the properties are normalized before removing the entry. | 2481 // Make sure the properties are normalized before removing the entry. |
2475 return DeleteNormalizedProperty(name, mode); | 2482 return DeleteNormalizedProperty(name, mode); |
2476 } | 2483 } |
2477 } | 2484 } |
2478 | 2485 |
2479 | 2486 |
2480 // Check whether this object references another object. | 2487 // Check whether this object references another object. |
2481 bool JSObject::ReferencesObject(Object* obj) { | 2488 bool JSObject::ReferencesObject(Object* obj) { |
2482 AssertNoAllocation no_alloc; | 2489 AssertNoAllocation no_alloc; |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2795 element_dictionary()->Set(index, structure, details); | 2802 element_dictionary()->Set(index, structure, details); |
2796 if (dict->IsFailure()) return dict; | 2803 if (dict->IsFailure()) return dict; |
2797 | 2804 |
2798 // If name is an index we need to stay in slow case. | 2805 // If name is an index we need to stay in slow case. |
2799 NumberDictionary* elements = NumberDictionary::cast(dict); | 2806 NumberDictionary* elements = NumberDictionary::cast(dict); |
2800 elements->set_requires_slow_elements(); | 2807 elements->set_requires_slow_elements(); |
2801 // Set the potential new dictionary on the object. | 2808 // Set the potential new dictionary on the object. |
2802 set_elements(NumberDictionary::cast(dict)); | 2809 set_elements(NumberDictionary::cast(dict)); |
2803 } else { | 2810 } else { |
2804 // Normalize object to make this operation simple. | 2811 // Normalize object to make this operation simple. |
2805 Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); | 2812 Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
2806 if (ok->IsFailure()) return ok; | 2813 if (ok->IsFailure()) return ok; |
2807 | 2814 |
2808 // For the global object allocate a new map to invalidate the global inline | 2815 // For the global object allocate a new map to invalidate the global inline |
2809 // caches which have a global property cell reference directly in the code. | 2816 // caches which have a global property cell reference directly in the code. |
2810 if (IsGlobalObject()) { | 2817 if (IsGlobalObject()) { |
2811 Object* new_map = map()->CopyDropDescriptors(); | 2818 Object* new_map = map()->CopyDropDescriptors(); |
2812 if (new_map->IsFailure()) return new_map; | 2819 if (new_map->IsFailure()) return new_map; |
2813 set_map(Map::cast(new_map)); | 2820 set_map(Map::cast(new_map)); |
2814 } | 2821 } |
2815 | 2822 |
(...skipping 5099 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7915 if (break_point_objects()->IsUndefined()) return 0; | 7922 if (break_point_objects()->IsUndefined()) return 0; |
7916 // Single beak point. | 7923 // Single beak point. |
7917 if (!break_point_objects()->IsFixedArray()) return 1; | 7924 if (!break_point_objects()->IsFixedArray()) return 1; |
7918 // Multiple break points. | 7925 // Multiple break points. |
7919 return FixedArray::cast(break_point_objects())->length(); | 7926 return FixedArray::cast(break_point_objects())->length(); |
7920 } | 7927 } |
7921 #endif | 7928 #endif |
7922 | 7929 |
7923 | 7930 |
7924 } } // namespace v8::internal | 7931 } } // namespace v8::internal |
OLD | NEW |