Revision: 5096
Author: [email protected]
Date: Mon Jul 19 06:26:25 2010
Log: Add a check that weak object handle is not in NEAR_DEATH state after weak callback invocation.

If object enters NEAR_DEATH state, it must be explicitly cleared and/or disposed, otherwise it would retain JS object forever. Note as well that parameter is reset to NULL on first
invocation so weak handle callback would be in hard situation.

Review URL: http://codereview.chromium.org/3011009
http://code.google.com/p/v8/source/detail?r=5096

Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/global-handles.cc
 /branches/bleeding_edge/src/profile-generator.cc
 /branches/bleeding_edge/test/cctest/test-api.cc
 /branches/bleeding_edge/test/cctest/test-heap.cc
 /branches/bleeding_edge/test/cctest/test-mark-compact.cc

=======================================
--- /branches/bleeding_edge/include/v8.h        Mon Jul 19 02:51:33 2010
+++ /branches/bleeding_edge/include/v8.h        Mon Jul 19 06:26:25 2010
@@ -137,6 +137,9 @@
 /**
  * A weak reference callback function.
  *
+ * This callback should either explicitly invoke Dispose on |object| if
+ * V8 wrapper is not needed anymore, or 'revive' it by invocation of MakeWeak.
+ *
* \param object the weak global object to be reclaimed by the garbage collector
  * \param parameter the value passed in when making the weak global object
  */
=======================================
--- /branches/bleeding_edge/src/global-handles.cc       Wed Dec  9 06:32:45 2009
+++ /branches/bleeding_edge/src/global-handles.cc       Mon Jul 19 06:26:25 2010
@@ -151,13 +151,14 @@
   bool PostGarbageCollectionProcessing() {
     if (state_ != Node::PENDING) return false;
     LOG(HandleEvent("GlobalHandle::Processing", handle().location()));
+    WeakReferenceCallback func = callback();
+    if (func == NULL) {
+      Destroy();
+      return false;
+    }
     void* par = parameter();
     state_ = NEAR_DEATH;
     set_parameter(NULL);
- // The callback function is resolved as late as possible to preserve old
-    // behavior.
-    WeakReferenceCallback func = callback();
-    if (func == NULL) return false;

     v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle());
     {
@@ -178,6 +179,9 @@
       VMState state(EXTERNAL);
       func(object, par);
     }
+    // Absense of explicit cleanup or revival of weak handle
+    // in most of the cases would lead to memory leak.
+    ASSERT(state_ != NEAR_DEATH);
     return true;
   }

=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Fri Jul 16 01:20:39 2010 +++ /branches/bleeding_edge/src/profile-generator.cc Mon Jul 19 06:26:25 2010
@@ -74,6 +74,7 @@
                                            void* parameter) {
   reinterpret_cast<TokenEnumerator*>(parameter)->TokenRemoved(
       Utils::OpenHandle(*handle).location());
+  handle.Dispose();
 }


=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc     Tue Jul 13 04:38:30 2010
+++ /branches/bleeding_edge/test/cctest/test-api.cc     Mon Jul 19 06:26:25 2010
@@ -8015,9 +8015,10 @@
 v8::Persistent<v8::Object> some_object;
 v8::Persistent<v8::Object> bad_handle;

-void NewPersistentHandleCallback(v8::Persistent<v8::Value>, void*) {
+void NewPersistentHandleCallback(v8::Persistent<v8::Value> handle, void*) {
   v8::HandleScope scope;
   bad_handle = v8::Persistent<v8::Object>::New(some_object);
+  handle.Dispose();
 }


@@ -8046,6 +8047,7 @@
 void DisposeAndForceGcCallback(v8::Persistent<v8::Value> handle, void*) {
   to_be_disposed.Dispose();
   i::Heap::CollectAllGarbage(false);
+  handle.Dispose();
 }


@@ -8070,6 +8072,7 @@
 void HandleCreatingCallback(v8::Persistent<v8::Value> handle, void*) {
   v8::HandleScope scope;
   v8::Persistent<v8::Object>::New(v8::Object::New());
+  handle.Dispose();
 }


=======================================
--- /branches/bleeding_edge/test/cctest/test-heap.cc Tue Jul 13 06:06:33 2010 +++ /branches/bleeding_edge/test/cctest/test-heap.cc Mon Jul 19 06:26:25 2010
@@ -322,8 +322,8 @@

 static void TestWeakGlobalHandleCallback(v8::Persistent<v8::Value> handle,
                                          void* id) {
-  USE(handle);
   if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true;
+  handle.Dispose();
 }


@@ -398,17 +398,8 @@

   CHECK(WeakPointerCleared);
   CHECK(!GlobalHandles::IsNearDeath(h1.location()));
-  CHECK(GlobalHandles::IsNearDeath(h2.location()));

   GlobalHandles::Destroy(h1.location());
-  GlobalHandles::Destroy(h2.location());
-}
-
-static void TestDeleteWeakGlobalHandleCallback(
-    v8::Persistent<v8::Value> handle,
-    void* id) {
-  if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true;
-  handle.Dispose();
 }

 TEST(DeleteWeakGlobalHandle) {
@@ -427,7 +418,7 @@

   GlobalHandles::MakeWeak(h.location(),
                           reinterpret_cast<void*>(1234),
-                          &TestDeleteWeakGlobalHandleCallback);
+                          &TestWeakGlobalHandleCallback);

   // Scanvenge does not recognize weak reference.
   Heap::PerformScavenge();
=======================================
--- /branches/bleeding_edge/test/cctest/test-mark-compact.cc Tue Jan 19 08:34:37 2010 +++ /branches/bleeding_edge/test/cctest/test-mark-compact.cc Mon Jul 19 06:26:25 2010
@@ -273,6 +273,7 @@
 static int NumberOfWeakCalls = 0;
static void WeakPointerCallback(v8::Persistent<v8::Value> handle, void* id) {
   NumberOfWeakCalls++;
+  handle.Dispose();
 }

 TEST(ObjectGroups) {

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to