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