[Local GC] Move Weak Reference finalization out of the GC (#10676)
authorSean Gillespie <sean@swgillespie.me>
Wed, 5 Apr 2017 16:57:50 +0000 (09:57 -0700)
committerGitHub <noreply@github.com>
Wed, 5 Apr 2017 16:57:50 +0000 (09:57 -0700)
* [Local GC] Move Weak Reference finalization out of the GC

* Address two issues:
  1) Use GetGCSafeMethodTable instead of GetMethodTable, so that the
     mark bit is correctly masked off the object's method table pointer,
  2) Address code review feedback by re-inserting a missed call to
     GetCanonicalMethodTable and rename the new API to EagerFinalized to
     better illustrate its broader purpose.

* Repair the GC sample

src/gc/env/gcenv.ee.h
src/gc/gc.cpp
src/gc/gc.h
src/gc/gcenv.ee.standalone.inl
src/gc/gcinterface.ee.h
src/gc/sample/gcenv.ee.cpp
src/vm/gcenv.ee.cpp
src/vm/gcenv.ee.h

index 8c4dfcc..e7102b0 100644 (file)
@@ -71,6 +71,7 @@ public:
 
     static void HandleFatalError(unsigned int exitCode);
     static bool ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj);
+    static bool EagerFinalized(Object* obj);
 };
 
 #endif // __GCENV_EE_H__
index ab8e56b..aad6ec8 100644 (file)
@@ -36269,16 +36269,11 @@ CFinalize::ScanForFinalization (promote_func* pfn, int gen, BOOL mark_only_p,
 
                     assert (method_table(obj)->HasFinalizer());
 
-#ifndef FEATURE_REDHAWK
-                    if (method_table(obj) == pWeakReferenceMT || method_table(obj)->GetCanonicalMethodTable() == pWeakReferenceOfTCanonMT)
+                    if (GCToEEInterface::EagerFinalized(obj))
                     {
-                        //destruct the handle right there.
-                        FinalizeWeakReference (obj);
                         MoveItem (i, Seg, FreeList);
                     }
-                    else
-#endif //!FEATURE_REDHAWK
-                    if ((obj->GetHeader()->GetBits()) & BIT_SBLK_FINALIZER_RUN)
+                    else if ((obj->GetHeader()->GetBits()) & BIT_SBLK_FINALIZER_RUN)
                     {
                         //remove the object because we don't want to
                         //run the finalizer
index 821b21d..8cd92fd 100644 (file)
@@ -256,12 +256,6 @@ void TouchPages(void * pStart, size_t cb);
 void updateGCShadow(Object** ptr, Object* val);
 #endif
 
-// the method table for the WeakReference class
-extern MethodTable  *pWeakReferenceMT;
-// The canonical method table for WeakReference<T>
-extern MethodTable  *pWeakReferenceOfTCanonMT;
-extern void FinalizeWeakReference(Object * obj);
-
 // The single GC heap instance, shared with the VM.
 extern IGCHeapInternal* g_theGCHeap;
 
index 328acef..13febb5 100644 (file)
@@ -219,6 +219,12 @@ ALWAYS_INLINE bool GCToEEInterface::ShouldFinalizeObjectForUnload(AppDomain* pDo
     return g_theGCToCLR->ShouldFinalizeObjectForUnload(pDomain, obj);
 }
 
+ALWAYS_INLINE bool GCToEEInterface::EagerFinalized(Object* obj)
+{
+    assert(g_theGCToCLR != nullptr);
+    return g_theGCToCLR->EagerFinalized(obj);
+}
+
 #undef ALWAYS_INLINE
 
 #endif // __GCTOENV_EE_STANDALONE_INL__
index 5c595b4..ee1b8ec 100644 (file)
@@ -142,6 +142,15 @@ public:
     // an app domain.
     virtual
     bool ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj) = 0;
+
+    // Offers the EE the option to finalize the given object eagerly, i.e.
+    // not on the finalizer thread but on the current thread. The
+    // EE returns true if it finalized the object eagerly and the GC does not
+    // need to do so, and false if it chose not to eagerly finalize the object
+    // and it's up to the GC to finalize it later.
+    virtual
+    bool EagerFinalized(Object* obj) = 0;
+
 };
 
 #endif // _GCINTERFACE_EE_H_
index aaca51e..392bfa1 100644 (file)
@@ -275,6 +275,12 @@ bool GCToEEInterface::ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object*
     return true;
 }
 
+bool GCToEEInterface::EagerFinalized(Object* obj)
+{
+    // The sample does not finalize anything eagerly.
+    return false;
+}
+
 bool IsGCSpecialThread()
 {
     // TODO: Implement for background GC
index f3c139e..a652359 100644 (file)
 #include "comcallablewrapper.h"
 #endif // FEATURE_COMINTEROP
 
+// the method table for the WeakReference class
+extern MethodTable* pWeakReferenceMT;
+
+// The canonical method table for WeakReference<T>
+extern MethodTable* pWeakReferenceOfTCanonMT;
+
+// Finalizes a weak reference directly.
+extern void FinalizeWeakReference(Object* obj);
+
 void GCToEEInterface::SuspendEE(SUSPEND_REASON reason)
 {
     WRAPPER_NO_CONTRACT;
@@ -1359,3 +1368,16 @@ bool GCToEEInterface::ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object*
     // to move them to a new app domain instead of finalizing them here.
     return true;
 }
+
+bool GCToEEInterface::EagerFinalized(Object* obj)
+{
+    MethodTable* pMT = obj->GetGCSafeMethodTable();
+    if (pMT == pWeakReferenceMT ||
+        pMT->GetCanonicalMethodTable() == pWeakReferenceOfTCanonMT)
+    {
+        FinalizeWeakReference(obj);
+        return true;
+    }
+
+    return false;
+}
index 030eb71..5eb3e3d 100644 (file)
@@ -46,6 +46,7 @@ public:
     void EnableFinalization(bool foundFinalizers);
     void HandleFatalError(unsigned int exitCode);
     bool ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj);
+    bool EagerFinalized(Object* obj);
 };
 
 #endif // FEATURE_STANDALONE_GC