From: Sean Gillespie Date: Sat, 1 Apr 2017 21:25:46 +0000 (-0700) Subject: [Local GC] Move some EE-specific finalize-on-unload logic out of the GC (dotnet/corec... X-Git-Tag: submit/tizen/20210909.063632~11030^2~7456 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2e5fa1fde20890c36b193da740231286382207aa;p=platform%2Fupstream%2Fdotnet%2Fruntime.git [Local GC] Move some EE-specific finalize-on-unload logic out of the GC (dotnet/coreclr#10598) * Move some EE-specific logic to a callback on GCToEEInterface * Fix the sample * Consistent style for pointers * Code review feedback: Move app domain index check into EE callback and make ShouldFinalizeObjectForUnload always return true (due to CoreCLR not having app domains) * Code review feedback: Fix a comment and add a TODO for bringing these changes to desktop Commit migrated from https://github.com/dotnet/coreclr/commit/41617fee235d22d9e6dc1fa31548de63637551fa --- diff --git a/src/coreclr/src/gc/env/gcenv.ee.h b/src/coreclr/src/gc/env/gcenv.ee.h index 689b1cc..8c4dfcc 100644 --- a/src/coreclr/src/gc/env/gcenv.ee.h +++ b/src/coreclr/src/gc/env/gcenv.ee.h @@ -70,6 +70,7 @@ public: static void EnableFinalization(bool foundFinalizers); static void HandleFatalError(unsigned int exitCode); + static bool ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj); }; #endif // __GCENV_EE_H__ diff --git a/src/coreclr/src/gc/gc.cpp b/src/coreclr/src/gc/gc.cpp index d8a59cd..ab8e56b 100644 --- a/src/coreclr/src/gc/gc.cpp +++ b/src/coreclr/src/gc/gc.cpp @@ -36102,43 +36102,15 @@ CFinalize::FinalizeSegForAppDomain (AppDomain *pDomain, // if it has the index we are looking for. If the methodtable is null, it can't be from the // unloading domain, so skip it. if (method_table(obj) == NULL) + { continue; + } - // eagerly finalize all objects except those that may be agile. - if (obj->GetAppDomainIndex() != pDomain->GetIndex()) + // does the EE actually want us to finalize this object? + if (!GCToEEInterface::ShouldFinalizeObjectForUnload(pDomain, obj)) + { continue; - -#ifndef FEATURE_REDHAWK - if (method_table(obj)->IsAgileAndFinalizable()) - { - // If an object is both agile & finalizable, we leave it in the - // finalization queue during unload. This is OK, since it's agile. - // Right now only threads can be this way, so if that ever changes, change - // the assert to just continue if not a thread. - _ASSERTE(method_table(obj) == g_pThreadClass); - - if (method_table(obj) == g_pThreadClass) - { - // However, an unstarted thread should be finalized. It could be holding a delegate - // in the domain we want to unload. Once the thread has been started, its - // delegate is cleared so only unstarted threads are a problem. - Thread *pThread = ((THREADBASEREF)ObjectToOBJECTREF(obj))->GetInternal(); - if (! pThread || ! pThread->IsUnstarted()) - { - // This appdomain is going to be gone soon so let us assign - // it the appdomain that's guaranteed to exist - // The object is agile and the delegate should be null so we can do it - obj->GetHeader()->ResetAppDomainIndexNoFailure(SystemDomain::System()->DefaultDomain()->GetIndex()); - continue; - } - } - else - { - obj->GetHeader()->ResetAppDomainIndexNoFailure(SystemDomain::System()->DefaultDomain()->GetIndex()); - continue; - } } -#endif //!FEATURE_REDHAWK if (!fRunFinalizers || (obj->GetHeader()->GetBits()) & BIT_SBLK_FINALIZER_RUN) { diff --git a/src/coreclr/src/gc/gcenv.ee.standalone.inl b/src/coreclr/src/gc/gcenv.ee.standalone.inl index c391ef8..328acef 100644 --- a/src/coreclr/src/gc/gcenv.ee.standalone.inl +++ b/src/coreclr/src/gc/gcenv.ee.standalone.inl @@ -213,6 +213,12 @@ ALWAYS_INLINE void GCToEEInterface::HandleFatalError(unsigned int exitCode) g_theGCToCLR->HandleFatalError(exitCode); } +ALWAYS_INLINE bool GCToEEInterface::ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj) +{ + assert(g_theGCToCLR != nullptr); + return g_theGCToCLR->ShouldFinalizeObjectForUnload(pDomain, obj); +} + #undef ALWAYS_INLINE #endif // __GCTOENV_EE_STANDALONE_INL__ diff --git a/src/coreclr/src/gc/gcinterface.ee.h b/src/coreclr/src/gc/gcinterface.ee.h index da74665..5c595b4 100644 --- a/src/coreclr/src/gc/gcinterface.ee.h +++ b/src/coreclr/src/gc/gcinterface.ee.h @@ -137,6 +137,11 @@ public: // Signals to the EE that the GC encountered a fatal error and can't recover. virtual void HandleFatalError(unsigned int exitCode) = 0; + + // Asks the EE if it wants a particular object to be finalized when unloading + // an app domain. + virtual + bool ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj) = 0; }; #endif // _GCINTERFACE_EE_H_ diff --git a/src/coreclr/src/gc/sample/gcenv.ee.cpp b/src/coreclr/src/gc/sample/gcenv.ee.cpp index 07be244..aaca51e 100644 --- a/src/coreclr/src/gc/sample/gcenv.ee.cpp +++ b/src/coreclr/src/gc/sample/gcenv.ee.cpp @@ -270,6 +270,11 @@ void GCToEEInterface::HandleFatalError(unsigned int exitCode) abort(); } +bool GCToEEInterface::ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj) +{ + return true; +} + bool IsGCSpecialThread() { // TODO: Implement for background GC diff --git a/src/coreclr/src/vm/gcenv.ee.cpp b/src/coreclr/src/vm/gcenv.ee.cpp index cf2728d..f3c139e 100644 --- a/src/coreclr/src/vm/gcenv.ee.cpp +++ b/src/coreclr/src/vm/gcenv.ee.cpp @@ -1350,3 +1350,12 @@ void GCToEEInterface::HandleFatalError(unsigned int exitCode) { EEPOLICY_HANDLE_FATAL_ERROR(exitCode); } + +bool GCToEEInterface::ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj) +{ + // CoreCLR does not have appdomains, so this code path is dead. Other runtimes may + // choose to inspect the object being finalized here. + // [DESKTOP TODO] Desktop looks for "agile and finalizable" objects and may choose + // to move them to a new app domain instead of finalizing them here. + return true; +} diff --git a/src/coreclr/src/vm/gcenv.ee.h b/src/coreclr/src/vm/gcenv.ee.h index e3ced6c..030eb71 100644 --- a/src/coreclr/src/vm/gcenv.ee.h +++ b/src/coreclr/src/vm/gcenv.ee.h @@ -45,6 +45,7 @@ public: void EnableFinalization(bool foundFinalizers); void HandleFatalError(unsigned int exitCode); + bool ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj); }; #endif // FEATURE_STANDALONE_GC