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