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;
}
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;
}
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) \
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) \
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;
}
Map* Map::elements_transition_map() {
- return transitions()->elements_transition();
+ int index = transitions()->Search(GetHeap()->elements_transition_symbol());
+ return transitions()->GetTarget(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;
}
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;
}
}
}
- 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();
}
-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;
}
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;
}
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());
}
// 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
//
// 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:
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(
// 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);
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;
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.