Index: test/cctest/test-heap-profiler.cc |
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc |
index 478f00caf72d22cfb33cb32d79cf7268a384de67..33477acfa2518efdbedb7bbb4840361d8a90c30f 100644 |
--- a/test/cctest/test-heap-profiler.cc |
+++ b/test/cctest/test-heap-profiler.cc |
@@ -428,6 +428,53 @@ class NamedEntriesDetector { |
} // namespace |
+ |
+static const v8::HeapGraphNode* GetGlobalObject( |
+ const v8::HeapSnapshot* snapshot) { |
+ if (i::Snapshot::IsEnabled()) { |
+ // In case if snapshots are enabled, there will present a |
+ // vanilla deserealized global object, without properties |
+ // added by the test code. |
+ CHECK_EQ(2, snapshot->GetHead()->GetChildrenCount()); |
+ // Choose the global object of a bigger size. |
+ const v8::HeapGraphNode* node0 = |
+ snapshot->GetHead()->GetChild(0)->GetToNode(); |
+ const v8::HeapGraphNode* node1 = |
+ snapshot->GetHead()->GetChild(1)->GetToNode(); |
+ return node0->GetTotalSize() > node1->GetTotalSize() ? node0 : node1; |
+ } else { |
+ CHECK_EQ(1, snapshot->GetHead()->GetChildrenCount()); |
+ return snapshot->GetHead()->GetChild(0)->GetToNode(); |
+ } |
+} |
+ |
+ |
+static const v8::HeapGraphNode* GetProperty(const v8::HeapGraphNode* node, |
+ v8::HeapGraphEdge::Type type, |
+ const char* name) { |
+ for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { |
+ const v8::HeapGraphEdge* prop = node->GetChild(i); |
+ v8::String::AsciiValue prop_name(prop->GetName()); |
+ if (prop->GetType() == type && strcmp(name, *prop_name) == 0) |
+ return prop->GetToNode(); |
+ } |
+ return NULL; |
+} |
+ |
+ |
+static bool HasString(const v8::HeapGraphNode* node, const char* contents) { |
+ for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { |
+ const v8::HeapGraphEdge* prop = node->GetChild(i); |
+ const v8::HeapGraphNode* node = prop->GetToNode(); |
+ if (node->GetType() == v8::HeapGraphNode::STRING) { |
+ v8::String::AsciiValue node_name(node->GetName()); |
+ if (strcmp(contents, *node_name) == 0) return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
+ |
TEST(HeapSnapshot) { |
v8::HandleScope scope; |
@@ -458,53 +505,20 @@ TEST(HeapSnapshot) { |
"var c2 = new C2(a2);"); |
const v8::HeapSnapshot* snapshot_env2 = |
v8::HeapProfiler::TakeSnapshot(v8::String::New("env2")); |
- const v8::HeapGraphNode* global_env2; |
- if (i::Snapshot::IsEnabled()) { |
- // In case if snapshots are enabled, there will present a |
- // vanilla deserealized global object, without properties |
- // added by the test code. |
- CHECK_EQ(2, snapshot_env2->GetHead()->GetChildrenCount()); |
- // Choose the global object of a bigger size. |
- const v8::HeapGraphNode* node0 = |
- snapshot_env2->GetHead()->GetChild(0)->GetToNode(); |
- const v8::HeapGraphNode* node1 = |
- snapshot_env2->GetHead()->GetChild(1)->GetToNode(); |
- global_env2 = node0->GetTotalSize() > node1->GetTotalSize() ? |
- node0 : node1; |
- } else { |
- CHECK_EQ(1, snapshot_env2->GetHead()->GetChildrenCount()); |
- global_env2 = snapshot_env2->GetHead()->GetChild(0)->GetToNode(); |
- } |
+ const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); |
// Verify, that JS global object of env2 doesn't have '..1' |
// properties, but has '..2' properties. |
- bool has_a1 = false, has_b1_1 = false, has_b1_2 = false, has_c1 = false; |
- bool has_a2 = false, has_b2_1 = false, has_b2_2 = false, has_c2 = false; |
- // This will be needed further. |
- const v8::HeapGraphNode* a2_node = NULL; |
- for (int i = 0, count = global_env2->GetChildrenCount(); i < count; ++i) { |
- const v8::HeapGraphEdge* prop = global_env2->GetChild(i); |
- v8::String::AsciiValue prop_name(prop->GetName()); |
- if (strcmp("a1", *prop_name) == 0) has_a1 = true; |
- if (strcmp("b1_1", *prop_name) == 0) has_b1_1 = true; |
- if (strcmp("b1_2", *prop_name) == 0) has_b1_2 = true; |
- if (strcmp("c1", *prop_name) == 0) has_c1 = true; |
- if (strcmp("a2", *prop_name) == 0) { |
- has_a2 = true; |
- a2_node = prop->GetToNode(); |
- } |
- if (strcmp("b2_1", *prop_name) == 0) has_b2_1 = true; |
- if (strcmp("b2_2", *prop_name) == 0) has_b2_2 = true; |
- if (strcmp("c2", *prop_name) == 0) has_c2 = true; |
- } |
- CHECK(!has_a1); |
- CHECK(!has_b1_1); |
- CHECK(!has_b1_2); |
- CHECK(!has_c1); |
- CHECK(has_a2); |
- CHECK(has_b2_1); |
- CHECK(has_b2_2); |
- CHECK(has_c2); |
+ CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "a1")); |
+ CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b1_1")); |
+ CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b1_2")); |
+ CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "c1")); |
+ const v8::HeapGraphNode* a2_node = |
+ GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "a2"); |
+ CHECK_NE(NULL, a2_node); |
+ CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b2_1")); |
+ CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b2_2")); |
+ CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "c2")); |
// Verify that anything related to '[ABC]1' is not reachable. |
NamedEntriesDetector det; |
@@ -565,4 +579,62 @@ TEST(HeapSnapshot) { |
CHECK(has_b2_2_x_ref); |
} |
+ |
+TEST(HeapSnapshotCodeObjects) { |
+ v8::HandleScope scope; |
+ v8::Handle<v8::Context> env = v8::Context::New(); |
+ env->Enter(); |
+ |
+ CompileAndRunScript( |
+ "function lazy(x) { return x - 1; }\n" |
+ "function compiled(x) { return x + 1; }\n" |
+ "compiled(1)"); |
+ const v8::HeapSnapshot* snapshot = |
+ v8::HeapProfiler::TakeSnapshot(v8::String::New("code")); |
+ |
+ const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
+ const v8::HeapGraphNode* compiled = |
+ GetProperty(global, v8::HeapGraphEdge::PROPERTY, "compiled"); |
+ CHECK_NE(NULL, compiled); |
+ CHECK_EQ(v8::HeapGraphNode::CLOSURE, compiled->GetType()); |
+ const v8::HeapGraphNode* lazy = |
+ GetProperty(global, v8::HeapGraphEdge::PROPERTY, "lazy"); |
+ CHECK_NE(NULL, lazy); |
+ CHECK_EQ(v8::HeapGraphNode::CLOSURE, lazy->GetType()); |
+ |
+ // Find references to code. |
+ const v8::HeapGraphNode* compiled_code = |
+ GetProperty(compiled, v8::HeapGraphEdge::INTERNAL, "code"); |
+ CHECK_NE(NULL, compiled_code); |
+ const v8::HeapGraphNode* lazy_code = |
+ GetProperty(lazy, v8::HeapGraphEdge::INTERNAL, "code"); |
+ CHECK_NE(NULL, lazy_code); |
+ |
+ // Verify that non-compiled code doesn't contain references to "x" |
+ // literal, while compiled code does. |
+ bool compiled_references_x = false, lazy_references_x = false; |
+ for (int i = 0, count = compiled_code->GetChildrenCount(); i < count; ++i) { |
+ const v8::HeapGraphEdge* prop = compiled_code->GetChild(i); |
+ const v8::HeapGraphNode* node = prop->GetToNode(); |
+ if (node->GetType() == v8::HeapGraphNode::CODE) { |
+ if (HasString(node, "x")) { |
+ compiled_references_x = true; |
+ break; |
+ } |
+ } |
+ } |
+ for (int i = 0, count = lazy_code->GetChildrenCount(); i < count; ++i) { |
+ const v8::HeapGraphEdge* prop = lazy_code->GetChild(i); |
+ const v8::HeapGraphNode* node = prop->GetToNode(); |
+ if (node->GetType() == v8::HeapGraphNode::CODE) { |
+ if (HasString(node, "x")) { |
+ lazy_references_x = true; |
+ break; |
+ } |
+ } |
+ } |
+ CHECK(compiled_references_x); |
+ CHECK(!lazy_references_x); |
+} |
+ |
#endif // ENABLE_LOGGING_AND_PROFILING |