summaryrefslogtreecommitdiff
path: root/src/vm/appdomainstack.inl
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/appdomainstack.inl')
-rw-r--r--src/vm/appdomainstack.inl443
1 files changed, 443 insertions, 0 deletions
diff --git a/src/vm/appdomainstack.inl b/src/vm/appdomainstack.inl
new file mode 100644
index 0000000000..badcb91a89
--- /dev/null
+++ b/src/vm/appdomainstack.inl
@@ -0,0 +1,443 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+/*============================================================
+**
+** Header: AppDomainStack.inl
+**
+** Purpose: Implements ADStack inline functions
+**
+
+
+**
+===========================================================*/
+#ifndef _APPDOMAINSTACK_INL
+#define _APPDOMAINSTACK_INL
+
+#include "threads.h"
+#include "appdomain.hpp"
+#include "appdomainstack.h"
+#include "security.h"
+
+
+#ifndef DACCESS_COMPILE
+
+#ifdef _DEBUG
+#define LogADStackUpdateIfDebug LogADStackUpdate()
+inline void AppDomainStack::LogADStackUpdate(void)
+{
+ LIMITED_METHOD_CONTRACT;
+ for (int i=m_numEntries-1; i >= 0; i--) {
+ AppDomainStackEntry* pEntry = __GetEntryPtr(i);
+
+ LOG((LF_APPDOMAIN, LL_INFO100, " stack[%d]: AppDomain id[%d] Overrides[%d] Asserts[%d] \n", i,
+ pEntry->m_domainID.m_dwId, pEntry->m_dwOverridesCount, pEntry->m_dwAsserts));
+ }
+}
+
+#else
+#define LogADStackUpdateIfDebug
+#endif
+
+inline void AppDomainStack::AddMoreDomains(void)
+{
+ CONTRACTL {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+ // Need to allocate a bigger block for pMoreDomains
+ AppDomainStackEntry *tmp = m_pExtraStack;
+ m_pExtraStack = new AppDomainStackEntry[m_ExtraStackSize + ADSTACK_BLOCK_SIZE];
+ memcpy(m_pExtraStack, tmp, sizeof(AppDomainStackEntry)*(m_ExtraStackSize));
+ FillEntries((m_pExtraStack+m_ExtraStackSize), ADSTACK_BLOCK_SIZE);
+ m_ExtraStackSize+= ADSTACK_BLOCK_SIZE;
+ delete[] tmp; // free the old block
+
+}
+inline void AppDomainStack::PushDomain(ADID pDomain)
+{
+ CONTRACTL {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+ LOG((LF_APPDOMAIN, LL_INFO100, "Thread::PushDomain (%d), count now %d\n", pDomain.m_dwId, m_numEntries+1));
+
+ //
+ // When entering a new AppDomain, we need to update the thread wide
+ // state with the intersection of the current and the new AppDomains flags.
+ // This is because the old AppDomain could have loaded new assemblies
+ // that are not yet reflected in the thread wide state, and the thread
+ // could then execute code in that new Assembly.
+ // We save the old thread wide state in the AppDomainStackEntry so we
+ // can restore it when we pop the stack entry.
+ //
+
+ // The pushed domain could be the default AppDomain (which is the starting
+ // AppDomain for all threads), in which case we don't need to intersect
+ // with the flags from the previous AppDomain.
+ Thread* pThread = GetThread();
+ if (pThread)
+ m_dwThreadWideSpecialFlags &= pThread->GetDomain()->GetSecurityDescriptor()->GetDomainWideSpecialFlag();
+
+ if (m_numEntries == ADSTACK_BLOCK_SIZE + m_ExtraStackSize)
+ {
+ AddMoreDomains();
+ }
+
+ _ASSERTE(m_numEntries < ADSTACK_BLOCK_SIZE + m_ExtraStackSize);
+ if (m_numEntries < ADSTACK_BLOCK_SIZE)
+ {
+ m_pStack[m_numEntries].m_domainID = pDomain;
+ m_pStack[m_numEntries].m_dwAsserts = 0;
+ m_pStack[m_numEntries].m_dwOverridesCount = 0;
+ m_pStack[m_numEntries].m_dwPreviousThreadWideSpecialFlags = m_dwThreadWideSpecialFlags;
+ }
+ else
+ {
+ m_pExtraStack[m_numEntries-ADSTACK_BLOCK_SIZE].m_domainID = pDomain ;
+ m_pExtraStack[m_numEntries-ADSTACK_BLOCK_SIZE].m_dwAsserts = 0;
+ m_pExtraStack[m_numEntries-ADSTACK_BLOCK_SIZE].m_dwOverridesCount = 0;
+ m_pExtraStack[m_numEntries-ADSTACK_BLOCK_SIZE].m_dwPreviousThreadWideSpecialFlags = m_dwThreadWideSpecialFlags;
+ }
+
+ if (pThread) {
+ AppDomainFromIDHolder pAppDomain(pDomain, TRUE);
+ if (!pAppDomain.IsUnloaded())
+ m_dwThreadWideSpecialFlags &= pAppDomain->GetSecurityDescriptor()->GetDomainWideSpecialFlag();
+ }
+
+ m_numEntries++;
+
+ LogADStackUpdateIfDebug;
+}
+
+inline ADID AppDomainStack::PopDomain()
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
+ ADID pRet = (ADID)INVALID_APPDOMAIN_ID;
+ _ASSERTE(m_numEntries > 0);
+ if (m_numEntries > 0)
+ {
+ m_numEntries--;
+ AppDomainStackEntry ret_entry;
+ const AppDomainStackEntry reset_entry = {ADID(INVALID_APPDOMAIN_ID), 0, 0};
+
+ if (m_numEntries < ADSTACK_BLOCK_SIZE)
+ {
+ ret_entry = m_pStack[m_numEntries];
+ m_pStack[m_numEntries] = reset_entry;
+ }
+ else
+ {
+ ret_entry = m_pExtraStack[m_numEntries-ADSTACK_BLOCK_SIZE];
+ m_pExtraStack[m_numEntries-ADSTACK_BLOCK_SIZE] = reset_entry;
+ }
+ pRet=ret_entry.m_domainID;
+
+ LOG((LF_APPDOMAIN, LL_INFO100, "PopDomain: Popping pRet.m_dwId [%d] m_dwAsserts:%d ret_entry.m_dwAsserts:%d. New m_dwAsserts:%d\n",
+ pRet.m_dwId, m_dwAsserts,ret_entry.m_dwAsserts, (m_dwAsserts-ret_entry.m_dwAsserts)));
+
+ m_dwAsserts -= ret_entry.m_dwAsserts;
+ m_dwOverridesCount -= ret_entry.m_dwOverridesCount;
+#ifdef _DEBUG
+ CheckOverridesAssertCounts();
+#endif
+
+ //
+ // When leaving an AppDomain, we need to update the thread wide state by
+ // restoring to the state we were in before entering the AppDomain
+ //
+
+ m_dwThreadWideSpecialFlags = ret_entry.m_dwPreviousThreadWideSpecialFlags;
+
+ LOG((LF_APPDOMAIN, LL_INFO100, "Thread::PopDomain popping [%d] count now %d\n",
+ pRet.m_dwId , m_numEntries));
+ }
+ else
+ {
+ LOG((LF_APPDOMAIN, LL_INFO100, "Thread::PopDomain count now %d (error pop)\n", m_numEntries));
+ }
+
+ LogADStackUpdateIfDebug;
+ return pRet;
+}
+#endif // DACCESS_COMPILE
+
+inline DWORD AppDomainStack::GetNumDomains() const
+{
+ LIMITED_METHOD_CONTRACT;
+ _ASSERTE(m_numEntries >= 1);
+ return m_numEntries;
+}
+
+inline DWORD AppDomainStack::GetThreadWideSpecialFlag() const
+{
+ LIMITED_METHOD_CONTRACT;
+ return m_dwThreadWideSpecialFlags;
+}
+
+inline DWORD AppDomainStack::IncrementOverridesCount()
+{
+
+ CONTRACTL
+ {
+ MODE_ANY;
+ GC_NOTRIGGER;
+ NOTHROW;
+ SO_TOLERANT;// Yes, we update global state here, but at worst we have an incorrect overrides count that will be updated the next
+ }CONTRACTL_END; // time we run any code that leads to UpdateOverrides. And I don't see even how that can happen: it doesn't look possible
+ // for use to take an SO between the update and when we return to managed code.
+ AppDomainStackEntry *pEntry = ReadTopOfStack();
+ _ASSERTE(pEntry->m_domainID.m_dwId != INVALID_APPDOMAIN_ID);
+ ++(pEntry->m_dwOverridesCount);
+ return ++m_dwOverridesCount;
+}
+inline DWORD AppDomainStack::DecrementOverridesCount()
+{
+ CONTRACTL
+ {
+ MODE_ANY;
+ GC_NOTRIGGER;
+ NOTHROW;
+ SO_TOLERANT;
+ }CONTRACTL_END;
+ AppDomainStackEntry *pEntry = ReadTopOfStack();
+ _ASSERTE(pEntry->m_domainID.m_dwId != INVALID_APPDOMAIN_ID);
+ _ASSERTE(pEntry->m_dwOverridesCount > 0);
+ _ASSERTE(m_dwOverridesCount > 0);
+ if (pEntry->m_dwOverridesCount > 0 && m_dwOverridesCount > 0)
+ {
+ --(pEntry->m_dwOverridesCount);
+ return --m_dwOverridesCount;
+ }
+
+ return 0;
+}
+inline DWORD AppDomainStack::GetOverridesCount()
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ SO_TOLERANT;
+ }
+ CONTRACTL_END;
+#ifdef _DEBUG
+ CheckOverridesAssertCounts();
+#endif
+ return m_dwOverridesCount;
+}
+
+inline DWORD AppDomainStack::GetInnerAppDomainOverridesCount()
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ SO_TOLERANT;
+ }
+ CONTRACTL_END;
+#ifdef _DEBUG
+ CheckOverridesAssertCounts();
+#endif
+ AppDomainStackEntry *pEntry = ReadTopOfStack();
+ _ASSERTE(pEntry->m_domainID.m_dwId != INVALID_APPDOMAIN_ID);
+
+ return pEntry->m_dwOverridesCount;
+}
+
+inline DWORD AppDomainStack::IncrementAssertCount()
+{
+ LIMITED_METHOD_CONTRACT;
+ AppDomainStackEntry *pEntry = ReadTopOfStack();
+ _ASSERTE(pEntry->m_domainID.m_dwId != INVALID_APPDOMAIN_ID);
+ LOG((LF_APPDOMAIN, LL_INFO100, "IncrementAssertCount: m_dwAsserts:%d ADID:%d pEntry:%p pEntry->m_dwAsserts:%d.\n",
+ m_dwAsserts, pEntry->m_domainID.m_dwId, pEntry, pEntry->m_dwAsserts));
+ ++(pEntry->m_dwAsserts);
+ return ++m_dwAsserts;
+}
+inline DWORD AppDomainStack::DecrementAssertCount()
+{
+ LIMITED_METHOD_CONTRACT;
+ AppDomainStackEntry *pEntry = ReadTopOfStack();
+ _ASSERTE(pEntry->m_domainID.m_dwId != INVALID_APPDOMAIN_ID);
+ _ASSERTE(pEntry->m_dwAsserts > 0);
+ _ASSERTE(m_dwAsserts > 0);
+ LOG((LF_APPDOMAIN, LL_INFO100, "DecrementAssertCount: m_dwAsserts:%d ADID:%d pEntry:%p pEntry->m_dwAsserts:%d.\n",
+ m_dwAsserts, pEntry->m_domainID.m_dwId, pEntry, pEntry->m_dwAsserts));
+ --(pEntry->m_dwAsserts);
+ return --m_dwAsserts;
+}
+
+inline DWORD AppDomainStack::GetAssertCount()
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ SO_TOLERANT;
+ }
+ CONTRACTL_END;
+#ifdef _DEBUG
+ CheckOverridesAssertCounts();
+#endif
+
+ return m_dwAsserts;
+}
+
+inline DWORD AppDomainStack::GetInnerAppDomainAssertCount()
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ SO_TOLERANT;
+ }
+ CONTRACTL_END;
+#ifdef _DEBUG
+ CheckOverridesAssertCounts();
+#endif
+ AppDomainStackEntry *pEntry = ReadTopOfStack();
+ _ASSERTE(pEntry->m_domainID.m_dwId != INVALID_APPDOMAIN_ID);
+
+ return pEntry->m_dwAsserts;
+}
+
+inline void AppDomainStack::InitDomainIteration(DWORD *pIndex) const
+{
+ LIMITED_METHOD_CONTRACT;
+ *pIndex = m_numEntries;
+}
+
+inline ADID AppDomainStack::GetNextDomainOnStack(DWORD *pIndex, DWORD *pOverrides, DWORD *pAsserts) const
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ SO_TOLERANT;
+ }
+ CONTRACTL_END;
+
+ _ASSERTE(*pIndex > 0 && *pIndex <= m_numEntries);
+ (*pIndex) --;
+ const AppDomainStackEntry *pEntry = __GetEntryPtr(*pIndex);
+ if (pOverrides != NULL)
+ *pOverrides = pEntry->m_dwOverridesCount;
+ if (pAsserts != NULL)
+ *pAsserts = pEntry->m_dwAsserts;
+ return (ADID)pEntry->m_domainID.m_dwId;
+}
+
+inline AppDomainStackEntry* AppDomainStack::GetCurrentDomainEntryOnStack(DWORD pIndex)
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
+ _ASSERTE(pIndex >=0 && pIndex < m_numEntries);
+ return __GetEntryPtr(pIndex);
+}
+
+inline AppDomainStackEntry* AppDomainStack::GetNextDomainEntryOnStack(DWORD *pIndex)
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ SO_TOLERANT;
+ }
+ CONTRACTL_END;
+
+ _ASSERTE(*pIndex >0 && *pIndex <= m_numEntries);
+ (*pIndex) --;
+ return __GetEntryPtr(*pIndex);
+}
+
+inline void AppDomainStack::UpdateDomainOnStack(DWORD pIndex, DWORD asserts, DWORD overrides)
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+ AppDomainStackEntry* entry;
+ _ASSERTE(pIndex >=0 && pIndex < m_numEntries);
+ entry = __GetEntryPtr(pIndex);
+ _ASSERTE(entry->m_domainID.m_dwId != INVALID_APPDOMAIN_ID);
+ entry->m_dwAsserts = asserts;
+ entry->m_dwOverridesCount = overrides;
+ UpdateStackFromEntries();
+
+}
+
+
+inline void AppDomainStack::UpdateStackFromEntries()
+{
+ LIMITED_METHOD_CONTRACT;
+ DWORD dwAppDomainIndex = 0;
+ DWORD dwOverrides = 0;
+ DWORD dwAsserts = 0;
+ AppDomainStackEntry *pEntry = NULL;
+ for(dwAppDomainIndex=0;dwAppDomainIndex<m_numEntries;dwAppDomainIndex++)
+ {
+ pEntry = __GetEntryPtr(dwAppDomainIndex);
+ dwOverrides += pEntry->m_dwOverridesCount;
+ dwAsserts += pEntry->m_dwAsserts;
+ }
+ LOG((LF_APPDOMAIN, LL_INFO100, "UpdateStackFromEntries: m_dwAsserts:%d Calculated dwAsserts:%d.\n",m_dwAsserts,dwAsserts));
+
+ m_dwAsserts = dwAsserts;
+ m_dwOverridesCount = dwOverrides;
+ return;
+}
+
+inline AppDomainStackEntry* AppDomainStack::ReadTopOfStack()
+{
+ LIMITED_METHOD_CONTRACT;
+ _ASSERTE(m_numEntries > 0);
+ AppDomainStackEntry* pEntry = NULL;
+ if (m_numEntries <= ADSTACK_BLOCK_SIZE)
+ {
+ pEntry = &(m_pStack[m_numEntries-1]);
+ }
+ else
+ {
+ pEntry = &(m_pExtraStack[m_numEntries-ADSTACK_BLOCK_SIZE-1]);
+ }
+ return pEntry;
+}
+
+inline bool AppDomainStack::IsDefaultSecurityInfo() const
+{
+ LIMITED_METHOD_CONTRACT;
+ return (m_numEntries == 1 && m_pStack[0].m_domainID == ADID(DefaultADID) &&
+ m_pStack[0].m_dwAsserts == 0 && m_pStack[0].m_dwOverridesCount == 0);
+}
+inline void AppDomainStack::ClearDomainStack()
+{
+ CONTRACTL
+ {
+ MODE_ANY;
+ GC_NOTRIGGER;
+ NOTHROW;
+ }CONTRACTL_END;
+ m_dwThreadWideSpecialFlags = 0xFFFFFFFF;
+ m_numEntries = 1;
+ FillEntries(m_pStack, ADSTACK_BLOCK_SIZE);
+ if (m_pExtraStack != NULL)
+ delete[] m_pExtraStack;
+ m_pExtraStack = NULL;
+ m_ExtraStackSize = 0;
+ m_dwOverridesCount = 0;
+ LOG((LF_APPDOMAIN, LL_INFO100, "ClearDomainStack: m_dwAsserts:%d setting to 0\n",m_dwAsserts));
+ m_dwAsserts = 0;
+ m_pStack[0].m_domainID = ADID(DefaultADID);
+}
+
+#endif