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

Side by Side Diff: src/objects.cc

Issue 8017003: Cache multiple ElementsKind map transition per map. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 3 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') | src/objects-printer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-printer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698