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

Side by Side Diff: src/objects.cc

Issue 10692026: Moving prototype transitions into the header of the transition array. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressing comments Created 8 years, 5 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
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 5117 matching lines...) Expand 10 before | Expand all | Expand 10 after
5128 5128
5129 // An iterator over all prototype transitions, reusing the map field of the 5129 // An iterator over all prototype transitions, reusing the map field of the
5130 // underlying array while it is running. 5130 // underlying array while it is running.
5131 class IntrusivePrototypeTransitionIterator { 5131 class IntrusivePrototypeTransitionIterator {
5132 public: 5132 public:
5133 explicit IntrusivePrototypeTransitionIterator(HeapObject* proto_trans) 5133 explicit IntrusivePrototypeTransitionIterator(HeapObject* proto_trans)
5134 : proto_trans_(proto_trans) { } 5134 : proto_trans_(proto_trans) { }
5135 5135
5136 void Start() { 5136 void Start() {
5137 ASSERT(!IsIterating()); 5137 ASSERT(!IsIterating());
5138 if (HasTransitions()) *Header() = Smi::FromInt(0); 5138 *Header() = Smi::FromInt(0);
5139 } 5139 }
5140 5140
5141 bool IsIterating() { 5141 bool IsIterating() {
5142 return HasTransitions() && (*Header())->IsSmi(); 5142 return (*Header())->IsSmi();
5143 } 5143 }
5144 5144
5145 Map* Next() { 5145 Map* Next() {
5146 ASSERT(IsIterating()); 5146 ASSERT(IsIterating());
5147 int transitionNumber = Smi::cast(*Header())->value(); 5147 int transitionNumber = Smi::cast(*Header())->value();
5148 if (transitionNumber < NumberOfTransitions()) { 5148 if (transitionNumber < NumberOfTransitions()) {
5149 *Header() = Smi::FromInt(transitionNumber + 1); 5149 *Header() = Smi::FromInt(transitionNumber + 1);
5150 return GetTransition(transitionNumber); 5150 return GetTransition(transitionNumber);
5151 } 5151 }
5152 *Header() = proto_trans_->GetHeap()->fixed_array_map(); 5152 *Header() = proto_trans_->GetHeap()->fixed_array_map();
5153 return NULL; 5153 return NULL;
5154 } 5154 }
5155 5155
5156 private: 5156 private:
5157 bool HasTransitions() {
5158 return proto_trans_->map()->IsSmi() || proto_trans_->IsFixedArray();
5159 }
5160
5161 Object** Header() { 5157 Object** Header() {
5162 return HeapObject::RawField(proto_trans_, FixedArray::kMapOffset); 5158 return HeapObject::RawField(proto_trans_, FixedArray::kMapOffset);
5163 } 5159 }
5164 5160
5165 int NumberOfTransitions() { 5161 int NumberOfTransitions() {
5166 ASSERT(HasTransitions());
5167 FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_); 5162 FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
5168 Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset); 5163 Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
5169 return Smi::cast(num)->value(); 5164 return Smi::cast(num)->value();
5170 } 5165 }
5171 5166
5172 Map* GetTransition(int transitionNumber) { 5167 Map* GetTransition(int transitionNumber) {
5173 ASSERT(HasTransitions());
5174 FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_); 5168 FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
5175 return Map::cast(proto_trans->get(IndexFor(transitionNumber))); 5169 return Map::cast(proto_trans->get(IndexFor(transitionNumber)));
5176 } 5170 }
5177 5171
5178 int IndexFor(int transitionNumber) { 5172 int IndexFor(int transitionNumber) {
5179 return Map::kProtoTransitionHeaderSize + 5173 return Map::kProtoTransitionHeaderSize +
5180 Map::kProtoTransitionMapOffset + 5174 Map::kProtoTransitionMapOffset +
5181 transitionNumber * Map::kProtoTransitionElementsPerEntry; 5175 transitionNumber * Map::kProtoTransitionElementsPerEntry;
5182 } 5176 }
5183 5177
(...skipping 29 matching lines...) Expand all
5213 // this map's map! 5207 // this map's map!
5214 void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); } 5208 void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); }
5215 5209
5216 // Reset the current map's map, returning the parent previously stored in it. 5210 // Reset the current map's map, returning the parent previously stored in it.
5217 TraversableMap* GetAndResetParent() { 5211 TraversableMap* GetAndResetParent() {
5218 TraversableMap* old_parent = static_cast<TraversableMap*>(map()); 5212 TraversableMap* old_parent = static_cast<TraversableMap*>(map());
5219 set_map_no_write_barrier(GetHeap()->meta_map()); 5213 set_map_no_write_barrier(GetHeap()->meta_map());
5220 return old_parent; 5214 return old_parent;
5221 } 5215 }
5222 5216
5223 // Can either be Smi (no instance descriptors), or a descriptor array with the
5224 // header overwritten as a Smi (thus iterating).
5225 TransitionArray* MutatedTransitions() {
5226 Object* object = *HeapObject::RawField(instance_descriptors(),
5227 DescriptorArray::kTransitionsOffset);
5228 TransitionArray* transition_array = static_cast<TransitionArray*>(object);
5229 return transition_array;
5230 }
5231
5232 // Start iterating over this map's children, possibly destroying a FixedArray 5217 // Start iterating over this map's children, possibly destroying a FixedArray
5233 // map (see explanation above). 5218 // map (see explanation above).
5234 void ChildIteratorStart() { 5219 void ChildIteratorStart() {
5235 if (HasTransitionArray()) { 5220 if (HasTransitionArray()) {
5221 if (HasPrototypeTransitions()) {
5222 IntrusivePrototypeTransitionIterator(GetPrototypeTransitions()).Start();
5223 }
5224
5236 IntrusiveMapTransitionIterator(transitions()).Start(); 5225 IntrusiveMapTransitionIterator(transitions()).Start();
5237 } 5226 }
5238 IntrusivePrototypeTransitionIterator(
5239 unchecked_prototype_transitions()).Start();
5240 } 5227 }
5241 5228
5242 // If we have an unvisited child map, return that one and advance. If we have 5229 // If we have an unvisited child map, return that one and advance. If we have
5243 // none, return NULL and reset any destroyed FixedArray maps. 5230 // none, return NULL and reset any destroyed FixedArray maps.
5244 TraversableMap* ChildIteratorNext() { 5231 TraversableMap* ChildIteratorNext() {
5245 IntrusivePrototypeTransitionIterator
5246 proto_iterator(unchecked_prototype_transitions());
5247 if (proto_iterator.IsIterating()) {
5248 Map* next = proto_iterator.Next();
5249 if (next != NULL) return static_cast<TraversableMap*>(next);
5250 }
5251 if (HasTransitionArray()) { 5232 if (HasTransitionArray()) {
5252 IntrusiveMapTransitionIterator 5233 TransitionArray* transition_array = unchecked_transition_array();
5253 transitions_iterator(MutatedTransitions()); 5234
5254 if (transitions_iterator.IsIterating()) { 5235 if (transition_array->HasPrototypeTransitions()) {
5255 Map* next = transitions_iterator.Next(); 5236 HeapObject* proto_transitions =
5237 transition_array->UncheckedPrototypeTransitions();
5238 IntrusivePrototypeTransitionIterator proto_iterator(proto_transitions);
5239 if (proto_iterator.IsIterating()) {
5240 Map* next = proto_iterator.Next();
5241 if (next != NULL) return static_cast<TraversableMap*>(next);
5242 }
5243 }
5244
5245 IntrusiveMapTransitionIterator transition_iterator(transition_array);
5246 if (transition_iterator.IsIterating()) {
5247 Map* next = transition_iterator.Next();
5256 if (next != NULL) return static_cast<TraversableMap*>(next); 5248 if (next != NULL) return static_cast<TraversableMap*>(next);
5257 } 5249 }
5258 } 5250 }
5251
5259 return NULL; 5252 return NULL;
5260 } 5253 }
5261 }; 5254 };
5262 5255
5263 5256
5264 // Traverse the transition tree in postorder without using the C++ stack by 5257 // Traverse the transition tree in postorder without using the C++ stack by
5265 // doing pointer reversal. 5258 // doing pointer reversal.
5266 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { 5259 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
5267 TraversableMap* current = static_cast<TraversableMap*>(this); 5260 TraversableMap* current = static_cast<TraversableMap*>(this);
5268 current->ChildIteratorStart(); 5261 current->ChildIteratorStart();
(...skipping 2128 matching lines...) Expand 10 before | Expand all | Expand 10 after
7397 t->ClearElementsTransition(); 7390 t->ClearElementsTransition();
7398 } else { 7391 } else {
7399 // If there are no transitions to be cleared, return. 7392 // If there are no transitions to be cleared, return.
7400 // TODO(verwaest) Should be an assert, otherwise back pointers are not 7393 // TODO(verwaest) Should be an assert, otherwise back pointers are not
7401 // properly cleared. 7394 // properly cleared.
7402 if (transition_index == t->number_of_transitions()) return; 7395 if (transition_index == t->number_of_transitions()) return;
7403 } 7396 }
7404 7397
7405 // If the final transition array does not contain any live transitions, remove 7398 // If the final transition array does not contain any live transitions, remove
7406 // the transition array from the map. 7399 // the transition array from the map.
7407 if (transition_index == 0 && !t->HasElementsTransition()) { 7400 if (transition_index == 0 &&
7401 !t->HasElementsTransition() &&
7402 !t->HasPrototypeTransitions()) {
7408 return ClearTransitions(); 7403 return ClearTransitions();
7409 } 7404 }
7410 7405
7411 int trim = t->number_of_transitions() - transition_index; 7406 int trim = t->number_of_transitions() - transition_index;
7412 if (trim > 0) { 7407 if (trim > 0) {
7413 RightTrimFixedArray(heap, t, trim * TransitionArray::kTransitionSize); 7408 RightTrimFixedArray(heap, t, trim * TransitionArray::kTransitionSize);
7414 } 7409 }
7415 } 7410 }
7416 7411
7417 7412
(...skipping 1397 matching lines...) Expand 10 before | Expand all | Expand 10 after
8815 8810
8816 8811
8817 MaybeObject* JSArray::SetElementsLength(Object* len) { 8812 MaybeObject* JSArray::SetElementsLength(Object* len) {
8818 // We should never end in here with a pixel or external array. 8813 // We should never end in here with a pixel or external array.
8819 ASSERT(AllowsSetElementsLength()); 8814 ASSERT(AllowsSetElementsLength());
8820 return GetElementsAccessor()->SetLength(this, len); 8815 return GetElementsAccessor()->SetLength(this, len);
8821 } 8816 }
8822 8817
8823 8818
8824 Map* Map::GetPrototypeTransition(Object* prototype) { 8819 Map* Map::GetPrototypeTransition(Object* prototype) {
8825 FixedArray* cache = prototype_transitions(); 8820 FixedArray* cache = GetPrototypeTransitions();
8826 int number_of_transitions = NumberOfProtoTransitions(); 8821 int number_of_transitions = NumberOfProtoTransitions();
8827 const int proto_offset = 8822 const int proto_offset =
8828 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; 8823 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset;
8829 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; 8824 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
8830 const int step = kProtoTransitionElementsPerEntry; 8825 const int step = kProtoTransitionElementsPerEntry;
8831 for (int i = 0; i < number_of_transitions; i++) { 8826 for (int i = 0; i < number_of_transitions; i++) {
8832 if (cache->get(proto_offset + i * step) == prototype) { 8827 if (cache->get(proto_offset + i * step) == prototype) {
8833 Object* map = cache->get(map_offset + i * step); 8828 Object* map = cache->get(map_offset + i * step);
8834 return Map::cast(map); 8829 return Map::cast(map);
8835 } 8830 }
8836 } 8831 }
8837 return NULL; 8832 return NULL;
8838 } 8833 }
8839 8834
8840 8835
8841 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) { 8836 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) {
8842 ASSERT(map->IsMap()); 8837 ASSERT(map->IsMap());
8843 ASSERT(HeapObject::cast(prototype)->map()->IsMap()); 8838 ASSERT(HeapObject::cast(prototype)->map()->IsMap());
8844 // Don't cache prototype transition if this map is shared. 8839 // Don't cache prototype transition if this map is shared.
8845 if (is_shared() || !FLAG_cache_prototype_transitions) return this; 8840 if (is_shared() || !FLAG_cache_prototype_transitions) return this;
8846 8841
8847 FixedArray* cache = prototype_transitions(); 8842 FixedArray* cache = GetPrototypeTransitions();
8848 8843
8849 const int step = kProtoTransitionElementsPerEntry; 8844 const int step = kProtoTransitionElementsPerEntry;
8850 const int header = kProtoTransitionHeaderSize; 8845 const int header = kProtoTransitionHeaderSize;
8851 8846
8852 int capacity = (cache->length() - header) / step; 8847 int capacity = (cache->length() - header) / step;
8853 8848
8854 int transitions = NumberOfProtoTransitions() + 1; 8849 int transitions = NumberOfProtoTransitions() + 1;
8855 8850
8856 if (transitions > capacity) { 8851 if (transitions > capacity) {
8857 if (capacity > kMaxCachedPrototypeTransitions) return this; 8852 if (capacity > kMaxCachedPrototypeTransitions) return this;
8858 8853
8859 FixedArray* new_cache; 8854 FixedArray* new_cache;
8860 // Grow array by factor 2 over and above what we need. 8855 // Grow array by factor 2 over and above what we need.
8861 { MaybeObject* maybe_cache = 8856 { MaybeObject* maybe_cache =
8862 GetHeap()->AllocateFixedArray(transitions * 2 * step + header); 8857 GetHeap()->AllocateFixedArray(transitions * 2 * step + header);
8863 if (!maybe_cache->To(&new_cache)) return maybe_cache; 8858 if (!maybe_cache->To(&new_cache)) return maybe_cache;
8864 } 8859 }
8865 8860
8866 for (int i = 0; i < capacity * step; i++) { 8861 for (int i = 0; i < capacity * step; i++) {
8867 new_cache->set(i + header, cache->get(i + header)); 8862 new_cache->set(i + header, cache->get(i + header));
8868 } 8863 }
8869 cache = new_cache; 8864 cache = new_cache;
8870 set_prototype_transitions(cache); 8865 MaybeObject* set_result = SetPrototypeTransitions(cache);
8866 if (set_result->IsFailure()) return set_result;
8871 } 8867 }
8872 8868
8873 int last = transitions - 1; 8869 int last = transitions - 1;
8874 8870
8875 cache->set(header + last * step + kProtoTransitionPrototypeOffset, prototype); 8871 cache->set(header + last * step + kProtoTransitionPrototypeOffset, prototype);
8876 cache->set(header + last * step + kProtoTransitionMapOffset, map); 8872 cache->set(header + last * step + kProtoTransitionMapOffset, map);
8877 SetNumberOfProtoTransitions(transitions); 8873 SetNumberOfProtoTransitions(transitions);
8878 8874
8879 return cache; 8875 return cache;
8880 } 8876 }
(...skipping 4382 matching lines...) Expand 10 before | Expand all | Expand 10 after
13263 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13259 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13264 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13260 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13265 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13261 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13266 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13262 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13267 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13263 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13268 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13264 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13269 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13265 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13270 } 13266 }
13271 13267
13272 } } // namespace v8::internal 13268 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | src/transitions.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698