Upgrade to V8 3.4

Merge 3.4.14.35

Simple merge required updates to makefiles only.

Bug: 568872
Change-Id: I403a38452c547e06fcfa951c12eca12a1bc40978
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index d686921..8675a01 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -2,388 +2,15 @@
 //
 // Tests for heap profiler
 
-#ifdef ENABLE_LOGGING_AND_PROFILING
-
 #include "v8.h"
 
 #include "cctest.h"
 #include "heap-profiler.h"
 #include "snapshot.h"
-#include "string-stream.h"
 #include "utils-inl.h"
-#include "zone-inl.h"
 #include "../include/v8-profiler.h"
 
 namespace i = v8::internal;
-using i::ClustersCoarser;
-using i::JSObjectsCluster;
-using i::JSObjectsRetainerTree;
-using i::JSObjectsClusterTree;
-using i::RetainerHeapProfile;
-
-
-namespace {
-
-class ConstructorHeapProfileTestHelper : public i::ConstructorHeapProfile {
- public:
-  ConstructorHeapProfileTestHelper()
-    : i::ConstructorHeapProfile(),
-      f_name_(FACTORY->NewStringFromAscii(i::CStrVector("F"))),
-      f_count_(0) {
-  }
-
-  void Call(const JSObjectsCluster& cluster,
-            const i::NumberAndSizeInfo& number_and_size) {
-    if (f_name_->Equals(cluster.constructor())) {
-      CHECK_EQ(f_count_, 0);
-      f_count_ = number_and_size.number();
-      CHECK_GT(f_count_, 0);
-    }
-  }
-
-  int f_count() { return f_count_; }
-
- private:
-  i::Handle<i::String> f_name_;
-  int f_count_;
-};
-
-}  // namespace
-
-
-TEST(ConstructorProfile) {
-  v8::HandleScope scope;
-  LocalContext env;
-
-  CompileRun(
-      "function F() {}  // A constructor\n"
-      "var f1 = new F();\n"
-      "var f2 = new F();\n");
-
-  ConstructorHeapProfileTestHelper cons_profile;
-  i::AssertNoAllocation no_alloc;
-  i::HeapIterator iterator;
-  for (i::HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next())
-    cons_profile.CollectStats(obj);
-  CHECK_EQ(0, cons_profile.f_count());
-  cons_profile.PrintStats();
-  CHECK_EQ(2, cons_profile.f_count());
-}
-
-
-static JSObjectsCluster AddHeapObjectToTree(JSObjectsRetainerTree* tree,
-                                            i::String* constructor,
-                                            int instance,
-                                            JSObjectsCluster* ref1 = NULL,
-                                            JSObjectsCluster* ref2 = NULL,
-                                            JSObjectsCluster* ref3 = NULL) {
-  JSObjectsCluster o(constructor, reinterpret_cast<i::Object*>(instance));
-  JSObjectsClusterTree* o_tree = new JSObjectsClusterTree();
-  JSObjectsClusterTree::Locator o_loc;
-  if (ref1 != NULL) o_tree->Insert(*ref1, &o_loc);
-  if (ref2 != NULL) o_tree->Insert(*ref2, &o_loc);
-  if (ref3 != NULL) o_tree->Insert(*ref3, &o_loc);
-  JSObjectsRetainerTree::Locator loc;
-  tree->Insert(o, &loc);
-  loc.set_value(o_tree);
-  return o;
-}
-
-
-static void AddSelfReferenceToTree(JSObjectsRetainerTree* tree,
-                                   JSObjectsCluster* self_ref) {
-  JSObjectsRetainerTree::Locator loc;
-  CHECK(tree->Find(*self_ref, &loc));
-  JSObjectsClusterTree::Locator o_loc;
-  CHECK_NE(NULL, loc.value());
-  loc.value()->Insert(*self_ref, &o_loc);
-}
-
-
-static inline void CheckEqualsHelper(const char* file, int line,
-                                     const char* expected_source,
-                                     const JSObjectsCluster& expected,
-                                     const char* value_source,
-                                     const JSObjectsCluster& value) {
-  if (JSObjectsCluster::Compare(expected, value) != 0) {
-    i::HeapStringAllocator allocator;
-    i::StringStream stream(&allocator);
-    stream.Add("#  Expected: ");
-    expected.DebugPrint(&stream);
-    stream.Add("\n#  Found: ");
-    value.DebugPrint(&stream);
-    V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n%s",
-             expected_source, value_source,
-             *stream.ToCString());
-  }
-}
-
-
-static inline void CheckNonEqualsHelper(const char* file, int line,
-                                     const char* expected_source,
-                                     const JSObjectsCluster& expected,
-                                     const char* value_source,
-                                     const JSObjectsCluster& value) {
-  if (JSObjectsCluster::Compare(expected, value) == 0) {
-    i::HeapStringAllocator allocator;
-    i::StringStream stream(&allocator);
-    stream.Add("# !Expected: ");
-    expected.DebugPrint(&stream);
-    stream.Add("\n#  Found: ");
-    value.DebugPrint(&stream);
-    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n%s",
-             expected_source, value_source,
-             *stream.ToCString());
-  }
-}
-
-
-TEST(ClustersCoarserSimple) {
-  v8::HandleScope scope;
-  LocalContext env;
-
-  i::ZoneScope zn_scope(i::Isolate::Current(), i::DELETE_ON_EXIT);
-
-  JSObjectsRetainerTree tree;
-  JSObjectsCluster function(HEAP->function_class_symbol());
-  JSObjectsCluster a(*FACTORY->NewStringFromAscii(i::CStrVector("A")));
-  JSObjectsCluster b(*FACTORY->NewStringFromAscii(i::CStrVector("B")));
-
-  // o1 <- Function
-  JSObjectsCluster o1 =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x100, &function);
-  // o2 <- Function
-  JSObjectsCluster o2 =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x200, &function);
-  // o3 <- A, B
-  JSObjectsCluster o3 =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x300, &a, &b);
-  // o4 <- B, A
-  JSObjectsCluster o4 =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x400, &b, &a);
-  // o5 <- A, B, Function
-  JSObjectsCluster o5 =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x500,
-                          &a, &b, &function);
-
-  ClustersCoarser coarser;
-  coarser.Process(&tree);
-
-  CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2));
-  CHECK_EQ(coarser.GetCoarseEquivalent(o3), coarser.GetCoarseEquivalent(o4));
-  CHECK_NE(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o3));
-  CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o5));
-}
-
-
-TEST(ClustersCoarserMultipleConstructors) {
-  v8::HandleScope scope;
-  LocalContext env;
-
-  i::ZoneScope zn_scope(i::Isolate::Current(), i::DELETE_ON_EXIT);
-
-  JSObjectsRetainerTree tree;
-  JSObjectsCluster function(HEAP->function_class_symbol());
-
-  // o1 <- Function
-  JSObjectsCluster o1 =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x100, &function);
-  // a1 <- Function
-  JSObjectsCluster a1 =
-      AddHeapObjectToTree(&tree, HEAP->Array_symbol(), 0x1000, &function);
-  // o2 <- Function
-  JSObjectsCluster o2 =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x200, &function);
-  // a2 <- Function
-  JSObjectsCluster a2 =
-      AddHeapObjectToTree(&tree, HEAP->Array_symbol(), 0x2000, &function);
-
-  ClustersCoarser coarser;
-  coarser.Process(&tree);
-
-  CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2));
-  CHECK_EQ(coarser.GetCoarseEquivalent(a1), coarser.GetCoarseEquivalent(a2));
-}
-
-
-TEST(ClustersCoarserPathsTraversal) {
-  v8::HandleScope scope;
-  LocalContext env;
-
-  i::ZoneScope zn_scope(i::Isolate::Current(), i::DELETE_ON_EXIT);
-
-  JSObjectsRetainerTree tree;
-
-  // On the following graph:
-  //
-  // p
-  //   <- o21 <- o11 <-
-  // q                  o
-  //   <- o22 <- o12 <-
-  // r
-  //
-  // we expect that coarser will deduce equivalences: p ~ q ~ r,
-  // o21 ~ o22, and o11 ~ o12.
-
-  JSObjectsCluster o =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x100);
-  JSObjectsCluster o11 =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x110, &o);
-  JSObjectsCluster o12 =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x120, &o);
-  JSObjectsCluster o21 =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x210, &o11);
-  JSObjectsCluster o22 =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x220, &o12);
-  JSObjectsCluster p =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x300, &o21);
-  JSObjectsCluster q =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x310, &o21, &o22);
-  JSObjectsCluster r =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x320, &o22);
-
-  ClustersCoarser coarser;
-  coarser.Process(&tree);
-
-  CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o));
-  CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(o11));
-  CHECK_EQ(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(o12));
-  CHECK_EQ(coarser.GetCoarseEquivalent(o21), coarser.GetCoarseEquivalent(o22));
-  CHECK_NE(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(o21));
-  CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(p));
-  CHECK_EQ(coarser.GetCoarseEquivalent(p), coarser.GetCoarseEquivalent(q));
-  CHECK_EQ(coarser.GetCoarseEquivalent(q), coarser.GetCoarseEquivalent(r));
-  CHECK_NE(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(p));
-  CHECK_NE(coarser.GetCoarseEquivalent(o21), coarser.GetCoarseEquivalent(p));
-}
-
-
-TEST(ClustersCoarserSelf) {
-  v8::HandleScope scope;
-  LocalContext env;
-
-  i::ZoneScope zn_scope(i::Isolate::Current(), i::DELETE_ON_EXIT);
-
-  JSObjectsRetainerTree tree;
-
-  // On the following graph:
-  //
-  // p (self-referencing)
-  //          <- o1     <-
-  // q (self-referencing)   o
-  //          <- o2     <-
-  // r (self-referencing)
-  //
-  // we expect that coarser will deduce equivalences: p ~ q ~ r, o1 ~ o2;
-
-  JSObjectsCluster o =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x100);
-  JSObjectsCluster o1 =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x110, &o);
-  JSObjectsCluster o2 =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x120, &o);
-  JSObjectsCluster p =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x300, &o1);
-  AddSelfReferenceToTree(&tree, &p);
-  JSObjectsCluster q =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x310, &o1, &o2);
-  AddSelfReferenceToTree(&tree, &q);
-  JSObjectsCluster r =
-      AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x320, &o2);
-  AddSelfReferenceToTree(&tree, &r);
-
-  ClustersCoarser coarser;
-  coarser.Process(&tree);
-
-  CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o));
-  CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(o1));
-  CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2));
-  CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(p));
-  CHECK_EQ(coarser.GetCoarseEquivalent(p), coarser.GetCoarseEquivalent(q));
-  CHECK_EQ(coarser.GetCoarseEquivalent(q), coarser.GetCoarseEquivalent(r));
-  CHECK_NE(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(p));
-}
-
-
-namespace {
-
-class RetainerProfilePrinter : public RetainerHeapProfile::Printer {
- public:
-  RetainerProfilePrinter() : stream_(&allocator_), lines_(100) {}
-
-  void PrintRetainers(const JSObjectsCluster& cluster,
-                      const i::StringStream& retainers) {
-    cluster.Print(&stream_);
-    stream_.Add("%s", *(retainers.ToCString()));
-    stream_.Put('\0');
-  }
-
-  const char* GetRetainers(const char* constructor) {
-    FillLines();
-    const size_t cons_len = strlen(constructor);
-    for (int i = 0; i < lines_.length(); ++i) {
-      if (strncmp(constructor, lines_[i], cons_len) == 0 &&
-          lines_[i][cons_len] == ',') {
-        return lines_[i] + cons_len + 1;
-      }
-    }
-    return NULL;
-  }
-
- private:
-  void FillLines() {
-    if (lines_.length() > 0) return;
-    stream_.Put('\0');
-    stream_str_ = stream_.ToCString();
-    const char* pos = *stream_str_;
-    while (pos != NULL && *pos != '\0') {
-      lines_.Add(pos);
-      pos = strchr(pos, '\0');
-      if (pos != NULL) ++pos;
-    }
-  }
-
-  i::HeapStringAllocator allocator_;
-  i::StringStream stream_;
-  i::SmartPointer<const char> stream_str_;
-  i::List<const char*> lines_;
-};
-
-}  // namespace
-
-
-TEST(RetainerProfile) {
-  v8::HandleScope scope;
-  LocalContext env;
-
-  CompileRun(
-      "function A() {}\n"
-      "function B(x) { this.x = x; }\n"
-      "function C(x) { this.x1 = x; this.x2 = x; }\n"
-      "var a = new A();\n"
-      "var b1 = new B(a), b2 = new B(a);\n"
-      "var c = new C(a);");
-
-  RetainerHeapProfile ret_profile;
-  i::AssertNoAllocation no_alloc;
-  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");
-  // The order of retainers is unspecified, so we check string length, and
-  // verify each retainer separately.
-  CHECK_EQ(i::StrLength("(global property);1,B;2,C;2"),
-           i::StrLength(retainers_of_a));
-  CHECK(strstr(retainers_of_a, "(global property);1") != NULL);
-  CHECK(strstr(retainers_of_a, "B;2") != NULL);
-  CHECK(strstr(retainers_of_a, "C;2") != NULL);
-  CHECK_EQ("(global property);2", printer.GetRetainers("B"));
-  CHECK_EQ("(global property);1", printer.GetRetainers("C"));
-}
-
 
 namespace {
 
@@ -416,8 +43,8 @@
   CHECK_EQ(2, snapshot->GetRoot()->GetChildrenCount());
   const v8::HeapGraphNode* global_obj =
       snapshot->GetRoot()->GetChild(0)->GetToNode();
-  CHECK_EQ("Object", const_cast<i::HeapEntry*>(
-      reinterpret_cast<const i::HeapEntry*>(global_obj))->name());
+  CHECK_EQ(0, strncmp("Object", const_cast<i::HeapEntry*>(
+      reinterpret_cast<const i::HeapEntry*>(global_obj))->name(), 6));
   return global_obj;
 }
 
@@ -726,116 +353,6 @@
 }
 
 
-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;
-
-  CompileRun(
-      "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::kHidden,
-                                              "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::kHidden,
-                                           "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.
-}
-
-
 TEST(HeapEntryDominator) {
   // The graph looks like this:
   //
@@ -1048,21 +565,6 @@
 }
 
 
-// Must not crash in debug mode.
-TEST(AggregatedHeapSnapshotJSONSerialization) {
-  v8::HandleScope scope;
-  LocalContext env;
-
-  const v8::HeapSnapshot* snapshot =
-      v8::HeapProfiler::TakeSnapshot(
-          v8::String::New("agg"), v8::HeapSnapshot::kAggregated);
-  TestJSONStream stream;
-  snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
-  CHECK_GT(stream.size(), 0);
-  CHECK_EQ(1, stream.eos_signaled());
-}
-
-
 TEST(HeapSnapshotGetNodeById) {
   v8::HandleScope scope;
   LocalContext env;
@@ -1322,4 +824,70 @@
   CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid3));
 }
 
-#endif  // ENABLE_LOGGING_AND_PROFILING
+
+TEST(DocumentURL) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  CompileRun("document = { URL:\"abcdefgh\" };");
+
+  const v8::HeapSnapshot* snapshot =
+      v8::HeapProfiler::TakeSnapshot(v8::String::New("document"));
+  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+  CHECK_NE(NULL, global);
+  CHECK_EQ("Object / abcdefgh",
+           const_cast<i::HeapEntry*>(
+               reinterpret_cast<const i::HeapEntry*>(global))->name());
+}
+
+
+TEST(DocumentWithException) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  CompileRun(
+      "this.__defineGetter__(\"document\", function() { throw new Error(); })");
+  const v8::HeapSnapshot* snapshot =
+      v8::HeapProfiler::TakeSnapshot(v8::String::New("document"));
+  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+  CHECK_NE(NULL, global);
+  CHECK_EQ("Object",
+           const_cast<i::HeapEntry*>(
+               reinterpret_cast<const i::HeapEntry*>(global))->name());
+}
+
+
+TEST(DocumentURLWithException) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  CompileRun(
+      "function URLWithException() {}\n"
+      "URLWithException.prototype = { get URL() { throw new Error(); } };\n"
+      "document = { URL: new URLWithException() };");
+  const v8::HeapSnapshot* snapshot =
+      v8::HeapProfiler::TakeSnapshot(v8::String::New("document"));
+  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+  CHECK_NE(NULL, global);
+  CHECK_EQ("Object",
+           const_cast<i::HeapEntry*>(
+               reinterpret_cast<const i::HeapEntry*>(global))->name());
+}
+
+
+TEST(NodesIteration) {
+  v8::HandleScope scope;
+  LocalContext env;
+  const v8::HeapSnapshot* snapshot =
+      v8::HeapProfiler::TakeSnapshot(v8::String::New("iteration"));
+  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+  CHECK_NE(NULL, global);
+  // Verify that we can find this object by iteration.
+  const int nodes_count = snapshot->GetNodesCount();
+  int count = 0;
+  for (int i = 0; i < nodes_count; ++i) {
+    if (snapshot->GetNode(i) == global)
+      ++count;
+  }
+  CHECK_EQ(1, count);
+}