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/10455005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11682 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
8cf2af4392
commit
3a2d4c88f4
@ -5099,39 +5099,46 @@ 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)));
|
int number_of_descriptors = descriptor_array_->number_of_descriptors();
|
||||||
|
while (index < 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;
|
||||||
((index & 1) == 0) ? accessors->getter() : accessors->setter();
|
if ((raw_index & 1) == 0) {
|
||||||
index++;
|
accessor = accessors->setter();
|
||||||
|
} else {
|
||||||
|
++index;
|
||||||
|
accessor = accessors->getter();
|
||||||
|
}
|
||||||
|
++raw_index;
|
||||||
if (accessor->IsMap()) {
|
if (accessor->IsMap()) {
|
||||||
*ContentHeader() = Smi::FromInt(index);
|
*DescriptorArrayHeader() = Smi::FromInt(raw_index);
|
||||||
return static_cast<Map*>(accessor);
|
return static_cast<Map*>(accessor);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -5143,28 +5150,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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -5263,6 +5284,20 @@ 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);
|
||||||
|
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() {
|
||||||
@ -5274,17 +5309,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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2591,6 +2591,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:
|
||||||
@ -2629,6 +2631,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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user