 Chromium Code Reviews
 Chromium Code Reviews Issue 10411067:
  TraversableMap only dependent on DescriptorArray  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
    
  
    Issue 10411067:
  TraversableMap only dependent on DescriptorArray  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge| 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 |