Skip to content
This repository
Browse code

Fixing bugs in promotion of elements transitions (r1175). - Fixed inv…

…alid memory access when reading enum-cache from descriptor array with elements transitions but 0 real descriptors. - Fixed infinite recursion in the intrusive map iterator when visiting elements transitions. - Properly cached non-fastmode elements transitions.

Review URL: https://chromiumcodereview.appspot.com/10565030

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@11841 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
  • Loading branch information...
commit 8a6ef65c2c8b39a040c6566bc91841989803631d 1 parent 7282ce9
authored June 18, 2012 piscisaureus committed June 19, 2012
98  deps/v8/src/objects.cc
@@ -2243,7 +2243,12 @@ Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
2243 2243
 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
2244 2244
   Map* current_map = map;
2245 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 2252
   for (; index < to_index; ++index) {
2248 2253
     Map* next_map = current_map->elements_transition_map();
2249 2254
     if (next_map == NULL) {
@@ -2251,27 +2256,36 @@ static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
2251 2256
     }
2252 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 2268
   return current_map;
2256 2269
 }
2257 2270
 
2258 2271
 
2259 2272
 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
2260  
-  if (this->instance_descriptors()->MayContainTransitions() &&
2261  
-      IsMoreGeneralElementsKindTransition(this->elements_kind(), to_kind)) {
2262  
-    Map* to_map = FindClosestElementsTransition(this, to_kind);
2263  
-    if (to_map->elements_kind() == to_kind) {
2264  
-      return to_map;
2265  
-    }
2266  
-  }
  2273
+  Map* to_map = FindClosestElementsTransition(this, to_kind);
  2274
+  if (to_map->elements_kind() == to_kind) return to_map;
2267 2275
   return NULL;
2268 2276
 }
2269 2277
 
2270 2278
 
2271 2279
 MaybeObject* Map::CreateNextElementsTransition(ElementsKind next_kind) {
2272  
-    ASSERT(elements_transition_map() == NULL);
2273  
-    ASSERT(GetSequenceIndexFromFastElementsKind(elements_kind()) ==
2274  
-           (GetSequenceIndexFromFastElementsKind(next_kind) - 1));
  2280
+    ASSERT(elements_transition_map() == NULL ||
  2281
+        ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
  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 2290
     Map* next_map;
2277 2291
     MaybeObject* maybe_next_map =
@@ -2287,19 +2301,31 @@ MaybeObject* Map::CreateNextElementsTransition(ElementsKind next_kind) {
2287 2301
 
2288 2302
 static MaybeObject* AddMissingElementsTransitions(Map* map,
2289 2303
                                                   ElementsKind to_kind) {
2290  
-  int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()) + 1;
2291  
-  int to_index = GetSequenceIndexFromFastElementsKind(to_kind);
  2304
+  ASSERT(IsFastElementsKind(map->elements_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 2310
   ASSERT(index <= to_index);
2293 2311
 
2294 2312
   Map* current_map = map;
2295 2313
 
2296  
-  for (; index <= to_index; ++index) {
2297  
-      ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index);
  2314
+  for (; index < to_index; ++index) {
  2315
+      ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index + 1);
2298 2316
       MaybeObject* maybe_next_map =
2299 2317
           current_map->CreateNextElementsTransition(next_kind);
2300 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 2329
   ASSERT(current_map->elements_kind() == to_kind);
2304 2330
   return current_map;
2305 2331
 }
@@ -2345,10 +2371,14 @@ MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) {
2345 2371
       // non-matching element transition.
2346 2372
       (global_context->object_function()->map() != map()) &&
2347 2373
       !start_map->IsUndefined() && !start_map->is_shared() &&
2348  
-      // Only store fast element maps in ascending generality.
2349  
-      IsTransitionableFastElementsKind(from_kind) &&
2350  
-      IsFastElementsKind(to_kind) &&
2351  
-      IsMoreGeneralElementsKindTransition(from_kind, to_kind);
  2374
+      IsFastElementsKind(from_kind);
  2375
+
  2376
+  // Only store fast element maps in ascending generality.
  2377
+  if (IsFastElementsKind(to_kind)) {
  2378
+    allow_store_transition &=
  2379
+        IsTransitionableFastElementsKind(from_kind) &&
  2380
+        IsMoreGeneralElementsKindTransition(from_kind, to_kind);
  2381
+  }
2352 2382
 
2353 2383
   if (!allow_store_transition) {
2354 2384
     // Create a new free-floating map only if we are not allowed to store it.
@@ -5063,7 +5093,7 @@ class IntrusiveMapTransitionIterator {
5063 5093
     if (index == descriptor_array_->number_of_descriptors()) {
5064 5094
       Map* elements_transition = descriptor_array_->elements_transition_map();
5065 5095
       if (elements_transition != NULL) {
5066  
-        *DescriptorArrayHeader() = Smi::FromInt(index + 1);
  5096
+        *DescriptorArrayHeader() = Smi::FromInt(raw_index + 2);
5067 5097
         return elements_transition;
5068 5098
       }
5069 5099
     }
@@ -5765,24 +5795,18 @@ MaybeObject* DescriptorArray::Allocate(int number_of_descriptors,
5765 5795
   Heap* heap = Isolate::Current()->heap();
5766 5796
   // Do not use DescriptorArray::cast on incomplete object.
5767 5797
   FixedArray* result;
5768  
-  if (number_of_descriptors == 0) {
5769  
-    if (shared_mode == MAY_BE_SHARED) {
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));
  5798
+  if (number_of_descriptors == 0 && shared_mode == MAY_BE_SHARED) {
  5799
+    return heap->empty_descriptor_array();
  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;
5784 5805
   }
  5806
+
5785 5807
   result->set(kBitField3StorageIndex, Smi::FromInt(0));
  5808
+  result->set(kEnumerationIndexIndex,
  5809
+              Smi::FromInt(PropertyDetails::kInitialIndex));
5786 5810
   result->set(kTransitionsIndex, Smi::FromInt(0));
5787 5811
   return result;
5788 5812
 }
15  deps/v8/src/objects.h
@@ -2441,9 +2441,7 @@ class DescriptorArray: public FixedArray {
2441 2441
 
2442 2442
   // Returns the number of descriptors in the array.
2443 2443
   int number_of_descriptors() {
2444  
-    ASSERT(length() > kFirstIndex ||
2445  
-           length() == kTransitionsIndex ||
2446  
-           IsEmpty());
  2444
+    ASSERT(length() >= kFirstIndex || IsEmpty());
2447 2445
     int len = length();
2448 2446
     return len <= kFirstIndex ? 0 : (len - kFirstIndex) / kDescriptorSize;
2449 2447
   }
@@ -2615,8 +2613,8 @@ class DescriptorArray: public FixedArray {
2615 2613
   static const int kNotFound = -1;
2616 2614
 
2617 2615
   static const int kBitField3StorageIndex = 0;
2618  
-  static const int kTransitionsIndex = 1;
2619  
-  static const int kEnumerationIndexIndex = 2;
  2616
+  static const int kEnumerationIndexIndex = 1;
  2617
+  static const int kTransitionsIndex = 2;
2620 2618
   static const int kFirstIndex = 3;
2621 2619
 
2622 2620
   // The length of the "bridge" to the enum cache.
@@ -2627,9 +2625,10 @@ class DescriptorArray: public FixedArray {
2627 2625
 
2628 2626
   // Layout description.
2629 2627
   static const int kBitField3StorageOffset = FixedArray::kHeaderSize;
2630  
-  static const int kTransitionsOffset = kBitField3StorageOffset + kPointerSize;
2631  
-  static const int kEnumerationIndexOffset = kTransitionsOffset + kPointerSize;
2632  
-  static const int kFirstOffset = kEnumerationIndexOffset + kPointerSize;
  2628
+  static const int kEnumerationIndexOffset =
  2629
+      kBitField3StorageOffset + kPointerSize;
  2630
+  static const int kTransitionsOffset = kEnumerationIndexOffset + kPointerSize;
  2631
+  static const int kFirstOffset = kTransitionsOffset + kPointerSize;
2633 2632
 
2634 2633
   // Layout description for the bridge array.
2635 2634
   static const int kEnumCacheBridgeEnumOffset = FixedArray::kHeaderSize;

0 notes on commit 8a6ef65

Please sign in to comment.
Something went wrong with that request. Please try again.