Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(272)

Side by Side Diff: src/objects.cc

Issue 10417030: Decoupling MarkDescriptorArray as much as possible from the ContentArray. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: removing were to be Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698