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:
parent
463a6ffdd4
commit
98c37e1f4c
@ -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:
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user