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 1981 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1992 cache->Update(descriptors, name, number); | 1992 cache->Update(descriptors, name, number); |
1993 } | 1993 } |
1994 if (number != DescriptorArray::kNotFound) { | 1994 if (number != DescriptorArray::kNotFound) { |
1995 result->DescriptorResult(holder, descriptors->GetDetails(number), number); | 1995 result->DescriptorResult(holder, descriptors->GetDetails(number), number); |
1996 } else { | 1996 } else { |
1997 result->NotFound(); | 1997 result->NotFound(); |
1998 } | 1998 } |
1999 } | 1999 } |
2000 | 2000 |
2001 | 2001 |
2002 MaybeObject* Map::GetElementsTransitionMap(ElementsKind elements_kind, | 2002 MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind elements_kind) { |
2003 bool safe_to_add_transition) { | 2003 Heap* current_heap = GetHeap(); |
2004 Heap* current_heap = heap(); | 2004 Map* current_map = map(); |
2005 DescriptorArray* descriptors = instance_descriptors(); | 2005 DescriptorArray* descriptors = current_map->instance_descriptors(); |
2006 String* elements_transition_sentinel_name = current_heap->empty_symbol(); | 2006 String* elements_transition_sentinel_name = current_heap->empty_symbol(); |
2007 | 2007 |
| 2008 if (current_map->elements_kind() == elements_kind) return current_map; |
| 2009 |
| 2010 // Only objects with FastProperties can have DescriptorArrays and can track |
| 2011 // element-related maps. Also don't add descriptors to maps that are shared. |
| 2012 bool safe_to_add_transition = HasFastProperties() && |
| 2013 !current_map->IsUndefined() && |
| 2014 !current_map->is_shared(); |
| 2015 |
| 2016 // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps cause by objects |
| 2017 // with elements that switch back and forth between dictionary and fast |
| 2018 // element mode. |
| 2019 if ((current_map->elements_kind() == DICTIONARY_ELEMENTS && |
| 2020 elements_kind == FAST_ELEMENTS)) { |
| 2021 safe_to_add_transition = false; |
| 2022 } |
| 2023 |
2008 if (safe_to_add_transition) { | 2024 if (safe_to_add_transition) { |
2009 // It's only safe to manipulate the descriptor array if it would be | 2025 // It's only safe to manipulate the descriptor array if it would be |
2010 // safe to add a transition. | 2026 // safe to add a transition. |
2011 | 2027 |
2012 ASSERT(!is_shared()); // no transitions can be added to shared maps. | |
2013 // Check if the elements transition already exists. | 2028 // Check if the elements transition already exists. |
2014 DescriptorLookupCache* cache = | 2029 DescriptorLookupCache* cache = |
2015 current_heap->isolate()->descriptor_lookup_cache(); | 2030 current_heap->isolate()->descriptor_lookup_cache(); |
2016 int index = cache->Lookup(descriptors, elements_transition_sentinel_name); | 2031 int index = cache->Lookup(descriptors, elements_transition_sentinel_name); |
2017 if (index == DescriptorLookupCache::kAbsent) { | 2032 if (index == DescriptorLookupCache::kAbsent) { |
2018 index = descriptors->Search(elements_transition_sentinel_name); | 2033 index = descriptors->Search(elements_transition_sentinel_name); |
2019 cache->Update(descriptors, | 2034 cache->Update(descriptors, |
2020 elements_transition_sentinel_name, | 2035 elements_transition_sentinel_name, |
2021 index); | 2036 index); |
2022 } | 2037 } |
2023 | 2038 |
2024 // If the transition already exists, check the type. If there is a match, | 2039 // If the transition already exists, check the type. If there is a match, |
2025 // return it. | 2040 // return it. |
2026 if (index != DescriptorArray::kNotFound) { | 2041 if (index != DescriptorArray::kNotFound) { |
2027 PropertyDetails details(PropertyDetails(descriptors->GetDetails(index))); | 2042 PropertyDetails details(PropertyDetails(descriptors->GetDetails(index))); |
2028 if (details.type() == ELEMENTS_TRANSITION && | 2043 if (details.type() == ELEMENTS_TRANSITION && |
2029 details.elements_kind() == elements_kind) { | 2044 details.elements_kind() == elements_kind) { |
2030 return descriptors->GetValue(index); | 2045 return descriptors->GetValue(index); |
2031 } else { | 2046 } else { |
2032 safe_to_add_transition = false; | 2047 safe_to_add_transition = false; |
2033 } | 2048 } |
2034 } | 2049 } |
2035 } | 2050 } |
2036 | 2051 |
2037 // No transition to an existing map for the given ElementsKind. Make a new | 2052 // No transition to an existing map for the given ElementsKind. Make a new |
2038 // one. | 2053 // one. |
2039 Object* obj; | 2054 Object* obj; |
2040 { MaybeObject* maybe_map = CopyDropTransitions(); | 2055 { MaybeObject* maybe_map = current_map->CopyDropTransitions(); |
2041 if (!maybe_map->ToObject(&obj)) return maybe_map; | 2056 if (!maybe_map->ToObject(&obj)) return maybe_map; |
2042 } | 2057 } |
2043 Map* new_map = Map::cast(obj); | 2058 Map* new_map = Map::cast(obj); |
2044 | 2059 |
2045 new_map->set_elements_kind(elements_kind); | 2060 new_map->set_elements_kind(elements_kind); |
2046 GetIsolate()->counters()->map_to_external_array_elements()->Increment(); | |
2047 | 2061 |
2048 // Only remember the map transition if the object's map is NOT equal to the | 2062 // Only remember the map transition if the object's map is NOT equal to the |
2049 // global object_function's map and there is not an already existing | 2063 // global object_function's map and there is not an already existing |
2050 // non-matching element transition. | 2064 // non-matching element transition. |
2051 bool allow_map_transition = | 2065 bool allow_map_transition = |
2052 safe_to_add_transition && | 2066 safe_to_add_transition && |
2053 (GetIsolate()->context()->global_context()->object_function()->map() != | 2067 (GetIsolate()->context()->global_context()->object_function()->map() != |
2054 map()); | 2068 map()); |
2055 if (allow_map_transition) { | 2069 if (allow_map_transition) { |
2056 // Allocate new instance descriptors for the old map with map transition. | 2070 // Allocate new instance descriptors for the old map with map transition. |
2057 ElementsTransitionDescriptor desc(elements_transition_sentinel_name, | 2071 ElementsTransitionDescriptor desc(elements_transition_sentinel_name, |
2058 Map::cast(new_map), | 2072 Map::cast(new_map), |
2059 elements_kind); | 2073 elements_kind); |
2060 Object* new_descriptors; | 2074 Object* new_descriptors; |
2061 MaybeObject* maybe_new_descriptors = descriptors->CopyInsert( | 2075 MaybeObject* maybe_new_descriptors = descriptors->CopyInsert( |
2062 &desc, | 2076 &desc, |
2063 KEEP_TRANSITIONS); | 2077 KEEP_TRANSITIONS); |
2064 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { | 2078 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { |
2065 return maybe_new_descriptors; | 2079 return maybe_new_descriptors; |
2066 } | 2080 } |
2067 descriptors = DescriptorArray::cast(new_descriptors); | 2081 descriptors = DescriptorArray::cast(new_descriptors); |
2068 set_instance_descriptors(descriptors); | 2082 current_map->set_instance_descriptors(descriptors); |
2069 } | 2083 } |
2070 | 2084 |
2071 return new_map; | 2085 return new_map; |
2072 } | 2086 } |
2073 | 2087 |
2074 | 2088 |
2075 void JSObject::LocalLookupRealNamedProperty(String* name, | 2089 void JSObject::LocalLookupRealNamedProperty(String* name, |
2076 LookupResult* result) { | 2090 LookupResult* result) { |
2077 if (IsJSGlobalProxy()) { | 2091 if (IsJSGlobalProxy()) { |
2078 Object* proto = GetPrototype(); | 2092 Object* proto = GetPrototype(); |
(...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2966 } | 2980 } |
2967 } | 2981 } |
2968 | 2982 |
2969 // Switch to using the dictionary as the backing storage for elements. | 2983 // Switch to using the dictionary as the backing storage for elements. |
2970 if (is_arguments) { | 2984 if (is_arguments) { |
2971 FixedArray::cast(elements())->set(1, dictionary); | 2985 FixedArray::cast(elements())->set(1, dictionary); |
2972 } else { | 2986 } else { |
2973 // Set the new map first to satify the elements type assert in | 2987 // Set the new map first to satify the elements type assert in |
2974 // set_elements(). | 2988 // set_elements(). |
2975 Object* new_map; | 2989 Object* new_map; |
2976 MaybeObject* maybe = map()->GetSlowElementsMap(); | 2990 MaybeObject* maybe = GetElementsTransitionMap(DICTIONARY_ELEMENTS); |
2977 if (!maybe->ToObject(&new_map)) return maybe; | 2991 if (!maybe->ToObject(&new_map)) return maybe; |
2978 set_map(Map::cast(new_map)); | 2992 set_map(Map::cast(new_map)); |
2979 set_elements(dictionary); | 2993 set_elements(dictionary); |
2980 } | 2994 } |
2981 | 2995 |
2982 old_map->isolate()->counters()->elements_to_dictionary()->Increment(); | 2996 old_map->isolate()->counters()->elements_to_dictionary()->Increment(); |
2983 | 2997 |
2984 #ifdef DEBUG | 2998 #ifdef DEBUG |
2985 if (FLAG_trace_normalization) { | 2999 if (FLAG_trace_normalization) { |
2986 PrintF("Object elements have been normalized:\n"); | 3000 PrintF("Object elements have been normalized:\n"); |
(...skipping 4287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7274 { Object* object; | 7288 { Object* object; |
7275 MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); | 7289 MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); |
7276 if (!maybe->ToObject(&object)) return maybe; | 7290 if (!maybe->ToObject(&object)) return maybe; |
7277 new_elements = FixedArray::cast(object); | 7291 new_elements = FixedArray::cast(object); |
7278 } | 7292 } |
7279 | 7293 |
7280 // Find the new map to use for this object if there is a map change. | 7294 // Find the new map to use for this object if there is a map change. |
7281 Map* new_map = NULL; | 7295 Map* new_map = NULL; |
7282 if (elements()->map() != heap->non_strict_arguments_elements_map()) { | 7296 if (elements()->map() != heap->non_strict_arguments_elements_map()) { |
7283 Object* object; | 7297 Object* object; |
7284 MaybeObject* maybe = map()->GetFastElementsMap(); | 7298 MaybeObject* maybe = GetElementsTransitionMap(FAST_ELEMENTS); |
7285 if (!maybe->ToObject(&object)) return maybe; | 7299 if (!maybe->ToObject(&object)) return maybe; |
7286 new_map = Map::cast(object); | 7300 new_map = Map::cast(object); |
7287 } | 7301 } |
7288 | 7302 |
7289 switch (GetElementsKind()) { | 7303 switch (GetElementsKind()) { |
7290 case FAST_ELEMENTS: { | 7304 case FAST_ELEMENTS: { |
7291 AssertNoAllocation no_gc; | 7305 AssertNoAllocation no_gc; |
7292 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); | 7306 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); |
7293 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode); | 7307 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode); |
7294 set_map(new_map); | 7308 set_map(new_map); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7377 // We should never end in here with a pixel or external array. | 7391 // We should never end in here with a pixel or external array. |
7378 ASSERT(!HasExternalArrayElements()); | 7392 ASSERT(!HasExternalArrayElements()); |
7379 | 7393 |
7380 Object* obj; | 7394 Object* obj; |
7381 { MaybeObject* maybe_obj = | 7395 { MaybeObject* maybe_obj = |
7382 heap->AllocateUninitializedFixedDoubleArray(capacity); | 7396 heap->AllocateUninitializedFixedDoubleArray(capacity); |
7383 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7397 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
7384 } | 7398 } |
7385 FixedDoubleArray* elems = FixedDoubleArray::cast(obj); | 7399 FixedDoubleArray* elems = FixedDoubleArray::cast(obj); |
7386 | 7400 |
7387 { MaybeObject* maybe_obj = map()->GetFastDoubleElementsMap(); | 7401 { MaybeObject* maybe_obj = |
| 7402 GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS); |
7388 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7403 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
7389 } | 7404 } |
7390 Map* new_map = Map::cast(obj); | 7405 Map* new_map = Map::cast(obj); |
7391 | 7406 |
7392 AssertNoAllocation no_gc; | 7407 AssertNoAllocation no_gc; |
7393 switch (GetElementsKind()) { | 7408 switch (GetElementsKind()) { |
7394 case FAST_ELEMENTS: { | 7409 case FAST_ELEMENTS: { |
7395 elems->Initialize(FixedArray::cast(elements())); | 7410 elems->Initialize(FixedArray::cast(elements())); |
7396 break; | 7411 break; |
7397 } | 7412 } |
(...skipping 2736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10134 // Convert to fast elements containing only the existing properties. | 10149 // Convert to fast elements containing only the existing properties. |
10135 // Ordering is irrelevant, since we are going to sort anyway. | 10150 // Ordering is irrelevant, since we are going to sort anyway. |
10136 NumberDictionary* dict = element_dictionary(); | 10151 NumberDictionary* dict = element_dictionary(); |
10137 if (IsJSArray() || dict->requires_slow_elements() || | 10152 if (IsJSArray() || dict->requires_slow_elements() || |
10138 dict->max_number_key() >= limit) { | 10153 dict->max_number_key() >= limit) { |
10139 return PrepareSlowElementsForSort(limit); | 10154 return PrepareSlowElementsForSort(limit); |
10140 } | 10155 } |
10141 // Convert to fast elements. | 10156 // Convert to fast elements. |
10142 | 10157 |
10143 Object* obj; | 10158 Object* obj; |
10144 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); | 10159 { MaybeObject* maybe_obj = GetElementsTransitionMap(FAST_ELEMENTS); |
10145 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 10160 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
10146 } | 10161 } |
10147 Map* new_map = Map::cast(obj); | 10162 Map* new_map = Map::cast(obj); |
10148 | 10163 |
10149 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; | 10164 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; |
10150 Object* new_array; | 10165 Object* new_array; |
10151 { MaybeObject* maybe_new_array = | 10166 { MaybeObject* maybe_new_array = |
10152 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); | 10167 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); |
10153 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; | 10168 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; |
10154 } | 10169 } |
(...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11591 if (break_point_objects()->IsUndefined()) return 0; | 11606 if (break_point_objects()->IsUndefined()) return 0; |
11592 // Single break point. | 11607 // Single break point. |
11593 if (!break_point_objects()->IsFixedArray()) return 1; | 11608 if (!break_point_objects()->IsFixedArray()) return 1; |
11594 // Multiple break points. | 11609 // Multiple break points. |
11595 return FixedArray::cast(break_point_objects())->length(); | 11610 return FixedArray::cast(break_point_objects())->length(); |
11596 } | 11611 } |
11597 #endif | 11612 #endif |
11598 | 11613 |
11599 | 11614 |
11600 } } // namespace v8::internal | 11615 } } // namespace v8::internal |
OLD | NEW |