Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(803)

Unified Diff: src/objects.cc

Issue 10412030: Merging ContentArray into DescriptorArray (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix unused variable in release mode Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index cb87c71fb1193c38953701a88ffac4e1f465d9cd..d04518c8021bd011a5cd8453a05380ab19e36bfb 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -4889,39 +4889,39 @@ class IntrusiveMapTransitionIterator {
void Start() {
ASSERT(!IsIterating());
- if (HasContentArray()) *ContentHeader() = Smi::FromInt(0);
+ if (HasDescriptors()) *DescriptorArrayHeader() = Smi::FromInt(0);
}
bool IsIterating() {
- return HasContentArray() && (*ContentHeader())->IsSmi();
+ return HasDescriptors() && (*DescriptorArrayHeader())->IsSmi();
}
Map* Next() {
ASSERT(IsIterating());
- FixedArray* contents = ContentArray();
- // Attention, tricky index manipulation ahead: Every entry in the contents
- // array consists of a value/details pair, so the index is typically even.
- // An exception is made for CALLBACKS entries: An even index means we look
- // at its getter, and an odd index means we look at its setter.
- int index = Smi::cast(*ContentHeader())->value();
- while (index < contents->length()) {
- PropertyDetails details(Smi::cast(contents->get(index | 1)));
+ // Attention, tricky index manipulation ahead: Two two consecutive indices
+ // are assigned to each descriptor. Most descriptors directly advance to the
+ // next descriptor by adding 2 to the index. The exceptions are the
+ // CALLBACKS entries: An even index means we look at its getter, and an odd
+ // index means we look at its setter.
+ int index = Smi::cast(*DescriptorArrayHeader())->value();
+ while ((index / 2) < descriptor_array_->number_of_descriptors()) {
+ PropertyDetails details(descriptor_array_->GetDetails(index / 2));
switch (details.type()) {
case MAP_TRANSITION:
case CONSTANT_TRANSITION:
case ELEMENTS_TRANSITION:
// We definitely have a map transition.
- *ContentHeader() = Smi::FromInt(index + 2);
- return static_cast<Map*>(contents->get(index));
+ *DescriptorArrayHeader() = Smi::FromInt(index + 2);
+ return static_cast<Map*>(descriptor_array_->GetValue(index / 2));
case CALLBACKS: {
// We might have a map transition in a getter or in a setter.
AccessorPair* accessors =
- static_cast<AccessorPair*>(contents->get(index & ~1));
+ static_cast<AccessorPair*>(descriptor_array_->GetValue(index / 2));
Florian Schneider 2012/05/22 16:53:09 Long line.
Object* accessor =
((index & 1) == 0) ? accessors->getter() : accessors->setter();
index++;
if (accessor->IsMap()) {
- *ContentHeader() = Smi::FromInt(index);
+ *DescriptorArrayHeader() = Smi::FromInt(index);
return static_cast<Map*>(accessor);
}
break;
@@ -4937,22 +4937,17 @@ class IntrusiveMapTransitionIterator {
break;
}
}
- *ContentHeader() = descriptor_array_->GetHeap()->fixed_array_map();
+ *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map();
return NULL;
}
private:
- bool HasContentArray() {
- return descriptor_array_-> length() > DescriptorArray::kContentArrayIndex;
+ bool HasDescriptors() {
+ return !descriptor_array_->IsEmpty();
}
- FixedArray* ContentArray() {
- Object* array = descriptor_array_->get(DescriptorArray::kContentArrayIndex);
- return static_cast<FixedArray*>(array);
- }
-
- Object** ContentHeader() {
- return HeapObject::RawField(ContentArray(), DescriptorArray::kMapOffset);
+ Object** DescriptorArrayHeader() {
+ return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset);
}
DescriptorArray* descriptor_array_;
@@ -5053,6 +5048,20 @@ class TraversableMap : public Map {
return old_parent;
}
+ // Can either be Smi (no instance descriptors), or a descriptor array with the
+ // header overwritten as a Smi (thus iterating).
+ DescriptorArray* MutatedInstanceDescriptors() {
+ Object* object = *HeapObject::RawField(this, kInstanceDescriptorsOrBitField3Offset);
Florian Schneider 2012/05/22 16:53:09 Long line.
+ if (object->IsSmi()) {
+ return GetHeap()->empty_descriptor_array();
+ } else {
+ DescriptorArray* descriptor_array = static_cast<DescriptorArray*>(object);
+ ASSERT((*HeapObject::RawField(descriptor_array,
+ DescriptorArray::kMapOffset))->IsSmi());
+ return descriptor_array;
+ }
+ }
+
// Start iterating over this map's children, possibly destroying a FixedArray
// map (see explanation above).
void ChildIteratorStart() {
@@ -5064,17 +5073,17 @@ class TraversableMap : public Map {
// If we have an unvisited child map, return that one and advance. If we have
// none, return NULL and reset any destroyed FixedArray maps.
TraversableMap* ChildIteratorNext() {
- IntrusiveMapTransitionIterator descriptor_iterator(instance_descriptors());
- if (descriptor_iterator.IsIterating()) {
- Map* next = descriptor_iterator.Next();
- if (next != NULL) return static_cast<TraversableMap*>(next);
- }
IntrusivePrototypeTransitionIterator
proto_iterator(unchecked_prototype_transitions());
if (proto_iterator.IsIterating()) {
Map* next = proto_iterator.Next();
if (next != NULL) return static_cast<TraversableMap*>(next);
}
+ IntrusiveMapTransitionIterator descriptor_iterator(MutatedInstanceDescriptors());
Florian Schneider 2012/05/22 16:53:09 Long line.
+ if (descriptor_iterator.IsIterating()) {
+ Map* next = descriptor_iterator.Next();
+ if (next != NULL) return static_cast<TraversableMap*>(next);
+ }
return NULL;
}
};
@@ -5638,13 +5647,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;
@@ -5829,7 +5832,11 @@ MaybeObject* DescriptorArray::RemoveTransitions() {
return new_descriptors;
}
-
+// The whiteness witness is needed since sort will reshuffle the entries in the
+// descriptor array. If the descriptor array were to be gray, the sort would
+// potentially swap a black and a white member. This would result in
+// accidentally reclaiming the white member if the descriptor array owned the
+// unique pointer.
void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) {
// In-place heap sort.
int len = number_of_descriptors();
@@ -5974,9 +5981,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
@@ -7198,23 +7205,20 @@ void Map::ClearNonLiveTransitions(Heap* heap) {
if (d->IsEmpty()) return;
Smi* NullDescriptorDetails =
PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi();
- FixedArray* contents = FixedArray::cast(
- d->get(DescriptorArray::kContentArrayIndex));
- ASSERT(contents->length() >= 2);
- for (int i = 0; i < contents->length(); i += 2) {
+ for (int i = 0; i < d->number_of_descriptors(); ++i) {
// If the pair (value, details) is a map transition, check if the target is
// live. If not, null the descriptor. Also drop the back pointer for that
// map transition, so that this map is not reached again by following a back
// pointer from that non-live map.
bool keep_entry = false;
- PropertyDetails details(Smi::cast(contents->get(i + 1)));
+ PropertyDetails details(d->GetDetails(i));
switch (details.type()) {
case MAP_TRANSITION:
case CONSTANT_TRANSITION:
- ClearBackPointer(heap, contents->get(i), &keep_entry);
+ ClearBackPointer(heap, d->GetValue(i), &keep_entry);
break;
case ELEMENTS_TRANSITION: {
- Object* object = contents->get(i);
+ Object* object = d->GetValue(i);
if (object->IsMap()) {
ClearBackPointer(heap, object, &keep_entry);
} else {
@@ -7228,7 +7232,7 @@ void Map::ClearNonLiveTransitions(Heap* heap) {
break;
}
case CALLBACKS: {
- Object* object = contents->get(i);
+ Object* object = d->GetValue(i);
if (object->IsAccessorPair()) {
AccessorPair* accessors = AccessorPair::cast(object);
if (ClearBackPointer(heap, accessors->getter(), &keep_entry)) {
@@ -7255,8 +7259,8 @@ void Map::ClearNonLiveTransitions(Heap* heap) {
// What we *really* want to do here is removing this entry completely, but
// for technical reasons we can't do this, so we zero it out instead.
if (!keep_entry) {
- contents->set_unchecked(i + 1, NullDescriptorDetails);
- contents->set_null_unchecked(heap, i);
+ d->SetDetailsUnchecked(i, NullDescriptorDetails);
+ d->SetNullValueUnchecked(i, heap);
}
}
}

Powered by Google App Engine
This is Rietveld 408576698