| 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 |