Make a single HeapEntry per single JSArrayBuffer data in heap snapshot.

It turned out that JSArrayBuffer's may share their backing_store so
the backing_store should go through hash map registration just like
other heap objects, so they won't be reported twice.

BUG=341741
LOG=N
R=dslomov@chromium.org, yurys@chromium.org

Review URL: https://codereview.chromium.org/166993002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19416 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
alph@chromium.org 2014-02-17 15:24:39 +00:00
parent 44b1aa4ea8
commit 429ce41f4b
3 changed files with 69 additions and 8 deletions

View File

@ -1456,6 +1456,23 @@ void V8HeapExplorer::ExtractAllocationSiteReferences(int entry,
}
class JSArrayBufferDataEntryAllocator : public HeapEntriesAllocator {
public:
JSArrayBufferDataEntryAllocator(int size, V8HeapExplorer* explorer)
: size_(size)
, explorer_(explorer) {
}
virtual HeapEntry* AllocateEntry(HeapThing ptr) {
return explorer_->AddEntry(
static_cast<Address>(ptr),
HeapEntry::kNative, "system / JSArrayBufferData", size_);
}
private:
int size_;
V8HeapExplorer* explorer_;
};
void V8HeapExplorer::ExtractJSArrayBufferReferences(
int entry, JSArrayBuffer* buffer) {
SetWeakReference(buffer, entry, "weak_next", buffer->weak_next(),
@ -1468,10 +1485,9 @@ void V8HeapExplorer::ExtractJSArrayBufferReferences(
return;
size_t data_size = NumberToSize(heap_->isolate(), buffer->byte_length());
CHECK(data_size <= static_cast<size_t>(kMaxInt));
HeapEntry* data_entry = AddEntry(
static_cast<Address>(buffer->backing_store()),
HeapEntry::kNative, "system / ArrayBufferData",
static_cast<int>(data_size));
JSArrayBufferDataEntryAllocator allocator(static_cast<int>(data_size), this);
HeapEntry* data_entry =
filler_->FindOrAddEntry(buffer->backing_store(), &allocator);
filler_->SetNamedReference(HeapGraphEdge::kInternal,
entry, "backing_store", data_entry);
}

View File

@ -386,6 +386,10 @@ class V8HeapExplorer : public HeapEntriesAllocator {
void TagGlobalObjects();
void TagCodeObject(Code* code);
void TagBuiltinCodeObject(Code* code, const char* name);
HeapEntry* AddEntry(Address address,
HeapEntry::Type type,
const char* name,
int size);
static String* GetConstructorName(JSObject* object);
@ -396,10 +400,6 @@ class V8HeapExplorer : public HeapEntriesAllocator {
HeapEntry* AddEntry(HeapObject* object,
HeapEntry::Type type,
const char* name);
HeapEntry* AddEntry(Address address,
HeapEntry::Type type,
const char* name,
int size);
const char* GetSystemEntryName(HeapObject* object);

View File

@ -2388,6 +2388,51 @@ TEST(ArrayBufferAndArrayBufferView) {
}
static int GetRetainersCount(const v8::HeapSnapshot* snapshot,
const v8::HeapGraphNode* node) {
int count = 0;
for (int i = 0, l = snapshot->GetNodesCount(); i < l; ++i) {
const v8::HeapGraphNode* parent = snapshot->GetNode(i);
for (int j = 0, l2 = parent->GetChildrenCount(); j < l2; ++j) {
if (parent->GetChild(j)->GetToNode() == node) {
++count;
}
}
}
return count;
}
TEST(ArrayBufferSharedBackingStore) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
CompileRun("sin1 = Math.sin(1);");
LocalContext env2;
CompileRun("sin2 = Math.sin(2);");
const v8::HeapSnapshot* snapshot =
heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
CHECK(ValidateSnapshot(snapshot));
// The 0th-child is (GC Roots), 1st is the user root.
const v8::HeapGraphNode* global =
snapshot->GetRoot()->GetChild(1)->GetToNode();
const v8::HeapGraphNode* builtins =
GetProperty(global, v8::HeapGraphEdge::kInternal, "builtins");
CHECK_NE(NULL, builtins);
const v8::HeapGraphNode* sin_table =
GetProperty(builtins, v8::HeapGraphEdge::kProperty, "kSinTable");
CHECK_NE(NULL, sin_table);
const v8::HeapGraphNode* buffer =
GetProperty(sin_table, v8::HeapGraphEdge::kInternal, "buffer");
CHECK_NE(NULL, buffer);
const v8::HeapGraphNode* backing_store =
GetProperty(buffer, v8::HeapGraphEdge::kInternal, "backing_store");
CHECK_NE(NULL, backing_store);
int retainers = GetRetainersCount(snapshot, backing_store);
CHECK_EQ(2, retainers);
}
TEST(BoxObject) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);