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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 2835182f1a1f6d1aacaf090cab40550ab27504ea..542b8a0049df836c369b929146697540424c7244 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -7677,204 +7677,35 @@ void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
}
-// An iterator over all map transitions in an descriptor array, reusing the
-// constructor field of the map while it is running. Negative values in
-// the constructor field indicate an active map transition iteration. The
-// original constructor is restored after iterating over all entries.
-class IntrusiveMapTransitionIterator {
- public:
- IntrusiveMapTransitionIterator(
- Map* map, TransitionArray* transition_array, Object* constructor)
- : map_(map),
- transition_array_(transition_array),
- constructor_(constructor) { }
-
- void StartIfNotStarted() {
- DCHECK(!(*IteratorField())->IsSmi() || IsIterating());
- if (!(*IteratorField())->IsSmi()) {
- DCHECK(*IteratorField() == constructor_);
- *IteratorField() = Smi::FromInt(-1);
- }
- }
-
- bool IsIterating() {
- return (*IteratorField())->IsSmi() &&
- Smi::cast(*IteratorField())->value() < 0;
- }
-
- Map* Next() {
- DCHECK(IsIterating());
- int value = Smi::cast(*IteratorField())->value();
- int index = -value - 1;
- int number_of_transitions = transition_array_->number_of_transitions();
- if (index < number_of_transitions) {
- *IteratorField() = Smi::FromInt(value - 1);
- return transition_array_->GetTarget(index);
- }
-
- *IteratorField() = constructor_;
- return NULL;
- }
-
- private:
- Object** IteratorField() {
- return HeapObject::RawField(map_, Map::kConstructorOffset);
- }
-
- Map* map_;
- TransitionArray* transition_array_;
- Object* constructor_;
-};
-
-
-// An iterator over all prototype transitions, reusing the constructor field
-// of the map while it is running. Positive values in the constructor field
-// indicate an active prototype transition iteration. The original constructor
-// is restored after iterating over all entries.
-class IntrusivePrototypeTransitionIterator {
- public:
- IntrusivePrototypeTransitionIterator(
- Map* map, HeapObject* proto_trans, Object* constructor)
- : map_(map), proto_trans_(proto_trans), constructor_(constructor) { }
-
- void StartIfNotStarted() {
- if (!(*IteratorField())->IsSmi()) {
- DCHECK(*IteratorField() == constructor_);
- *IteratorField() = Smi::FromInt(0);
- }
- }
-
- bool IsIterating() {
- return (*IteratorField())->IsSmi() &&
- Smi::cast(*IteratorField())->value() >= 0;
- }
-
- Map* Next() {
- DCHECK(IsIterating());
- int transitionNumber = Smi::cast(*IteratorField())->value();
- if (transitionNumber < NumberOfTransitions()) {
- *IteratorField() = Smi::FromInt(transitionNumber + 1);
- return GetTransition(transitionNumber);
- }
- *IteratorField() = constructor_;
- return NULL;
- }
-
- private:
- Object** IteratorField() {
- return HeapObject::RawField(map_, Map::kConstructorOffset);
- }
-
- int NumberOfTransitions() {
- FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
- Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
- return Smi::cast(num)->value();
- }
-
- Map* GetTransition(int transitionNumber) {
- FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
- int index = Map::kProtoTransitionHeaderSize + transitionNumber;
- return Map::cast(proto_trans->get(index));
- }
-
- Map* map_;
- HeapObject* proto_trans_;
- Object* constructor_;
-};
-
-
-// To traverse the transition tree iteratively, we have to store two kinds of
-// information in a map: The parent map in the traversal and which children of a
-// node have already been visited. To do this without additional memory, we
-// temporarily reuse two fields with known values:
-//
-// (1) The map of the map temporarily holds the parent, and is restored to the
-// meta map afterwards.
-//
-// (2) The info which children have already been visited depends on which part
-// of the map we currently iterate. We use the constructor field of the
-// map to store the current index. We can do that because the constructor
-// is the same for all involved maps.
-//
-// (a) If we currently follow normal map transitions, we temporarily store
-// the current index in the constructor field, and restore it to the
-// original constructor afterwards. Note that a single descriptor can
-// have 0, 1, or 2 transitions.
-//
-// (b) If we currently follow prototype transitions, we temporarily store
-// the current index in the constructor field, and restore it to the
-// original constructor afterwards.
-//
-// Note that the child iterator is just a concatenation of two iterators: One
-// iterating over map transitions and one iterating over prototype transisitons.
-class TraversableMap : public Map {
- public:
- // Record the parent in the traversal within this map. Note that this destroys
- // this map's map!
- void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); }
-
- // Reset the current map's map, returning the parent previously stored in it.
- TraversableMap* GetAndResetParent() {
- TraversableMap* old_parent = static_cast<TraversableMap*>(map());
- set_map_no_write_barrier(GetHeap()->meta_map());
- return old_parent;
- }
-
- // If we have an unvisited child map, return that one and advance. If we have
- // none, return NULL and restore the overwritten constructor field.
- TraversableMap* ChildIteratorNext(Object* constructor) {
- if (!HasTransitionArray()) return NULL;
-
- TransitionArray* transition_array = transitions();
- if (transition_array->HasPrototypeTransitions()) {
- HeapObject* proto_transitions =
- transition_array->GetPrototypeTransitions();
- IntrusivePrototypeTransitionIterator proto_iterator(this,
- proto_transitions,
- constructor);
- proto_iterator.StartIfNotStarted();
- if (proto_iterator.IsIterating()) {
- Map* next = proto_iterator.Next();
- if (next != NULL) return static_cast<TraversableMap*>(next);
+static void TraverseTransitionTreeInternal(Map* map,
+ Map::TraverseCallback callback,
+ void* data) {
+ if (map->HasTransitionArray()) {
+ TransitionArray* transitions = map->transitions();
+ if (transitions->HasPrototypeTransitions()) {
+ FixedArray* proto_trans = transitions->GetPrototypeTransitions();
+ Object* num_obj =
+ proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
+ int num = Smi::cast(num_obj)->value();
+ for (int i = 0; i < num; ++i) {
+ int index = Map::kProtoTransitionHeaderSize + i;
+ TraverseTransitionTreeInternal(Map::cast(proto_trans->get(index)),
+ callback, data);
}
}
-
- IntrusiveMapTransitionIterator transition_iterator(this,
- transition_array,
- constructor);
- transition_iterator.StartIfNotStarted();
- if (transition_iterator.IsIterating()) {
- Map* next = transition_iterator.Next();
- if (next != NULL) return static_cast<TraversableMap*>(next);
+ for (int i = 0; i < transitions->number_of_transitions(); ++i) {
+ TraverseTransitionTreeInternal(transitions->GetTarget(i), callback, data);
}
-
- return NULL;
}
-};
+ callback(map, data);
+}
-// Traverse the transition tree in postorder without using the C++ stack by
-// doing pointer reversal.
+// Traverse the transition tree in postorder.
void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
// Make sure that we do not allocate in the callback.
DisallowHeapAllocation no_allocation;
-
- TraversableMap* current = static_cast<TraversableMap*>(this);
- // Get the root constructor here to restore it later when finished iterating
- // over maps.
- Object* root_constructor = constructor();
- while (true) {
- TraversableMap* child = current->ChildIteratorNext(root_constructor);
- if (child != NULL) {
- child->SetParent(current);
- current = child;
- } else {
- TraversableMap* parent = current->GetAndResetParent();
- callback(current, data);
- if (current == this) break;
- current = parent;
- }
- }
+ TraverseTransitionTreeInternal(this, callback, data);
}
« 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