[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:
parent
5d3c5784f5
commit
e8925ad509
@ -1336,12 +1336,20 @@ void V8HeapExplorer::ExtractFixedArrayReferences(int entry, FixedArray* array) {
|
|||||||
int key_index =
|
int key_index =
|
||||||
ObjectHashTable::EntryToIndex(i) + ObjectHashTable::kEntryKeyIndex;
|
ObjectHashTable::EntryToIndex(i) + ObjectHashTable::kEntryKeyIndex;
|
||||||
int value_index = ObjectHashTable::EntryToValueIndex(i);
|
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));
|
table->OffsetOfElementAt(key_index));
|
||||||
SetInternalReference(table, entry, value_index, table->get(value_index),
|
SetInternalReference(table, entry, value_index, value,
|
||||||
table->OffsetOfElementAt(value_index));
|
table->OffsetOfElementAt(value_index));
|
||||||
// TODO(alph): Add a strong link (shortcut?) from key to value per
|
HeapEntry* key_entry = GetEntry(key);
|
||||||
// WeakMap the key was added to. See crbug.com/778739
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -198,6 +198,11 @@ static bool ValidateSnapshot(const v8::HeapSnapshot* snapshot, int depth = 3) {
|
|||||||
return unretained_entries_count == 0;
|
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) {
|
TEST(HeapSnapshot) {
|
||||||
LocalContext env2;
|
LocalContext env2;
|
||||||
@ -719,6 +724,38 @@ TEST(HeapSnapshotInternalReferences) {
|
|||||||
v8::HeapGraphEdge::kInternal, "1"));
|
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) {
|
TEST(HeapSnapshotAddressReuse) {
|
||||||
LocalContext env;
|
LocalContext env;
|
||||||
@ -2894,12 +2931,6 @@ TEST(EmbedderGraph) {
|
|||||||
CheckEmbedderGraphSnapshot(env->GetIsolate(), snapshot);
|
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) {
|
TEST(StrongHandleAnnotation) {
|
||||||
LocalContext env;
|
LocalContext env;
|
||||||
v8::HandleScope scope(env->GetIsolate());
|
v8::HandleScope scope(env->GetIsolate());
|
||||||
|
Loading…
Reference in New Issue
Block a user