<data name="NotSupported_DBNullSerial" xml:space="preserve">
<value>Only one DBNull instance may exist, and calls to DBNull deserialization methods are not allowed.</value>
</data>
- <data name="NotSupported_DelegateMarshalToWrongDomain" xml:space="preserve">
- <value>Delegates cannot be marshaled from native code into a domain other than their home domain.</value>
- </data>
<data name="NotSupported_DelegateSerHolderSerial" xml:space="preserve">
<value>DelegateSerializationHolder objects are designed to represent a delegate during serialization and are not serializable themselves.</value>
</data>
return NULL;
}
- DWORD adIndex = (value >> SBLK_APPDOMAIN_SHIFT) & SBLK_MASK_APPDOMAININDEX;
+ DWORD adIndex = 0;
if ( ((value & BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX) != 0) || adIndex==0)
{
// No AppDomainID information. We'll make use of a heuristic.
#define BIT_SBLK_SPIN_LOCK 0x10000000
#define SBLK_MASK_LOCK_THREADID 0x000003FF // special value of 0 + 1023 thread ids
#define SBLK_MASK_LOCK_RECLEVEL 0x0000FC00 // 64 recursion levels
-#define SBLK_APPDOMAIN_SHIFT 16 // shift right this much to get appdomain index
-#define SBLK_MASK_APPDOMAININDEX 0x000007FF // 2048 appdomain indices
#define SBLK_RECLEVEL_SHIFT 10 // shift right this much to get recursion level
#define BIT_SBLK_IS_HASHCODE 0x04000000
#define MASK_HASHCODE ((1<<HASHCODE_BITS)-1)
COMPlusThrow(kInvalidCastException, W("InvalidCast_DownCastArrayElement"));
OBJECTREF * destData = (OBJECTREF*)(gc.pDest->GetDataPtr()) + i - srcIndex + destIndex;
- SetObjectReference(destData, gc.obj, gc.pDest->GetAppDomain());
+ SetObjectReference(destData, gc.obj);
}
GCPROTECT_END();
gc.obj = pSrcMT->FastBox(&srcPtr);
OBJECTREF * destData = (OBJECTREF*)((gc.dest)->GetDataPtr()) + i;
- SetObjectReference(destData, gc.obj, gc.dest->GetAppDomain());
+ SetObjectReference(destData, gc.obj);
}
GCPROTECT_END();
GCPROTECT_END();
if (thTarget == TypeHandle(g_pObjectClass))
{
// Everything is compatible with Object
- SetObjectReference((OBJECTREF*)target->data,(OBJECTREF)obj,GetAppDomain());
+ SetObjectReference((OBJECTREF*)target->data,(OBJECTREF)obj);
}
else
if (!pTargetMT->IsValueType())
HELPER_METHOD_FRAME_END();
}
- SetObjectReference((OBJECTREF*)target->data,obj,GetAppDomain());
+ SetObjectReference((OBJECTREF*)target->data,obj);
}
else
{
// MethodTable::Box is a cleaner way to copy value class, but it is slower than following code.
//
retVal = OBJECTREFToObject(AllocateObject(pMT));
- CopyValueClass(retVal->GetData(), objRef->GetData(), pMT, retVal->GetAppDomain());
+ CopyValueClass(retVal->GetData(), objRef->GetData(), pMT);
HELPER_METHOD_FRAME_END();
return(retVal);
{
STRINGREF str = StringObject::NewString(argv[i]);
STRINGREF * destData = ((STRINGREF*)(strArray->GetDataPtr())) + i;
- SetObjectReference((OBJECTREF*)destData, (OBJECTREF)str, strArray->GetAppDomain());
+ SetObjectReference((OBJECTREF*)destData, (OBJECTREF)str);
}
delete [] argv;
EX_TRY
{
- AppDomainIterator iter(FALSE);
-
- status = E_INVALIDARG;
- while (iter.Next())
+ if (uniqueID != DefaultADID)
{
- if (iter.GetDomain()->GetId().m_dwId == uniqueID)
- {
- *appDomain = new (nothrow)
- ClrDataAppDomain(this, iter.GetDomain());
- status = *appDomain ? S_OK : E_OUTOFMEMORY;
- break;
- }
+ status = E_INVALIDARG;
+ }
+ else
+ {
+ *appDomain = new (nothrow)
+ ClrDataAppDomain(this, AppDomain::GetCurrentDomain());
+ status = *appDomain ? S_OK : E_OUTOFMEMORY;
}
}
EX_CATCH
if (mask & 1)
{
dac_handle_table *pTable = hTable;
- PTR_AppDomain pDomain = SystemDomain::GetAppDomainAtIndex(ADIndex(pTable->uADIndex));
+ PTR_AppDomain pDomain = AppDomain::GetCurrentDomain();
param.AppDomain = TO_CDADDR(pDomain.GetAddr());
param.Type = handleType;
else
{
AppDomain * pAppDomain = vmAppDomain.GetDacPtr();
- return pAppDomain->GetId().m_dwId;
+ return DefaultADID;
}
}
offsetof(AppDomain, m_sDomainLocalBlock);
appdomainData->pDomainLocalModules = PTR_CDADDR(pAppDomain->m_sDomainLocalBlock.m_pModuleSlots);
- appdomainData->dwId = pAppDomain->GetId().m_dwId;
+ appdomainData->dwId = DefaultADID;
appdomainData->appDomainStage = (DacpAppDomainDataStage)pAppDomain->m_Stage.Load();
if (pAppDomain->IsActive())
{
pSyncBlockData->MonitorHeld = pBlock->m_Monitor.GetMonitorHeldStateVolatile();
pSyncBlockData->Recursion = pBlock->m_Monitor.GetRecursionLevel();
pSyncBlockData->HoldingThread = HOST_CDADDR(pBlock->m_Monitor.GetHoldingThread());
-
- if (pBlock->GetAppDomainIndex().m_dwIndex)
- {
- pSyncBlockData->appDomainPtr = PTR_HOST_TO_TADDR(
- SystemDomain::TestGetAppDomainAtIndex(pBlock->GetAppDomainIndex()));
- }
+ pSyncBlockData->appDomainPtr = PTR_HOST_TO_TADDR(AppDomain::GetCurrentDomain());
// TODO: Microsoft, implement the wait list
pSyncBlockData->AdditionalThreadCount = 0;
DAC_ENTER_SUB(m_dac);
- EX_TRY
- {
- *id = m_appDomain->GetId().m_dwId;
- status = S_OK;
- }
- EX_CATCH
- {
- if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status))
- {
- EX_RETHROW;
- }
- }
- EX_END_CATCH(SwallowAllExceptions)
+ *id = DefaultADID;
+ status = S_OK;
DAC_LEAVE();
return status;
#include "stdafx.h"
#include <daccess.h>
-// This header include will need to be rmeoved as part of GitHub#12170.
-// The only reason it's here now is that this file references the GC-private
-// variable g_HandleTableMap.
-#include "../../gc/objecthandle.h"
#include "../../vm/virtualcallstub.h"
#include "../../vm/win32threadpool.h"
#include "../../vm/hillclimbing.h"
#include "../../vm/gcenv.h"
#include "../../vm/ecall.h"
#include "../../vm/rcwwalker.h"
+// This header include will need to be rmeoved as part of GitHub#12170.
+// The only reason it's here now is that this file references the GC-private
+// variable g_HandleTableMap.
+#include "../../gc/objecthandle.h"
#ifdef DEBUGGING_SUPPORTED
// AppDomain ID which is safe to use after the AD is unloaded. It's only safe to
// use the DebuggerModule* after we've verified the ADID is still valid (i.e. by entering that domain).
m_debuggerModule = g_pDebugger->LookupOrCreateModule(pEvalInfo->vmDomainFile);
-
- if (m_debuggerModule == NULL)
- {
- // We have no associated code.
- _ASSERTE((m_evalType == DB_IPCE_FET_NEW_STRING) || (m_evalType == DB_IPCE_FET_NEW_ARRAY));
-
- // We'll just do the creation in whatever domain the thread is already in.
- // It's conceivable that we might want to allow the caller to specify a specific domain, but
- // ICorDebug provides the debugger with no was to specify the domain.
- m_appDomainId = m_thread->GetDomain()->GetId();
- }
- else
- {
- m_appDomainId = m_debuggerModule->GetAppDomain()->GetId();
- }
-
m_funcEvalKey = pEvalInfo->funcEvalKey;
m_argCount = pEvalInfo->argCount;
m_targetCodeAddr = NULL;
return;
}
- STRESS_LOG2(LF_CORDB, LL_INFO10000, "D::SCADE: AppDomain creation:%#08x, %#08x\n",
- pRuntimeAppDomain, pRuntimeAppDomain->GetId().m_dwId);
+ STRESS_LOG1(LF_CORDB, LL_INFO10000, "D::SCADE: AppDomain creation:%#08x\n",
+ pRuntimeAppDomain);
LOG((LF_CORDB, LL_INFO100, "D::EAD: Exit AppDomain 0x%08x.\n",
pRuntimeAppDomain));
- STRESS_LOG3(LF_CORDB, LL_INFO10000, "D::EAD: AppDomain exit:%#08x, %#08x, %#08x\n",
- pRuntimeAppDomain, pRuntimeAppDomain->GetId().m_dwId, CORDebuggerAttached());
+ STRESS_LOG2(LF_CORDB, LL_INFO10000, "D::EAD: AppDomain exit:%#08x, %#08x\n",
+ pRuntimeAppDomain, CORDebuggerAttached());
Thread *thread = g_pEEInterface->GetThread();
// Prevent other Runtime threads from handling events.
//
AppDomain *pDomain = pThread->GetDomain();
AppDomain *pResultDomain = ((pDE->m_debuggerModule == NULL) ? pDomain : pDE->m_debuggerModule->GetAppDomain());
- _ASSERTE( pResultDomain->GetId() == pDE->m_appDomainId );
// Send a func eval complete event to the Right Side.
DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
if(fValid)
{
// Get the appdomain
- IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager();
- ADIndex appDomainIndex = ADIndex((DWORD)(SIZE_T)(mgr->GetHandleContext(objectHandle)));
- pAppDomain = SystemDomain::GetAppDomainAtIndex(appDomainIndex);
+ pAppDomain = AppDomain::GetCurrentDomain();
_ASSERTE(pAppDomain != NULL);
}
HRESULT hr = S_OK;
LPCWSTR szName = NULL;
- LOG((LF_CORDB, LL_INFO100, "D::AADTIPC: Executing AADTIPC for AppDomain 0x%08x (0x%x).\n",
- pAppDomain,
- pAppDomain->GetId().m_dwId));
+ LOG((LF_CORDB, LL_INFO100, "D::AADTIPC: Executing AADTIPC for AppDomain 0x%08x.\n",
+ pAppDomain));
- STRESS_LOG2(LF_CORDB, LL_INFO10000, "D::AADTIPC: AddAppDomainToIPC:%#08x, %#08x\n",
- pAppDomain, pAppDomain->GetId().m_dwId);
+ STRESS_LOG1(LF_CORDB, LL_INFO10000, "D::AADTIPC: AddAppDomainToIPC:%#08x\n",
+ pAppDomain);
goto LErrExit;
}
- // copy the ID
- pAppDomainInfo->m_id = pAppDomain->GetId().m_dwId;
-
// Now set the AppDomainName.
/*
HRESULT hr = E_FAIL;
- LOG((LF_CORDB, LL_INFO100, "D::RADFIPC: Executing RADFIPC for AppDomain 0x%08x (0x%x).\n",
- pAppDomain,
- pAppDomain->GetId().m_dwId));
+ LOG((LF_CORDB, LL_INFO100, "D::RADFIPC: Executing RADFIPC for AppDomain 0x%08x.\n",
+ pAppDomain));
// if none of the slots are occupied, then simply return.
if (m_pAppDomainCB->m_iNumOfUsedSlots == 0)
while (pADInfo)
{
- STRESS_LOG3(LF_CORDB, LL_INFO100, "Iterating over domain %#08x AD:%#08x %ls\n", pADInfo->m_pAppDomain->GetId().m_dwId, pADInfo->m_pAppDomain, pADInfo->m_szAppDomainName);
+ STRESS_LOG2(LF_CORDB, LL_INFO100, "Iterating over domain AD:%#08x %ls\n", pADInfo->m_pAppDomain, pADInfo->m_szAppDomainName);
AppDomain::AssemblyIterator i;
i = pADInfo->m_pAppDomain->IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoaded | kIncludeLoading | kIncludeExecution));
OBJECTREF *dst = (OBJECTREF*)objectRefAddress;
OBJECTREF src = *((OBJECTREF*)&newReference);
- SetObjectReferenceUnchecked(dst, src);
+ SetObjectReference(dst, src);
}
else
{
return CORDBG_E_CLASS_NOT_LOADED;
// Update the value class.
- CopyValueClassUnchecked(oldData, newData, th.GetMethodTable());
+ CopyValueClass(oldData, newData, th.GetMethodTable());
// Free the buffer that is holding the new data. This is a buffer that was created in response to a GET_BUFFER
// message, so we release it with ReleaseRemoteBuffer.
DebuggerIPCE_FuncEvalType m_evalType;
mdMethodDef m_methodToken;
mdTypeDef m_classToken;
- ADID m_appDomainId; // Safe even if AD unloaded
PTR_DebuggerModule m_debuggerModule; // Only valid if AD is still around
RSPTR_CORDBEVAL m_funcEvalKey;
bool m_successful; // Did the eval complete successfully
if (size <= sizeof(ARG_SLOT))
{
// Its not ByRef, so we need to copy the value class onto the ARG_SLOT.
- CopyValueClassUnchecked(ArgSlotEndianessFixup(pArgument, sizeof(LPVOID)), pData, o1->GetMethodTable());
+ CopyValueClass(ArgSlotEndianessFixup(pArgument, sizeof(LPVOID)), pData, o1->GetMethodTable());
}
else
{
// box the object
CopyValueClass(retObject->GetData(),
pRetBuff,
- RetValueType.GetMethodTable(),
- retObject->GetAppDomain());
+ RetValueType.GetMethodTable());
}
else
{
// box the primitive returned, retObject is a true nullable for nullabes, It will be Normalized later
CopyValueClass(retObject->GetData(),
pDE->m_result,
- RetValueType.GetMethodTable(),
- retObject->GetAppDomain());
+ RetValueType.GetMethodTable());
}
pDE->m_result[0] = ObjToArgSlot(retObject);
// invalid due to an AD unload.
// All normal func evals should have an AppDomain specified.
//
- _ASSERTE( pDE->m_appDomainId.m_dwId != 0 );
- ENTER_DOMAIN_ID( pDE->m_appDomainId );
// Wrap everything in a EX_TRY so we catch any exceptions that could be thrown.
// Note that we don't let any thrown exceptions cross the AppDomain boundary because we don't
// the funceval. If a ThreadAbort occurred other than for a funcEval abort, we'll re-throw it manually.
EX_END_CATCH(SwallowAllExceptions);
- // Restore context
- END_DOMAIN_TRANSITION;
-
protectValueClassFrame.Pop();
CleanUpTemporaryVariables(protectValueClassFrame.GetValueClassInfoList());
return;
}
- // The method may be in a different AD than the thread.
- // The RS already verified that all of the arguments are in the same appdomain as the function
- // (because we can't verify it here).
- // Note that this is exception safe, so we are guarenteed to be in the correct AppDomain when
- // we leave this method.
- // Before this, we can't safely use the DebuggerModule* since the domain may have been unloaded.
- ENTER_DOMAIN_ID( pDE->m_appDomainId );
-
OBJECTREF newObj = NULL;
GCPROTECT_BEGIN(newObj);
EX_END_CATCH(SwallowAllExceptions);
GCPROTECT_END();
-
- //
- // Restore context
- //
- END_DOMAIN_TRANSITION;
-
}
//
// All pointers are for the left side, and we do not own any of the memory
struct AppDomainInfo
{
- ULONG m_id; // unique identifier
+ DWORD m_id = 0; // UNUSED, only present to maintain the shape of this structure
int m_iNameLengthInBytes;
LPCWSTR m_szAppDomainName;
AppDomain *m_pAppDomain; // only used by LS
// Define function pointer DEFINETOKEN_CALLBACK
typedef void (*DEFINETOKEN_CALLBACK)(LPVOID pModuleContext, CORINFO_MODULE_HANDLE moduleHandle, DWORD index, mdTypeRef* token);
-typedef HRESULT (*CROSS_DOMAIN_CALLBACK)(LPVOID pArgs);
-
class ICorCompileInfo
{
public:
BOOL fForceInstrument
) = 0;
- // calls pfnCallback in the specified domain
- virtual HRESULT MakeCrossDomainCallback(
- ICorCompilationDomain* pDomain,
- CROSS_DOMAIN_CALLBACK pfnCallback,
- LPVOID pArgs
- ) = 0;
-
// Destroys a compilation domain
virtual HRESULT DestroyDomain(
ICorCompilationDomain *pDomain
DEFINE_DACVAR(ULONG, PTR_AppDomain, AppDomain__m_pTheAppDomain, AppDomain::m_pTheAppDomain)
DEFINE_DACVAR(ULONG, PTR_SystemDomain, SystemDomain__m_pSystemDomain, SystemDomain::m_pSystemDomain)
-DEFINE_DACVAR(ULONG, ArrayListStatic, SystemDomain__m_appDomainIndexList, SystemDomain::m_appDomainIndexList)
DEFINE_DACVAR(ULONG, BOOL, SystemDomain__s_fForceDebug, SystemDomain::s_fForceDebug)
DEFINE_DACVAR(ULONG, BOOL, SystemDomain__s_fForceProfiling, SystemDomain::s_fForceProfiling)
DEFINE_DACVAR(ULONG, BOOL, SystemDomain__s_fForceInstrument, SystemDomain::s_fForceInstrument)
void ComputeAssemblyDependencies(CORINFO_ASSEMBLY_HANDLE hAssembly);
void CreatePdb(BSTR pAssemblyPathOrName, BSTR pNativeImagePath, BSTR pPdbPath, BOOL pdbLines, BSTR pManagedPdbSearchPath);
- void CreatePdbInCurrentDomain(BSTR pAssemblyPathOrName, BSTR pNativeImagePath, BSTR pPdbPath, BOOL pdbLines, BSTR pManagedPdbSearchPath);
void DefineOutputAssembly(SString& strAssemblyName, ULONG * pHashAlgId);
virtual void doCallback() = NULL;
};
- static HRESULT __stdcall GenericDomainCallback(LPVOID pvArgs);
- void InvokeDomainCallback(DomainCallback *callback);
-
void CompileInCurrentDomain(__in LPCWSTR path, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig);
void ComputeDependenciesInCurrentDomain(LPCWSTR pAssemblyName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig);
void CreateDependenciesLookupDomainInCurrentDomain();
MIN_SIZE equ 28h
JIT_NEW equ ?JIT_New@@YAPEAVObject@@PEAUCORINFO_CLASS_STRUCT_@@@Z
-Object__DEBUG_SetAppDomain equ ?DEBUG_SetAppDomain@Object@@QEAAXPEAVAppDomain@@@Z
CopyValueClassUnchecked equ ?CopyValueClassUnchecked@@YAXPEAX0PEAVMethodTable@@@Z
JIT_Box equ ?JIT_Box@@YAPEAVObject@@PEAUCORINFO_CLASS_STRUCT_@@PEAX@Z
g_pStringClass equ ?g_pStringClass@@3PEAVMethodTable@@EA
ASMCONSTANTS_C_ASSERT(OFFSETOF__UMEntryThunk__m_pUMThunkMarshInfo
== offsetof(UMEntryThunk, m_pUMThunkMarshInfo));
-#define OFFSETOF__UMEntryThunk__m_dwDomainId 0x20
-ASMCONSTANTS_C_ASSERT(OFFSETOF__UMEntryThunk__m_dwDomainId
- == offsetof(UMEntryThunk, m_dwDomainId));
-
#define OFFSETOF__UMThunkMarshInfo__m_pILStub 0x00
ASMCONSTANTS_C_ASSERT(OFFSETOF__UMThunkMarshInfo__m_pILStub
== offsetof(UMThunkMarshInfo, m_pILStub));
ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_State
== offsetof(Thread, m_State));
-#define OFFSETOF__Thread__m_pDomain 0x18
-ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_pDomain
- == offsetof(Thread, m_pDomain));
-
#define OFFSETOF__Thread__m_dwLockCount 0x20
ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_dwLockCount
== offsetof(Thread, m_dwLockCount));
ASMCONSTANTS_C_ASSERT(SIZEOF__InterfaceInfo_t
== sizeof(InterfaceInfo_t));
-#define OFFSETOF__AppDomain__m_dwId 0x8
-ASMCONSTANTS_C_ASSERT(OFFSETOF__AppDomain__m_dwId
- == offsetof(AppDomain, m_dwId));
-
-#define OFFSETOF__AppDomain__m_sDomainLocalBlock DBG_FRE(0x10, 0x10)
-ASMCONSTANTS_C_ASSERT(OFFSETOF__AppDomain__m_sDomainLocalBlock
- == offsetof(AppDomain, m_sDomainLocalBlock));
-
#define OFFSETOF__DomainLocalBlock__m_pModuleSlots 0x8
ASMCONSTANTS_C_ASSERT(OFFSETOF__DomainLocalBlock__m_pModuleSlots
== offsetof(DomainLocalBlock, m_pModuleSlots));
mov METHODDESC_REGISTER, [rbp - UMThunkStubAMD64_RBP_OFFSET + UMThunkStubAMD64_METHODDESC_OFFSET]
-#if _DEBUG
- mov rax, [r12 + OFFSETOF__Thread__m_pDomain]
- mov eax, [rax + OFFSETOF__AppDomain__m_dwId]
-
- mov r11d, [METHODDESC_REGISTER + OFFSETOF__UMEntryThunk__m_dwDomainId]
-
- cmp rax, r11
- jne LOCAL_LABEL(WrongAppDomain)
-#endif
-
mov r11, [METHODDESC_REGISTER + OFFSETOF__UMEntryThunk__m_pUMThunkMarshInfo]
mov eax, [r11 + OFFSETOF__UMThunkMarshInfo__m_cbActualArgSize] // stack_args
test rax, rax // stack_args
jmp LOCAL_LABEL(UMThunkStub_ArgumentsSetup)
-#if _DEBUG
-LOCAL_LABEL(WrongAppDomain):
- int3
-#endif
-
NESTED_END UMThunkStub, _TEXT
SPTR_IMPL(AppDomain, AppDomain, m_pTheAppDomain);
SPTR_IMPL(SystemDomain, SystemDomain, m_pSystemDomain);
-SVAL_IMPL(ArrayListStatic, SystemDomain, m_appDomainIndexList);
SVAL_IMPL(BOOL, SystemDomain, s_fForceDebug);
SVAL_IMPL(BOOL, SystemDomain, s_fForceProfiling);
SVAL_IMPL(BOOL, SystemDomain, s_fForceInstrument);
ULONG SystemDomain::s_dNumAppDomains = 0;
-ArrayListStatic SystemDomain::m_appDomainIdList;
-
DWORD SystemDomain::m_dwLowestFreeIndex = 0;
ClassLoader::LoadArrayTypeThrowing(g_pObjectClass),
(INT32 *)(&Size),
1,
- TRUE
- DEBUG_ARG(TRUE));
+ TRUE);
}
- array->SetAppDomain(pAD);
-
HandleArrayObj = (PTRARRAYREF)array;
}
// Add the released handles to the list of available handles.
for (DWORD i = 0; i < nReleased; i++)
{
- SetObjectReference(&pObjRef[i], pPreallocatedSentinalObject, NULL);
+ SetObjectReference(&pObjRef[i], pPreallocatedSentinalObject);
}
m_cEmbeddedFree += nReleased;
#undef LOADERHEAP_PROFILE_COUNTER
-#ifndef CROSSGEN_COMPILE
-//*****************************************************************************
-void BaseDomain::Terminate()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- m_crstLoaderAllocatorReferences.Destroy();
- m_DomainCrst.Destroy();
- m_DomainCacheCrst.Destroy();
- m_DomainLocalBlockCrst.Destroy();
- m_InteropDataCrst.Destroy();
-
- JitListLockEntry* pJitElement;
- ListLockEntry* pElement;
-
- // All the threads that are in this domain had better be stopped by this
- // point.
- //
- // We might be jitting or running a .cctor so we need to empty that queue.
- pJitElement = m_JITLock.Pop(TRUE);
- while (pJitElement)
- {
-#ifdef STRICT_JITLOCK_ENTRY_LEAK_DETECTION
- _ASSERTE ((m_JITLock.m_pHead->m_dwRefCount == 1
- && m_JITLock.m_pHead->m_hrResultCode == E_FAIL) ||
- dbg_fDrasticShutdown || g_fInControlC);
-#endif // STRICT_JITLOCK_ENTRY_LEAK_DETECTION
- delete(pJitElement);
- pJitElement = m_JITLock.Pop(TRUE);
-
- }
- m_JITLock.Destroy();
-
- pElement = m_ClassInitLock.Pop(TRUE);
- while (pElement)
- {
-#ifdef STRICT_CLSINITLOCK_ENTRY_LEAK_DETECTION
- _ASSERTE (dbg_fDrasticShutdown || g_fInControlC);
-#endif
- delete(pElement);
- pElement = m_ClassInitLock.Pop(TRUE);
- }
- m_ClassInitLock.Destroy();
-
- FileLoadLock* pFileElement;
- pFileElement = (FileLoadLock*) m_FileLoadLock.Pop(TRUE);
- while (pFileElement)
- {
-#ifdef STRICT_CLSINITLOCK_ENTRY_LEAK_DETECTION
- _ASSERTE (dbg_fDrasticShutdown || g_fInControlC);
-#endif
- pFileElement->Release();
- pFileElement = (FileLoadLock*) m_FileLoadLock.Pop(TRUE);
- }
- m_FileLoadLock.Destroy();
-
- pElement = m_ILStubGenLock.Pop(TRUE);
- while (pElement)
- {
-#ifdef STRICT_JITLOCK_ENTRY_LEAK_DETECTION
- _ASSERTE ((m_ILStubGenLock.m_pHead->m_dwRefCount == 1
- && m_ILStubGenLock.m_pHead->m_hrResultCode == E_FAIL) ||
- dbg_fDrasticShutdown || g_fInControlC);
-#endif // STRICT_JITLOCK_ENTRY_LEAK_DETECTION
- delete(pElement);
- pElement = m_ILStubGenLock.Pop(TRUE);
- }
- m_ILStubGenLock.Destroy();
-
- m_LargeHeapHandleTableCrst.Destroy();
-
- if (m_pLargeHeapHandleTable != NULL)
- {
- delete m_pLargeHeapHandleTable;
- m_pLargeHeapHandleTable = NULL;
- }
-
- if (!IsAppDomain())
- {
- // Kind of a workaround - during unloading, we need to have an EE halt
- // around deleting this stuff. So it gets deleted in AppDomain::Terminate()
- // for those things (because there is a convenient place there.)
- GetLoaderAllocator()->CleanupStringLiteralMap();
- }
-
-#ifdef FEATURE_COMINTEROP
- if (m_pMngStdInterfacesInfo)
- {
- delete m_pMngStdInterfacesInfo;
- m_pMngStdInterfacesInfo = NULL;
- }
-
- if (m_pWinRtBinder != NULL)
- {
- m_pWinRtBinder->Release();
- }
-#endif // FEATURE_COMINTEROP
-
- ClearFusionContext();
-
- m_dwSizedRefHandles = 0;
-}
-#endif // CROSSGEN_COMPILE
-
void BaseDomain::InitVSD()
{
STANDARD_VM_CONTRACT;
}
}
-#ifdef FEATURE_PREJIT
-void AppDomain::DeleteNativeCodeRanges()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_PREEMPTIVE;
- FORBID_FAULT;
- }
- CONTRACTL_END;
-
- // Fast path to skip using the assembly iterator when the appdomain has not yet completely been initialized
- // and yet we are destroying it. (This is the case if we OOM during AppDomain creation.)
- if (m_Assemblies.IsEmpty())
- return;
-
- // Shutdown assemblies
- AssemblyIterator i = IterateAssembliesEx( (AssemblyIterationFlags)(kIncludeLoaded | kIncludeLoading | kIncludeExecution | kIncludeFailedToLoad) );
- CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
-
- while (i.Next(pDomainAssembly.This()))
- {
- Assembly * assembly = pDomainAssembly->m_pAssembly;
- if ((assembly != NULL))
- assembly->DeleteNativeCodeRanges();
- }
-}
-#endif
-
-void AppDomain::ShutdownAssemblies()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- // Fast path to skip using the assembly iterator when the appdomain has not yet completely been initialized
- // and yet we are destroying it. (This is the case if we OOM during AppDomain creation.)
- if (m_Assemblies.IsEmpty())
- return;
-
- // Shutdown assemblies
- // has two stages because Terminate needs info from the Assembly's dependencies
-
- // Stage 1: call code:Assembly::Terminate
- AssemblyIterator i = IterateAssembliesEx((AssemblyIterationFlags)(
- kIncludeLoaded | kIncludeLoading | kIncludeExecution | kIncludeFailedToLoad | kIncludeCollected));
- DomainAssembly * pDomainAssembly = NULL;
-
- while (i.Next_UnsafeNoAddRef(&pDomainAssembly))
- {
- // Note: cannot use DomainAssembly::GetAssembly() here as it asserts that the assembly has been
- // loaded to at least the FILE_LOAD_ALLOCATE level. Since domain shutdown can take place
- // asynchronously this property cannot be guaranteed. Access the m_pAssembly field directly instead.
- Assembly * assembly = pDomainAssembly->m_pAssembly;
- if (assembly)
- assembly->Terminate();
- }
-
- // Stage 2: Clear the list of assemblies
- i = IterateAssembliesEx((AssemblyIterationFlags)(
- kIncludeLoaded | kIncludeLoading | kIncludeExecution | kIncludeFailedToLoad | kIncludeCollected));
- while (i.Next_UnsafeNoAddRef(&pDomainAssembly))
- {
- // We are in shutdown path, no one else can get to the list anymore
- delete pDomainAssembly;
- }
- m_Assemblies.Clear(this);
-
- // Stage 2: Clear the loader allocators registered for deletion from code:Assembly:Terminate calls in
- // stage 1
- // Note: It is not clear to me why we cannot delete the loader allocator from within
- // code:DomainAssembly::~DomainAssembly
- ShutdownFreeLoaderAllocators(FALSE);
-} // AppDomain::ShutdownAssemblies
-
-void AppDomain::ShutdownFreeLoaderAllocators(BOOL bFromManagedCode)
+void AppDomain::ShutdownFreeLoaderAllocators()
{
// If we're called from managed code (i.e. the finalizer thread) we take a lock in
// LoaderAllocator::CleanupFailedTypeInit, which may throw. Otherwise we're called
CONTRACTL
{
GC_TRIGGERS;
- if (bFromManagedCode) THROWS; else NOTHROW;
+ THROWS;
MODE_ANY;
CAN_TAKE_LOCK;
}
// Remove next loader allocator from the list
m_pDelayedLoaderAllocatorUnloadList = m_pDelayedLoaderAllocatorUnloadList->m_pLoaderAllocatorDestroyNext;
- if (bFromManagedCode)
- {
- // For loader allocator finalization, we need to be careful about cleaning up per-appdomain allocations
- // and synchronizing with GC using delay unload list. We need to wait for next Gen2 GC to finish to ensure
- // that GC heap does not have any references to the MethodTables being unloaded.
+ // For loader allocator finalization, we need to be careful about cleaning up per-appdomain allocations
+ // and synchronizing with GC using delay unload list. We need to wait for next Gen2 GC to finish to ensure
+ // that GC heap does not have any references to the MethodTables being unloaded.
- pCurrentLoaderAllocator->CleanupFailedTypeInit();
+ pCurrentLoaderAllocator->CleanupFailedTypeInit();
- pCurrentLoaderAllocator->CleanupHandles();
+ pCurrentLoaderAllocator->CleanupHandles();
- GCX_COOP();
- SystemDomain::System()->AddToDelayedUnloadList(pCurrentLoaderAllocator);
- }
- else
- {
- // For appdomain unload, delete the loader allocator right away
- delete pCurrentLoaderAllocator;
- }
+ GCX_COOP();
+ SystemDomain::System()->AddToDelayedUnloadList(pCurrentLoaderAllocator);
}
} // AppDomain::ShutdownFreeLoaderAllocators
}
}
-void AppDomain::ShutdownNativeDllSearchDirectories()
-{
- LIMITED_METHOD_CONTRACT;
- // Shutdown assemblies
- PathIterator i = IterateNativeDllSearchDirectories();
-
- while (i.Next())
- {
- delete i.GetPath();
- }
-
- m_NativeDllSearchDirectories.Clear();
-}
-
void AppDomain::ReleaseFiles()
{
STANDARD_VM_CONTRACT;
PerAppDomainTPCountList::InitAppDomainIndexList();
#endif // CROSSGEN_COMPILE
- m_appDomainIndexList.Init();
- m_appDomainIdList.Init();
-
m_SystemDomainCrst.Init(CrstSystemDomain, (CrstFlags)(CRST_REENTRANCY | CRST_TAKEN_DURING_SHUTDOWN));
m_DelayedUnloadCrst.Init(CrstSystemDomainDelayedUnloadList, CRST_UNSAFE_COOPGC);
i.GetDomain()->Stop();
}
-
-void SystemDomain::Terminate() // bNotifyProfiler is ignored
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- // This ignores the refences and terminates the appdomains
- AppDomainIterator i(FALSE);
-
- while (i.Next())
- {
- delete i.GetDomain();
- // Keep the iterator from Releasing the current domain
- i.m_pCurrent = NULL;
- }
-
- if (m_pSystemFile != NULL) {
- m_pSystemFile->Release();
- m_pSystemFile = NULL;
- }
-
- m_pSystemAssembly = NULL;
-
- if (m_pGlobalStringLiteralMap) {
- delete m_pGlobalStringLiteralMap;
- m_pGlobalStringLiteralMap = NULL;
- }
-
- BaseDomain::Terminate();
-
-#ifdef FEATURE_COMINTEROP
- if (g_pRCWCleanupList != NULL)
- delete g_pRCWCleanupList;
-#endif // FEATURE_COMINTEROP
- m_GlobalAllocator.Terminate();
-}
-
-
void SystemDomain::PreallocateSpecialObjects()
{
CONTRACTL
SystemDomain* sysDomain = SystemDomain::System();
if (sysDomain)
{
- DWORD i;
- DWORD count = (DWORD) m_appDomainIdList.GetCount();
- for (i = 0 ; i < count ; i++)
+ AppDomain* pAppDomain = ::GetAppDomain();
+ if (pAppDomain && pAppDomain->IsActive())
{
- AppDomain* pAppDomain = (AppDomain *)m_appDomainIdList.Get(i);
- if (pAppDomain && pAppDomain->IsActive())
- {
#ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
- if (g_fEnableARM)
- {
- sc->pCurrentDomain = pAppDomain;
- }
-#endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
- pAppDomain->EnumStaticGCRefs(fn, sc);
+ if (g_fEnableARM)
+ {
+ sc->pCurrentDomain = pAppDomain;
}
+#endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
+ pAppDomain->EnumStaticGCRefs(fn, sc);
}
}
SystemDomain* sysDomain = SystemDomain::System();
if (sysDomain)
{
- DWORD i;
- DWORD count = (DWORD) m_appDomainIdList.GetCount();
- for (i = 0 ; i < count ; i++)
+ AppDomain* pAppDomain = ::GetAppDomain();
+ if (pAppDomain && pAppDomain->IsUserActive())
{
- AppDomain* pAppDomain = (AppDomain *)m_appDomainIdList.Get(i);
- if (pAppDomain && pAppDomain->IsUserActive())
- {
- pAppDomain->ResetSurvivedBytes();
- }
+ pAppDomain->ResetSurvivedBytes();
}
}
ULONGLONG ullTotalADSurvived = 0;
if (sysDomain)
{
- DWORD i;
- DWORD count = (DWORD) m_appDomainIdList.GetCount();
- for (i = 0 ; i < count ; i++)
+ AppDomain* pAppDomain = ::GetAppDomain();
+ if (pAppDomain && pAppDomain->IsUserActive())
{
- AppDomain* pAppDomain = (AppDomain *)m_appDomainIdList.Get(i);
- if (pAppDomain && pAppDomain->IsUserActive())
- {
- ULONGLONG ullSurvived = pAppDomain->GetSurvivedBytes();
- ullTotalADSurvived += ullSurvived;
- }
+ ULONGLONG ullSurvived = pAppDomain->GetSurvivedBytes();
+ ullTotalADSurvived += ullSurvived;
}
}
SystemDomain* sysDomain = SystemDomain::System();
if (sysDomain)
{
- DWORD i;
- DWORD count = (DWORD) m_appDomainIdList.GetCount();
- for (i = 0 ; i < count ; i++)
+ AppDomain* pAppDomain = ::GetAppDomain();
+ if (pAppDomain && pAppDomain->IsUserActive())
{
- AppDomain* pAppDomain = (AppDomain *)m_appDomainIdList.Get(i);
- if (pAppDomain && pAppDomain->IsUserActive())
- {
- FireEtwAppDomainMemSurvived((ULONGLONG)pAppDomain, pAppDomain->GetSurvivedBytes(), totalSurvivedBytes, GetClrInstanceId());
- }
+ FireEtwAppDomainMemSurvived((ULONGLONG)pAppDomain, pAppDomain->GetSurvivedBytes(), totalSurvivedBytes, GetClrInstanceId());
}
}
DWORD dwTotalNumSizedRefHandles = 0;
if (sysDomain)
{
- DWORD i;
- DWORD count = (DWORD) m_appDomainIdList.GetCount();
- for (i = 0 ; i < count ; i++)
+ AppDomain* pAppDomain = ::GetAppDomain();
+ if (pAppDomain && pAppDomain->IsActive())
{
- AppDomain* pAppDomain = (AppDomain *)m_appDomainIdList.Get(i);
- if (pAppDomain && pAppDomain->IsActive())
- {
- dwTotalNumSizedRefHandles += pAppDomain->GetNumSizedRefHandles();
- }
+ dwTotalNumSizedRefHandles += pAppDomain->GetNumSizedRefHandles();
}
}
SystemDomain::System()->AddDomain(pDomain);
}
-ADIndex SystemDomain::GetNewAppDomainIndex(AppDomain *pAppDomain)
-{
- STANDARD_VM_CONTRACT;
-
- DWORD count = m_appDomainIndexList.GetCount();
- DWORD i;
-
-#ifdef _DEBUG
- if (count < 2000)
- {
- // So that we can keep AD index inside object header.
- // We do not want to create syncblock unless needed.
- i = count;
- }
- else
- {
-#endif // _DEBUG
- //
- // Look for an unused index. Note that in a checked build,
- // we never reuse indexes - this makes it easier to tell
- // when we are looking at a stale app domain.
- //
-
- i = m_appDomainIndexList.FindElement(m_dwLowestFreeIndex, NULL);
- if (i == (DWORD) ArrayList::NOT_FOUND)
- i = count;
- m_dwLowestFreeIndex = i+1;
-#ifdef _DEBUG
- if (m_dwLowestFreeIndex >= 2000)
- {
- m_dwLowestFreeIndex = 0;
- }
- }
-#endif // _DEBUG
-
- if (i == count)
- IfFailThrow(m_appDomainIndexList.Append(pAppDomain));
- else
- m_appDomainIndexList.Set(i, pAppDomain);
-
- _ASSERTE(i < m_appDomainIndexList.GetCount());
-
- // Note that index 0 means domain agile.
- return ADIndex(i+1);
-}
-
-void SystemDomain::ReleaseAppDomainIndex(ADIndex index)
-{
- WRAPPER_NO_CONTRACT;
- SystemDomain::LockHolder lh;
- // Note that index 0 means domain agile.
- index.m_dwIndex--;
-
- _ASSERTE(m_appDomainIndexList.Get(index.m_dwIndex) != NULL);
-
- m_appDomainIndexList.Set(index.m_dwIndex, NULL);
-
-#ifndef _DEBUG
- if (index.m_dwIndex < m_dwLowestFreeIndex)
- m_dwLowestFreeIndex = index.m_dwIndex;
-#endif // !_DEBUG
-}
-
#endif // !DACCESS_COMPILE
-PTR_AppDomain SystemDomain::GetAppDomainAtIndex(ADIndex index)
-{
- LIMITED_METHOD_CONTRACT;
- SUPPORTS_DAC;
- _ASSERTE(index.m_dwIndex != 0);
-
- PTR_AppDomain pAppDomain = TestGetAppDomainAtIndex(index);
-
- _ASSERTE(pAppDomain || !"Attempt to access unloaded app domain");
-
- return pAppDomain;
-}
-
-PTR_AppDomain SystemDomain::TestGetAppDomainAtIndex(ADIndex index)
-{
- LIMITED_METHOD_CONTRACT;
- SUPPORTS_DAC;
- _ASSERTE(index.m_dwIndex != 0);
- index.m_dwIndex--;
-
-#ifndef DACCESS_COMPILE
- _ASSERTE(index.m_dwIndex < (DWORD)m_appDomainIndexList.GetCount());
- AppDomain *pAppDomain = (AppDomain*) m_appDomainIndexList.Get(index.m_dwIndex);
-#else // DACCESS_COMPILE
- PTR_ArrayListStatic pList = &m_appDomainIndexList;
- AppDomain *pAppDomain = dac_cast<PTR_AppDomain>(pList->Get(index.m_dwIndex));
-#endif // DACCESS_COMPILE
- return PTR_AppDomain(pAppDomain);
-}
-
#ifndef DACCESS_COMPILE
-// See also code:SystemDomain::ReleaseAppDomainId
-ADID SystemDomain::GetNewAppDomainId(AppDomain *pAppDomain)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- INJECT_FAULT(COMPlusThrowOM(););
- }
- CONTRACTL_END;
-
- DWORD i = m_appDomainIdList.GetCount();
-
- IfFailThrow(m_appDomainIdList.Append(pAppDomain));
-
- _ASSERTE(i < m_appDomainIdList.GetCount());
-
- return ADID(i+1);
-}
-
-AppDomain *SystemDomain::GetAppDomainAtId(ADID index)
-{
- CONTRACTL
- {
-#ifdef _DEBUG
- if (!SystemDomain::IsUnderDomainLock() && !IsGCThread()) { MODE_COOPERATIVE;} else { DISABLED(MODE_ANY);}
-#endif
- GC_NOTRIGGER;
- NOTHROW;
- }
- CONTRACTL_END;
-
- if(index.m_dwId == 0)
- return NULL;
- DWORD requestedID = index.m_dwId - 1;
-
- if(requestedID >= (DWORD)m_appDomainIdList.GetCount())
- return NULL;
-
- AppDomain * result = (AppDomain *)m_appDomainIdList.Get(requestedID);
-
-#ifndef CROSSGEN_COMPILE
- // If the current thread can't enter the AppDomain, then don't return it.
- if (!result)
- return NULL;
-#endif // CROSSGEN_COMPILE
-
- return result;
-}
-
-// Releases an appdomain index. Note that today we have code that depends on these
-// indexes not being recycled, so we don't actually shrink m_appDomainIdList, but
-// simply zero out an entry. THus we 'leak' the memory associated the slot in
-// m_appDomainIdList.
-//
-// TODO make this a sparse structure so that we avoid that leak.
-//
-void SystemDomain::ReleaseAppDomainId(ADID index)
-{
- LIMITED_METHOD_CONTRACT;
- index.m_dwId--;
-
- _ASSERTE(index.m_dwId < (DWORD)m_appDomainIdList.GetCount());
-
- m_appDomainIdList.Set(index.m_dwId, NULL);
-}
-
#if defined(FEATURE_COMINTEROP_APARTMENT_SUPPORT) && !defined(CROSSGEN_COMPILE)
Thread::ApartmentState SystemDomain::GetEntryPointThreadAptState(IMDInternalImport* pScope, mdMethodDef mdMethod)
pDomain->Init();
- // need to make this assignment here since we'll be releasing
- // the lock before calling AddDomain. So any other thread
- // grabbing this lock after we release it will find that
- // the COM Domain has already been created
- _ASSERTE (pDomain->GetId().m_dwId == DefaultADID);
-
// allocate a Virtual Call Stub Manager for the default domain
pDomain->InitVSD();
pDomain->m_Stage == AppDomain::STAGE_ACTIVE)
{
pDomain->SetStage(AppDomain::STAGE_OPEN);
- IncrementNumAppDomains(); // Maintain a count of app domains added to the list.
}
}
}
#endif // PROFILING_SUPPORTED
-
-#ifdef _DEBUG
-struct AppDomain::ThreadTrackInfo {
- Thread *pThread;
- CDynArray<Frame *> frameStack;
-};
-#endif // _DEBUG
-
AppDomain::AppDomain()
{
// initialize fields so the appdomain can be safely destructed
m_handleStore = NULL;
- #ifdef _DEBUG
- m_pThreadTrackInfoList = NULL;
- m_TrackSpinLock = 0;
+#ifdef _DEBUG
m_Assemblies.Debug_SetAppDomain(this);
#endif // _DEBUG
- m_dwThreadEnterCount = 0;
- m_dwThreadsStillInAppDomain = (ULONG)-1;
-
#ifdef FEATURE_COMINTEROP
m_pRefDispIDCache = NULL;
m_hndMissing = NULL;
if (GetTPIndex().m_dwIndex != 0)
PerAppDomainTPCountList::ResetAppDomainIndex(GetTPIndex());
- if (m_dwId.m_dwId!=0)
- SystemDomain::ReleaseAppDomainId(m_dwId);
-
m_AssemblyCache.Clear();
- if(!g_fEEInit)
- Terminate();
-
-
-
-
#ifdef FEATURE_COMINTEROP
if (m_pNameToTypeMap != nullptr)
{
}
#endif //FEATURE_COMINTEROP
-#ifdef _DEBUG
- // If we were tracking thread AD transitions, cleanup the list on shutdown
- if (m_pThreadTrackInfoList)
- {
- while (m_pThreadTrackInfoList->Count() > 0)
- {
- // Get the very last element
- ThreadTrackInfo *pElem = *(m_pThreadTrackInfoList->Get(m_pThreadTrackInfoList->Count() - 1));
- _ASSERTE(pElem);
-
- // Free the memory
- delete pElem;
-
- // Remove pointer entry from the list
- m_pThreadTrackInfoList->Delete(m_pThreadTrackInfoList->Count() - 1);
- }
-
- // Now delete the list itself
- delete m_pThreadTrackInfoList;
- m_pThreadTrackInfoList = NULL;
- }
-#endif // _DEBUG
-
#endif // CROSSGEN_COMPILE
}
INDEBUG(| CRST_DEBUG_ONLY_CHECK_FORBID_SUSPEND_THREAD)));
m_crstHostAssemblyMapAdd.Init(CrstHostAssemblyMapAdd);
- m_dwId = SystemDomain::GetNewAppDomainId(this);
-
#ifndef CROSSGEN_COMPILE
//Allocate the threadpool entry before the appdomain id list. Otherwise,
//the thread pool list will be out of sync if insertion of id in
m_tpIndex = PerAppDomainTPCountList::AddNewTPIndex();
#endif // CROSSGEN_COMPILE
- m_dwIndex = SystemDomain::GetNewAppDomainIndex(this);
-
-#ifndef CROSSGEN_COMPILE
- PerAppDomainTPCountList::SetAppDomainId(m_tpIndex, m_dwId);
-#endif
-
BaseDomain::Init();
// Set up the binding caches
m_ullLastEtwAllocBytes = 0;
#endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
- // Default domain reuses the handletablemap that was created during EEStartup since
- // default domain cannot be unloaded.
- if (GetId().m_dwId == DefaultADID)
- {
- m_handleStore = GCHandleUtilities::GetGCHandleManager()->GetGlobalHandleStore();
- }
- else
- {
- m_handleStore = GCHandleUtilities::GetGCHandleManager()->CreateHandleStore((void*)(uintptr_t)m_dwIndex.m_dwIndex);
- }
+ // Default domain reuses the handletablemap that was created during EEStartup
+ m_handleStore = GCHandleUtilities::GetGCHandleManager()->GetGlobalHandleStore();
if (!m_handleStore)
{
#ifndef CROSSGEN_COMPILE
#ifdef FEATURE_TIERED_COMPILATION
- m_tieredCompilationManager.Init(GetId());
+ m_tieredCompilationManager.Init();
#endif
#endif // CROSSGEN_COMPILE
} // AppDomain::Init
#endif // DEBUGGING_SUPPORTED
}
-void AppDomain::Terminate()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- GCX_PREEMP();
-
- _ASSERTE(m_dwThreadEnterCount == 0 || IsDefaultDomain());
-
-#ifdef FEATURE_COMINTEROP
- if (m_pRCWCache)
- {
- delete m_pRCWCache;
- m_pRCWCache = NULL;
- }
-
- if (m_pRCWRefCache)
- {
- delete m_pRCWRefCache;
- m_pRCWRefCache = NULL;
- }
-#endif // FEATURE_COMINTEROP
-
- if (!IsAtProcessExit())
- {
- // if we're not shutting down everything then clean up the string literals associated
- // with this appdomain -- note that is no longer needs to happen while suspended
- // because the appropriate locks are taken in the GlobalStringLiteralMap
- // this is important as this locks have a higher lock number than does the
- // thread-store lock which is taken when we suspend.
- GetLoaderAllocator()->CleanupStringLiteralMap();
-
- // Suspend the EE to do some clean up that can only occur
- // while no threads are running.
- GCX_COOP (); // SuspendEE may require current thread to be in Coop mode
- ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_FOR_APPDOMAIN_SHUTDOWN);
- }
-
- // Note that this must be performed before restarting the EE. It will clean
- // the cache and prevent others from using stale cache entries.
- //@TODO: Would be nice to get this back to BaseDomain, but need larger fix for that.
- // NOTE: Must have the runtime suspended to unlink managers
- // NOTE: May be NULL due to OOM during initialization. Can skip in that case.
- GetLoaderAllocator()->UninitVirtualCallStubManager();
- MethodTable::ClearMethodDataCache();
- ClearJitGenericHandleCache(this);
-
- // @TODO s_TPMethodTableCrst prevents us from from keeping the whole
- // assembly shutdown logic here. See if we can do better in the next milestone
-#ifdef FEATURE_PREJIT
- DeleteNativeCodeRanges();
-#endif
-
- if (!IsAtProcessExit())
- {
- // Resume the EE.
- ThreadSuspend::RestartEE(FALSE, TRUE);
- }
-
- ShutdownAssemblies();
- ShutdownNativeDllSearchDirectories();
-
- if (m_pRefClassFactHash)
- {
- m_pRefClassFactHash->Destroy();
- // storage for m_pRefClassFactHash itself is allocated on the loader heap
- }
-
-#ifdef FEATURE_TYPEEQUIVALENCE
- m_TypeEquivalenceCrst.Destroy();
-#endif
-
- m_ReflectionCrst.Destroy();
- m_RefClassFactCrst.Destroy();
-
- BaseDomain::Terminate();
-
- if (m_handleStore)
- {
- GCHandleUtilities::GetGCHandleManager()->DestroyHandleStore(m_handleStore);
- m_handleStore = NULL;
- }
-
-#ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
- if (m_pullAllocBytes)
- {
- delete [] m_pullAllocBytes;
- }
- if (m_pullSurvivedBytes)
- {
- delete [] m_pullSurvivedBytes;
- }
-#endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
-
- if(m_dwIndex.m_dwIndex != 0)
- SystemDomain::ReleaseAppDomainIndex(m_dwIndex);
-} // AppDomain::Terminate
-
-void AppDomain::CloseDomain()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
-
- BOOL bADRemoved=FALSE;;
-
- AddRef(); // Hold a reference
- AppDomainRefHolder AdHolder(this);
- {
- SystemDomain::LockHolder lh;
-
- SystemDomain::System()->DecrementNumAppDomains(); // Maintain a count of app domains added to the list.
- bADRemoved = SystemDomain::System()->RemoveDomain(this);
- }
-
- if(bADRemoved)
- Stop();
-}
-
#endif // !CROSSGEN_COMPILE
#ifdef FEATURE_COMINTEROP
return m_level;
}
-ADID FileLoadLock::GetAppDomainId()
-{
- LIMITED_METHOD_CONTRACT;
- return m_AppDomainId;
-}
-
// Acquire will return FALSE and not take the lock if the file
// has already been loaded to the target level. Otherwise,
// it will return TRUE and take the lock.
case FILE_LOAD_DELIVER_EVENTS:
case FILE_LOADED:
case FILE_ACTIVE: // The timing of stress logs is not critical, so even for the FILE_ACTIVE stage we need not do it while the m_pList lock is held.
- STRESS_LOG4(LF_CLASSLOADER, LL_INFO100, "Completed Load Level %s for DomainFile %p in AD %i - success = %i\n", fileLoadLevelName[level], m_pDomainFile, m_AppDomainId.m_dwId, success);
+ STRESS_LOG3(LF_CLASSLOADER, LL_INFO100, "Completed Load Level %s for DomainFile %p - success = %i\n", fileLoadLevelName[level], m_pDomainFile, success);
break;
default:
break;
: ListLockEntry(pLock, pFile, "File load lock"),
m_level((FileLoadLevel) (FILE_LOAD_CREATE)),
m_pDomainFile(pDomainFile),
- m_cachedHR(S_OK),
- m_AppDomainId(pDomainFile->GetAppDomain()->GetId())
+ m_cachedHR(S_OK)
{
WRAPPER_NO_CONTRACT;
pFile->AddRef();
TryIncrementalLoad(pFile, workLevel, fileLock);
}
- TESTHOOKCALL(CompletedFileLoadLevel(GetId().m_dwId,pFile,workLevel));
+ TESTHOOKCALL(CompletedFileLoadLevel(DefaultADID,pFile,workLevel));
}
if (pLock->GetLoadLevel() == immediateTargetLevel-1)
}
// Do the work
- TESTHOOKCALL(NextFileLoadLevel(GetId().m_dwId,pFile,workLevel));
+ TESTHOOKCALL(NextFileLoadLevel(DefaultADID,pFile,workLevel));
BOOL success = pFile->DoIncrementalLoad(workLevel);
- TESTHOOKCALL(CompletingFileLoadLevel(GetId().m_dwId,pFile,workLevel));
+ TESTHOOKCALL(CompletingFileLoadLevel(DefaultADID,pFile,workLevel));
if (released)
{
// Reobtain lock to increment level. (Note that another thread may
FieldDesc * pEmptyStringFD = MscorlibBinder::GetField(FIELD__STRING__EMPTY);
OBJECTREF* pEmptyStringHandle = (OBJECTREF*)
((TADDR)pLocalModule->GetPrecomputedGCStaticsBasePointer()+pEmptyStringFD->GetOffset());
- SetObjectReference( pEmptyStringHandle, StringObject::GetEmptyString(), this );
+ SetObjectReference( pEmptyStringHandle, StringObject::GetEmptyString());
#endif // CROSSGEN_COMPILE
}
}
else
{
- if (IsDefaultDomain())
- tmpFriendlyName.Set(DEFAULT_DOMAIN_FRIENDLY_NAME);
-
- // This is for the profiler - if they call GetFriendlyName on an AppdomainCreateStarted
- // event, then we want to give them a temporary name they can use.
- else if (GetId().m_dwId != 0)
- {
- tmpFriendlyName.Clear();
- tmpFriendlyName.Printf(W("%s %d"), OTHER_DOMAIN_FRIENDLY_NAME_PREFIX, GetId().m_dwId);
- }
+ tmpFriendlyName.Set(DEFAULT_DOMAIN_FRIENDLY_NAME);
}
-
}
tmpFriendlyName.Normalize();
if (!cRef)
{
_ASSERTE (m_Stage == STAGE_CREATING);
- ADID adid=GetId();
delete this;
- TESTHOOKCALL(AppDomainDestroyed(adid.m_dwId));
+ TESTHOOKCALL(AppDomainDestroyed(DefaultADID));
}
return (cRef);
}
GCX_PREEMP();
// Initialize the assembly binder for the default context loads for CoreCLR.
- IfFailThrow(CCoreCLRBinderHelper::DefaultBinderSetupContext(GetId().m_dwId, &pTPABinder));
+ IfFailThrow(CCoreCLRBinderHelper::DefaultBinderSetupContext(DefaultADID, &pTPABinder));
m_pFusionContext = reinterpret_cast<IUnknown *>(pTPABinder);
// By default, initial binding context setup for CoreCLR is also the TPABinding context
if (!IsDebuggerAttached())
return;
- LOG((LF_CORDB, LL_INFO10, "AD::NDD domain [%d] %#08x %ls\n",
- GetId().m_dwId, this, GetFriendlyNameForLogging()));
+ LOG((LF_CORDB, LL_INFO10, "AD::NDD domain %#08x %ls\n",
+ this, GetFriendlyNameForLogging()));
LOG((LF_CORDB, LL_INFO100, "AD::NDD: Interating domain bound assemblies\n"));
AssemblyIterator i = IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoaded | kIncludeLoading | kIncludeExecution));
LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::ExceptionUnwind: not first transition or abort\n"));
}
-#ifdef _DEBUG
-
-void AppDomain::TrackADThreadEnter(Thread *pThread, Frame *pFrame)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- // REENTRANT
- PRECONDITION(CheckPointer(pThread));
- PRECONDITION(pFrame != (Frame*)(size_t) INVALID_POINTER_CD);
- }
- CONTRACTL_END;
-
- while (FastInterlockCompareExchange((LONG*)&m_TrackSpinLock, 1, 0) != 0)
- ;
- if (m_pThreadTrackInfoList == NULL)
- m_pThreadTrackInfoList = new (nothrow) ThreadTrackInfoList;
- // If we don't assert here, we will AV in the for loop below
- _ASSERTE(m_pThreadTrackInfoList);
-
- ThreadTrackInfoList *pTrackList= m_pThreadTrackInfoList;
-
- ThreadTrackInfo *pTrack = NULL;
- int i;
- for (i=0; i < pTrackList->Count(); i++) {
- if ((*(pTrackList->Get(i)))->pThread == pThread) {
- pTrack = *(pTrackList->Get(i));
- break;
- }
- }
- if (! pTrack) {
- pTrack = new (nothrow) ThreadTrackInfo;
- // If we don't assert here, we will AV in the for loop below.
- _ASSERTE(pTrack);
- pTrack->pThread = pThread;
- ThreadTrackInfo **pSlot = pTrackList->Append();
- *pSlot = pTrack;
- }
-
- InterlockedIncrement((LONG*)&m_dwThreadEnterCount);
- Frame **pSlot;
- if (pTrack)
- {
- pSlot = pTrack->frameStack.Insert(0);
- *pSlot = pFrame;
- }
- int totThreads = 0;
- for (i=0; i < pTrackList->Count(); i++)
- totThreads += (*(pTrackList->Get(i)))->frameStack.Count();
- _ASSERTE(totThreads == (int)m_dwThreadEnterCount);
-
- InterlockedExchange((LONG*)&m_TrackSpinLock, 0);
-}
-
-
-void AppDomain::TrackADThreadExit(Thread *pThread, Frame *pFrame)
-{
- CONTRACTL
- {
- if (GetThread()) {MODE_COOPERATIVE;}
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- while (FastInterlockCompareExchange((LONG*)&m_TrackSpinLock, 1, 0) != 0)
- ;
- ThreadTrackInfoList *pTrackList= m_pThreadTrackInfoList;
- _ASSERTE(pTrackList);
- ThreadTrackInfo *pTrack = NULL;
- int i;
- for (i=0; i < pTrackList->Count(); i++)
- {
- if ((*(pTrackList->Get(i)))->pThread == pThread)
- {
- pTrack = *(pTrackList->Get(i));
- break;
- }
- }
- _ASSERTE(pTrack);
- _ASSERTE(*(pTrack->frameStack.Get(0)) == pFrame);
- pTrack->frameStack.Delete(0);
- InterlockedDecrement((LONG*)&m_dwThreadEnterCount);
-
- int totThreads = 0;
- for (i=0; i < pTrackList->Count(); i++)
- totThreads += (*(pTrackList->Get(i)))->frameStack.Count();
- _ASSERTE(totThreads == (int)m_dwThreadEnterCount);
-
- InterlockedExchange((LONG*)&m_TrackSpinLock, 0);
-}
-
-void AppDomain::DumpADThreadTrack()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
- while (FastInterlockCompareExchange((LONG*)&m_TrackSpinLock, 1, 0) != 0)
- ;
- ThreadTrackInfoList *pTrackList= m_pThreadTrackInfoList;
- if (!pTrackList)
- goto end;
-
- {
- LOG((LF_APPDOMAIN, LL_INFO10000, "\nThread dump of %d threads for [%d] %#08x %S\n",
- m_dwThreadEnterCount, GetId().m_dwId, this, GetFriendlyNameForLogging()));
- int totThreads = 0;
- for (int i=0; i < pTrackList->Count(); i++)
- {
- ThreadTrackInfo *pTrack = *(pTrackList->Get(i));
- if (pTrack->frameStack.Count()==0)
- continue;
- LOG((LF_APPDOMAIN, LL_INFO100, " ADEnterCount for %x is %d\n", pTrack->pThread->GetThreadId(), pTrack->frameStack.Count()));
- totThreads += pTrack->frameStack.Count();
- for (int j=0; j < pTrack->frameStack.Count(); j++)
- LOG((LF_APPDOMAIN, LL_INFO100, " frame %8.8x\n", *(pTrack->frameStack.Get(j))));
- }
- _ASSERTE(totThreads == (int)m_dwThreadEnterCount);
- }
-end:
- InterlockedExchange((LONG*)&m_TrackSpinLock, 0);
-}
-#endif // _DEBUG
-
#endif // CROSSGEN_COMPILE
#endif // !DACCESS_COMPILE
{
AppDomain::GetCurrentDomain()->EnumMemoryRegions(flags, true);
}
-
- m_appDomainIndexList.EnumMem();
- (&m_appDomainIndexList)->EnumMemoryRegions(flags);
}
#endif //DACCESS_COMPILE
FileLoadLevel m_level;
DomainFile *m_pDomainFile;
HRESULT m_cachedHR;
- ADID m_AppDomainId;
public:
static FileLoadLock *Create(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile);
~FileLoadLock();
DomainFile *GetDomainFile();
- ADID GetAppDomainId();
FileLoadLevel GetLoadLevel();
// CanAcquire will return FALSE if Acquire will definitely not take the lock due
VPTR_UNIQUE(VPTR_UNIQUE_BaseDomain)
protected:
- // These 2 variables are only used on the AppDomain, but by placing them here
- // we reduce the cost of keeping the asmconstants file up to date.
-
- // The creation sequence number of this app domain (starting from 1)
- // This ID is generated by the code:SystemDomain::GetNewAppDomainId routine
- // The ID are recycled.
- //
- // see also code:ADID
- ADID m_dwId;
-
DomainLocalBlock m_sDomainLocalBlock;
public:
virtual ~BaseDomain() {}
void Init();
void Stop();
- void Terminate();
- // ID to uniquely identify this AppDomain - used by the AppDomain publishing
- // service (to publish the list of all appdomains present in the process),
- // which in turn is used by, for eg., the debugger (to decide which App-
- // Domain(s) to attach to).
- // This is also used by Remoting for routing cross-appDomain calls.
- ADID GetId (void)
- {
- LIMITED_METHOD_DAC_CONTRACT;
- return m_dwId;
- }
-
virtual BOOL IsAppDomain() { LIMITED_METHOD_DAC_CONTRACT; return FALSE; }
BOOL IsSharedDomain() { LIMITED_METHOD_DAC_CONTRACT; return FALSE; }
// the critical sections
void Stop();
- // Gets rid of resources
- void Terminate();
-
-#ifdef FEATURE_PREJIT
- //assembly cleanup that requires suspended runtime
- void DeleteNativeCodeRanges();
-#endif
-
// final assembly cleanup
- void ShutdownAssemblies();
- void ShutdownFreeLoaderAllocators(BOOL bFromManagedCode);
+ void ShutdownFreeLoaderAllocators();
void ReleaseFiles();
-
- // Remove the Appdomain for the system and cleans up. This call should not be
- // called from shut down code.
- void CloseDomain();
-
virtual BOOL IsAppDomain() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; }
virtual PTR_AppDomain AsAppDomain() { LIMITED_METHOD_CONTRACT; return dac_cast<PTR_AppDomain>(this); }
PathIterator IterateNativeDllSearchDirectories();
void SetNativeDllSearchDirectories(LPCWSTR paths);
BOOL HasNativeDllSearchDirectories();
- void ShutdownNativeDllSearchDirectories();
public:
SIZE_T GetAssemblyCount()
//****************************************************************************************
// Get the proxy for this app domain
- ADIndex GetIndex()
- {
- LIMITED_METHOD_CONTRACT;
- SUPPORTS_DAC;
-
- return m_dwIndex;
- }
-
TPIndex GetTPIndex()
{
LIMITED_METHOD_CONTRACT;
static void ExceptionUnwind(Frame *pFrame);
-#ifdef _DEBUG
- void TrackADThreadEnter(Thread *pThread, Frame *pFrame);
- void TrackADThreadExit(Thread *pThread, Frame *pFrame);
- void DumpADThreadTrack();
-#endif
-
-#ifndef DACCESS_COMPILE
- void ThreadEnter(Thread *pThread, Frame *pFrame)
- {
- STATIC_CONTRACT_NOTHROW;
- STATIC_CONTRACT_GC_NOTRIGGER;
-
-#ifdef _DEBUG
- if (LoggingOn(LF_APPDOMAIN, LL_INFO100))
- TrackADThreadEnter(pThread, pFrame);
- else
-#endif
- {
- InterlockedIncrement((LONG*)&m_dwThreadEnterCount);
- LOG((LF_APPDOMAIN, LL_INFO1000, "AppDomain::ThreadEnter %p to [%d] (%8.8x) %S count %d\n",
- pThread,GetId().m_dwId, this,
- GetFriendlyNameForLogging(),GetThreadEnterCount()));
-#if _DEBUG_AD_UNLOAD
- printf("AppDomain::ThreadEnter %p to [%d] (%8.8x) %S count %d\n",
- pThread, GetId().m_dwId, this,
- GetFriendlyNameForLogging(), GetThreadEnterCount());
-#endif
- }
- }
-
- void ThreadExit(Thread *pThread, Frame *pFrame)
- {
- STATIC_CONTRACT_NOTHROW;
- STATIC_CONTRACT_GC_NOTRIGGER;
-
-#ifdef _DEBUG
- if (LoggingOn(LF_APPDOMAIN, LL_INFO100)) {
- TrackADThreadExit(pThread, pFrame);
- }
- else
-#endif
- {
- LONG result;
- result = InterlockedDecrement((LONG*)&m_dwThreadEnterCount);
- _ASSERTE(result >= 0);
- LOG((LF_APPDOMAIN, LL_INFO1000, "AppDomain::ThreadExit from [%d] (%8.8x) %S count %d\n",
- this, GetId().m_dwId,
- GetFriendlyNameForLogging(), GetThreadEnterCount()));
- }
- }
-#endif // DACCESS_COMPILE
-
- ULONG GetThreadEnterCount()
- {
- LIMITED_METHOD_CONTRACT;
- return m_dwThreadEnterCount;
- }
-
- BOOL OnlyOneThreadLeft()
- {
- LIMITED_METHOD_CONTRACT;
- return m_dwThreadEnterCount==1 || m_dwThreadsStillInAppDomain ==1;
- }
-
static void RefTakerAcquire(AppDomain* pDomain)
{
WRAPPER_NO_CONTRACT;
_ASSERTE(m_dwCreationHolders > -1);
}
#endif
- BOOL IsRunningIn(Thread* pThread);
-
BOOL NotReadyForManagedCode()
{
LIMITED_METHOD_CONTRACT;
MODE_ANY;
}
CONTRACTL_END;
- STRESS_LOG2(LF_APPDOMAIN, LL_INFO100,"Updating AD stage, ADID=%d, stage=%d\n",GetId().m_dwId,stage);
- TESTHOOKCALL(AppDomainStageChanged(GetId().m_dwId,m_Stage,stage));
+ STRESS_LOG1(LF_APPDOMAIN, LL_INFO100,"Updating AD stage, stage=%d\n",stage);
+ TESTHOOKCALL(AppDomainStageChanged(DefaultADID,m_Stage,stage));
Stage lastStage=m_Stage;
while (lastStage !=stage)
lastStage = (Stage)FastInterlockCompareExchange((LONG*)&m_Stage,stage,lastStage);
return GetLoaderAllocator()->GetGCRefPoint();
}
- static USHORT GetOffsetOfId()
- {
- LIMITED_METHOD_CONTRACT;
- size_t ofs = offsetof(class AppDomain, m_dwId);
- _ASSERTE(FitsInI2(ofs));
- return (USHORT)ofs;
- }
-
-
void AddMemoryPressure();
void RemoveMemoryPressure();
RCWRefCache *m_pRCWRefCache;
#endif // FEATURE_COMINTEROP
- // The index of this app domain among existing app domains (starting from 1)
- ADIndex m_dwIndex;
-
// The thread-pool index of this app domain among existing app domains (starting from 1)
TPIndex m_tpIndex;
Volatile<ULONGLONG> m_ullTotalProcessorUsage;
#endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
-#ifdef _DEBUG
- struct ThreadTrackInfo;
- typedef CDynArray<ThreadTrackInfo *> ThreadTrackInfoList;
- ThreadTrackInfoList *m_pThreadTrackInfoList;
- DWORD m_TrackSpinLock;
-#endif
-
- // The number of times we have entered this AD
- ULONG m_dwThreadEnterCount;
- // The number of threads that have entered this AD, for ADU only
- ULONG m_dwThreadsStillInAppDomain;
-
Volatile<Stage> m_Stage;
ArrayList m_failedAssemblies;
friend class AppDomainIterator;
friend class UnsafeAppDomainIterator;
friend class ClrDataAccess;
- friend Frame *Thread::IsRunningIn(AppDomain* pDomain, int *count);
VPTR_VTABLE_CLASS(SystemDomain, BaseDomain)
VPTR_UNIQUE(VPTR_UNIQUE_SystemDomain)
- static AppDomain *GetAppDomainAtId(ADID indx);
public:
static PTR_LoaderAllocator GetGlobalLoaderAllocator();
- static AppDomain* GetAppDomainFromId(ADID indx,DWORD ADValidityKind)
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
- AppDomain* pRetVal;
- if (indx.m_dwId==DefaultADID)
- pRetVal= SystemDomain::System()->DefaultDomain();
- else
- pRetVal= GetAppDomainAtId(indx);
-#ifdef _DEBUG
- // Only call CheckADValidity in DEBUG builds for non-NULL return values
- if (pRetVal != NULL)
- CheckADValidity(pRetVal, ADValidityKind);
-#endif
- return pRetVal;
- }
+
//****************************************************************************************
//
// To be run during the initial start up of the EE. This must be
#endif
void Init();
void Stop();
- void Terminate();
static void LazyInitGlobalStringLiteralMap();
//****************************************************************************************
static HRESULT NotifyProfilerShutdown();
#endif // PROFILING_SUPPORTED
- //****************************************************************************************
- // return the dev path
-
-#ifndef DACCESS_COMPILE
- void IncrementNumAppDomains ()
- {
- LIMITED_METHOD_CONTRACT;
-
- s_dNumAppDomains++;
- }
-
- void DecrementNumAppDomains ()
- {
- LIMITED_METHOD_CONTRACT;
-
- s_dNumAppDomains--;
- }
-
- ULONG GetNumAppDomains ()
- {
- LIMITED_METHOD_CONTRACT;
-
- return s_dNumAppDomains;
- }
-#endif // DACCESS_COMPILE
-
- //
- // AppDomains currently have both an index and an ID. The
- // index is "densely" assigned; indices are reused as domains
- // are unloaded. The Id's on the other hand, are not reclaimed
- // so may be sparse.
- //
- // Another important difference - it's OK to call GetAppDomainAtId for
- // an unloaded domain (it will return NULL), while GetAppDomainAtIndex
- // will assert if the domain is unloaded.
- //<TODO>
- // @todo:
- // I'm not really happy with this situation, but
- // (a) we need an ID for a domain which will last the process lifetime for the
- // remoting code.
- // (b) we need a dense ID, for the handle table index.
- // So for now, I'm leaving both, but hopefully in the future we can come up
- // with something better.
- //</TODO>
-
- static ADIndex GetNewAppDomainIndex(AppDomain * pAppDomain);
- static void ReleaseAppDomainIndex(ADIndex indx);
- static PTR_AppDomain GetAppDomainAtIndex(ADIndex indx);
- static PTR_AppDomain TestGetAppDomainAtIndex(ADIndex indx);
- static DWORD GetCurrentAppDomainMaxIndex()
- {
- WRAPPER_NO_CONTRACT;
-
- ArrayListStatic* list = (ArrayListStatic *)&m_appDomainIndexList;
- PREFIX_ASSUME(list!=NULL);
- return list->GetCount();
- }
-
- static ADID GetNewAppDomainId(AppDomain *pAppDomain);
- static void ReleaseAppDomainId(ADID indx);
-
-#ifndef DACCESS_COMPILE
- static ADID GetCurrentAppDomainMaxId() { ADID id; id.m_dwId=m_appDomainIdList.GetCount(); return id;}
-#endif // DACCESS_COMPILE
-
-
#ifndef DACCESS_COMPILE
DWORD RequireAppDomainCleanup()
{
static size_t m_totalSurvivedBytes;
#endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
- SVAL_DECL(ArrayListStatic, m_appDomainIndexList);
#ifndef DACCESS_COMPILE
static CrstStatic m_DelayedUnloadCrst;
static CrstStatic m_SystemDomainCrst;
-
- static ArrayListStatic m_appDomainIdList;
-
static GlobalStringLiteralMap *m_pGlobalStringLiteralMap;
static ULONG s_dNumAppDomains; // Maintain a count of children app domains.
// start & end of the iteration. This iterator is considered unsafe because it does not
// reference count the various appdomains, and can only be used when the runtime is stopped,
// or external synchronization is used. (and therefore no other thread may cause the appdomain list to change.)
+// In CoreCLR, this iterator doesn't use a list as there is at most 1 AppDomain, and instead will find the only AppDomain, or not.
//
class UnsafeAppDomainIterator
{
void Init()
{
LIMITED_METHOD_CONTRACT;
- SystemDomain* sysDomain = SystemDomain::System();
- if (sysDomain)
- {
- ArrayListStatic* list = &sysDomain->m_appDomainIndexList;
- PREFIX_ASSUME(list != NULL);
- m_i = list->Iterate();
- }
- else
- {
- m_i.SetEmpty();
- }
-
+ m_iterationCount = 0;
m_pCurrent = NULL;
}
{
WRAPPER_NO_CONTRACT;
- while (m_i.Next())
+ if (m_iterationCount == 0)
{
- m_pCurrent = dac_cast<PTR_AppDomain>(m_i.GetElement());
+ m_iterationCount++;
+ m_pCurrent = AppDomain::GetCurrentDomain();
if (m_pCurrent != NULL &&
(m_bOnlyActive ?
m_pCurrent->IsActive() : m_pCurrent->IsValid()))
private:
- ArrayList::Iterator m_i;
+ int m_iterationCount;
AppDomain * m_pCurrent;
BOOL m_bOnlyActive;
}; // class UnsafeAppDomainIterator
#include "comreflectioncache.inl"
-#define INVALID_APPDOMAIN_ID ((DWORD)-1)
-#define CURRENT_APPDOMAIN_ID ((ADID)(DWORD)0)
-
#endif
return assembly->FindDomainAssembly(this);
};
-inline BOOL AppDomain::IsRunningIn(Thread* pThread)
-{
- WRAPPER_NO_CONTRACT;
- if (IsDefaultDomain())
- return TRUE;
- return pThread->IsRunningIn(this, NULL)!=NULL;
-}
-
-
-
inline void AppDomain::AddMemoryPressure()
{
STANDARD_VM_CONTRACT;
#define UMEntryThunk__m_pUMThunkMarshInfo 0x0C
ASMCONSTANTS_C_ASSERT(UMEntryThunk__m_pUMThunkMarshInfo == offsetof(UMEntryThunk, m_pUMThunkMarshInfo))
-#define UMEntryThunk__m_dwDomainId 0x10
-ASMCONSTANTS_C_ASSERT(UMEntryThunk__m_dwDomainId == offsetof(UMEntryThunk, m_dwDomainId))
-
#define UMThunkMarshInfo__m_pILStub 0x00
ASMCONSTANTS_C_ASSERT(UMThunkMarshInfo__m_pILStub == offsetof(UMThunkMarshInfo, m_pILStub))
#define Thread_m_pFrame Thread__m_pFrame
#ifndef CROSSGEN_COMPILE
-#define Thread__m_pDomain 0x10
-ASMCONSTANTS_C_ASSERT(Thread__m_pDomain == offsetof(Thread, m_pDomain));
-
-#define AppDomain__m_dwId 0x04
-ASMCONSTANTS_C_ASSERT(AppDomain__m_dwId == offsetof(AppDomain, m_dwId));
-
-#define AppDomain__m_sDomainLocalBlock 0x08
-ASMCONSTANTS_C_ASSERT(AppDomain__m_sDomainLocalBlock == offsetof(AppDomain, m_sDomainLocalBlock));
-
#define DomainLocalBlock__m_pModuleSlots 0x04
ASMCONSTANTS_C_ASSERT(DomainLocalBlock__m_pModuleSlots == offsetof(DomainLocalBlock, m_pModuleSlots));
#define Thread_m_pFrame Thread__m_pFrame
#define Thread_m_fPreemptiveGCDisabled Thread__m_fPreemptiveGCDisabled
-#ifndef CROSSGEN_COMPILE
-#define Thread__m_pDomain 0x18
-ASMCONSTANTS_C_ASSERT(Thread__m_pDomain == offsetof(Thread, m_pDomain));
-
-#define AppDomain__m_dwId 0x08
-ASMCONSTANTS_C_ASSERT(AppDomain__m_dwId == offsetof(AppDomain, m_dwId));
-#endif
-
#define METHODDESC_REGISTER x12
#define SIZEOF__ArgumentRegisters 0x40
#define UMEntryThunk__m_pUMThunkMarshInfo 0x18
ASMCONSTANTS_C_ASSERT(UMEntryThunk__m_pUMThunkMarshInfo == offsetof(UMEntryThunk, m_pUMThunkMarshInfo))
-#define UMEntryThunk__m_dwDomainId 0x20
-ASMCONSTANTS_C_ASSERT(UMEntryThunk__m_dwDomainId == offsetof(UMEntryThunk, m_dwDomainId))
-
#define UMThunkMarshInfo__m_pILStub 0x00
ASMCONSTANTS_C_ASSERT(UMThunkMarshInfo__m_pILStub == offsetof(UMThunkMarshInfo, m_pILStub))
loaderAllocator->ActivateManagedTracking();
}
- IfFailThrow(CLRPrivBinderAssemblyLoadContext::SetupContext(pCurDomain->GetId().m_dwId, pTPABinderContext, loaderAllocator, loaderAllocatorHandle, ptrManagedAssemblyLoadContext, &pBindContext));
+ IfFailThrow(CLRPrivBinderAssemblyLoadContext::SetupContext(DefaultADID, pTPABinderContext, loaderAllocator, loaderAllocatorHandle, ptrManagedAssemblyLoadContext, &pBindContext));
ptrNativeAssemblyLoadContext = reinterpret_cast<INT_PTR>(pBindContext);
}
else
/* thread abort has been requested */ \
if (!(flags & EEToManagedCriticalCall)) \
{ \
- TESTHOOKCALL(AppDomainCanBeUnloaded(CURRENT_THREAD->GetDomain()->GetId().m_dwId,FALSE)); \
+ TESTHOOKCALL(AppDomainCanBeUnloaded(DefaultADID,FALSE)); \
if (CURRENT_THREAD->IsAbortRequested()) { \
CURRENT_THREAD->HandleThreadAbort(); \
} \
// Check if it is an OBJECTREF (from the GC heap)
if (pvDest)
- SetObjectReferenceUnchecked((OBJECTREF *)pvDest, *src);
+ SetObjectReference((OBJECTREF *)pvDest, *src);
*(OBJECTREF*)&ret = (*src);
}
OBJECTREF* pRef = pDomain->AllocateObjRefPtrsInLargeTable(1);
STRINGREF str = AllocateStringObject(&strData);
- SetObjectReference(pRef, str, NULL);
+ SetObjectReference(pRef, str);
#ifdef LOGGING
int length = strData.GetCharCount();
// assemblies/app domains.
//
// This should throw.
- STRESS_LOG2(LF_CLASSLOADER, LL_INFO100,"EnableModuleFailureTriggers for module %p in AppDomain %i\n",pModuleTo,pDomain->GetId().m_dwId);
+ STRESS_LOG1(LF_CLASSLOADER, LL_INFO100,"EnableModuleFailureTriggers for module %p\n",pModuleTo);
DomainFile *pDomainFileTo = pModuleTo->GetDomainFile(pDomain);
pDomainFileTo->EnsureActive();
#endif //!DACCESS_COMPILE
-//
-// an GetAssemblyIfLoadedAppDomainIterator is used to iterate over all domains that
-// are known to be walkable at the time GetAssemblyIfLoaded is executed.
-//
-// The iteration is guaranteed to include all domains that exist at the
-// start & end of the iteration that are safely accessible. This class is logically part
-// of GetAssemblyIfLoaded and logically has the same set of contracts.
-//
-
-class GetAssemblyIfLoadedAppDomainIterator
-{
- enum IteratorType
- {
- StackwalkingThreadIterator,
- AllAppDomainWalkingIterator,
- CurrentAppDomainIterator
- } m_iterType;
-
-public:
- GetAssemblyIfLoadedAppDomainIterator() :
- m_adIteratorAll(TRUE),
- m_appDomainCurrent(NULL),
- m_pFrame(NULL),
- m_fNextCalledForCurrentADIterator(FALSE)
- {
- LIMITED_METHOD_CONTRACT;
-#ifndef DACCESS_COMPILE
- if (IsStackWalkerThread())
- {
- Thread * pThread = (Thread *)ClrFlsGetValue(TlsIdx_StackWalkerWalkingThread);
- m_iterType = StackwalkingThreadIterator;
- m_pFrame = pThread->GetFrame();
- m_appDomainCurrent = pThread->GetDomain();
- }
- else if (IsGCThread())
- {
- m_iterType = AllAppDomainWalkingIterator;
- m_adIteratorAll.Init();
- }
- else
- {
- _ASSERTE(::GetAppDomain() != NULL);
- m_appDomainCurrent = ::GetAppDomain();
- m_iterType = CurrentAppDomainIterator;
- }
-#else //!DACCESS_COMPILE
- // We have to walk all AppDomains in debugger
- m_iterType = AllAppDomainWalkingIterator;
- m_adIteratorAll.Init();
-#endif //!DACCESS_COMPILE
- }
-
- BOOL Next()
- {
- WRAPPER_NO_CONTRACT;
-
- switch (m_iterType)
- {
-#ifndef DACCESS_COMPILE
- case StackwalkingThreadIterator:
- if (!m_fNextCalledForCurrentADIterator)
- {
- m_fNextCalledForCurrentADIterator = TRUE;
-
- // Try searching frame chain if the current domain is NULL
- if (m_appDomainCurrent == NULL)
- return Next();
-
- return TRUE;
- }
- else
- {
- while (m_pFrame != FRAME_TOP)
- {
- AppDomain * pDomain = m_pFrame->GetReturnDomain();
- if ((pDomain != NULL) && (pDomain != m_appDomainCurrent))
- {
- m_appDomainCurrent = pDomain;
- return TRUE;
- }
- m_pFrame = m_pFrame->PtrNextFrame();
- }
-
- return FALSE;
- }
-#endif //!DACCESS_COMPILE
-
- case AllAppDomainWalkingIterator:
- {
- BOOL fSuccess = m_adIteratorAll.Next();
- if (fSuccess)
- m_appDomainCurrent = m_adIteratorAll.GetDomain();
- return fSuccess;
- }
-
-#ifndef DACCESS_COMPILE
- case CurrentAppDomainIterator:
- {
- BOOL retVal;
- retVal = !m_fNextCalledForCurrentADIterator;
- m_fNextCalledForCurrentADIterator = TRUE;
- return retVal;
- }
-#endif //!DACCESS_COMPILE
-
- default:
- _ASSERTE(FALSE);
- return FALSE;
- }
- }
-
- AppDomain * GetDomain()
- {
- LIMITED_METHOD_CONTRACT;
-
- return m_appDomainCurrent;
- }
-
- BOOL UsingCurrentAD()
- {
- LIMITED_METHOD_CONTRACT;
- return m_iterType == CurrentAppDomainIterator;
- }
-
- private:
-
- UnsafeAppDomainIterator m_adIteratorAll;
- AppDomain * m_appDomainCurrent;
- Frame * m_pFrame;
- BOOL m_fNextCalledForCurrentADIterator;
-}; // class GetAssemblyIfLoadedAppDomainIterator
-
#if !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT)
// This function, given an AssemblyRef into the ngen generated native metadata section, will find the assembly referenced if
// 1. The Assembly is defined with a different name than the AssemblyRef provides
if (pAssembly == NULL)
{
- // If in stackwalking or gc mode
- // For each AppDomain that is on the stack being walked...
- // For each AppDomain in the process... if gc'ing
- // For the current AppDomain ... if none of the above
- GetAssemblyIfLoadedAppDomainIterator appDomainIter;
-
- while (appDomainIter.Next())
+ do
{
- AppDomain * pAppDomainExamine = appDomainIter.GetDomain();
+ AppDomain * pAppDomainExamine = AppDomain::GetCurrentDomain();
DomainAssembly * pCurAssemblyInExamineDomain = GetAssembly()->FindDomainAssembly(pAppDomainExamine);
if (pCurAssemblyInExamineDomain == NULL)
pAssembly = pDomainAssembly->GetCurrentAssembly(); // <NOTE> Do not use GetAssembly - that may force the completion of a load
// Only store in the rid map if working with the current AppDomain.
- if (fCanUseRidMap && pAssembly && appDomainIter.UsingCurrentAD())
+ if (fCanUseRidMap && pAssembly)
StoreAssemblyRef(kAssemblyRef, pAssembly);
if (pAssembly != NULL)
break;
}
#endif //!DACCESS_COMPILE
- }
+ } while (false);
}
#if !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT)
bool onlyScanCurrentModule = HasNativeImage() && GetFile()->IsAssembly();
mdAssemblyRef foundAssemblyRef = mdAssemblyRefNil;
- GetAssemblyIfLoadedAppDomainIterator appDomainIter;
-
// In each AppDomain that might be interesting, scan for an ngen image that is loaded that has a dependency on the same
// assembly that is now being looked up. If that ngen image has the same dependency, then we can use the CORCOMPILE_DEPENDENCIES
// table to find the exact AssemblyDef that defines the assembly, and attempt a load based on that information.
// As this logic is expected to be used only in exceedingly rare situations, this code has not been tuned for performance
// in any way.
- while (!abortAdditionalChecks && appDomainIter.Next())
+ do
{
- AppDomain * pAppDomainExamine = appDomainIter.GetDomain();
+ AppDomain * pAppDomainExamine = ::GetAppDomain(); // There is only 1 AppDomain on CoreCLR
DomainAssembly * pCurAssemblyInExamineDomain = GetAssembly()->FindDomainAssembly(pAppDomainExamine);
if (pCurAssemblyInExamineDomain == NULL)
pAssembly = pNativeImageModule->GetAssemblyIfLoadedFromNativeAssemblyRefWithRefDefMismatch(foundAssemblyRef, &abortAdditionalChecks);
- if (fCanUseRidMap && pAssembly && appDomainIter.UsingCurrentAD())
+ if (fCanUseRidMap && pAssembly)
StoreAssemblyRef(kAssemblyRef, pAssembly);
}
pDomainFileNativeImage = pDomainFileNativeImage->FindNextDomainFileWithNativeImage();
}
- }
+ } while (false);
}
}
#endif // !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT)
FillMemory(pUMThunkMarshInfo, sizeof(*pUMThunkMarshInfo), 0);
pUMThunkMarshInfo->LoadTimeInit(pMD);
- pUMEntryThunk->LoadTimeInit(NULL, NULL, pUMThunkMarshInfo, pMD, pAppDomain->GetId());
+ pUMEntryThunk->LoadTimeInit(NULL, NULL, pUMThunkMarshInfo, pMD);
SetTargetForVTableEntry(hInstThis, (BYTE **)&pPointers[iMethod], (BYTE *)pUMEntryThunk->GetCode());
pData->MarkMethodFixedUp(iFixup, iMethod);
//
AppDomain *pDomain = pCurrentThread->GetDomain();
- m_adid = pDomain->GetId();
-
{
GCX_COOP_THREAD_EXISTS(pCurrentThread);
m_ppObject = pDomain->CreateShortWeakHandle(pSimpleWrapper->GetObjectRef());
GC_TRIGGERS;
MODE_PREEMPTIVE;
PRECONDITION(CheckPointer(ppvObject));
- PRECONDITION(AppDomain::GetCurrentDomain()->GetId() == m_adid);
}
CONTRACTL_END;
m_pOuter = NULL;
m_pSyncBlock = pSyncBlock;
- m_dwDomainId = GetAppDomain()->GetId();
if (pMT->IsComObjectType())
m_flags |= enum_IsExtendsCom;
}
}
- // get this info before the simple wrapper gets cleaned up.
- ADID domainId=CURRENT_APPDOMAIN_ID;
if (m_pSimpleWrapper)
{
m_pSimpleWrapper->Cleanup();
- domainId=m_pSimpleWrapper->GetDomainID();
}
if (g_fEEStarted || m_pSimpleWrapper->GetOuter() == NULL)
};
public:
- ADID GetDomainID();
-
VOID ResetHandleStrength();
VOID MarkHandleWeak();
class WeakReferenceImpl : public IUnknownCommon<IWeakReference>
{
private:
- ADID m_adid; // AppDomain ID of where this weak reference is created
OBJECTHANDLE m_ppObject; // Short weak global handle points back to the object,
- // created in domain ID = m_adid
public:
WeakReferenceImpl(SimpleComCallWrapper *pSimpleWrapper, Thread *pCurrentThread);
BOOL FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP);
void EnumConnectionPoints(IEnumConnectionPoints **ppEnumCP);
- ADID GetDomainID()
- {
- CONTRACTL
- {
- WRAPPER(THROWS);
- WRAPPER(GC_TRIGGERS);
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return m_dwDomainId;
- }
-
- ADID GetRawDomainID()
- {
- LIMITED_METHOD_DAC_CONTRACT;
- return m_dwDomainId;
- }
-
// is the object aggregated by a COM component
BOOL IsAggregated()
{
// Points to uncommonly used data that are dynamically allocated
VolatilePtr<SimpleCCWAuxData> m_pAuxData;
- ADID m_dwDomainId;
-
DWORD m_flags;
// This maintains both COM ref and Jupiter ref in 64-bit
RETURN pWrap;
}
-inline ADID ComCallWrapper::GetDomainID()
-{
- WRAPPER_NO_CONTRACT;
-
- return GetSimpleWrapper()->GetDomainID();
-}
-
inline ULONG ComCallWrapper::GetRefCount()
{
CONTRACTL
pUMEntryThunk->LoadTimeInit(
pManagedTargetForDiagnostics,
objhnd,
- pUMThunkMarshInfo, pInvokeMeth,
- GetAppDomain()->GetId());
+ pUMThunkMarshInfo, pInvokeMeth);
#ifdef FEATURE_WINDOWSPHONE
// Perform the runtime initialization lazily for better startup time. Lazy initialization
pUMEntryThunk = (UMEntryThunk*)pInteropInfo->GetUMEntryThunk();
_ASSERTE(pUMEntryThunk);
- if (pUMEntryThunk->GetDomainId() != GetAppDomain()->GetId())
- COMPlusThrow(kNotSupportedException, W("NotSupported_DelegateMarshalToWrongDomain"));
-
GCPROTECT_END();
return pDelegate;
}
m_flags = RCW::CF_None;
m_pCallback = NULL;
m_pThread = NULL;
-
- m_dwServerSyncBlockIndex = 0;
}
//--------------------------------------------------------------------------------
m_typeHandle = TypeHandle(g_pBaseCOMObject);
}
-//--------------------------------------------------------------------
-// OBJECTREF COMInterfaceMarshaler::GetCCWObject()
-//--------------------------------------------------------------------
-OBJECTREF COMInterfaceMarshaler::GetCCWObject()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
- OBJECTREF oref = NULL;
-
- if (m_dwServerSyncBlockIndex != 0)
- {
- AppDomain* pCurrDomain = m_pThread->GetDomain();
-
- // if we are in the right AD, we know for sure that the object is still alive
- // since we keep the CCW addref'ed
- oref = ObjectToOBJECTREF(g_pSyncTable[m_dwServerSyncBlockIndex].m_Object);
- }
-
- return oref;
-}
-
//--------------------------------------------------------------------------------
// void COMInterfaceMarshaler::CreateObjectRef(BOOL fDuplicate, OBJECTREF *pComObj)
// Creates an RCW of the proper type.
static void IKeyValuePairUnboxWorker(OBJECTREF oref, OBJECTREF *porefResult);
private:
- OBJECTREF GetCCWObject();
-
OBJECTREF FindOrCreateObjectRefInternal(IUnknown **ppIncomingIP, MethodTable *pIncomingItfMT, bool bIncomingIPAddRefed);
VOID CreateObjectRef(BOOL fDuplicate, OBJECTREF *pComObj, IUnknown **ppIncomingIP, MethodTable *pIncomingItfMT, bool bIncomingIPAddRefed);
void IReferenceUnbox(IUnknown **ppIncomingIP, OBJECTREF *poref, bool bIncomingIPAddRefed);
DWORD m_flags;
ICOMInterfaceMarshalerCallback *m_pCallback; // Callback to call when we created a RCW or got back RCW from cache
-
- // For Transparent Proxys
- ADID m_dwServerDomainId;
- DWORD m_dwServerSyncBlockIndex;
};
{
GCX_COOP();
- ENTER_DOMAIN_PTR(pCompilationDomain,ADV_COMPILATION)
- {
- pCompilationDomain->CreateFusionContext();
+ pCompilationDomain->CreateFusionContext();
- pCompilationDomain->SetFriendlyName(W("Compilation Domain"));
- SystemDomain::System()->LoadDomain(pCompilationDomain);
- }
- END_DOMAIN_TRANSITION;
+ pCompilationDomain->SetFriendlyName(W("Compilation Domain"));
+ SystemDomain::System()->LoadDomain(pCompilationDomain);
}
COOPERATIVE_TRANSITION_END();
return S_OK;
}
-HRESULT MakeCrossDomainCallbackWorker(
- CROSS_DOMAIN_CALLBACK pfnCallback,
- LPVOID pArgs)
-{
- STATIC_CONTRACT_MODE_COOPERATIVE;
-
- return pfnCallback(pArgs);
-}
-
-HRESULT CEECompileInfo::MakeCrossDomainCallback(
- ICorCompilationDomain* pDomain,
- CROSS_DOMAIN_CALLBACK pfnCallback,
- LPVOID pArgs)
-{
- STANDARD_VM_CONTRACT;
-
- HRESULT hrRetVal = E_UNEXPECTED;
-
- COOPERATIVE_TRANSITION_BEGIN();
-
- {
- // Switch to cooperative mode to switch appdomains
- GCX_COOP();
-
- ENTER_DOMAIN_PTR((CompilationDomain*)pDomain,ADV_COMPILATION)
- {
- //
- // Switch to preemptive mode on before calling back into
- // the zapper
- //
-
- GCX_PREEMP();
-
- hrRetVal = MakeCrossDomainCallbackWorker(pfnCallback, pArgs);
- }
- END_DOMAIN_TRANSITION;
- }
-
- COOPERATIVE_TRANSITION_END();
-
- return hrRetVal;
-}
-
#ifdef TRITON_STRESS_NEED_IMPL
int LogToSvcLogger(LPCWSTR format, ...)
{
BOOL fForceProfiling,
BOOL fForceInstrument);
- HRESULT MakeCrossDomainCallback(
- ICorCompilationDomain* pDomain,
- CROSS_DOMAIN_CALLBACK pfnCallback,
- LPVOID pArgs);
-
HRESULT DestroyDomain(ICorCompilationDomain *pDomain);
HRESULT LoadAssemblyByPath(LPCWSTR wzPath,
}
CONTRACTL_END;
- AppDomain *ad = SystemDomain::GetAppDomainFromId(internal->GetKickOffDomainId(), ADV_CURRENTAD);
+ AppDomain *ad = ::GetAppDomain();
m_Threadable = ad->CreateHandle(threadable);
m_ThreadStartArg = ad->CreateHandle(threadStartArg);
// we can adjust the delegate we are going to invoke on.
_ASSERTE(GetThread() == pThread); // Now that it's started
- ManagedThreadBase::KickOff(pThread->GetKickOffDomainId(), KickOffThread_Worker, &args);
+ ManagedThreadBase::KickOff(KickOffThread_Worker, &args);
// If TS_FailStarted is set then the args are deleted in ThreadNative::StartInner
if ((args.share) && !pThread->HasThreadState(Thread::TS_FailStarted))
}
#endif
- SetObjectReferenceUnchecked( (OBJECTREF *)&m_Delegate, delegate );
+ SetObjectReference( (OBJECTREF *)&m_Delegate, delegate );
// If the delegate is being set then initialize the other data members.
if (m_Delegate != NULL)
/*****************************************************************************************************/
// Caller has to GC protect Objectrefs being passed in
-DelegateInfo *DelegateInfo::MakeDelegateInfo(AppDomain *pAppDomain,
- OBJECTREF *state,
+DelegateInfo *DelegateInfo::MakeDelegateInfo(OBJECTREF *state,
OBJECTREF *waitEvent,
OBJECTREF *registeredWaitHandle)
{
PRECONDITION(state == NULL || IsProtectedByGCFrame(state));
PRECONDITION(waitEvent == NULL || IsProtectedByGCFrame(waitEvent));
PRECONDITION(registeredWaitHandle == NULL || IsProtectedByGCFrame(registeredWaitHandle));
- PRECONDITION(CheckPointer(pAppDomain));
INJECT_FAULT(COMPlusThrowOM());
}
CONTRACTL_END;
DelegateInfoHolder delegateInfo = (DelegateInfo*) ThreadpoolMgr::GetRecycledMemory(ThreadpoolMgr::MEMTYPE_DelegateInfo);
-
- delegateInfo->m_appDomainId = pAppDomain->GetId();
+
+ AppDomain* pAppDomain = ::GetAppDomain();
if (state != NULL)
delegateInfo->m_stateHandle = pAppDomain->CreateHandle(*state);
RegisterWaitForSingleObjectCallback_Args args = { ((DelegateInfo*) delegateInfo), TimerOrWaitFired };
- ManagedThreadBase::ThreadPool(((DelegateInfo*) delegateInfo)->m_appDomainId, RegisterWaitForSingleObjectCallback_Worker, &args);
+ ManagedThreadBase::ThreadPool(RegisterWaitForSingleObjectCallback_Worker, &args);
// We should have released all locks.
_ASSERTE(g_fEEShutDown || pThread->m_dwLockCount == 0 || pThread->m_fRudeAborted);
Thread* pCurThread = GetThread();
_ASSERTE( pCurThread);
- AppDomain* appDomain = pCurThread->GetDomain();
- _ASSERTE(appDomain);
-
- DelegateInfoHolder delegateInfo = DelegateInfo::MakeDelegateInfo(appDomain,
+ DelegateInfoHolder delegateInfo = DelegateInfo::MakeDelegateInfo(
&gc.state,
(OBJECTREF *)&gc.waitObject,
&gc.registeredWaitObject);
{
// Create a GCHandle in the WaitInfo, so that it can hold on to the safe handle
pWaitInfo->ExternalEventSafeHandle = GetAppDomain()->CreateHandle(NULL);
- pWaitInfo->handleOwningAD = GetAppDomain()->GetId();
// Holder will now release objecthandle in face of exceptions
wiHolder.Assign(pWaitInfo);
GCX_COOP();
BindIoCompletion_Args args = {ErrorCode, numBytesTransferred, lpOverlapped};
- ManagedThreadBase::ThreadPool((ADID)DefaultADID, BindIoCompletionCallBack_Worker, &args);
+ ManagedThreadBase::ThreadPool(BindIoCompletionCallBack_Worker, &args);
LOG((LF_INTEROP, LL_INFO10000, "Leaving IO_CallBackStub thread 0x%x retCode 0x%x, overlap 0x%x\n", pThread, ErrorCode, lpOverlapped));
// We should have released all locks.
GCX_COOP();
ThreadpoolMgr::TimerInfoContext* pTimerInfoContext = (ThreadpoolMgr::TimerInfoContext*)callbackState;
- ManagedThreadBase::ThreadPool(pTimerInfoContext->AppDomainId, AppDomainTimerCallback_Worker, pTimerInfoContext);
+ ManagedThreadBase::ThreadPool(AppDomainTimerCallback_Worker, pTimerInfoContext);
// We should have released all locks.
_ASSERTE(g_fEEShutDown || pThread->m_dwLockCount == 0 || pThread->m_fRudeAborted);
_ASSERTE(timerId >= 0);
AppDomain* pAppDomain = GetThread()->GetDomain();
- ADID adid = pAppDomain->GetId();
ThreadpoolMgr::TimerInfoContext* timerContext = new ThreadpoolMgr::TimerInfoContext();
- timerContext->AppDomainId = adid;
timerContext->TimerId = timerId;
NewHolder<ThreadpoolMgr::TimerInfoContext> timerContextHolder(timerContext);
}
else
{
- *pdwAppDomainId = SystemDomain::GetCurrentDomain()->GetId().m_dwId;
+ *pdwAppDomainId = DefaultADID;
}
}
}
}
- if(pCurDomain->GetId().m_dwId != DefaultADID)
- {
- return HOST_E_INVALIDOPERATION;
- }
-
INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
INSTALL_UNWIND_AND_CONTINUE_HANDLER;
_ASSERTE (!pThread->PreemptiveGCDisabled());
- _ASSERTE (SystemDomain::GetCurrentDomain()->GetId().m_dwId == DefaultADID);
-
INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
INSTALL_UNWIND_AND_CONTINUE_HANDLER;
if( pCallback == NULL)
return E_POINTER;
+ // This is currently supported in default domain only
+ if (dwAppDomainId != DefaultADID)
+ return HOST_E_INVALIDOPERATION;
+
CONTRACTL
{
NOTHROW;
BEGIN_ENTRYPOINT_NOTHROW;
BEGIN_EXTERNAL_ENTRYPOINT(&hr);
GCX_COOP_THREAD_EXISTS(GET_THREAD());
- ENTER_DOMAIN_ID(ADID(dwAppDomainId))
+
+ // We are calling an unmanaged function pointer, either an unmanaged function, or a marshaled out delegate.
+ // The thread should be in preemptive mode.
{
- // We are calling an unmanaged function pointer, either an unmanaged function, or a marshaled out delegate.
- // The thread should be in preemptive mode.
GCX_PREEMP();
hr=ExecuteInAppDomainHelper (pCallback, cookie);
}
- END_DOMAIN_TRANSITION;
END_EXTERNAL_ENTRYPOINT;
END_ENTRYPOINT_NOTHROW;
}
#endif
- *pAppDomainID=pDomain->GetId().m_dwId;
+ *pAppDomainID=DefaultADID;
m_fAppDomainCreated = TRUE;
if(wszMethodName == NULL)
return E_INVALIDARG;
+ // This is currently supported in default domain only
+ if (appDomainID != DefaultADID)
+ return HOST_E_INVALIDOPERATION;
+
BEGIN_ENTRYPOINT_NOTHROW;
BEGIN_EXTERNAL_ENTRYPOINT(&hr);
MAKE_UTF8PTR_FROMWIDE(szClassName, wszClassName);
MAKE_UTF8PTR_FROMWIDE(szMethodName, wszMethodName);
- ADID id;
- id.m_dwId=appDomainID;
-
- ENTER_DOMAIN_ID(id)
-
- GCX_PREEMP();
+ {
+ GCX_PREEMP();
- AssemblySpec spec;
- spec.Init(szAssemblyName);
- Assembly* pAsm=spec.LoadAssembly(FILE_ACTIVE);
+ AssemblySpec spec;
+ spec.Init(szAssemblyName);
+ Assembly* pAsm=spec.LoadAssembly(FILE_ACTIVE);
- TypeHandle th=pAsm->GetLoader()->LoadTypeByNameThrowing(pAsm,NULL,szClassName);
- MethodDesc* pMD=NULL;
+ TypeHandle th=pAsm->GetLoader()->LoadTypeByNameThrowing(pAsm,NULL,szClassName);
+ MethodDesc* pMD=NULL;
- if (!th.IsTypeDesc())
- {
- pMD = MemberLoader::FindMethodByName(th.GetMethodTable(), szMethodName, MemberLoader::FM_Unique);
- if (pMD == NULL)
+ if (!th.IsTypeDesc())
{
- // try again without the FM_Unique flag (error path)
- pMD = MemberLoader::FindMethodByName(th.GetMethodTable(), szMethodName, MemberLoader::FM_Default);
- if (pMD != NULL)
+ pMD = MemberLoader::FindMethodByName(th.GetMethodTable(), szMethodName, MemberLoader::FM_Unique);
+ if (pMD == NULL)
{
- // the method exists but is overloaded
- ThrowHR(COR_E_AMBIGUOUSMATCH);
+ // try again without the FM_Unique flag (error path)
+ pMD = MemberLoader::FindMethodByName(th.GetMethodTable(), szMethodName, MemberLoader::FM_Default);
+ if (pMD != NULL)
+ {
+ // the method exists but is overloaded
+ ThrowHR(COR_E_AMBIGUOUSMATCH);
+ }
}
}
- }
-
- if (pMD==NULL || !pMD->IsStatic() || pMD->ContainsGenericVariables())
- ThrowHR(COR_E_MISSINGMETHOD);
- UMEntryThunk *pUMEntryThunk = pMD->GetLoaderAllocator()->GetUMEntryThunkCache()->GetUMEntryThunk(pMD);
- *fnPtr = (INT_PTR)pUMEntryThunk->GetCode();
+ if (pMD==NULL || !pMD->IsStatic() || pMD->ContainsGenericVariables())
+ ThrowHR(COR_E_MISSINGMETHOD);
- END_DOMAIN_TRANSITION;
+ UMEntryThunk *pUMEntryThunk = pMD->GetLoaderAllocator()->GetUMEntryThunkCache()->GetUMEntryThunk(pMD);
+ *fnPtr = (INT_PTR)pUMEntryThunk->GetCode();
+ }
END_EXTERNAL_ENTRYPOINT;
}
}
- if(SystemDomain::GetCurrentDomain()->GetId().m_dwId != DefaultADID)
- {
- return HOST_E_INVALIDOPERATION;
- }
-
return DllGetActivationFactoryImpl(NULL, wszTypeName, NULL, factory);
#else
return E_NOTIMPL;
if (pLoaderAllocatorOfValue != m_pLoaderAllocator)
{
gc.hashKeyToTrackers = (LAHASHKEYTOTRACKERSREF)AllocateObject(MscorlibBinder::GetExistingClass(CLASS__LAHASHKEYTOTRACKERS));
- SetObjectReference(&gc.hashKeyToTrackers->_laLocalKeyValueStore, gc.keyValueStore, GetAppDomain());
+ SetObjectReference(&gc.hashKeyToTrackers->_laLocalKeyValueStore, gc.keyValueStore);
gc.hashKeyEntry = gc.hashKeyToTrackers;
}
else
{
if (gc.hashKeyToTrackers != NULL)
{
- SetObjectReference(&gc.hashKeyToTrackers->_laLocalKeyValueStore, gc.keyValueStore, GetAppDomain());
+ SetObjectReference(&gc.hashKeyToTrackers->_laLocalKeyValueStore, gc.keyValueStore);
}
else
{
{
// Nothing has yet caused the trackers proxy object to be setup. Create it now, and update the keyToTrackersHash
gc.hashKeyToTrackers = (LAHASHKEYTOTRACKERSREF)AllocateObject(MscorlibBinder::GetExistingClass(CLASS__LAHASHKEYTOTRACKERS));
- SetObjectReference(&gc.hashKeyToTrackers->_laLocalKeyValueStore, gc.keyValueStore, GetAppDomain());
+ SetObjectReference(&gc.hashKeyToTrackers->_laLocalKeyValueStore, gc.keyValueStore);
gc.hashKeyEntry = gc.hashKeyToTrackers;
gc.keyToTrackersHash.SetElement(index, gc.hashKeyEntry);
}
if (gc.hashKeyToTrackers->_trackerOrTrackerSet == NULL)
{
gc.dependentTracker = GetDependentTrackerForLoaderAllocator(pValueLoaderAllocator);
- SetObjectReference(&gc.hashKeyToTrackers->_trackerOrTrackerSet, gc.dependentTracker, GetAppDomain());
+ SetObjectReference(&gc.hashKeyToTrackers->_trackerOrTrackerSet, gc.dependentTracker);
}
else if (gc.hashKeyToTrackers->_trackerOrTrackerSet->GetMethodTable() == MscorlibBinder::GetExistingClass(CLASS__LAHASHDEPENDENTHASHTRACKER))
{
gc.dependentTracker = GetDependentTrackerForLoaderAllocator(pValueLoaderAllocator);
if (!gc.dependentTrackerMaybe->IsLoaderAllocatorLive())
{
- SetObjectReference(&gc.hashKeyToTrackers->_trackerOrTrackerSet, gc.dependentTracker, GetAppDomain());
+ SetObjectReference(&gc.hashKeyToTrackers->_trackerOrTrackerSet, gc.dependentTracker);
}
else
{
{
arr->SetAt(index, (OBJECTREF)gc.dependentTrackerMaybe);
});
- SetObjectReference(&gc.hashKeyToTrackers->_trackerOrTrackerSet, gc.dependentTrackerHash.GetGCHeapRef(), GetAppDomain());
+ SetObjectReference(&gc.hashKeyToTrackers->_trackerOrTrackerSet, gc.dependentTrackerHash.GetGCHeapRef());
}
}
}
if (type == SERIALIZATION_TYPE_TYPE || type == SERIALIZATION_TYPE_STRING)
{
- SetObjectReference((OBJECTREF*)&pValue->m_enumOrTypeName, gc.string, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&pValue->m_enumOrTypeName, gc.string);
}
else if (type == SERIALIZATION_TYPE_ENUM)
{
- SetObjectReference((OBJECTREF*)&pValue->m_type.m_enumName, gc.string, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&pValue->m_type.m_enumName, gc.string);
}
else if (type == SERIALIZATION_TYPE_SZARRAY)
{
- SetObjectReference((OBJECTREF*)&pValue->m_value, gc.array, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&pValue->m_value, gc.array);
if (pValue->m_type.m_arrayType == SERIALIZATION_TYPE_ENUM)
- SetObjectReference((OBJECTREF*)&pValue->m_type.m_enumName, gc.string, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&pValue->m_type.m_enumName, gc.string);
}
}
// Allocate memory for the MethodInfo objects
BASEARRAYREF methodInfoArray = (BASEARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_I, data.cElements);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgMethodHandle), (OBJECTREF)methodInfoArray,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgMethodHandle), (OBJECTREF)methodInfoArray);
// Allocate memory for the Offsets
OBJECTREF offsets = AllocatePrimitiveArray(ELEMENT_TYPE_I4, data.cElements);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiOffset), (OBJECTREF)offsets,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiOffset), (OBJECTREF)offsets);
// Allocate memory for the ILOffsets
OBJECTREF ilOffsets = AllocatePrimitiveArray(ELEMENT_TYPE_I4, data.cElements);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiILOffset), (OBJECTREF)ilOffsets,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiILOffset), (OBJECTREF)ilOffsets);
// Allocate memory for the array of assembly file names
PTRARRAYREF assemblyPathArray = (PTRARRAYREF) AllocateObjectArray(data.cElements, g_pStringClass);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgAssemblyPath), (OBJECTREF)assemblyPathArray,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgAssemblyPath), (OBJECTREF)assemblyPathArray);
// Allocate memory for the array of assemblies
PTRARRAYREF assemblyArray = (PTRARRAYREF) AllocateObjectArray(data.cElements, g_pObjectClass);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgAssembly), (OBJECTREF)assemblyArray,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgAssembly), (OBJECTREF)assemblyArray);
// Allocate memory for the LoadedPeAddress
BASEARRAYREF loadedPeAddressArray = (BASEARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_I, data.cElements);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgLoadedPeAddress), (OBJECTREF)loadedPeAddressArray,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgLoadedPeAddress), (OBJECTREF)loadedPeAddressArray);
// Allocate memory for the LoadedPeSize
OBJECTREF loadedPeSizeArray = AllocatePrimitiveArray(ELEMENT_TYPE_I4, data.cElements);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiLoadedPeSize), (OBJECTREF)loadedPeSizeArray,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiLoadedPeSize), (OBJECTREF)loadedPeSizeArray);
// Allocate memory for the InMemoryPdbAddress
BASEARRAYREF inMemoryPdbAddressArray = (BASEARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_I, data.cElements);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgInMemoryPdbAddress), (OBJECTREF)inMemoryPdbAddressArray,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgInMemoryPdbAddress), (OBJECTREF)inMemoryPdbAddressArray);
// Allocate memory for the InMemoryPdbSize
OBJECTREF inMemoryPdbSizeArray = AllocatePrimitiveArray(ELEMENT_TYPE_I4, data.cElements);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiInMemoryPdbSize), (OBJECTREF)inMemoryPdbSizeArray,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiInMemoryPdbSize), (OBJECTREF)inMemoryPdbSizeArray);
// Allocate memory for the MethodTokens
OBJECTREF methodTokens = AllocatePrimitiveArray(ELEMENT_TYPE_I4, data.cElements);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiMethodToken), (OBJECTREF)methodTokens,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiMethodToken), (OBJECTREF)methodTokens);
// Allocate memory for the Filename string objects
PTRARRAYREF filenameArray = (PTRARRAYREF) AllocateObjectArray(data.cElements, g_pStringClass);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgFilename), (OBJECTREF)filenameArray,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgFilename), (OBJECTREF)filenameArray);
// Allocate memory for the LineNumbers
OBJECTREF lineNumbers = AllocatePrimitiveArray(ELEMENT_TYPE_I4, data.cElements);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiLineNumber), (OBJECTREF)lineNumbers,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiLineNumber), (OBJECTREF)lineNumbers);
// Allocate memory for the ColumnNumbers
OBJECTREF columnNumbers = AllocatePrimitiveArray(ELEMENT_TYPE_I4, data.cElements);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiColumnNumber), (OBJECTREF)columnNumbers,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiColumnNumber), (OBJECTREF)columnNumbers);
// Allocate memory for the flag indicating if this frame represents the last one from a foreign
// exception stack trace provided we have any such frames. Otherwise, set it to null.
{
IsLastFrameFromForeignStackTraceFlags = AllocatePrimitiveArray(ELEMENT_TYPE_BOOLEAN, data.cElements);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiLastFrameFromForeignExceptionStackTrace), (OBJECTREF)IsLastFrameFromForeignStackTraceFlags,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiLastFrameFromForeignExceptionStackTrace), (OBJECTREF)IsLastFrameFromForeignStackTraceFlags);
}
else
{
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiLastFrameFromForeignExceptionStackTrace), NULL,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->rgiLastFrameFromForeignExceptionStackTrace), NULL);
}
// Determine if there are any dynamic methods in the stack trace. If there are,
if (iNumDynamics)
{
PTRARRAYREF dynamicDataArray = (PTRARRAYREF) AllocateObjectArray(iNumDynamics, g_pObjectClass);
- SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->dynamicMethods), (OBJECTREF)dynamicDataArray,
- pStackFrameHelper->GetAppDomain());
+ SetObjectReference( (OBJECTREF *)&(pStackFrameHelper->dynamicMethods), (OBJECTREF)dynamicDataArray);
}
int iNumValidFrames = 0;
g_pDebugInterface->SendCustomDebuggerNotification(pThread, pDomainFile, classToken);
pThread->ClearThreadCurrNotification();
- TESTHOOKCALL(AppDomainCanBeUnloaded(pThread->GetDomain()->GetId().m_dwId, FALSE));
+ TESTHOOKCALL(AppDomainCanBeUnloaded(DefaultADID, FALSE));
if (pThread->IsAbortRequested())
{
pThread->HandleThreadAbort();
return GetThread ();
}
-AppDomain *GetAppDomainForObject(UINT_PTR obj)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- return ((Object*)obj)->GetAppDomain();
-}
-
-ADIndex GetAppDomainIndexForObject(UINT_PTR obj)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- return ((Object*)obj)->GetHeader()->GetAppDomainIndex();
-}
-
-AppDomain *GetAppDomainForObjectHeader(UINT_PTR hdr)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- ADIndex indx = ((ObjHeader*)hdr)->GetAppDomainIndex();
- if (!indx.m_dwIndex)
- {
- return NULL;
- }
-
- return SystemDomain::GetAppDomainAtIndex(indx);
-}
-
-ADIndex GetAppDomainIndexForObjectHeader(UINT_PTR hdr)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- return ((ObjHeader*)hdr)->GetAppDomainIndex();
-}
-
SyncBlock *GetSyncBlockForObject(UINT_PTR obj)
{
CONTRACTL
struct PrintCallbackData {
BOOL toStdout;
- BOOL withAppDomain;
#ifdef _DEBUG
BOOL toLOG;
#endif
{
MethodTable * pMT = pMD->GetMethodTable();
- if (pCBD->withAppDomain)
- {
- if(_snwprintf_s(&buff[wcslen(buff)],
- nLen - wcslen(buff) - 1,
- _TRUNCATE,
- W("{[%3.3x] %s} "),
- pCF->GetAppDomain()->GetId().m_dwId,
- pCF->GetAppDomain()->GetFriendlyName(FALSE)) < 0)
- {
- return SWA_CONTINUE;
- }
- }
-
DefineFullyQualifiedNameForClass();
LPCUTF8 clsName = GetFullyQualifiedNameForClass(pMT);
CONTRACTL_END;
WszOutputDebugString(W("***************************************************\n"));
- PrintCallbackData cbd = {0, 0};
+ PrintCallbackData cbd = {0};
GetThread()->StackWalkFrames(PrintStackTraceCallback, &cbd, ALLOW_ASYNC_STACK_WALK, 0);
}
}
CONTRACTL_END;
- PrintCallbackData cbd = {1, 0};
+ PrintCallbackData cbd = {1};
GetThread()->StackWalkFrames(PrintStackTraceCallback, &cbd, ALLOW_ASYNC_STACK_WALK, 0);
}
}
CONTRACTL_END;
- PrintCallbackData cbd = {0, 0, 1};
- GetThread()->StackWalkFrames(PrintStackTraceCallback, &cbd, ALLOW_ASYNC_STACK_WALK, 0);
-}
-#endif
-
-void PrintStackTraceWithAD()
-{
- CONTRACTL
- {
- DISABLED(NOTHROW);
- DISABLED(GC_TRIGGERS);
- }
- CONTRACTL_END;
-
- WszOutputDebugString(W("***************************************************\n"));
PrintCallbackData cbd = {0, 1};
GetThread()->StackWalkFrames(PrintStackTraceCallback, &cbd, ALLOW_ASYNC_STACK_WALK, 0);
}
-
-void PrintStackTraceWithADToStdout()
-{
- CONTRACTL
- {
- DISABLED(NOTHROW);
- DISABLED(GC_TRIGGERS);
- }
- CONTRACTL_END;
-
- PrintCallbackData cbd = {1, 1};
- GetThread()->StackWalkFrames(PrintStackTraceCallback, &cbd, ALLOW_ASYNC_STACK_WALK, 0);
-}
-
-#ifdef _DEBUG
-void PrintStackTraceWithADToLog()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- PrintCallbackData cbd = {0, 1, 1};
- GetThread()->StackWalkFrames(PrintStackTraceCallback, &cbd, ALLOW_ASYNC_STACK_WALK, 0);
-}
-
-void PrintStackTraceWithADToLog(Thread *pThread)
-{
- CONTRACTL
- {
- DISABLED(NOTHROW);
- DISABLED(GC_TRIGGERS);
- }
- CONTRACTL_END;
-
- PrintCallbackData cbd = {0, 1, 1};
- pThread->StackWalkFrames(PrintStackTraceCallback, &cbd, ALLOW_ASYNC_STACK_WALK, 0);
-}
#endif
/*******************************************************************/
{
WRAPPER_NO_CONTRACT;
- PrintCallbackData cbd = {0, 0, 1};
+ PrintCallbackData cbd = {0, 1};
GetThread()->StackWalkFrames(PrintStackTraceCallback, &cbd,ALLOW_ASYNC_STACK_WALK, 0);
}
#endif
struct DelegateInfo
{
- ADID m_appDomainId;
OBJECTHANDLE m_stateHandle;
OBJECTHANDLE m_eventHandle;
OBJECTHANDLE m_registeredWaitHandle;
}
#endif
- static DelegateInfo *MakeDelegateInfo(AppDomain *pAppDomain,
- OBJECTREF *state,
+ static DelegateInfo *MakeDelegateInfo(OBJECTREF *state,
OBJECTREF *waitEvent,
OBJECTREF *registeredWaitObject);
};
// If the variant is a byref static array, then remember the property value.
if (IsVariantByrefStaticArray(pSrcOleVariant))
- SetObjectReference(&pObjs->ByrefStaticArrayBackupPropVal, pObjs->PropVal, pAppDomain);
+ SetObjectReference(&pObjs->ByrefStaticArrayBackupPropVal, pObjs->PropVal);
}
DispatchMemberInfo* pInfo = new DispatchMemberInfo(this, DispID, strMemberName, MemberInfoObj);
- AppDomain* pDomain = SystemDomain::GetAppDomainFromId(m_pSimpleWrapperOwner->GetDomainID(), ADV_CURRENTAD);
-
pInfo->SetHandle(GetLoaderAllocator()->AllocateHandle(MemberInfoObj));
RETURN pInfo;
}
if (pDelegate == NULL)
- SetObjectReference(pDestObj, NULL, GetAppDomain());
+ SetObjectReference(pDestObj, NULL);
else
- SetObjectReference(pDestObj, COMDelegate::ConvertToDelegate(pDelegate, m_pDelegateMT), GetAppDomain());
+ SetObjectReference(pDestObj, COMDelegate::ConvertToDelegate(pDelegate, m_pDelegateMT));
}
void DispParamDelegateMarshaler::MarshalManagedToNative(OBJECTREF *pSrcObj, VARIANT *pDestVar)
miHolder.Assign(pMarshInfo);
pMarshInfo->LoadTimeInit(pMD);
- pThunk->LoadTimeInit(NULL, NULL, pMarshInfo, pMD, m_pDomain->GetId());
+ pThunk->LoadTimeInit(NULL, NULL, pMarshInfo, pMD);
// add it to the cache
CacheElement element;
VOID LoadTimeInit(PCODE pManagedTarget,
OBJECTHANDLE pObjectHandle,
UMThunkMarshInfo *pUMThunkMarshInfo,
- MethodDesc *pMD,
- ADID dwDomainId)
+ MethodDesc *pMD)
{
CONTRACTL
{
m_pManagedTarget = pManagedTarget;
m_pObjectHandle = pObjectHandle;
m_pUMThunkMarshInfo = pUMThunkMarshInfo;
- m_dwDomainId = dwDomainId;
m_pMD = pMD; // For debugging and profiling, so they can identify the target
RETURN m_pMD;
}
- ADID GetDomainId() const
- {
- CONTRACT (ADID)
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(m_state == kRunTimeInited || m_state == kLoadTimeInited);
- }
- CONTRACT_END;
-
- RETURN m_dwDomainId;
- }
-
static DWORD GetOffsetOfMethodDesc()
{
LIMITED_METHOD_CONTRACT;
UMEntryThunk *m_pNextFreeThunk;
};
- ADID m_dwDomainId; // appdomain of module (cached for fast access)
#ifdef _DEBUG
DWORD m_state; // the initialization state
#endif
// ICorProfilerInfo2::DoStackSnapshot! And that dude is called asynchronously and
// must therefore never cause a GC.
// Other reasons for notrigger: also called by notrigger dudes Thread::SysStartSuspendForDebug,
- // CheckSuspended, Thread::IsRunningIn, Thread::IsExecutingWithinCer, Thread::IsExecutingWithinCer,
+ // CheckSuspended, Thread::IsExecutingWithinCer, Thread::IsExecutingWithinCer,
// UnwindFrames
GC_NOTRIGGER;
IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager();
OBJECTREF pHelperObj = ObjectToOBJECTREF(mgr->GetDependentHandleSecondary(pEntry->m_FieldData));
OBJECTREF *pHelperRef = (OBJECTREF *)pHelperField->GetAddress( pHelperObj->GetAddress() );
- SetObjectReference( pHelperRef, obj, pDomain );
+ SetObjectReference( pHelperRef, obj);
GCPROTECT_END ();
}
OBJECTREF **pOR = (OBJECTREF**)&pEntry->m_FieldData;
*pOR = pDomain->AllocateStaticFieldObjRefPtrs(1);
OBJECTREF obj = AllocateObject(pFD->GetFieldTypeHandleThrowing().GetMethodTable());
- SetObjectReference( *pOR, obj, pDomain );
+ SetObjectReference( *pOR, obj);
}
else if (pFD->GetFieldType() == ELEMENT_TYPE_CLASS)
{
}
CONTRACTL_END;
- // Enumerate only active app domains (first parameter). We use the unsafe
- // iterator here because this method is called under the threadstore lock
- // and it's safe to use while the runtime is suspended.
- UnsafeAppDomainIterator appIter(TRUE);
- appIter.Init();
- while (appIter.Next())
{
- AppDomain *domain = appIter.GetDomain();
+ AppDomain *domain = ::GetAppDomain(); // There is only 1 AppDomain, so no iterator here.
AppDomain::AssemblyIterator assemblyIter = domain->IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoaded|kIncludeExecution));
CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad)
{
- FireEtwAppDomainLoad_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, pBaseDomain->GetId().m_dwId, GetClrInstanceId());
+ FireEtwAppDomainLoad_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, DefaultADID, GetClrInstanceId());
}
else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)
{
- FireEtwAppDomainUnload_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, pBaseDomain->GetId().m_dwId, GetClrInstanceId());
+ FireEtwAppDomainUnload_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, DefaultADID, GetClrInstanceId());
}
else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart)
{
- FireEtwAppDomainDCStart_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, pBaseDomain->GetId().m_dwId, GetClrInstanceId());
+ FireEtwAppDomainDCStart_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, DefaultADID, GetClrInstanceId());
}
else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd)
{
- FireEtwAppDomainDCEnd_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, pBaseDomain->GetId().m_dwId, GetClrInstanceId());
+ FireEtwAppDomainDCEnd_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, DefaultADID, GetClrInstanceId());
}
else
{
MethodDescCallSite getResourceStringLocal(METHOD__ENVIRONMENT__GET_RESOURCE_STRING_LOCAL);
// Call Environment::GetResourceStringLocal(String name). Returns String value (or maybe null)
-
- ENTER_DOMAIN_PTR(SystemDomain::System()->DefaultDomain(),ADV_DEFAULTAD);
-
// Don't need to GCPROTECT pArgs, since it's not used after the function call.
ARG_SLOT pArgs[1] = { ObjToArgSlot(gc.key) };
gc.ret = getResourceStringLocal.Call_RetSTRINGREF(pArgs);
- END_DOMAIN_TRANSITION;
-
GCPROTECT_END();
return gc.ret;
#define HELPER_METHOD_FRAME_BEGIN_EX(ret, helperFrame, gcpoll, allowGC) \
HELPER_METHOD_FRAME_BEGIN_EX_BODY(ret, helperFrame, gcpoll, allowGC) \
- TESTHOOKCALL(AppDomainCanBeUnloaded(GET_THREAD()->GetDomain()->GetId().m_dwId,!allowGC)); \
+ TESTHOOKCALL(AppDomainCanBeUnloaded(DefaultADID,!allowGC)); \
/* <TODO>TODO TURN THIS ON!!! </TODO> */ \
/* gcpoll; */ \
INSTALL_MANAGED_EXCEPTION_DISPATCHER; \
#define HELPER_METHOD_FRAME_END_EX(gcpoll,allowGC) \
UNINSTALL_UNWIND_AND_CONTINUE_HANDLER; \
UNINSTALL_MANAGED_EXCEPTION_DISPATCHER; \
- TESTHOOKCALL(AppDomainCanBeUnloaded(GET_THREAD()->GetDomain()->GetId().m_dwId,!allowGC)); \
+ TESTHOOKCALL(AppDomainCanBeUnloaded(DefaultADID,!allowGC)); \
HELPER_METHOD_FRAME_END_EX_BODY(gcpoll,allowGC);
#define HELPER_METHOD_FRAME_END_EX_NOTHROW(gcpoll,allowGC) \
{
OBJECTREF ref = ObjectToOBJECTREF(*(Object**)pInVal);
- SetObjectReference((OBJECTREF*)pFieldAddress, ref,
- o->GetAppDomain());
+ SetObjectReference((OBJECTREF*)pFieldAddress, ref);
}
else if (fieldType == ELEMENT_TYPE_VALUETYPE)
{
// The Approximate MT is enough to do the copy
CopyValueClass(pFieldAddress,
(void*)pInVal,
- LookupFieldTypeHandle().GetMethodTable(),
- o->GetAppDomain());
+ LookupFieldTypeHandle().GetMethodTable());
}
else
{
GCPROTECT_BEGIN(objRef);
OBJECTREF *pObjRef = (OBJECTREF *)GetCurrentStaticAddress();
- SetObjectReference(pObjRef, objRef, GetAppDomain());
+ SetObjectReference(pObjRef, objRef);
GCPROTECT_END();
}
{
pCLRValue = *(OBJECTREF*)(internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData));
pFM->UpdateNative(&pCLRValue, pNativeData + pFM->GetExternalOffset(), ppCleanupWorkListOnStack);
- SetObjectReferenceUnchecked( (OBJECTREF*) (internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData)), pCLRValue);
+ SetObjectReference( (OBJECTREF*) (internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData)), pCLRValue);
}
// The cleanup work list is not used to clean up the native contents. It is used
{
gc.pOldCLRValue = *(OBJECTREF*)(internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData));
pFM->UpdateCLR( pNativeData + pFM->GetExternalOffset(), &gc.pCLRValue, &gc.pOldCLRValue );
- SetObjectReferenceUnchecked( (OBJECTREF*) (internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData)), gc.pCLRValue );
+ SetObjectReference( (OBJECTREF*) (internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData)), gc.pCLRValue );
}
((BYTE*&)pFM) += MAXFIELDMARSHALERSIZE;
}
}
-struct FinalizeAllObjects_Args {
- OBJECTREF fobj;
- int bitToCheck;
-};
-
-void FinalizerThread::FinalizeAllObjects_Wrapper(void *ptr)
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_GC_TRIGGERS;
- STATIC_CONTRACT_MODE_COOPERATIVE;
-
- FinalizeAllObjects_Args *args = (FinalizeAllObjects_Args *) ptr;
- _ASSERTE(args->fobj);
- Object *fobj = OBJECTREFToObject(args->fobj);
- args->fobj = NULL; // don't want to do this guy again, if we take an exception here:
- args->fobj = ObjectToOBJECTREF(FinalizeAllObjects(fobj, args->bitToCheck));
-}
-
-// The following is inadequate when we have multiple Finalizer threads in some future release.
-// Instead, we will have to store this in TLS or pass it through the call tree of finalization.
-// It is used to tie together the base exception handling and the AppDomain transition exception
-// handling for this thread.
-static struct ManagedThreadCallState *pThreadTurnAround;
-
-Object * FinalizerThread::DoOneFinalization(Object* fobj, Thread* pThread,int bitToCheck,bool *pbTerminate)
+void FinalizerThread::DoOneFinalization(Object* fobj, Thread* pThread)
{
STATIC_CONTRACT_THROWS;
STATIC_CONTRACT_GC_TRIGGERS;
STATIC_CONTRACT_MODE_COOPERATIVE;
- bool fTerminate=false;
- Object *pReturnObject = NULL;
-
-
- AppDomain* targetAppDomain = fobj->GetAppDomain();
- AppDomain* currentDomain = pThread->GetDomain();
- if (! targetAppDomain)
+ class ResetFinalizerStartTime
{
- // if can't get into domain to finalize it, then it must be agile so finalize in current domain
- targetAppDomain = currentDomain;
- }
-
- if (targetAppDomain == currentDomain)
- {
- class ResetFinalizerStartTime
+ public:
+ ResetFinalizerStartTime()
{
- public:
- ResetFinalizerStartTime()
- {
- if (CLRHosted())
- {
- g_ObjFinalizeStartTime = CLRGetTickCount64();
- }
- }
- ~ResetFinalizerStartTime()
+ if (CLRHosted())
{
- if (g_ObjFinalizeStartTime)
- {
- g_ObjFinalizeStartTime = 0;
- }
- }
- };
- {
- ResetFinalizerStartTime resetTime;
- CallFinalizer(fobj);
+ g_ObjFinalizeStartTime = CLRGetTickCount64();
+ }
}
- pThread->InternalReset();
- }
- else
- {
- if (!currentDomain->IsDefaultDomain())
+ ~ResetFinalizerStartTime()
{
- // this means we are in some other domain, so need to return back out through the DoADCallback
- // and handle the object from there in another domain.
- pReturnObject = fobj;
- fTerminate = true;
- }
- else
- {
- // otherwise call back to ourselves to process as many as we can in that other domain
- FinalizeAllObjects_Args args;
- args.fobj = ObjectToOBJECTREF(fobj);
- args.bitToCheck = bitToCheck;
- GCPROTECT_BEGIN(args.fobj);
+ if (g_ObjFinalizeStartTime)
{
- _ASSERTE(pThreadTurnAround != NULL);
- ManagedThreadBase::FinalizerAppDomain(targetAppDomain,
- FinalizeAllObjects_Wrapper,
- &args,
- pThreadTurnAround);
+ g_ObjFinalizeStartTime = 0;
}
- pThread->InternalReset();
- // process the object we got back or be done if we got back null
- pReturnObject = OBJECTREFToObject(args.fobj);
- GCPROTECT_END();
}
- }
-
- *pbTerminate = fTerminate;
- return pReturnObject;
+ };
+ {
+ ResetFinalizerStartTime resetTime;
+ CallFinalizer(fobj);
+ }
+ pThread->InternalReset();
}
-Object * FinalizerThread::FinalizeAllObjects(Object* fobj, int bitToCheck)
+void FinalizerThread::FinalizeAllObjects(int bitToCheck)
{
STATIC_CONTRACT_THROWS;
STATIC_CONTRACT_GC_TRIGGERS;
FireEtwGCFinalizersBegin_V1(GetClrInstanceId());
unsigned int fcount = 0;
- bool fTerminate = false;
- if (fobj == NULL)
- {
- fobj = GCHeapUtilities::GetGCHeap()->GetNextFinalizable();
- }
+ Object* fobj = GCHeapUtilities::GetGCHeap()->GetNextFinalizable();
Thread *pThread = GetThread();
else
{
fcount++;
- fobj = DoOneFinalization(fobj, pThread, bitToCheck,&fTerminate);
- if (fTerminate)
- {
- break;
- }
-
- if (fobj == NULL)
- {
- fobj = GCHeapUtilities::GetGCHeap()->GetNextFinalizable();
- }
+ DoOneFinalization(fobj, pThread);
+ fobj = GCHeapUtilities::GetGCHeap()->GetNextFinalizable();
}
}
FireEtwGCFinalizersEnd_V1(fcount, GetClrInstanceId());
-
- return fobj;
}
SCAN_IGNORE_THROW;
SCAN_IGNORE_TRIGGER;
- // This is used to stitch together the exception handling at the base of our thread with
- // any eventual transitions into different AppDomains for finalization.
- _ASSERTE(args != NULL);
- pThreadTurnAround = (ManagedThreadCallState *) args;
-
BOOL bPriorityBoosted = FALSE;
while (!fQuitFinalizer)
}
FastInterlockExchange ((LONG*)&g_FinalizerIsRunning, TRUE);
- FinalizeAllObjects(NULL, 0);
+ FinalizeAllObjects(0);
_ASSERTE(GetFinalizerThread()->GetDomain()->IsDefaultDomain());
FastInterlockExchange ((LONG*)&g_FinalizerIsRunning, FALSE);
{
WRAPPER_NO_CONTRACT;
- // This is used to stitch together the exception handling at the base of our thread with
- // any eventual transitions into different AppDomains for finalization.
- _ASSERTE(args != NULL);
- pThreadTurnAround = (ManagedThreadCallState *) args;
-
- FinalizeAllObjects(NULL, BIT_SBLK_FINALIZER_RUN);
+ FinalizeAllObjects(BIT_SBLK_FINALIZER_RUN);
}
static void ProcessProfilerAttachIfNecessary(ULONGLONG * pui64TimestampLastCheckedEventMs);
#endif // FEATURE_PROFAPI_ATTACH_DETACH
- static Object * DoOneFinalization(Object* fobj, Thread* pThread, int bitToCheck, bool *pbTerminate);
+ static void DoOneFinalization(Object* fobj, Thread* pThread);
- static void FinalizeAllObjects_Wrapper(void *ptr);
- static Object * FinalizeAllObjects(Object* fobj, int bitToCheck);
+ static void FinalizeAllObjects(int bitToCheck);
public:
static Thread* GetFinalizerThread()
CONTRACTL_END;
#ifdef FEATURE_COMINTEROP
- // Go through all the app domains and for each one detach all the *unmarked* RCWs to prevent
+ // Go through all the only app domain and detach all the *unmarked* RCWs to prevent
// the RCW cache from resurrecting them.
- UnsafeAppDomainIterator i(TRUE);
- i.Init();
-
- while (i.Next())
- {
- i.GetDomain()->DetachRCWs();
- }
+ ::GetAppDomain()->DetachRCWs();
#endif // FEATURE_COMINTEROP
}
{
LIMITED_METHOD_CONTRACT;
- return SystemDomain::System()->DefaultDomain()->GetIndex().m_dwIndex;
+ return DefaultADID;
}
void *GCToEEInterface::GetAppDomainAtIndex(uint32_t appDomainIndex)
{
LIMITED_METHOD_CONTRACT;
- ADIndex index(appDomainIndex);
- return static_cast<void *>(SystemDomain::GetAppDomainAtIndex(index));
+ return ::GetAppDomain();
}
bool GCToEEInterface::AppDomainCanAccessHandleTable(uint32_t appDomainID)
{
LIMITED_METHOD_CONTRACT;
- ADIndex index(appDomainID);
- AppDomain *pDomain = SystemDomain::GetAppDomainAtIndex(index);
- return (pDomain != NULL);
+ return appDomainID == DefaultADID;
}
uint32_t GCToEEInterface::GetIndexOfAppDomainBeingUnloaded()
#define _tfopen _wfopen
#endif
+// -----------------------------------------------------------------------------------------------------------
+//
+// AppDomain emulation. We don't have these in the CLR anymore so instead we emulate the bare minimum of the API
+// touched by the GC/HandleTable and pretend we have precisely one (default) appdomain.
+//
+
+#define RH_DEFAULT_DOMAIN_ID 1
+
+struct ADIndex
+{
+ DWORD m_dwIndex;
+
+ ADIndex () : m_dwIndex(RH_DEFAULT_DOMAIN_ID) {}
+ explicit ADIndex (DWORD id) : m_dwIndex(id) {}
+ BOOL operator==(const ADIndex& ad) const { return m_dwIndex == ad.m_dwIndex; }
+ BOOL operator!=(const ADIndex& ad) const { return m_dwIndex != ad.m_dwIndex; }
+};
+
#endif // GCENV_H_
IGCHandleManager* g_pGCHandleManager = nullptr;
-// Debug-only validation for handle.
-
-void ValidateObjectAndAppDomain(OBJECTREF objRef, ADIndex appDomainIndex)
-{
-#ifdef _DEBUG_IMPL
- VALIDATEOBJECTREF(objRef);
-
- AppDomain *domain = SystemDomain::GetAppDomainAtIndex(appDomainIndex);
-
- // Access to a handle in an unloaded domain is not allowed
- assert(domain != nullptr);
-
-#endif // _DEBUG_IMPL
-}
-
void ValidateHandleAssignment(OBJECTHANDLE handle, OBJECTREF objRef)
{
#ifdef _DEBUG_IMPL
// Verify that we are not trying to access a freed handle.
_ASSERTE("Attempt to access destroyed handle." && *(_UNCHECKED_OBJECTREF*)handle != DEBUG_DestroyedHandleValue);
#endif
-
- IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager();
- ADIndex appDomainIndex = ADIndex((DWORD)((SIZE_T)mgr->GetHandleContext(handle)));
-
- ValidateObjectAndAppDomain(objRef, appDomainIndex);
+ VALIDATEOBJECTREF(objRef);
#endif // _DEBUG_IMPL
}
GCHandleUtilities() = delete;
};
-void ValidateObjectAndAppDomain(OBJECTREF objRef, ADIndex appDomainIndex);
void ValidateHandleAssignment(OBJECTHANDLE handle, OBJECTREF objRef);
void DiagHandleCreated(OBJECTHANDLE handle, OBJECTREF object);
void DiagHandleDestroyed(OBJECTHANDLE handle);
_ASSERTE(handle);
#if defined(_DEBUG_IMPL) && !defined(DACCESS_COMPILE)
- // not allowed to dispatch virtually on a IGCHandleManager when compiling for DAC
- DWORD context = (DWORD)(SIZE_T)GCHandleUtilities::GetGCHandleManager()->GetHandleContext(handle);
OBJECTREF objRef = ObjectToOBJECTREF(*(Object**)handle);
- ValidateObjectAndAppDomain(objRef, ADIndex(context));
+ VALIDATEOBJECTREF(objRef);
#endif // defined(_DEBUG_IMPL) && !defined(DACCESS_COMPILE)
// Wrap the raw OBJECTREF and return it
//
// This is wrapper overload to handle TypeHandle arrayType
//
-OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap
- DEBUG_ARG(BOOL bDontSetAppDomain))
+OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap)
{
CONTRACTL
{
ArrayTypeDesc* arrayDesc = arrayType.AsArray();
MethodTable* pArrayMT = arrayDesc->GetMethodTable();
- return AllocateArrayEx(pArrayMT, pArgs, dwNumArgs, bAllocateInLargeHeap
- DEBUG_ARG(bDontSetAppDomain));
+ return AllocateArrayEx(pArrayMT, pArgs, dwNumArgs, bAllocateInLargeHeap);
}
//
// allocate sub-arrays and fill them in.
//
// For arrays with lower bounds, pBounds is <lower bound 1>, <count 1>, <lower bound 2>, ...
-OBJECTREF AllocateArrayEx(MethodTable *pArrayMT, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap
- DEBUG_ARG(BOOL bDontSetAppDomain))
+OBJECTREF AllocateArrayEx(MethodTable *pArrayMT, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap)
{
CONTRACTL {
THROWS;
// This recursive call doesn't go any farther, because the dwNumArgs will be 1,
// so don't bother with stack probe.
TypeHandle szArrayType = ClassLoader::LoadArrayTypeThrowing(pArrayMT->GetApproxArrayElementTypeHandle(), ELEMENT_TYPE_SZARRAY, 1);
- return AllocateArrayEx(szArrayType, &pArgs[dwNumArgs - 1], 1, bAllocateInLargeHeap DEBUG_ARG(bDontSetAppDomain));
+ return AllocateArrayEx(szArrayType, &pArgs[dwNumArgs - 1], 1, bAllocateInLargeHeap);
}
providedLowerBounds = (dwNumArgs == 2*rank);
TypeHandle subArrayType = pArrayMT->GetApproxArrayElementTypeHandle();
for (UINT32 i = 0; i < cElements; i++)
{
- OBJECTREF obj = AllocateArrayEx(subArrayType, &pArgs[1], dwNumArgs-1, bAllocateInLargeHeap DEBUG_ARG(bDontSetAppDomain));
+ OBJECTREF obj = AllocateArrayEx(subArrayType, &pArgs[1], dwNumArgs-1, bAllocateInLargeHeap);
outerArray->SetAt(i, obj);
}
numArgs = 1;
args[0] = pRef->GetNumComponents();
}
- return AllocateArrayEx(TypeHandle(&arrayType), args, numArgs, bAllocateInLargeHeap DEBUG_ARG(FALSE));
+ return AllocateArrayEx(TypeHandle(&arrayType), args, numArgs, bAllocateInLargeHeap);
}
#if defined(_TARGET_X86_)
return AllocateArrayEx(ClassLoader::LoadArrayTypeThrowing(elementType),
(INT32 *)(&cElements),
1,
- bAllocateInLargeHeap
- DEBUG_ARG(FALSE));
+ bAllocateInLargeHeap);
}
orObject->SetMethodTable(pMT);
}
- if (pMT->HasFinalizer())
- orObject->SetAppDomain();
-
// Notify the profiler of the allocation
if (TrackAllocations())
{
OBJECTREF AllocateValueSzArray(TypeHandle elementType, INT32 length);
// The main Array allocation routine, can do multi-dimensional
-OBJECTREF AllocateArrayEx(MethodTable *pArrayMT, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap = FALSE
- DEBUG_ARG(BOOL bDontSetAppDomain = FALSE));
-OBJECTREF AllocateArrayEx(TypeHandle arrayClass, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap = FALSE
- DEBUG_ARG(BOOL bDontSetAppDomain = FALSE));
+OBJECTREF AllocateArrayEx(MethodTable *pArrayMT, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap = FALSE);
+OBJECTREF AllocateArrayEx(TypeHandle arrayClass, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap = FALSE);
// Optimized verion of above
OBJECTREF FastAllocatePrimitiveArray(MethodTable* arrayType, DWORD cElements, BOOL bAllocateInLargeHeap = FALSE);
// from clr/src/vm/appdomain.hpp
-#define AppDomain__m_dwId 0x4
-ASMCONSTANTS_C_ASSERT(AppDomain__m_dwId == offsetof(AppDomain, m_dwId));
-
// This is the offset from EBP at which the original CONTEXT is stored in one of the
// RedirectedHandledJITCase*_Stub functions.
#define REDIRECTSTUB_EBP_OFFSET_CONTEXT (-4)
#define UMEntryThunk__m_pUMThunkMarshInfo 0x0C
ASMCONSTANTS_C_ASSERT(UMEntryThunk__m_pUMThunkMarshInfo == offsetof(UMEntryThunk, m_pUMThunkMarshInfo))
-#define UMEntryThunk__m_dwDomainId 0x10
-ASMCONSTANTS_C_ASSERT(UMEntryThunk__m_dwDomainId == offsetof(UMEntryThunk, m_dwDomainId))
-
#define UMThunkMarshInfo__m_pILStub 0x00
ASMCONSTANTS_C_ASSERT(UMThunkMarshInfo__m_pILStub == offsetof(UMThunkMarshInfo, m_pILStub))
ASMCONSTANTS_C_ASSERT(UMThunkMarshInfo__m_cbRetPop == offsetof(UMThunkMarshInfo, m_cbRetPop))
#endif //FEATURE_STUBS_AS_IL
-#ifndef CROSSGEN_COMPILE
-#define Thread__m_pDomain 0x10
-ASMCONSTANTS_C_ASSERT(Thread__m_pDomain == offsetof(Thread, m_pDomain));
-
-#endif
-
// For JIT_PInvokeBegin and JIT_PInvokeEnd helpers
#define Frame__m_Next 0x04
ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next));
#define InlinedCallFrame__m_pCalleeSavedFP 0x14
ASMCONSTANTS_C_ASSERT(InlinedCallFrame__m_pCalleeSavedFP == offsetof(InlinedCallFrame, m_pCalleeSavedFP));
-
#ifdef FEATURE_STUBS_AS_IL
// DelegateObject from src/vm/object.h
#define DelegateObject___target 0x04 // offset 0 is m_pMethTab of base class Object
void BogusFunction()
{
// Sample usage to generate the error
- FindCompileTimeConstant<offsetof(AppDomain, m_dwId)> bogus_variable;
+ FindCompileTimeConstant<offsetof(Thread, m_ExceptionState)> bogus_variable;
}
#endif // defined(__cplusplus) && defined(USE_COMPILE_TIME_CONSTANT_FINDER)
return OBJECTREFToObject(AllocateArrayEx(pArrayMT,
(INT32 *)(&cElements),
1,
- FALSE
- DEBUG_ARG(FALSE)));
+ FALSE));
}
HCIMPLEND_RAW
LOCAL_LABEL(InCooperativeMode):
-#if _DEBUG
- mov eax, dword ptr [ebp - UMThunkStub_THREAD_OFFSET]
- mov eax, dword ptr [eax + Thread__m_pDomain]
- mov esi, dword ptr [eax + AppDomain__m_dwId]
-
- mov eax, dword ptr [ebp - UMThunkStub_UMENTRYTHUNK_OFFSET]
- mov edi, dword ptr [eax + UMEntryThunk__m_dwDomainId]
-
- cmp esi, edi
- jne LOCAL_LABEL(WrongAppDomain)
-#endif
-
mov eax, dword ptr [ebp - UMThunkStub_UMENTRYTHUNK_OFFSET]
mov ebx, dword ptr [eax + UMEntryThunk__m_pUMThunkMarshInfo]
mov eax, dword ptr [ebx + UMThunkMarshInfo__m_cbActualArgSize]
pop edx
jmp LOCAL_LABEL(UMThunkStub_ArgumentsSetup)
-#if _DEBUG
-LOCAL_LABEL(WrongAppDomain):
- int3
-#endif
-
NESTED_END UMThunkStub, _TEXT
if (*pNativeHome == NULL)
{
- SetObjectReference(pManagedHome, NULL, GetAppDomain());
+ SetObjectReference(pManagedHome, NULL);
}
else
{
//
// Allocate array
//
- SetObjectReference(pManagedHome, AllocateArrayEx(pThis->m_Array, &cElements, 1), GetAppDomain());
+ SetObjectReference(pManagedHome, AllocateArrayEx(pThis->m_Array, &cElements, 1));
}
HELPER_METHOD_FRAME_END();
}
SetObjectReference(pManagedHome,
(OBJECTREF) OleVariant::CreateArrayRefForSafeArray((SAFEARRAY*) *pNativeHome,
pThis->m_vt,
- pThis->m_pElementMT), GetAppDomain());
+ pThis->m_pElementMT));
}
else
{
- SetObjectReference(pManagedHome, NULL, GetAppDomain());
+ SetObjectReference(pManagedHome, NULL);
}
HELPER_METHOD_FRAME_END();
if (*pNativeHome == NULL)
{
- SetObjectReference(pManagedHome, NULL, GetAppDomain());
+ SetObjectReference(pManagedHome, NULL);
}
else
{
TypeHandle elementType(pThis->m_pElementMT);
TypeHandle arrayType = ClassLoader::LoadArrayTypeThrowing(elementType);
- SetObjectReference(pManagedHome, AllocateArrayEx(arrayType, &cElements, 1), GetAppDomain());
+ SetObjectReference(pManagedHome, AllocateArrayEx(arrayType, &cElements, 1));
}
HELPER_METHOD_FRAME_END();
HELPER_METHOD_FRAME_BEGIN_0();
- SetObjectReference(pManagedHome, pThis->m_pCMHelper->InvokeMarshalNativeToManagedMeth(*pNativeHome), GetAppDomain());
+ SetObjectReference(pManagedHome, pThis->m_pCMHelper->InvokeMarshalNativeToManagedMeth(*pNativeHome));
HELPER_METHOD_FRAME_END();
}
{ // our tear-off
_ASSERTE(pWrap != NULL);
AppDomain* pCurrDomain = pThread->GetDomain();
- ADID pObjDomain = pWrap->GetDomainID();
- _ASSERTE(pObjDomain == pCurrDomain->GetId());
*pObjOut = pWrap->GetObjectRef();
}
return GetObjectRefFromComIP(pObjOut, &pUnk, pMTClass, pItfMT, dwFlags);
}
-
-//--------------------------------------------------------------------------------
-// UnMarshalObjectForCurrentDomain
-// unmarshal the managed object for the current domain
-BOOL UnMarshalObjectForCurrentDomain(ADID pObjDomain, ComCallWrapper* pWrap, OBJECTREF* pResult);
-
#endif // FEATURE_COMINTEROP
#endif // #ifndef _H_INTEROPCONVERTER_
OBJECTREF val = ObjectToOBJECTREF(OpStackGet<Object*>(stackInd1));
OBJECTREF* ptr = OpStackGet<OBJECTREF*>(stackInd0);
ThrowOnInvalidPointer(ptr);
- SetObjectReferenceUnchecked(ptr, val);
+ SetObjectReference(ptr, val);
m_curStackHt -= 2;
#if INTERP_TRACING
else
{
OBJECTREF val = *reinterpret_cast<OBJECTREF*>(src);
- SetObjectReferenceUnchecked(reinterpret_cast<OBJECTREF*>(dest), val);
+ SetObjectReference(reinterpret_cast<OBJECTREF*>(dest), val);
}
m_curStackHt -= 2;
m_ILCodePtr += 5;
GCX_FORBID();
OBJECTREF val = ObjectToOBJECTREF(OpStackGet<Object*>(valInd));
- SetObjectReferenceUnchecked(reinterpret_cast<OBJECTREF*>(dest), val);
+ SetObjectReference(reinterpret_cast<OBJECTREF*>(dest), val);
}
m_curStackHt -= 2;
else
{
// The ostack entry is an object reference.
- SetObjectReferenceUnchecked(reinterpret_cast<OBJECTREF*>(dest), NULL);
+ SetObjectReference(reinterpret_cast<OBJECTREF*>(dest), NULL);
}
m_curStackHt -= 1;
m_ILCodePtr += 6;
else if (valCit == CORINFO_TYPE_CLASS)
{
OBJECTREF val = ObjectToOBJECTREF(OpStackGet<Object*>(valInd));
- SetObjectReferenceUnchecked(reinterpret_cast<OBJECTREF*>(destPtr), val);
+ SetObjectReference(reinterpret_cast<OBJECTREF*>(destPtr), val);
}
else
{
}
else if (valCit == CORINFO_TYPE_CLASS)
{
- SetObjectReferenceUnchecked(reinterpret_cast<OBJECTREF*>(dstPtr), ObjectToOBJECTREF(OpStackGet<Object*>(m_curStackHt)));
+ SetObjectReference(reinterpret_cast<OBJECTREF*>(dstPtr), ObjectToOBJECTREF(OpStackGet<Object*>(m_curStackHt)));
}
else
{
((ReflectionPointer *)OBJECTREFToObject(refObj))->_ptr = p;
OBJECTREF refType = th.GetManagedClassObject();
- SetObjectReference(&(((ReflectionPointer *)OBJECTREFToObject(refObj))->_ptrType), refType, GetAppDomain());
+ SetObjectReference(&(((ReflectionPointer *)OBJECTREFToObject(refObj))->_ptrType), refType);
GCPROTECT_END();
RETURN refObj;
if (pField->IsStatic())
CopyValueClass(obj->UnBox(),
pField->GetCurrentStaticAddress(),
- fieldType.AsMethodTable(),
- obj->GetAppDomain());
+ fieldType.AsMethodTable());
else
pField->GetInstanceField(*target, obj->UnBox());
GCPROTECT_END();
// copy the field to the unboxed object.
// note: this will be done only for the non-remoting case
if (p) {
- CopyValueClass(obj->GetData(), p, fieldType.AsMethodTable(), obj->GetAppDomain());
+ CopyValueClass(obj->GetData(), p, fieldType.AsMethodTable());
}
// If it is a Nullable<T>, box it using Nullable<T> conventions.
MethodTable *pIntPtrMT = MscorlibBinder::GetClass(CLASS__INTPTR);
obj = AllocateObject(pIntPtrMT);
- CopyValueClass(obj->UnBox(), &value, pIntPtrMT, obj->GetAppDomain());
+ CopyValueClass(obj->UnBox(), &value, pIntPtrMT);
break;
}
}
void * address = pFD->GetAddressGuaranteedInHeap(obj);
- SetObjectReference((OBJECTREF*)address, ObjectToOBJECTREF(value), GetAppDomain());
+ SetObjectReference((OBJECTREF*)address, ObjectToOBJECTREF(value));
FC_GC_POLL();
}
HCIMPLEND
if (!fRemoted)
{
void * pAddr = pFD->GetAddress(OBJECTREFToObject(objRef));
- CopyValueClass(retBuff, pAddr, pFieldMT, objRef->GetAppDomain());
+ CopyValueClass(retBuff, pAddr, pFieldMT);
}
HELPER_METHOD_FRAME_END(); // Tear down the frame
}
void * pAddr = pFD->GetAddressGuaranteedInHeap(obj);
- CopyValueClass(retBuff, pAddr, pFieldMT, obj->GetAppDomain());
+ CopyValueClass(retBuff, pAddr, pFieldMT);
}
HCIMPLEND
#include <optdefault.h>
if (!fRemoted)
{
void * pAddr = pFD->GetAddress(OBJECTREFToObject(objRef));
- CopyValueClass(pAddr, valuePtr, pFieldMT, objRef->GetAppDomain());
+ CopyValueClass(pAddr, valuePtr, pFieldMT);
}
HELPER_METHOD_FRAME_END(); // Tear down the frame
}
void * pAddr = pFD->GetAddressGuaranteedInHeap(obj);
- CopyValueClass(pAddr, valuePtr, pFieldMT, obj->GetAppDomain());
+ CopyValueClass(pAddr, valuePtr, pFieldMT);
}
HCIMPLEND
#include <optdefault.h>
}
#ifdef _TARGET_ARM64_
- SetObjectReferenceUnchecked((OBJECTREF*)&array->m_Array[idx], ObjectToOBJECTREF(val));
+ SetObjectReference((OBJECTREF*)&array->m_Array[idx], ObjectToOBJECTREF(val));
#else
// The performance gain of the optimized JIT_Stelem_Ref in
// jitinterfacex86.cpp is mainly due to calling JIT_WriteBarrier
FieldDesc *pField = (FieldDesc *)field;
SetObjectReference((OBJECTREF*) destPtr,
- pField->GetStubFieldInfo(), GetAppDomain());
+ pField->GetStubFieldInfo());
HELPER_METHOD_FRAME_END();
}
MethodDesc *pMethod = (MethodDesc *)method;
SetObjectReference((OBJECTREF*) destPtr,
- pMethod->GetStubMethodInfo(), GetAppDomain());
+ pMethod->GetStubMethodInfo());
HELPER_METHOD_FRAME_END();
}
if (typePtr != NULL)
{
SetObjectReference((OBJECTREF*) destPtr,
- typePtr, GetAppDomain());
+ typePtr);
return;
}
}
HELPER_METHOD_FRAME_BEGIN_0();
SetObjectReference((OBJECTREF*) destPtr,
- typeHnd.GetManagedClassObject(), GetAppDomain());
+ typeHnd.GetManagedClassObject());
HELPER_METHOD_FRAME_END();
}
if (pbLockTaken != 0) *pbLockTaken = 0;
- TESTHOOKCALL(AppDomainCanBeUnloaded(GET_THREAD()->GetDomain()->GetId().m_dwId,FALSE));
+ TESTHOOKCALL(AppDomainCanBeUnloaded(DefaultADID,FALSE));
if (GET_THREAD()->IsAbortRequested()) {
GET_THREAD()->HandleThreadAbort();
if (psb != NULL)
psb->QuickGetMonitor()->Signal();
- TESTHOOKCALL(AppDomainCanBeUnloaded(GET_THREAD()->GetDomain()->GetId().m_dwId,FALSE));
+ TESTHOOKCALL(AppDomainCanBeUnloaded(DefaultADID,FALSE));
if (GET_THREAD()->IsAbortRequested()) {
GET_THREAD()->HandleThreadAbort();
COMPlusThrow(kSynchronizationLockException);
MONHELPER_STATE(*pbLockTaken = 0;)
- TESTHOOKCALL(AppDomainCanBeUnloaded(GET_THREAD()->GetDomain()->GetId().m_dwId,FALSE));
+ TESTHOOKCALL(AppDomainCanBeUnloaded(DefaultADID,FALSE));
if (GET_THREAD()->IsAbortRequested()) {
GET_THREAD()->HandleThreadAbort();
}
lock->Signal();
- TESTHOOKCALL(AppDomainCanBeUnloaded(GET_THREAD()->GetDomain()->GetId().m_dwId,FALSE));
+ TESTHOOKCALL(AppDomainCanBeUnloaded(DefaultADID,FALSE));
if (GET_THREAD()->IsAbortRequested()) {
GET_THREAD()->HandleThreadAbort();
}
MethodTable *pMT = typeHnd.AsMethodTable();
HELPER_METHOD_FRAME_BEGIN_NOPOLL(); // Set up a frame
- CopyValueClassUnchecked(dest, src, pMT);
+ CopyValueClass(dest, src, pMT);
HELPER_METHOD_FRAME_END_POLL();
}
// Deleting the DomainAssemblies will have created a list of LoaderAllocator's on the AppDomain
// Call this shutdown function to clean those up.
- pAppDomain->ShutdownFreeLoaderAllocators(TRUE);
+ pAppDomain->ShutdownFreeLoaderAllocators();
} // LoaderAllocator::GCLoaderAllocators
//---------------------------------------------------------------------------------------
else
{
OBJECTREF* pRef = GetDomain()->AllocateObjRefPtrsInLargeTable(1);
- SetObjectReference(pRef, gc.value, GetDomain()->AsAppDomain());
+ SetObjectReference(pRef, gc.value);
retVal = (((UINT_PTR)pRef) + 1);
}
gc.previous = *ptr;
if ((*ptr) == gc.compare)
{
- SetObjectReference(ptr, gc.value, GetDomain()->AsAppDomain());
+ SetObjectReference(ptr, gc.value);
}
}
else
if ((((UINT_PTR)handle) & 1) != 0)
{
OBJECTREF *ptr = (OBJECTREF *)(((UINT_PTR)handle) - 1);
- SetObjectReference(ptr, value, GetDomain()->AsAppDomain());
+ SetObjectReference(ptr, value);
}
else
{
LOG((LF_CLASSLOADER, LL_INFO10000, "\tInstantiating static of type %s\n", pFieldMT->GetDebugClassName()));
OBJECTREF obj = AllocateStaticBox(pFieldMT, pClassCtorInfoEntry->hasFixedAddressVTStatics);
- SetObjectReference( &(pStaticSlots[i]), obj, GetAppDomain() );
+ SetObjectReference( &(pStaticSlots[i]), obj);
}
GCPROTECT_END();
}
LOG((LF_CLASSLOADER, LL_INFO10000, "\tInstantiating static of type %s\n", pFieldMT->GetDebugClassName()));
OBJECTREF obj = AllocateStaticBox(pFieldMT, HasFixedAddressVTStatics());
- SetObjectReference( (OBJECTREF*)(pStaticBase + pField->GetOffset()), obj, GetAppDomain() );
+ SetObjectReference( (OBJECTREF*)(pStaticBase + pField->GetOffset()), obj);
}
pField++;
return Nullable::Box(*data, this);
OBJECTREF ref = Allocate();
- CopyValueClass(ref->UnBox(), *data, this, ref->GetAppDomain());
+ CopyValueClass(ref->UnBox(), *data, this);
return ref;
}
#ifdef STRESS_LOG
if (fCriticalFinalizer)
{
- STRESS_LOG2(LF_GCALLOC, LL_INFO100, "Finalizing CriticalFinalizer %pM in domain %d\n",
- pMT, GetAppDomain()->GetId().m_dwId);
+ STRESS_LOG1(LF_GCALLOC, LL_INFO100, "Finalizing CriticalFinalizer %pM\n",
+ pMT);
}
#endif
#ifdef STRESS_LOG
if (fCriticalFinalizer)
{
- STRESS_LOG2(LF_GCALLOC, LL_INFO100, "Finalized CriticalFinalizer %pM in domain %d without exception\n",
- pMT, GetAppDomain()->GetId().m_dwId);
+ STRESS_LOG1(LF_GCALLOC, LL_INFO100, "Finalized CriticalFinalizer %pM without exception\n",
+ pMT);
}
#endif
}
if (src == NULL || src->GetMethodTable() != this)
return FALSE;
- CopyValueClass(dest, src->UnBox(), this, src->GetAppDomain());
+ CopyValueClass(dest, src->UnBox(), this);
}
return TRUE;
}
if (src == NULL || src->GetMethodTable() != this)
return FALSE;
- CopyValueClassArg(argDest, src->UnBox(), this, src->GetAppDomain(), 0);
+ CopyValueClassArg(argDest, src->UnBox(), this, 0);
}
return TRUE;
}
{
_ASSERTE(src->GetMethodTable()->GetNumInstanceFieldBytes() == GetNumInstanceFieldBytes());
- CopyValueClass(dest, src->UnBox(), this, src->GetAppDomain());
+ CopyValueClass(dest, src->UnBox(), this);
}
}
#endif
}
NewHolder<MulticoreJitProfilePlayer> player(new (nothrow) MulticoreJitProfilePlayer(
- m_pDomain,
m_pBinderContext,
nSession,
m_fAppxMode));
friend class MulticoreJitRecorder;
private:
- ADID m_DomainID;
ICLRPrivBinder * m_pBinderContext;
LONG m_nMySession;
unsigned m_nStartTime;
public:
- MulticoreJitProfilePlayer(AppDomain * pDomain, ICLRPrivBinder * pBinderContext, LONG nSession, bool fAppxMode);
+ MulticoreJitProfilePlayer(ICLRPrivBinder * pBinderContext, LONG nSession, bool fAppxMode);
~MulticoreJitProfilePlayer();
}
-MulticoreJitProfilePlayer::MulticoreJitProfilePlayer(AppDomain * pDomain, ICLRPrivBinder * pBinderContext, LONG nSession, bool fAppxMode)
- : m_stats(pDomain->GetMulticoreJitManager().GetStats()), m_appdomainSession(pDomain->GetMulticoreJitManager().GetProfileSession())
+MulticoreJitProfilePlayer::MulticoreJitProfilePlayer(ICLRPrivBinder * pBinderContext, LONG nSession, bool fAppxMode)
+ : m_stats(::GetAppDomain()->GetMulticoreJitManager().GetStats()), m_appdomainSession(::GetAppDomain()->GetMulticoreJitManager().GetProfileSession())
{
LIMITED_METHOD_CONTRACT;
- m_DomainID = pDomain->GetId();
m_pBinderContext = pBinderContext;
m_nMySession = nSession;
m_moduleCount = 0;
unsigned nSize = m_nFileSize;
- MulticoreJitTrace(("PlayProfile %d bytes in (%d, %s)",
+ MulticoreJitTrace(("PlayProfile %d bytes in (%s)",
nSize,
- GetAppDomain()->GetId().m_dwId,
GetAppDomain()->GetFriendlyNameForLogging()));
while ((SUCCEEDED(hr)) && (nSize > sizeof(unsigned)))
EX_TRY
{
- ENTER_DOMAIN_ID(m_DomainID);
{
// Go into preemptive mode
GCX_PREEMP();
m_stats.m_hr = PlayProfile();
}
- END_DOMAIN_TRANSITION;
}
EX_CATCH
{
//Poll and wait if GC is in progress, to avoid blocking GC for too long.
FC_GC_POLL();
- *lpOverlapped = ThreadpoolMgr::CompletionPortDispatchWorkWithinAppDomain(pThread, errorCode, numBytes, &key, DefaultADID);
+ *lpOverlapped = ThreadpoolMgr::CompletionPortDispatchWorkWithinAppDomain(pThread, errorCode, numBytes, &key);
if(*lpOverlapped == NULL)
{
return;
g_pOverlappedDataClass = MscorlibBinder::GetClass(CLASS__OVERLAPPEDDATA);
// We have optimization to avoid creating event if IO is in default domain. This depends on default domain
// can not be unloaded.
- _ASSERTE(SystemDomain::System()->DefaultDomain()->GetId().m_dwId == DefaultADID);
}
CONSISTENCY_CHECK(overlapped->GetMethodTable() == g_pOverlappedDataClass);
}
else
{
- // If a thread is holding the thin lock or an appdomain index is set, we need a syncblock
- if ((bits & (SBLK_MASK_LOCK_THREADID | (SBLK_MASK_APPDOMAININDEX << SBLK_APPDOMAIN_SHIFT))) != 0)
+ // If a thread is holding the thin lock we need a syncblock
+ if ((bits & (SBLK_MASK_LOCK_THREADID)) != 0)
{
GetSyncBlock();
// No need to replicate the above code dealing with sync blocks
return m_pAssembly->GetAssembly();
}
-#ifdef _DEBUG
-// Object::DEBUG_SetAppDomain specified DEBUG_ONLY in the contract to disable SO-tolerance
-// checking for paths that are DEBUG-only.
-//
-// NOTE: currently this is only used by WIN64 allocation helpers, but they really should
-// be calling the JIT helper SetObjectAppDomain (which currently only exists for
-// x86).
-void Object::DEBUG_SetAppDomain(AppDomain *pDomain)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- DEBUG_ONLY;
- INJECT_FAULT(COMPlusThrowOM(););
- PRECONDITION(CheckPointer(pDomain));
- }
- CONTRACTL_END;
-
- SetAppDomain(pDomain);
-}
-#endif
-
-void Object::SetAppDomain(AppDomain *pDomain)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- INJECT_FAULT(COMPlusThrowOM(););
- PRECONDITION(CheckPointer(pDomain));
- }
- CONTRACTL_END;
-
-#ifndef _DEBUG
- //
- // If we have a per-app-domain method table, we can
- // infer the app domain from the method table, so
- // there is no reason to mark the object.
- //
- // But we don't do this in a debug build, because
- // we want to be able to detect the case when the
- // domain was unloaded from underneath an object (and
- // the MethodTable will be toast in that case.)
- //
- _ASSERTE(pDomain == GetMethodTable()->GetDomain());
-#else
- ADIndex index = pDomain->GetIndex();
- GetHeader()->SetAppDomainIndex(index);
-#endif
-
- _ASSERTE(GetHeader()->GetAppDomainIndex().m_dwIndex != 0);
-}
-
-BOOL Object::SetAppDomainNoThrow()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- BOOL success = FALSE;
-
- EX_TRY
- {
- SetAppDomain();
- success = TRUE;
- }
- EX_CATCH
- {
- _ASSERTE (!"Exception happened during Object::SetAppDomain");
- }
- EX_END_CATCH(RethrowTerminalExceptions)
-
- return success;
-}
-
-AppDomain *Object::GetAppDomain()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-#ifndef _DEBUG
- return (AppDomain*) GetMethodTable()->GetDomain();
-#endif
-
- ADIndex index = GetHeader()->GetAppDomainIndex();
-
- if (index.m_dwIndex == 0)
- return NULL;
-
- AppDomain *pDomain = SystemDomain::TestGetAppDomainAtIndex(index);
- return pDomain;
-}
-
STRINGREF AllocateString(SString sstr)
{
CONTRACTL {
location = (OBJECTREF *) &GetData()[dwOffset];
o = ObjectToOBJECTREF(*(Object **) &dwValue);
- SetObjectReference( location, o, GetAppDomain() );
+ SetObjectReference( location, o );
}
void SetObjectReferenceUnchecked(OBJECTREF *dst,OBJECTREF ref)
OBJECTREF* srcPtrStop = (OBJECTREF*)((BYTE*) srcPtr + cur->GetSeriesSize() + size);
while (srcPtr < srcPtrStop)
{
- SetObjectReferenceUnchecked(destPtr, ObjectToOBJECTREF(*(Object**)srcPtr));
+ SetObjectReference(destPtr, ObjectToOBJECTREF(*(Object**)srcPtr));
srcPtr++;
destPtr++;
}
GCPROTECT_BEGININTERIOR (src);
MethodTable* argMT = nullableMT->GetInstantiation()[0].GetMethodTable();
obj = argMT->Allocate();
- CopyValueClass(obj->UnBox(), src->ValueAddr(nullableMT), argMT, obj->GetAppDomain());
+ CopyValueClass(obj->UnBox(), src->ValueAddr(nullableMT), argMT);
GCPROTECT_END ();
return obj;
// This should not happen normally, but we want to be robust
if (destMT->IsEquivalentTo(boxedVal->GetMethodTable()))
{
- CopyValueClass(dest, boxedVal->GetData(), destMT, boxedVal->GetAppDomain());
+ CopyValueClass(dest, boxedVal->GetData(), destMT);
fRet = TRUE;
}
else
else
{
*dest->HasValueAddr(destMT) = true;
- CopyValueClass(dest->ValueAddr(destMT), boxedVal->UnBox(), boxedVal->GetMethodTable(), boxedVal->GetAppDomain());
+ CopyValueClass(dest->ValueAddr(destMT), boxedVal->UnBox(), boxedVal->GetMethodTable());
fRet = TRUE;
}
GCPROTECT_END();
// This should not happen normally, but we want to be robust
if (destMT == boxedVal->GetMethodTable())
{
- CopyValueClass(dest, boxedVal->GetData(), destMT, boxedVal->GetAppDomain());
+ CopyValueClass(dest, boxedVal->GetData(), destMT);
return TRUE;
}
return FALSE;
}
*dest->HasValueAddr(destMT) = true;
- CopyValueClass(dest->ValueAddr(destMT), boxedVal->UnBox(), boxedVal->GetMethodTable(), boxedVal->GetAppDomain());
+ CopyValueClass(dest->ValueAddr(destMT), boxedVal->UnBox(), boxedVal->GetMethodTable());
}
return TRUE;
}
// This should not happen normally, but we want to be robust
if (destMT == boxedVal->GetMethodTable())
{
- CopyValueClassArg(argDest, boxedVal->GetData(), destMT, boxedVal->GetAppDomain(), 0);
+ CopyValueClassArg(argDest, boxedVal->GetData(), destMT, 0);
return TRUE;
}
return FALSE;
Nullable* dest = (Nullable*)argDest->GetStructGenRegDestinationAddress();
*dest->HasValueAddr(destMT) = true;
int destOffset = (BYTE*)dest->ValueAddr(destMT) - (BYTE*)dest;
- CopyValueClassArg(argDest, boxedVal->UnBox(), boxedVal->GetMethodTable(), boxedVal->GetAppDomain(), destOffset);
+ CopyValueClassArg(argDest, boxedVal->UnBox(), boxedVal->GetMethodTable(), destOffset);
}
return TRUE;
}
{
// For safety's sake, also allow true nullables to be unboxed normally.
// This should not happen normally, but we want to be robust
- CopyValueClass(dest, boxedVal->GetData(), destMT, boxedVal->GetAppDomain());
+ CopyValueClass(dest, boxedVal->GetData(), destMT);
}
*dest->HasValueAddr(destMT) = true;
- CopyValueClass(dest->ValueAddr(destMT), boxedVal->UnBox(), boxedVal->GetMethodTable(), boxedVal->GetAppDomain());
+ CopyValueClass(dest->ValueAddr(destMT), boxedVal->UnBox(), boxedVal->GetMethodTable());
}
}
Thread *m_pThread = GetThread();
SpinLock::AcquireLock(&g_StackTraceArrayLock, SPINLOCK_THREAD_PARAM_ONLY_IN_SOME_BUILDS);
- SetObjectReference((OBJECTREF*)&_stackTrace, (OBJECTREF)stackTrace.Get(), GetAppDomain());
- SetObjectReference((OBJECTREF*)&_dynamicMethods, (OBJECTREF)dynamicMethodArray, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&_stackTrace, (OBJECTREF)stackTrace.Get());
+ SetObjectReference((OBJECTREF*)&_dynamicMethods, (OBJECTREF)dynamicMethodArray);
SpinLock::ReleaseLock(&g_StackTraceArrayLock, SPINLOCK_THREAD_PARAM_ONLY_IN_SOME_BUILDS);
I1ARRAYREF stackTraceArray = NULL;
PTRARRAYREF dynamicMethodArray = NULL;
- SetObjectReference((OBJECTREF*)&_stackTrace, (OBJECTREF)stackTraceArray, GetAppDomain());
- SetObjectReference((OBJECTREF*)&_dynamicMethods, (OBJECTREF)dynamicMethodArray, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&_stackTrace, (OBJECTREF)stackTraceArray);
+ SetObjectReference((OBJECTREF*)&_dynamicMethods, (OBJECTREF)dynamicMethodArray);
SpinLock::ReleaseLock(&g_StackTraceArrayLock, SPINLOCK_THREAD_PARAM_ONLY_IN_SOME_BUILDS);
}
return GetHeader()->GetSyncBlockIndex();
}
- ADIndex GetAppDomainIndex();
-
- // Get app domain of object, or NULL if it is agile
- AppDomain *GetAppDomain();
-
-#ifndef DACCESS_COMPILE
- // Set app domain of object to current domain.
- void SetAppDomain() { WRAPPER_NO_CONTRACT; SetAppDomain(::GetAppDomain()); }
- BOOL SetAppDomainNoThrow();
-
-#endif
-
- // Set app domain of object to given domain - it can only be set once
- void SetAppDomain(AppDomain *pDomain);
-
-#ifdef _DEBUG
-#ifndef DACCESS_COMPILE
- // For SO-tolerance contract violation purposes, define these DEBUG_ versions to identify
- // the codepaths to SetAppDomain that are called only from DEBUG code.
- void DEBUG_SetAppDomain()
- {
- WRAPPER_NO_CONTRACT;
-
- DEBUG_SetAppDomain(::GetAppDomain());
- }
-#endif //!DACCESS_COMPILE
-
- void DEBUG_SetAppDomain(AppDomain *pDomain);
-#endif //_DEBUG
-
// DO NOT ADD ANY ASSERTS TO THIS METHOD.
// DO NOT USE THIS METHOD.
// Yes folks, for better or worse the debugger pokes supposed object addresses
/*
* Object ref setting routines. You must use these to do
- * proper write barrier support, as well as app domain
- * leak checking.
- *
- * Note that the AppDomain parameter is the app domain affinity
- * of the object containing the field or value class. It should
- * be NULL if the containing object is app domain agile. Note that
- * you typically get this value by calling obj->GetAppDomain() on
- * the containing object.
+ * proper write barrier support.
*/
// SetObjectReference sets an OBJECTREF field
// Initialize value class argument
void InitValueClassArg(ArgDestination *argDest, MethodTable *pMT);
-#define SetObjectReference(_d,_r,_a) SetObjectReferenceUnchecked(_d, _r)
-#define CopyValueClass(_d,_s,_m,_a) CopyValueClassUnchecked(_d,_s,_m)
-#define CopyValueClassArg(_d,_s,_m,_a,_o) CopyValueClassArgUnchecked(_d,_s,_m,_o)
+#define SetObjectReference(_d,_r) SetObjectReferenceUnchecked(_d, _r)
+#define CopyValueClass(_d,_s,_m) CopyValueClassUnchecked(_d,_s,_m)
+#define CopyValueClassArg(_d,_s,_m,_o) CopyValueClassArgUnchecked(_d,_s,_m,_o)
#include <pshpack4.h>
friend class GCHeap;
friend class CObjectHeader;
friend class Object;
- friend OBJECTREF AllocateArrayEx(MethodTable *pArrayMT, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap DEBUG_ARG(BOOL bDontSetAppDomain));
+ friend OBJECTREF AllocateArrayEx(MethodTable *pArrayMT, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap);
friend OBJECTREF FastAllocatePrimitiveArray(MethodTable* arrayType, DWORD cElements, BOOL bAllocateInLargeHeap);
friend FCDECL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size);
friend FCDECL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size);
}
CONTRACTL_END;
_ASSERTE(i < GetNumComponents());
- SetObjectReference(m_Array + i, ref, GetAppDomain());
+ SetObjectReference(m_Array + i, ref);
}
void ClearAt(SIZE_T i)
CONTRACTL_END;
INDEBUG(TypeCheck());
- SetObjectReference(&m_keepalive, keepalive, GetAppDomain());
+ SetObjectReference(&m_keepalive, keepalive);
}
TypeHandle GetType() {
void SetKeepAlive(OBJECTREF keepalive)
{
WRAPPER_NO_CONTRACT;
- SetObjectReference(&m_object, keepalive, GetAppDomain());
+ SetObjectReference(&m_object, keepalive);
}
MethodDesc *GetMethod() {
void SetKeepAlive(OBJECTREF keepalive)
{
WRAPPER_NO_CONTRACT;
- SetObjectReference(&m_object, keepalive, GetAppDomain());
+ SetObjectReference(&m_object, keepalive);
}
FieldDesc *GetField() {
void SetAssembly(OBJECTREF assembly)
{
WRAPPER_NO_CONTRACT;
- SetObjectReference(&m_runtimeAssembly, assembly, GetAppDomain());
+ SetObjectReference(&m_runtimeAssembly, assembly);
}
};
_ASSERTE(newThreadStartArg == NULL);
// Note: this is an unchecked assignment. We are cleaning out the ThreadStartArg field when
// a thread starts so that ADU does not cause problems
- SetObjectReferenceUnchecked( (OBJECTREF *)&m_ThreadStartArg, newThreadStartArg);
+ SetObjectReference( (OBJECTREF *)&m_ThreadStartArg, newThreadStartArg);
}
void SetSyncRoot(OBJECTREF pSyncRoot)
{
WRAPPER_NO_CONTRACT;
- SetObjectReferenceUnchecked(&m_pSyncRoot, pSyncRoot);
+ SetObjectReference(&m_pSyncRoot, pSyncRoot);
}
};
NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, DomainAssembly *pAssembly, OBJECTREF keepAlive);
BOOL IsWrapperDelegate() { LIMITED_METHOD_CONTRACT; return _methodPtrAux == NULL; }
OBJECTREF GetTarget() { LIMITED_METHOD_CONTRACT; return _target; }
- void SetTarget(OBJECTREF target) { WRAPPER_NO_CONTRACT; SetObjectReference(&_target, target, GetAppDomain()); }
+ void SetTarget(OBJECTREF target) { WRAPPER_NO_CONTRACT; SetObjectReference(&_target, target); }
static int GetOffsetOfTarget() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _target); }
PCODE GetMethodPtr() { LIMITED_METHOD_CONTRACT; return _methodPtr; }
static int GetOffsetOfMethodPtrAux() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _methodPtrAux); }
OBJECTREF GetInvocationList() { LIMITED_METHOD_CONTRACT; return _invocationList; }
- void SetInvocationList(OBJECTREF invocationList) { WRAPPER_NO_CONTRACT; SetObjectReference(&_invocationList, invocationList, GetAppDomain()); }
+ void SetInvocationList(OBJECTREF invocationList) { WRAPPER_NO_CONTRACT; SetObjectReference(&_invocationList, invocationList); }
static int GetOffsetOfInvocationList() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _invocationList); }
INT_PTR GetInvocationCount() { LIMITED_METHOD_CONTRACT; return _invocationCount; }
void SetInvocationCount(INT_PTR invocationCount) { LIMITED_METHOD_CONTRACT; _invocationCount = invocationCount; }
static int GetOffsetOfInvocationCount() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _invocationCount); }
- void SetMethodBase(OBJECTREF newMethodBase) { LIMITED_METHOD_CONTRACT; SetObjectReference((OBJECTREF*)&_methodBase, newMethodBase, GetAppDomain()); }
+ void SetMethodBase(OBJECTREF newMethodBase) { LIMITED_METHOD_CONTRACT; SetObjectReference((OBJECTREF*)&_methodBase, newMethodBase); }
// README:
// If you modify the order of these fields, make sure to update the definition in
void SetHandleTable(PTRARRAYREF handleTable)
{
LIMITED_METHOD_CONTRACT;
- SetObjectReferenceUnchecked(&m_pSlots, (OBJECTREF)handleTable);
+ SetObjectReference(&m_pSlots, (OBJECTREF)handleTable);
}
INT32 GetSlotsUsed()
void SetInnerException(OBJECTREF innerException)
{
WRAPPER_NO_CONTRACT;
- SetObjectReference((OBJECTREF*)&_innerException, (OBJECTREF)innerException, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&_innerException, (OBJECTREF)innerException);
}
OBJECTREF GetInnerException()
void SetMessage(STRINGREF message)
{
WRAPPER_NO_CONTRACT;
- SetObjectReference((OBJECTREF*)&_message, (OBJECTREF)message, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&_message, (OBJECTREF)message);
}
STRINGREF GetMessage()
void SetStackTraceString(STRINGREF stackTraceString)
{
WRAPPER_NO_CONTRACT;
- SetObjectReference((OBJECTREF*)&_stackTraceString, (OBJECTREF)stackTraceString, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&_stackTraceString, (OBJECTREF)stackTraceString);
}
STRINGREF GetStackTraceString()
void SetHelpURL(STRINGREF helpURL)
{
WRAPPER_NO_CONTRACT;
- SetObjectReference((OBJECTREF*)&_helpURL, (OBJECTREF)helpURL, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&_helpURL, (OBJECTREF)helpURL);
}
void SetSource(STRINGREF source)
{
WRAPPER_NO_CONTRACT;
- SetObjectReference((OBJECTREF*)&_source, (OBJECTREF)source, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&_source, (OBJECTREF)source);
}
void ClearStackTraceForThrow()
{
WRAPPER_NO_CONTRACT;
- SetObjectReferenceUnchecked((OBJECTREF*)&_remoteStackTraceString, NULL);
- SetObjectReferenceUnchecked((OBJECTREF*)&_stackTrace, NULL);
- SetObjectReferenceUnchecked((OBJECTREF*)&_stackTraceString, NULL);
+ SetObjectReference((OBJECTREF*)&_remoteStackTraceString, NULL);
+ SetObjectReference((OBJECTREF*)&_stackTrace, NULL);
+ SetObjectReference((OBJECTREF*)&_stackTraceString, NULL);
}
void ClearStackTracePreservingRemoteStackTrace()
{
WRAPPER_NO_CONTRACT;
- SetObjectReferenceUnchecked((OBJECTREF*)&_stackTrace, NULL);
- SetObjectReferenceUnchecked((OBJECTREF*)&_stackTraceString, NULL);
+ SetObjectReference((OBJECTREF*)&_stackTrace, NULL);
+ SetObjectReference((OBJECTREF*)&_stackTraceString, NULL);
}
// This method will set the reference to the array
void SetWatsonBucketReference(OBJECTREF oWatsonBucketArray)
{
WRAPPER_NO_CONTRACT;
- SetObjectReference((OBJECTREF*)&_watsonBuckets, (OBJECTREF)oWatsonBucketArray, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&_watsonBuckets, (OBJECTREF)oWatsonBucketArray);
}
// This method will return the reference to the array
STATIC_CONTRACT_GC_NOTRIGGER;
STATIC_CONTRACT_MODE_COOPERATIVE;
- SetObjectReference((OBJECTREF*)&_data, (OBJECTREF)data, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&_data, (OBJECTREF)data);
}
protected:
return dac_cast<PTR_BYTE>(this) + sizeof(*this);
}
-inline ADIndex Object::GetAppDomainIndex()
-{
- WRAPPER_NO_CONTRACT;
-#ifndef _DEBUG
- // ok to cast to AppDomain because we know it's a real AppDomain if it's not shared
- return (dac_cast<PTR_AppDomain>(GetGCSafeMethodTable()->GetDomain())->GetIndex());
-#endif
- return GetHeader()->GetAppDomainIndex();
-}
-
inline DWORD Object::GetNumComponents()
{
LIMITED_METHOD_DAC_CONTRACT;
pCom = (OBJECTREF *) (unprotectedArray->GetAddress() + currentOffset);
}
- SetObjectReference(pCom++, obj, pDomain);
+ SetObjectReference(pCom++, obj);
}
}
GCPROTECT_END();
pCom = (STRINGREF *) (unprotectedArray->GetAddress() + currentOffset);
}
- SetObjectReference((OBJECTREF*) pCom++, (OBJECTREF) stringObj, pDomain);
+ SetObjectReference((OBJECTREF*) pCom++, (OBJECTREF) stringObj);
}
}
GCPROTECT_END();
pCom = (STRINGREF *) (unprotectedArray->GetAddress() + currentOffset);
}
- SetObjectReference((OBJECTREF*) pCom++, (OBJECTREF) string, pDomain);
+ SetObjectReference((OBJECTREF*) pCom++, (OBJECTREF) string);
}
}
pCom = (STRINGREF *) (unprotectedArray->GetAddress() + currentOffset);
}
- SetObjectReference((OBJECTREF*) pCom++, (OBJECTREF) string, pDomain);
+ SetObjectReference((OBJECTREF*) pCom++, (OBJECTREF) string);
}
}
{
case VT_EMPTY:
SetObjectReference( pObj,
- NULL,
- GetAppDomain() );
+ NULL );
break;
case VT_I4:
case VT_INT:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_I4)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_I4)) );
*(LONG*)((*pObj)->GetData()) = V_I4(pOle);
break;
case VT_BYREF|VT_I4:
case VT_BYREF|VT_INT:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_I4)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_I4)) );
*(LONG*)((*pObj)->GetData()) = *(V_I4REF(pOle));
break;
case VT_UI4:
case VT_UINT:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_U4)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_U4)) );
*(ULONG*)((*pObj)->GetData()) = V_UI4(pOle);
break;
case VT_BYREF|VT_UI4:
case VT_BYREF|VT_UINT:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_U4)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_U4)) );
*(ULONG*)((*pObj)->GetData()) = *(V_UI4REF(pOle));
break;
case VT_I2:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_I2)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_I2)) );
(*(SHORT*)((*pObj)->GetData())) = V_I2(pOle);
break;
case VT_BYREF|VT_I2:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_I2)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_I2)) );
*(SHORT*)((*pObj)->GetData()) = *(V_I2REF(pOle));
break;
case VT_UI2:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_U2)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_U2)) );
*(USHORT*)((*pObj)->GetData()) = V_UI2(pOle);
break;
case VT_BYREF|VT_UI2:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_U2)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_U2)) );
*(USHORT*)((*pObj)->GetData()) = *(V_UI2REF(pOle));
break;
case VT_I1:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_I1)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_I1)) );
*(CHAR*)((*pObj)->GetData()) = V_I1(pOle);
break;
case VT_BYREF|VT_I1:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_I1)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_I1)) );
*(CHAR*)((*pObj)->GetData()) = *(V_I1REF(pOle));
break;
case VT_UI1:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_U1)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_U1)) );
*(BYTE*)((*pObj)->GetData()) = V_UI1(pOle);
break;
case VT_BYREF|VT_UI1:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_U1)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_U1)) );
*(BYTE*)((*pObj)->GetData()) = *(V_UI1REF(pOle));
break;
case VT_R4:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_R4)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_R4)) );
*(FLOAT*)((*pObj)->GetData()) = V_R4(pOle);
break;
case VT_BYREF|VT_R4:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_R4)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_R4)) );
*(FLOAT*)((*pObj)->GetData()) = *(V_R4REF(pOle));
break;
case VT_R8:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_R8)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_R8)) );
*(DOUBLE*)((*pObj)->GetData()) = V_R8(pOle);
break;
case VT_BYREF|VT_R8:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_R8)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_R8)) );
*(DOUBLE*)((*pObj)->GetData()) = *(V_R8REF(pOle));
break;
case VT_BOOL:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_BOOLEAN)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_BOOLEAN)) );
*(VARIANT_BOOL*)((*pObj)->GetData()) = V_BOOL(pOle) ? 1 : 0;
break;
case VT_BYREF|VT_BOOL:
SetObjectReference( pObj,
- AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_BOOLEAN)),
- GetAppDomain() );
+ AllocateObject(MscorlibBinder::GetElementType(ELEMENT_TYPE_BOOLEAN)) );
*(VARIANT_BOOL*)((*pObj)->GetData()) = *(V_BOOLREF(pOle)) ? 1 : 0;
break;
OleVariant::MarshalComVariantForOleVariant((VARIANT*)pOle, &managedVariant);
ARG_SLOT args[] = { PtrToArgSlot(&managedVariant) };
SetObjectReference( pObj,
- convertVariantToObject.Call_RetOBJECTREF(args),
- GetAppDomain() );
+ convertVariantToObject.Call_RetOBJECTREF(args) );
}
GCPROTECT_END_VARIANTDATA();
}
BASEARRAYREF unprotectedArray = *pComArray;
OBJECTREF *pCom = (OBJECTREF *) unprotectedArray->GetDataPtr();
- AppDomain *pDomain = unprotectedArray->GetAppDomain();
-
OBJECTREF TmpObj = NULL;
GCPROTECT_BEGIN(TmpObj)
{
unprotectedArray = *pComArray;
pCom = (OBJECTREF *) (unprotectedArray->GetAddress() + currentOffset);
}
- SetObjectReference(pCom++, TmpObj, pDomain);
+ SetObjectReference(pCom++, TmpObj);
}
}
GCPROTECT_END();
GCPROTECT_BEGIN(DestArray)
{
SIZE_T NumComponents = (*pArray)->GetNumComponents();
- AppDomain *pDomain = DestArray->GetAppDomain();
if (hndWrapperType == TypeHandle(MscorlibBinder::GetClass(CLASS__DISPATCH_WRAPPER)))
{
DISPATCHWRAPPEROBJECTREF *pSrcEnd = pSrc + NumComponents;
OBJECTREF *pDest = (OBJECTREF *)DestArray->GetDataPtr();
for (; pSrc < pSrcEnd; pSrc++, pDest++)
- SetObjectReference(pDest, (*pSrc) != NULL ? (*pSrc)->GetWrappedObject() : NULL, pDomain);
+ SetObjectReference(pDest, (*pSrc) != NULL ? (*pSrc)->GetWrappedObject() : NULL);
}
else if (hndWrapperType == TypeHandle(MscorlibBinder::GetClass(CLASS__UNKNOWN_WRAPPER)))
{
UNKNOWNWRAPPEROBJECTREF *pSrcEnd = pSrc + NumComponents;
OBJECTREF *pDest = (OBJECTREF *)DestArray->GetDataPtr();
for (; pSrc < pSrcEnd; pSrc++, pDest++)
- SetObjectReference(pDest, (*pSrc) != NULL ? (*pSrc)->GetWrappedObject() : NULL, pDomain);
+ SetObjectReference(pDest, (*pSrc) != NULL ? (*pSrc)->GetWrappedObject() : NULL);
}
else if (hndWrapperType == TypeHandle(MscorlibBinder::GetClass(CLASS__ERROR_WRAPPER)))
{
BSTRWRAPPEROBJECTREF *pSrcEnd = pSrc + NumComponents;
OBJECTREF *pDest = (OBJECTREF *)DestArray->GetDataPtr();
for (; pSrc < pSrcEnd; pSrc++, pDest++)
- SetObjectReference(pDest, (*pSrc) != NULL ? (*pSrc)->GetWrappedObject() : NULL, pDomain);
+ SetObjectReference(pDest, (*pSrc) != NULL ? (*pSrc)->GetWrappedObject() : NULL);
}
else
{
// Check to see if the BSTR has trailing odd byte.
BOOL bHasTrailByte = ((length%sizeof(WCHAR)) != 0);
length = length / sizeof(WCHAR);
- SetObjectReference((OBJECTREF*)pStringObj, (OBJECTREF)StringObject::NewString(length, bHasTrailByte), GetAppDomain());
+ SetObjectReference((OBJECTREF*)pStringObj, (OBJECTREF)StringObject::NewString(length, bHasTrailByte));
}
void OleVariant::ConvertContentsBSTRToString(BSTR bstr, STRINGREF *pStringObj)
if (objRef!=NULL)
{
- SetObjectReferenceUnchecked((OBJECTREF*)&m_or, objRef);
+ SetObjectReference((OBJECTREF*)&m_or, objRef);
}
else
{
// < AppDomainCreationFinished issued
// < AD NOT available from catch-up enumeration
//
- // The AppDomainIterator constructor parameter m_bActive is set to be TRUE below,
- // meaning only AppDomains in stage STAGE_ACTIVE or higher will be included
- // in the iteration.
// * AppDomainCreationFinished (with S_OK hrStatus) is issued once the AppDomain
// reaches STAGE_ACTIVE.
- AppDomainIterator appDomainIterator(TRUE);
- while (appDomainIterator.Next())
+ AppDomain * pAppDomain = ::GetAppDomain();
+ if (pAppDomain->IsActive())
{
- AppDomain * pAppDomain = appDomainIterator.GetDomain();
// Of course, the AD could start unloading here, but if it does we're guaranteed
// the profiler has had a chance to see the Unload callback for the AD, and thus
// System.AppDomain.GetNativeHandle() should ensure that we're not calling through with a null AppDomain pointer.
_ASSERTE(m_pAppDomain);
-
- // QCalls should only be made with pointers to the current domain
- _ASSERTE(GetAppDomain() == m_pAppDomain);
-
- // We should not have a QCall made on an invalid AppDomain. Once unload a domain, we won't let anyone else
- // in and any threads that are already in will be unwound.
- _ASSERTE(SystemDomain::GetAppDomainAtIndex(m_pAppDomain->GetIndex()) != NULL);
}
#endif // _DEBUG
BOOL bWalkFailed = FALSE;
- //
- // Walk every AppDomain
- // Use UnsafeAppDomain iterator to avoid taking locks
- //
HRESULT hr = S_OK;
EX_TRY
{
- UnsafeAppDomainIterator appDomainIterator(TRUE);
- appDomainIterator.Init();
- while (appDomainIterator.Next())
{
- AppDomain *pDomain = appDomainIterator.GetDomain();
+ AppDomain *pDomain = ::GetAppDomain(); // There is only actually 1 AppDomain in CoreCLR, so no iterator
RCWRefCache *pRCWRefCache = pDomain->GetRCWRefCache();
_ASSERTE(pRCWRefCache != NULL);
// Shrink the dependent handle cache if necessary and clear unused handles.
//
pRCWRefCache->ShrinkDependentHandles();
-
- if (FAILED(hr))
- {
- break;
- }
}
}
EX_CATCH
gc.obj = allocMT->Allocate();
if (gc.value != NULL)
- CopyValueClassUnchecked(gc.obj->UnBox(), gc.value->UnBox(), allocMT);
+ CopyValueClass(gc.obj->UnBox(), gc.value->UnBox(), allocMT);
}
}
{
COMPlusThrow(kNullReferenceException, IDS_INVOKE_NULLREF_RETURNED);
}
- CopyValueClass(gc.retVal->GetData(), pReturnedReference, gc.retVal->GetMethodTable(), gc.retVal->GetAppDomain());
+ CopyValueClass(gc.retVal->GetData(), pReturnedReference, gc.retVal->GetMethodTable());
}
// if the structure is returned by value, then we need to copy in the boxed object
// we have allocated for this purpose.
else if (!fHasRetBuffArg)
{
- CopyValueClass(gc.retVal->GetData(), &callDescrData.returnValue, gc.retVal->GetMethodTable(), gc.retVal->GetAppDomain());
+ CopyValueClass(gc.retVal->GetData(), &callDescrData.returnValue, gc.retVal->GetMethodTable());
}
else if (pRetBufStackCopy)
{
- CopyValueClass(gc.retVal->GetData(), pRetBufStackCopy, gc.retVal->GetMethodTable(), gc.retVal->GetAppDomain());
+ CopyValueClass(gc.retVal->GetData(), pRetBufStackCopy, gc.retVal->GetMethodTable());
}
// From here on out, it is OK to have GCs since the return object (which may have had
// GC pointers has been put into a GC object and thus protected.
while (byRefToNullables != NULL) {
OBJECTREF obj = Nullable::Box(byRefToNullables->data, byRefToNullables->type.GetMethodTable());
- SetObjectReference(&gc.args->m_Array[byRefToNullables->argNum], obj, gc.args->GetAppDomain());
+ SetObjectReference(&gc.args->m_Array[byRefToNullables->argNum], obj);
byRefToNullables = byRefToNullables->next;
}
case ELEMENT_TYPE_ARRAY: // General Array
case ELEMENT_TYPE_CLASS:
case ELEMENT_TYPE_OBJECT:
- SetObjectReferenceUnchecked((OBJECTREF*)pDst, gc.oValue);
+ SetObjectReference((OBJECTREF*)pDst, gc.oValue);
break;
case ELEMENT_TYPE_VALUETYPE:
COUNT_T cIL = header.GetCodeSize();
gc.U1Array = (U1ARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_U1, cIL);
- SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_IL, gc.U1Array, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_IL, gc.U1Array);
memcpyNoGCRefs(gc.MethodBodyObj->_IL->GetDataPtr(), pIL, cIL);
// Allocate the array of exception clauses.
const COR_ILMETHOD_SECT_EH* ehInfo = header.EH;
gc.TempArray = (BASEARRAYREF) AllocateArrayEx(thEHClauseArray, &cEh, 1);
- SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_exceptionClauses, gc.TempArray, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_exceptionClauses, gc.TempArray);
for (INT32 i = 0; i < cEh; i++)
{
gc.EHClauseObj->_filterOffset = ehClause->GetFilterOffset();
gc.MethodBodyObj->_exceptionClauses->SetAt(i, (OBJECTREF) gc.EHClauseObj);
- SetObjectReference((OBJECTREF*)&(gc.EHClauseObj->_methodBody), (OBJECTREF)gc.MethodBodyObj, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&(gc.EHClauseObj->_methodBody), (OBJECTREF)gc.MethodBodyObj);
}
if (header.LocalVarSig != NULL)
MetaSig::sigLocalVars);
INT32 cLocals = metaSig.NumFixedArgs();
gc.TempArray = (BASEARRAYREF) AllocateArrayEx(thLocalVariableArray, &cLocals, 1);
- SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_localVariables, gc.TempArray, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_localVariables, gc.TempArray);
for (INT32 i = 0; i < cLocals; i ++)
{
{
INT32 cLocals = 0;
gc.TempArray = (BASEARRAYREF) AllocateArrayEx(thLocalVariableArray, &cLocals, 1);
- SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_localVariables, gc.TempArray, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_localVariables, gc.TempArray);
}
}
}
void SetType(OBJECTREF type)
{
- SetObjectReference(&_type, type, GetAppDomain());
+ SetObjectReference(&_type, type);
}
OBJECTREF _type;
MODE_COOPERATIVE;
}
CONTRACTL_END;
- SetObjectReference(&m_returnType, returnType, GetAppDomain());
+ SetObjectReference(&m_returnType, returnType);
}
void SetKeepAlive(OBJECTREF keepAlive)
MODE_COOPERATIVE;
}
CONTRACTL_END;
- SetObjectReference(&m_keepalive, keepAlive, GetAppDomain());
+ SetObjectReference(&m_keepalive, keepAlive);
}
void SetDeclaringType(REFLECTCLASSBASEREF declaringType)
MODE_COOPERATIVE;
}
CONTRACTL_END;
- SetObjectReference((OBJECTREF*)&m_declaringType, (OBJECTREF)declaringType, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&m_declaringType, (OBJECTREF)declaringType);
}
void SetArgumentArray(PTRARRAYREF ptrArrayarguments)
MODE_COOPERATIVE;
}
CONTRACTL_END;
- SetObjectReference((OBJECTREF*)&m_PtrArrayarguments, (OBJECTREF)ptrArrayarguments, GetAppDomain());
+ SetObjectReference((OBJECTREF*)&m_PtrArrayarguments, (OBJECTREF)ptrArrayarguments);
}
void SetArgument(INT32 argument, OBJECTREF argumentType)
void StackSampler::RecordJittingInfoInternal(MethodDesc* pMD, CORJIT_FLAGS flags)
{
- ADID dwDomainId = GetThread()->GetDomain()->GetId();
- JitInfoHashEntry entry(pMD, dwDomainId);
+ JitInfoHashEntry entry(pMD, flags);
// Record the domain in the hash map.
{
}
}
-// Obtain the domain ID in which the method was originally JITted, if
-// it was never JITted (Ngened) or the original app domain was unloaded
-// use the "defaultId" supplied.
-ADID StackSampler::GetDomainId(MethodDesc* pMD, const ADID& defaultId)
-{
- ADID adId;
- BOOL bPresent = FALSE;
- {
- CrstHolder ch(&m_crstJitInfo);
- bPresent = m_jitInfo.Lookup(pMD, &adId);
- }
- if (bPresent != FALSE)
- {
- return adId;
- }
- return defaultId;
-}
-
// Stack walk callback data.
struct WalkInfo
{
}
// Lookup the method desc and obtain info.
- ADID adId = pMdThread->GetDomain()->GetId();
- CountInfo info(adId);
+ CountInfo info;
m_countInfo.Lookup(pMD, &info);
// Record the current domain ID of the method's thread, i.e.,
// the method is last known to be executing.
- info.adDomainId = adId;
info.uCount++;
// Put the info back.
{
// Try to get the original app domain ID in which the method was JITTed, if not
// use the app domain ID the method was last seen executing.
- ADID adId = GetDomainId(freq[i].pMD, freq[i].info.adDomainId);
- JitAndCollectTrace(freq[i].pMD, adId);
+ JitAndCollectTrace(freq[i].pMD);
}
}
}
// Invoke the JIT for the method desc. Switch to the appropriate domain.
-void StackSampler::JitAndCollectTrace(MethodDesc* pMD, const ADID& adId)
+void StackSampler::JitAndCollectTrace(MethodDesc* pMD)
{
CONTRACTL
{
EX_TRY
{
- ENTER_DOMAIN_ID(adId)
{
GCX_PREEMP();
PCODE pCode = UnsafeJitFunction(NativeCodeVersion(pMD), pDecoder, flags);
}
- END_DOMAIN_TRANSITION;
// Update that this method has been already JITted.
- CountInfo info((ADID) DefaultADID);
+ CountInfo info;
m_countInfo.Lookup(pMD, &info);
info.fJitted = true;
m_countInfo.AddOrReplace(CountInfoHashEntry(pMD, info));
void JitFrequentMethodsInSamples();
- void JitAndCollectTrace(MethodDesc* pMD, const ADID& adId);
+ void JitAndCollectTrace(MethodDesc* pMD);
void RecordJittingInfoInternal(MethodDesc* pMD, CORJIT_FLAGS flags);
- ADID GetDomainId(MethodDesc* pMD, const ADID& defaultId);
// Constants
typedef MapSHash<MethodDesc*, CountInfo> CountInfoHash;
typedef CountInfoHash::element_t CountInfoHashEntry;
- typedef MapSHash<MethodDesc*, ADID> JitInfoHash;
+ typedef MapSHash<MethodDesc*, CORJIT_FLAGS> JitInfoHash;
typedef JitInfoHash::element_t JitInfoHashEntry;
// Nested types
{
unsigned uCount;
bool fJitted;
- ADID adDomainId;
- CountInfo(const ADID& adId) : adDomainId(adId), fJitted(false), uCount(0) {}
- CountInfo() {} // SHash doesn't like it
+ CountInfo() : fJitted(false), uCount(0) {}
};
// Fields
STRINGREF strObj = AllocateStringObject(pStringData);
// Allocate a handle for the string.
- SetObjectReference(pStrObj[0], (OBJECTREF) strObj, NULL);
+ SetObjectReference(pStrObj[0], (OBJECTREF) strObj);
// Allocate the StringLiteralEntry.
{
LargeHeapHandleBlockHolder pStrObj(&m_LargeHeapHandleTable,1);
- SetObjectReference(pStrObj[0], (OBJECTREF) *pString, NULL);
+ SetObjectReference(pStrObj[0], (OBJECTREF) *pString);
// Since the allocation might have caused a GC we need to re-get the
// string data.
} EE_END_FINALLY;
}
-// When a appdomain is unloading, we need to insure that any pointers to
-// it from sync blocks (eg from COM Callable Wrappers) are properly
-// updated so that they fail gracefully if another call is made from
-// them. This is what this routine does.
-//
-VOID SyncBlockCache::CleanupSyncBlocksInAppDomain(AppDomain *pDomain)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- THROWS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
-#ifndef DACCESS_COMPILE
- _ASSERTE(IsFinalizerThread());
-
- ADIndex index = pDomain->GetIndex();
-
- ADID id = pDomain->GetId();
-
- // Make sure we dont race with anybody updating the table
- DWORD maxIndex;
-
- {
- // Taking this lock here avoids races whre m_FreeSyncTableIndex is being updated.
- // (a volatile read would have been enough however).
- SyncBlockCache::LockHolder lh(SyncBlockCache::GetSyncBlockCache());
- maxIndex = m_FreeSyncTableIndex;
- }
- BOOL bModifiedCleanupList=FALSE;
- STRESS_LOG1(LF_APPDOMAIN, LL_INFO100, "To cleanup - %d sync blocks", maxIndex);
- DWORD nb;
- for (nb = 1; nb < maxIndex; nb++)
- {
- // This is a check for syncblocks that were already cleaned up.
- if ((size_t)SyncTableEntry::GetSyncTableEntry()[nb].m_Object.Load() & 1)
- {
- continue;
- }
-
- // If the syncblock pointer is invalid, nothing more we can do.
- SyncBlock *pSyncBlock = SyncTableEntry::GetSyncTableEntry()[nb].m_SyncBlock;
- if (!pSyncBlock)
- {
- continue;
- }
-
- // If we happen to have a CCW living in the AppDomain being cleaned, then we need to neuter it.
- // We do this check early because we have to neuter CCWs for agile objects as well.
- // Neutering the object simply means we disconnect the object from the CCW so it can no longer
- // be used. When its ref-count falls to zero, it gets cleaned up.
- STRESS_LOG1(LF_APPDOMAIN, LL_INFO1000000, "SyncBlock %p.", pSyncBlock);
- InteropSyncBlockInfo* pInteropInfo = pSyncBlock->GetInteropInfoNoCreate();
- if (pInteropInfo)
- {
-#ifdef FEATURE_COMINTEROP
- ComCallWrapper* pWrap = pInteropInfo->GetCCW();
- if (pWrap)
- {
- SimpleComCallWrapper* pSimpleWrapper = pWrap->GetSimpleWrapper();
- _ASSERTE(pSimpleWrapper);
-
- if (pSimpleWrapper->GetDomainID() == id)
- {
- pSimpleWrapper->Neuter();
- }
- }
-#endif // FEATURE_COMINTEROP
-
- UMEntryThunk* umThunk=(UMEntryThunk*)pInteropInfo->GetUMEntryThunk();
-
-#ifdef FEATURE_COMINTEROP
- {
- // we need to take RCWCache lock to avoid the race with another thread which is
- // removing the RCW from cache, decoupling it from the object, and deleting the RCW.
- RCWCache* pCache = pDomain->GetRCWCache();
- _ASSERTE(pCache);
- RCWCache::LockHolder lh(pCache);
- RCW* pRCW = pInteropInfo->GetRawRCW();
- if (pRCW && pRCW->GetDomain()==pDomain)
- {
- // We should have initialized the cleanup list with the
- // first RCW cache we created
- _ASSERTE(g_pRCWCleanupList != NULL);
-
- g_pRCWCleanupList->AddWrapper(pRCW);
-
- pCache->RemoveWrapper(pRCW);
- pInteropInfo->SetRawRCW(NULL);
- bModifiedCleanupList=TRUE;
- }
- }
-#endif // FEATURE_COMINTEROP
- }
- }
- STRESS_LOG1(LF_APPDOMAIN, LL_INFO100, "AD cleanup - %d sync blocks done", nb);
- // Make sure nobody decreased m_FreeSyncTableIndex behind our back (we would read
- // off table limits)
- _ASSERTE(maxIndex <= m_FreeSyncTableIndex);
-
- if (bModifiedCleanupList)
- GetThread()->SetSyncBlockCleanup();
-
- while (GetThread()->RequireSyncBlockCleanup()) //we also might have something in the cleanup list
- CleanupSyncBlocks();
-
-#ifdef _DEBUG
- {
- SyncBlockCache::LockHolder lh(SyncBlockCache::GetSyncBlockCache());
- DWORD maxIndex = m_FreeSyncTableIndex;
- for (DWORD nb = 1; nb < maxIndex; nb++)
- {
- if ((size_t)SyncTableEntry::GetSyncTableEntry()[nb].m_Object.Load() & 1)
- {
- continue;
- }
-
- // If the syncblock pointer is invalid, nothing more we can do.
- SyncBlock *pSyncBlock = SyncTableEntry::GetSyncTableEntry()[nb].m_SyncBlock;
- if (!pSyncBlock)
- {
- continue;
- }
- InteropSyncBlockInfo* pInteropInfo = pSyncBlock->GetInteropInfoNoCreate();
- if (pInteropInfo)
- {
- UMEntryThunk* umThunk=(UMEntryThunk*)pInteropInfo->GetUMEntryThunk();
-
- if (umThunk && umThunk->GetDomainId()==id)
- {
- _ASSERTE(!umThunk->GetObjectHandle());
- }
- }
-
- }
- }
-#endif
-
-#endif
-}
-
-
// create the sync block cache
/* static */
void SyncBlockCache::Attach()
LIMITED_METHOD_CONTRACT;
}
-// destroy the sync block cache
-// This method is NO longer called.
-#if 0
-void SyncBlockCache::DoDetach()
-{
- CONTRACTL
- {
- INSTANCE_CHECK;
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- Object *pObj;
- ObjHeader *pHeader;
-
-
- // Ensure that all the critical sections are released. This is particularly
- // important in DEBUG, because all critical sections are threaded onto a global
- // list which would otherwise be corrupted.
- for (DWORD i=0; i<m_FreeSyncTableIndex; i++)
- if (((size_t)SyncTableEntry::GetSyncTableEntry()[i].m_Object & 1) == 0)
- if (SyncTableEntry::GetSyncTableEntry()[i].m_SyncBlock)
- {
- // <TODO>@TODO -- If threads are executing during this detach, they will
- // fail in various ways:
- //
- // 1) They will race between us tearing these data structures down
- // as they navigate through them.
- //
- // 2) They will unexpectedly see the syncblock destroyed, even though
- // they hold the synchronization lock, or have been exposed out
- // to COM, etc.
- //
- // 3) The instance's hash code may change during the shutdown.
- //
- // The correct solution involves suspending the threads earlier, but
- // changing our suspension code so that it allows pumping if we are
- // in a shutdown case.
- //
- // </TODO>
-
- // Make sure this gets updated because the finalizer thread & others
- // will continue to run for a short while more during our shutdown.
- pObj = SyncTableEntry::GetSyncTableEntry()[i].m_Object;
- pHeader = pObj->GetHeader();
-
- {
- ENTER_SPIN_LOCK(pHeader);
- ADIndex appDomainIndex = pHeader->GetAppDomainIndex();
- if (! appDomainIndex.m_dwIndex)
- {
- SyncBlock* syncBlock = pObj->PassiveGetSyncBlock();
- if (syncBlock)
- appDomainIndex = syncBlock->GetAppDomainIndex();
- }
-
- pHeader->ResetIndex();
-
- if (appDomainIndex.m_dwIndex)
- {
- pHeader->SetIndex(appDomainIndex.m_dwIndex<<SBLK_APPDOMAIN_SHIFT);
- }
- LEAVE_SPIN_LOCK(pHeader);
- }
-
- SyncTableEntry::GetSyncTableEntry()[i].m_Object = (Object *)(m_FreeSyncTableList | 1);
- m_FreeSyncTableList = i << 1;
-
- DeleteSyncBlock(SyncTableEntry::GetSyncTableEntry()[i].m_SyncBlock);
- }
-}
-#endif
-
-// destroy the sync block cache
-/* static */
-// This method is NO longer called.
-#if 0
-void SyncBlockCache::Detach()
-{
- SyncBlockCache::GetSyncBlockCache()->DoDetach();
-}
-#endif
-
-
// create the sync block cache
/* static */
void SyncBlockCache::Start()
descrip = param.descrip;
isString = param.isString;
}
- ADIndex idx;
- if (oref)
- idx = pEntry->m_Object->GetHeader()->GetRawAppDomainIndex();
- if (! idx.m_dwIndex && pEntry->m_SyncBlock)
- idx = pEntry->m_SyncBlock->GetAppDomainIndex();
- if (idx.m_dwIndex && ! SystemDomain::System()->TestGetAppDomainAtIndex(idx))
- {
- sprintf_s(buffer, COUNTOF(buffer), "** unloaded (%3.3x) %s", idx.m_dwIndex, descrip);
- descrip = buffer;
- }
- else
- {
- sprintf_s(buffer, COUNTOF(buffer), "(AD %3.3x) %s", idx.m_dwIndex, descrip);
- descrip = buffer;
- }
+ sprintf_s(buffer, COUNTOF(buffer), "%s", descrip);
+ descrip = buffer;
}
if (dumpSBStyle < 2)
LogSpewAlways("[%4.4d]: %8.8x %s\n", nb, oref, descrip);
#endif //!DACCESS_COMPILE
-ADIndex ObjHeader::GetRawAppDomainIndex()
-{
- LIMITED_METHOD_CONTRACT;
- SUPPORTS_DAC;
-
- // pull the value out before checking it to avoid race condition
- DWORD value = m_SyncBlockValue.LoadWithoutBarrier();
- if ((value & BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX) == 0)
- return ADIndex((value >> SBLK_APPDOMAIN_SHIFT) & SBLK_MASK_APPDOMAININDEX);
- return ADIndex(0);
-}
-
-ADIndex ObjHeader::GetAppDomainIndex()
-{
- STATIC_CONTRACT_NOTHROW;
- STATIC_CONTRACT_GC_NOTRIGGER;
- STATIC_CONTRACT_SUPPORTS_DAC;
-
- ADIndex indx = GetRawAppDomainIndex();
- if (indx.m_dwIndex)
- return indx;
- SyncBlock* syncBlock = PassiveGetSyncBlock();
- if (! syncBlock)
- return ADIndex(0);
-
- return syncBlock->GetAppDomainIndex();
-}
-
#ifndef DACCESS_COMPILE
-void ObjHeader::SetAppDomainIndex(ADIndex indx)
-{
- CONTRACTL
- {
- INSTANCE_CHECK;
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- INJECT_FAULT(COMPlusThrowOM(););
- }
- CONTRACTL_END;
-
- //
- // This should only be called during the header initialization,
- // so don't worry about races.
- //
-
- BOOL done = FALSE;
-
-#ifdef _DEBUG
- static int forceSB = -1;
-
- if (forceSB == -1)
- forceSB = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ADForceSB);
-
- if (forceSB)
- // force a synblock so we get one for every object.
- GetSyncBlock();
-#endif
-
- if (GetHeaderSyncBlockIndex() == 0 && indx.m_dwIndex < SBLK_MASK_APPDOMAININDEX)
- {
- ENTER_SPIN_LOCK(this);
- //Try one more time
- if (GetHeaderSyncBlockIndex() == 0)
- {
- _ASSERTE(GetRawAppDomainIndex().m_dwIndex == 0);
- // can store it in the object header
- FastInterlockOr(&m_SyncBlockValue, indx.m_dwIndex << SBLK_APPDOMAIN_SHIFT);
- done = TRUE;
- }
- LEAVE_SPIN_LOCK(this);
- }
-
- if (!done)
- {
- // must create a syncblock entry and store the appdomain indx there
- SyncBlock *psb = GetSyncBlock();
- _ASSERTE(psb);
- psb->SetAppDomainIndex(indx);
- }
-}
-
-void ObjHeader::ResetAppDomainIndex(ADIndex indx)
-{
- CONTRACTL
- {
- INSTANCE_CHECK;
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- //
- // This should only be called during the header initialization,
- // so don't worry about races.
- //
-
- BOOL done = FALSE;
-
- if (GetHeaderSyncBlockIndex() == 0 && indx.m_dwIndex < SBLK_MASK_APPDOMAININDEX)
- {
- ENTER_SPIN_LOCK(this);
- //Try one more time
- if (GetHeaderSyncBlockIndex() == 0)
- {
- // can store it in the object header
- while (TRUE)
- {
- DWORD oldValue = m_SyncBlockValue.LoadWithoutBarrier();
- DWORD newValue = (oldValue & (~(SBLK_MASK_APPDOMAININDEX << SBLK_APPDOMAIN_SHIFT))) |
- (indx.m_dwIndex << SBLK_APPDOMAIN_SHIFT);
- if (FastInterlockCompareExchange((LONG*)&m_SyncBlockValue,
- newValue,
- oldValue) == (LONG)oldValue)
- {
- break;
- }
- }
- done = TRUE;
- }
- LEAVE_SPIN_LOCK(this);
- }
-
- if (!done)
- {
- // must create a syncblock entry and store the appdomain indx there
- SyncBlock *psb = GetSyncBlock();
- _ASSERTE(psb);
- psb->SetAppDomainIndex(indx);
- }
-}
-
-void ObjHeader::ResetAppDomainIndexNoFailure(ADIndex indx)
-{
- CONTRACTL
- {
- INSTANCE_CHECK;
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(indx.m_dwIndex < SBLK_MASK_APPDOMAININDEX);
- }
- CONTRACTL_END;
-
- ENTER_SPIN_LOCK(this);
- if (GetHeaderSyncBlockIndex() == 0)
- {
- // can store it in the object header
- while (TRUE)
- {
- DWORD oldValue = m_SyncBlockValue.LoadWithoutBarrier();
- DWORD newValue = (oldValue & (~(SBLK_MASK_APPDOMAININDEX << SBLK_APPDOMAIN_SHIFT))) |
- (indx.m_dwIndex << SBLK_APPDOMAIN_SHIFT);
- if (FastInterlockCompareExchange((LONG*)&m_SyncBlockValue,
- newValue,
- oldValue) == (LONG)oldValue)
- {
- break;
- }
- }
- }
- else
- {
- SyncBlock *psb = PassiveGetSyncBlock();
- _ASSERTE(psb);
- psb->SetAppDomainIndex(indx);
- }
- LEAVE_SPIN_LOCK(this);
-}
-
DWORD ObjHeader::GetSyncBlockIndex()
{
CONTRACTL
if ((indx = GetHeaderSyncBlockIndex()) == 0)
{
BOOL fMustCreateSyncBlock = FALSE;
-
- if (GetAppDomainIndex().m_dwIndex)
- {
- // if have an appdomain set then must create a sync block to store it
- fMustCreateSyncBlock = TRUE;
- }
- else
{
//Need to get it from the cache
SyncBlockCache::LockHolder lh(SyncBlockCache::GetSyncBlockCache());
// Now the header will be stable - check whether hashcode, appdomain index or lock information is stored in it.
DWORD bits = GetBits();
if (((bits & (BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX | BIT_SBLK_IS_HASHCODE)) == (BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX | BIT_SBLK_IS_HASHCODE)) ||
- ((bits & BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX) == 0 &&
- (bits & ((SBLK_MASK_APPDOMAININDEX<<SBLK_APPDOMAIN_SHIFT)|SBLK_MASK_LOCK_RECLEVEL|SBLK_MASK_LOCK_THREADID)) != 0))
+ ((bits & BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX) == 0))
{
// Need a sync block to store this info
fMustCreateSyncBlock = TRUE;
// BIT_SBLK_STRING_HIGH_CHARS_KNOWN 0x40000000
// BIT_SBLK_STRING_HAS_SPECIAL_SORT 0xC0000000
//for other objects:
- // BIT_SBLK_AGILE_IN_PROGRESS 0x80000000
// BIT_SBLK_FINALIZER_RUN 0x40000000
if (bits & BIT_SBLK_STRING_HIGH_CHAR_MASK)
{
}
else
{
- //BIT_SBLK_AGILE_IN_PROGRESS is set only in debug build
- ASSERT_AND_CHECK (!(bits & BIT_SBLK_AGILE_IN_PROGRESS));
if (bits & BIT_SBLK_FINALIZER_RUN)
{
ASSERT_AND_CHECK (obj->GetGCSafeMethodTable ()->HasFinalizer ());
//if thread ID is 0, recursionLeve got to be zero
//but thread ID doesn't have to be valid because the lock could be orphanend
ASSERT_AND_CHECK (lockThreadId != 0 || recursionLevel == 0 );
-
-#ifndef _DEBUG
- DWORD adIndex = (bits >> SBLK_APPDOMAIN_SHIFT) & SBLK_MASK_APPDOMAININDEX;
- //in non debug build, objects do not have appdomain index in header
- ASSERT_AND_CHECK (adIndex == 0);
-#endif //!_DEBUG
}
return TRUE;
new (syncBlock) SyncBlock(indx);
{
- // after this point, nobody can update the index in the header to give an AD index
+ // after this point, nobody can update the index in the header
ENTER_SPIN_LOCK(this);
{
- // If there's an appdomain index stored in the header, transfer it to the syncblock
-
- ADIndex dwAppDomainIndex = GetAppDomainIndex();
- if (dwAppDomainIndex.m_dwIndex)
- syncBlock->SetAppDomainIndex(dwAppDomainIndex);
-
// If the thin lock in the header is in use, transfer the information to the syncblock
DWORD bits = GetBits();
if ((bits & BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX) == 0)
CONTRACTL_END;
Thread *pCurThread = GetThread();
- TESTHOOKCALL(AppDomainCanBeUnloaded(pCurThread->GetDomain()->GetId().m_dwId, FALSE));
+ TESTHOOKCALL(AppDomainCanBeUnloaded(DefaultADID, FALSE));
if (pCurThread->IsAbortRequested())
{
// Store the field info (should only ever happen once)
_ASSERTE( m_pEnCInfo == NULL );
m_pEnCInfo = pEnCInfo;
-
- // Also store the AppDomain that this object lives in.
- // Also verify that the AD was either not yet set, or set correctly before overwriting it.
- // I'm not sure why it should ever be set to the default domain and then changed to a different domain,
- // perhaps that can be removed.
- _ASSERTE (m_dwAppDomainIndex.m_dwIndex == 0 ||
- m_dwAppDomainIndex == SystemDomain::System()->DefaultDomain()->GetIndex() ||
- m_dwAppDomainIndex == GetAppDomain()->GetIndex());
- m_dwAppDomainIndex = GetAppDomain()->GetIndex();
}
#endif // EnC_SUPPORTED
#endif // !DACCESS_COMPILE
// so the value of this bit does not matter for strings
#define BIT_SBLK_STRING_HAS_NO_HIGH_CHARS 0x80000000
-// Used as workaround for infinite loop case. Will set this bit in the sblk if we have already
-// seen this sblk in our agile checking logic. Problem is seen when object 1 has a ref to object 2
-// and object 2 has a ref to object 1. The agile checker will infinitely loop on these references.
-#define BIT_SBLK_AGILE_IN_PROGRESS 0x80000000
#define BIT_SBLK_STRING_HIGH_CHARS_KNOWN 0x40000000
#define BIT_SBLK_STRING_HAS_SPECIAL_SORT 0xC0000000
#define BIT_SBLK_STRING_HIGH_CHAR_MASK 0xC0000000
// value is zero if no thread is holding the lock
// - following six bits (bits 10 thru 15) is recursion level used for the thin locks
// value is zero if lock is not taken or only taken once by the same thread
-// - following 11 bits (bits 16 thru 26) is app domain index
-// value is zero if no app domain index is set for the object
#define SBLK_MASK_LOCK_THREADID 0x000003FF // special value of 0 + 1023 thread ids
#define SBLK_MASK_LOCK_RECLEVEL 0x0000FC00 // 64 recursion levels
#define SBLK_LOCK_RECLEVEL_INC 0x00000400 // each level is this much higher than the previous one
-#define SBLK_APPDOMAIN_SHIFT 16 // shift right this much to get appdomain index
#define SBLK_RECLEVEL_SHIFT 10 // shift right this much to get recursion level
-#define SBLK_MASK_APPDOMAININDEX 0x000007FF // 2048 appdomain indices
// add more bits here... (adjusting the following mask to make room)
// space for the minimum, which is the pointer within an SLink.
SLink m_Link;
- // This is the index for the appdomain to which the object belongs. If we
- // can't set it in the object header, then we set it here. Note that an
- // object doesn't always have this filled in. Only for COM interop,
- // finalizers and objects in handles
- ADIndex m_dwAppDomainIndex;
-
// This is the hash code for the object. It can either have been transfered
// from the header dword, in which case it will be limited to 26 bits, or
// have been generated right into this member variable here, when it will
void SetEnCInfo(EnCSyncBlockInfo *pEnCInfo);
#endif // EnC_SUPPORTED
- ADIndex GetAppDomainIndex()
- {
- LIMITED_METHOD_DAC_CONTRACT;
- return m_dwAppDomainIndex;
- }
-
- void SetAppDomainIndex(ADIndex dwAppDomainIndex)
- {
- WRAPPER_NO_CONTRACT;
- SetPrecious();
- m_dwAppDomainIndex = dwAppDomainIndex;
- }
-
DWORD GetHashCode()
{
LIMITED_METHOD_CONTRACT;
void CleanupSyncBlocks();
- void CleanupSyncBlocksInAppDomain(AppDomain *pDomain);
-
int GetTableEntryCount()
{
LIMITED_METHOD_CONTRACT;
}
CONTRACTL_END
-
-#ifdef _DEBUG
- // if we have an index here, make sure we already transferred it to the syncblock
- // before we clear it out
- ADIndex adIndex = GetRawAppDomainIndex();
- if (adIndex.m_dwIndex)
- {
- SyncBlock *pSyncBlock = SyncTableEntry::GetSyncTableEntry() [indx & ~BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX].m_SyncBlock;
- _ASSERTE(pSyncBlock && pSyncBlock->GetAppDomainIndex() == adIndex);
- }
-#endif
-
LONG newValue;
LONG oldValue;
while (TRUE) {
m_SyncBlockValue.RawValue() &=~(BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX | BIT_SBLK_IS_HASHCODE | MASK_SYNCBLOCKINDEX);
}
- void SetAppDomainIndex(ADIndex);
- void ResetAppDomainIndex(ADIndex);
- void ResetAppDomainIndexNoFailure(ADIndex);
- ADIndex GetRawAppDomainIndex();
- ADIndex GetAppDomainIndex();
-
// For now, use interlocked operations to twiddle bits in the bitfield portion.
// If we ever have high-performance requirements where we can guarantee that no
// other threads are accessing the ObjHeader, this can be reconsidered for those
return DwfreeIndex;
}
-
-void PerAppDomainTPCountList::SetAppDomainId(TPIndex index, ADID id)
-{
- CONTRACTL
- {
- NOTHROW;
- MODE_ANY;
- GC_TRIGGERS;
- }
- CONTRACTL_END;
-
- IPerAppDomainTPCount * pAdCount = dac_cast<PTR_IPerAppDomainTPCount>(s_appDomainIndexList.Get(index.m_dwIndex-1));
-
- //SetAppDomainID needs to be called after the PerDomainCount has been
- //succesfully allocated for the appdomain.
- _ASSERTE(pAdCount);
-
- STRESS_LOG2(LF_THREADPOOL, LL_INFO1000, "SetAppDomainId: index %d id %d\n", index.m_dwIndex, id.m_dwId);
- pAdCount->SetAppDomainId(id);
-}
-
//---------------------------------------------------------------------------
//ResetAppDomainIndex: Resets the AppDomain ID and the per-appdomain
// thread pool counts
//
_ASSERTE(m_index.m_dwIndex != UNUSED_THREADPOOL_INDEX);
- _ASSERTE(m_id.m_dwId != 0);
#ifndef DACCESS_COMPILE
LONG count = VolatileLoad(&m_numRequestsPending);
//the TpIndex is set to unused.
_ASSERTE(m_index.m_dwIndex != UNUSED_THREADPOOL_INDEX);
- _ASSERTE(m_id.m_dwId != 0);
LONG count = VolatileLoad(&m_numRequestsPending);
while (count > 0)
//
{
- ADID appDomainId(m_id);
-
// This TPIndex may have been recycled since we chose it for workitem dispatch.
- // Thus it's possible for the ADID we just read to refer to an AppDomain that's still
- // being created. If so, the new AppDomain will necessarily have zero requests
+ // If so, the new AppDomain will necessarily have zero requests
// pending (because the destruction of the previous AD that used this TPIndex
// will have reset this object). We don't want to call into such an AppDomain.
// TODO: fix this another way!
// if (IsRequestPending())
{
- ManagedThreadBase::ThreadPool(appDomainId, QueueUserWorkItemManagedCallback, wasNotRecalled);
+ ManagedThreadBase::ThreadPool(QueueUserWorkItemManagedCallback, wasNotRecalled);
}
if (pThread->IsAbortRequested())
{
// thread was aborted, and may not have had a chance to tell us it has work.
- ENTER_DOMAIN_ID(m_id)
- {
- ThreadpoolMgr::SetAppDomainRequestsActive();
- ThreadpoolMgr::QueueUserWorkItem(NULL,
- NULL,
- 0,
- FALSE);
-
- }
- END_DOMAIN_TRANSITION;
+ ThreadpoolMgr::SetAppDomainRequestsActive();
+ ThreadpoolMgr::QueueUserWorkItem(NULL,
+ NULL,
+ 0,
+ FALSE);
}
}
//Takes care of dispatching requests in the right domain.
virtual void DispatchWorkItem(bool* foundWork, bool* wasNotRecalled) = 0;
- virtual void SetAppDomainId(ADID id) = 0;
virtual void SetTPIndexUnused() = 0;
virtual BOOL IsTPIndexUnused() = 0;
virtual void SetTPIndex(TPIndex index) = 0;
{
LIMITED_METHOD_CONTRACT;
VolatileStore(&m_numRequestsPending, (LONG)0);
- m_id.m_dwId = 0;
}
inline BOOL IsRequestPending()
void ClearAppDomainRequestsActive();
bool TakeActiveRequest();
- inline void SetAppDomainId(ADID id)
- {
- LIMITED_METHOD_CONTRACT;
- //This function should be called during appdomain creation when no managed code
- //has started running yet. That implies, no requests should be pending
- //or dispatched to this structure yet.
-
- _ASSERTE(m_id.m_dwId == 0);
-
- m_id = id;
- }
-
inline void SetTPIndex(TPIndex index)
{
LIMITED_METHOD_CONTRACT;
//has started running yet. That implies, no requests should be pending
//or dispatched to this structure yet.
- _ASSERTE(m_id.m_dwId == 0);
_ASSERTE(m_index.m_dwIndex == UNUSED_THREADPOOL_INDEX);
m_index = index;
LIMITED_METHOD_CONTRACT;
if (m_index.m_dwIndex == UNUSED_THREADPOOL_INDEX)
{
- //This function is called during appdomain creation, and no new appdomains can be
- //added removed at this time. So, make sure that the per-appdomain structures that
- //have been cleared(reclaimed) don't have any pending requests to them.
-
- _ASSERTE(m_id.m_dwId == 0);
-
return TRUE;
}
inline void SetTPIndexUnused()
{
WRAPPER_NO_CONTRACT;
- //This function should be called during appdomain unload when all threads have
- //succesfully exited the appdomain. That implies, no requests should be pending
- //or dispatched to this structure.
-
- _ASSERTE(m_id.m_dwId == 0);
-
m_index.m_dwIndex = UNUSED_THREADPOOL_INDEX;
}
void DispatchWorkItem(bool* foundWork, bool* wasNotRecalled);
private:
- ADID m_id;
TPIndex m_index;
struct DECLSPEC_ALIGN(MAX_CACHE_LINE_SIZE) {
BYTE m_padding1[MAX_CACHE_LINE_SIZE - sizeof(LONG)];
bool TakeActiveRequest();
- inline void SetAppDomainId(ADID id)
- {
- }
-
void QueueUnmanagedWorkRequest(LPTHREAD_START_ROUTINE function, PVOID context);
PVOID DeQueueUnManagedWorkRequest(bool* lastOne);
static void ResetAppDomainIndex(TPIndex index);
static bool AreRequestsPendingInAnyAppDomains();
static LONG GetAppDomainIndexForThreadpoolDispatch();
- static void SetAppDomainId(TPIndex index, ADID id);
static TPIndex AddNewTPIndex();
inline static IPerAppDomainTPCount* GetPerAppdomainCount(TPIndex index)
static DWORD dwHashCodeSeed = 123456789;
-#ifdef _DEBUG
-void CheckADValidity(AppDomain* pDomain, DWORD ADValidityKind)
-{
- CONTRACTL
- {
- NOTHROW;
- FORBID_FAULT;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- //
- // Note: this apparently checks if any one of the supplied conditions is satisified, rather
- // than checking that *all* of them are satisfied. One would have expected it to assert all of the
- // conditions but it does not.
- //
-
- CONTRACT_VIOLATION(FaultViolation);
- if (::GetAppDomain()==pDomain)
- return;
- if ((ADValidityKind & ADV_DEFAULTAD) &&
- pDomain->IsDefaultDomain())
- return;
- if ((ADValidityKind & ADV_ITERATOR) &&
- pDomain->IsHeldByIterator())
- return;
- if ((ADValidityKind & ADV_CREATING) &&
- pDomain->IsBeingCreated())
- return;
- if ((ADValidityKind & ADV_COMPILATION) &&
- pDomain->IsCompilationDomain())
- return;
- if ((ADValidityKind & ADV_FINALIZER) &&
- IsFinalizerThread())
- return;
- if ((ADValidityKind & ADV_RUNNINGIN) &&
- pDomain->IsRunningIn(GetThread()))
- return;
- if ((ADValidityKind & ADV_REFTAKER) &&
- pDomain->IsHeldByRefTaker())
- return;
-
- _ASSERTE(!"Appdomain* can be invalid");
-}
-#endif
-
-
//--------------------------------------------------------------------
// Thread construction
//--------------------------------------------------------------------
Thread *pThread = GetThread();
InitContext();
- if (pThread)
- {
- _ASSERTE(pThread->GetDomain());
- // Start off the new thread in the default context of
- // the creating thread's appDomain. This could be changed by SetDelegate
- SetKickOffDomainId(pThread->GetDomain()->GetId());
- } else
- SetKickOffDomainId((ADID)DefaultADID);
// Do not expose thread until it is fully constructed
g_pThinLockThreadIdDispenser->NewId(this, this->m_ThreadId);
return m_debuggerCantStop != 0;
}
-
-//-----------------------------------------------------------------------------
-// Call w/a wrapper.
-// We've already transitioned AppDomains here. This just places a 1st-pass filter to sniff
-// for catch-handler found callbacks for the debugger.
-//-----------------------------------------------------------------------------
-void MakeADCallDebuggerWrapper(
- FPAPPDOMAINCALLBACK fpCallback,
- CtxTransitionBaseArgs * args,
- ContextTransitionFrame* pFrame)
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_GC_TRIGGERS;
- STATIC_CONTRACT_MODE_ANY;
-
- BYTE * pCatcherStackAddr = (BYTE*) pFrame;
-
- struct Param : NotifyOfCHFFilterWrapperParam
- {
- FPAPPDOMAINCALLBACK fpCallback;
- CtxTransitionBaseArgs *args;
- } param;
- param.pFrame = pCatcherStackAddr;
- param.fpCallback = fpCallback;
- param.args = args;
-
- PAL_TRY(Param *, pParam, ¶m)
- {
- pParam->fpCallback(pParam->args);
- }
- PAL_EXCEPT_FILTER(AppDomainTransitionExceptionFilter)
- {
- // Should never reach here b/c handler should always continue search.
- _ASSERTE(false);
- }
- PAL_ENDTRY
-}
-
-
-// Invoke a callback in another appdomain.
-// Caller should have checked that we're actually transitioning domains here.
-void MakeCallWithAppDomainTransition(
- ADID TargetDomain,
- FPAPPDOMAINCALLBACK fpCallback,
- CtxTransitionBaseArgs * args)
-{
- DEBUG_ASSURE_NO_RETURN_BEGIN(MAKECALL)
-
- Thread* _ctx_trans_pThread = GetThread();
- TESTHOOKCALL(EnteringAppDomain((TargetDomain.m_dwId)));
- AppDomain* pTargetDomain = SystemDomain::GetAppDomainFromId(TargetDomain, ADV_CURRENTAD);
- _ASSERTE(_ctx_trans_pThread != NULL);
- _ASSERTE(_ctx_trans_pThread->GetDomain()->GetId()!= TargetDomain);
-
- bool _ctx_trans_fRaiseNeeded = false;
- Exception* _ctx_trans_pTargetDomainException=NULL; \
-
- FrameWithCookie<ContextTransitionFrame> _ctx_trans_Frame;
- ContextTransitionFrame* _ctx_trans_pFrame = &_ctx_trans_Frame;
-
- args->pCtxFrame = _ctx_trans_pFrame;
- TESTHOOKCALL(EnteredAppDomain((TargetDomain.m_dwId)));
- /* work around unreachable code warning */
- EX_TRY
- {
- // Invoke the callback
- if (CORDebuggerAttached())
- {
- // If a debugger is attached, do it through a wrapper that will sniff for CHF callbacks.
- MakeADCallDebuggerWrapper(fpCallback, args, GET_CTX_TRANSITION_FRAME());
- }
- else
- {
- // If no debugger is attached, call directly.
- fpCallback(args);
- }
- }
- EX_CATCH
- {
- LOG((LF_EH|LF_APPDOMAIN, LL_INFO1000, "ENTER_DOMAIN(%s, %s, %d): exception in flight\n",
- __FUNCTION__, __FILE__, __LINE__));
-
- _ctx_trans_pTargetDomainException=EXTRACT_EXCEPTION();
- _ctx_trans_fRaiseNeeded = true;
- }
- /* SwallowAllExceptions is fine because we don't get to this point */
- /* unless fRaiseNeeded = true or no exception was thrown */
- EX_END_CATCH(SwallowAllExceptions);
- TESTHOOKCALL(LeavingAppDomain((TargetDomain.m_dwId)));
- if (_ctx_trans_fRaiseNeeded)
- {
- LOG((LF_EH, LL_INFO1000, "RaiseCrossContextException(%s, %s, %d)\n",
- __FUNCTION__, __FILE__, __LINE__));
- _ctx_trans_pThread->RaiseCrossContextException(_ctx_trans_pTargetDomainException,_ctx_trans_pFrame);
- }
-
- LOG((LF_APPDOMAIN, LL_INFO1000, "LEAVE_DOMAIN(%s, %s, %d)\n",
- __FUNCTION__, __FILE__, __LINE__));
-
-#ifdef FEATURE_TESTHOOKS
- TESTHOOKCALL(LeftAppDomain(TargetDomain.m_dwId));
-#endif
-
- DEBUG_ASSURE_NO_RETURN_END(MAKECALL)
-}
-
-
-
void Thread::InitContext()
{
CONTRACTL {
_ASSERTE(m_pDomain == NULL);
GCX_COOP_NO_THREAD_BROKEN();
m_pDomain = SystemDomain::System()->DefaultDomain();
- _ASSERTE(m_pDomain);
- m_pDomain->ThreadEnter(this, NULL);
}
void Thread::ClearContext()
if (!m_pDomain)
return;
- m_pDomain->ThreadExit(this, NULL);
-
// must set exposed context to null first otherwise object verification
// checks will fail AV when m_Context is null
m_pDomain = NULL;
}
-struct FindADCallbackType {
- AppDomain *pSearchDomain;
- AppDomain *pPrevDomain;
- Frame *pFrame;
- int count;
- enum TargetTransition
- {fFirstTransitionInto, fMostRecentTransitionInto}
- fTargetTransition;
-
- FindADCallbackType() : pSearchDomain(NULL), pPrevDomain(NULL), pFrame(NULL)
- {
- LIMITED_METHOD_CONTRACT;
- }
-};
-
-StackWalkAction StackWalkCallback_FindAD(CrawlFrame* pCF, void* data)
-{
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- FindADCallbackType *pData = (FindADCallbackType *)data;
-
- Frame *pFrame = pCF->GetFrame();
-
- if (!pFrame)
- return SWA_CONTINUE;
-
- AppDomain *pReturnDomain = pFrame->GetReturnDomain();
- if (!pReturnDomain || pReturnDomain == pData->pPrevDomain)
- return SWA_CONTINUE;
-
- LOG((LF_APPDOMAIN, LL_INFO100, "StackWalkCallback_FindAD transition frame %8.8x into AD [%d]\n",
- pFrame, pReturnDomain->GetId().m_dwId));
-
- if (pData->pPrevDomain == pData->pSearchDomain) {
- ++pData->count;
- // this is a transition into the domain we are unloading, so save it in case it is the first
- pData->pFrame = pFrame;
- if (pData->fTargetTransition == FindADCallbackType::fMostRecentTransitionInto)
- return SWA_ABORT; // only need to find last transition, so bail now
- }
-
- pData->pPrevDomain = pReturnDomain;
- return SWA_CONTINUE;
-}
-
-// This determines if a thread is running in the given domain at any point on the stack
-Frame *Thread::IsRunningIn(AppDomain *pDomain, int *count)
-{
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- FindADCallbackType fct;
- fct.pSearchDomain = pDomain;
- if (!fct.pSearchDomain)
- return FALSE;
-
- // set prev to current so if are currently running in the target domain,
- // we will detect the transition
- fct.pPrevDomain = m_pDomain;
- fct.fTargetTransition = FindADCallbackType::fMostRecentTransitionInto;
- fct.count = 0;
-
- // when this returns, if there is a transition into the AD, it will be in pFirstFrame
- StackWalkAction res;
- res = StackWalkFrames(StackWalkCallback_FindAD, (void*) &fct, ALLOW_ASYNC_STACK_WALK);
- if (count)
- *count = fct.count;
- return fct.pFrame;
-}
-
-// This finds the very first frame on the stack where the thread transitioned into the given domain
-Frame *Thread::GetFirstTransitionInto(AppDomain *pDomain, int *count)
-{
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- FindADCallbackType fct;
- fct.pSearchDomain = pDomain;
- // set prev to current so if are currently running in the target domain,
- // we will detect the transition
- fct.pPrevDomain = m_pDomain;
- fct.fTargetTransition = FindADCallbackType::fFirstTransitionInto;
- fct.count = 0;
-
- // when this returns, if there is a transition into the AD, it will be in pFirstFrame
- StackWalkAction res;
- res = StackWalkFrames(StackWalkCallback_FindAD, (void*) &fct, ALLOW_ASYNC_STACK_WALK);
- if (count)
- *count = fct.count;
- return fct.pFrame;
-}
-
BOOL Thread::HaveExtraWorkForFinalizer()
{
LIMITED_METHOD_CONTRACT;
struct ManagedThreadCallState
{
- ADID pAppDomainId;
- AppDomain* pUnsafeAppDomain;
- BOOL bDomainIsAsID;
-
ADCallBackFcnType pTarget;
LPVOID args;
UnhandledExceptionLocation filterType;
- BOOL IsAppDomainEqual(AppDomain* pApp)
- {
- LIMITED_METHOD_CONTRACT;
- return bDomainIsAsID?(pApp->GetId()==pAppDomainId):(pUnsafeAppDomain==pApp);
- }
- ManagedThreadCallState(ADID AppDomainId,ADCallBackFcnType Target,LPVOID Args,
- UnhandledExceptionLocation FilterType):
- pAppDomainId(AppDomainId),
- pUnsafeAppDomain(NULL),
- bDomainIsAsID(TRUE),
- pTarget(Target),
- args(Args),
- filterType(FilterType)
- {
- LIMITED_METHOD_CONTRACT;
- };
-protected:
- ManagedThreadCallState(AppDomain* AppDomain,ADCallBackFcnType Target,LPVOID Args,
+
+ ManagedThreadCallState(ADCallBackFcnType Target,LPVOID Args,
UnhandledExceptionLocation FilterType):
- pAppDomainId(ADID(0)),
- pUnsafeAppDomain(AppDomain),
- bDomainIsAsID(FALSE),
pTarget(Target),
args(Args),
filterType(FilterType)
{
LIMITED_METHOD_CONTRACT;
};
- void InitForFinalizer(AppDomain* AppDomain,ADCallBackFcnType Target,LPVOID Args)
- {
- LIMITED_METHOD_CONTRACT;
- filterType=FinalizerThread;
- pUnsafeAppDomain=AppDomain;
- pTarget=Target;
- args=Args;
- };
-
- friend void ManagedThreadBase_NoADTransition(ADCallBackFcnType pTarget,
- UnhandledExceptionLocation filterType);
- friend void ManagedThreadBase::FinalizerAppDomain(AppDomain* pAppDomain,
- ADCallBackFcnType pTarget,
- LPVOID args,
- ManagedThreadCallState *pTurnAround);
};
// The following static helpers are outside of the ManagedThreadBase struct because I
// For the implementation, there are three variants of work possible:
// 1. Establish the base of a managed thread, and switch to the correct AppDomain.
-static void ManagedThreadBase_FullTransitionWithAD(ADID pAppDomain,
- ADCallBackFcnType pTarget,
+static void ManagedThreadBase_FullTransition(ADCallBackFcnType pTarget,
LPVOID args,
UnhandledExceptionLocation filterType)
{
}
CONTRACTL_END;
- ManagedThreadCallState CallState(pAppDomain, pTarget, args, filterType);
+ ManagedThreadCallState CallState(pTarget, args, filterType);
ManagedThreadBase_DispatchOuter(&CallState);
}
AppDomain *pAppDomain = GetAppDomain();
- ManagedThreadCallState CallState(pAppDomain, pTarget, NULL, filterType);
+ ManagedThreadCallState CallState(pTarget, NULL, filterType);
// self-describing, to create a pTurnAround data for eventual delivery to a subsequent AppDomain
// transition.
// And here are the various exposed entrypoints for base thread behavior
// The 'new Thread(...).Start()' case from COMSynchronizable kickoff thread worker
-void ManagedThreadBase::KickOff(ADID pAppDomain, ADCallBackFcnType pTarget, LPVOID args)
+void ManagedThreadBase::KickOff(ADCallBackFcnType pTarget, LPVOID args)
{
WRAPPER_NO_CONTRACT;
- ManagedThreadBase_FullTransitionWithAD(pAppDomain, pTarget, args, ManagedThread);
+ ManagedThreadBase_FullTransition(pTarget, args, ManagedThread);
}
// The IOCompletion, QueueUserWorkItem, AddTimer, RegisterWaitForSingleObject cases in the ThreadPool
-void ManagedThreadBase::ThreadPool(ADID pAppDomain, ADCallBackFcnType pTarget, LPVOID args)
+void ManagedThreadBase::ThreadPool(ADCallBackFcnType pTarget, LPVOID args)
{
WRAPPER_NO_CONTRACT;
- ManagedThreadBase_FullTransitionWithAD(pAppDomain, pTarget, args, ThreadPoolThread);
+ ManagedThreadBase_FullTransition(pTarget, args, ThreadPoolThread);
}
// The Finalizer thread establishes exception handling at its base, but defers all the AppDomain
ManagedThreadBase_NoADTransition(pTarget, FinalizerThread);
}
-void ManagedThreadBase::FinalizerAppDomain(AppDomain *pAppDomain,
- ADCallBackFcnType pTarget,
- LPVOID args,
- ManagedThreadCallState *pTurnAround)
-{
- WRAPPER_NO_CONTRACT;
- pTurnAround->InitForFinalizer(pAppDomain,pTarget,args);
- ManagedThreadBase_DispatchInner(pTurnAround);
-}
-
//+----------------------------------------------------------------------------
//
// Method: Thread::GetStaticFieldAddress private
BOOL IsAddressInStack (PTR_VOID addr) const { return TRUE; }
static BOOL IsAddressInCurrentStack (PTR_VOID addr) { return TRUE; }
- Frame *IsRunningIn(AppDomain* pDomain, int *count) { return NULL; }
-
StackingAllocator m_MarshalAlloc;
private:
inline void CommonTripThread() { }
-//current ad, always safe
-#define ADV_CURRENTAD 0
-//default ad, never unloaded
-#define ADV_DEFAULTAD 1
-// held by iterator, iterator holds a ref
-#define ADV_ITERATOR 2
-// the appdomain is on the stack
-#define ADV_RUNNINGIN 4
-// we're in process of creating the appdomain, refcount guaranteed to be >0
-#define ADV_CREATING 8
-// compilation domain - ngen guarantees it won't be unloaded until everyone left
-#define ADV_COMPILATION 0x10
-// finalizer thread - synchronized with ADU
-#define ADV_FINALIZER 0x40
-// held by AppDomainRefTaker
-#define ADV_REFTAKER 0x100
-
-#define CheckADValidity(pDomain,ADValidityKind) { }
-
-#define ENTER_DOMAIN_PTR(_pDestDomain,ADValidityKind) {
-#define END_DOMAIN_TRANSITION }
-
class DeadlockAwareLock
{
public:
return m_pDomain;
}
- Frame *IsRunningIn(AppDomain* pDomain, int *count);
- Frame *GetFirstTransitionInto(AppDomain *pDomain, int *count);
-
//---------------------------------------------------------------
// Track use of the thread block. See the general comments on
// thread destruction in threads.cpp, for details.
return (m_LastThrownObjectHandle == g_pPreallocatedStackOverflowException);
}
- void SetKickOffDomainId(ADID ad);
- ADID GetKickOffDomainId();
-
// get the current notification (if any) from this thread
OBJECTHANDLE GetThreadCurrNotification();
private:
void SetLastThrownObjectHandle(OBJECTHANDLE h);
- ADID m_pKickOffDomainId;
-
ThreadExceptionState m_ExceptionState;
//-----------------------------------------------------------
// general corruption.
BOOL HasIllegalReentrancy();
-//
-// _pThread: (Thread*) current Thread
-// _pCurrDomain: (AppDomain*) current AppDomain
-// _pDestDomain: (AppDomain*) AppDomain to transition to
-// _predicate_expr: (bool) Expression to predicate the transition. If this is true, we transition,
-// otherwise we don't. WARNING : if you change this macro, be sure you
-// guarantee that this macro argument is only evaluated once.
-//
-
-//
-// @TODO: can't we take the transition with a holder?
-//
-#define ENTER_DOMAIN_SETUPVARS(_pThread, _predicate_expr) \
-{ \
- DEBUG_ASSURE_NO_RETURN_BEGIN(DOMAIN) \
- \
- Thread* _ctx_trans_pThread = (_pThread); \
- bool _ctx_trans_fTransitioned = false; \
- bool _ctx_trans_fPredicate = (_predicate_expr); \
- bool _ctx_trans_fRaiseNeeded = false; \
- Exception* _ctx_trans_pTargetDomainException=NULL; \
- ADID _ctx_trans_pDestDomainId=ADID(0); \
- FrameWithCookie<ContextTransitionFrame> _ctx_trans_Frame; \
- ContextTransitionFrame* _ctx_trans_pFrame = &_ctx_trans_Frame; \
-
-#define ENTER_DOMAIN_SWITCH_CTX_BY_ADID(_pCurrDomainPtr,_pDestDomainId,_bUnsafePoint) \
- AppDomain* _ctx_trans_pCurrDomain=_pCurrDomainPtr; \
- _ctx_trans_pDestDomainId=(ADID)_pDestDomainId; \
- if (_ctx_trans_fPredicate && \
- (_ctx_trans_pCurrDomain==NULL || \
- (_ctx_trans_pCurrDomain->GetId() != _ctx_trans_pDestDomainId))) \
- { \
- _ctx_trans_fTransitioned = true; \
- }
-
-#define ENTER_DOMAIN_SWITCH_CTX_BY_ADPTR(_pCurrDomain,_pDestDomain) \
- AppDomain* _ctx_trans_pCurrDomain=_pCurrDomain; \
- AppDomain* _ctx_trans_pDestDomain=_pDestDomain; \
- _ctx_trans_pDestDomainId=_ctx_trans_pDestDomain->GetId(); \
- \
- if (_ctx_trans_fPredicate && (_ctx_trans_pCurrDomain != _ctx_trans_pDestDomain)) \
- { \
- TESTHOOKCALL(AppDomainCanBeUnloaded(_ctx_trans_pDestDomain->GetId().m_dwId,FALSE)); \
- GCX_FORBID(); \
- \
- _ctx_trans_fTransitioned = true; \
- }
-
-
-
-#define ENTER_DOMAIN_SETUP_EH \
- /* work around unreachable code warning */ \
- SCAN_BLOCKMARKER_N(DOMAIN); \
- if (true) EX_TRY \
- { \
- SCAN_BLOCKMARKER_MARK_N(DOMAIN); \
- LOG((LF_APPDOMAIN, LL_INFO1000, "ENTER_DOMAIN(%s, %s, %d): %s\n", \
- __FUNCTION__, __FILE__, __LINE__, \
- _ctx_trans_fTransitioned ? "ENTERED" : "NOP"));
-
-// Note: we go to preemptive mode before the EX_RETHROW Going preemp here is safe, since there are many other paths in
-// this macro that toggle the GC mode, too.
-#define END_DOMAIN_TRANSITION \
- TESTHOOKCALL(LeavingAppDomain(::GetAppDomain()->GetId().m_dwId)); \
- } \
- EX_CATCH \
- { \
- SCAN_BLOCKMARKER_USE_N(DOMAIN); \
- LOG((LF_EH|LF_APPDOMAIN, LL_INFO1000, "ENTER_DOMAIN(%s, %s, %d): exception in flight\n", \
- __FUNCTION__, __FILE__, __LINE__)); \
- \
- if (!_ctx_trans_fTransitioned) \
- { \
- if (_ctx_trans_pThread->PreemptiveGCDisabled()) \
- { \
- _ctx_trans_pThread->EnablePreemptiveGC(); \
- } \
- \
- EX_RETHROW; \
- } \
- \
- \
- _ctx_trans_pTargetDomainException=EXTRACT_EXCEPTION(); \
- \
- /* Save Watson buckets before the exception object is changed */ \
- CAPTURE_BUCKETS_AT_TRANSITION(_ctx_trans_pThread, GET_THROWABLE()); \
- \
- _ctx_trans_fRaiseNeeded = true; \
- SCAN_BLOCKMARKER_END_USE_N(DOMAIN); \
- } \
- /* SwallowAllExceptions is fine because we don't get to this point */ \
- /* unless fRaiseNeeded = true or no exception was thrown */ \
- EX_END_CATCH(SwallowAllExceptions); \
- \
- if (_ctx_trans_fRaiseNeeded) \
- { \
- SCAN_BLOCKMARKER_USE_N(DOMAIN); \
- LOG((LF_EH, LL_INFO1000, "RaiseCrossContextException(%s, %s, %d)\n", \
- __FUNCTION__, __FILE__, __LINE__)); \
- _ctx_trans_pThread->RaiseCrossContextException(_ctx_trans_pTargetDomainException, _ctx_trans_pFrame); \
- } \
- \
- LOG((LF_APPDOMAIN, LL_INFO1000, "LEAVE_DOMAIN(%s, %s, %d)\n", \
- __FUNCTION__, __FILE__, __LINE__)); \
- \
- TESTHOOKCALL(LeftAppDomain(_ctx_trans_pDestDomainId.m_dwId)); \
- DEBUG_ASSURE_NO_RETURN_END(DOMAIN) \
-}
-
-//current ad, always safe
-#define ADV_CURRENTAD 0
-//default ad, never unloaded
-#define ADV_DEFAULTAD 1
-// held by iterator, iterator holds a ref
-#define ADV_ITERATOR 2
-// the appdomain is on the stack
-#define ADV_RUNNINGIN 4
-// we're in process of creating the appdomain, refcount guaranteed to be >0
-#define ADV_CREATING 8
-// compilation domain - ngen guarantees it won't be unloaded until everyone left
-#define ADV_COMPILATION 0x10
-// finalizer thread - synchronized with ADU
-#define ADV_FINALIZER 0x40
-// held by AppDomainRefTaker
-#define ADV_REFTAKER 0x100
-
-#ifdef _DEBUG
-void CheckADValidity(AppDomain* pDomain, DWORD ADValidityKind);
-#else
-#define CheckADValidity(pDomain,ADValidityKind)
-#endif
-
-// Please keep these macros in sync with the NO_EH_AT_TRANSITION macros below.
-#define ENTER_DOMAIN_ID_PREDICATED(_pDestDomain,_predicate_expr) \
- TESTHOOKCALL(EnteringAppDomain(_pDestDomain.m_dwId)) ; \
- ENTER_DOMAIN_SETUPVARS(GetThread(), _predicate_expr) \
- ENTER_DOMAIN_SWITCH_CTX_BY_ADID(_ctx_trans_pThread->GetDomain(), _pDestDomain, FALSE) \
- ENTER_DOMAIN_SETUP_EH \
- TESTHOOKCALL(EnteredAppDomain(_pDestDomain.m_dwId));
-
-#define ENTER_DOMAIN_PTR_PREDICATED(_pDestDomain,ADValidityKind,_predicate_expr) \
- TESTHOOKCALL(EnteringAppDomain((_pDestDomain)->GetId().m_dwId)); \
- ENTER_DOMAIN_SETUPVARS(GetThread(), _predicate_expr) \
- CheckADValidity(_ctx_trans_fPredicate?(_pDestDomain):GetAppDomain(),ADValidityKind); \
- ENTER_DOMAIN_SWITCH_CTX_BY_ADPTR(_ctx_trans_pThread->GetDomain(), _pDestDomain) \
- ENTER_DOMAIN_SETUP_EH \
- TESTHOOKCALL(EnteredAppDomain((_pDestDomain)->GetId().m_dwId));
-
-
-#define ENTER_DOMAIN_PTR(_pDestDomain,ADValidityKind) \
- TESTHOOKCALL(EnteringAppDomain((_pDestDomain)->GetId().m_dwId)); \
- CheckADValidity(_pDestDomain,ADValidityKind); \
- ENTER_DOMAIN_SETUPVARS(GetThread(), true) \
- ENTER_DOMAIN_SWITCH_CTX_BY_ADPTR(_ctx_trans_pThread->GetDomain(), _pDestDomain) \
- ENTER_DOMAIN_SETUP_EH \
- TESTHOOKCALL(EnteredAppDomain((_pDestDomain)->GetId().m_dwId));
-
-#define ENTER_DOMAIN_ID(_pDestDomain) \
- ENTER_DOMAIN_ID_PREDICATED(_pDestDomain,true)
-
-// <EnableADTransitionWithoutEH>
-// The following macros support the AD transition *without* using EH at transition boundary.
-// Please keep them in sync with the macros above.
-#define ENTER_DOMAIN_PTR_NO_EH_AT_TRANSITION(_pDestDomain,ADValidityKind) \
- TESTHOOKCALL(EnteringAppDomain((_pDestDomain)->GetId().m_dwId)); \
- CheckADValidity(_pDestDomain,ADValidityKind); \
- ENTER_DOMAIN_SETUPVARS(GetThread(), true) \
- ENTER_DOMAIN_SWITCH_CTX_BY_ADPTR(_ctx_trans_pThread->GetDomain(), _pDestDomain) \
- TESTHOOKCALL(EnteredAppDomain((_pDestDomain)->GetId().m_dwId));
-
-#define ENTER_DOMAIN_ID_NO_EH_AT_TRANSITION_PREDICATED(_pDestDomain,_predicate_expr) \
- TESTHOOKCALL(EnteringAppDomain(_pDestDomain.m_dwId)) ; \
- ENTER_DOMAIN_SETUPVARS(GetThread(), _predicate_expr) \
- ENTER_DOMAIN_SWITCH_CTX_BY_ADID(_ctx_trans_pThread->GetDomain(), _pDestDomain, FALSE) \
- TESTHOOKCALL(EnteredAppDomain(_pDestDomain.m_dwId));
-
-#define ENTER_DOMAIN_ID_NO_EH_AT_TRANSITION(_pDestDomain) \
- ENTER_DOMAIN_ID_NO_EH_AT_TRANSITION_PREDICATED(_pDestDomain,true)
-
-#define END_DOMAIN_TRANSITION_NO_EH_AT_TRANSITION \
- TESTHOOKCALL(LeavingAppDomain(::GetAppDomain()->GetId().m_dwId)); \
- LOG((LF_APPDOMAIN, LL_INFO1000, "LEAVE_DOMAIN(%s, %s, %d)\n", \
- __FUNCTION__, __FILE__, __LINE__)); \
- \
- __returnToPreviousAppDomainHolder.SuppressRelease(); \
- TESTHOOKCALL(LeftAppDomain(_ctx_trans_pDestDomainId.m_dwId)); \
- DEBUG_ASSURE_NO_RETURN_END(DOMAIN) \
- } // Close scope setup by ENTER_DOMAIN_SETUPVARS
-
-// </EnableADTransitionWithoutEH>
-
-#define GET_CTX_TRANSITION_FRAME() \
- (_ctx_trans_pFrame)
-
-//-----------------------------------------------------------------------------
-// System to make Cross-Appdomain calls.
-//
-// Cross-AppDomain calls are made via a callback + args. This gives us the flexibility
-// to check if a transition is needed, and take fast vs. slow paths for the debugger.
-//
-// Example usage:
-// struct FooArgs : public CtxTransitionBaseArgs { ... } args (...); // load up args
-// MakeCallWithPossibleAppDomainTransition(pNewDomain, MyFooFunc, &args);
-//
-// MyFooFunc is always executed in pNewDomain.
-// If we're already in pNewDomain, then that just becomes MyFooFunc(&args);
-// else we'll switch ADs, and do the proper Try/Catch/Rethrow.
-//-----------------------------------------------------------------------------
-
-// All Arg structs should derive from this. This makes certain standard args
-// are available (such as the context-transition frame).
-// The ADCallback helpers will fill in these base args.
-struct CtxTransitionBaseArgs;
-
-// Pointer type for the AppDomain callback function.
-typedef void (*FPAPPDOMAINCALLBACK)(
- CtxTransitionBaseArgs* pData // Caller's private data
-);
-
-
-//-----------------------------------------------------------------------------
-// Call w/a wrapper.
-// We've already transitioned AppDomains here. This just places a 1st-pass filter to sniff
-// for catch-handler found callbacks for the debugger.
-//-----------------------------------------------------------------------------
-void MakeADCallDebuggerWrapper(
- FPAPPDOMAINCALLBACK fpCallback,
- CtxTransitionBaseArgs * args,
- ContextTransitionFrame* pFrame);
-
-// Invoke a callback in another appdomain.
-// Caller should have checked that we're actually transitioning domains here.
-void MakeCallWithAppDomainTransition(
- ADID pTargetDomain,
- FPAPPDOMAINCALLBACK fpCallback,
- CtxTransitionBaseArgs * args);
-
-// Invoke the callback in the AppDomain.
-// Ensure that predicate only gets evaluted once!!
-#define MakePredicatedCallWithPossibleAppDomainTransition(pTargetDomain, fPredicate, fpCallback, args) \
-{ \
- Thread* _ctx_trans_pThread = GetThread(); \
- _ASSERTE(_ctx_trans_pThread != NULL); \
- ADID _ctx_trans_pCurrDomain = _ctx_trans_pThread->GetDomain()->GetId(); \
- ADID _ctx_trans_pDestDomain = (pTargetDomain); \
- \
- if (fPredicate && (_ctx_trans_pCurrDomain != _ctx_trans_pDestDomain)) \
- { \
- /* Transition domains and make the call */ \
- MakeCallWithAppDomainTransition(pTargetDomain, (FPAPPDOMAINCALLBACK) fpCallback, args); \
- } \
- else \
- { \
- /* No transition needed. Just call directly. */ \
- (fpCallback)(args); \
- }\
-}
-
-// Invoke the callback in the AppDomain.
-#define MakeCallWithPossibleAppDomainTransition(pTargetDomain, fpCallback, args) \
- MakePredicatedCallWithPossibleAppDomainTransition(pTargetDomain, true, fpCallback, args)
-
-
-struct CtxTransitionBaseArgs
-{
- // This function fills out the private base args.
- friend void MakeCallWithAppDomainTransition(
- ADID pTargetDomain,
- FPAPPDOMAINCALLBACK fpCallback,
- CtxTransitionBaseArgs * args);
-
-public:
- CtxTransitionBaseArgs() { pCtxFrame = NULL; }
- // This will be NULL if we didn't actually transition.
- ContextTransitionFrame* GetCtxTransitionFrame() { return pCtxFrame; }
-private:
- ContextTransitionFrame* pCtxFrame;
-};
-
-
// We have numerous places where we start up a managed thread. This includes several places in the
// ThreadPool, the 'new Thread(...).Start()' case, and the Finalizer. Try to factor the code so our
// base exception handling behavior is consistent across those places. The resulting code is convoluted,
struct ManagedThreadBase
{
// The 'new Thread(...).Start()' case from COMSynchronizable kickoff thread worker
- static void KickOff(ADID pAppDomain,
- ADCallBackFcnType pTarget,
+ static void KickOff(ADCallBackFcnType pTarget,
LPVOID args);
// The IOCompletion, QueueUserWorkItem, AddTimer, RegisterWaitForSingleObject cases in
// the ThreadPool
- static void ThreadPool(ADID pAppDomain, ADCallBackFcnType pTarget, LPVOID args);
-
- // The Finalizer thread separates the tasks of establishing exception handling at its
- // base and transitioning into AppDomains. The turnaround structure that ties the 2 calls together
- // is the ManagedThreadCallState.
-
-
- // For the case (like Finalization) where the base transition and the AppDomain transition are
- // separated, an opaque structure is used to tie together the two calls.
+ static void ThreadPool(ADCallBackFcnType pTarget, LPVOID args);
+ // The Finalizer thread uses this path
static void FinalizerBase(ADCallBackFcnType pTarget);
- static void FinalizerAppDomain(AppDomain* pAppDomain,
- ADCallBackFcnType pTarget,
- LPVOID args,
- ManagedThreadCallState *pTurnAround);
};
m_ExceptionState.SetThrowable(pThrowable DEBUG_ARG(stecFlags));
}
-inline void Thread::SetKickOffDomainId(ADID ad)
-{
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- m_pKickOffDomainId = ad;
-}
-
-
-inline ADID Thread::GetKickOffDomainId()
-{
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- _ASSERTE(m_pKickOffDomainId.m_dwId != 0);
- return m_pKickOffDomainId;
-}
-
// get the current notification (if any) from this thread
inline OBJECTHANDLE Thread::GetThreadCurrNotification()
{
PTR_BYTE pStaticBase = pMT->GetGCThreadStaticsBasePointer();
_ASSERTE(pStaticBase != NULL);
- SetObjectReference( (OBJECTREF*)(pStaticBase + pField->GetOffset()), obj, GetAppDomain() );
+ SetObjectReference( (OBJECTREF*)(pStaticBase + pField->GetOffset()), obj );
// If we created a pinning handle, save it to the list
if (handle != NULL)
STATIC_CONTRACT_THROWS;
STATIC_CONTRACT_GC_TRIGGERS;
- TESTHOOKCALL(AppDomainCanBeUnloaded(GetDomain()->GetId().m_dwId,FALSE));
+ TESTHOOKCALL(AppDomainCanBeUnloaded(DefaultADID, FALSE));
// It's possible we could go through here if we hit a hard SO and MC++ has called back
// into the runtime on this thread
}
// Called at AppDomain Init
-void TieredCompilationManager::Init(ADID appDomainId)
+void TieredCompilationManager::Init()
{
CONTRACTL
{
CONTRACTL_END;
CrstHolder holder(&m_lock);
- m_domainId = appDomainId;
}
#endif // FEATURE_TIERED_COMPILATION && !DACCESS_COMPILE
{
return false;
}
- timerContextHolder->AppDomainId = m_domainId;
timerContextHolder->TimerId = 0;
{
EX_TRY
{
GCX_COOP();
- ManagedThreadBase::ThreadPool(timerContext->AppDomainId, TieringDelayTimerCallbackInAppDomain, nullptr);
+ ManagedThreadBase::ThreadPool(TieringDelayTimerCallbackInAppDomain, nullptr);
}
EX_CATCH
{
void TieredCompilationManager::TieringDelayTimerCallbackWorker()
{
WRAPPER_NO_CONTRACT;
- _ASSERTE(GetAppDomain()->GetId() == m_domainId);
HANDLE tieringDelayTimerHandle;
bool tier1CallCountingCandidateMethodRecentlyRecorded;
EX_TRY
{
GCX_COOP();
- ENTER_DOMAIN_ID(m_domainId);
- {
- OptimizeMethods();
- }
- END_DOMAIN_TRANSITION;
+ OptimizeMethods();
}
EX_CATCH
{
{
WRAPPER_NO_CONTRACT;
_ASSERTE(DebugGetWorkerThreadCount() != 0);
- _ASSERTE(GetAppDomain()->GetId() == m_domainId);
ULONGLONG startTickCount = CLRGetTickCount64();
NativeCodeVersion nativeCodeVersion;
TieredCompilationManager();
#endif
- void Init(ADID appDomainId);
+ void Init();
#endif // FEATURE_TIERED_COMPILATION
Crst m_lock;
SList<SListElem<NativeCodeVersion>> m_methodsToOptimize;
- ADID m_domainId;
BOOL m_isAppDomainShuttingDown;
DWORD m_countOptimizationThreadsRunning;
DWORD m_optimizationQuantumMs;
#define MAXULONGLONG UI64(0xffffffffffffffff)
#endif
-// #ADID_vs_ADIndex
-// code:ADID is an ID for an appdomain that is sparse and remains unique within the process for the lifetime of the process.
-// Remoting and (I believe) the thread pool use the former as a way of referring to appdomains outside of their normal lifetime safely.
-// Interop also uses ADID to handle issues involving unloaded domains.
-//
-// code:ADIndex is an ID for an appdomain that's dense and may be reused once the appdomain is unloaded.
-// This is useful for fast array based lookup from a number to an appdomain property.
-struct ADIndex
-{
- DWORD m_dwIndex;
- ADIndex ()
- : m_dwIndex(0)
- {}
- explicit ADIndex (DWORD id)
- : m_dwIndex(id)
- {
- SUPPORTS_DAC;
- }
- BOOL operator==(const ADIndex& ad) const
- {
- return m_dwIndex == ad.m_dwIndex;
- }
- BOOL operator!=(const ADIndex& ad) const
- {
- return m_dwIndex != ad.m_dwIndex;
- }
-};
-
-// An ADID is a number that represents an appdomain. They are allcoated with code:SystemDomain::GetNewAppDomainId
-// ADIDs are NOT reused today, so they are unique even after the appdomain dies.
-//
-// see also code:BaseDomain::m_dwId
-// see also code:ADIndex
-// see also code:ADIndex#ADID_vs_ADIndex
-struct ADID
-{
- DWORD m_dwId;
- ADID ()
- : m_dwId(0)
- {LIMITED_METHOD_CONTRACT;}
- explicit ADID (DWORD id)
- : m_dwId(id)
- {LIMITED_METHOD_CONTRACT;}
- BOOL operator==(const ADID& ad) const
- {
- LIMITED_METHOD_DAC_CONTRACT;
- return m_dwId == ad.m_dwId;
- }
- BOOL operator!=(const ADID& ad) const
- {
- LIMITED_METHOD_CONTRACT;
- return m_dwId != ad.m_dwId;
- }
-};
-
struct TPIndex
{
DWORD m_dwIndex;
waitInfo->refCount = 1; // safe to do this since no wait has yet been queued, so no other thread could be modifying this
waitInfo->ExternalCompletionEvent = INVALID_HANDLE;
waitInfo->ExternalEventSafeHandle = NULL;
- waitInfo->handleOwningAD = (ADID) 0;
waitInfo->timer.startTime = GetTickCount();
waitInfo->timer.remainingTime = timeout;
Thread* pThread,
DWORD* pErrorCode,
DWORD* pNumBytes,
- size_t* pKey,
- DWORD adid)
+ size_t* pKey)
//
//This function is called just after dispatching the previous BindIO callback
//to Managed code. This is a perf optimization to do a quick call to
timerInfo->flag = Flag;
timerInfo->ExternalCompletionEvent = INVALID_HANDLE;
timerInfo->ExternalEventSafeHandle = NULL;
- timerInfo->handleOwningAD = (ADID) 0;
BOOL status = QueueUserAPC((PAPCFUNC)InsertNewTimer,TimerThread,(size_t)timerInfo);
if (FALSE == status)
};
typedef struct {
- ADID AppDomainId;
INT32 TimerId;
} TimerInfoContext;
static BOOL HaveTimerInfosToFlush() { return TimerInfosToBeRecycled != NULL; }
#ifndef FEATURE_PAL
- static LPOVERLAPPED CompletionPortDispatchWorkWithinAppDomain(Thread* pThread, DWORD* pErrorCode, DWORD* pNumBytes, size_t* pKey, DWORD adid);
+ static LPOVERLAPPED CompletionPortDispatchWorkWithinAppDomain(Thread* pThread, DWORD* pErrorCode, DWORD* pNumBytes, size_t* pKey);
static void StoreOverlappedInfoInThread(Thread* pThread, DWORD dwErrorCode, DWORD dwNumBytes, size_t key, LPOVERLAPPED lpOverlapped);
#endif // !FEATURE_PAL
CLREvent InternalCompletionEvent; // only one of InternalCompletion or ExternalCompletion is used
// but I cant make a union since CLREvent has a non-default constructor
HANDLE ExternalCompletionEvent; // they are signalled when all callbacks have completed (refCount=0)
- ADID handleOwningAD;
OBJECTHANDLE ExternalEventSafeHandle;
} ;
}
static VOID ReleaseInfo(OBJECTHANDLE& hndSafeHandle,
- ADID& owningAD,
HANDLE hndNativeHandle)
{
CONTRACTL
{
EX_TRY
{
- ENTER_DOMAIN_ID(owningAD);
- {
- // Read the GC handle
- refSH = (SAFEHANDLEREF) ObjectToOBJECTREF(ObjectFromHandle(hndSafeHandle));
+ // Read the GC handle
+ refSH = (SAFEHANDLEREF) ObjectToOBJECTREF(ObjectFromHandle(hndSafeHandle));
+
+ // Destroy the GC handle
+ DestroyHandle(hndSafeHandle);
- // Destroy the GC handle
- DestroyHandle(hndSafeHandle);
+ if (refSH != NULL)
+ {
+ SafeHandleHolder h(&refSH);
- if (refSH != NULL)
+ HANDLE hEvent = refSH->GetHandle();
+ if (hEvent != INVALID_HANDLE_VALUE)
{
- SafeHandleHolder h(&refSH);
-
- HANDLE hEvent = refSH->GetHandle();
- if (hEvent != INVALID_HANDLE_VALUE)
- {
- UnsafeSetEvent(hEvent);
- }
+ UnsafeSetEvent(hEvent);
}
}
- END_DOMAIN_TRANSITION;
}
EX_CATCH
{
GCPROTECT_END();
hndSafeHandle = NULL;
- owningAD = (ADID) 0;
}
#endif
}
HANDLE ExternalCompletionEvent; // only one of this is used, but cant do a union since CLREvent has a non-default constructor
CLREvent InternalCompletionEvent; // flags indicates which one is being used
OBJECTHANDLE ExternalEventSafeHandle;
- ADID handleOwningAD;
} TimerInfo;
static VOID AcquireWaitInfo(WaitInfo *pInfo)
WRAPPER_NO_CONTRACT;
#ifndef DACCESS_COMPILE
ReleaseInfo(pInfo->ExternalEventSafeHandle,
- pInfo->handleOwningAD,
pInfo->ExternalCompletionEvent);
#endif
}
WRAPPER_NO_CONTRACT;
#ifndef DACCESS_COMPILE
ReleaseInfo(pInfo->ExternalEventSafeHandle,
- pInfo->handleOwningAD,
pInfo->ExternalCompletionEvent);
#endif
}
return TRUE;
}
-/*static*/ HRESULT Zapper::GenericDomainCallback(LPVOID pvArgs)
-{
- STATIC_CONTRACT_ENTRY_POINT;
-
- HRESULT hr = S_OK;
-
- BEGIN_ENTRYPOINT_NOTHROW;
- EX_TRY
- {
- ((DomainCallback *) pvArgs)->doCallback();
- }
- EX_CATCH_HRESULT(hr);
-
- END_ENTRYPOINT_NOTHROW;
-
- return hr;
-}
-
-void Zapper::InvokeDomainCallback(DomainCallback *callback)
-{
-#ifdef CROSSGEN_COMPILE
- // Call the callback directly for better error messages (avoids exception swallowing and rethrow)
- callback->doCallback();
-#else
- IfFailThrow(m_pEECompileInfo->MakeCrossDomainCallback(m_pDomain,
- Zapper::GenericDomainCallback,
- (LPVOID) callback));
-#endif
-}
-
void Zapper::SetContextInfo(LPCWSTR assemblyName)
{
// A special case: If we're compiling mscorlib, ignore m_exeName and don't set any context.
void Zapper::CreateDependenciesLookupDomain()
{
- class Callback : public DomainCallback
- {
- public:
- Callback(Zapper *pZapper)
- {
- this->pZapper = pZapper;
- }
-
- virtual void doCallback()
- {
- pZapper->CreateDependenciesLookupDomainInCurrentDomain();
- }
-
- Zapper* pZapper;
- };
-
-
CreateCompilationDomain();
-
- Callback callback(this);
- InvokeDomainCallback(&callback);
+ CreateDependenciesLookupDomainInCurrentDomain();
}
void Zapper::CreatePdb(BSTR pAssemblyPathOrName, BSTR pNativeImagePath, BSTR pPdbPath, BOOL pdbLines, BSTR pManagedPdbSearchPath)
{
- class Callback : public DomainCallback {
-
- public:
-
- Callback(Zapper *pZapper, BSTR pAssemblyPathOrName, BSTR pNativeImagePath, BSTR pPdbPath, BOOL pdbLines, BSTR pManagedPdbSearchPath)
- : m_pZapper(pZapper),
- m_pAssemblyPathOrName(pAssemblyPathOrName),
- m_pNativeImagePath(pNativeImagePath),
- m_pPdbPath(pPdbPath),
- m_pdbLines(pdbLines),
- m_pManagedPdbSearchPath(pManagedPdbSearchPath)
- {
- }
-
- virtual void doCallback()
- {
- m_pZapper->CreatePdbInCurrentDomain(m_pAssemblyPathOrName, m_pNativeImagePath, m_pPdbPath, m_pdbLines, m_pManagedPdbSearchPath);
- };
-
- private:
-
- Zapper *m_pZapper;
- BSTR m_pAssemblyPathOrName;
- BSTR m_pNativeImagePath;
- BSTR m_pPdbPath;
- BOOL m_pdbLines;
- BSTR m_pManagedPdbSearchPath;
-
- };
-
#ifdef CROSSGEN_COMPILE
CreateCompilationDomain();
#endif
- _ASSERTE(m_pDomain);
-
- Callback callback(this, pAssemblyPathOrName, pNativeImagePath, pPdbPath, pdbLines, pManagedPdbSearchPath);
- InvokeDomainCallback(&callback);
-}
-
-void Zapper::CreatePdbInCurrentDomain(BSTR pAssemblyPathOrName, BSTR pNativeImagePath, BSTR pPdbPath, BOOL pdbLines, BSTR pManagedPdbSearchPath)
-{
EX_TRY
{
CORINFO_ASSEMBLY_HANDLE hAssembly = NULL;
HRESULT Zapper::Compile(LPCWSTR string, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig)
{
- class Callback : public DomainCallback
- {
- public:
- Callback(Zapper *pZapper, LPCWSTR pAssemblyName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig)
- {
- this->pZapper = pZapper;
- this->pAssemblyName = pAssemblyName;
- this->pNativeImageSig = pNativeImageSig;
- }
-
- virtual void doCallback()
- {
- pZapper->CompileInCurrentDomain(pAssemblyName, pNativeImageSig);
- }
-
- Zapper* pZapper;
- LPCWSTR pAssemblyName;
- CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig;
- };
-
HRESULT hr = S_OK;
bool fMscorlib = false;
EX_TRY
{
- Callback callback(this, string, pNativeImageSig);
- InvokeDomainCallback(&callback);
+ CompileInCurrentDomain(string, pNativeImageSig);
}
EX_CATCH
{