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 4871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4882 | 4882 |
| 4883 // An iterator over all map transitions in an descriptor array, reusing the map | 4883 // An iterator over all map transitions in an descriptor array, reusing the map |
| 4884 // field of the contens array while it is running. | 4884 // field of the contens array while it is running. |
| 4885 class IntrusiveMapTransitionIterator { | 4885 class IntrusiveMapTransitionIterator { |
| 4886 public: | 4886 public: |
| 4887 explicit IntrusiveMapTransitionIterator(DescriptorArray* descriptor_array) | 4887 explicit IntrusiveMapTransitionIterator(DescriptorArray* descriptor_array) |
| 4888 : descriptor_array_(descriptor_array) { } | 4888 : descriptor_array_(descriptor_array) { } |
| 4889 | 4889 |
| 4890 void Start() { | 4890 void Start() { |
| 4891 ASSERT(!IsIterating()); | 4891 ASSERT(!IsIterating()); |
| 4892 if (HasContentArray()) *ContentHeader() = Smi::FromInt(0); | 4892 if (HasDescriptors()) *DescriptorArrayHeader() = Smi::FromInt(0); |
| 4893 } | 4893 } |
| 4894 | 4894 |
| 4895 bool IsIterating() { | 4895 bool IsIterating() { |
| 4896 return HasContentArray() && (*ContentHeader())->IsSmi(); | 4896 return HasDescriptors() && (*DescriptorArrayHeader())->IsSmi(); |
| 4897 } | 4897 } |
| 4898 | 4898 |
| 4899 Map* Next() { | 4899 Map* Next() { |
| 4900 ASSERT(IsIterating()); | 4900 ASSERT(IsIterating()); |
| 4901 FixedArray* contents = ContentArray(); | 4901 // Attention, tricky index manipulation ahead: Two consecutive indices are |
| 4902 // Attention, tricky index manipulation ahead: Every entry in the contents | 4902 // assigned to each descriptor. Most descriptors directly advance to the |
| 4903 // array consists of a value/details pair, so the index is typically even. | 4903 // next descriptor by adding 2 to the index. The exceptions are the |
| 4904 // An exception is made for CALLBACKS entries: An even index means we look | 4904 // CALLBACKS entries: An even index means we look at its getter, and an odd |
| 4905 // at its getter, and an odd index means we look at its setter. | 4905 // index means we look at its setter. |
| 4906 int index = Smi::cast(*ContentHeader())->value(); | 4906 int raw_index = Smi::cast(*DescriptorArrayHeader())->value(); |
| 4907 while (index < contents->length()) { | 4907 int index = raw_index / 2; |
| 4908 PropertyDetails details(Smi::cast(contents->get(index | 1))); | 4908 while (index < descriptor_array_->number_of_descriptors()) { |
| 4909 PropertyDetails details(RawGetDetails(index)); | |
| 4909 switch (details.type()) { | 4910 switch (details.type()) { |
| 4910 case MAP_TRANSITION: | 4911 case MAP_TRANSITION: |
| 4911 case CONSTANT_TRANSITION: | 4912 case CONSTANT_TRANSITION: |
| 4912 case ELEMENTS_TRANSITION: | 4913 case ELEMENTS_TRANSITION: |
| 4913 // We definitely have a map transition. | 4914 // We definitely have a map transition. |
| 4914 *ContentHeader() = Smi::FromInt(index + 2); | 4915 *DescriptorArrayHeader() = Smi::FromInt(raw_index + 2); |
| 4915 return static_cast<Map*>(contents->get(index)); | 4916 return static_cast<Map*>(RawGetValue(index)); |
| 4916 case CALLBACKS: { | 4917 case CALLBACKS: { |
| 4917 // We might have a map transition in a getter or in a setter. | 4918 // We might have a map transition in a getter or in a setter. |
| 4918 AccessorPair* accessors = | 4919 AccessorPair* accessors = |
| 4919 static_cast<AccessorPair*>(contents->get(index & ~1)); | 4920 static_cast<AccessorPair*>(RawGetValue(index)); |
| 4920 Object* accessor = | 4921 Object* accessor = |
| 4921 ((index & 1) == 0) ? accessors->getter() : accessors->setter(); | 4922 ((raw_index & 1) == 0) ? accessors->getter():accessors->setter(); |
|
Michael Starzinger
2012/05/25 12:18:00
Spaces to the left and right of ":". I know it wil
Toon Verwaest
2012/05/25 12:32:09
Done.
| |
| 4922 index++; | |
| 4923 if (accessor->IsMap()) { | 4923 if (accessor->IsMap()) { |
| 4924 *ContentHeader() = Smi::FromInt(index); | 4924 *DescriptorArrayHeader() = Smi::FromInt(raw_index + 1); |
| 4925 return static_cast<Map*>(accessor); | 4925 return static_cast<Map*>(accessor); |
| 4926 } | 4926 } |
| 4927 break; | 4927 break; |
| 4928 } | 4928 } |
| 4929 case NORMAL: | 4929 case NORMAL: |
| 4930 case FIELD: | 4930 case FIELD: |
| 4931 case CONSTANT_FUNCTION: | 4931 case CONSTANT_FUNCTION: |
| 4932 case HANDLER: | 4932 case HANDLER: |
| 4933 case INTERCEPTOR: | 4933 case INTERCEPTOR: |
| 4934 case NULL_DESCRIPTOR: | 4934 case NULL_DESCRIPTOR: |
| 4935 // We definitely have no map transition. | 4935 // We definitely have no map transition. |
| 4936 index += 2; | 4936 raw_index += 2; |
| 4937 ++index; | |
| 4937 break; | 4938 break; |
| 4938 } | 4939 } |
| 4939 } | 4940 } |
| 4940 *ContentHeader() = descriptor_array_->GetHeap()->fixed_array_map(); | 4941 *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map(); |
| 4941 return NULL; | 4942 return NULL; |
| 4942 } | 4943 } |
| 4943 | 4944 |
| 4944 private: | 4945 private: |
| 4945 bool HasContentArray() { | 4946 bool HasDescriptors() { |
| 4946 return descriptor_array_-> length() > DescriptorArray::kContentArrayIndex; | 4947 return descriptor_array_-> length() > DescriptorArray::kFirstIndex; |
| 4947 } | 4948 } |
| 4948 | 4949 |
| 4949 FixedArray* ContentArray() { | 4950 Object** DescriptorArrayHeader() { |
| 4950 Object* array = descriptor_array_->get(DescriptorArray::kContentArrayIndex); | 4951 return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset); |
| 4951 return static_cast<FixedArray*>(array); | |
| 4952 } | 4952 } |
| 4953 | 4953 |
| 4954 Object** ContentHeader() { | 4954 FixedArray* RawGetContentArray() { |
| 4955 return HeapObject::RawField(ContentArray(), DescriptorArray::kMapOffset); | 4955 Object* array = |
| 4956 descriptor_array_->get(DescriptorArray::kContentArrayIndex); | |
| 4957 return static_cast<FixedArray*>(array); | |
| 4956 } | 4958 } |
| 4957 | 4959 |
| 4960 Object* RawGetValue(int descriptor_number) { | |
| 4961 return RawGetContentArray()->get( | |
| 4962 DescriptorArray::ToValueIndex(descriptor_number)); | |
| 4963 } | |
| 4964 | |
| 4965 PropertyDetails RawGetDetails(int descriptor_number) { | |
| 4966 Object* details = RawGetContentArray()->get( | |
| 4967 DescriptorArray::ToDetailsIndex(descriptor_number)); | |
| 4968 return PropertyDetails(Smi::cast(details)); | |
| 4969 } | |
| 4970 | |
| 4971 | |
| 4958 DescriptorArray* descriptor_array_; | 4972 DescriptorArray* descriptor_array_; |
| 4959 }; | 4973 }; |
| 4960 | 4974 |
| 4961 | 4975 |
| 4962 // An iterator over all prototype transitions, reusing the map field of the | 4976 // An iterator over all prototype transitions, reusing the map field of the |
| 4963 // underlying array while it is running. | 4977 // underlying array while it is running. |
| 4964 class IntrusivePrototypeTransitionIterator { | 4978 class IntrusivePrototypeTransitionIterator { |
| 4965 public: | 4979 public: |
| 4966 explicit IntrusivePrototypeTransitionIterator(HeapObject* proto_trans) | 4980 explicit IntrusivePrototypeTransitionIterator(HeapObject* proto_trans) |
| 4967 : proto_trans_(proto_trans) { } | 4981 : proto_trans_(proto_trans) { } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5046 // this map's map! | 5060 // this map's map! |
| 5047 void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); } | 5061 void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); } |
| 5048 | 5062 |
| 5049 // Reset the current map's map, returning the parent previously stored in it. | 5063 // Reset the current map's map, returning the parent previously stored in it. |
| 5050 TraversableMap* GetAndResetParent() { | 5064 TraversableMap* GetAndResetParent() { |
| 5051 TraversableMap* old_parent = static_cast<TraversableMap*>(map()); | 5065 TraversableMap* old_parent = static_cast<TraversableMap*>(map()); |
| 5052 set_map_no_write_barrier(GetHeap()->meta_map()); | 5066 set_map_no_write_barrier(GetHeap()->meta_map()); |
| 5053 return old_parent; | 5067 return old_parent; |
| 5054 } | 5068 } |
| 5055 | 5069 |
| 5070 // Can either be Smi (no instance descriptors), or a descriptor array with the | |
| 5071 // header overwritten as a Smi (thus iterating). | |
| 5072 DescriptorArray* MutatedInstanceDescriptors() { | |
| 5073 Object* object = | |
| 5074 *HeapObject::RawField(this, kInstanceDescriptorsOrBitField3Offset); | |
| 5075 if (object->IsSmi()) { | |
| 5076 return GetHeap()->empty_descriptor_array(); | |
| 5077 } else { | |
| 5078 DescriptorArray* descriptor_array = | |
| 5079 static_cast<DescriptorArray*>(object); | |
| 5080 Object* map = | |
| 5081 *HeapObject::RawField(descriptor_array, DescriptorArray::kMapOffset); | |
| 5082 ASSERT(map->IsSmi()); | |
| 5083 return descriptor_array; | |
| 5084 } | |
| 5085 } | |
| 5086 | |
| 5056 // Start iterating over this map's children, possibly destroying a FixedArray | 5087 // Start iterating over this map's children, possibly destroying a FixedArray |
| 5057 // map (see explanation above). | 5088 // map (see explanation above). |
| 5058 void ChildIteratorStart() { | 5089 void ChildIteratorStart() { |
| 5059 IntrusiveMapTransitionIterator(instance_descriptors()).Start(); | 5090 IntrusiveMapTransitionIterator(instance_descriptors()).Start(); |
| 5060 IntrusivePrototypeTransitionIterator( | 5091 IntrusivePrototypeTransitionIterator( |
| 5061 unchecked_prototype_transitions()).Start(); | 5092 unchecked_prototype_transitions()).Start(); |
| 5062 } | 5093 } |
| 5063 | 5094 |
| 5064 // If we have an unvisited child map, return that one and advance. If we have | 5095 // If we have an unvisited child map, return that one and advance. If we have |
| 5065 // none, return NULL and reset any destroyed FixedArray maps. | 5096 // none, return NULL and reset any destroyed FixedArray maps. |
| 5066 TraversableMap* ChildIteratorNext() { | 5097 TraversableMap* ChildIteratorNext() { |
| 5067 IntrusiveMapTransitionIterator descriptor_iterator(instance_descriptors()); | |
| 5068 if (descriptor_iterator.IsIterating()) { | |
| 5069 Map* next = descriptor_iterator.Next(); | |
| 5070 if (next != NULL) return static_cast<TraversableMap*>(next); | |
| 5071 } | |
| 5072 IntrusivePrototypeTransitionIterator | 5098 IntrusivePrototypeTransitionIterator |
| 5073 proto_iterator(unchecked_prototype_transitions()); | 5099 proto_iterator(unchecked_prototype_transitions()); |
| 5074 if (proto_iterator.IsIterating()) { | 5100 if (proto_iterator.IsIterating()) { |
| 5075 Map* next = proto_iterator.Next(); | 5101 Map* next = proto_iterator.Next(); |
| 5076 if (next != NULL) return static_cast<TraversableMap*>(next); | 5102 if (next != NULL) return static_cast<TraversableMap*>(next); |
| 5077 } | 5103 } |
| 5104 IntrusiveMapTransitionIterator | |
| 5105 descriptor_iterator(MutatedInstanceDescriptors()); | |
| 5106 if (descriptor_iterator.IsIterating()) { | |
| 5107 Map* next = descriptor_iterator.Next(); | |
| 5108 if (next != NULL) return static_cast<TraversableMap*>(next); | |
| 5109 } | |
| 5078 return NULL; | 5110 return NULL; |
| 5079 } | 5111 } |
| 5080 }; | 5112 }; |
| 5081 | 5113 |
| 5082 | 5114 |
| 5083 // Traverse the transition tree in postorder without using the C++ stack by | 5115 // Traverse the transition tree in postorder without using the C++ stack by |
| 5084 // doing pointer reversal. | 5116 // doing pointer reversal. |
| 5085 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { | 5117 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { |
| 5086 TraversableMap* current = static_cast<TraversableMap*>(this); | 5118 TraversableMap* current = static_cast<TraversableMap*>(this); |
| 5087 current->ChildIteratorStart(); | 5119 current->ChildIteratorStart(); |
| (...skipping 7843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12931 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 12963 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
| 12932 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 12964 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
| 12933 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 12965 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
| 12934 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 12966 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
| 12935 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 12967 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
| 12936 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 12968 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
| 12937 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 12969 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
| 12938 } | 12970 } |
| 12939 | 12971 |
| 12940 } } // namespace v8::internal | 12972 } } // namespace v8::internal |
| OLD | NEW |