OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 5117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5128 | 5128 |
5129 // An iterator over all prototype transitions, reusing the map field of the | 5129 // An iterator over all prototype transitions, reusing the map field of the |
5130 // underlying array while it is running. | 5130 // underlying array while it is running. |
5131 class IntrusivePrototypeTransitionIterator { | 5131 class IntrusivePrototypeTransitionIterator { |
5132 public: | 5132 public: |
5133 explicit IntrusivePrototypeTransitionIterator(HeapObject* proto_trans) | 5133 explicit IntrusivePrototypeTransitionIterator(HeapObject* proto_trans) |
5134 : proto_trans_(proto_trans) { } | 5134 : proto_trans_(proto_trans) { } |
5135 | 5135 |
5136 void Start() { | 5136 void Start() { |
5137 ASSERT(!IsIterating()); | 5137 ASSERT(!IsIterating()); |
5138 if (HasTransitions()) *Header() = Smi::FromInt(0); | 5138 *Header() = Smi::FromInt(0); |
Michael Starzinger
2012/07/06 13:53:18
Oh yeah, I like that change!
| |
5139 } | 5139 } |
5140 | 5140 |
5141 bool IsIterating() { | 5141 bool IsIterating() { |
5142 return HasTransitions() && (*Header())->IsSmi(); | 5142 return (*Header())->IsSmi(); |
5143 } | 5143 } |
5144 | 5144 |
5145 Map* Next() { | 5145 Map* Next() { |
5146 ASSERT(IsIterating()); | 5146 ASSERT(IsIterating()); |
5147 int transitionNumber = Smi::cast(*Header())->value(); | 5147 int transitionNumber = Smi::cast(*Header())->value(); |
5148 if (transitionNumber < NumberOfTransitions()) { | 5148 if (transitionNumber < NumberOfTransitions()) { |
5149 *Header() = Smi::FromInt(transitionNumber + 1); | 5149 *Header() = Smi::FromInt(transitionNumber + 1); |
5150 return GetTransition(transitionNumber); | 5150 return GetTransition(transitionNumber); |
5151 } | 5151 } |
5152 *Header() = proto_trans_->GetHeap()->fixed_array_map(); | 5152 *Header() = proto_trans_->GetHeap()->fixed_array_map(); |
5153 return NULL; | 5153 return NULL; |
5154 } | 5154 } |
5155 | 5155 |
5156 private: | 5156 private: |
5157 bool HasTransitions() { | |
5158 return proto_trans_->map()->IsSmi() || proto_trans_->IsFixedArray(); | |
5159 } | |
5160 | |
5161 Object** Header() { | 5157 Object** Header() { |
5162 return HeapObject::RawField(proto_trans_, FixedArray::kMapOffset); | 5158 return HeapObject::RawField(proto_trans_, FixedArray::kMapOffset); |
5163 } | 5159 } |
5164 | 5160 |
5165 int NumberOfTransitions() { | 5161 int NumberOfTransitions() { |
5166 ASSERT(HasTransitions()); | |
5167 FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_); | 5162 FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_); |
5168 Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset); | 5163 Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset); |
5169 return Smi::cast(num)->value(); | 5164 return Smi::cast(num)->value(); |
5170 } | 5165 } |
5171 | 5166 |
5172 Map* GetTransition(int transitionNumber) { | 5167 Map* GetTransition(int transitionNumber) { |
5173 ASSERT(HasTransitions()); | |
5174 FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_); | 5168 FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_); |
5175 return Map::cast(proto_trans->get(IndexFor(transitionNumber))); | 5169 return Map::cast(proto_trans->get(IndexFor(transitionNumber))); |
5176 } | 5170 } |
5177 | 5171 |
5178 int IndexFor(int transitionNumber) { | 5172 int IndexFor(int transitionNumber) { |
5179 return Map::kProtoTransitionHeaderSize + | 5173 return Map::kProtoTransitionHeaderSize + |
5180 Map::kProtoTransitionMapOffset + | 5174 Map::kProtoTransitionMapOffset + |
5181 transitionNumber * Map::kProtoTransitionElementsPerEntry; | 5175 transitionNumber * Map::kProtoTransitionElementsPerEntry; |
5182 } | 5176 } |
5183 | 5177 |
(...skipping 29 matching lines...) Expand all Loading... | |
5213 // this map's map! | 5207 // this map's map! |
5214 void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); } | 5208 void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); } |
5215 | 5209 |
5216 // Reset the current map's map, returning the parent previously stored in it. | 5210 // Reset the current map's map, returning the parent previously stored in it. |
5217 TraversableMap* GetAndResetParent() { | 5211 TraversableMap* GetAndResetParent() { |
5218 TraversableMap* old_parent = static_cast<TraversableMap*>(map()); | 5212 TraversableMap* old_parent = static_cast<TraversableMap*>(map()); |
5219 set_map_no_write_barrier(GetHeap()->meta_map()); | 5213 set_map_no_write_barrier(GetHeap()->meta_map()); |
5220 return old_parent; | 5214 return old_parent; |
5221 } | 5215 } |
5222 | 5216 |
5223 // Can either be Smi (no instance descriptors), or a descriptor array with the | |
5224 // header overwritten as a Smi (thus iterating). | |
5225 TransitionArray* MutatedTransitions() { | |
5226 Object* object = *HeapObject::RawField(instance_descriptors(), | |
5227 DescriptorArray::kTransitionsOffset); | |
5228 TransitionArray* transition_array = static_cast<TransitionArray*>(object); | |
5229 return transition_array; | |
5230 } | |
5231 | |
5232 // Start iterating over this map's children, possibly destroying a FixedArray | 5217 // Start iterating over this map's children, possibly destroying a FixedArray |
5233 // map (see explanation above). | 5218 // map (see explanation above). |
5234 void ChildIteratorStart() { | 5219 void ChildIteratorStart() { |
5235 if (HasTransitionArray()) { | 5220 if (HasTransitionArray()) { |
5221 if (HasPrototypeTransitions()) { | |
5222 IntrusivePrototypeTransitionIterator(prototype_transitions()).Start(); | |
5223 } | |
5224 | |
5236 IntrusiveMapTransitionIterator(transitions()).Start(); | 5225 IntrusiveMapTransitionIterator(transitions()).Start(); |
5237 } | 5226 } |
5238 IntrusivePrototypeTransitionIterator( | |
5239 unchecked_prototype_transitions()).Start(); | |
5240 } | 5227 } |
5241 | 5228 |
5242 // If we have an unvisited child map, return that one and advance. If we have | 5229 // If we have an unvisited child map, return that one and advance. If we have |
5243 // none, return NULL and reset any destroyed FixedArray maps. | 5230 // none, return NULL and reset any destroyed FixedArray maps. |
5244 TraversableMap* ChildIteratorNext() { | 5231 TraversableMap* ChildIteratorNext() { |
5245 IntrusivePrototypeTransitionIterator | |
5246 proto_iterator(unchecked_prototype_transitions()); | |
5247 if (proto_iterator.IsIterating()) { | |
5248 Map* next = proto_iterator.Next(); | |
5249 if (next != NULL) return static_cast<TraversableMap*>(next); | |
5250 } | |
5251 if (HasTransitionArray()) { | 5232 if (HasTransitionArray()) { |
5252 IntrusiveMapTransitionIterator | 5233 TransitionArray* transition_array = unchecked_transition_array(); |
5253 transitions_iterator(MutatedTransitions()); | 5234 |
5254 if (transitions_iterator.IsIterating()) { | 5235 if (transition_array->HasPrototypeTransitions()) { |
5255 Map* next = transitions_iterator.Next(); | 5236 HeapObject* proto_transitions = |
5237 transition_array->unchecked_prototype_transitions(); | |
5238 IntrusivePrototypeTransitionIterator proto_iterator(proto_transitions); | |
5239 if (proto_iterator.IsIterating()) { | |
5240 Map* next = proto_iterator.Next(); | |
5241 if (next != NULL) return static_cast<TraversableMap*>(next); | |
5242 } | |
5243 } | |
5244 | |
5245 IntrusiveMapTransitionIterator transition_iterator(transition_array); | |
5246 if (transition_iterator.IsIterating()) { | |
5247 Map* next = transition_iterator.Next(); | |
5256 if (next != NULL) return static_cast<TraversableMap*>(next); | 5248 if (next != NULL) return static_cast<TraversableMap*>(next); |
5257 } | 5249 } |
5258 } | 5250 } |
5251 | |
5259 return NULL; | 5252 return NULL; |
5260 } | 5253 } |
5261 }; | 5254 }; |
5262 | 5255 |
5263 | 5256 |
5264 // Traverse the transition tree in postorder without using the C++ stack by | 5257 // Traverse the transition tree in postorder without using the C++ stack by |
5265 // doing pointer reversal. | 5258 // doing pointer reversal. |
5266 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { | 5259 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { |
5267 TraversableMap* current = static_cast<TraversableMap*>(this); | 5260 TraversableMap* current = static_cast<TraversableMap*>(this); |
5268 current->ChildIteratorStart(); | 5261 current->ChildIteratorStart(); |
(...skipping 2128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7397 t->ClearElementsTransition(); | 7390 t->ClearElementsTransition(); |
7398 } else { | 7391 } else { |
7399 // If there are no transitions to be cleared, return. | 7392 // If there are no transitions to be cleared, return. |
7400 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 7393 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
7401 // properly cleared. | 7394 // properly cleared. |
7402 if (transition_index == t->number_of_transitions()) return; | 7395 if (transition_index == t->number_of_transitions()) return; |
7403 } | 7396 } |
7404 | 7397 |
7405 // If the final transition array does not contain any live transitions, remove | 7398 // If the final transition array does not contain any live transitions, remove |
7406 // the transition array from the map. | 7399 // the transition array from the map. |
7407 if (transition_index == 0 && !t->HasElementsTransition()) { | 7400 if (transition_index == 0 && |
7401 !t->HasElementsTransition() && | |
7402 !t->HasPrototypeTransitions()) { | |
7408 return ClearTransitions(); | 7403 return ClearTransitions(); |
7409 } | 7404 } |
7410 | 7405 |
7411 int trim = t->number_of_transitions() - transition_index; | 7406 int trim = t->number_of_transitions() - transition_index; |
7412 if (trim > 0) { | 7407 if (trim > 0) { |
7413 RightTrimFixedArray(heap, t, trim * TransitionArray::kTransitionSize); | 7408 RightTrimFixedArray(heap, t, trim * TransitionArray::kTransitionSize); |
7414 } | 7409 } |
7415 } | 7410 } |
7416 | 7411 |
7417 | 7412 |
(...skipping 1442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8860 // Grow array by factor 2 over and above what we need. | 8855 // Grow array by factor 2 over and above what we need. |
8861 { MaybeObject* maybe_cache = | 8856 { MaybeObject* maybe_cache = |
8862 GetHeap()->AllocateFixedArray(transitions * 2 * step + header); | 8857 GetHeap()->AllocateFixedArray(transitions * 2 * step + header); |
8863 if (!maybe_cache->To(&new_cache)) return maybe_cache; | 8858 if (!maybe_cache->To(&new_cache)) return maybe_cache; |
8864 } | 8859 } |
8865 | 8860 |
8866 for (int i = 0; i < capacity * step; i++) { | 8861 for (int i = 0; i < capacity * step; i++) { |
8867 new_cache->set(i + header, cache->get(i + header)); | 8862 new_cache->set(i + header, cache->get(i + header)); |
8868 } | 8863 } |
8869 cache = new_cache; | 8864 cache = new_cache; |
8870 set_prototype_transitions(cache); | 8865 MaybeObject* set_result = set_prototype_transitions(cache); |
8866 if (set_result->IsFailure()) return set_result; | |
8871 } | 8867 } |
8872 | 8868 |
8873 int last = transitions - 1; | 8869 int last = transitions - 1; |
8874 | 8870 |
8875 cache->set(header + last * step + kProtoTransitionPrototypeOffset, prototype); | 8871 cache->set(header + last * step + kProtoTransitionPrototypeOffset, prototype); |
8876 cache->set(header + last * step + kProtoTransitionMapOffset, map); | 8872 cache->set(header + last * step + kProtoTransitionMapOffset, map); |
8877 SetNumberOfProtoTransitions(transitions); | 8873 SetNumberOfProtoTransitions(transitions); |
8878 | 8874 |
8879 return cache; | 8875 return cache; |
8880 } | 8876 } |
(...skipping 4382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13263 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13259 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13264 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13260 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13265 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13261 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13266 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13262 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13267 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13263 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13268 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13264 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13269 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13265 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13270 } | 13266 } |
13271 | 13267 |
13272 } } // namespace v8::internal | 13268 } } // namespace v8::internal |
OLD | NEW |