| 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 5070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5081 | 5081 |
| 5082 // An iterator over all map transitions in an descriptor array, reusing the map | 5082 // An iterator over all map transitions in an descriptor array, reusing the map |
| 5083 // field of the contens array while it is running. | 5083 // field of the contens array while it is running. |
| 5084 class IntrusiveMapTransitionIterator { | 5084 class IntrusiveMapTransitionIterator { |
| 5085 public: | 5085 public: |
| 5086 explicit IntrusiveMapTransitionIterator(DescriptorArray* descriptor_array) | 5086 explicit IntrusiveMapTransitionIterator(DescriptorArray* descriptor_array) |
| 5087 : descriptor_array_(descriptor_array) { } | 5087 : descriptor_array_(descriptor_array) { } |
| 5088 | 5088 |
| 5089 void Start() { | 5089 void Start() { |
| 5090 ASSERT(!IsIterating()); | 5090 ASSERT(!IsIterating()); |
| 5091 if (HasDescriptors()) *DescriptorArrayHeader() = Smi::FromInt(0); | 5091 if (HasContentArray()) *ContentHeader() = Smi::FromInt(0); |
| 5092 } | 5092 } |
| 5093 | 5093 |
| 5094 bool IsIterating() { | 5094 bool IsIterating() { |
| 5095 return HasDescriptors() && (*DescriptorArrayHeader())->IsSmi(); | 5095 return HasContentArray() && (*ContentHeader())->IsSmi(); |
| 5096 } | 5096 } |
| 5097 | 5097 |
| 5098 Map* Next() { | 5098 Map* Next() { |
| 5099 ASSERT(IsIterating()); | 5099 ASSERT(IsIterating()); |
| 5100 // Attention, tricky index manipulation ahead: Two consecutive indices are | 5100 FixedArray* contents = ContentArray(); |
| 5101 // assigned to each descriptor. Most descriptors directly advance to the | 5101 // Attention, tricky index manipulation ahead: Every entry in the contents |
| 5102 // next descriptor by adding 2 to the index. The exceptions are the | 5102 // array consists of a value/details pair, so the index is typically even. |
| 5103 // CALLBACKS entries: An even index means we look at its getter, and an odd | 5103 // An exception is made for CALLBACKS entries: An even index means we look |
| 5104 // index means we look at its setter. | 5104 // at its getter, and an odd index means we look at its setter. |
| 5105 int raw_index = Smi::cast(*DescriptorArrayHeader())->value(); | 5105 int index = Smi::cast(*ContentHeader())->value(); |
| 5106 int index = raw_index / 2; | 5106 while (index < contents->length()) { |
| 5107 while (index < descriptor_array_->number_of_descriptors()) { | 5107 PropertyDetails details(Smi::cast(contents->get(index | 1))); |
| 5108 PropertyDetails details(RawGetDetails(index)); | |
| 5109 switch (details.type()) { | 5108 switch (details.type()) { |
| 5110 case MAP_TRANSITION: | 5109 case MAP_TRANSITION: |
| 5111 case CONSTANT_TRANSITION: | 5110 case CONSTANT_TRANSITION: |
| 5112 case ELEMENTS_TRANSITION: | 5111 case ELEMENTS_TRANSITION: |
| 5113 // We definitely have a map transition. | 5112 // We definitely have a map transition. |
| 5114 *DescriptorArrayHeader() = Smi::FromInt(raw_index + 2); | 5113 *ContentHeader() = Smi::FromInt(index + 2); |
| 5115 return static_cast<Map*>(RawGetValue(index)); | 5114 return static_cast<Map*>(contents->get(index)); |
| 5116 case CALLBACKS: { | 5115 case CALLBACKS: { |
| 5117 // We might have a map transition in a getter or in a setter. | 5116 // We might have a map transition in a getter or in a setter. |
| 5118 AccessorPair* accessors = | 5117 AccessorPair* accessors = |
| 5119 static_cast<AccessorPair*>(RawGetValue(index)); | 5118 static_cast<AccessorPair*>(contents->get(index & ~1)); |
| 5120 Object* accessor = ((raw_index & 1) == 0) | 5119 Object* accessor = |
| 5121 ? accessors->getter() | 5120 ((index & 1) == 0) ? accessors->getter() : accessors->setter(); |
| 5122 : accessors->setter(); | 5121 index++; |
| 5123 if (accessor->IsMap()) { | 5122 if (accessor->IsMap()) { |
| 5124 *DescriptorArrayHeader() = Smi::FromInt(raw_index + 1); | 5123 *ContentHeader() = Smi::FromInt(index); |
| 5125 return static_cast<Map*>(accessor); | 5124 return static_cast<Map*>(accessor); |
| 5126 } | 5125 } |
| 5127 break; | 5126 break; |
| 5128 } | 5127 } |
| 5129 case NORMAL: | 5128 case NORMAL: |
| 5130 case FIELD: | 5129 case FIELD: |
| 5131 case CONSTANT_FUNCTION: | 5130 case CONSTANT_FUNCTION: |
| 5132 case HANDLER: | 5131 case HANDLER: |
| 5133 case INTERCEPTOR: | 5132 case INTERCEPTOR: |
| 5134 case NULL_DESCRIPTOR: | 5133 case NULL_DESCRIPTOR: |
| 5135 // We definitely have no map transition. | 5134 // We definitely have no map transition. |
| 5136 raw_index += 2; | 5135 index += 2; |
| 5137 ++index; | |
| 5138 break; | 5136 break; |
| 5139 } | 5137 } |
| 5140 } | 5138 } |
| 5141 *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map(); | 5139 *ContentHeader() = descriptor_array_->GetHeap()->fixed_array_map(); |
| 5142 return NULL; | 5140 return NULL; |
| 5143 } | 5141 } |
| 5144 | 5142 |
| 5145 private: | 5143 private: |
| 5146 bool HasDescriptors() { | 5144 bool HasContentArray() { |
| 5147 return descriptor_array_-> length() > DescriptorArray::kFirstIndex; | 5145 return descriptor_array_-> length() > DescriptorArray::kContentArrayIndex; |
| 5148 } | 5146 } |
| 5149 | 5147 |
| 5150 Object** DescriptorArrayHeader() { | 5148 FixedArray* ContentArray() { |
| 5151 return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset); | 5149 Object* array = descriptor_array_->get(DescriptorArray::kContentArrayIndex); |
| 5150 return static_cast<FixedArray*>(array); |
| 5152 } | 5151 } |
| 5153 | 5152 |
| 5154 FixedArray* RawGetContentArray() { | 5153 Object** ContentHeader() { |
| 5155 Object* array = | 5154 return HeapObject::RawField(ContentArray(), DescriptorArray::kMapOffset); |
| 5156 descriptor_array_->get(DescriptorArray::kContentArrayIndex); | |
| 5157 return static_cast<FixedArray*>(array); | |
| 5158 } | 5155 } |
| 5159 | 5156 |
| 5160 Object* RawGetValue(int descriptor_number) { | |
| 5161 return RawGetContentArray()->get( | |
| 5162 DescriptorArray::ToValueIndex(descriptor_number)); | |
| 5163 } | |
| 5164 | |
| 5165 PropertyDetails RawGetDetails(int descriptor_number) { | |
| 5166 Object* details = RawGetContentArray()->get( | |
| 5167 DescriptorArray::ToDetailsIndex(descriptor_number)); | |
| 5168 return PropertyDetails(Smi::cast(details)); | |
| 5169 } | |
| 5170 | |
| 5171 | |
| 5172 DescriptorArray* descriptor_array_; | 5157 DescriptorArray* descriptor_array_; |
| 5173 }; | 5158 }; |
| 5174 | 5159 |
| 5175 | 5160 |
| 5176 // An iterator over all prototype transitions, reusing the map field of the | 5161 // An iterator over all prototype transitions, reusing the map field of the |
| 5177 // underlying array while it is running. | 5162 // underlying array while it is running. |
| 5178 class IntrusivePrototypeTransitionIterator { | 5163 class IntrusivePrototypeTransitionIterator { |
| 5179 public: | 5164 public: |
| 5180 explicit IntrusivePrototypeTransitionIterator(HeapObject* proto_trans) | 5165 explicit IntrusivePrototypeTransitionIterator(HeapObject* proto_trans) |
| 5181 : proto_trans_(proto_trans) { } | 5166 : proto_trans_(proto_trans) { } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5260 // this map's map! | 5245 // this map's map! |
| 5261 void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); } | 5246 void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); } |
| 5262 | 5247 |
| 5263 // Reset the current map's map, returning the parent previously stored in it. | 5248 // Reset the current map's map, returning the parent previously stored in it. |
| 5264 TraversableMap* GetAndResetParent() { | 5249 TraversableMap* GetAndResetParent() { |
| 5265 TraversableMap* old_parent = static_cast<TraversableMap*>(map()); | 5250 TraversableMap* old_parent = static_cast<TraversableMap*>(map()); |
| 5266 set_map_no_write_barrier(GetHeap()->meta_map()); | 5251 set_map_no_write_barrier(GetHeap()->meta_map()); |
| 5267 return old_parent; | 5252 return old_parent; |
| 5268 } | 5253 } |
| 5269 | 5254 |
| 5270 // Can either be Smi (no instance descriptors), or a descriptor array with the | |
| 5271 // header overwritten as a Smi (thus iterating). | |
| 5272 DescriptorArray* MutatedInstanceDescriptors() { | |
| 5273 Object* object = | |
| 5274 *HeapObject::RawField(this, kInstanceDescriptorsOrBitField3Offset); | |
| 5275 if (object->IsSmi()) { | |
| 5276 return GetHeap()->empty_descriptor_array(); | |
| 5277 } else { | |
| 5278 DescriptorArray* descriptor_array = | |
| 5279 static_cast<DescriptorArray*>(object); | |
| 5280 ASSERT((*HeapObject::RawField(descriptor_array, | |
| 5281 DescriptorArray::kMapOffset))->IsSmi()); | |
| 5282 return descriptor_array; | |
| 5283 } | |
| 5284 } | |
| 5285 | |
| 5286 // Start iterating over this map's children, possibly destroying a FixedArray | 5255 // Start iterating over this map's children, possibly destroying a FixedArray |
| 5287 // map (see explanation above). | 5256 // map (see explanation above). |
| 5288 void ChildIteratorStart() { | 5257 void ChildIteratorStart() { |
| 5289 IntrusiveMapTransitionIterator(instance_descriptors()).Start(); | 5258 IntrusiveMapTransitionIterator(instance_descriptors()).Start(); |
| 5290 IntrusivePrototypeTransitionIterator( | 5259 IntrusivePrototypeTransitionIterator( |
| 5291 unchecked_prototype_transitions()).Start(); | 5260 unchecked_prototype_transitions()).Start(); |
| 5292 } | 5261 } |
| 5293 | 5262 |
| 5294 // If we have an unvisited child map, return that one and advance. If we have | 5263 // If we have an unvisited child map, return that one and advance. If we have |
| 5295 // none, return NULL and reset any destroyed FixedArray maps. | 5264 // none, return NULL and reset any destroyed FixedArray maps. |
| 5296 TraversableMap* ChildIteratorNext() { | 5265 TraversableMap* ChildIteratorNext() { |
| 5266 IntrusiveMapTransitionIterator descriptor_iterator(instance_descriptors()); |
| 5267 if (descriptor_iterator.IsIterating()) { |
| 5268 Map* next = descriptor_iterator.Next(); |
| 5269 if (next != NULL) return static_cast<TraversableMap*>(next); |
| 5270 } |
| 5297 IntrusivePrototypeTransitionIterator | 5271 IntrusivePrototypeTransitionIterator |
| 5298 proto_iterator(unchecked_prototype_transitions()); | 5272 proto_iterator(unchecked_prototype_transitions()); |
| 5299 if (proto_iterator.IsIterating()) { | 5273 if (proto_iterator.IsIterating()) { |
| 5300 Map* next = proto_iterator.Next(); | 5274 Map* next = proto_iterator.Next(); |
| 5301 if (next != NULL) return static_cast<TraversableMap*>(next); | 5275 if (next != NULL) return static_cast<TraversableMap*>(next); |
| 5302 } | 5276 } |
| 5303 IntrusiveMapTransitionIterator | |
| 5304 descriptor_iterator(MutatedInstanceDescriptors()); | |
| 5305 if (descriptor_iterator.IsIterating()) { | |
| 5306 Map* next = descriptor_iterator.Next(); | |
| 5307 if (next != NULL) return static_cast<TraversableMap*>(next); | |
| 5308 } | |
| 5309 return NULL; | 5277 return NULL; |
| 5310 } | 5278 } |
| 5311 }; | 5279 }; |
| 5312 | 5280 |
| 5313 | 5281 |
| 5314 // Traverse the transition tree in postorder without using the C++ stack by | 5282 // Traverse the transition tree in postorder without using the C++ stack by |
| 5315 // doing pointer reversal. | 5283 // doing pointer reversal. |
| 5316 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { | 5284 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { |
| 5317 TraversableMap* current = static_cast<TraversableMap*>(this); | 5285 TraversableMap* current = static_cast<TraversableMap*>(this); |
| 5318 current->ChildIteratorStart(); | 5286 current->ChildIteratorStart(); |
| (...skipping 7908 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13227 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13195 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
| 13228 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13196 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
| 13229 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13197 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
| 13230 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13198 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
| 13231 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13199 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
| 13232 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13200 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
| 13233 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13201 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
| 13234 } | 13202 } |
| 13235 | 13203 |
| 13236 } } // namespace v8::internal | 13204 } } // namespace v8::internal |
| OLD | NEW |