| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 431952811b36f8e4496905f49791786f6460a437..0232b969f1e4f2ce48d72a0fd7ac126458e697e5 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -5089,39 +5089,40 @@ 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 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 raw_index = Smi::cast(*DescriptorArrayHeader())->value();
|
| + int index = raw_index / 2;
|
| + while (index < descriptor_array_->number_of_descriptors()) {
|
| + PropertyDetails details(RawGetDetails(index));
|
| 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(raw_index + 2);
|
| + return static_cast<Map*>(RawGetValue(index));
|
| case CALLBACKS: {
|
| // We might have a map transition in a getter or in a setter.
|
| AccessorPair* accessors =
|
| - static_cast<AccessorPair*>(contents->get(index & ~1));
|
| - Object* accessor =
|
| - ((index & 1) == 0) ? accessors->getter() : accessors->setter();
|
| - index++;
|
| + static_cast<AccessorPair*>(RawGetValue(index));
|
| + Object* accessor = ((raw_index & 1) == 0)
|
| + ? accessors->getter()
|
| + : accessors->setter();
|
| if (accessor->IsMap()) {
|
| - *ContentHeader() = Smi::FromInt(index);
|
| + *DescriptorArrayHeader() = Smi::FromInt(raw_index + 1);
|
| return static_cast<Map*>(accessor);
|
| }
|
| break;
|
| @@ -5133,28 +5134,42 @@ class IntrusiveMapTransitionIterator {
|
| case INTERCEPTOR:
|
| case NULL_DESCRIPTOR:
|
| // We definitely have no map transition.
|
| - index += 2;
|
| + raw_index += 2;
|
| + ++index;
|
| 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_-> length() > DescriptorArray::kFirstIndex;
|
| }
|
|
|
| - FixedArray* ContentArray() {
|
| - Object* array = descriptor_array_->get(DescriptorArray::kContentArrayIndex);
|
| - return static_cast<FixedArray*>(array);
|
| + Object** DescriptorArrayHeader() {
|
| + return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset);
|
| }
|
|
|
| - Object** ContentHeader() {
|
| - return HeapObject::RawField(ContentArray(), 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_;
|
| };
|
|
|
| @@ -5253,6 +5268,23 @@ 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);
|
| + 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
|
| // map (see explanation above).
|
| void ChildIteratorStart() {
|
| @@ -5264,17 +5296,18 @@ 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());
|
| + if (descriptor_iterator.IsIterating()) {
|
| + Map* next = descriptor_iterator.Next();
|
| + if (next != NULL) return static_cast<TraversableMap*>(next);
|
| + }
|
| return NULL;
|
| }
|
| };
|
|
|