| 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;
|
|
|