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

Side by Side Diff: src/objects.cc

Issue 10565030: Fixing bugs in promotion of elements transitions (r1175). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 6 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') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 2225 matching lines...) Expand 10 before | Expand all | Expand 10 after
2236 current_map = maybe_transitioned_map; 2236 current_map = maybe_transitioned_map;
2237 } 2237 }
2238 } 2238 }
2239 return transitioned_map; 2239 return transitioned_map;
2240 } 2240 }
2241 2241
2242 2242
2243 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) { 2243 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
2244 Map* current_map = map; 2244 Map* current_map = map;
2245 int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()); 2245 int index = GetSequenceIndexFromFastElementsKind(map->elements_kind());
2246 int to_index = GetSequenceIndexFromFastElementsKind(to_kind); 2246 int to_index = IsFastElementsKind(to_kind)
2247 ? GetSequenceIndexFromFastElementsKind(to_kind)
2248 : GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
2249
2250 ASSERT(index <= to_index);
2251
2247 for (; index < to_index; ++index) { 2252 for (; index < to_index; ++index) {
2248 Map* next_map = current_map->elements_transition_map(); 2253 Map* next_map = current_map->elements_transition_map();
2249 if (next_map == NULL) { 2254 if (next_map == NULL) {
2250 return current_map; 2255 return current_map;
2251 } 2256 }
2252 current_map = next_map; 2257 current_map = next_map;
2253 } 2258 }
2254 ASSERT(current_map->elements_kind() == to_kind); 2259 if (!IsFastElementsKind(to_kind)) {
2260 Map* next_map = current_map->elements_transition_map();
2261 if (next_map != NULL && next_map->elements_kind() == to_kind) {
2262 return next_map;
2263 }
2264 ASSERT(current_map->elements_kind() == TERMINAL_FAST_ELEMENTS_KIND);
2265 } else {
2266 ASSERT(current_map->elements_kind() == to_kind);
2267 }
2255 return current_map; 2268 return current_map;
2256 } 2269 }
2257 2270
2258 2271
2259 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { 2272 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
2260 if (this->instance_descriptors()->MayContainTransitions() && 2273 Map* to_map = FindClosestElementsTransition(this, to_kind);
2261 IsMoreGeneralElementsKindTransition(this->elements_kind(), to_kind)) { 2274 if (to_map->elements_kind() == to_kind) return to_map;
2262 Map* to_map = FindClosestElementsTransition(this, to_kind);
2263 if (to_map->elements_kind() == to_kind) {
2264 return to_map;
2265 }
2266 }
2267 return NULL; 2275 return NULL;
2268 } 2276 }
2269 2277
2270 2278
2271 MaybeObject* Map::CreateNextElementsTransition(ElementsKind next_kind) { 2279 MaybeObject* Map::CreateNextElementsTransition(ElementsKind next_kind) {
2272 ASSERT(elements_transition_map() == NULL); 2280 ASSERT(elements_transition_map() == NULL ||
2273 ASSERT(GetSequenceIndexFromFastElementsKind(elements_kind()) == 2281 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
2274 (GetSequenceIndexFromFastElementsKind(next_kind) - 1)); 2282 IsExternalArrayElementsKind(
2283 elements_transition_map()->elements_kind())) &&
2284 (next_kind == DICTIONARY_ELEMENTS ||
2285 IsExternalArrayElementsKind(next_kind))));
2286 ASSERT(!IsFastElementsKind(next_kind) ||
2287 IsMoreGeneralElementsKindTransition(elements_kind(), next_kind));
2288 ASSERT(next_kind != elements_kind());
2275 2289
2276 Map* next_map; 2290 Map* next_map;
2277 MaybeObject* maybe_next_map = 2291 MaybeObject* maybe_next_map =
2278 this->CopyDropTransitions(DescriptorArray::CANNOT_BE_SHARED); 2292 this->CopyDropTransitions(DescriptorArray::CANNOT_BE_SHARED);
2279 if (!maybe_next_map->To(&next_map)) return maybe_next_map; 2293 if (!maybe_next_map->To(&next_map)) return maybe_next_map;
2280 2294
2281 next_map->set_elements_kind(next_kind); 2295 next_map->set_elements_kind(next_kind);
2282 next_map->SetBackPointer(this); 2296 next_map->SetBackPointer(this);
2283 this->set_elements_transition_map(next_map); 2297 this->set_elements_transition_map(next_map);
2284 return next_map; 2298 return next_map;
2285 } 2299 }
2286 2300
2287 2301
2288 static MaybeObject* AddMissingElementsTransitions(Map* map, 2302 static MaybeObject* AddMissingElementsTransitions(Map* map,
2289 ElementsKind to_kind) { 2303 ElementsKind to_kind) {
2290 int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()) + 1; 2304 ASSERT(IsFastElementsKind(map->elements_kind()));
2291 int to_index = GetSequenceIndexFromFastElementsKind(to_kind); 2305 int index = GetSequenceIndexFromFastElementsKind(map->elements_kind());
2306 int to_index = IsFastElementsKind(to_kind)
2307 ? GetSequenceIndexFromFastElementsKind(to_kind)
2308 : GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
2309
2292 ASSERT(index <= to_index); 2310 ASSERT(index <= to_index);
2293 2311
2294 Map* current_map = map; 2312 Map* current_map = map;
2295 2313
2296 for (; index <= to_index; ++index) { 2314 for (; index < to_index; ++index) {
2297 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index); 2315 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index + 1);
2298 MaybeObject* maybe_next_map = 2316 MaybeObject* maybe_next_map =
2299 current_map->CreateNextElementsTransition(next_kind); 2317 current_map->CreateNextElementsTransition(next_kind);
2300 if (!maybe_next_map->To(&current_map)) return maybe_next_map; 2318 if (!maybe_next_map->To(&current_map)) return maybe_next_map;
2301 } 2319 }
2302 2320
2321 // In case we are exiting the fast elements kind system, just add the map in
2322 // the end.
2323 if (!IsFastElementsKind(to_kind)) {
2324 MaybeObject* maybe_next_map =
2325 current_map->CreateNextElementsTransition(to_kind);
2326 if (!maybe_next_map->To(&current_map)) return maybe_next_map;
2327 }
2328
2303 ASSERT(current_map->elements_kind() == to_kind); 2329 ASSERT(current_map->elements_kind() == to_kind);
2304 return current_map; 2330 return current_map;
2305 } 2331 }
2306 2332
2307 2333
2308 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, 2334 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
2309 ElementsKind to_kind) { 2335 ElementsKind to_kind) {
2310 Isolate* isolate = object->GetIsolate(); 2336 Isolate* isolate = object->GetIsolate();
2311 CALL_HEAP_FUNCTION(isolate, 2337 CALL_HEAP_FUNCTION(isolate,
2312 object->GetElementsTransitionMap(isolate, to_kind), 2338 object->GetElementsTransitionMap(isolate, to_kind),
(...skipping 25 matching lines...) Expand all
2338 return start_map; 2364 return start_map;
2339 } 2365 }
2340 2366
2341 Context* global_context = GetIsolate()->context()->global_context(); 2367 Context* global_context = GetIsolate()->context()->global_context();
2342 bool allow_store_transition = 2368 bool allow_store_transition =
2343 // Only remember the map transition if the object's map is NOT equal to 2369 // Only remember the map transition if the object's map is NOT equal to
2344 // the global object_function's map and there is not an already existing 2370 // the global object_function's map and there is not an already existing
2345 // non-matching element transition. 2371 // non-matching element transition.
2346 (global_context->object_function()->map() != map()) && 2372 (global_context->object_function()->map() != map()) &&
2347 !start_map->IsUndefined() && !start_map->is_shared() && 2373 !start_map->IsUndefined() && !start_map->is_shared() &&
2348 // Only store fast element maps in ascending generality. 2374 IsFastElementsKind(from_kind);
2349 IsTransitionableFastElementsKind(from_kind) && 2375
2350 IsFastElementsKind(to_kind) && 2376 // Only store fast element maps in ascending generality.
2351 IsMoreGeneralElementsKindTransition(from_kind, to_kind); 2377 if (IsFastElementsKind(to_kind)) {
2378 allow_store_transition &=
2379 IsTransitionableFastElementsKind(from_kind) &&
2380 IsMoreGeneralElementsKindTransition(from_kind, to_kind);
2381 }
2352 2382
2353 if (!allow_store_transition) { 2383 if (!allow_store_transition) {
2354 // Create a new free-floating map only if we are not allowed to store it. 2384 // Create a new free-floating map only if we are not allowed to store it.
2355 Map* new_map = NULL; 2385 Map* new_map = NULL;
2356 MaybeObject* maybe_new_map = 2386 MaybeObject* maybe_new_map =
2357 start_map->CopyDropTransitions(DescriptorArray::MAY_BE_SHARED); 2387 start_map->CopyDropTransitions(DescriptorArray::MAY_BE_SHARED);
2358 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 2388 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
2359 new_map->set_elements_kind(to_kind); 2389 new_map->set_elements_kind(to_kind);
2360 return new_map; 2390 return new_map;
2361 } 2391 }
(...skipping 2694 matching lines...) Expand 10 before | Expand all | Expand 10 after
5056 case NULL_DESCRIPTOR: 5086 case NULL_DESCRIPTOR:
5057 // We definitely have no map transition. 5087 // We definitely have no map transition.
5058 raw_index += 2; 5088 raw_index += 2;
5059 ++index; 5089 ++index;
5060 break; 5090 break;
5061 } 5091 }
5062 } 5092 }
5063 if (index == descriptor_array_->number_of_descriptors()) { 5093 if (index == descriptor_array_->number_of_descriptors()) {
5064 Map* elements_transition = descriptor_array_->elements_transition_map(); 5094 Map* elements_transition = descriptor_array_->elements_transition_map();
5065 if (elements_transition != NULL) { 5095 if (elements_transition != NULL) {
5066 *DescriptorArrayHeader() = Smi::FromInt(index + 1); 5096 *DescriptorArrayHeader() = Smi::FromInt(raw_index + 2);
5067 return elements_transition; 5097 return elements_transition;
5068 } 5098 }
5069 } 5099 }
5070 *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map(); 5100 *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map();
5071 return NULL; 5101 return NULL;
5072 } 5102 }
5073 5103
5074 private: 5104 private:
5075 Object** DescriptorArrayHeader() { 5105 Object** DescriptorArrayHeader() {
5076 return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset); 5106 return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset);
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after
5758 return true; 5788 return true;
5759 } 5789 }
5760 #endif 5790 #endif
5761 5791
5762 5792
5763 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, 5793 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors,
5764 SharedMode shared_mode) { 5794 SharedMode shared_mode) {
5765 Heap* heap = Isolate::Current()->heap(); 5795 Heap* heap = Isolate::Current()->heap();
5766 // Do not use DescriptorArray::cast on incomplete object. 5796 // Do not use DescriptorArray::cast on incomplete object.
5767 FixedArray* result; 5797 FixedArray* result;
5768 if (number_of_descriptors == 0) { 5798 if (number_of_descriptors == 0 && shared_mode == MAY_BE_SHARED) {
5769 if (shared_mode == MAY_BE_SHARED) { 5799 return heap->empty_descriptor_array();
5770 return heap->empty_descriptor_array();
5771 }
5772 { MaybeObject* maybe_array =
5773 heap->AllocateFixedArray(kTransitionsIndex + 1);
5774 if (!maybe_array->To(&result)) return maybe_array;
5775 }
5776 } else {
5777 // Allocate the array of keys.
5778 { MaybeObject* maybe_array =
5779 heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors));
5780 if (!maybe_array->To(&result)) return maybe_array;
5781 }
5782 result->set(kEnumerationIndexIndex,
5783 Smi::FromInt(PropertyDetails::kInitialIndex));
5784 } 5800 }
5801 // Allocate the array of keys.
5802 { MaybeObject* maybe_array =
5803 heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors));
5804 if (!maybe_array->To(&result)) return maybe_array;
5805 }
5806
5785 result->set(kBitField3StorageIndex, Smi::FromInt(0)); 5807 result->set(kBitField3StorageIndex, Smi::FromInt(0));
5808 result->set(kEnumerationIndexIndex,
5809 Smi::FromInt(PropertyDetails::kInitialIndex));
5786 result->set(kTransitionsIndex, Smi::FromInt(0)); 5810 result->set(kTransitionsIndex, Smi::FromInt(0));
5787 return result; 5811 return result;
5788 } 5812 }
5789 5813
5790 5814
5791 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, 5815 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
5792 FixedArray* new_cache, 5816 FixedArray* new_cache,
5793 Object* new_index_cache) { 5817 Object* new_index_cache) {
5794 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); 5818 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
5795 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); 5819 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
(...skipping 7454 matching lines...) Expand 10 before | Expand all | Expand 10 after
13250 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13274 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13251 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13275 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13252 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13276 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13253 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13277 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13254 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13278 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13255 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13279 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13256 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13280 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13257 } 13281 }
13258 13282
13259 } } // namespace v8::internal 13283 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698