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 5081 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5092 | 5092 |
5093 // An iterator over all map transitions in an descriptor array, reusing the map | 5093 // An iterator over all map transitions in an descriptor array, reusing the map |
5094 // field of the contens array while it is running. | 5094 // field of the contens array while it is running. |
5095 class IntrusiveMapTransitionIterator { | 5095 class IntrusiveMapTransitionIterator { |
5096 public: | 5096 public: |
5097 explicit IntrusiveMapTransitionIterator(DescriptorArray* descriptor_array) | 5097 explicit IntrusiveMapTransitionIterator(DescriptorArray* descriptor_array) |
5098 : descriptor_array_(descriptor_array) { } | 5098 : descriptor_array_(descriptor_array) { } |
5099 | 5099 |
5100 void Start() { | 5100 void Start() { |
5101 ASSERT(!IsIterating()); | 5101 ASSERT(!IsIterating()); |
5102 if (HasContentArray()) *ContentHeader() = Smi::FromInt(0); | 5102 if (HasDescriptors()) *DescriptorArrayHeader() = Smi::FromInt(0); |
5103 } | 5103 } |
5104 | 5104 |
5105 bool IsIterating() { | 5105 bool IsIterating() { |
5106 return HasContentArray() && (*ContentHeader())->IsSmi(); | 5106 return HasDescriptors() && (*DescriptorArrayHeader())->IsSmi(); |
5107 } | 5107 } |
5108 | 5108 |
5109 Map* Next() { | 5109 Map* Next() { |
5110 ASSERT(IsIterating()); | 5110 ASSERT(IsIterating()); |
5111 FixedArray* contents = ContentArray(); | 5111 // Attention, tricky index manipulation ahead: Two consecutive indices are |
5112 // Attention, tricky index manipulation ahead: Every entry in the contents | 5112 // assigned to each descriptor. Most descriptors directly advance to the |
5113 // array consists of a value/details pair, so the index is typically even. | 5113 // next descriptor by adding 2 to the index. The exceptions are the |
5114 // An exception is made for CALLBACKS entries: An even index means we look | 5114 // CALLBACKS entries: An even index means we look at its getter, and an odd |
5115 // at its getter, and an odd index means we look at its setter. | 5115 // index means we look at its setter. |
5116 int index = Smi::cast(*ContentHeader())->value(); | 5116 int raw_index = Smi::cast(*DescriptorArrayHeader())->value(); |
5117 while (index < contents->length()) { | 5117 int index = raw_index / 2; |
5118 PropertyDetails details(Smi::cast(contents->get(index | 1))); | 5118 int number_of_descriptors = descriptor_array_->number_of_descriptors(); |
| 5119 while (index < number_of_descriptors) { |
| 5120 PropertyDetails details(RawGetDetails(index)); |
5119 switch (details.type()) { | 5121 switch (details.type()) { |
5120 case MAP_TRANSITION: | 5122 case MAP_TRANSITION: |
5121 case CONSTANT_TRANSITION: | 5123 case CONSTANT_TRANSITION: |
5122 case ELEMENTS_TRANSITION: | 5124 case ELEMENTS_TRANSITION: |
5123 // We definitely have a map transition. | 5125 // We definitely have a map transition. |
5124 *ContentHeader() = Smi::FromInt(index + 2); | 5126 *DescriptorArrayHeader() = Smi::FromInt(raw_index + 2); |
5125 return static_cast<Map*>(contents->get(index)); | 5127 return static_cast<Map*>(RawGetValue(index)); |
5126 case CALLBACKS: { | 5128 case CALLBACKS: { |
5127 // We might have a map transition in a getter or in a setter. | 5129 // We might have a map transition in a getter or in a setter. |
5128 AccessorPair* accessors = | 5130 AccessorPair* accessors = |
5129 static_cast<AccessorPair*>(contents->get(index & ~1)); | 5131 static_cast<AccessorPair*>(RawGetValue(index)); |
5130 Object* accessor = | 5132 Object* accessor; |
5131 ((index & 1) == 0) ? accessors->getter() : accessors->setter(); | 5133 if ((raw_index & 1) == 0) { |
5132 index++; | 5134 accessor = accessors->setter(); |
| 5135 } else { |
| 5136 ++index; |
| 5137 accessor = accessors->getter(); |
| 5138 } |
| 5139 ++raw_index; |
5133 if (accessor->IsMap()) { | 5140 if (accessor->IsMap()) { |
5134 *ContentHeader() = Smi::FromInt(index); | 5141 *DescriptorArrayHeader() = Smi::FromInt(raw_index); |
5135 return static_cast<Map*>(accessor); | 5142 return static_cast<Map*>(accessor); |
5136 } | 5143 } |
5137 break; | 5144 break; |
5138 } | 5145 } |
5139 case NORMAL: | 5146 case NORMAL: |
5140 case FIELD: | 5147 case FIELD: |
5141 case CONSTANT_FUNCTION: | 5148 case CONSTANT_FUNCTION: |
5142 case HANDLER: | 5149 case HANDLER: |
5143 case INTERCEPTOR: | 5150 case INTERCEPTOR: |
5144 case NULL_DESCRIPTOR: | 5151 case NULL_DESCRIPTOR: |
5145 // We definitely have no map transition. | 5152 // We definitely have no map transition. |
5146 index += 2; | 5153 raw_index += 2; |
| 5154 ++index; |
5147 break; | 5155 break; |
5148 } | 5156 } |
5149 } | 5157 } |
5150 *ContentHeader() = descriptor_array_->GetHeap()->fixed_array_map(); | 5158 *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map(); |
5151 return NULL; | 5159 return NULL; |
5152 } | 5160 } |
5153 | 5161 |
5154 private: | 5162 private: |
5155 bool HasContentArray() { | 5163 bool HasDescriptors() { |
5156 return descriptor_array_-> length() > DescriptorArray::kContentArrayIndex; | 5164 return descriptor_array_->length() > DescriptorArray::kFirstIndex; |
5157 } | 5165 } |
5158 | 5166 |
5159 FixedArray* ContentArray() { | 5167 Object** DescriptorArrayHeader() { |
5160 Object* array = descriptor_array_->get(DescriptorArray::kContentArrayIndex); | 5168 return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset); |
5161 return static_cast<FixedArray*>(array); | |
5162 } | 5169 } |
5163 | 5170 |
5164 Object** ContentHeader() { | 5171 FixedArray* RawGetContentArray() { |
5165 return HeapObject::RawField(ContentArray(), DescriptorArray::kMapOffset); | 5172 Object* array = |
| 5173 descriptor_array_->get(DescriptorArray::kContentArrayIndex); |
| 5174 return static_cast<FixedArray*>(array); |
5166 } | 5175 } |
5167 | 5176 |
| 5177 Object* RawGetValue(int descriptor_number) { |
| 5178 return RawGetContentArray()->get( |
| 5179 DescriptorArray::ToValueIndex(descriptor_number)); |
| 5180 } |
| 5181 |
| 5182 PropertyDetails RawGetDetails(int descriptor_number) { |
| 5183 Object* details = RawGetContentArray()->get( |
| 5184 DescriptorArray::ToDetailsIndex(descriptor_number)); |
| 5185 return PropertyDetails(Smi::cast(details)); |
| 5186 } |
| 5187 |
| 5188 |
5168 DescriptorArray* descriptor_array_; | 5189 DescriptorArray* descriptor_array_; |
5169 }; | 5190 }; |
5170 | 5191 |
5171 | 5192 |
5172 // An iterator over all prototype transitions, reusing the map field of the | 5193 // An iterator over all prototype transitions, reusing the map field of the |
5173 // underlying array while it is running. | 5194 // underlying array while it is running. |
5174 class IntrusivePrototypeTransitionIterator { | 5195 class IntrusivePrototypeTransitionIterator { |
5175 public: | 5196 public: |
5176 explicit IntrusivePrototypeTransitionIterator(HeapObject* proto_trans) | 5197 explicit IntrusivePrototypeTransitionIterator(HeapObject* proto_trans) |
5177 : proto_trans_(proto_trans) { } | 5198 : proto_trans_(proto_trans) { } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5256 // this map's map! | 5277 // this map's map! |
5257 void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); } | 5278 void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); } |
5258 | 5279 |
5259 // Reset the current map's map, returning the parent previously stored in it. | 5280 // Reset the current map's map, returning the parent previously stored in it. |
5260 TraversableMap* GetAndResetParent() { | 5281 TraversableMap* GetAndResetParent() { |
5261 TraversableMap* old_parent = static_cast<TraversableMap*>(map()); | 5282 TraversableMap* old_parent = static_cast<TraversableMap*>(map()); |
5262 set_map_no_write_barrier(GetHeap()->meta_map()); | 5283 set_map_no_write_barrier(GetHeap()->meta_map()); |
5263 return old_parent; | 5284 return old_parent; |
5264 } | 5285 } |
5265 | 5286 |
| 5287 // Can either be Smi (no instance descriptors), or a descriptor array with the |
| 5288 // header overwritten as a Smi (thus iterating). |
| 5289 DescriptorArray* MutatedInstanceDescriptors() { |
| 5290 Object* object = |
| 5291 *HeapObject::RawField(this, kInstanceDescriptorsOrBitField3Offset); |
| 5292 if (object->IsSmi()) { |
| 5293 return GetHeap()->empty_descriptor_array(); |
| 5294 } else { |
| 5295 DescriptorArray* descriptor_array = |
| 5296 static_cast<DescriptorArray*>(object); |
| 5297 return descriptor_array; |
| 5298 } |
| 5299 } |
| 5300 |
5266 // Start iterating over this map's children, possibly destroying a FixedArray | 5301 // Start iterating over this map's children, possibly destroying a FixedArray |
5267 // map (see explanation above). | 5302 // map (see explanation above). |
5268 void ChildIteratorStart() { | 5303 void ChildIteratorStart() { |
5269 IntrusiveMapTransitionIterator(instance_descriptors()).Start(); | 5304 IntrusiveMapTransitionIterator(instance_descriptors()).Start(); |
5270 IntrusivePrototypeTransitionIterator( | 5305 IntrusivePrototypeTransitionIterator( |
5271 unchecked_prototype_transitions()).Start(); | 5306 unchecked_prototype_transitions()).Start(); |
5272 } | 5307 } |
5273 | 5308 |
5274 // If we have an unvisited child map, return that one and advance. If we have | 5309 // If we have an unvisited child map, return that one and advance. If we have |
5275 // none, return NULL and reset any destroyed FixedArray maps. | 5310 // none, return NULL and reset any destroyed FixedArray maps. |
5276 TraversableMap* ChildIteratorNext() { | 5311 TraversableMap* ChildIteratorNext() { |
5277 IntrusiveMapTransitionIterator descriptor_iterator(instance_descriptors()); | |
5278 if (descriptor_iterator.IsIterating()) { | |
5279 Map* next = descriptor_iterator.Next(); | |
5280 if (next != NULL) return static_cast<TraversableMap*>(next); | |
5281 } | |
5282 IntrusivePrototypeTransitionIterator | 5312 IntrusivePrototypeTransitionIterator |
5283 proto_iterator(unchecked_prototype_transitions()); | 5313 proto_iterator(unchecked_prototype_transitions()); |
5284 if (proto_iterator.IsIterating()) { | 5314 if (proto_iterator.IsIterating()) { |
5285 Map* next = proto_iterator.Next(); | 5315 Map* next = proto_iterator.Next(); |
5286 if (next != NULL) return static_cast<TraversableMap*>(next); | 5316 if (next != NULL) return static_cast<TraversableMap*>(next); |
5287 } | 5317 } |
| 5318 IntrusiveMapTransitionIterator |
| 5319 descriptor_iterator(MutatedInstanceDescriptors()); |
| 5320 if (descriptor_iterator.IsIterating()) { |
| 5321 Map* next = descriptor_iterator.Next(); |
| 5322 if (next != NULL) return static_cast<TraversableMap*>(next); |
| 5323 } |
5288 return NULL; | 5324 return NULL; |
5289 } | 5325 } |
5290 }; | 5326 }; |
5291 | 5327 |
5292 | 5328 |
5293 // Traverse the transition tree in postorder without using the C++ stack by | 5329 // Traverse the transition tree in postorder without using the C++ stack by |
5294 // doing pointer reversal. | 5330 // doing pointer reversal. |
5295 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { | 5331 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { |
5296 TraversableMap* current = static_cast<TraversableMap*>(this); | 5332 TraversableMap* current = static_cast<TraversableMap*>(this); |
5297 current->ChildIteratorStart(); | 5333 current->ChildIteratorStart(); |
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6026 MaybeObject* copy_result = | 6062 MaybeObject* copy_result = |
6027 new_descriptors->CopyFrom(next_descriptor++, this, i, witness); | 6063 new_descriptors->CopyFrom(next_descriptor++, this, i, witness); |
6028 if (copy_result->IsFailure()) return copy_result; | 6064 if (copy_result->IsFailure()) return copy_result; |
6029 } | 6065 } |
6030 } | 6066 } |
6031 ASSERT(next_descriptor == new_descriptors->number_of_descriptors()); | 6067 ASSERT(next_descriptor == new_descriptors->number_of_descriptors()); |
6032 | 6068 |
6033 return new_descriptors; | 6069 return new_descriptors; |
6034 } | 6070 } |
6035 | 6071 |
6036 | 6072 // We need the whiteness witness since sort will reshuffle the entries in the |
| 6073 // descriptor array. If the descriptor array were to be black, the shuffling |
| 6074 // would move a slot that was already recorded as pointing into an evacuation |
| 6075 // candidate. This would result in missing updates upon evacuation. |
6037 void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) { | 6076 void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) { |
6038 // In-place heap sort. | 6077 // In-place heap sort. |
6039 int len = number_of_descriptors(); | 6078 int len = number_of_descriptors(); |
6040 | 6079 |
6041 // Bottom-up max-heap construction. | 6080 // Bottom-up max-heap construction. |
6042 // Index of the last node with children | 6081 // Index of the last node with children |
6043 const int max_parent_index = (len / 2) - 1; | 6082 const int max_parent_index = (len / 2) - 1; |
6044 for (int i = max_parent_index; i >= 0; --i) { | 6083 for (int i = max_parent_index; i >= 0; --i) { |
6045 int parent_index = i; | 6084 int parent_index = i; |
6046 const uint32_t parent_hash = GetKey(i)->Hash(); | 6085 const uint32_t parent_hash = GetKey(i)->Hash(); |
(...skipping 7211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13258 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13297 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13259 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13298 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13260 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13299 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13261 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13300 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13262 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13301 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13263 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13302 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13264 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13303 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13265 } | 13304 } |
13266 | 13305 |
13267 } } // namespace v8::internal | 13306 } } // namespace v8::internal |
OLD | NEW |