| Index: test/cctest/test-heap-profiler.cc
|
| diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
|
| index 92ad0a4002a1fbd967a3bf03a4324ec8be8c290d..6dc49c0e54911adba3981d9fb565dda9e2d087b0 100644
|
| --- a/test/cctest/test-heap-profiler.cc
|
| +++ b/test/cctest/test-heap-profiler.cc
|
| @@ -372,6 +372,7 @@ TEST(RetainerProfile) {
|
| i::HeapIterator iterator;
|
| for (i::HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next())
|
| ret_profile.CollectStats(obj);
|
| + ret_profile.CoarseAndAggregate();
|
| RetainerProfilePrinter printer;
|
| ret_profile.DebugPrintStats(&printer);
|
| const char* retainers_of_a = printer.GetRetainers("A");
|
| @@ -650,6 +651,8 @@ TEST(HeapSnapshotCodeObjects) {
|
| CompileAndRunScript(
|
| "function lazy(x) { return x - 1; }\n"
|
| "function compiled(x) { return x + 1; }\n"
|
| + "var inferred = function(x) { return x; }\n"
|
| + "var anonymous = (function() { return function() { return 0; } })();\n"
|
| "compiled(1)");
|
| const v8::HeapSnapshot* snapshot =
|
| v8::HeapProfiler::TakeSnapshot(v8::String::New("code"));
|
| @@ -663,6 +666,18 @@ TEST(HeapSnapshotCodeObjects) {
|
| GetProperty(global, v8::HeapGraphEdge::kProperty, "lazy");
|
| CHECK_NE(NULL, lazy);
|
| CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType());
|
| + const v8::HeapGraphNode* inferred =
|
| + GetProperty(global, v8::HeapGraphEdge::kProperty, "inferred");
|
| + CHECK_NE(NULL, inferred);
|
| + CHECK_EQ(v8::HeapGraphNode::kClosure, inferred->GetType());
|
| + v8::String::AsciiValue inferred_name(inferred->GetName());
|
| + CHECK_EQ("inferred", *inferred_name);
|
| + const v8::HeapGraphNode* anonymous =
|
| + GetProperty(global, v8::HeapGraphEdge::kProperty, "anonymous");
|
| + CHECK_NE(NULL, anonymous);
|
| + CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType());
|
| + v8::String::AsciiValue anonymous_name(anonymous->GetName());
|
| + CHECK_EQ("(anonymous function)", *anonymous_name);
|
|
|
| // Find references to code.
|
| const v8::HeapGraphNode* compiled_code =
|
| @@ -864,4 +879,114 @@ TEST(Issue822) {
|
| i::HeapSnapshotTester::CalculateNetworkSize(*jsobj);
|
| }
|
|
|
| +
|
| +static const v8::HeapGraphNode* GetChild(
|
| + const v8::HeapGraphNode* node,
|
| + v8::HeapGraphNode::Type type,
|
| + const char* name,
|
| + const v8::HeapGraphNode* after = NULL) {
|
| + bool ignore_child = after == NULL ? false : true;
|
| + for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
|
| + const v8::HeapGraphEdge* prop = node->GetChild(i);
|
| + const v8::HeapGraphNode* child = prop->GetToNode();
|
| + v8::String::AsciiValue child_name(child->GetName());
|
| + if (!ignore_child
|
| + && child->GetType() == type
|
| + && strcmp(name, *child_name) == 0)
|
| + return child;
|
| + if (after != NULL && child == after) ignore_child = false;
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +static bool IsNodeRetainedAs(const v8::HeapGraphNode* node,
|
| + int element) {
|
| + for (int i = 0, count = node->GetRetainersCount(); i < count; ++i) {
|
| + const v8::HeapGraphEdge* prop = node->GetRetainer(i);
|
| + if (prop->GetType() == v8::HeapGraphEdge::kElement
|
| + && element == prop->GetName()->Int32Value())
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +TEST(AggregatedHeapSnapshot) {
|
| + v8::HandleScope scope;
|
| + LocalContext env;
|
| +
|
| + CompileAndRunScript(
|
| + "function A() {}\n"
|
| + "function B(x) { this.x = x; }\n"
|
| + "var a = new A();\n"
|
| + "var b = new B(a);");
|
| + const v8::HeapSnapshot* snapshot =
|
| + v8::HeapProfiler::TakeSnapshot(
|
| + v8::String::New("agg"), v8::HeapSnapshot::kAggregated);
|
| + const v8::HeapGraphNode* strings = GetChild(snapshot->GetRoot(),
|
| + v8::HeapGraphNode::kInternal,
|
| + "STRING_TYPE");
|
| + CHECK_NE(NULL, strings);
|
| + CHECK_NE(0, strings->GetSelfSize());
|
| + CHECK_NE(0, strings->GetInstancesCount());
|
| + const v8::HeapGraphNode* maps = GetChild(snapshot->GetRoot(),
|
| + v8::HeapGraphNode::kInternal,
|
| + "MAP_TYPE");
|
| + CHECK_NE(NULL, maps);
|
| + CHECK_NE(0, maps->GetSelfSize());
|
| + CHECK_NE(0, maps->GetInstancesCount());
|
| +
|
| + const v8::HeapGraphNode* a = GetChild(snapshot->GetRoot(),
|
| + v8::HeapGraphNode::kObject,
|
| + "A");
|
| + CHECK_NE(NULL, a);
|
| + CHECK_NE(0, a->GetSelfSize());
|
| + CHECK_EQ(1, a->GetInstancesCount());
|
| +
|
| + const v8::HeapGraphNode* b = GetChild(snapshot->GetRoot(),
|
| + v8::HeapGraphNode::kObject,
|
| + "B");
|
| + CHECK_NE(NULL, b);
|
| + CHECK_NE(0, b->GetSelfSize());
|
| + CHECK_EQ(1, b->GetInstancesCount());
|
| +
|
| + const v8::HeapGraphNode* glob_prop = GetChild(snapshot->GetRoot(),
|
| + v8::HeapGraphNode::kObject,
|
| + "(global property)",
|
| + b);
|
| + CHECK_NE(NULL, glob_prop);
|
| + CHECK_EQ(0, glob_prop->GetSelfSize());
|
| + CHECK_EQ(0, glob_prop->GetInstancesCount());
|
| + CHECK_NE(0, glob_prop->GetChildrenCount());
|
| +
|
| + const v8::HeapGraphNode* a_from_glob_prop = GetChild(
|
| + glob_prop,
|
| + v8::HeapGraphNode::kObject,
|
| + "A");
|
| + CHECK_NE(NULL, a_from_glob_prop);
|
| + CHECK_EQ(0, a_from_glob_prop->GetSelfSize());
|
| + CHECK_EQ(0, a_from_glob_prop->GetInstancesCount());
|
| + CHECK_EQ(0, a_from_glob_prop->GetChildrenCount()); // Retains nothing.
|
| + CHECK(IsNodeRetainedAs(a_from_glob_prop, 1)); // (global propery) has 1 ref.
|
| +
|
| + const v8::HeapGraphNode* b_with_children = GetChild(
|
| + snapshot->GetRoot(),
|
| + v8::HeapGraphNode::kObject,
|
| + "B",
|
| + b);
|
| + CHECK_NE(NULL, b_with_children);
|
| + CHECK_EQ(0, b_with_children->GetSelfSize());
|
| + CHECK_EQ(0, b_with_children->GetInstancesCount());
|
| + CHECK_NE(0, b_with_children->GetChildrenCount());
|
| +
|
| + const v8::HeapGraphNode* a_from_b = GetChild(
|
| + b_with_children,
|
| + v8::HeapGraphNode::kObject,
|
| + "A");
|
| + CHECK_NE(NULL, a_from_b);
|
| + CHECK_EQ(0, a_from_b->GetSelfSize());
|
| + CHECK_EQ(0, a_from_b->GetInstancesCount());
|
| + CHECK_EQ(0, a_from_b->GetChildrenCount()); // Retains nothing.
|
| + CHECK(IsNodeRetainedAs(a_from_b, 1)); // B has 1 ref to A.
|
| +}
|
| +
|
| #endif // ENABLE_LOGGING_AND_PROFILING
|
|
|