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

Side by Side Diff: src/objects.cc

Issue 942523003: Drop Intrusive*TransitionIterators, use recursion instead. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebased Created 5 years, 10 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <sstream> 5 #include <sstream>
6 6
7 #include "src/v8.h" 7 #include "src/v8.h"
8 8
9 #include "src/accessors.h" 9 #include "src/accessors.h"
10 #include "src/allocation-site-scopes.h" 10 #include "src/allocation-site-scopes.h"
(...skipping 7659 matching lines...) Expand 10 before | Expand all | Expand 10 after
7670 7670
7671 7671
7672 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) { 7672 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
7673 // No GC is supposed to happen between a call to IndexInCodeCache and 7673 // No GC is supposed to happen between a call to IndexInCodeCache and
7674 // RemoveFromCodeCache so the code cache must be there. 7674 // RemoveFromCodeCache so the code cache must be there.
7675 DCHECK(!code_cache()->IsFixedArray()); 7675 DCHECK(!code_cache()->IsFixedArray());
7676 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); 7676 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
7677 } 7677 }
7678 7678
7679 7679
7680 // An iterator over all map transitions in an descriptor array, reusing the 7680 static void TraverseTransitionTreeInternal(Map* map,
7681 // constructor field of the map while it is running. Negative values in 7681 Map::TraverseCallback callback,
7682 // the constructor field indicate an active map transition iteration. The 7682 void* data) {
7683 // original constructor is restored after iterating over all entries. 7683 if (map->HasTransitionArray()) {
7684 class IntrusiveMapTransitionIterator { 7684 TransitionArray* transitions = map->transitions();
7685 public: 7685 if (transitions->HasPrototypeTransitions()) {
7686 IntrusiveMapTransitionIterator( 7686 FixedArray* proto_trans = transitions->GetPrototypeTransitions();
7687 Map* map, TransitionArray* transition_array, Object* constructor) 7687 Object* num_obj =
7688 : map_(map), 7688 proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
7689 transition_array_(transition_array), 7689 int num = Smi::cast(num_obj)->value();
7690 constructor_(constructor) { } 7690 for (int i = 0; i < num; ++i) {
7691 7691 int index = Map::kProtoTransitionHeaderSize + i;
7692 void StartIfNotStarted() { 7692 TraverseTransitionTreeInternal(Map::cast(proto_trans->get(index)),
7693 DCHECK(!(*IteratorField())->IsSmi() || IsIterating()); 7693 callback, data);
7694 if (!(*IteratorField())->IsSmi()) { 7694 }
7695 DCHECK(*IteratorField() == constructor_); 7695 }
7696 *IteratorField() = Smi::FromInt(-1); 7696 for (int i = 0; i < transitions->number_of_transitions(); ++i) {
7697 TraverseTransitionTreeInternal(transitions->GetTarget(i), callback, data);
7697 } 7698 }
7698 } 7699 }
7699 7700 callback(map, data);
7700 bool IsIterating() { 7701 }
7701 return (*IteratorField())->IsSmi() &&
7702 Smi::cast(*IteratorField())->value() < 0;
7703 }
7704
7705 Map* Next() {
7706 DCHECK(IsIterating());
7707 int value = Smi::cast(*IteratorField())->value();
7708 int index = -value - 1;
7709 int number_of_transitions = transition_array_->number_of_transitions();
7710 if (index < number_of_transitions) {
7711 *IteratorField() = Smi::FromInt(value - 1);
7712 return transition_array_->GetTarget(index);
7713 }
7714
7715 *IteratorField() = constructor_;
7716 return NULL;
7717 }
7718
7719 private:
7720 Object** IteratorField() {
7721 return HeapObject::RawField(map_, Map::kConstructorOffset);
7722 }
7723
7724 Map* map_;
7725 TransitionArray* transition_array_;
7726 Object* constructor_;
7727 };
7728 7702
7729 7703
7730 // An iterator over all prototype transitions, reusing the constructor field 7704 // Traverse the transition tree in postorder.
7731 // of the map while it is running. Positive values in the constructor field
7732 // indicate an active prototype transition iteration. The original constructor
7733 // is restored after iterating over all entries.
7734 class IntrusivePrototypeTransitionIterator {
7735 public:
7736 IntrusivePrototypeTransitionIterator(
7737 Map* map, HeapObject* proto_trans, Object* constructor)
7738 : map_(map), proto_trans_(proto_trans), constructor_(constructor) { }
7739
7740 void StartIfNotStarted() {
7741 if (!(*IteratorField())->IsSmi()) {
7742 DCHECK(*IteratorField() == constructor_);
7743 *IteratorField() = Smi::FromInt(0);
7744 }
7745 }
7746
7747 bool IsIterating() {
7748 return (*IteratorField())->IsSmi() &&
7749 Smi::cast(*IteratorField())->value() >= 0;
7750 }
7751
7752 Map* Next() {
7753 DCHECK(IsIterating());
7754 int transitionNumber = Smi::cast(*IteratorField())->value();
7755 if (transitionNumber < NumberOfTransitions()) {
7756 *IteratorField() = Smi::FromInt(transitionNumber + 1);
7757 return GetTransition(transitionNumber);
7758 }
7759 *IteratorField() = constructor_;
7760 return NULL;
7761 }
7762
7763 private:
7764 Object** IteratorField() {
7765 return HeapObject::RawField(map_, Map::kConstructorOffset);
7766 }
7767
7768 int NumberOfTransitions() {
7769 FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
7770 Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
7771 return Smi::cast(num)->value();
7772 }
7773
7774 Map* GetTransition(int transitionNumber) {
7775 FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
7776 int index = Map::kProtoTransitionHeaderSize + transitionNumber;
7777 return Map::cast(proto_trans->get(index));
7778 }
7779
7780 Map* map_;
7781 HeapObject* proto_trans_;
7782 Object* constructor_;
7783 };
7784
7785
7786 // To traverse the transition tree iteratively, we have to store two kinds of
7787 // information in a map: The parent map in the traversal and which children of a
7788 // node have already been visited. To do this without additional memory, we
7789 // temporarily reuse two fields with known values:
7790 //
7791 // (1) The map of the map temporarily holds the parent, and is restored to the
7792 // meta map afterwards.
7793 //
7794 // (2) The info which children have already been visited depends on which part
7795 // of the map we currently iterate. We use the constructor field of the
7796 // map to store the current index. We can do that because the constructor
7797 // is the same for all involved maps.
7798 //
7799 // (a) If we currently follow normal map transitions, we temporarily store
7800 // the current index in the constructor field, and restore it to the
7801 // original constructor afterwards. Note that a single descriptor can
7802 // have 0, 1, or 2 transitions.
7803 //
7804 // (b) If we currently follow prototype transitions, we temporarily store
7805 // the current index in the constructor field, and restore it to the
7806 // original constructor afterwards.
7807 //
7808 // Note that the child iterator is just a concatenation of two iterators: One
7809 // iterating over map transitions and one iterating over prototype transisitons.
7810 class TraversableMap : public Map {
7811 public:
7812 // Record the parent in the traversal within this map. Note that this destroys
7813 // this map's map!
7814 void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); }
7815
7816 // Reset the current map's map, returning the parent previously stored in it.
7817 TraversableMap* GetAndResetParent() {
7818 TraversableMap* old_parent = static_cast<TraversableMap*>(map());
7819 set_map_no_write_barrier(GetHeap()->meta_map());
7820 return old_parent;
7821 }
7822
7823 // If we have an unvisited child map, return that one and advance. If we have
7824 // none, return NULL and restore the overwritten constructor field.
7825 TraversableMap* ChildIteratorNext(Object* constructor) {
7826 if (!HasTransitionArray()) return NULL;
7827
7828 TransitionArray* transition_array = transitions();
7829 if (transition_array->HasPrototypeTransitions()) {
7830 HeapObject* proto_transitions =
7831 transition_array->GetPrototypeTransitions();
7832 IntrusivePrototypeTransitionIterator proto_iterator(this,
7833 proto_transitions,
7834 constructor);
7835 proto_iterator.StartIfNotStarted();
7836 if (proto_iterator.IsIterating()) {
7837 Map* next = proto_iterator.Next();
7838 if (next != NULL) return static_cast<TraversableMap*>(next);
7839 }
7840 }
7841
7842 IntrusiveMapTransitionIterator transition_iterator(this,
7843 transition_array,
7844 constructor);
7845 transition_iterator.StartIfNotStarted();
7846 if (transition_iterator.IsIterating()) {
7847 Map* next = transition_iterator.Next();
7848 if (next != NULL) return static_cast<TraversableMap*>(next);
7849 }
7850
7851 return NULL;
7852 }
7853 };
7854
7855
7856 // Traverse the transition tree in postorder without using the C++ stack by
7857 // doing pointer reversal.
7858 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { 7705 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
7859 // Make sure that we do not allocate in the callback. 7706 // Make sure that we do not allocate in the callback.
7860 DisallowHeapAllocation no_allocation; 7707 DisallowHeapAllocation no_allocation;
7861 7708 TraverseTransitionTreeInternal(this, callback, data);
7862 TraversableMap* current = static_cast<TraversableMap*>(this);
7863 // Get the root constructor here to restore it later when finished iterating
7864 // over maps.
7865 Object* root_constructor = constructor();
7866 while (true) {
7867 TraversableMap* child = current->ChildIteratorNext(root_constructor);
7868 if (child != NULL) {
7869 child->SetParent(current);
7870 current = child;
7871 } else {
7872 TraversableMap* parent = current->GetAndResetParent();
7873 callback(current, data);
7874 if (current == this) break;
7875 current = parent;
7876 }
7877 }
7878 } 7709 }
7879 7710
7880 7711
7881 void CodeCache::Update( 7712 void CodeCache::Update(
7882 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) { 7713 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7883 // The number of monomorphic stubs for normal load/store/call IC's can grow to 7714 // The number of monomorphic stubs for normal load/store/call IC's can grow to
7884 // a large number and therefore they need to go into a hash table. They are 7715 // a large number and therefore they need to go into a hash table. They are
7885 // used to load global properties from cells. 7716 // used to load global properties from cells.
7886 if (code->type() == Code::NORMAL) { 7717 if (code->type() == Code::NORMAL) {
7887 // Make sure that a hash table is allocated for the normal load code cache. 7718 // Make sure that a hash table is allocated for the normal load code cache.
(...skipping 9441 matching lines...) Expand 10 before | Expand all | Expand 10 after
17329 CompilationInfo* info) { 17160 CompilationInfo* info) {
17330 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( 17161 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo(
17331 handle(cell->dependent_code(), info->isolate()), 17162 handle(cell->dependent_code(), info->isolate()),
17332 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); 17163 DependentCode::kPropertyCellChangedGroup, info->object_wrapper());
17333 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); 17164 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
17334 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( 17165 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
17335 cell, info->zone()); 17166 cell, info->zone());
17336 } 17167 }
17337 17168
17338 } } // namespace v8::internal 17169 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698