Implement VisitHandlesInNewSpaceWithClassIds()
authormstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 24 Jan 2013 15:53:16 +0000 (15:53 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 24 Jan 2013 15:53:16 +0000 (15:53 +0000)
BUG=
TEST=test-api.cc::PersistentHandleInNewSpaceVisitor

Review URL: https://codereview.chromium.org/11365131
Patch from Kentaro Hara <haraken@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13496 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

include/v8.h
src/api.cc
src/global-handles.cc
src/global-handles.h
test/cctest/test-api.cc

index 8d8a992..5f3e2ed 100644 (file)
@@ -3489,6 +3489,16 @@ class V8EXPORT V8 {
   static void VisitHandlesWithClassIds(PersistentHandleVisitor* visitor);
 
   /**
+   * Iterates through all the persistent handles in the current isolate's heap
+   * that have class_ids and are candidates to be marked as partially dependent
+   * handles. This will visit handles to young objects created since the last
+   * garbage collection but is free to visit an arbitrary superset of these
+   * objects.
+   */
+  static void VisitHandlesForPartialDependence(
+      Isolate* isolate, PersistentHandleVisitor* visitor);
+
+  /**
    * Optional notification that the embedder is idle.
    * V8 uses the notification to reduce memory footprint.
    * This call can be used repeatedly if the embedder remains idle.
index 54b233c..1561f24 100644 (file)
@@ -4495,30 +4495,47 @@ void v8::V8::VisitExternalResources(ExternalResourceVisitor* visitor) {
 }
 
 
+class VisitorAdapter : public i::ObjectVisitor {
+ public:
+  explicit VisitorAdapter(PersistentHandleVisitor* visitor)
+      : visitor_(visitor) {}
+  virtual void VisitPointers(i::Object** start, i::Object** end) {
+    UNREACHABLE();
+  }
+  virtual void VisitEmbedderReference(i::Object** p, uint16_t class_id) {
+    visitor_->VisitPersistentHandle(ToApi<Value>(i::Handle<i::Object>(p)),
+                                    class_id);
+  }
+ private:
+  PersistentHandleVisitor* visitor_;
+};
+
+
 void v8::V8::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) {
   i::Isolate* isolate = i::Isolate::Current();
   IsDeadCheck(isolate, "v8::V8::VisitHandlesWithClassId");
 
   i::AssertNoAllocation no_allocation;
 
-  class VisitorAdapter : public i::ObjectVisitor {
-   public:
-    explicit VisitorAdapter(PersistentHandleVisitor* visitor)
-        : visitor_(visitor) {}
-    virtual void VisitPointers(i::Object** start, i::Object** end) {
-      UNREACHABLE();
-    }
-    virtual void VisitEmbedderReference(i::Object** p, uint16_t class_id) {
-      visitor_->VisitPersistentHandle(ToApi<Value>(i::Handle<i::Object>(p)),
-                                      class_id);
-    }
-   private:
-    PersistentHandleVisitor* visitor_;
-  } visitor_adapter(visitor);
+  VisitorAdapter visitor_adapter(visitor);
   isolate->global_handles()->IterateAllRootsWithClassIds(&visitor_adapter);
 }
 
 
+void v8::V8::VisitHandlesForPartialDependence(
+    Isolate* exported_isolate, PersistentHandleVisitor* visitor) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(exported_isolate);
+  ASSERT(isolate == i::Isolate::Current());
+  IsDeadCheck(isolate, "v8::V8::VisitHandlesForPartialDependence");
+
+  i::AssertNoAllocation no_allocation;
+
+  VisitorAdapter visitor_adapter(visitor);
+  isolate->global_handles()->IterateAllRootsInNewSpaceWithClassIds(
+      &visitor_adapter);
+}
+
+
 bool v8::V8::IdleNotification(int hint) {
   // Returning true tells the caller that it need not
   // continue to call IdleNotification.
@@ -5447,11 +5464,11 @@ void V8::AddObjectGroup(Persistent<Value>* objects,
 }
 
 
-void V8::AddObjectGroup(Isolate* exportedIsolate,
+void V8::AddObjectGroup(Isolate* exported_isolate,
                         Persistent<Value>* objects,
                         size_t length,
                         RetainedObjectInfo* info) {
-  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(exportedIsolate);
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(exported_isolate);
   ASSERT(isolate == i::Isolate::Current());
   if (IsDeadCheck(isolate, "v8::V8::AddObjectGroup()")) return;
   STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
index 427eae0..23b3918 100644 (file)
@@ -682,6 +682,17 @@ void GlobalHandles::IterateAllRootsWithClassIds(ObjectVisitor* v) {
 }
 
 
+void GlobalHandles::IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v) {
+  for (int i = 0; i < new_space_nodes_.length(); ++i) {
+    Node* node = new_space_nodes_[i];
+    if (node->IsRetainer() && node->has_wrapper_class_id()) {
+      v->VisitEmbedderReference(node->location(),
+                                node->wrapper_class_id());
+    }
+  }
+}
+
+
 int GlobalHandles::NumberOfWeakHandles() {
   int count = 0;
   for (NodeIterator it(this); !it.done(); it.Advance()) {
index 8cfb34b..18bfc11 100644 (file)
@@ -173,6 +173,10 @@ class GlobalHandles {
   // Iterates over all handles that have embedder-assigned class ID.
   void IterateAllRootsWithClassIds(ObjectVisitor* v);
 
+  // Iterates over all handles in the new space that have embedder-assigned
+  // class ID.
+  void IterateAllRootsInNewSpaceWithClassIds(ObjectVisitor* v);
+
   // Iterates over all weak roots in heap.
   void IterateWeakRoots(ObjectVisitor* v);
 
index d3b8824..ca027df 100644 (file)
@@ -16699,6 +16699,32 @@ TEST(WrapperClassId) {
 }
 
 
+TEST(PersistentHandleInNewSpaceVisitor) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8::Persistent<v8::Object> object1 =
+      v8::Persistent<v8::Object>::New(v8::Object::New());
+  CHECK_EQ(0, object1.WrapperClassId());
+  object1.SetWrapperClassId(42);
+  CHECK_EQ(42, object1.WrapperClassId());
+
+  HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
+
+  v8::Persistent<v8::Object> object2 =
+      v8::Persistent<v8::Object>::New(v8::Object::New());
+  CHECK_EQ(0, object2.WrapperClassId());
+  object2.SetWrapperClassId(42);
+  CHECK_EQ(42, object2.WrapperClassId());
+
+  Visitor42 visitor(object2);
+  v8::V8::VisitHandlesForPartialDependence(v8::Isolate::GetCurrent(), &visitor);
+  CHECK_EQ(1, visitor.counter_);
+
+  object1.Dispose();
+  object2.Dispose();
+}
+
+
 TEST(RegExp) {
   v8::HandleScope scope;
   LocalContext context;