Commit 8b57f269 authored by verwaest@chromium.org's avatar verwaest@chromium.org

Reduce space usage of simple transitions and descriptors holders.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12544 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f0dcaf9a
...@@ -3560,17 +3560,31 @@ DescriptorArray* Map::instance_descriptors() { ...@@ -3560,17 +3560,31 @@ DescriptorArray* Map::instance_descriptors() {
} }
enum TransitionsKind { DESCRIPTORS_HOLDER, FULL_TRANSITION_ARRAY };
// If the descriptor is using the empty transition array, install a new empty // If the descriptor is using the empty transition array, install a new empty
// transition array that will have place for an element transition. // transition array that will have place for an element transition.
static MaybeObject* EnsureHasTransitionArray(Map* map) { static MaybeObject* EnsureHasTransitionArray(Map* map, TransitionsKind kind) {
if (map->HasTransitionArray()) return map;
TransitionArray* transitions; TransitionArray* transitions;
JSGlobalPropertyCell* pointer = map->RetrieveDescriptorsPointer(); MaybeObject* maybe_transitions;
MaybeObject* maybe_transitions = TransitionArray::Allocate(0, pointer); if (map->HasTransitionArray()) {
if (!maybe_transitions->To(&transitions)) return maybe_transitions; if (kind != FULL_TRANSITION_ARRAY ||
map->transitions()->IsFullTransitionArray()) {
transitions->set_back_pointer_storage(map->GetBackPointer()); return map;
}
maybe_transitions = map->transitions()->ExtendToFullTransitionArray();
if (!maybe_transitions->To(&transitions)) return maybe_transitions;
} else {
JSGlobalPropertyCell* pointer = map->RetrieveDescriptorsPointer();
if (kind == FULL_TRANSITION_ARRAY) {
maybe_transitions = TransitionArray::Allocate(0, pointer);
} else {
maybe_transitions = TransitionArray::AllocateDescriptorsHolder(pointer);
}
if (!maybe_transitions->To(&transitions)) return maybe_transitions;
transitions->set_back_pointer_storage(map->GetBackPointer());
}
map->set_transitions(transitions); map->set_transitions(transitions);
return transitions; return transitions;
} }
...@@ -3578,7 +3592,8 @@ static MaybeObject* EnsureHasTransitionArray(Map* map) { ...@@ -3578,7 +3592,8 @@ static MaybeObject* EnsureHasTransitionArray(Map* map) {
MaybeObject* Map::SetDescriptors(DescriptorArray* value) { MaybeObject* Map::SetDescriptors(DescriptorArray* value) {
ASSERT(!is_shared()); ASSERT(!is_shared());
MaybeObject* maybe_failure = EnsureHasTransitionArray(this); MaybeObject* maybe_failure =
EnsureHasTransitionArray(this, DESCRIPTORS_HOLDER);
if (maybe_failure->IsFailure()) return maybe_failure; if (maybe_failure->IsFailure()) return maybe_failure;
ASSERT(NumberOfOwnDescriptors() <= value->number_of_descriptors()); ASSERT(NumberOfOwnDescriptors() <= value->number_of_descriptors());
...@@ -3688,11 +3703,13 @@ JSGlobalPropertyCell* Map::RetrieveDescriptorsPointer() { ...@@ -3688,11 +3703,13 @@ JSGlobalPropertyCell* Map::RetrieveDescriptorsPointer() {
} }
MaybeObject* Map::AddTransition(String* key, Map* target) { MaybeObject* Map::AddTransition(String* key,
Map* target,
SimpleTransitionFlag flag) {
if (HasTransitionArray()) return transitions()->CopyInsert(key, target); if (HasTransitionArray()) return transitions()->CopyInsert(key, target);
JSGlobalPropertyCell* descriptors_pointer = RetrieveDescriptorsPointer(); JSGlobalPropertyCell* descriptors_pointer = RetrieveDescriptorsPointer();
return TransitionArray::NewWith( return TransitionArray::NewWith(
key, target, descriptors_pointer, GetBackPointer()); flag, key, target, descriptors_pointer, GetBackPointer());
} }
...@@ -3707,7 +3724,8 @@ Map* Map::GetTransition(int transition_index) { ...@@ -3707,7 +3724,8 @@ Map* Map::GetTransition(int transition_index) {
MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) { MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) {
MaybeObject* allow_elements = EnsureHasTransitionArray(this); MaybeObject* allow_elements =
EnsureHasTransitionArray(this, FULL_TRANSITION_ARRAY);
if (allow_elements->IsFailure()) return allow_elements; if (allow_elements->IsFailure()) return allow_elements;
transitions()->set_elements_transition(transitioned_map); transitions()->set_elements_transition(transitioned_map);
return this; return this;
...@@ -3724,7 +3742,8 @@ FixedArray* Map::GetPrototypeTransitions() { ...@@ -3724,7 +3742,8 @@ FixedArray* Map::GetPrototypeTransitions() {
MaybeObject* Map::SetPrototypeTransitions(FixedArray* proto_transitions) { MaybeObject* Map::SetPrototypeTransitions(FixedArray* proto_transitions) {
MaybeObject* allow_prototype = EnsureHasTransitionArray(this); MaybeObject* allow_prototype =
EnsureHasTransitionArray(this, FULL_TRANSITION_ARRAY);
if (allow_prototype->IsFailure()) return allow_prototype; if (allow_prototype->IsFailure()) return allow_prototype;
#ifdef DEBUG #ifdef DEBUG
if (HasPrototypeTransitions()) { if (HasPrototypeTransitions()) {
......
...@@ -330,6 +330,9 @@ void StaticMarkingVisitor<StaticVisitor>::MarkTransitionArray( ...@@ -330,6 +330,9 @@ void StaticMarkingVisitor<StaticVisitor>::MarkTransitionArray(
// is not compacted and descriptors are referenced through a cell. // is not compacted and descriptors are referenced through a cell.
StaticVisitor::MarkObject(heap, transitions->descriptors_pointer()); StaticVisitor::MarkObject(heap, transitions->descriptors_pointer());
// Simple transitions do not have keys nor prototype transitions.
if (transitions->IsSimpleTransition()) return;
if (transitions->HasPrototypeTransitions()) { if (transitions->HasPrototypeTransitions()) {
// Mark prototype transitions array but do not push it onto marking // Mark prototype transitions array but do not push it onto marking
// stack, this will make references from it weak. We will clean dead // stack, this will make references from it weak. We will clean dead
......
...@@ -5000,7 +5000,8 @@ MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) { ...@@ -5000,7 +5000,8 @@ MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) {
String* name = descriptor->GetKey(); String* name = descriptor->GetKey();
TransitionArray* transitions; TransitionArray* transitions;
MaybeObject* maybe_transitions = AddTransition(name, result); MaybeObject* maybe_transitions =
AddTransition(name, result, SIMPLE_TRANSITION);
if (!maybe_transitions->To(&transitions)) return maybe_transitions; if (!maybe_transitions->To(&transitions)) return maybe_transitions;
DescriptorArray* descriptors = instance_descriptors(); DescriptorArray* descriptors = instance_descriptors();
...@@ -5051,7 +5052,8 @@ MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) { ...@@ -5051,7 +5052,8 @@ MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) {
MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
String* name, String* name,
TransitionFlag flag) { TransitionFlag flag,
int descriptor_index) {
ASSERT(descriptors->IsSortedNoDuplicates()); ASSERT(descriptors->IsSortedNoDuplicates());
Map* result; Map* result;
...@@ -5068,7 +5070,11 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, ...@@ -5068,7 +5070,11 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
TransitionArray* transitions; TransitionArray* transitions;
MaybeObject* maybe_transitions = AddTransition(name, result); SimpleTransitionFlag simple_flag =
(descriptor_index == descriptors->number_of_descriptors() - 1)
? SIMPLE_TRANSITION
: FULL_TRANSITION;
MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag);
if (!maybe_transitions->To(&transitions)) return maybe_transitions; if (!maybe_transitions->To(&transitions)) return maybe_transitions;
if (descriptors->IsEmpty()) { if (descriptors->IsEmpty()) {
...@@ -5173,7 +5179,7 @@ MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { ...@@ -5173,7 +5179,7 @@ MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() {
descriptors->CopyUpTo(number_of_own_descriptors); descriptors->CopyUpTo(number_of_own_descriptors);
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION); return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0);
} }
...@@ -5185,7 +5191,7 @@ MaybeObject* Map::Copy() { ...@@ -5185,7 +5191,7 @@ MaybeObject* Map::Copy() {
descriptors->CopyUpTo(number_of_own_descriptors); descriptors->CopyUpTo(number_of_own_descriptors);
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION); return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0);
} }
...@@ -5227,8 +5233,9 @@ MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, ...@@ -5227,8 +5233,9 @@ MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
} }
String* key = descriptor->GetKey(); String* key = descriptor->GetKey();
int insertion_index = new_descriptors->number_of_descriptors() - 1;
return CopyReplaceDescriptors(new_descriptors, key, flag); return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index);
} }
...@@ -5304,7 +5311,7 @@ MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor, ...@@ -5304,7 +5311,7 @@ MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor,
// Re-sort if descriptors were removed. // Re-sort if descriptors were removed.
if (new_size != descriptors->length()) new_descriptors->Sort(); if (new_size != descriptors->length()) new_descriptors->Sort();
return CopyReplaceDescriptors(new_descriptors, key, flag); return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index);
} }
...@@ -7554,8 +7561,8 @@ void Map::ClearNonLiveTransitions(Heap* heap) { ...@@ -7554,8 +7561,8 @@ void Map::ClearNonLiveTransitions(Heap* heap) {
int trim = t->number_of_transitions() - transition_index; int trim = t->number_of_transitions() - transition_index;
if (trim > 0) { if (trim > 0) {
RightTrimFixedArray<FROM_GC>( RightTrimFixedArray<FROM_GC>(heap, t, t->IsSimpleTransition()
heap, t, trim * TransitionArray::kTransitionSize); ? trim : trim * TransitionArray::kTransitionSize);
} }
} }
......
...@@ -177,6 +177,16 @@ enum TransitionFlag { ...@@ -177,6 +177,16 @@ enum TransitionFlag {
OMIT_TRANSITION OMIT_TRANSITION
}; };
// Indicates whether the transition is simple: the target map of the transition
// either extends the current map with a new property, or it modifies the
// property that was added last to the current map.
enum SimpleTransitionFlag {
SIMPLE_TRANSITION,
FULL_TRANSITION
};
// Indicates whether we are only interested in the descriptors of a particular // Indicates whether we are only interested in the descriptors of a particular
// map, or in all descriptors in the descriptor array. // map, or in all descriptors in the descriptor array.
enum DescriptorFlag { enum DescriptorFlag {
...@@ -4836,7 +4846,9 @@ class Map: public HeapObject { ...@@ -4836,7 +4846,9 @@ class Map: public HeapObject {
Map* transitioned_map); Map* transitioned_map);
inline void SetTransition(int transition_index, Map* target); inline void SetTransition(int transition_index, Map* target);
inline Map* GetTransition(int transition_index); inline Map* GetTransition(int transition_index);
MUST_USE_RESULT inline MaybeObject* AddTransition(String* key, Map* target); MUST_USE_RESULT inline MaybeObject* AddTransition(String* key,
Map* target,
SimpleTransitionFlag flag);
DECL_ACCESSORS(transitions, TransitionArray) DECL_ACCESSORS(transitions, TransitionArray)
inline void ClearTransitions(Heap* heap, inline void ClearTransitions(Heap* heap,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER); WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
...@@ -4987,7 +4999,8 @@ class Map: public HeapObject { ...@@ -4987,7 +4999,8 @@ class Map: public HeapObject {
MUST_USE_RESULT MaybeObject* CopyReplaceDescriptors( MUST_USE_RESULT MaybeObject* CopyReplaceDescriptors(
DescriptorArray* descriptors, DescriptorArray* descriptors,
String* name, String* name,
TransitionFlag flag); TransitionFlag flag,
int descriptor_index);
MUST_USE_RESULT MaybeObject* ShareDescriptor(Descriptor* descriptor); MUST_USE_RESULT MaybeObject* ShareDescriptor(Descriptor* descriptor);
MUST_USE_RESULT MaybeObject* CopyAddDescriptor(Descriptor* descriptor, MUST_USE_RESULT MaybeObject* CopyAddDescriptor(Descriptor* descriptor,
TransitionFlag flag); TransitionFlag flag);
......
...@@ -69,12 +69,14 @@ void TransitionArray::ClearElementsTransition() { ...@@ -69,12 +69,14 @@ void TransitionArray::ClearElementsTransition() {
bool TransitionArray::HasElementsTransition() { bool TransitionArray::HasElementsTransition() {
return get(kElementsTransitionIndex) != Smi::FromInt(0); return IsFullTransitionArray() &&
get(kElementsTransitionIndex) != Smi::FromInt(0);
} }
void TransitionArray::set_elements_transition(Map* transition_map, void TransitionArray::set_elements_transition(Map* transition_map,
WriteBarrierMode mode) { WriteBarrierMode mode) {
ASSERT(IsFullTransitionArray());
Heap* heap = GetHeap(); Heap* heap = GetHeap();
WRITE_FIELD(this, kElementsTransitionOffset, transition_map); WRITE_FIELD(this, kElementsTransitionOffset, transition_map);
CONDITIONAL_WRITE_BARRIER( CONDITIONAL_WRITE_BARRIER(
...@@ -121,12 +123,13 @@ void TransitionArray::set_back_pointer_storage(Object* back_pointer, ...@@ -121,12 +123,13 @@ void TransitionArray::set_back_pointer_storage(Object* back_pointer,
bool TransitionArray::HasPrototypeTransitions() { bool TransitionArray::HasPrototypeTransitions() {
Object* prototype_transitions = get(kPrototypeTransitionsIndex); return IsFullTransitionArray() &&
return prototype_transitions != Smi::FromInt(0); get(kPrototypeTransitionsIndex) != Smi::FromInt(0);
} }
FixedArray* TransitionArray::GetPrototypeTransitions() { FixedArray* TransitionArray::GetPrototypeTransitions() {
ASSERT(IsFullTransitionArray());
Object* prototype_transitions = get(kPrototypeTransitionsIndex); Object* prototype_transitions = get(kPrototypeTransitionsIndex);
return FixedArray::cast(prototype_transitions); return FixedArray::cast(prototype_transitions);
} }
...@@ -140,7 +143,7 @@ HeapObject* TransitionArray::UncheckedPrototypeTransitions() { ...@@ -140,7 +143,7 @@ HeapObject* TransitionArray::UncheckedPrototypeTransitions() {
void TransitionArray::SetPrototypeTransitions(FixedArray* transitions, void TransitionArray::SetPrototypeTransitions(FixedArray* transitions,
WriteBarrierMode mode) { WriteBarrierMode mode) {
ASSERT(this != NULL); ASSERT(IsFullTransitionArray());
ASSERT(transitions->IsFixedArray()); ASSERT(transitions->IsFixedArray());
Heap* heap = GetHeap(); Heap* heap = GetHeap();
WRITE_FIELD(this, kPrototypeTransitionsOffset, transitions); WRITE_FIELD(this, kPrototypeTransitionsOffset, transitions);
...@@ -156,6 +159,7 @@ Object** TransitionArray::GetPrototypeTransitionsSlot() { ...@@ -156,6 +159,7 @@ Object** TransitionArray::GetPrototypeTransitionsSlot() {
Object** TransitionArray::GetKeySlot(int transition_number) { Object** TransitionArray::GetKeySlot(int transition_number) {
ASSERT(!IsSimpleTransition());
ASSERT(transition_number < number_of_transitions()); ASSERT(transition_number < number_of_transitions());
return HeapObject::RawField( return HeapObject::RawField(
reinterpret_cast<HeapObject*>(this), reinterpret_cast<HeapObject*>(this),
...@@ -164,24 +168,39 @@ Object** TransitionArray::GetKeySlot(int transition_number) { ...@@ -164,24 +168,39 @@ Object** TransitionArray::GetKeySlot(int transition_number) {
String* TransitionArray::GetKey(int transition_number) { String* TransitionArray::GetKey(int transition_number) {
if (IsSimpleTransition()) {
Map* target = GetTarget(kSimpleTransitionIndex);
int descriptor = target->LastAdded();
String* key = target->instance_descriptors()->GetKey(descriptor);
return key;
}
ASSERT(transition_number < number_of_transitions()); ASSERT(transition_number < number_of_transitions());
return String::cast(get(ToKeyIndex(transition_number))); return String::cast(get(ToKeyIndex(transition_number)));
} }
void TransitionArray::SetKey(int transition_number, String* key) { void TransitionArray::SetKey(int transition_number, String* key) {
ASSERT(!IsSimpleTransition());
ASSERT(transition_number < number_of_transitions()); ASSERT(transition_number < number_of_transitions());
set(ToKeyIndex(transition_number), key); set(ToKeyIndex(transition_number), key);
} }
Map* TransitionArray::GetTarget(int transition_number) { Map* TransitionArray::GetTarget(int transition_number) {
if (IsSimpleTransition()) {
ASSERT(transition_number == kSimpleTransitionIndex);
return Map::cast(get(kSimpleTransitionTarget));
}
ASSERT(transition_number < number_of_transitions()); ASSERT(transition_number < number_of_transitions());
return Map::cast(get(ToTargetIndex(transition_number))); return Map::cast(get(ToTargetIndex(transition_number)));
} }
void TransitionArray::SetTarget(int transition_number, Map* value) { void TransitionArray::SetTarget(int transition_number, Map* value) {
if (IsSimpleTransition()) {
ASSERT(transition_number == kSimpleTransitionIndex);
return set(kSimpleTransitionTarget, value);
}
ASSERT(transition_number < number_of_transitions()); ASSERT(transition_number < number_of_transitions());
set(ToTargetIndex(transition_number), value); set(ToTargetIndex(transition_number), value);
} }
......
...@@ -35,8 +35,8 @@ namespace v8 { ...@@ -35,8 +35,8 @@ namespace v8 {
namespace internal { namespace internal {
MaybeObject* TransitionArray::Allocate(int number_of_transitions, static MaybeObject* AllocateRaw(int length,
JSGlobalPropertyCell* descriptors_cell) { JSGlobalPropertyCell* descriptors_cell) {
Heap* heap = Isolate::Current()->heap(); Heap* heap = Isolate::Current()->heap();
if (descriptors_cell == NULL) { if (descriptors_cell == NULL) {
...@@ -45,13 +45,22 @@ MaybeObject* TransitionArray::Allocate(int number_of_transitions, ...@@ -45,13 +45,22 @@ MaybeObject* TransitionArray::Allocate(int number_of_transitions,
if (!maybe_cell->To(&descriptors_cell)) return maybe_cell; if (!maybe_cell->To(&descriptors_cell)) return maybe_cell;
} }
// Use FixedArray to not use DescriptorArray::cast on incomplete object. // Use FixedArray to not use TransitionArray::cast on incomplete object.
FixedArray* array; FixedArray* array;
MaybeObject* maybe_array = MaybeObject* maybe_array = heap->AllocateFixedArray(length);
heap->AllocateFixedArray(ToKeyIndex(number_of_transitions));
if (!maybe_array->To(&array)) return maybe_array; if (!maybe_array->To(&array)) return maybe_array;
array->set(kDescriptorsPointerIndex, descriptors_cell); array->set(TransitionArray::kDescriptorsPointerIndex, descriptors_cell);
return array;
}
MaybeObject* TransitionArray::Allocate(int number_of_transitions,
JSGlobalPropertyCell* descriptors_cell) {
FixedArray* array;
MaybeObject* maybe_array =
AllocateRaw(ToKeyIndex(number_of_transitions), descriptors_cell);
if (!maybe_array->To(&array)) return maybe_array;
array->set(kElementsTransitionIndex, Smi::FromInt(0)); array->set(kElementsTransitionIndex, Smi::FromInt(0));
array->set(kPrototypeTransitionsIndex, Smi::FromInt(0)); array->set(kPrototypeTransitionsIndex, Smi::FromInt(0));
return array; return array;
...@@ -72,18 +81,46 @@ static bool InsertionPointFound(String* key1, String* key2) { ...@@ -72,18 +81,46 @@ static bool InsertionPointFound(String* key1, String* key2) {
} }
MaybeObject* TransitionArray::NewWith( MaybeObject* TransitionArray::NewWith(SimpleTransitionFlag flag,
String* name, String* key,
Map* target, Map* target,
JSGlobalPropertyCell* descriptors_pointer, JSGlobalPropertyCell* descriptors_pointer,
Object* back_pointer) { Object* back_pointer) {
TransitionArray* result;
MaybeObject* maybe_result;
if (flag == SIMPLE_TRANSITION) {
maybe_result = AllocateRaw(kSimpleTransitionSize, descriptors_pointer);
if (!maybe_result->To(&result)) return maybe_result;
result->set(kSimpleTransitionTarget, target);
} else {
maybe_result = Allocate(1, descriptors_pointer);
if (!maybe_result->To(&result)) return maybe_result;
result->NoIncrementalWriteBarrierSet(0, key, target);
}
result->set_back_pointer_storage(back_pointer);
return result;
}
MaybeObject* TransitionArray::AllocateDescriptorsHolder(
JSGlobalPropertyCell* descriptors_pointer) {
return AllocateRaw(kDescriptorsHolderSize, descriptors_pointer);
}
MaybeObject* TransitionArray::ExtendToFullTransitionArray() {
ASSERT(!IsFullTransitionArray());
int nof = number_of_transitions();
TransitionArray* result; TransitionArray* result;
MaybeObject* maybe_result = Allocate(nof, descriptors_pointer());
if (!maybe_result->To(&result)) return maybe_result;
MaybeObject* maybe_array = TransitionArray::Allocate(1, descriptors_pointer); if (nof == 1) {
if (!maybe_array->To(&result)) return maybe_array; result->NoIncrementalWriteBarrierCopyFrom(this, kSimpleTransitionIndex, 0);
}
result->NoIncrementalWriteBarrierSet(0, name, target); result->set_back_pointer_storage(back_pointer_storage());
result->set_back_pointer_storage(back_pointer);
return result; return result;
} }
......
...@@ -91,7 +91,7 @@ class TransitionArray: public FixedArray { ...@@ -91,7 +91,7 @@ class TransitionArray: public FixedArray {
// Returns the number of transitions in the array. // Returns the number of transitions in the array.
int number_of_transitions() { int number_of_transitions() {
ASSERT(length() >= kFirstIndex); if (IsSimpleTransition()) return 1;
int len = length(); int len = length();
return len <= kFirstIndex ? 0 : (len - kFirstIndex) / kTransitionSize; return len <= kFirstIndex ? 0 : (len - kFirstIndex) / kTransitionSize;
} }
...@@ -100,11 +100,17 @@ class TransitionArray: public FixedArray { ...@@ -100,11 +100,17 @@ class TransitionArray: public FixedArray {
// Allocate a new transition array with a single entry. // Allocate a new transition array with a single entry.
static MUST_USE_RESULT MaybeObject* NewWith( static MUST_USE_RESULT MaybeObject* NewWith(
String* name, SimpleTransitionFlag flag,
String* key,
Map* target, Map* target,
JSGlobalPropertyCell* descriptor_pointer, JSGlobalPropertyCell* descriptor_pointer,
Object* back_pointer); Object* back_pointer);
static MUST_USE_RESULT MaybeObject* AllocateDescriptorsHolder(
JSGlobalPropertyCell* descriptor_pointer);
MUST_USE_RESULT MaybeObject* ExtendToFullTransitionArray();
// Copy the transition array, inserting a new transition. // Copy the transition array, inserting a new transition.
// TODO(verwaest): This should not cause an existing transition to be // TODO(verwaest): This should not cause an existing transition to be
// overwritten. // overwritten.
...@@ -123,6 +129,10 @@ class TransitionArray: public FixedArray { ...@@ -123,6 +129,10 @@ class TransitionArray: public FixedArray {
int number_of_transitions, int number_of_transitions,
JSGlobalPropertyCell* descriptors_cell); JSGlobalPropertyCell* descriptors_cell);
bool IsDescriptorsHolder() { return length() == kDescriptorsHolderSize; }
bool IsSimpleTransition() { return length() == kSimpleTransitionSize; }
bool IsFullTransitionArray() { return length() >= kFirstIndex; }
// Casting. // Casting.
static inline TransitionArray* cast(Object* obj); static inline TransitionArray* cast(Object* obj);
...@@ -131,20 +141,30 @@ class TransitionArray: public FixedArray { ...@@ -131,20 +141,30 @@ class TransitionArray: public FixedArray {
static const int kDescriptorsPointerIndex = 0; static const int kDescriptorsPointerIndex = 0;
static const int kBackPointerStorageIndex = 1; static const int kBackPointerStorageIndex = 1;
static const int kDescriptorsHolderSize = 2;
// Layout for full transition arrays.
static const int kElementsTransitionIndex = 2; static const int kElementsTransitionIndex = 2;
static const int kPrototypeTransitionsIndex = 3; static const int kPrototypeTransitionsIndex = 3;
static const int kFirstIndex = 4; static const int kFirstIndex = 4;
// Layout transition array header. // Layout for simple transition arrays.
static const int kSimpleTransitionTarget = 2;
static const int kSimpleTransitionSize = 3;
static const int kSimpleTransitionIndex = 0;
STATIC_ASSERT(kSimpleTransitionIndex != kNotFound);
static const int kDescriptorsPointerOffset = FixedArray::kHeaderSize; static const int kDescriptorsPointerOffset = FixedArray::kHeaderSize;
static const int kBackPointerStorageOffset = kDescriptorsPointerOffset + static const int kBackPointerStorageOffset = kDescriptorsPointerOffset +
kPointerSize; kPointerSize;
// Layout for the full transition array header.
static const int kElementsTransitionOffset = kBackPointerStorageOffset + static const int kElementsTransitionOffset = kBackPointerStorageOffset +
kPointerSize; kPointerSize;
static const int kPrototypeTransitionsOffset = kElementsTransitionOffset + static const int kPrototypeTransitionsOffset = kElementsTransitionOffset +
kPointerSize; kPointerSize;
// Layout of map transition. // Layout of map transition entries in full transition arrays.
static const int kTransitionKey = 0; static const int kTransitionKey = 0;
static const int kTransitionTarget = 1; static const int kTransitionTarget = 1;
static const int kTransitionSize = 2; static const int kTransitionSize = 2;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment