Chromium Code Reviews| 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 |