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 |