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 2004 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2015 cache->Update(descriptors, name, number); | 2015 cache->Update(descriptors, name, number); |
2016 } | 2016 } |
2017 if (number != DescriptorArray::kNotFound) { | 2017 if (number != DescriptorArray::kNotFound) { |
2018 result->DescriptorResult(holder, descriptors->GetDetails(number), number); | 2018 result->DescriptorResult(holder, descriptors->GetDetails(number), number); |
2019 } else { | 2019 } else { |
2020 result->NotFound(); | 2020 result->NotFound(); |
2021 } | 2021 } |
2022 } | 2022 } |
2023 | 2023 |
2024 | 2024 |
2025 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, | |
2026 ElementsKind elements_kind) { | |
2027 if (descriptor_contents->IsMap()) { | |
2028 Map* map = Map::cast(descriptor_contents); | |
2029 if (map->elements_kind() == elements_kind) { | |
2030 return map; | |
2031 } | |
2032 return NULL; | |
2033 } | |
2034 | |
2035 FixedArray* map_array = FixedArray::cast(descriptor_contents); | |
2036 for (int i = 0; i < map_array->length(); ++i) { | |
2037 Map* current_map = Map::cast(map_array->get(i)); | |
2038 if (current_map->elements_kind() == elements_kind) { | |
2039 return current_map; | |
2040 } | |
2041 } | |
2042 | |
2043 return NULL; | |
2044 } | |
2045 | |
2046 | |
2047 static MaybeObject* AddElementsTransitionMapToDescriptor( | |
2048 Object* descriptor_contents, | |
2049 Map* new_map) { | |
2050 // Nothing was in the descriptor for an ELEMENTS_TRANSITION, | |
2051 // simply add the map. | |
2052 if (descriptor_contents == NULL) { | |
2053 return new_map; | |
2054 } | |
2055 | |
2056 // There was already a map in the descriptor, create a 2-element FixedArray | |
2057 // to contain the existing map plus the new one. | |
2058 FixedArray* new_array; | |
2059 Heap* heap = new_map->GetHeap(); | |
2060 if (descriptor_contents->IsMap()) { | |
2061 MaybeObject* maybe_new_array = heap->AllocateFixedArray(2); | |
2062 if (!maybe_new_array->To<FixedArray>(&new_array)) { | |
2063 return maybe_new_array; | |
2064 } | |
2065 new_array->set(0, descriptor_contents); | |
2066 new_array->set(1, new_map); | |
2067 return new_array; | |
2068 } | |
2069 | |
2070 // The descriptor already contained a list of maps for different ElementKinds | |
2071 // of ELEMENTS_TRANSITION, create a FixedArray to hold the existing maps plus | |
2072 // the new one and fill it it. | |
2073 FixedArray* array = FixedArray::cast(descriptor_contents); | |
2074 MaybeObject* maybe_new_array = | |
2075 heap->AllocateFixedArray(array->length() + 1); | |
2076 if (!maybe_new_array->To<FixedArray>(&new_array)) { | |
2077 return maybe_new_array; | |
2078 } | |
2079 int i = 0; | |
2080 while (i < array->length()) { | |
2081 new_array->set(i, FixedArray::cast(descriptor_contents)->get(i)); | |
Jakob Kummerow
2011/09/23 12:12:28
Simplification: s/FixedArray::cast(descriptor_cont
danno
2011/09/23 13:33:45
Done.
| |
2082 ++i; | |
2083 } | |
2084 new_array->set(i, new_map); | |
2085 return new_array; | |
2086 } | |
2087 | |
2088 | |
2025 MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind elements_kind) { | 2089 MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind elements_kind) { |
2026 Heap* current_heap = GetHeap(); | 2090 Heap* current_heap = GetHeap(); |
2027 Map* current_map = map(); | 2091 Map* current_map = map(); |
2028 DescriptorArray* descriptors = current_map->instance_descriptors(); | 2092 DescriptorArray* descriptors = current_map->instance_descriptors(); |
2029 String* elements_transition_sentinel_name = current_heap->empty_symbol(); | 2093 String* elements_transition_sentinel_name = current_heap->empty_symbol(); |
2030 | 2094 |
2031 if (current_map->elements_kind() == elements_kind) return current_map; | 2095 if (current_map->elements_kind() == elements_kind) return current_map; |
2032 | 2096 |
2033 // Only objects with FastProperties can have DescriptorArrays and can track | 2097 // Only objects with FastProperties can have DescriptorArrays and can track |
2034 // element-related maps. Also don't add descriptors to maps that are shared. | 2098 // element-related maps. Also don't add descriptors to maps that are shared. |
2035 bool safe_to_add_transition = HasFastProperties() && | 2099 bool safe_to_add_transition = HasFastProperties() && |
2036 !current_map->IsUndefined() && | 2100 !current_map->IsUndefined() && |
2037 !current_map->is_shared(); | 2101 !current_map->is_shared(); |
2038 | 2102 |
2039 // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps cause by objects | 2103 // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps cause by objects |
2040 // with elements that switch back and forth between dictionary and fast | 2104 // with elements that switch back and forth between dictionary and fast |
2041 // element mode. | 2105 // element mode. |
2042 if ((current_map->elements_kind() == DICTIONARY_ELEMENTS && | 2106 if ((current_map->elements_kind() == DICTIONARY_ELEMENTS && |
2043 elements_kind == FAST_ELEMENTS)) { | 2107 elements_kind == FAST_ELEMENTS)) { |
2044 safe_to_add_transition = false; | 2108 safe_to_add_transition = false; |
2045 } | 2109 } |
2046 | 2110 |
2111 Object* descriptor_contents = NULL; | |
2047 if (safe_to_add_transition) { | 2112 if (safe_to_add_transition) { |
2048 // It's only safe to manipulate the descriptor array if it would be | 2113 // It's only safe to manipulate the descriptor array if it would be |
2049 // safe to add a transition. | 2114 // safe to add a transition. |
2050 | 2115 |
2051 // Check if the elements transition already exists. | 2116 // Check if the elements transition already exists. |
2052 DescriptorLookupCache* cache = | 2117 DescriptorLookupCache* cache = |
2053 current_heap->isolate()->descriptor_lookup_cache(); | 2118 current_heap->isolate()->descriptor_lookup_cache(); |
2054 int index = cache->Lookup(descriptors, elements_transition_sentinel_name); | 2119 int index = cache->Lookup(descriptors, elements_transition_sentinel_name); |
2055 if (index == DescriptorLookupCache::kAbsent) { | 2120 if (index == DescriptorLookupCache::kAbsent) { |
2056 index = descriptors->Search(elements_transition_sentinel_name); | 2121 index = descriptors->Search(elements_transition_sentinel_name); |
2057 cache->Update(descriptors, | 2122 cache->Update(descriptors, |
2058 elements_transition_sentinel_name, | 2123 elements_transition_sentinel_name, |
2059 index); | 2124 index); |
2060 } | 2125 } |
2061 | 2126 |
2062 // If the transition already exists, check the type. If there is a match, | 2127 // If the transition already exists, check the type. If there is a match, |
2063 // return it. | 2128 // return it. |
2064 if (index != DescriptorArray::kNotFound) { | 2129 if (index != DescriptorArray::kNotFound) { |
2065 PropertyDetails details(PropertyDetails(descriptors->GetDetails(index))); | 2130 PropertyDetails details(PropertyDetails(descriptors->GetDetails(index))); |
2066 if (details.type() == ELEMENTS_TRANSITION && | 2131 if (details.type() == ELEMENTS_TRANSITION) { |
2067 details.elements_kind() == elements_kind) { | 2132 descriptor_contents = descriptors->GetValue(index); |
2068 return descriptors->GetValue(index); | 2133 Map* maybe_transition_map = |
2069 } else { | 2134 GetElementsTransitionMapFromDescriptor(descriptor_contents, |
2070 safe_to_add_transition = false; | 2135 elements_kind); |
2136 if (maybe_transition_map) return maybe_transition_map; | |
2071 } | 2137 } |
2138 safe_to_add_transition = false; | |
2072 } | 2139 } |
2073 } | 2140 } |
2074 | 2141 |
2075 // No transition to an existing map for the given ElementsKind. Make a new | 2142 // No transition to an existing map for the given ElementsKind. Make a new |
2076 // one. | 2143 // one. |
2077 Object* obj; | 2144 Object* obj; |
2078 { MaybeObject* maybe_map = current_map->CopyDropTransitions(); | 2145 { MaybeObject* maybe_map = current_map->CopyDropTransitions(); |
2079 if (!maybe_map->ToObject(&obj)) return maybe_map; | 2146 if (!maybe_map->ToObject(&obj)) return maybe_map; |
2080 } | 2147 } |
2081 Map* new_map = Map::cast(obj); | 2148 Map* new_map = Map::cast(obj); |
2082 | 2149 |
2083 new_map->set_elements_kind(elements_kind); | 2150 new_map->set_elements_kind(elements_kind); |
2084 | 2151 |
2085 // Only remember the map transition if the object's map is NOT equal to the | 2152 // Only remember the map transition if the object's map is NOT equal to the |
2086 // global object_function's map and there is not an already existing | 2153 // global object_function's map and there is not an already existing |
2087 // non-matching element transition. | 2154 // non-matching element transition. |
2088 bool allow_map_transition = | 2155 bool allow_map_transition = safe_to_add_transition; |
2089 safe_to_add_transition && | 2156 //&& |
2090 (GetIsolate()->context()->global_context()->object_function()->map() != | 2157 // (GetIsolate()->context()->global_context()->object_function()->map() != |
2091 map()); | 2158 // map()); |
2092 if (allow_map_transition) { | 2159 if (allow_map_transition) { |
2093 // Allocate new instance descriptors for the old map with map transition. | 2160 MaybeObject* maybe_new_contents = |
2161 AddElementsTransitionMapToDescriptor(descriptor_contents, new_map); | |
2162 Object* new_contents; | |
2163 if (!maybe_new_contents->To<Object>(&new_contents)) { | |
Jakob Kummerow
2011/09/23 12:12:28
Simplification: s/To<Object>/ToObject/
danno
2011/09/23 13:33:45
Done.
| |
2164 return maybe_new_contents; | |
2165 } | |
2166 | |
2094 ElementsTransitionDescriptor desc(elements_transition_sentinel_name, | 2167 ElementsTransitionDescriptor desc(elements_transition_sentinel_name, |
2095 Map::cast(new_map), | 2168 new_contents); |
2096 elements_kind); | |
2097 Object* new_descriptors; | 2169 Object* new_descriptors; |
2098 MaybeObject* maybe_new_descriptors = descriptors->CopyInsert( | 2170 MaybeObject* maybe_new_descriptors = descriptors->CopyInsert( |
2099 &desc, | 2171 &desc, |
2100 KEEP_TRANSITIONS); | 2172 KEEP_TRANSITIONS); |
2101 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { | 2173 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { |
2102 return maybe_new_descriptors; | 2174 return maybe_new_descriptors; |
2103 } | 2175 } |
2104 descriptors = DescriptorArray::cast(new_descriptors); | 2176 descriptors = DescriptorArray::cast(new_descriptors); |
2105 current_map->set_instance_descriptors(descriptors); | 2177 current_map->set_instance_descriptors(descriptors); |
2106 } | 2178 } |
(...skipping 9777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11884 if (break_point_objects()->IsUndefined()) return 0; | 11956 if (break_point_objects()->IsUndefined()) return 0; |
11885 // Single break point. | 11957 // Single break point. |
11886 if (!break_point_objects()->IsFixedArray()) return 1; | 11958 if (!break_point_objects()->IsFixedArray()) return 1; |
11887 // Multiple break points. | 11959 // Multiple break points. |
11888 return FixedArray::cast(break_point_objects())->length(); | 11960 return FixedArray::cast(break_point_objects())->length(); |
11889 } | 11961 } |
11890 #endif | 11962 #endif |
11891 | 11963 |
11892 | 11964 |
11893 } } // namespace v8::internal | 11965 } } // namespace v8::internal |
OLD | NEW |