Reviewers: Mads Ager,
Description:
Fix traversal of the map transition tree to take the prototype
transitions into account.
Please review this at http://codereview.chromium.org/7033052/
SVN Base: http://v8.googlecode.com/svn/branches/3.2/
Affected files:
M src/objects.cc
Index: src/objects.cc
===================================================================
--- src/objects.cc (revision 8160)
+++ src/objects.cc (working copy)
@@ -3713,39 +3713,68 @@
void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
+ // Traverse the transition tree without using a stack. We do this by
+ // reversing the pointers in the maps and descriptor arrays.
Map* current = this;
Map* meta_map = heap()->meta_map();
+ Object** map_or_index_field = NULL;
while (current != meta_map) {
DescriptorArray* d = reinterpret_cast<DescriptorArray*>(
*RawField(current, Map::kInstanceDescriptorsOffset));
- if (d == heap()->empty_descriptor_array()) {
- Map* prev = current->map();
- current->set_map(meta_map);
- callback(current, data);
- current = prev;
- continue;
+ if (!d->IsEmpty()) {
+ FixedArray* contents = reinterpret_cast<FixedArray*>(
+ d->get(DescriptorArray::kContentArrayIndex));
+ map_or_index_field = RawField(contents, HeapObject::kMapOffset);
+ Object* map_or_index = *map_or_index_field;
+ bool map_done = true; // Controls a nested continue statement.
+ for (int i = map_or_index->IsSmi() ?
Smi::cast(map_or_index)->value() : 0;
+ i < contents->length();
+ i += 2) {
+ PropertyDetails details(Smi::cast(contents->get(i + 1)));
+ if (details.IsTransition()) {
+ // Found a map in the transition array. We record our progress
in
+ // the transition array by recording the current map in the map
field
+ // of the next map and recording the index in the transition
array in
+ // the map field of the array.
+ Map* next = Map::cast(contents->get(i));
+ next->set_map(current);
+ *map_or_index_field = Smi::FromInt(i + 2);
+ current = next;
+ map_done = false;
+ break;
+ }
+ }
+ if (!map_done) continue;
}
-
- FixedArray* contents = reinterpret_cast<FixedArray*>(
- d->get(DescriptorArray::kContentArrayIndex));
- Object** map_or_index_field = RawField(contents,
HeapObject::kMapOffset);
- Object* map_or_index = *map_or_index_field;
- bool map_done = true;
- for (int i = map_or_index->IsSmi() ?
Smi::cast(map_or_index)->value() : 0;
- i < contents->length();
- i += 2) {
- PropertyDetails details(Smi::cast(contents->get(i + 1)));
- if (details.IsTransition()) {
- Map* next = reinterpret_cast<Map*>(contents->get(i));
+ // That was the regular transitions, now for the prototype transitions.
+ FixedArray* prototype_transitions =
+ current->unchecked_prototype_transitions();
+ Object** proto_map_or_index_field =
+ RawField(prototype_transitions, HeapObject::kMapOffset);
+ Object* map_or_index = *proto_map_or_index_field;
+ const int start = 2;
+ int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() :
start;
+ if (i < prototype_transitions->length()) {
+ // Found a map in the prototype transition array. Record progress in
+ // an analogous way to the regular transitions array above.
+ Object* perhaps_map = prototype_transitions->get(i);
+ if (perhaps_map->IsMap()) {
+ Map* next = Map::cast(perhaps_map);
next->set_map(current);
- *map_or_index_field = Smi::FromInt(i + 2);
+ *proto_map_or_index_field =
+ Smi::FromInt(i + 2);
current = next;
- map_done = false;
- break;
+ continue;
}
}
- if (!map_done) continue;
- *map_or_index_field = heap()->fixed_array_map();
+ *proto_map_or_index_field = heap()->fixed_array_map();
+ if (map_or_index_field != NULL) {
+ *map_or_index_field = heap()->fixed_array_map();
+ }
+
+ // The callback expects a map to have a real map as its map, so we save
+ // the map field, which is being used to track the traversal and put
the
+ // correct map (the meta_map) in place while we do the callback.
Map* prev = current->map();
current->set_map(meta_map);
callback(current, data);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev