diff --git a/include/v8.h b/include/v8.h index 6b18153833..a4eae968d3 100644 --- a/include/v8.h +++ b/include/v8.h @@ -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; diff --git a/src/heap.cc b/src/heap.cc index 777661570a..c2a2707602 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -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; } diff --git a/src/heap.h b/src/heap.h index fbe0531014..de6f55bfaf 100644 --- a/src/heap.h +++ b/src/heap.h @@ -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) \ diff --git a/src/objects-debug.cc b/src/objects-debug.cc index cb5f2b7900..395f95ca7e 100644 --- a/src/objects-debug.cc +++ b/src/objects-debug.cc @@ -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; } diff --git a/src/objects-inl.h b/src/objects-inl.h index 3c70569241..128dc6be28 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -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; } diff --git a/src/objects.cc b/src/objects.cc index 1fdd478b7f..2e9badbb2a 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -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(); diff --git a/src/transitions-inl.h b/src/transitions-inl.h index 45b6457245..c4825fcf73 100644 --- a/src/transitions-inl.h +++ b/src/transitions-inl.h @@ -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; } diff --git a/src/transitions.cc b/src/transitions.cc index df53178dd3..086edcb994 100644 --- a/src/transitions.cc +++ b/src/transitions.cc @@ -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()); } diff --git a/src/transitions.h b/src/transitions.h index 7abef47346..fde1279895 100644 --- a/src/transitions.h +++ b/src/transitions.h @@ -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.