Commit fd579e3d authored by verwaest@chromium.org's avatar verwaest@chromium.org

TraversableMap only dependent on DescriptorArray

This is the first step towards merging the ContentArray into the DescriptorArray, (hence reclaiming 3 words per descriptor array).

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11665 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0fa7de11
...@@ -5088,39 +5088,40 @@ class IntrusiveMapTransitionIterator { ...@@ -5088,39 +5088,40 @@ class IntrusiveMapTransitionIterator {
void Start() { void Start() {
ASSERT(!IsIterating()); ASSERT(!IsIterating());
if (HasContentArray()) *ContentHeader() = Smi::FromInt(0); if (HasDescriptors()) *DescriptorArrayHeader() = Smi::FromInt(0);
} }
bool IsIterating() { bool IsIterating() {
return HasContentArray() && (*ContentHeader())->IsSmi(); return HasDescriptors() && (*DescriptorArrayHeader())->IsSmi();
} }
Map* Next() { Map* Next() {
ASSERT(IsIterating()); ASSERT(IsIterating());
FixedArray* contents = ContentArray(); // Attention, tricky index manipulation ahead: Two consecutive indices are
// Attention, tricky index manipulation ahead: Every entry in the contents // assigned to each descriptor. Most descriptors directly advance to the
// array consists of a value/details pair, so the index is typically even. // next descriptor by adding 2 to the index. The exceptions are the
// An exception is made for CALLBACKS entries: An even index means we look // CALLBACKS entries: An even index means we look at its getter, and an odd
// at its getter, and an odd index means we look at its setter. // index means we look at its setter.
int index = Smi::cast(*ContentHeader())->value(); int raw_index = Smi::cast(*DescriptorArrayHeader())->value();
while (index < contents->length()) { int index = raw_index / 2;
PropertyDetails details(Smi::cast(contents->get(index | 1))); while (index < descriptor_array_->number_of_descriptors()) {
PropertyDetails details(RawGetDetails(index));
switch (details.type()) { switch (details.type()) {
case MAP_TRANSITION: case MAP_TRANSITION:
case CONSTANT_TRANSITION: case CONSTANT_TRANSITION:
case ELEMENTS_TRANSITION: case ELEMENTS_TRANSITION:
// We definitely have a map transition. // We definitely have a map transition.
*ContentHeader() = Smi::FromInt(index + 2); *DescriptorArrayHeader() = Smi::FromInt(raw_index + 2);
return static_cast<Map*>(contents->get(index)); return static_cast<Map*>(RawGetValue(index));
case CALLBACKS: { case CALLBACKS: {
// We might have a map transition in a getter or in a setter. // We might have a map transition in a getter or in a setter.
AccessorPair* accessors = AccessorPair* accessors =
static_cast<AccessorPair*>(contents->get(index & ~1)); static_cast<AccessorPair*>(RawGetValue(index));
Object* accessor = Object* accessor = ((raw_index & 1) == 0)
((index & 1) == 0) ? accessors->getter() : accessors->setter(); ? accessors->getter()
index++; : accessors->setter();
if (accessor->IsMap()) { if (accessor->IsMap()) {
*ContentHeader() = Smi::FromInt(index); *DescriptorArrayHeader() = Smi::FromInt(raw_index + 1);
return static_cast<Map*>(accessor); return static_cast<Map*>(accessor);
} }
break; break;
...@@ -5132,28 +5133,42 @@ class IntrusiveMapTransitionIterator { ...@@ -5132,28 +5133,42 @@ class IntrusiveMapTransitionIterator {
case INTERCEPTOR: case INTERCEPTOR:
case NULL_DESCRIPTOR: case NULL_DESCRIPTOR:
// We definitely have no map transition. // We definitely have no map transition.
index += 2; raw_index += 2;
++index;
break; break;
} }
} }
*ContentHeader() = descriptor_array_->GetHeap()->fixed_array_map(); *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map();
return NULL; return NULL;
} }
private: private:
bool HasContentArray() { bool HasDescriptors() {
return descriptor_array_-> length() > DescriptorArray::kContentArrayIndex; return descriptor_array_-> length() > DescriptorArray::kFirstIndex;
} }
FixedArray* ContentArray() { Object** DescriptorArrayHeader() {
Object* array = descriptor_array_->get(DescriptorArray::kContentArrayIndex); return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset);
return static_cast<FixedArray*>(array);
} }
Object** ContentHeader() { FixedArray* RawGetContentArray() {
return HeapObject::RawField(ContentArray(), DescriptorArray::kMapOffset); 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_; DescriptorArray* descriptor_array_;
}; };
...@@ -5252,6 +5267,23 @@ class TraversableMap : public Map { ...@@ -5252,6 +5267,23 @@ class TraversableMap : public Map {
return old_parent; 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);
if (object->IsSmi()) {
return GetHeap()->empty_descriptor_array();
} else {
DescriptorArray* descriptor_array =
static_cast<DescriptorArray*>(object);
Object* map =
*HeapObject::RawField(descriptor_array, DescriptorArray::kMapOffset);
ASSERT(map->IsSmi());
return descriptor_array;
}
}
// Start iterating over this map's children, possibly destroying a FixedArray // Start iterating over this map's children, possibly destroying a FixedArray
// map (see explanation above). // map (see explanation above).
void ChildIteratorStart() { void ChildIteratorStart() {
...@@ -5263,17 +5295,18 @@ class TraversableMap : public Map { ...@@ -5263,17 +5295,18 @@ class TraversableMap : public Map {
// If we have an unvisited child map, return that one and advance. If we have // If we have an unvisited child map, return that one and advance. If we have
// none, return NULL and reset any destroyed FixedArray maps. // none, return NULL and reset any destroyed FixedArray maps.
TraversableMap* ChildIteratorNext() { 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 IntrusivePrototypeTransitionIterator
proto_iterator(unchecked_prototype_transitions()); proto_iterator(unchecked_prototype_transitions());
if (proto_iterator.IsIterating()) { if (proto_iterator.IsIterating()) {
Map* next = proto_iterator.Next(); Map* next = proto_iterator.Next();
if (next != NULL) return static_cast<TraversableMap*>(next); if (next != NULL) return static_cast<TraversableMap*>(next);
} }
IntrusiveMapTransitionIterator
descriptor_iterator(MutatedInstanceDescriptors());
if (descriptor_iterator.IsIterating()) {
Map* next = descriptor_iterator.Next();
if (next != NULL) return static_cast<TraversableMap*>(next);
}
return NULL; return NULL;
} }
}; };
......
...@@ -2588,6 +2588,8 @@ class DescriptorArray: public FixedArray { ...@@ -2588,6 +2588,8 @@ class DescriptorArray: public FixedArray {
static const int kMaxNumberOfDescriptors = 1024 + 512; static const int kMaxNumberOfDescriptors = 1024 + 512;
private: private:
friend class IntrusiveMapTransitionIterator;
// An entry in a DescriptorArray, represented as an (array, index) pair. // An entry in a DescriptorArray, represented as an (array, index) pair.
class Entry { class Entry {
public: public:
...@@ -2626,6 +2628,7 @@ class DescriptorArray: public FixedArray { ...@@ -2626,6 +2628,7 @@ class DescriptorArray: public FixedArray {
FixedArray* GetContentArray() { FixedArray* GetContentArray() {
return FixedArray::cast(get(kContentArrayIndex)); return FixedArray::cast(get(kContentArrayIndex));
} }
DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray); DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray);
}; };
......
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