diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp
index be380486e356ca..c9b85fe68527bc 100644
--- a/src/coreclr/vm/appdomain.cpp
+++ b/src/coreclr/vm/appdomain.cpp
@@ -174,8 +174,8 @@ OBJECTREF *PinnedHeapHandleBucket::TryAllocateEmbeddedFreeHandle()
}
CONTRACTL_END;
- OBJECTREF pPreallocatedSentinelObject = ObjectFromHandle(g_pPreallocatedSentinelObject);
- _ASSERTE(pPreallocatedSentinelObject != NULL);
+ OBJECTREF pPreallocatedSentinelObject = g_pPreallocatedSentinelObject;
+ _ASSERTE(pPreallocatedSentinelObject != NULL);
for (int i = m_CurrentEmbeddedFreePos; i < m_CurrentPos; i++)
{
@@ -405,8 +405,8 @@ void PinnedHeapHandleTable::ReleaseHandlesLocked(OBJECTREF *pObjRef, DWORD nRele
_ASSERTE(m_Crst.OwnedByCurrentThread());
#endif
- OBJECTREF pPreallocatedSentinelObject = ObjectFromHandle(g_pPreallocatedSentinelObject);
- _ASSERTE(pPreallocatedSentinelObject != NULL);
+ OBJECTREF pPreallocatedSentinelObject = g_pPreallocatedSentinelObject;
+ _ASSERTE(pPreallocatedSentinelObject != NULL);
// Add the released handles to the list of available handles.
@@ -807,8 +807,14 @@ void SystemDomain::PreallocateSpecialObjects()
_ASSERTE(g_pPreallocatedSentinelObject == NULL);
- OBJECTREF pPreallocatedSentinelObject = AllocateObject(g_pObjectClass);
- g_pPreallocatedSentinelObject = AppDomain::GetCurrentDomain()->CreatePinningHandle( pPreallocatedSentinelObject );
+ g_pPreallocatedSentinelObject = TryAllocateFrozenObject(g_pObjectClass);
+ if (g_pPreallocatedSentinelObject == NULL)
+ {
+ OBJECTREF pPreallocatedSentinelObject = AllocateObject(g_pObjectClass);
+ // Keep the fallback object alive and immovable for the lifetime of the runtime.
+ OBJECTHANDLE handle = AppDomain::GetCurrentDomain()->CreatePinningHandle(pPreallocatedSentinelObject);
+ g_pPreallocatedSentinelObject = ObjectFromHandle(handle);
+ }
}
void SystemDomain::CreatePreallocatedExceptions()
diff --git a/src/coreclr/vm/vars.cpp b/src/coreclr/vm/vars.cpp
index ae813d80f56c72..3a1f1c766300d4 100644
--- a/src/coreclr/vm/vars.cpp
+++ b/src/coreclr/vm/vars.cpp
@@ -124,11 +124,11 @@ GVAL_IMPL_INIT(PTR_WSTR, g_EntryAssemblyPath, NULL);
#ifndef DACCESS_COMPILE
-// @TODO - PROMOTE.
OBJECTHANDLE g_pPreallocatedOutOfMemoryException;
OBJECTHANDLE g_pPreallocatedStackOverflowException;
OBJECTHANDLE g_pPreallocatedExecutionEngineException;
-OBJECTHANDLE g_pPreallocatedSentinelObject;
+
+OBJECTREF g_pPreallocatedSentinelObject = NULL;
//
//
diff --git a/src/coreclr/vm/vars.hpp b/src/coreclr/vm/vars.hpp
index 49334c9953d73e..2d3560af03b931 100644
--- a/src/coreclr/vm/vars.hpp
+++ b/src/coreclr/vm/vars.hpp
@@ -396,14 +396,12 @@ GVAL_DECL(PTR_WSTR, g_EntryAssemblyPath);
// Global System Information
extern SYSTEM_INFO g_SystemInfo;
-// @TODO - PROMOTE.
-// @TODO - I'd like to make these private members of CLRException some day.
EXTERN OBJECTHANDLE g_pPreallocatedOutOfMemoryException;
EXTERN OBJECTHANDLE g_pPreallocatedStackOverflowException;
EXTERN OBJECTHANDLE g_pPreallocatedExecutionEngineException;
// we use this as a dummy object to indicate free space in the handle tables -- this object is never visible to the world
-EXTERN OBJECTHANDLE g_pPreallocatedSentinelObject;
+EXTERN OBJECTREF g_pPreallocatedSentinelObject;
EXTERN MethodTable* g_pCastHelpers;