[heap-profiler] Show key as the value retainer for weak maps.

The key -> value edge is shown as "<index> / WeakMap", where <index> is
the index of the edge in the key.

Bug: chromium:778739, chromium:749502
Change-Id: I657051695f2a171372788dbb777543a55a35d554
Reviewed-on: https://chromium-review.googlesource.com/926524
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Alexei Filippov <alph@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51559}
This commit is contained in:
Ulan Degenbaev 2018-02-20 17:06:21 +01:00 committed by Commit Bot
parent 5d3c5784f5
commit e8925ad509
2 changed files with 49 additions and 10 deletions

View File

@ -1336,12 +1336,20 @@ void V8HeapExplorer::ExtractFixedArrayReferences(int entry, FixedArray* array) {
int key_index =
ObjectHashTable::EntryToIndex(i) + ObjectHashTable::kEntryKeyIndex;
int value_index = ObjectHashTable::EntryToValueIndex(i);
SetWeakReference(table, entry, key_index, table->get(key_index),
Object* key = table->get(key_index);
Object* value = table->get(value_index);
SetWeakReference(table, entry, key_index, key,
table->OffsetOfElementAt(key_index));
SetInternalReference(table, entry, value_index, table->get(value_index),
SetInternalReference(table, entry, value_index, value,
table->OffsetOfElementAt(value_index));
// TODO(alph): Add a strong link (shortcut?) from key to value per
// WeakMap the key was added to. See crbug.com/778739
HeapEntry* key_entry = GetEntry(key);
int key_entry_index = key_entry->index();
HeapEntry* value_entry = GetEntry(value);
if (key_entry && value_entry) {
filler_->SetNamedAutoIndexReference(HeapGraphEdge::kInternal,
key_entry_index, "WeakMap",
value_entry);
}
}
break;
}

View File

@ -198,6 +198,11 @@ static bool ValidateSnapshot(const v8::HeapSnapshot* snapshot, int depth = 3) {
return unretained_entries_count == 0;
}
bool EndsWith(const char* a, const char* b) {
size_t length_a = strlen(a);
size_t length_b = strlen(b);
return (length_a >= length_b) && !strcmp(a + length_a - length_b, b);
}
TEST(HeapSnapshot) {
LocalContext env2;
@ -719,6 +724,38 @@ TEST(HeapSnapshotInternalReferences) {
v8::HeapGraphEdge::kInternal, "1"));
}
TEST(HeapSnapshotEphemeron) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun(
"class KeyClass{};\n"
"class ValueClass{};\n"
"var wm = new WeakMap();\n"
"function foo(key) { wm.set(key, new ValueClass()); }\n"
"var key = new KeyClass();\n"
"foo(key);");
const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
const v8::HeapGraphNode* key = GetProperty(
env->GetIsolate(), global, v8::HeapGraphEdge::kProperty, "key");
CHECK(key);
bool success = false;
for (int i = 0, count = key->GetChildrenCount(); i < count; ++i) {
const v8::HeapGraphEdge* edge = key->GetChild(i);
const v8::HeapGraphNode* child = edge->GetToNode();
if (!strcmp("ValueClass", GetName(child))) {
v8::String::Utf8Value edge_name(CcTest::isolate(), edge->GetName());
CHECK(EndsWith(*edge_name, " / WeakMap"));
success = true;
break;
}
}
CHECK(success);
}
TEST(HeapSnapshotAddressReuse) {
LocalContext env;
@ -2894,12 +2931,6 @@ TEST(EmbedderGraph) {
CheckEmbedderGraphSnapshot(env->GetIsolate(), snapshot);
}
bool EndsWith(const char* a, const char* b) {
size_t length_a = strlen(a);
size_t length_b = strlen(b);
return (length_a >= length_b) && !strcmp(a + length_a - length_b, b);
}
TEST(StrongHandleAnnotation) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());