Chromium Code Reviews| 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 |