OLD | NEW |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |