Remove elements transitions from the transition array.
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 31 Jul 2013 17:08:50 +0000 (17:08 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 31 Jul 2013 17:08:50 +0000 (17:08 +0000)
This is preparatory work for reordering the transition tree. Since elements transitions will be at the root of the transition tree, runtime access to them is slow since we have to walk the transition tree backwards first. Hence remove the optimization that promoted them to a special field, requiring a pointer (mostly NULL) in every non-simple transition array.

R=titzer@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15993 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

include/v8.h
src/heap.cc
src/heap.h
src/objects-debug.cc
src/objects-inl.h
src/objects.cc
src/transitions-inl.h
src/transitions.cc
src/transitions.h

index 6b1815383314046ef429acc68dd43c6c7a489335..a4eae968d3a5f1f4aa3c7e5b3a14b1742153737b 100644 (file)
@@ -5429,7 +5429,7 @@ class Internals {
   static const int kNullValueRootIndex = 7;
   static const int kTrueValueRootIndex = 8;
   static const int kFalseValueRootIndex = 9;
-  static const int kEmptyStringRootIndex = 134;
+  static const int kEmptyStringRootIndex = 135;
 
   static const int kNodeClassIdOffset = 1 * kApiPointerSize;
   static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
index 777661570aaf7d86736695d6a09f9c20d0877988..c2a2707602e88eb60d3d7db3921796d66f0ef3aa 100644 (file)
@@ -3202,6 +3202,11 @@ bool Heap::CreateInitialObjects() {
   }
   set_frozen_symbol(Symbol::cast(obj));
 
+  { MaybeObject* maybe_obj = AllocateSymbol();
+    if (!maybe_obj->ToObject(&obj)) return false;
+  }
+  set_elements_transition_symbol(Symbol::cast(obj));
+
   { MaybeObject* maybe_obj = SeededNumberDictionary::Allocate(this, 0, TENURED);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
index fbe0531014e6c7a7adae10c6ffd03bfde43ff826..de6f55bfaf70f858fac85d597d23cde460099bdb 100644 (file)
@@ -178,7 +178,7 @@ namespace internal {
   V(Smi, last_script_id, LastScriptId)                                         \
   V(Script, empty_script, EmptyScript)                                         \
   V(Smi, real_stack_limit, RealStackLimit)                                     \
-  V(NameDictionary, intrinsic_function_names, IntrinsicFunctionNames)        \
+  V(NameDictionary, intrinsic_function_names, IntrinsicFunctionNames)          \
   V(Smi, arguments_adaptor_deopt_pc_offset, ArgumentsAdaptorDeoptPCOffset)     \
   V(Smi, construct_stub_deopt_pc_offset, ConstructStubDeoptPCOffset)           \
   V(Smi, getter_stub_deopt_pc_offset, GetterStubDeoptPCOffset)                 \
@@ -186,6 +186,7 @@ namespace internal {
   V(JSObject, observation_state, ObservationState)                             \
   V(Map, external_map, ExternalMap)                                            \
   V(Symbol, frozen_symbol, FrozenSymbol)                                       \
+  V(Symbol, elements_transition_symbol, ElementsTransitionSymbol)              \
   V(SeededNumberDictionary, empty_slow_element_dictionary,                     \
       EmptySlowElementDictionary)                                              \
   V(Symbol, observed_symbol, ObservedSymbol)                                   \
index cb5f2b79009d756eebdf14afaa17900acd4eb019..395f95ca7ea98a771ef0af15c282962e9327db53 100644 (file)
@@ -1162,10 +1162,6 @@ static bool CheckOneBackPointer(Map* current_map, Object* target) {
 
 
 bool TransitionArray::IsConsistentWithBackPointers(Map* current_map) {
-  if (HasElementsTransition() &&
-      !CheckOneBackPointer(current_map, elements_transition())) {
-    return false;
-  }
   for (int i = 0; i < number_of_transitions(); ++i) {
     if (!CheckOneBackPointer(current_map, GetTarget(i))) return false;
   }
index 3c70569241e920bfb20ba397b3951d49d21b90a5..128dc6be2810cccfb9c5cc26e1e93e4d969ef0b0 100644 (file)
@@ -4269,7 +4269,8 @@ bool Map::HasTransitionArray() {
 
 
 Map* Map::elements_transition_map() {
-  return transitions()->elements_transition();
+  int index = transitions()->Search(GetHeap()->elements_transition_symbol());
+  return transitions()->GetTarget(index);
 }
 
 
@@ -4300,10 +4301,14 @@ Map* Map::GetTransition(int transition_index) {
 
 
 MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) {
-  MaybeObject* allow_elements = EnsureHasTransitionArray(this);
-  if (allow_elements->IsFailure()) return allow_elements;
-  transitions()->set_elements_transition(transitioned_map);
-  return this;
+  TransitionArray* transitions;
+  MaybeObject* maybe_transitions = AddTransition(
+      GetHeap()->elements_transition_symbol(),
+      transitioned_map,
+      FULL_TRANSITION);
+  if (!maybe_transitions->To(&transitions)) return maybe_transitions;
+  set_transitions(transitions);
+  return transitions;
 }
 
 
index 1fdd478b7f9f55f9a237afbb2d605b706464eead..2e9badbb2aa073a3eb684b201fab60cec913ec68 100644 (file)
@@ -7023,12 +7023,6 @@ class IntrusiveMapTransitionIterator {
       return transition_array_->GetTarget(index);
     }
 
-    if (index == number_of_transitions &&
-        transition_array_->HasElementsTransition()) {
-      Map* elements_transition = transition_array_->elements_transition();
-      *TransitionArrayHeader() = Smi::FromInt(index + 1);
-      return elements_transition;
-    }
     *TransitionArrayHeader() = transition_array_->GetHeap()->fixed_array_map();
     return NULL;
   }
@@ -9145,18 +9139,10 @@ void Map::ClearNonLiveTransitions(Heap* heap) {
     }
   }
 
-  if (t->HasElementsTransition() &&
-      ClearBackPointer(heap, t->elements_transition())) {
-    if (t->elements_transition()->instance_descriptors() == descriptors) {
-      descriptors_owner_died = true;
-    }
-    t->ClearElementsTransition();
-  } else {
-    // If there are no transitions to be cleared, return.
-    // TODO(verwaest) Should be an assert, otherwise back pointers are not
-    // properly cleared.
-    if (transition_index == t->number_of_transitions()) return;
-  }
+  // If there are no transitions to be cleared, return.
+  // TODO(verwaest) Should be an assert, otherwise back pointers are not
+  // properly cleared.
+  if (transition_index == t->number_of_transitions()) return;
 
   int number_of_own_descriptors = NumberOfOwnDescriptors();
 
index 45b645724520910292f19362da73dd17c7541b3b..c4825fcf734a590dc6dbe114355fa3fc08fede2a 100644 (file)
@@ -57,30 +57,8 @@ TransitionArray* TransitionArray::cast(Object* object) {
 }
 
 
-Map* TransitionArray::elements_transition() {
-  Object* transition_map = get(kElementsTransitionIndex);
-  return Map::cast(transition_map);
-}
-
-
-void TransitionArray::ClearElementsTransition() {
-  WRITE_FIELD(this, kElementsTransitionOffset, Smi::FromInt(0));
-}
-
-
 bool TransitionArray::HasElementsTransition() {
-  return IsFullTransitionArray() &&
-      get(kElementsTransitionIndex) != Smi::FromInt(0);
-}
-
-
-void TransitionArray::set_elements_transition(Map* transition_map,
-                                              WriteBarrierMode mode) {
-  ASSERT(IsFullTransitionArray());
-  Heap* heap = GetHeap();
-  WRITE_FIELD(this, kElementsTransitionOffset, transition_map);
-  CONDITIONAL_WRITE_BARRIER(
-      heap, this, kElementsTransitionOffset, transition_map, mode);
+  return Search(GetHeap()->elements_transition_symbol()) != kNotFound;
 }
 
 
index df53178dd3d451bdf5514b2f50599b5755016660..086edcb99480369dd97ec7bf170b7d30db296416 100644 (file)
@@ -50,7 +50,6 @@ MaybeObject* TransitionArray::Allocate(int number_of_transitions) {
   FixedArray* array;
   MaybeObject* maybe_array = AllocateRaw(ToKeyIndex(number_of_transitions));
   if (!maybe_array->To(&array)) return maybe_array;
-  array->set(kElementsTransitionIndex, Smi::FromInt(0));
   array->set(kPrototypeTransitionsIndex, Smi::FromInt(0));
   return array;
 }
@@ -120,10 +119,6 @@ MaybeObject* TransitionArray::CopyInsert(Name* name, Map* target) {
   maybe_array = TransitionArray::Allocate(new_size);
   if (!maybe_array->To(&result)) return maybe_array;
 
-  if (HasElementsTransition()) {
-    result->set_elements_transition(elements_transition());
-  }
-
   if (HasPrototypeTransitions()) {
     result->SetPrototypeTransitions(GetPrototypeTransitions());
   }
index 7abef47346870a012fc1e6c86c1b52bec10aa3ae..fde1279895205efa5f227001e9c1d4f2a4480f47 100644 (file)
@@ -41,10 +41,10 @@ namespace internal {
 // TransitionArrays are fixed arrays used to hold map transitions for property,
 // constant, and element changes. They can either be simple transition arrays
 // that store a single property transition, or a full transition array that has
-// space for elements transitions, prototype transitions and multiple property
-// transitons. The details related to property transitions are accessed in the
-// descriptor array of the target map. In the case of a simple transition, the
-// key is also read from the descriptor array of the target map.
+// prototype transitions and multiple property transitons. The details related
+// to property transitions are accessed in the descriptor array of the target
+// map. In the case of a simple transition, the key is also read from the
+// descriptor array of the target map.
 //
 // The simple format of the these objects is:
 // [0] Undefined or back pointer map
@@ -52,9 +52,8 @@ namespace internal {
 //
 // The full format is:
 // [0] Undefined or back pointer map
-// [1] Smi(0) or elements transition map
-// [2] Smi(0) or fixed array of prototype transitions
-// [3] First transition
+// [1] Smi(0) or fixed array of prototype transitions
+// [2] First transition
 // [length() - kTransitionSize] Last transition
 class TransitionArray: public FixedArray {
  public:
@@ -73,12 +72,7 @@ class TransitionArray: public FixedArray {
 
   inline PropertyDetails GetTargetDetails(int transition_number);
 
-  inline Map* elements_transition();
-  inline void set_elements_transition(
-      Map* target,
-      WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
   inline bool HasElementsTransition();
-  inline void ClearElementsTransition();
 
   inline Object* back_pointer_storage();
   inline void set_back_pointer_storage(
@@ -127,8 +121,21 @@ class TransitionArray: public FixedArray {
   // Allocates a TransitionArray.
   MUST_USE_RESULT static MaybeObject* Allocate(int number_of_transitions);
 
-  bool IsSimpleTransition() { return length() == kSimpleTransitionSize; }
-  bool IsFullTransitionArray() { return length() >= kFirstIndex; }
+  bool IsSimpleTransition() {
+    return length() == kSimpleTransitionSize &&
+        get(kSimpleTransitionTarget)->IsHeapObject() &&
+        // The IntrusivePrototypeTransitionIterator may have set the map of the
+        // prototype transitions array to a smi. In that case, there are
+        // prototype transitions, hence this transition array is a full
+        // transition array.
+        HeapObject::cast(get(kSimpleTransitionTarget))->map()->IsMap() &&
+        get(kSimpleTransitionTarget)->IsMap();
+  }
+
+  bool IsFullTransitionArray() {
+    return length() > kFirstIndex ||
+        (length() == kFirstIndex && !IsSimpleTransition());
+  }
 
   // Casting.
   static inline TransitionArray* cast(Object* obj);
@@ -139,9 +146,8 @@ class TransitionArray: public FixedArray {
   static const int kBackPointerStorageIndex = 0;
 
   // Layout for full transition arrays.
-  static const int kElementsTransitionIndex = 1;
-  static const int kPrototypeTransitionsIndex = 2;
-  static const int kFirstIndex = 3;
+  static const int kPrototypeTransitionsIndex = 1;
+  static const int kFirstIndex = 2;
 
   // Layout for simple transition arrays.
   static const int kSimpleTransitionTarget = 1;
@@ -152,9 +158,7 @@ class TransitionArray: public FixedArray {
   static const int kBackPointerStorageOffset = FixedArray::kHeaderSize;
 
   // Layout for the full transition array header.
-  static const int kElementsTransitionOffset = kBackPointerStorageOffset +
-                                               kPointerSize;
-  static const int kPrototypeTransitionsOffset = kElementsTransitionOffset +
+  static const int kPrototypeTransitionsOffset = kBackPointerStorageOffset +
                                                  kPointerSize;
 
   // Layout of map transition entries in full transition arrays.