// 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)
{
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__
// 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_
{
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;
+}