From 20ca26f4941c8100bfc54c85b36ca11232a9de2f Mon Sep 17 00:00:00 2001 From: "verwaest@chromium.org" Date: Mon, 19 Aug 2013 12:32:50 +0000 Subject: [PATCH] Improve generalization / migration tracing. R=yangguo@chromium.org Review URL: https://chromiumcodereview.appspot.com/23047002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16219 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/objects-inl.h | 17 ++++++++- src/objects.cc | 94 +++++++++++++++++++++++++++++++---------------- src/objects.h | 13 +++++++ 3 files changed, 90 insertions(+), 34 deletions(-) diff --git a/src/objects-inl.h b/src/objects-inl.h index 169475791d..6c1ecbb322 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -1567,14 +1567,27 @@ MaybeObject* JSObject::MigrateInstance() { // Converting any field to the most specific type will cause the // GeneralizeFieldRepresentation algorithm to create the most general existing // transition that matches the object. This achieves what is needed. - return GeneralizeFieldRepresentation(0, Representation::None()); + Map* original_map = map(); + MaybeObject* maybe_result = GeneralizeFieldRepresentation( + 0, Representation::None()); + JSObject* result; + if (FLAG_trace_migration && maybe_result->To(&result)) { + PrintInstanceMigration(stdout, original_map, result->map()); + } + return maybe_result; } MaybeObject* JSObject::TryMigrateInstance() { Map* new_map = map()->CurrentMapForDeprecated(); if (new_map == NULL) return Smi::FromInt(0); - return MigrateToMap(new_map); + Map* original_map = map(); + MaybeObject* maybe_result = MigrateToMap(new_map); + JSObject* result; + if (FLAG_trace_migration && maybe_result->To(&result)) { + PrintInstanceMigration(stdout, original_map, result->map()); + } + return maybe_result; } diff --git a/src/objects.cc b/src/objects.cc index 38d8647b52..7e15f3005d 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1449,6 +1449,54 @@ void JSObject::PrintElementsTransition( } +void Map::PrintGeneralization(FILE* file, + int modify_index, + int split, + int descriptors, + Representation old_representation, + Representation new_representation) { + PrintF(file, "[generalizing "); + constructor_name()->PrintOn(file); + PrintF(file, "] "); + String::cast(instance_descriptors()->GetKey(modify_index))->PrintOn(file); + PrintF(file, ":%s->%s (+%i maps) [", + old_representation.Mnemonic(), + new_representation.Mnemonic(), + descriptors - split); + JavaScriptFrame::PrintTop(GetIsolate(), file, false, true); + PrintF(file, "]\n"); +} + + +void JSObject::PrintInstanceMigration(FILE* file, + Map* original_map, + Map* new_map) { + PrintF(file, "[migrating "); + map()->constructor_name()->PrintOn(file); + PrintF(file, "] "); + DescriptorArray* o = original_map->instance_descriptors(); + DescriptorArray* n = new_map->instance_descriptors(); + for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) { + Representation o_r = o->GetDetails(i).representation(); + Representation n_r = n->GetDetails(i).representation(); + if (!o_r.Equals(n_r)) { + String::cast(o->GetKey(i))->PrintOn(file); + PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic()); + } else if (o->GetDetails(i).type() == CONSTANT && + n->GetDetails(i).type() == FIELD) { + Name* name = o->GetKey(i); + if (name->IsString()) { + String::cast(name)->PrintOn(file); + } else { + PrintF(file, "???"); + } + PrintF(file, " "); + } + } + PrintF(file, "\n"); +} + + void HeapObject::HeapObjectShortPrint(StringStream* accumulator) { Heap* heap = GetHeap(); if (!heap->Contains(this)) { @@ -1783,14 +1831,14 @@ String* JSReceiver::class_name() { } -String* JSReceiver::constructor_name() { - if (map()->constructor()->IsJSFunction()) { - JSFunction* constructor = JSFunction::cast(map()->constructor()); +String* Map::constructor_name() { + if (constructor()->IsJSFunction()) { + JSFunction* constructor = JSFunction::cast(this->constructor()); String* name = String::cast(constructor->shared()->name()); if (name->length() > 0) return name; String* inferred_name = constructor->shared()->inferred_name(); if (inferred_name->length() > 0) return inferred_name; - Object* proto = GetPrototype(); + Object* proto = prototype(); if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name(); } // TODO(rossberg): what about proxies? @@ -1799,6 +1847,11 @@ String* JSReceiver::constructor_name() { } +String* JSReceiver::constructor_name() { + return map()->constructor_name(); +} + + MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, Name* name, Object* value, @@ -2626,12 +2679,6 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index, if (old_representation.IsNone() && !new_representation.IsNone() && !new_representation.IsDouble()) { - if (FLAG_trace_generalization) { - PrintF("initializing representation %i: %p -> %s\n", - modify_index, - static_cast(this), - new_representation.Mnemonic()); - } old_descriptors->SetRepresentation(modify_index, new_representation); return old_map; } @@ -2661,11 +2708,9 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index, if (FLAG_trace_generalization && !(modify_index == 0 && new_representation.IsNone())) { PropertyDetails old_details = old_descriptors->GetDetails(modify_index); - PrintF("migrating to existing map %p(%s) -> %p(%s)\n", - static_cast(this), - old_details.representation().Mnemonic(), - static_cast(updated), - updated_representation.Mnemonic()); + PrintGeneralization(stdout, modify_index, descriptors, descriptors, + old_details.representation(), + updated_representation); } return updated; } @@ -2698,13 +2743,8 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index, if (FLAG_trace_generalization && !(modify_index == 0 && new_representation.IsNone())) { - PrintF("migrating to new map %i: %p(%s) -> %p(%s) (%i steps)\n", - modify_index, - static_cast(this), - old_representation.Mnemonic(), - static_cast(new_descriptors), - updated_representation.Mnemonic(), - descriptors - descriptor); + PrintGeneralization(stdout, modify_index, descriptor, descriptors, + old_representation, updated_representation); } Map* new_map = split_map; @@ -3726,11 +3766,6 @@ void JSObject::AllocateStorageForMap(Handle object, Handle map) { void JSObject::MigrateInstance(Handle object) { - if (FLAG_trace_migration) { - PrintF("migrating instance %p (%p)\n", - static_cast(*object), - static_cast(object->map())); - } CALL_HEAP_FUNCTION_VOID( object->GetIsolate(), object->MigrateInstance()); @@ -3738,11 +3773,6 @@ void JSObject::MigrateInstance(Handle object) { Handle JSObject::TryMigrateInstance(Handle object) { - if (FLAG_trace_migration) { - PrintF("migrating instance (no new maps) %p (%p)\n", - static_cast(*object), - static_cast(object->map())); - } CALL_HEAP_FUNCTION( object->GetIsolate(), object->MigrateInstance(), diff --git a/src/objects.h b/src/objects.h index f800c5d580..96b4011664 100644 --- a/src/objects.h +++ b/src/objects.h @@ -2672,6 +2672,8 @@ class JSObject: public JSReceiver { FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements, ElementsKind to_kind, FixedArrayBase* to_elements); + void PrintInstanceMigration(FILE* file, Map* original_map, Map* new_map); + #ifdef DEBUG // Structure for collecting spill information about JSObjects. class SpillInformation { @@ -5623,6 +5625,17 @@ class Map: public HeapObject { Representation representation); MUST_USE_RESULT MaybeObject* CopyGeneralizeAllRepresentations(); + void PrintGeneralization(FILE* file, + int modify_index, + int split, + int descriptors, + Representation old_representation, + Representation new_representation); + + // Returns the constructor name (the name (possibly, inferred name) of the + // function that was used to instantiate the object). + String* constructor_name(); + // Tells whether the map is attached to SharedFunctionInfo // (for inobject slack tracking). inline void set_attached_to_shared_function_info(bool value);