Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 03f5e553a4bf65981fc10858d904a1499947224e..56e8ada4afd3b1c172ce9b6d59b079154912b418 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -5135,11 +5135,11 @@ class IntrusivePrototypeTransitionIterator { |
void Start() { |
ASSERT(!IsIterating()); |
- if (HasTransitions()) *Header() = Smi::FromInt(0); |
+ *Header() = Smi::FromInt(0); |
} |
bool IsIterating() { |
- return HasTransitions() && (*Header())->IsSmi(); |
+ return (*Header())->IsSmi(); |
} |
Map* Next() { |
@@ -5154,23 +5154,17 @@ class IntrusivePrototypeTransitionIterator { |
} |
private: |
- bool HasTransitions() { |
- return proto_trans_->map()->IsSmi() || proto_trans_->IsFixedArray(); |
- } |
- |
Object** Header() { |
return HeapObject::RawField(proto_trans_, FixedArray::kMapOffset); |
} |
int NumberOfTransitions() { |
- ASSERT(HasTransitions()); |
FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_); |
Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset); |
return Smi::cast(num)->value(); |
} |
Map* GetTransition(int transitionNumber) { |
- ASSERT(HasTransitions()); |
FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_); |
return Map::cast(proto_trans->get(IndexFor(transitionNumber))); |
} |
@@ -5220,42 +5214,41 @@ 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). |
- TransitionArray* MutatedTransitions() { |
- Object* object = *HeapObject::RawField(instance_descriptors(), |
- DescriptorArray::kTransitionsOffset); |
- TransitionArray* transition_array = static_cast<TransitionArray*>(object); |
- return transition_array; |
- } |
- |
// Start iterating over this map's children, possibly destroying a FixedArray |
// map (see explanation above). |
void ChildIteratorStart() { |
if (HasTransitionArray()) { |
+ if (HasPrototypeTransitions()) { |
+ IntrusivePrototypeTransitionIterator(GetPrototypeTransitions()).Start(); |
+ } |
+ |
IntrusiveMapTransitionIterator(transitions()).Start(); |
} |
- IntrusivePrototypeTransitionIterator( |
- unchecked_prototype_transitions()).Start(); |
} |
// 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() { |
- IntrusivePrototypeTransitionIterator |
- proto_iterator(unchecked_prototype_transitions()); |
- if (proto_iterator.IsIterating()) { |
- Map* next = proto_iterator.Next(); |
- if (next != NULL) return static_cast<TraversableMap*>(next); |
- } |
if (HasTransitionArray()) { |
- IntrusiveMapTransitionIterator |
- transitions_iterator(MutatedTransitions()); |
- if (transitions_iterator.IsIterating()) { |
- Map* next = transitions_iterator.Next(); |
+ TransitionArray* transition_array = unchecked_transition_array(); |
+ |
+ if (transition_array->HasPrototypeTransitions()) { |
+ HeapObject* proto_transitions = |
+ transition_array->UncheckedPrototypeTransitions(); |
+ IntrusivePrototypeTransitionIterator proto_iterator(proto_transitions); |
+ if (proto_iterator.IsIterating()) { |
+ Map* next = proto_iterator.Next(); |
+ if (next != NULL) return static_cast<TraversableMap*>(next); |
+ } |
+ } |
+ |
+ IntrusiveMapTransitionIterator transition_iterator(transition_array); |
+ if (transition_iterator.IsIterating()) { |
+ Map* next = transition_iterator.Next(); |
if (next != NULL) return static_cast<TraversableMap*>(next); |
} |
} |
+ |
return NULL; |
} |
}; |
@@ -7404,7 +7397,9 @@ void Map::ClearNonLiveTransitions(Heap* heap) { |
// If the final transition array does not contain any live transitions, remove |
// the transition array from the map. |
- if (transition_index == 0 && !t->HasElementsTransition()) { |
+ if (transition_index == 0 && |
+ !t->HasElementsTransition() && |
+ !t->HasPrototypeTransitions()) { |
return ClearTransitions(); |
} |
@@ -8822,7 +8817,7 @@ MaybeObject* JSArray::SetElementsLength(Object* len) { |
Map* Map::GetPrototypeTransition(Object* prototype) { |
- FixedArray* cache = prototype_transitions(); |
+ FixedArray* cache = GetPrototypeTransitions(); |
int number_of_transitions = NumberOfProtoTransitions(); |
const int proto_offset = |
kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; |
@@ -8844,7 +8839,7 @@ MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) { |
// Don't cache prototype transition if this map is shared. |
if (is_shared() || !FLAG_cache_prototype_transitions) return this; |
- FixedArray* cache = prototype_transitions(); |
+ FixedArray* cache = GetPrototypeTransitions(); |
const int step = kProtoTransitionElementsPerEntry; |
const int header = kProtoTransitionHeaderSize; |
@@ -8867,7 +8862,8 @@ MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) { |
new_cache->set(i + header, cache->get(i + header)); |
} |
cache = new_cache; |
- set_prototype_transitions(cache); |
+ MaybeObject* set_result = SetPrototypeTransitions(cache); |
+ if (set_result->IsFailure()) return set_result; |
} |
int last = transitions - 1; |