Merging ContentArray into DescriptorArray

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11703 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
verwaest@chromium.org 2012-06-04 07:20:11 +00:00
parent 463a6ffdd4
commit 98c37e1f4c
5 changed files with 81 additions and 74 deletions

View File

@ -1867,25 +1867,42 @@ void Marker<T>::MarkDescriptorArray(DescriptorArray* descriptors) {
// Empty descriptor array is marked as a root before any maps are marked.
ASSERT(descriptors != descriptors->GetHeap()->empty_descriptor_array());
// The DescriptorArray contains a pointer to its contents array, but the
// contents array will be marked black and hence not be visited again.
if (!base_marker()->MarkObjectAndPush(descriptors)) return;
FixedArray* contents = FixedArray::cast(
descriptors->get(DescriptorArray::kContentArrayIndex));
ASSERT(Marking::IsWhite(Marking::MarkBitFrom(contents)));
base_marker()->MarkObjectWithoutPush(contents);
if (!base_marker()->MarkObjectWithoutPush(descriptors)) return;
Object** descriptor_start = descriptors->data_start();
// Since the descriptor array itself is not pushed for scanning, all fields
// that point to objects manually have to be pushed, marked, and their slots
// recorded.
if (descriptors->HasEnumCache()) {
Object** enum_cache_slot = descriptors->GetEnumCacheSlot();
Object* enum_cache = *enum_cache_slot;
base_marker()->MarkObjectAndPush(
reinterpret_cast<HeapObject*>(enum_cache));
mark_compact_collector()->RecordSlot(descriptor_start,
enum_cache_slot,
enum_cache);
}
// If the descriptor contains a transition (value is a Map), we don't mark the
// value as live. It might be set to the NULL_DESCRIPTOR in
// ClearNonLiveTransitions later.
for (int i = 0; i < descriptors->number_of_descriptors(); ++i) {
Object** key_slot = descriptors->GetKeySlot(i);
Object* key = *key_slot;
if (key->IsHeapObject()) {
base_marker()->MarkObjectAndPush(reinterpret_cast<HeapObject*>(key));
mark_compact_collector()->RecordSlot(descriptor_start, key_slot, key);
}
Object** value_slot = descriptors->GetValueSlot(i);
if (!(*value_slot)->IsHeapObject()) continue;
HeapObject* value = HeapObject::cast(*value_slot);
mark_compact_collector()->RecordSlot(descriptor_start,
value_slot,
value);
PropertyDetails details(descriptors->GetDetails(i));
Object** slot = descriptors->GetValueSlot(i);
if (!(*slot)->IsHeapObject()) continue;
HeapObject* value = HeapObject::cast(*slot);
mark_compact_collector()->RecordSlot(slot, slot, *slot);
switch (details.type()) {
case NORMAL:

View File

@ -1013,14 +1013,9 @@ void NormalizedMapCache::NormalizedMapCacheVerify() {
void Map::ZapInstanceDescriptors() {
DescriptorArray* descriptors = instance_descriptors();
if (descriptors == GetHeap()->empty_descriptor_array()) return;
FixedArray* contents = FixedArray::cast(
descriptors->get(DescriptorArray::kContentArrayIndex));
MemsetPointer(descriptors->data_start(),
GetHeap()->the_hole_value(),
descriptors->length());
MemsetPointer(contents->data_start(),
GetHeap()->the_hole_value(),
contents->length());
}

View File

@ -1925,6 +1925,14 @@ int DescriptorArray::SearchWithCache(String* name) {
}
Object** DescriptorArray::GetKeySlot(int descriptor_number) {
ASSERT(descriptor_number < number_of_descriptors());
return HeapObject::RawField(
reinterpret_cast<HeapObject*>(this),
OffsetOfElementAt(ToKeyIndex(descriptor_number)));
}
String* DescriptorArray::GetKey(int descriptor_number) {
ASSERT(descriptor_number < number_of_descriptors());
return String::cast(get(ToKeyIndex(descriptor_number)));
@ -1933,32 +1941,34 @@ String* DescriptorArray::GetKey(int descriptor_number) {
Object** DescriptorArray::GetValueSlot(int descriptor_number) {
ASSERT(descriptor_number < number_of_descriptors());
return GetContentArray()->data_start() + ToValueIndex(descriptor_number);
return HeapObject::RawField(
reinterpret_cast<HeapObject*>(this),
OffsetOfElementAt(ToValueIndex(descriptor_number)));
}
Object* DescriptorArray::GetValue(int descriptor_number) {
ASSERT(descriptor_number < number_of_descriptors());
return GetContentArray()->get(ToValueIndex(descriptor_number));
return get(ToValueIndex(descriptor_number));
}
void DescriptorArray::SetNullValueUnchecked(int descriptor_number, Heap* heap) {
ASSERT(descriptor_number < number_of_descriptors());
GetContentArray()->set_null_unchecked(heap, ToValueIndex(descriptor_number));
set_null_unchecked(heap, ToValueIndex(descriptor_number));
}
PropertyDetails DescriptorArray::GetDetails(int descriptor_number) {
ASSERT(descriptor_number < number_of_descriptors());
Object* details = GetContentArray()->get(ToDetailsIndex(descriptor_number));
Object* details = get(ToDetailsIndex(descriptor_number));
return PropertyDetails(Smi::cast(details));
}
void DescriptorArray::SetDetailsUnchecked(int descriptor_number, Smi* value) {
ASSERT(descriptor_number < number_of_descriptors());
GetContentArray()->set_unchecked(ToDetailsIndex(descriptor_number), value);
set_unchecked(ToDetailsIndex(descriptor_number), value);
}
@ -2042,11 +2052,10 @@ void DescriptorArray::Set(int descriptor_number,
NoIncrementalWriteBarrierSet(this,
ToKeyIndex(descriptor_number),
desc->GetKey());
FixedArray* content_array = GetContentArray();
NoIncrementalWriteBarrierSet(content_array,
NoIncrementalWriteBarrierSet(this,
ToValueIndex(descriptor_number),
desc->GetValue());
NoIncrementalWriteBarrierSet(content_array,
NoIncrementalWriteBarrierSet(this,
ToDetailsIndex(descriptor_number),
desc->GetDetails().AsSmi());
}
@ -2055,11 +2064,10 @@ void DescriptorArray::Set(int descriptor_number,
void DescriptorArray::NoIncrementalWriteBarrierSwapDescriptors(
int first, int second) {
NoIncrementalWriteBarrierSwap(this, ToKeyIndex(first), ToKeyIndex(second));
FixedArray* content_array = GetContentArray();
NoIncrementalWriteBarrierSwap(content_array,
NoIncrementalWriteBarrierSwap(this,
ToValueIndex(first),
ToValueIndex(second));
NoIncrementalWriteBarrierSwap(content_array,
NoIncrementalWriteBarrierSwap(this,
ToDetailsIndex(first),
ToDetailsIndex(second));
}
@ -2070,7 +2078,6 @@ DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array)
marking_->EnterNoMarkingScope();
if (array->number_of_descriptors() > 0) {
ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT);
ASSERT(Marking::Color(array->GetContentArray()) == Marking::WHITE_OBJECT);
}
}

View File

@ -5116,18 +5116,18 @@ class IntrusiveMapTransitionIterator {
int index = raw_index / 2;
int number_of_descriptors = descriptor_array_->number_of_descriptors();
while (index < number_of_descriptors) {
PropertyDetails details(RawGetDetails(index));
PropertyDetails details(descriptor_array_->GetDetails(index));
switch (details.type()) {
case MAP_TRANSITION:
case CONSTANT_TRANSITION:
case ELEMENTS_TRANSITION:
// We definitely have a map transition.
*DescriptorArrayHeader() = Smi::FromInt(raw_index + 2);
return static_cast<Map*>(RawGetValue(index));
return static_cast<Map*>(descriptor_array_->GetValue(index));
case CALLBACKS: {
// We might have a map transition in a getter or in a setter.
AccessorPair* accessors =
static_cast<AccessorPair*>(RawGetValue(index));
static_cast<AccessorPair*>(descriptor_array_->GetValue(index));
Object* accessor;
if ((raw_index & 1) == 0) {
accessor = accessors->setter();
@ -5167,24 +5167,6 @@ class IntrusiveMapTransitionIterator {
return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset);
}
FixedArray* RawGetContentArray() {
Object* array =
descriptor_array_->get(DescriptorArray::kContentArrayIndex);
return static_cast<FixedArray*>(array);
}
Object* RawGetValue(int descriptor_number) {
return RawGetContentArray()->get(
DescriptorArray::ToValueIndex(descriptor_number));
}
PropertyDetails RawGetDetails(int descriptor_number) {
Object* details = RawGetContentArray()->get(
DescriptorArray::ToDetailsIndex(descriptor_number));
return PropertyDetails(Smi::cast(details));
}
DescriptorArray* descriptor_array_;
};
@ -5883,13 +5865,7 @@ MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) {
// Do not use DescriptorArray::cast on incomplete object.
FixedArray* result = FixedArray::cast(array);
// Allocate the content array and set it in the descriptor array.
{ MaybeObject* maybe_array =
heap->AllocateFixedArray(number_of_descriptors << 1);
if (!maybe_array->ToObject(&array)) return maybe_array;
}
result->set(kBitField3StorageIndex, Smi::FromInt(0));
result->set(kContentArrayIndex, array);
result->set(kEnumerationIndexIndex,
Smi::FromInt(PropertyDetails::kInitialIndex));
return result;
@ -6216,9 +6192,9 @@ bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
if (other->IsEmpty()) return false;
if (length() != other->length()) return false;
for (int i = 0; i < length(); ++i) {
if (get(i) != other->get(i) && i != kContentArrayIndex) return false;
if (get(i) != other->get(i)) return false;
}
return GetContentArray()->IsEqualTo(other->GetContentArray());
return true;
}
#endif

View File

@ -2403,7 +2403,7 @@ class DescriptorArray: public FixedArray {
int number_of_descriptors() {
ASSERT(length() > kFirstIndex || IsEmpty());
int len = length();
return len <= kFirstIndex ? 0 : len - kFirstIndex;
return len <= kFirstIndex ? 0 : (len - kFirstIndex) / kDescriptorSize;
}
int NextEnumerationIndex() {
@ -2433,6 +2433,12 @@ class DescriptorArray: public FixedArray {
return bridge->get(kEnumCacheBridgeCacheIndex);
}
Object** GetEnumCacheSlot() {
ASSERT(HasEnumCache());
return HeapObject::RawField(reinterpret_cast<HeapObject*>(this),
kEnumerationIndexOffset);
}
// TODO(1399): It should be possible to make room for bit_field3 in the map
// without overloading the instance descriptors field in the map
// (and storing it in the DescriptorArray when the map has one).
@ -2447,6 +2453,7 @@ class DescriptorArray: public FixedArray {
// Accessors for fetching instance descriptor at descriptor number.
inline String* GetKey(int descriptor_number);
inline Object** GetKeySlot(int descriptor_number);
inline Object* GetValue(int descriptor_number);
inline Object** GetValueSlot(int descriptor_number);
inline void SetNullValueUnchecked(int descriptor_number, Heap* heap);
@ -2552,9 +2559,8 @@ class DescriptorArray: public FixedArray {
static const int kNotFound = -1;
static const int kBitField3StorageIndex = 0;
static const int kContentArrayIndex = 1;
static const int kEnumerationIndexIndex = 2;
static const int kFirstIndex = 3;
static const int kEnumerationIndexIndex = 1;
static const int kFirstIndex = 2;
// The length of the "bridge" to the enum cache.
static const int kEnumCacheBridgeLength = 3;
@ -2564,8 +2570,8 @@ class DescriptorArray: public FixedArray {
// Layout description.
static const int kBitField3StorageOffset = FixedArray::kHeaderSize;
static const int kContentArrayOffset = kBitField3StorageOffset + kPointerSize;
static const int kEnumerationIndexOffset = kContentArrayOffset + kPointerSize;
static const int kEnumerationIndexOffset = kBitField3StorageOffset +
kPointerSize;
static const int kFirstOffset = kEnumerationIndexOffset + kPointerSize;
// Layout description for the bridge array.
@ -2573,6 +2579,12 @@ class DescriptorArray: public FixedArray {
static const int kEnumCacheBridgeCacheOffset =
kEnumCacheBridgeEnumOffset + kPointerSize;
// Layout of descriptor.
static const int kDescriptorKey = 0;
static const int kDescriptorDetails = 1;
static const int kDescriptorValue = 2;
static const int kDescriptorSize = 3;
#ifdef OBJECT_PRINT
// Print all the descriptors.
inline void PrintDescriptors() {
@ -2597,8 +2609,6 @@ class DescriptorArray: public FixedArray {
static const int kMaxNumberOfDescriptors = 1024 + 512;
private:
friend class IntrusiveMapTransitionIterator;
// An entry in a DescriptorArray, represented as an (array, index) pair.
class Entry {
public:
@ -2615,15 +2625,21 @@ class DescriptorArray: public FixedArray {
// Conversion from descriptor number to array indices.
static int ToKeyIndex(int descriptor_number) {
return descriptor_number+kFirstIndex;
return kFirstIndex +
(descriptor_number * kDescriptorSize) +
kDescriptorKey;
}
static int ToDetailsIndex(int descriptor_number) {
return (descriptor_number << 1) + 1;
return kFirstIndex +
(descriptor_number * kDescriptorSize) +
kDescriptorDetails;
}
static int ToValueIndex(int descriptor_number) {
return descriptor_number << 1;
return kFirstIndex +
(descriptor_number * kDescriptorSize) +
kDescriptorValue;
}
// Swap operation on FixedArray without using write barriers.
@ -2634,10 +2650,6 @@ class DescriptorArray: public FixedArray {
inline void NoIncrementalWriteBarrierSwapDescriptors(
int first, int second);
FixedArray* GetContentArray() {
return FixedArray::cast(get(kContentArrayIndex));
}
DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray);
};