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 |