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 two consecutive indices |
Michael Starzinger
2012/05/24 14:02:25
Only one "two".
Toon Verwaest
2012/05/25 11:36:46
Done.
| |
4902 // Attention, tricky index manipulation ahead: Every entry in the contents | 4902 // are 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 index = Smi::cast(*DescriptorArrayHeader())->value(); |
4907 while (index < contents->length()) { | 4907 while ((index / 2) < descriptor_array_->number_of_descriptors()) { |
Michael Starzinger
2012/05/24 14:02:25
Can we hoist the division by two into a local vari
Toon Verwaest
2012/05/25 11:36:46
Done.
| |
4908 PropertyDetails details(Smi::cast(contents->get(index | 1))); | 4908 PropertyDetails details(descriptor_array_->RawGetDetails(index / 2)); |
4909 switch (details.type()) { | 4909 switch (details.type()) { |
4910 case MAP_TRANSITION: | 4910 case MAP_TRANSITION: |
4911 case CONSTANT_TRANSITION: | 4911 case CONSTANT_TRANSITION: |
4912 case ELEMENTS_TRANSITION: | 4912 case ELEMENTS_TRANSITION: |
4913 // We definitely have a map transition. | 4913 // We definitely have a map transition. |
4914 *ContentHeader() = Smi::FromInt(index + 2); | 4914 *DescriptorArrayHeader() = Smi::FromInt(index + 2); |
4915 return static_cast<Map*>(contents->get(index)); | 4915 return static_cast<Map*>(descriptor_array_->RawGetValue(index / 2)); |
4916 case CALLBACKS: { | 4916 case CALLBACKS: { |
4917 // We might have a map transition in a getter or in a setter. | 4917 // We might have a map transition in a getter or in a setter. |
4918 AccessorPair* accessors = | 4918 AccessorPair* accessors = |
4919 static_cast<AccessorPair*>(contents->get(index & ~1)); | 4919 static_cast<AccessorPair*>(descriptor_array_->RawGetValue(index / 2)); |
Michael Starzinger
2012/05/24 14:02:25
More than 80 characters.
Toon Verwaest
2012/05/25 11:36:46
Done.
| |
4920 Object* accessor = | 4920 Object* accessor = |
4921 ((index & 1) == 0) ? accessors->getter() : accessors->setter(); | 4921 ((index & 1) == 0) ? accessors->getter() : accessors->setter(); |
4922 index++; | 4922 index++; |
4923 if (accessor->IsMap()) { | 4923 if (accessor->IsMap()) { |
4924 *ContentHeader() = Smi::FromInt(index); | 4924 *DescriptorArrayHeader() = Smi::FromInt(index); |
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 index += 2; |
4937 break; | 4937 break; |
4938 } | 4938 } |
4939 } | 4939 } |
4940 *ContentHeader() = descriptor_array_->GetHeap()->fixed_array_map(); | 4940 *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map(); |
4941 return NULL; | 4941 return NULL; |
4942 } | 4942 } |
4943 | 4943 |
4944 private: | 4944 private: |
4945 bool HasContentArray() { | 4945 bool HasDescriptors() { |
4946 return descriptor_array_-> length() > DescriptorArray::kContentArrayIndex; | 4946 return descriptor_array_-> length() > DescriptorArray::kFirstIndex; |
4947 } | 4947 } |
4948 | 4948 |
4949 FixedArray* ContentArray() { | 4949 Object** DescriptorArrayHeader() { |
4950 Object* array = descriptor_array_->get(DescriptorArray::kContentArrayIndex); | 4950 return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset); |
4951 return static_cast<FixedArray*>(array); | |
4952 } | |
4953 | |
4954 Object** ContentHeader() { | |
4955 return HeapObject::RawField(ContentArray(), DescriptorArray::kMapOffset); | |
4956 } | 4951 } |
4957 | 4952 |
4958 DescriptorArray* descriptor_array_; | 4953 DescriptorArray* descriptor_array_; |
4959 }; | 4954 }; |
4960 | 4955 |
4961 | 4956 |
4962 // An iterator over all prototype transitions, reusing the map field of the | 4957 // An iterator over all prototype transitions, reusing the map field of the |
4963 // underlying array while it is running. | 4958 // underlying array while it is running. |
4964 class IntrusivePrototypeTransitionIterator { | 4959 class IntrusivePrototypeTransitionIterator { |
4965 public: | 4960 public: |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5046 // this map's map! | 5041 // this map's map! |
5047 void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); } | 5042 void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); } |
5048 | 5043 |
5049 // Reset the current map's map, returning the parent previously stored in it. | 5044 // Reset the current map's map, returning the parent previously stored in it. |
5050 TraversableMap* GetAndResetParent() { | 5045 TraversableMap* GetAndResetParent() { |
5051 TraversableMap* old_parent = static_cast<TraversableMap*>(map()); | 5046 TraversableMap* old_parent = static_cast<TraversableMap*>(map()); |
5052 set_map_no_write_barrier(GetHeap()->meta_map()); | 5047 set_map_no_write_barrier(GetHeap()->meta_map()); |
5053 return old_parent; | 5048 return old_parent; |
5054 } | 5049 } |
5055 | 5050 |
5051 // Can either be Smi (no instance descriptors), or a descriptor array with the | |
5052 // header overwritten as a Smi (thus iterating). | |
5053 DescriptorArray* MutatedInstanceDescriptors() { | |
5054 Object* object = *HeapObject::RawField(this, kInstanceDescriptorsOrBitField3 Offset); | |
5055 if (object->IsSmi()) { | |
5056 return GetHeap()->empty_descriptor_array(); | |
5057 } else { | |
5058 DescriptorArray* descriptor_array = static_cast<DescriptorArray*>(object); | |
5059 Object* map = *HeapObject::RawField(descriptor_array, DescriptorArray::kMa pOffset); | |
5060 ASSERT(map->IsSmi()); | |
5061 return descriptor_array; | |
5062 } | |
5063 } | |
5064 | |
5056 // Start iterating over this map's children, possibly destroying a FixedArray | 5065 // Start iterating over this map's children, possibly destroying a FixedArray |
5057 // map (see explanation above). | 5066 // map (see explanation above). |
5058 void ChildIteratorStart() { | 5067 void ChildIteratorStart() { |
5059 IntrusiveMapTransitionIterator(instance_descriptors()).Start(); | 5068 IntrusiveMapTransitionIterator(instance_descriptors()).Start(); |
5060 IntrusivePrototypeTransitionIterator( | 5069 IntrusivePrototypeTransitionIterator( |
5061 unchecked_prototype_transitions()).Start(); | 5070 unchecked_prototype_transitions()).Start(); |
5062 } | 5071 } |
5063 | 5072 |
5064 // If we have an unvisited child map, return that one and advance. If we have | 5073 // 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. | 5074 // none, return NULL and reset any destroyed FixedArray maps. |
5066 TraversableMap* ChildIteratorNext() { | 5075 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 | 5076 IntrusivePrototypeTransitionIterator |
5073 proto_iterator(unchecked_prototype_transitions()); | 5077 proto_iterator(unchecked_prototype_transitions()); |
5074 if (proto_iterator.IsIterating()) { | 5078 if (proto_iterator.IsIterating()) { |
5075 Map* next = proto_iterator.Next(); | 5079 Map* next = proto_iterator.Next(); |
5076 if (next != NULL) return static_cast<TraversableMap*>(next); | 5080 if (next != NULL) return static_cast<TraversableMap*>(next); |
5077 } | 5081 } |
5082 IntrusiveMapTransitionIterator descriptor_iterator(MutatedInstanceDescriptor s()); | |
Michael Starzinger
2012/05/24 14:02:25
Could we just pass the map itself to the construct
Toon Verwaest
2012/05/25 11:36:46
As discussed offline, leaving it as it is.
On 201
| |
5083 if (descriptor_iterator.IsIterating()) { | |
5084 Map* next = descriptor_iterator.Next(); | |
5085 if (next != NULL) return static_cast<TraversableMap*>(next); | |
5086 } | |
5078 return NULL; | 5087 return NULL; |
5079 } | 5088 } |
5080 }; | 5089 }; |
5081 | 5090 |
5082 | 5091 |
5083 // Traverse the transition tree in postorder without using the C++ stack by | 5092 // Traverse the transition tree in postorder without using the C++ stack by |
5084 // doing pointer reversal. | 5093 // doing pointer reversal. |
5085 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { | 5094 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { |
5086 TraversableMap* current = static_cast<TraversableMap*>(this); | 5095 TraversableMap* current = static_cast<TraversableMap*>(this); |
5087 current->ChildIteratorStart(); | 5096 current->ChildIteratorStart(); |
(...skipping 7843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
12931 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 12940 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
12932 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 12941 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
12933 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 12942 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
12934 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 12943 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
12935 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 12944 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
12936 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 12945 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
12937 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 12946 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
12938 } | 12947 } |
12939 | 12948 |
12940 } } // namespace v8::internal | 12949 } } // namespace v8::internal |
OLD | NEW |