diff options
author | danmosemsft <danmose@microsoft.com> | 2017-02-12 12:19:09 -0800 |
---|---|---|
committer | danmosemsft <danmose@microsoft.com> | 2017-02-12 16:58:49 -0800 |
commit | 3d3333347351975148854e83603241b84764eb32 (patch) | |
tree | 04c893c6bd4b09b88f55bf1b7d81c0f28662e38a | |
parent | 71abc31bcdb631b739bee606930e63d1384aea2f (diff) | |
download | coreclr-3d3333347351975148854e83603241b84764eb32.tar.gz coreclr-3d3333347351975148854e83603241b84764eb32.tar.bz2 coreclr-3d3333347351975148854e83603241b84764eb32.zip |
Remove never defined FEATURE_CER and header
30 files changed, 0 insertions, 1419 deletions
diff --git a/src/debug/daccess/enummem.cpp b/src/debug/daccess/enummem.cpp index 0f38aa582a..16a9ceec11 100644 --- a/src/debug/daccess/enummem.cpp +++ b/src/debug/daccess/enummem.cpp @@ -292,9 +292,6 @@ HRESULT ClrDataAccess::EnumMemCLRStatic(IN CLRDataEnumMemoryFlags flags) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pValueTypeClass.EnumMem(); ) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pEnumClass.EnumMem(); ) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pThreadClass.EnumMem(); ) -#ifdef FEATURE_CER - CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pCriticalFinalizerObjectClass.EnumMem(); ) -#endif CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pFreeObjectMethodTable.EnumMem(); ) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pObjectCtorMD.EnumMem(); ) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_fHostConfig.EnumMem(); ) diff --git a/src/debug/daccess/nidump.cpp b/src/debug/daccess/nidump.cpp index 9eb761ba32..2b46da2fe0 100644 --- a/src/debug/daccess/nidump.cpp +++ b/src/debug/daccess/nidump.cpp @@ -19,7 +19,6 @@ #include <algorithm> #endif -#include <constrainedexecutionregion.h> #include <formattype.h> @@ -4065,25 +4064,6 @@ void NativeImageDumper::DumpModule( PTR_Module module ) (int)(module->m_maxDynamicEntries * sizeof(*(module->m_pDynamicStaticsInfo)))); -#ifdef FEATURE_CER - DisplayWriteFieldInt( m_dwReliabilityContract, - module->m_dwReliabilityContract, Module, MODULE ); - - DisplayWriteFieldPointer( m_pCerPrepInfo, - DataPtrToDisplay((TADDR)module->m_pCerPrepInfo), - Module, MODULE ); - DisplayWriteFieldPointer( m_pCerCrst, DataPtrToDisplay((TADDR)module->m_pCerCrst), - Module, MODULE ); - _ASSERTE(module->m_pCerPrepInfo == NULL && module->m_pCerCrst == NULL); - - IF_OPT_OR(MODULE, SLIM_MODULE_TBLS) - { - PTR_CerNgenRootTable table( TO_TADDR(module->m_pCerNgenRootTable) ); - DumpNgenRootTable( table, "m_pCerNgenRootTable", - offsetof(Module, m_pCerNgenRootTable), - fieldsize(Module, m_pCerNgenRootTable) ); - } -#endif _ASSERTE(module->m_debuggerSpecificData.m_pDynamicILCrst == NULL); @@ -4131,87 +4111,6 @@ bool NativeImageDumper::isPrecode(TADDR maybePrecode) return !!module->IsZappedPrecode(maybePrecode); } -#ifdef FEATURE_CER -void NativeImageDumper::DumpNgenRootTable( PTR_CerNgenRootTable table, - const char * name, unsigned offset, - unsigned fieldSize ) -{ - if( table == NULL ) - { - IF_OPT(MODULE) - { - m_display->WriteFieldPointer( name, (unsigned)DPtrToPreferredAddr(table), - offset, fieldSize ); - } - return; - } - IF_OPT(MODULE) - { - m_display->StartStructureWithOffset( name, offset, fieldSize, - DPtrToPreferredAddr(table), - sizeof(*table) ); - } - - DisplayWriteFieldPointer( m_cRoots, table->GetRootCount(), - CerNgenRootTable, MODULE ); - DisplayWriteFieldAddress( m_pRestoreBitmap, - DataPtrToDisplay((TADDR)table->GetRestoreBitmap()), - table->SizeOfRestoreBitmap(), - CerNgenRootTable, MODULE ); - DisplayWriteFieldInt( m_cSlots, table->m_cSlots, CerNgenRootTable, - MODULE ); - DisplayStartArray( "Roots", NULL, SLIM_MODULE_TBLS ); - - PTR_CerRoot roots(TO_TADDR(table->GetRoots())); - for( unsigned i = 0; i < table->GetRootCount(); ++i ) - { - PTR_CerRoot root = roots + i; - DisplayStartStructure( "CerRoot", DPtrToPreferredAddr(root), - sizeof(*root), SLIM_MODULE_TBLS ); - WriteFieldMethodDesc( m_pRootMD, - PTR_MethodDesc(TO_TADDR(root->m_pRootMD)), - CerRoot, SLIM_MODULE_TBLS ); - - DisplayStartArray( "MethodContexts", NULL, SLIM_MODULE_TBLS ); - - PTR_MethodContextElement ctx(TO_TADDR(root->m_pList)); - bool dumpedSentinel = false; - while( !dumpedSentinel ) - { - DisplayStartStructure( "MethodContext", - DPtrToPreferredAddr(ctx), - sizeof(*ctx), SLIM_MODULE_TBLS ); - if( ctx->m_pMethodDesc.IsNull() ) - dumpedSentinel = true; - WriteFieldMethodDesc( m_pMethodDesc, - ctx->m_pMethodDesc.GetValue(), - MethodContextElement, SLIM_MODULE_TBLS ); - - if (!ctx->m_pExactMT.IsNull()) - { - WriteFieldMethodTable( m_pExactMT, - ctx->m_pExactMT.GetValue(), - MethodContextElement, SLIM_MODULE_TBLS ); - } - - DisplayEndStructure( SLIM_MODULE_TBLS ); //MethodContext - ++ctx; - } - - DisplayEndArray( "Total Contexts", SLIM_MODULE_TBLS); //MethodContexts - DisplayEndStructure(SLIM_MODULE_TBLS); //CerRoot - } - - DisplayEndArray( "Total Roots", SLIM_MODULE_TBLS ); //Roots - - /* REVISIT_TODO Wed 10/05/2005 - * m_cSlots seems to be set to something, but the number seems - * completely useless. What is up with that? - */ - - DisplayEndStructure( MODULE ); //CERNgenRootTable -} -#endif // FEATURE_CER void NativeImageDumper::IterateTypeDefToMTCallback( TADDR mtTarget, TADDR flags, @@ -9016,14 +8915,6 @@ NativeImageDumper::DumpEEClassForMethodTable( PTR_MethodTable mt ) DisplayWriteFieldInt( m_cbModuleDynamicID, pClassOptional->m_cbModuleDynamicID, EEClassOptionalFields, EECLASSES ); -#ifdef FEATURE_CER - /* REVISIT_TODO Fri 10/14/2005 - * Use the macros from ConstrainedExecutionRegion.cpp on this? - */ - DisplayWriteFieldUInt( m_dwReliabilityContract, - clazz->GetReliabilityContract(), - EEClassOptionalFields, EECLASSES ); -#endif DisplayWriteFieldEnumerated( m_SecProps, clazz->GetSecurityProperties()->dwFlags, EEClassOptionalFields, s_SecurityProperties, W("|"), diff --git a/src/inc/dacvars.h b/src/inc/dacvars.h index 7289533e1b..e86cb8b579 100644 --- a/src/inc/dacvars.h +++ b/src/inc/dacvars.h @@ -227,9 +227,6 @@ DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pOverlappedDataClass, ::g_pOve DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pValueTypeClass, ::g_pValueTypeClass) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pEnumClass, ::g_pEnumClass) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pThreadClass, ::g_pThreadClass) -#ifdef FEATURE_CER -DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pCriticalFinalizerObjectClass, ::g_pCriticalFinalizerObjectClass) -#endif DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pPredefinedArrayTypes, ::g_pPredefinedArrayTypes) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_TypedReferenceMT, ::g_TypedReferenceMT) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pByteArrayMT, ::g_pByteArrayMT) @@ -243,9 +240,6 @@ DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pBaseRuntimeClass, ::g_pBaseRu DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pICastableInterface, ::g_pICastableInterface) #endif // FEATURE_ICASTABLE -#ifdef FEATURE_CER -DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pPrepareConstrainedRegionsMethod, ::g_pPrepareConstrainedRegionsMethod) -#endif DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pExecuteBackoutCodeHelperMethod, ::g_pExecuteBackoutCodeHelperMethod) DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pObjectCtorMD, ::g_pObjectCtorMD) diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt index 79bd078c45..e1cfcbb06f 100644 --- a/src/vm/CMakeLists.txt +++ b/src/vm/CMakeLists.txt @@ -240,12 +240,6 @@ set(VM_SOURCES_WKS ${VM_SOURCES_GDBJIT} ) -if(FEATURE_CER) - list(APPEND VM_SOURCES_WKS - constrainedexecutionregion.cpp - ) -endif(FEATURE_CER) - if(FEATURE_EVENT_TRACE) list(APPEND VM_SOURCES_WKS eventtrace.cpp diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp index 8efb3c5692..f6c97f30c5 100644 --- a/src/vm/appdomain.cpp +++ b/src/vm/appdomain.cpp @@ -2924,16 +2924,6 @@ void SystemDomain::LoadBaseSystemClasses() g_pExecutionEngineExceptionClass = MscorlibBinder::GetException(kExecutionEngineException); g_pThreadAbortExceptionClass = MscorlibBinder::GetException(kThreadAbortException); -#ifdef FEATURE_CER - // Used for determining whether a class has a critical finalizer - // To determine whether a class has a critical finalizer, we - // currently will simply see if it's parent class has a critical - // finalizer. To introduce a class with a critical finalizer, - // we'll explicitly load CriticalFinalizerObject and set the bit - // here. - g_pCriticalFinalizerObjectClass = MscorlibBinder::GetClass(CLASS__CRITICAL_FINALIZER_OBJECT); - _ASSERTE(g_pCriticalFinalizerObjectClass->HasCriticalFinalizer()); -#endif // used by gc to handle predefined agility checking g_pThreadClass = MscorlibBinder::GetClass(CLASS__THREAD); @@ -2963,9 +2953,6 @@ void SystemDomain::LoadBaseSystemClasses() // Load a special marker method used to detect Constrained Execution Regions // at jit time. -#ifdef FEATURE_CER - g_pPrepareConstrainedRegionsMethod = MscorlibBinder::GetMethod(METHOD__RUNTIME_HELPERS__PREPARE_CONSTRAINED_REGIONS); -#endif g_pExecuteBackoutCodeHelperMethod = MscorlibBinder::GetMethod(METHOD__RUNTIME_HELPERS__EXECUTE_BACKOUT_CODE_HELPER); // Make sure that FCall mapping for Monitor.Enter is initialized. We need it in case Monitor.Enter is used only as JIT helper. diff --git a/src/vm/assembly.cpp b/src/vm/assembly.cpp index 4d36947a3c..dd8aaf88f7 100644 --- a/src/vm/assembly.cpp +++ b/src/vm/assembly.cpp @@ -56,7 +56,6 @@ #include "customattribute.h" #include "winnls.h" -#include "constrainedexecutionregion.h" #include "caparser.h" #include "../md/compiler/custattr.h" #include "mdaassistants.h" diff --git a/src/vm/ceeload.cpp b/src/vm/ceeload.cpp index 605c014d41..ea1a0402ee 100644 --- a/src/vm/ceeload.cpp +++ b/src/vm/ceeload.cpp @@ -78,7 +78,6 @@ #include "perflog.h" #include "ecall.h" #include "../md/compiler/custattr.h" -#include "constrainedexecutionregion.h" #include "typekey.h" #include "peimagelayout.inl" #include "ildbsymlib.h" @@ -1653,24 +1652,6 @@ void Module::Destruct() m_InstMethodHashTableCrst.Destroy(); m_ISymUnmanagedReaderCrst.Destroy(); -#ifdef FEATURE_CER - if (m_pCerPrepInfo) - { - _ASSERTE(m_pCerCrst != NULL); - CrstHolder sCrstHolder(m_pCerCrst); - - EEHashTableIteration sIter; - m_pCerPrepInfo->IterateStart(&sIter); - while (m_pCerPrepInfo->IterateNext(&sIter)) { - CerPrepInfo *pPrepInfo = (CerPrepInfo*)m_pCerPrepInfo->IterateGetValue(&sIter); - delete pPrepInfo; - } - - delete m_pCerPrepInfo; - } - if (m_pCerCrst) - delete m_pCerCrst; -#endif // FEATURE_CER if (m_debuggerSpecificData.m_pDynamicILCrst) { @@ -1701,10 +1682,6 @@ void Module::Destruct() } #ifdef FEATURE_PREJIT -#ifdef FEATURE_CER - if (m_pCerNgenRootTable && (m_dwTransientFlags & M_CER_ROOT_TABLE_ON_HEAP)) - delete m_pCerNgenRootTable; -#endif if (HasNativeImage()) { @@ -3155,34 +3132,6 @@ BOOL Module::IsPreV4Assembly() return !!(m_dwPersistedFlags & IS_PRE_V4_ASSEMBLY); } -#ifdef FEATURE_CER -DWORD Module::GetReliabilityContract() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END - - if (!(m_dwPersistedFlags & COMPUTED_RELIABILITY_CONTRACT)) - { - // The flags should be precomputed in native images - _ASSERTE(!HasNativeImage()); - - // This flag applies to assembly, but it is stored on module so it can be cached in ngen image - // Thus, we should ever need it for manifest module only. - IMDInternalImport *mdImport = GetAssembly()->GetManifestImport(); - - m_dwReliabilityContract = ::GetReliabilityContract(mdImport, TokenFromRid(1, mdtAssembly)); - - FastInterlockOr(&m_dwPersistedFlags, COMPUTED_RELIABILITY_CONTRACT); - } - - return m_dwReliabilityContract; -} -#endif // FEATURE_CER ArrayDPTR(FixupPointer<PTR_MethodTable>) ModuleCtorInfo::GetGCStaticMTs(DWORD index) { @@ -9827,12 +9776,6 @@ void Module::PrepareTypesForSave(DataImage *image) PrepareRemotableMethodInfo(pMT); #endif // FEATURE_REMOTING -#ifdef FEATURE_CER - // If this module defines any CriticalFinalizerObject derived classes, - // then we'll prepare these types for Constrained Execution Regions (CER) now. - // (Normally they're prepared at object instantiation time, a little too late for ngen). - PrepareCriticalType(pMT); -#endif // FEATURE_CER } } @@ -9916,9 +9859,6 @@ void Module::Save(DataImage *image) // Cache values of all persisted flags computed from custom attributes IsNoStringInterning(); IsRuntimeWrapExceptions(); -#ifdef FEATURE_CER - GetReliabilityContract(); -#endif IsPreV4Assembly(); HasDefaultDllImportSearchPathsAttribute(); @@ -10273,12 +10213,6 @@ void Module::Save(DataImage *image) m_nPropertyNameSet * sizeof(BYTE), DataImage::ITEM_PROPERTY_NAME_SET); -#ifdef FEATURE_CER - // Save Constrained Execution Region (CER) fixup information (used to eagerly fixup trees of methods to avoid any runtime - // induced failures when invoking the tree). - if (m_pCerNgenRootTable != NULL) - m_pCerNgenRootTable->Save(image, profileData); -#endif // Sort the list of RVA statics in an ascending order wrt the RVA // and save them. @@ -10734,18 +10668,6 @@ void Module::PlaceMethod(DataImage *image, MethodDesc *pMD, DWORD profilingFlags image->PlaceStructureForAddress(pMD, CORCOMPILE_SECTION_WRITE); } -#ifdef FEATURE_CER - if (profilingFlags & (1 << ReadCerMethodList)) - { - // protect against stale IBC data - // Check if the profiling data incorrectly set the ReadCerMethodList bit. - // This is more likely to happen with incremental IBC. - if ((m_pCerNgenRootTable != NULL) && m_pCerNgenRootTable->IsNgenRootMethod(pMD)) - { - image->PlaceStructureForAddress(m_pCerNgenRootTable->GetList(pMD), CORCOMPILE_SECTION_HOT); - } - } -#endif // FEATURE_CER if (profilingFlags & (1 << WriteMethodPrecode)) { @@ -11289,24 +11211,6 @@ void Module::Fixup(DataImage *image) image->ZeroField(m_FileReferencesMap.pTable, 0, m_FileReferencesMap.GetSize() * sizeof(void*)); -#ifdef FEATURE_CER - // - // Fixup Constrained Execution Regions restoration records. - // - if (m_pCerNgenRootTable != NULL) - { - image->BeginRegion(CORINFO_REGION_HOT); - image->FixupPointerField(this, offsetof(Module, m_pCerNgenRootTable)); - m_pCerNgenRootTable->Fixup(image); - image->EndRegion(CORINFO_REGION_HOT); - } - else - image->ZeroPointerField(this, offsetof(Module, m_pCerNgenRootTable)); - - // Zero out fields we always compute at runtime lazily. - image->ZeroField(this, offsetof(Module, m_pCerPrepInfo), sizeof(m_pCerPrepInfo)); - image->ZeroField(this, offsetof(Module, m_pCerCrst), sizeof(m_pCerCrst)); -#endif // FEATURE_CER image->ZeroField(this, offsetof(Module, m_debuggerSpecificData), sizeof(m_debuggerSpecificData)); @@ -15570,159 +15474,6 @@ FieldDesc *Module::LookupFieldDef(mdFieldDef token) #endif // DACCESS_COMPILE -#if !defined(DACCESS_COMPILE) && defined(FEATURE_CER) - -// Access to CerPrepInfo, the structure used to track CERs prepared at runtime (as opposed to ngen time). GetCerPrepInfo will -// return the structure associated with the given method desc if it exists or NULL otherwise. CreateCerPrepInfo will get the -// structure if it exists or allocate and return a new struct otherwise. Creation of CerPrepInfo structures is automatically -// synchronized by the CerCrst (lazily allocated as needed). -CerPrepInfo *Module::GetCerPrepInfo(MethodDesc *pMD) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - SO_TOLERANT; - PRECONDITION(CheckPointer(pMD)); - } - CONTRACTL_END; - - if (m_pCerPrepInfo == NULL) - return NULL; - - // Don't need a crst for read only access to the hash table. - HashDatum sDatum; - if (m_pCerPrepInfo->GetValue(pMD, &sDatum)) - return (CerPrepInfo*)sDatum; - else - return NULL; -} - -CerPrepInfo *Module::CreateCerPrepInfo(MethodDesc *pMD) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(CheckPointer(pMD)); - } - CONTRACTL_END; - - // Lazily allocate a Crst to serialize update access to the info structure. - // Carefully synchronize to ensure we don't leak a Crst in race conditions. - if (m_pCerCrst == NULL) - { - Crst *pCrst = new Crst(CrstCer); - if (InterlockedCompareExchangeT(&m_pCerCrst, pCrst, NULL) != NULL) - delete pCrst; - } - - CrstHolder sCrstHolder(m_pCerCrst); - - // Lazily allocate the info structure. - if (m_pCerPrepInfo == NULL) - { - LockOwner sLock = {m_pCerCrst, IsOwnerOfCrst}; - NewHolder <EEPtrHashTable> tempCerPrepInfo (new EEPtrHashTable()); - if (!tempCerPrepInfo->Init(CER_DEFAULT_HASH_SIZE, &sLock)) - COMPlusThrowOM(); - m_pCerPrepInfo = tempCerPrepInfo.Extract (); - } - else - { - // Try getting an existing value first. - HashDatum sDatum; - if (m_pCerPrepInfo->GetValue(pMD, &sDatum)) - return (CerPrepInfo*)sDatum; - } - - // We get here if there was no info structure or no existing method desc entry. Either way we now have an info structure and - // need to create a new method desc entry. - NewHolder<CerPrepInfo> pInfo(new CerPrepInfo()); - - m_pCerPrepInfo->InsertValue(pMD, (HashDatum)pInfo); - - return pInfo.Extract(); -} - -#ifdef FEATURE_NATIVE_IMAGE_GENERATION -// Access to CerNgenRootTable which holds holds information for all the CERs rooted at a method in this module (that were -// discovered during an ngen). - -// Add a list of MethodContextElements representing a CER to the root table keyed by the MethodDesc* of the root method. Creates -// or expands the root table as necessary. This should only be called during ngen (at runtime we only read the table). -void Module::AddCerListToRootTable(MethodDesc *pRootMD, MethodContextElement *pList) -{ - CONTRACTL - { - STANDARD_VM_CHECK; - PRECONDITION(IsCompilationProcess()); - } - CONTRACTL_END; - - // Although this is only called during ngen we still get cases where a module comes through here already ngen'd (because of - // ngen's habit of letting code execute during compilation). Until that's fixed we'll just back out if the module has already - // fixed the root table into unwriteable storage. - if (m_pCerNgenRootTable && !(m_dwTransientFlags & M_CER_ROOT_TABLE_ON_HEAP)) - return; - - // Lazily allocate a Crst to serialize update access to the info structure. - // Carefully synchronize to ensure we don't leak a Crst in race conditions. - if (m_pCerCrst == NULL) - { - Crst *pCrst = new Crst(CrstCer); - if (InterlockedCompareExchangeT(&m_pCerCrst, pCrst, NULL) != NULL) - delete pCrst; - } - - CrstHolder sCrstHolder(m_pCerCrst); - - // Lazily allocate the root table structure. - if (m_pCerNgenRootTable == NULL) - { - FastInterlockOr(&m_dwTransientFlags, M_CER_ROOT_TABLE_ON_HEAP); - m_pCerNgenRootTable = new CerNgenRootTable(); - } - - _ASSERTE(m_dwTransientFlags & M_CER_ROOT_TABLE_ON_HEAP); - - // And add the new element. - m_pCerNgenRootTable->AddRoot(pRootMD, pList); -} -#endif // FEATURE_NATIVE_IMAGE_GENERATION - -#ifdef FEATURE_PREJIT -// Returns true if the given method is a CER root detected at ngen time. -bool Module::IsNgenCerRootMethod(MethodDesc *pMD) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - SO_TOLERANT; - MODE_ANY; - } - CONTRACTL_END; - _ASSERTE(pMD->GetModule() == this); - if (m_pCerNgenRootTable) - return m_pCerNgenRootTable->IsNgenRootMethod(pMD); - return false; -} - -// Restores the CER rooted at this method (no-op if this method isn't a CER root). -void Module::RestoreCer(MethodDesc *pMD) -{ - STANDARD_VM_CONTRACT; - _ASSERTE(pMD->GetModule() == this); - if (m_pCerNgenRootTable) - m_pCerNgenRootTable->Restore(pMD); -} - -#endif // FEATURE_PREJIT - -#endif // !DACCESS_COMPILE && FEATURE_CER diff --git a/src/vm/ceeload.h b/src/vm/ceeload.h index fad76a6594..af06363e39 100644 --- a/src/vm/ceeload.h +++ b/src/vm/ceeload.h @@ -3390,12 +3390,6 @@ public: //----------------------------------------------------------------------------------------- BOOL IsPreV4Assembly(); -#ifdef FEATURE_CER - //----------------------------------------------------------------------------------------- - // Get reliability contract info, see ConstrainedExecutionRegion.cpp for details. - //----------------------------------------------------------------------------------------- - DWORD GetReliabilityContract(); -#endif //----------------------------------------------------------------------------------------- // Parse/Return NeutralResourcesLanguageAttribute if it exists (updates Module member variables at ngen time) @@ -3404,46 +3398,11 @@ public: protected: -#ifdef FEATURE_CER - Volatile<DWORD> m_dwReliabilityContract; -#endif // initialize Crst controlling the Dynamic IL hashtables void InitializeDynamicILCrst(); public: -#if !defined(DACCESS_COMPILE) && defined(FEATURE_CER) - - // Support for getting and creating information about Constrained Execution Regions rooted in this module. - - // Access to CerPrepInfo, the structure used to track CERs prepared at runtime (as opposed to ngen time). GetCerPrepInfo will - // return the structure associated with the given method desc if it exists or NULL otherwise. CreateCerPrepInfo will get the - // structure if it exists or allocate and return a new struct otherwise. Creation of CerPrepInfo structures is automatically - // synchronized by the CerCrst (lazily allocated as needed). - CerPrepInfo *GetCerPrepInfo(MethodDesc *pMD); - CerPrepInfo *CreateCerPrepInfo(MethodDesc *pMD); - -#ifdef FEATURE_PREJIT - // Access to CerNgenRootTable which holds holds information for all the CERs rooted at a method in this module (that were - // discovered during an ngen). - - // Add a list of MethodContextElements representing a CER to the root table keyed by the MethodDesc* of the root method. Creates - // or expands the root table as necessary. - void AddCerListToRootTable(MethodDesc *pRootMD, MethodContextElement *pList); - - // Returns true if the given method is a CER root detected at ngen time. - bool IsNgenCerRootMethod(MethodDesc *pMD); - - // Restores the CER rooted at this method (no-op if this method isn't a CER root). - void RestoreCer(MethodDesc *pMD); -#endif // FEATURE_PREJIT - - Crst *GetCerCrst() - { - LIMITED_METHOD_CONTRACT; - return m_pCerCrst; - } -#endif // !DACCESS_COMPILE && FEATURE_CER void VerifyAllMethods(); @@ -3454,13 +3413,6 @@ public: } private: -#ifdef FEATURE_CER - EEPtrHashTable *m_pCerPrepInfo; // Root methods prepared for Constrained Execution Regions - Crst *m_pCerCrst; // Mutex protecting update access to both of the above hashes -#ifdef FEATURE_PREJIT - CerNgenRootTable *m_pCerNgenRootTable; // Root methods of CERs found during ngen and requiring runtime restoration -#endif -#endif // This struct stores the data used by the managed debugging infrastructure. If it turns out that // the debugger is increasing the size of the Module class by too much, we can consider allocating diff --git a/src/vm/class.cpp b/src/vm/class.cpp index cff71f328f..785536a7a4 100644 --- a/src/vm/class.cpp +++ b/src/vm/class.cpp @@ -16,7 +16,6 @@ #include "dllimport.h" #include "dllimportcallback.h" #include "fieldmarshaler.h" -#include "constrainedexecutionregion.h" #include "customattribute.h" #include "encee.h" #include "typestring.h" @@ -2491,14 +2490,6 @@ MethodTable::GetSubstitutionForParent( #endif //!DACCESS_COMPILE -#ifdef FEATURE_CER -//******************************************************************************* -DWORD EEClass::GetReliabilityContract() -{ - LIMITED_METHOD_CONTRACT; - return HasOptionalFields() ? GetOptionalFields()->m_dwReliabilityContract : RC_NULL; -} -#endif // FEATURE_CER //******************************************************************************* #ifdef FEATURE_PREJIT diff --git a/src/vm/class.h b/src/vm/class.h index 3b7ff4490e..80be180a6e 100644 --- a/src/vm/class.h +++ b/src/vm/class.h @@ -703,9 +703,6 @@ class EEClassOptionalFields #define MODULE_NON_DYNAMIC_STATICS ((DWORD)-1) DWORD m_cbModuleDynamicID; -#ifdef FEATURE_CER - DWORD m_dwReliabilityContract; -#endif SecurityProperties m_SecProps; @@ -1755,14 +1752,6 @@ public: // Cached class level reliability contract info, see ConstrainedExecutionRegion.cpp for details. DWORD GetReliabilityContract(); -#ifdef FEATURE_CER - inline void SetReliabilityContract(DWORD dwValue) - { - LIMITED_METHOD_CONTRACT; - _ASSERTE(HasOptionalFields()); - GetOptionalFields()->m_dwReliabilityContract = dwValue; - } -#endif #if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) // Get number of eightbytes used by a struct passed in registers. diff --git a/src/vm/class.inl b/src/vm/class.inl index 7d5c74d586..1a7e169ed7 100644 --- a/src/vm/class.inl +++ b/src/vm/class.inl @@ -13,7 +13,6 @@ #ifndef _CLASS_INL_ #define _CLASS_INL_ -#include "constrainedexecutionregion.h" //*************************************************************************************** inline PTR_MethodDescChunk EEClass::GetChunks() { @@ -50,9 +49,6 @@ inline void EEClassOptionalFields::Init() m_WinRTRedirectedTypeIndex = WinMDAdapter::RedirectedTypeIndex_Invalid; #endif // FEATURE_COMINTEROP m_cbModuleDynamicID = MODULE_NON_DYNAMIC_STATICS; -#ifdef FEATURE_CER - m_dwReliabilityContract = RC_NULL; -#endif m_SecProps = 0; #if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) m_numberEightBytes = 0; diff --git a/src/vm/compile.cpp b/src/vm/compile.cpp index dffe7a6581..097c90ba5a 100644 --- a/src/vm/compile.cpp +++ b/src/vm/compile.cpp @@ -31,7 +31,6 @@ #include "virtualcallstub.h" #include "typeparse.h" #include "typestring.h" -#include "constrainedexecutionregion.h" #include "dllimport.h" #include "comdelegate.h" #include "stringarraylist.h" @@ -6492,9 +6491,6 @@ void CEEPreloader::PrePrepareMethodIfNecessary(CORINFO_METHOD_HANDLE hMethod) { STANDARD_VM_CONTRACT; -#ifdef FEATURE_CER - ::PrePrepareMethodIfNecessary(hMethod); -#endif } static void SetStubMethodDescOnInteropMethodDesc(MethodDesc* pInteropMD, MethodDesc* pStubMD, bool fReverseStub) diff --git a/src/vm/constrainedexecutionregion.cpp b/src/vm/constrainedexecutionregion.cpp index 77b944c416..0745bd5e1b 100644 --- a/src/vm/constrainedexecutionregion.cpp +++ b/src/vm/constrainedexecutionregion.cpp @@ -13,7 +13,6 @@ #include "common.h" #include <openum.h> #include <mdaassistants.h> -#include <constrainedexecutionregion.h> #include <ecmakey.h> #include <typestring.h> #include <jitinterface.h> diff --git a/src/vm/constrainedexecutionregion.h b/src/vm/constrainedexecutionregion.h deleted file mode 100644 index 4b41b2570e..0000000000 --- a/src/vm/constrainedexecutionregion.h +++ /dev/null @@ -1,566 +0,0 @@ -// 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. -// -// Methods to support the implementation of Constrained Execution Regions (CERs). This includes logic to walk the IL of methods to -// determine the statically determinable call graph and prepare each submethod (jit, prepopulate generic dictionaries etc., -// everything needed to ensure that the runtime won't generate implicit failure points during the execution of said call graph). -// - -// - - -#ifndef __CONSTRAINED_EXECUTION_REGION_H -#define __CONSTRAINED_EXECUTION_REGION_H - -#ifdef FEATURE_CER - -#include <corhlpr.h> -#include <typestring.h> - - -// An enumeration that abstracts the interesting information (from our point of view) present in a reliability contract decorating a -// method. -enum ReliabilityContractLevel -{ - RCL_UNKNOWN = -1, // The contract attribute hasn't been read yet - RCL_NO_CONTRACT = 0, // No contract (or a fairly useless one) was specified - RCL_BASIC_CONTRACT = 1, // The contract promises enough for the method to be a legal member of a CER call graph - RCL_PREPARE_CONTRACT = 2, // The contract promises enough to be worth preparing the method as part of a CER call graph -}; - -// Various definitions used to parse reliability contracts. These must be kept synchronized with the managed version in -// BCL\System\Runtime\Reliability\ReliabilityContractAttribute.cs - -#define RELIABILITY_CONTRACT_NAME "System.Runtime.ConstrainedExecution.ReliabilityContractAttribute" -#define RC_CONSISTENCY_PROP_NAME "ConsistencyGuarantee" -#define RC_CER_PROP_NAME "Cer" - -enum { - RC_CONSISTENCY_CORRUPT_PROCESS = 0, - RC_CONSISTENCY_CORRUPT_APPDOMAIN = 1, - RC_CONSISTENCY_CORRUPT_INSTANCE = 2, - RC_CONSISTENCY_CORRUPT_NOTHING = 3, - RC_CONSISTENCY_UNDEFINED = 4, - RC_CER_NONE = 0, - RC_CER_MAYFAIL = 1, - RC_CER_SUCCESS = 2, - RC_CER_UNDEFINED = 3 -}; - - -// We compact the reliability contract states above into a single DWORD format easy to cache at the assembly and class level -// opaquely. We also encode in this DWORD whether a given part of the state has been defined yet (an assembly might set a -// consistency level without specifying a cer level, for instance, and this information is vital when merging states between -// assembly, class and method levels). -// The macros below handle the encoding so nobody else needs to know the details. - -// The base state for an encoded DWORD: neither consistency or cer defined. -#define RC_NULL RC_ENCODE(RC_CONSISTENCY_UNDEFINED, RC_CER_UNDEFINED) - -// Extract the raw consistency value from an encoded DWORD. -#define RC_CONSISTENCY(_encoded) ((_encoded) >> 2) - -// Extract the raw cer value from an encoded DWORD. -#define RC_CER(_encoded) ((_encoded) & 3) - -// Produce an encoded DWORD from a pair of raw consistency and cer values. Values must have been range validated first. -#define RC_ENCODE(_consistency, _cer) (DWORD)(((_consistency) << 2) | (_cer)) - -// Produce an abstracted ReliabilityContractLevel from an encoded DWORD, see CheckForReliabilityContract for details of the rules. -#define RC_ENCODED_TO_LEVEL(_encoded) \ - ((RC_CONSISTENCY(_encoded) == RC_CONSISTENCY_UNDEFINED || \ - RC_CONSISTENCY(_encoded) < RC_CONSISTENCY_CORRUPT_INSTANCE) ? RCL_NO_CONTRACT : \ - (RC_CER(_encoded) == RC_CER_UNDEFINED || \ - RC_CER(_encoded) == RC_CER_NONE) ? RCL_BASIC_CONTRACT : \ - RCL_PREPARE_CONTRACT) - -// Given two DWORD encodings presumed to come from different scopes (e.g. method and class) merge them to find the effective -// contract state. It's presumed the first encoding is the most tightly scoped (i.e. method would go first in the example above) and -// therefore takes precedence. -#define RC_MERGE(_old, _new) RC_ENCODE((RC_CONSISTENCY(_old) == RC_CONSISTENCY_UNDEFINED) ? \ - RC_CONSISTENCY(_new) : RC_CONSISTENCY(_old), \ - (RC_CER(_old) == RC_CER_UNDEFINED) ? \ - RC_CER(_new) : RC_CER(_old)) \ - -// Return true if either consistency or cer has not been specified in the encoded DWORD given. -#define RC_INCOMPLETE(_encoded) (RC_CONSISTENCY(_encoded) == RC_CONSISTENCY_UNDEFINED || RC_CER(_encoded) == RC_CER_UNDEFINED) - -// Look for reliability contracts at the method, class and assembly level and parse them to extract the information we're interested -// in from a runtime preparation viewpoint. This information is abstracted in the form of the ReliabilityContractLevel enumeration. -ReliabilityContractLevel CheckForReliabilityContract(MethodDesc *pMD); - - -// Structure used to track enough information to identify a method (possibly generic or belonging to a generic class). Includes a -// MethodDesc pointer and a SigTypeContext (values of class and method type parameters to narrow down the exact method being refered -// to). Similar to MethodContext (see ConstrainedExecutionRegion.cpp), but without the unneeded list link field (we expect to embed -// these in arrays, hence the name). -struct MethodContextElement -{ - FixupPointer<PTR_MethodDesc> m_pMethodDesc; // Pointer to a MethodDesc - FixupPointer<PTR_MethodTable> m_pExactMT; // Exact type to disambiguate code shared by instantiations - - MethodDesc * GetMethodDesc() - { - return m_pMethodDesc.GetValue(); - } - - MethodTable * GetExactMT() - { - return m_pExactMT.GetValue(); - } -}; - - -// Base structure used to track which CERs have been prepared so far. -// These structures are looked up via a per-assembly hash table using the root method desc as a key. -// Used to avoid extra work in both the jit and PrepareMethod calls. The latter case is more involved because we support preparing a -// CER with generic type parameters (the instantiation is passed in along with the method in the PrepareMethod call). In that case -// we need to track exactly which instantiations we've prepared for a given method. -struct CerPrepInfo -{ - CerPrepInfo() : - m_fFullyPrepared(false), - m_fRequiresInstantiation(false), - m_fMethodHasCallsWithinExplicitCer(false) - { - CONTRACTL { - THROWS; - GC_NOTRIGGER; - MODE_ANY; - } CONTRACTL_END; - - if (!m_sIsInitAtInstHash.Init(17, NULL, NULL, FALSE)) - COMPlusThrowOM(); - } - - bool m_fFullyPrepared; // True implies we've prep'd this once and there are no shared instantiations - bool m_fRequiresInstantiation; // True implies that this method is shared amongst multiple instantiations - bool m_fMethodHasCallsWithinExplicitCer; // True if method contains calls out from within an explicit PCER range - EEInstantiationHashTable m_sIsInitAtInstHash; // Hash of instantiations we've prepared this CER for -}; - - -#ifdef FEATURE_PREJIT - -// Structure used to represent a CER by a root method and a list of MethodContextElements that indicate all the methods contained. -// The MethodContextElement list is terminated with a sentinel entry (m_pMethodDesc set to NULL). -// Keep this structure small since we'll access the whole array of them randomly at runtime; density is our best friend. -struct CerRoot -{ - MethodDesc *m_pRootMD; // Root method (no type context since it never has type params) - MethodContextElement *m_pList; // List of methods in this CER -}; - -// Class used to track all the CERs rooted at methods defined within a given module that are discovered at ngen time. This data is -// then used at runtime to determine when and how to perform necessary restoration work so that the CERs don't encounter any -// unexpected failure points during execution. -// During ngen this class keeps a dynamically expanded array of CER roots (both the class and the array are allocated from a win32 -// heap). When we save the image to storage (and thus know the final size of the table) we combine the two so that at runtime -// they're adjacent and exactly the right size. -class CerNgenRootTable -{ -#ifdef DACCESS_COMPILE - friend class NativeImageDumper; -#endif - - DWORD *m_pRestoreBitmap; // Pointer to array of restored flag bits - DWORD m_cRoots; // Count of root methods represented - DWORD m_cSlots; // Extra empty slots at the tail of the array below (ngen time only) - CerRoot *m_pRoots; // Pointer to array of CER roots (sorted by RootMD address) - MethodContextElement **m_pRootsInCompilationOrder; // Pointer to array of CerRoot::m_pList (in the order AddRoot is called) - -public: - - CerNgenRootTable() : - m_pRestoreBitmap(NULL), - m_cRoots(0), - m_cSlots(0), - m_pRoots(NULL), - m_pRootsInCompilationOrder(NULL) - { - } - - ~CerNgenRootTable() - { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - SO_TOLERANT; - MODE_ANY; - } - CONTRACTL_END; - delete m_pRestoreBitmap; - delete m_pRoots; - delete m_pRootsInCompilationOrder; - } - - // Add a new root to the table, expanding it as necessary. Note that this method must be called with the CerCrst already held. - void AddRoot(MethodDesc *pRootMD, MethodContextElement *pList); - - // Retrieve the address of the list of methods for the CER rooted at the given index. - inline MethodContextElement *GetList(DWORD dwIndex) { LIMITED_METHOD_CONTRACT; _ASSERTE(dwIndex < m_cRoots); return m_pRoots[dwIndex].m_pList; } - - // Retrieve the address of the list of methods for the CER rooted at the given method. (The root must exist). - inline MethodContextElement *GetList(MethodDesc *pRootMD) { WRAPPER_NO_CONTRACT; return GetList(FindIndex(pRootMD)); } - - // Indicate whether the given method has ngen restoration information associated with it. - inline bool IsNgenRootMethod(MethodDesc *pRootMD) { WRAPPER_NO_CONTRACT; return FindIndex(pRootMD) != NoSuchRoot; } - - // Prepare the CER rooted at the given method (it's OK to pass a MethodDesc* that doesn't root a CER, in which case the method - // is a no-op). - void Restore(MethodDesc *pRootMD); - - // Ngen callouts to help serialize this structure and its children to storage. - void Save(DataImage *image, CorProfileData *profileData); - void Fixup(DataImage *image); - void FixupRVAs(DataImage *image); - - // Calculate (in bytes) the size of bitmap to allocate to record whether each CER has been restored at runtime. Size is - // rounded up to DWORD alignment. - inline DWORD SizeOfRestoreBitmap() - { - LIMITED_METHOD_CONTRACT; - return ((m_cRoots + 31) / 32) * sizeof(DWORD); - } - - inline DWORD GetRootCount() { LIMITED_METHOD_CONTRACT; return m_cRoots; } - inline CerRoot *GetRoots() { LIMITED_METHOD_CONTRACT; return m_pRoots; } - inline DWORD *GetRestoreBitmap() { LIMITED_METHOD_CONTRACT; return m_pRestoreBitmap; } - -private: - enum { NoSuchRoot = 0xffffffff }; - - // Locate the index of a given CerRoot record in the array given the root method. This is used to access the array and to locate - // the restored flag for the entry in the restored bitmap. NoSuchRoot is returned if the root cannot be found. - DWORD FindIndex(MethodDesc *pRootMD); -}; - -#endif - - -// Default initial size for hash table used to track CerPrepInfo structures on a per-module basis. -#define CER_DEFAULT_HASH_SIZE 17 - - -// Structure used to track a single exception handling range (catch, finally etc.). We build an array of these and then track which -// ones have become 'activated' by virtue of having their try clause immediately preceded by a call to our preparation marker -// method. This allows us to determine which call sites in the method body should be followed during method preparation. -struct EHClauseRange -{ - DWORD m_dwTryOffset; - DWORD m_dwHandlerOffset; - DWORD m_dwHandlerLength; - bool m_fActive; -}; - - -// Structure used to track enough information to identify a method (possibly generic or belonging to a generic class). Includes a -// MethodDesc pointer and a SigTypeContext (values of class and method type parameters to narrow down the exact method being refered -// to). The structure also contains a next pointer so that it can be placed in a singly linked list (see MethodContextStack below). -struct MethodContext -{ - MethodContext *m_pNext; // Next MethodContext in a MethodContextStack list - MethodDesc *m_pMethodDesc; // Pointer to a MethodDesc - SigTypeContext m_sTypeContext; // Additional type parameter information to qualify the exact method targetted - bool m_fRoot; // Does this method contain a CER root of its own? - - // Allocate and initialize a MethodContext from the per-thread stacking allocator (we assume the checkpoint has already been - // taken). - static MethodContext* PerThreadAllocate(MethodDesc *pMD, SigTypeContext *pTypeContext) - { - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } CONTRACTL_END; - - - MethodContext *pContext = new (&GetThread()->m_MarshalAlloc) MethodContext(); - pContext->m_pMethodDesc = pMD; - pContext->m_sTypeContext = *pTypeContext; - pContext->m_fRoot = false; - - return pContext; - } - - // Determine if two MethodContexts are equivalent (same MethodDesc pointer and identical arrays of TypeHandles in the - // TypeContext). - bool Equals(MethodContext *pOther) - { - WRAPPER_NO_CONTRACT; - - if (pOther->m_pMethodDesc != m_pMethodDesc) - return false; - - if (pOther->m_sTypeContext.m_classInst.GetNumArgs() != m_sTypeContext.m_classInst.GetNumArgs()) - return false; - - if (pOther->m_sTypeContext.m_methodInst.GetNumArgs() != m_sTypeContext.m_methodInst.GetNumArgs()) - return false; - - DWORD i; - - for (i = 0; i < m_sTypeContext.m_classInst.GetNumArgs(); i++) - if (pOther->m_sTypeContext.m_classInst[i] != m_sTypeContext.m_classInst[i]) - return false; - - for (i = 0; i < m_sTypeContext.m_methodInst.GetNumArgs(); i++) - if (pOther->m_sTypeContext.m_methodInst[i] != m_sTypeContext.m_methodInst[i]) - return false; - - return true; - } - -#ifdef _DEBUG -#define CER_DBG_MAX_OUT 4096 - char *ToString() - { - STATIC_CONTRACT_THROWS; - STATIC_CONTRACT_GC_TRIGGERS; - STATIC_CONTRACT_MODE_ANY; - - // Support up to two ToString calls before we re-use a buffer and overwrite previous output. - static char szOut1[CER_DBG_MAX_OUT]; - static char szOut2[CER_DBG_MAX_OUT]; - static char *pszOut = szOut1; - - StackSString ssBuffer; - StackScratchBuffer ssScratch; - - TypeString::AppendMethod(ssBuffer, m_pMethodDesc, m_sTypeContext.m_classInst, TypeString::FormatNamespace | TypeString::FormatAngleBrackets); - sprintf_s(&pszOut[0], CER_DBG_MAX_OUT, "%s", ssBuffer.GetUTF8(ssScratch)); - - char *pszReturn = pszOut; - pszOut = pszOut == szOut1 ? szOut2 : szOut1; - return pszReturn; - } -#endif -}; - -// Maintains a stack of MethodContexts (implemented as a singly linked list with insert and remove operations only at the head). -class MethodContextStack -{ - MethodContext *m_pFirst; // The head of the linked list - DWORD m_cElements; // Count of elements in the stack - -public: - - // Initialize to an empty list. - MethodContextStack() - { - LIMITED_METHOD_CONTRACT; - - m_pFirst = NULL; - m_cElements = 0; - } - - // Push a MethodContext pointer on the head of the list. - void Push(MethodContext *pContext) - { - LIMITED_METHOD_CONTRACT; - - pContext->m_pNext = m_pFirst; - m_pFirst = pContext; - m_cElements++; - } - - // Remove and retrieve the most recently pushed MethodContext. Return NULL if no more entries exist. - MethodContext *Pop() - { - LIMITED_METHOD_CONTRACT; - - MethodContext* pContext = m_pFirst; - if (pContext == NULL) - return NULL; - - m_pFirst = pContext->m_pNext; - m_cElements--; - - return pContext; - } - - // Return true if an MethodContext equivalent to the argument exists in the stack. - bool IsInStack(MethodContext *pMatchContext) - { - WRAPPER_NO_CONTRACT; - - MethodContext* pContext = m_pFirst; - while (pContext) { - if (pContext->Equals(pMatchContext)) - return true; - pContext = pContext->m_pNext; - } - - return false; - } - - // Get count of elements in the stack. - DWORD GetCount() - { - LIMITED_METHOD_CONTRACT; - - return m_cElements; - } -}; - - -class MethodCallGraphPreparer -{ - MethodDesc *m_pRootMD; - SigTypeContext *m_pRootTypeContext; - - COR_ILMETHOD_DECODER *m_pMethodDecoder; - - MethodContextStack m_sLeftToProcess; // MethodContexts we have yet to look at in this call graph - MethodContextStack m_sAlreadySeen; // MethodContexts we've already processed at least once - - EHClauseRange *m_pEHClauses; // Array of exception handling clauses in current method (only if !fEntireMethod) - DWORD m_cEHClauses; // Number of elements in above array - CerPrepInfo *m_pCerPrepInfo; // Context recording how much preparation this region has had - MethodContextStack m_sPersist; // MethodContexts we need to keep around past the 'prepare' phase of preparation -#ifdef FEATURE_NATIVE_IMAGE_GENERATION - bool m_fNgen; // True when being called as part of an ngen - MethodContextStack m_sRootMethods; // Methods containing a sub-CER (excludes the real root) -#endif // FEATURE_NATIVE_IMAGE_GENERATION - Thread *m_pThread; // Cached managed thread pointer (for allocations and the like) - bool m_fPartialPreparation; // True if we have unbound type vars at the CER root and can only prep one instantiation at a time - - bool m_fEntireMethod; // True if are preparing for the entire method - bool m_fExactTypeContext; - bool m_fMethodHasCallsWithinExplicitCer; // True if method contains calls out from within an explicit PCER range - - bool m_fIgnoreVirtualCERCallMDA; // True if VirtualCER MDA is not desirable to be fired - - MethodCallGraphPreparer * m_pNext; // Links this instance on a per-thread stack used to detect - // and defeat recursive preparations - - public: - MethodCallGraphPreparer(MethodDesc *pRootMD, SigTypeContext *pRootTypeContext, bool fEntireMethod, bool fExactTypeContext, bool fIgnoreVirtualCERCallMDA = false); - - // Walk the call graph of the method given by m_pRootMD (and type context in m_pRootTypeContext which provides instantiation information - // for generic methods/classes). - // - // If fEntireMethod is true then the entire body of pRootMD is scanned for callsites, otherwise we assume that one or more CER - // exception handlers exist in the method and only the finally and catch blocks of such handlers are scanned for graph roots. - // - // Each method we come across in the call graph (excluding late bound invocation destinations precipitated by virtual or interface - // calls) is jitted and has any generic dictionary information we can determine at jit time prepopulated. This includes implicit - // cctor invocations. If this method is called at ngen time we will attach extra fixup information to the affected method to ensure - // that fixing up the root method of the graph will cause all methods in the graph to be fixed up at that point also. - // - // Some generic dictionary entries may not be prepopulated if unbound type variables exist at the root of the call tree. Such cases - // will be ignored (as for the virtual/interface dispatch case we assume the caller will use an out-of-band mechanism to pre-prepare - // these entries explicitly). - // - // Returns true if the m_pRootMD contains a CER that calls outside the method. - // - bool Run(); - - // Methods used to control re-entrancy on the same thread. Essentially we'd like to avoid all re-entrancy - // (since it can lead to unbounded recursion easily) but unfortunately jitting methods during the - // preparation phase can cause this both directly (if we spot a sub-root) or indirectly (where implicit - // jit execution of a cctor causes a possibly unrelated CER graph to be prepared). The algorithm we use to - // avoid this records a stack of preparations attempts on the current thread (implemented via a singly - // linked list of the MethodCallGraphPreparer instances). Re-entrant prepare requests become noops if - // they're for a root method we're already processing (anywhere in the stack) and run to completion - // otherwise. This prevents infinite recursion since it removes at least one method from the intersection - // of the CER call graphs on each iteration. Theoretically it might not be the most efficient solution - // since there might still be a lot of overlap between graphs, but in practice the number of sub-CER roots - // is likely to be small and we won't recurse very far. This will still allow a re-entrant preparation - // that is the result of running a cctor to potentially early-out (and thus allow code to run before its - // CERs have been fully prepped). But this should only happen when a CER causes (directly or indirectly) a - // cctor to run that depends on that CER having been prepared already, which we really can't do much - // about. - // - BOOL CanPreparationProceed(MethodDesc * pMD, SigTypeContext * pTypeContext); - - static void BeginPrepareCerForHolder(MethodCallGraphPreparer *pPrepState); - static void EndPrepareCerForHolder(MethodCallGraphPreparer *pPrepState); - - typedef Holder<MethodCallGraphPreparer*, BeginPrepareCerForHolder, EndPrepareCerForHolder> ThreadPreparingCerHolder; - - private: - void GetEHClauses(); - void MarkEHClauseActivatedByCERCall(MethodContext *pContext, BYTE *pbIL, DWORD cbIL); - bool CheckIfCallsiteWithinCER(DWORD dwOffset); - bool ShouldGatherExplicitCERCallInfo(); - void LookForInterestingCallsites(MethodContext *pContext); - void PrepareMethods(); - bool RecordResults(); -}; - -// Determines whether the given method contains a CER root that can be pre-prepared (i.e. prepared at jit time). -bool ContainsPrePreparableCerRoot(MethodDesc *pMD); - -// Prepares the critical finalizer call graph for the given object type (which must derive from CriticalFinalizerObject). This -// involves preparing at least the finalizer method and possibly some others (for SafeHandle and CriticalHandle derivations). If a -// module pointer is supplied then only the critical methods introduced in that module are prepared (this is used at ngen time to -// ensure that we're only generating ngen preparation info for the targetted module). -void PrepareCriticalFinalizerObject(MethodTable *pMT, Module *pModule = NULL); - -void PrepareMethodDesc(MethodDesc* pMD, Instantiation classInst = Instantiation(), Instantiation methodInst = Instantiation(), BOOL onlyContractedMethod = FALSE, BOOL fIgnoreVirtualCERCallMDA = FALSE); -// Determine whether the method given as a parameter is the root of a CER. -// @todo: Need an x86 offset as well and logic to determine whether we're actually in a root-CER portion of the method (if the whole -// thing isn't the root). -bool IsCerRootMethod(MethodDesc *pMD); - -// Fill the cache of overflowed generic dictionary entries that the jit maintains with all the overflow slots stored so far in the -// dictionary layout. -void PrepopulateGenericHandleCache(DictionaryLayout *pDictionaryLayout, - MethodDesc *pMD, - MethodTable *pMT); - -DWORD GetReliabilityContract(IMDInternalImport *pImport, mdToken tkParent); - -#ifdef FEATURE_PREJIT - -// Prepare the class if it is derived from CriticalFinalizerObject. This is used at ngen time since such classes are normally -// prepared at runtime (at instantiation) and would therefore miss the ngen image. -void PrepareCriticalType(MethodTable *pMT); - -// Prepare a method and its statically determinable call graph if a hint attribute has been applied. This is only called at ngen -// time to save additional preparation information into the ngen image that wouldn't normally be there (and thus lower runtime -// overheads). -void PrePrepareMethodIfNecessary(CORINFO_METHOD_HANDLE hMethod); - -#endif - - -// A fixed sized hash table keyed by pointers and storing two bits worth of value for every entry. The value is stored in the low -// order bits of the keys, so the pointers must be at least DWORD aligned. No hash table expansion occurs so new entries will sooner -// or later overwrite old. The implementation uses no locks (all accesses are single aligned pointer sized operations and therefore -// inherently atomic). -// The purpose of this table is to store a smallish number of reliability contract levels for the most recently queried methods, -// mainly for the purpose of speeding up thread abort processing (where we will walk the stack probing methods for contracts, -// sometimes repeatedly). So we use a small fixed sized hash to speed up lookups on average but avoid impacting working set. -#define PHC_BUCKETS 29 -#define PHC_CHAIN 5 -#define PHC_DATA_MASK 3 - -class PtrHashCache -{ -public: - PtrHashCache(); - bool Lookup(void *pKey, DWORD *pdwValue); - void Add(void *pKey, DWORD dwValue); - -#ifdef _DEBUG - void DbgDumpStats(); -#endif - -private: - DWORD GetHash(void *pKey); - - UINT_PTR m_rEntries[PHC_BUCKETS * PHC_CHAIN]; - -#ifdef _DEBUG - DWORD m_dwHits; - DWORD m_dwMisses; -#endif -}; - -#endif // FEATURE_CER - -#endif diff --git a/src/vm/crossgen/CMakeLists.txt b/src/vm/crossgen/CMakeLists.txt index c6ef163d53..bef9f62d85 100644 --- a/src/vm/crossgen/CMakeLists.txt +++ b/src/vm/crossgen/CMakeLists.txt @@ -96,12 +96,6 @@ set(VM_CROSSGEN_SOURCES ../crossgencompile.cpp ) -if(FEATURE_CER) - list(APPEND VM_CROSSGEN_SOURCES - ../constrainedexecutionregion.cpp - ) -endif(FEATURE_CER) - if(FEATURE_READYTORUN) list(APPEND VM_CROSSGEN_SOURCES ../readytoruninfo.cpp diff --git a/src/vm/crossgencompile.cpp b/src/vm/crossgencompile.cpp index d214aa6152..5a4f41e021 100644 --- a/src/vm/crossgencompile.cpp +++ b/src/vm/crossgencompile.cpp @@ -16,7 +16,6 @@ #include "comdelegate.h" #include "compile.h" -#include "constrainedexecutionregion.h" #include "security.h" #include "invokeutil.h" #include "comcallablewrapper.h" diff --git a/src/vm/dataimage.cpp b/src/vm/dataimage.cpp index df1ef30291..f6b8337b7c 100644 --- a/src/vm/dataimage.cpp +++ b/src/vm/dataimage.cpp @@ -12,7 +12,6 @@ #include "compile.h" #include "field.h" -#include "constrainedexecutionregion.h" // // Include Zapper infrastructure here @@ -892,10 +891,6 @@ void DataImage::FixupRVAs() FixupModuleRVAs(); FixupRvaStructure(); -#ifdef FEATURE_CER - if (m_module->m_pCerNgenRootTable != NULL) - m_module->m_pCerNgenRootTable->FixupRVAs(this); -#endif // Dev11 bug 181494 instrumentation if (m_Fixups.GetCount() != m_iCurrentFixup) EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); diff --git a/src/vm/gchelpers.cpp b/src/vm/gchelpers.cpp index 30f6dd0c81..f2311f8351 100644 --- a/src/vm/gchelpers.cpp +++ b/src/vm/gchelpers.cpp @@ -21,7 +21,6 @@ #include "threads.h" #include "fieldmarshaler.h" #include "interoputil.h" -#include "constrainedexecutionregion.h" #include "dynamicmethod.h" #include "stubhelpers.h" #include "eventtrace.h" @@ -1005,10 +1004,6 @@ OBJECTREF AllocateObject(MethodTable *pMT g_IBCLogger.LogMethodTableAccess(pMT); SetTypeHandleOnThreadForAlloc(TypeHandle(pMT)); -#ifdef FEATURE_CER - if (pMT->HasCriticalFinalizer()) - PrepareCriticalFinalizerObject(pMT); -#endif #ifdef FEATURE_COMINTEROP #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION diff --git a/src/vm/jithelpers.cpp b/src/vm/jithelpers.cpp index 5dc83b12f5..48cfc1a41b 100644 --- a/src/vm/jithelpers.cpp +++ b/src/vm/jithelpers.cpp @@ -50,7 +50,6 @@ #include "genericdict.h" #include "array.h" #include "debuginfostore.h" -#include "constrainedexecutionregion.h" #include "security.h" #include "safemath.h" #include "threadstatics.h" diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index d595057a66..0128c3009b 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -51,7 +51,6 @@ #include "genericdict.h" #include "array.h" #include "debuginfostore.h" -#include "constrainedexecutionregion.h" #include "security.h" #include "safemath.h" #include "runtimehandles.h" @@ -5086,29 +5085,6 @@ void CEEInfo::getCallInfo( } -#ifdef FEATURE_CER - if (pMD == g_pPrepareConstrainedRegionsMethod && !isVerifyOnly()) - { - MethodDesc * methodFromContext = GetMethodFromContext(pResolvedToken->tokenContext); - - if (methodFromContext != NULL && methodFromContext->IsIL()) - { - SigTypeContext typeContext; - GetTypeContext(pResolvedToken->tokenContext, &typeContext); - - // If the method whose context we're in is attempting a call to PrepareConstrainedRegions() then we've found the root - // method in a Constrained Execution Region (CER). Prepare the call graph of the critical parts of that method now so - // they won't fail because of us at runtime. - MethodCallGraphPreparer mcgp(methodFromContext, &typeContext, false, false); - bool fMethodHasCallsWithinExplicitCer = mcgp.Run(); - if (! g_pConfig->ProbeForStackOverflow() || ! fMethodHasCallsWithinExplicitCer) - { - // if the method does not contain any CERs that call out, we can optimize the probe away - pMD = MscorlibBinder::GetMethod(METHOD__RUNTIME_HELPERS__PREPARE_CONSTRAINED_REGIONS_NOOP); - } - } - } -#endif // FEATURE_CER TypeHandle exactType = TypeHandle(pResolvedToken->hClass); @@ -8237,16 +8213,6 @@ bool CEEInfo::canTailCall (CORINFO_METHOD_HANDLE hCaller, } } -#ifdef FEATURE_CER - // We cannot tail call from a root CER method, the thread abort algorithm to - // detect CERs depends on seeing such methods on the stack. - if (IsCerRootMethod(pCaller)) - { - result = false; - szFailReason = "Caller is a CER root"; - goto exit; - } -#endif // FEATURE_CER result = true; diff --git a/src/vm/method.cpp b/src/vm/method.cpp index eceb936b57..12eeb60c96 100644 --- a/src/vm/method.cpp +++ b/src/vm/method.cpp @@ -3255,15 +3255,6 @@ bool MethodDesc::CanSkipDoPrestub ( return false; } -#ifdef FEATURE_CER - // Can't hard bind to a method which contains one or more Constrained Execution Region roots (we need to force the prestub to - // execute for such methods). - if (ContainsPrePreparableCerRoot(this)) - { - *pReason = CORINFO_INDIRECT_CALL_CER; - return false; - } -#endif // FEATURE_CER // Check whether our methoddesc needs restore if (NeedsRestore(GetAppDomain()->ToCompilationDomain()->GetTargetImage(), TRUE)) diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp index 72be79bc83..55f1afd965 100644 --- a/src/vm/methodtablebuilder.cpp +++ b/src/vm/methodtablebuilder.cpp @@ -15,7 +15,6 @@ #include "methodtablebuilder.h" -#include "constrainedexecutionregion.h" #include "sigbuilder.h" #include "dllimport.h" #include "fieldmarshaler.h" @@ -191,18 +190,6 @@ MethodTableBuilder::CreateClass( Module *pModule, pEEClass->GetSecurityProperties()->SetFlags(dwSecFlags, dwNullDeclFlags); } -#ifdef FEATURE_CER - // Cache class level reliability contract info. - DWORD dwReliabilityContract = ::GetReliabilityContract(pInternalImport, cl); - if (dwReliabilityContract != RC_NULL) - { - // Reliability contract is an optional field. If we have a non-default value we need to ensure the - // optional field descriptor has been allocated. - EnsureOptionalFieldsAreAllocated(pEEClass, pamTracker, pAllocator->GetLowFrequencyHeap()); - - pEEClass->SetReliabilityContract(dwReliabilityContract); - } -#endif // FEATURE_CER if (fHasLayout) pEEClass->SetHasLayout(); diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp index 9fd7c52446..723e6b68f2 100644 --- a/src/vm/prestub.cpp +++ b/src/vm/prestub.cpp @@ -24,7 +24,6 @@ #include "listlock.inl" #include "stubgen.h" #include "eventtrace.h" -#include "constrainedexecutionregion.h" #include "array.h" #include "compile.h" #include "ecall.h" @@ -1233,12 +1232,6 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT) RETURN GetStableEntryPoint(); } -#if defined(FEATURE_PREJIT) && defined(FEATURE_CER) - // If this method is the root of a CER call graph and we've recorded this fact in the ngen image then we're in the prestub in - // order to trip any runtime level preparation needed for this graph (P/Invoke stub generation/library binding, generic - // dictionary prepopulation etc.). - GetModule()->RestoreCer(this); -#endif // FEATURE_PREJIT && FEATURE_CER #ifdef FEATURE_COMINTEROP /************************** INTEROP *************************/ diff --git a/src/vm/reflectioninvocation.cpp b/src/vm/reflectioninvocation.cpp index 6311bdf65d..1c93d23946 100644 --- a/src/vm/reflectioninvocation.cpp +++ b/src/vm/reflectioninvocation.cpp @@ -22,7 +22,6 @@ #include "contractimpl.h" #include "virtualcallstub.h" #include "comdelegate.h" -#include "constrainedexecutionregion.h" #include "generics.h" #ifdef FEATURE_COMINTEROP @@ -2263,103 +2262,9 @@ FCIMPL1(void, ReflectionInvocation::PrepareContractedDelegate, Object * delegate } CONTRACTL_END; -#ifdef FEATURE_CER - if (delegateUNSAFE == NULL) - return; - - OBJECTREF delegate = ObjectToOBJECTREF(delegateUNSAFE); - HELPER_METHOD_FRAME_BEGIN_1(delegate); - - PrepareDelegateHelper(&delegate, TRUE); - - HELPER_METHOD_FRAME_END(); -#endif // FEATURE_CER } FCIMPLEND -#ifdef FEATURE_CER -void ReflectionInvocation::PrepareDelegateHelper(OBJECTREF *pDelegate, BOOL onlyContractedMethod) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - PRECONDITION(CheckPointer(pDelegate)); - PRECONDITION(CheckPointer(OBJECTREFToObject(*pDelegate))); - } - CONTRACTL_END; - - // Make sure the delegate subsystem itself is prepared. - // Force the immediate creation of any global stubs required. This is platform specific. -#ifdef _TARGET_X86_ - { - GCX_PREEMP(); - COMDelegate::TheDelegateInvokeStub(); - } -#endif - - MethodDesc *pMDTarget = COMDelegate::GetMethodDesc(*pDelegate); - MethodDesc *pMDInvoke = COMDelegate::FindDelegateInvokeMethod((*pDelegate)->GetMethodTable()); - - // If someone does give us a multicast delegate, then both MDs will be the same -- they - // will both be the Delegate's Invoke member. Normally, pMDTarget points at the method - // the delegate is wrapping, of course. - if (pMDTarget == pMDInvoke) - { - pMDTarget->CheckRestore(); - - // The invoke method itself is never generic, but the delegate class itself might be. - PrepareMethodDesc(pMDInvoke, - pMDInvoke->GetExactClassInstantiation((*pDelegate)->GetTypeHandle()), - Instantiation(), - onlyContractedMethod); - } - else - { - pMDTarget->CheckRestore(); - pMDInvoke->CheckRestore(); - - // Prepare the eventual target method first. - - // Load the exact type of the method if it needs to be instantiated (because it's a generic type definition, e.g. C<T>, or a - // shared type instantiation, e.g. C<Object>). - MethodTable *pExactMT = pMDTarget->GetMethodTable(); - if (pExactMT->IsGenericTypeDefinition() || pExactMT->IsSharedByGenericInstantiations()) - { - OBJECTREF targetObj = COMDelegate::GetTargetObject(*pDelegate); - -#ifdef FEATURE_REMOTING - // We prepare the delegate for the sole purpose of reliability (CER). - // If the target is a transparent proxy, we cannot guarantee reliability anyway. - if (CRemotingServices::IsTransparentProxy(OBJECTREFToObject(targetObj))) - return; -#endif //FEATURE_REMOTING - - pExactMT = targetObj->GetMethodTable(); - } - - - // For delegates with generic target methods it must be the case that we are passed an instantiating stub -- there's no - // other way the necessary method instantiation information can be passed to us. - // The target MD may be shared by generic instantiations as long as it does not require extra instantiation arguments. - // We have the actual target object so we can extract the exact class instantiation from it. - _ASSERTE(!pMDTarget->RequiresInstArg() && - !pMDTarget->ContainsGenericVariables()); - - PrepareMethodDesc(pMDTarget, - pMDTarget->GetExactClassInstantiation(TypeHandle(pExactMT)), - pMDTarget->GetMethodInstantiation(), - onlyContractedMethod); - - // Now prepare the delegate invoke method. - // The invoke method itself is never generic, but the delegate class itself might be. - PrepareMethodDesc(pMDInvoke, - pMDInvoke->GetExactClassInstantiation((*pDelegate)->GetTypeHandle()), - Instantiation(), - onlyContractedMethod); - } -} -#endif // FEATURE_CER FCIMPL0(void, ReflectionInvocation::ProbeForSufficientStack) { @@ -2606,18 +2511,6 @@ FCIMPL3(void, ReflectionInvocation::ExecuteCodeWithGuaranteedCleanup, Object* co if (gc.backoutDelegate == NULL) COMPlusThrowArgumentNull(W("backoutCode")); -#ifdef FEATURE_CER - if (!IsCompilationProcess()) - { - // Delegates are prepared as part of the ngen process, so only prepare the backout - // delegate for non-ngen processes. - PrepareDelegateHelper((OBJECTREF *)&gc.backoutDelegate, FALSE); - - // Make sure the managed backout code helper function has been prepared before we - // attempt to run the backout code. - PrepareMethodDesc(g_pExecuteBackoutCodeHelperMethod, Instantiation(), Instantiation(), FALSE, TRUE); - } -#endif // FEATURE_CER ExecuteCodeWithGuaranteedCleanupHelper(&gc); diff --git a/src/vm/runtimecallablewrapper.cpp b/src/vm/runtimecallablewrapper.cpp index a3f71279d9..93b5c2c38a 100644 --- a/src/vm/runtimecallablewrapper.cpp +++ b/src/vm/runtimecallablewrapper.cpp @@ -41,7 +41,6 @@ class Object; #include "mdaassistants.h" #include "olevariant.h" #include "interopconverter.h" -#include "constrainedexecutionregion.h" #include "typestring.h" #ifdef FEATURE_REMOTING #include "crossdomaincalls.h" diff --git a/src/vm/runtimehandles.h b/src/vm/runtimehandles.h index bd3dc49f88..2450a2b971 100644 --- a/src/vm/runtimehandles.h +++ b/src/vm/runtimehandles.h @@ -12,7 +12,6 @@ #include "fcall.h" #include "field.h" #include "typectxt.h" -#include "constrainedexecutionregion.h" typedef void* EnregisteredTypeHandle; class SignatureNative; diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp index 26c8dceb86..b58cc04631 100644 --- a/src/vm/threads.cpp +++ b/src/vm/threads.cpp @@ -72,7 +72,6 @@ CLREvent *ThreadStore::s_pWaitForStackCrawlEvent; #ifndef DACCESS_COMPILE -#include "constrainedexecutionregion.h" BOOL Thread::s_fCleanFinalizedThread = FALSE; diff --git a/src/vm/threadsuspend.cpp b/src/vm/threadsuspend.cpp index f9a96e7e8f..dd8bb48df9 100644 --- a/src/vm/threadsuspend.cpp +++ b/src/vm/threadsuspend.cpp @@ -754,29 +754,6 @@ static StackWalkAction TAStackCrawlCallBackWorker(CrawlFrame* pCf, StackCrawlCon } #undef METHODNAME -#ifdef FEATURE_CER - // If we're asking about CERs and we don't yet have a definite answer either way then take a closer look at the current method. - if (pData->eType & StackCrawlContext::SCC_CheckWithinCer && !pData->fUnprotectedCode && !pData->fWithinCer) - { - // Check for CER root methods (these are never inlined). If we've found one of these at the root of a bunch of potential CER - // methods (i.e. those with a compatible reliability contract) then we're executing in a CER. - if (IsCerRootMethod(pMD)) - pData->fWithinCer = true; - - // Only need to look deeper if we couldn't decide if we're in a CER yet. - if (!pData->fWithinCer) - { - // IL stubs are transparent to CERs. - if (!pMD->IsILStub()) - // Check for reliability contracts on the method (and class and assembly). If it's high enough level to be included - // in a CER then we can continue (hopefully finding a CER root method further down the stack). Otherwise we've got - // at least one method that's not part of a CER on the top of the stack so we're definitely not executing within a - // CER. - if (CheckForReliabilityContract(pMD) < RCL_BASIC_CONTRACT) - pData->fUnprotectedCode = true; - } - } -#endif // FEATURE_CER // If we weren't asked about EH clauses then we can return now (stop the stack trace if we have a definitive answer on the CER // question, move to the next frame otherwise). @@ -1124,50 +1101,6 @@ struct CerStackCrawlContext bool m_fWithinCer; // The result }; -#ifdef FEATURE_CER -// Callback used on the stack crawl described above. -StackWalkAction CerStackCrawlCallBack(CrawlFrame *pCf, void *pData) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - CerStackCrawlContext *pCtx = (CerStackCrawlContext *)pData; - - // Skip initial frame which should be our target. - if (pCtx->m_fFirstFrame) - { - _ASSERTE(pCtx->m_pStartMethod == pCf->GetFunction()); - pCtx->m_fFirstFrame = false; - return SWA_CONTINUE; - } - - // If we get this far we've located the target method and are scanning the calling tree to see if we have a chain of methods - // marked with strong reliability contracts terminated by a CER root method. - MethodDesc *pMD = pCf->GetFunction(); - _ASSERTE(pMD != NULL); - - // If the current method is the root of a CER then we can say the target method was executing in a CER and terminate the stack - // walk. - // @TODO: Need to be more specific than this: only certain areas of the root method are actually in the CER. - if (IsCerRootMethod(pMD)) - { - pCtx->m_fWithinCer = true; - return SWA_ABORT; - } - - // Now look at reliability contracts on the current method. If they're missing or very weak then the chain is broken and the - // target method cannot possibly be in a CER. - if (CheckForReliabilityContract(pMD) < RCL_BASIC_CONTRACT) - return SWA_ABORT; - - // Otherwise everything looks OK so far and we need to investigate the next frame. - return SWA_CONTINUE; -} -#endif // FEATURE_CER // Determine whether the method at the given depth in the thread's execution stack is executing within a CER. BOOL Thread::IsWithinCer(CrawlFrame *pCf) @@ -1179,126 +1112,7 @@ BOOL Thread::IsWithinCer(CrawlFrame *pCf) } CONTRACTL_END; -#ifndef FEATURE_CER return FALSE; -#else - // There had better be a method associated with this frame. - MethodDesc *pMD = pCf->GetFunction(); - _ASSERTE(pMD != NULL); - - // Try the cheap checks first (before resorting to an actual stackwalk). - - // Handle IL stubs specially. We get called for these guys and they always appear to have a strong reliability contract (due to - // the System.StubHelpers class they're placed in) but the stack walking logic we have below will skip them (messing up our - // accounting). For simplicitly and speed we'll just always say these guys are in a CER (we trust the code and it won't block - // indefinitely so it's a safe guess). - if (pMD->IsILStub()) - return TRUE; - - // If the method is itself the root of a CER then we say yes immediately. - // @TODO: Need to be more specific than this: only certain areas of the root method are actually in the CER. - if (IsCerRootMethod(pMD)) - return TRUE; - - // Now look at reliability contracts on the method. If they're missing or very weak then this method cannot possibly be in a - // CER. - if (CheckForReliabilityContract(pMD) < RCL_BASIC_CONTRACT) - return FALSE; - - // No way around it: this method has a good reliability contract but is not the root of a CER. We'll have to have to walk the - // stack to determine whether it was called from a good root. - - // Now things get really tricky. We want to perform a recursive stackwalk (we're called as part of an ongoing stackwalk and we - // wish to recursively look at one or more of the callers of the current frame). - // - // On x86 this is relatively straightforward -- we make a copy of the current crawl frame context (since walking the stack - // updates the context) and build a new regdisplay around it. We can then start a new crawl from that context (ignoring the - // first frame of course, because that's this frame). - // - // 64-bit is trickier because the context provided by the OS might not be (from our point of view) a valid current context. In - // particular IA64 provides a mostly valid context except that the SP is from the caller. AMD64 on the other hand will always - // provide a consistent context, but it may belong to either the current or caller frame. As noted above though, we're really - // not all that interested in the current context, so as long as we can get to a consistent caller context we're happy. - // - // So for AMD64 we'll either have a complete current context and we'll use the the x86 algorithm or we have a complete caller - // context and we can use more or less the x86 algorithm except we don't need to skip the first frame on the stackwalk callback. - // - // IA64 is trickier since it doesn't always give us a consistent context (current or caller). Here we'll have to bite the bullet - // and perform a full stackwalk to build the context we're after. We'll use a combination of the caller SP and the current BSP - // as a discriminator (to determine when the full stackwalk has synchronized with this frame and the real walk can begin, it's - // the same discriminator the OS uses). - // - // <REVISIT_TODO> We will want to try and cache the context we eventually arrive at from this stack walk, since we're likely to see - // further calls to IsWithinCer further down the stack and we can use the end context as a much faster way to sync to a valid - // context in those cases. The chief technical difficulty there is cache management since the OS is handling the actual - // exception walk (so we're not sure when to invalidate our cached data, which presumably we'd store on the Thread). Look into - // hooking into the ExceptionTracker mechanism for this.</REVISIT_TODO> - - REGDISPLAY *pCurrentRd = pCf->GetRegisterSet(); - REGDISPLAY rd; - CONTEXT ctx; - CerStackCrawlContext sContext = { pMD, true, false }; - -#if defined(_TARGET_AMD64_) || defined(_TARGET_ARM_) - // This check is similar to the one in ExceptionTracker::InitializeCrawlFrame. - // - // However, on ARM, we can easily check if we have the caller context (or not) by - // checking the IsCallerContextValid field of RegDisplay, which is set during - // the first pass of exception dispatch since the OS always passes us the caller - // context in that scenario (refer to ExceptionTracker::InitializeCrawlFrame - // implementation for details). - if (ARM_ONLY(pCurrentRd->IsCallerContextValid) NOT_ARM(GetControlPC(pCurrentRd) != GetIP(pCurrentRd->pCurrentContext))) - { - // This is the case on AMD64, or ARM, where the OS has handed us the caller context. Build a regdisplay around that (pretending that - // it's the current context) and reset our first frame flag so the stack walk we're about to do thinks we've already - // processed the current frame. - ctx = *pCurrentRd->pCallerContext; - FillRegDisplay(&rd, &ctx); - sContext.m_fFirstFrame = false; - } - else -#endif // defined(_TARGET_AMD64_) || defined(_TARGET_ARM_) - { - // On x86, ARM or AMD64, where the OS gave us the current context, we just copy that into a new regdisplay (our stackwalking - // callback will skip the first (current) frame for us). - CopyRegDisplay(pCurrentRd, &rd, &ctx); - } - - // The stackwalker requires a starting frame as input. If we're currently inspecting an explicit frame then it's easy -- we just - // pass that. Otherwise (we're on some frameless managed method) we look at all of the frames for the current thread and choose - // the one that would synchronize us for walking to the next frame. - Frame *pFrame; - if (pCf->IsFrameless()) - { -#if defined(_TARGET_X86_) - TADDR limitSP = GetRegdisplaySP(&rd); -#else - TADDR limitSP = (TADDR)( EECodeManager::GetCallerSp(&rd) ); -#endif - pFrame = GetFrame(); - while (pFrame && (TADDR)(pFrame) < limitSP) - pFrame = pFrame->Next(); - } - else - { - pFrame = pCf->GetFrame(); - -#ifdef _TARGET_X86_ - if (pFrame->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr()) - { - // If we walk from an ICF, the function will not be reported again because X86 stack walker handles managed stack frame - // before explicit frames contained in it. - sContext.m_fFirstFrame = false; - } -#endif // _TARGET_X86_ - } - - StackWalkFramesEx(&rd, CerStackCrawlCallBack, &sContext, QUICKUNWIND | FUNCTIONSONLY, pFrame); - - _ASSERTE(!sContext.m_fFirstFrame); - - return sContext.m_fWithinCer; -#endif // FEATURE_CER } #if defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK) diff --git a/src/vm/vars.cpp b/src/vm/vars.cpp index 02f7efc696..165d172e74 100644 --- a/src/vm/vars.cpp +++ b/src/vm/vars.cpp @@ -80,9 +80,6 @@ GPTR_IMPL(MethodTable, g_pMulticastDelegateClass); GPTR_IMPL(MethodTable, g_pValueTypeClass); GPTR_IMPL(MethodTable, g_pEnumClass); GPTR_IMPL(MethodTable, g_pThreadClass); -#ifdef FEATURE_CER -GPTR_IMPL(MethodTable, g_pCriticalFinalizerObjectClass); -#endif GPTR_IMPL(MethodTable, g_pFreeObjectMethodTable); GPTR_IMPL(MethodTable, g_pOverlappedDataClass); @@ -100,9 +97,6 @@ GPTR_IMPL(MethodTable, g_pICastableInterface); #endif // FEATURE_ICASTABLE -#ifdef FEATURE_CER -GPTR_IMPL(MethodDesc, g_pPrepareConstrainedRegionsMethod); -#endif GPTR_IMPL(MethodDesc, g_pExecuteBackoutCodeHelperMethod); GPTR_IMPL(MethodDesc, g_pObjectCtorMD); diff --git a/src/vm/vars.hpp b/src/vm/vars.hpp index 5aa6e2b228..1848ed594e 100644 --- a/src/vm/vars.hpp +++ b/src/vm/vars.hpp @@ -408,9 +408,6 @@ GPTR_DECL(MethodTable, g_pFreeObjectMethodTable); GPTR_DECL(MethodTable, g_pValueTypeClass); GPTR_DECL(MethodTable, g_pEnumClass); GPTR_DECL(MethodTable, g_pThreadClass); -#ifdef FEATURE_CER -GPTR_DECL(MethodTable, g_pCriticalFinalizerObjectClass); -#endif GPTR_DECL(MethodTable, g_pOverlappedDataClass); GPTR_DECL(MethodTable, g_TypedReferenceMT); @@ -426,9 +423,6 @@ GPTR_DECL(MethodTable, g_pBaseRuntimeClass); GPTR_DECL(MethodTable, g_pICastableInterface); #endif // FEATURE_ICASTABLE -#ifdef FEATURE_CER -GPTR_DECL(MethodDesc, g_pPrepareConstrainedRegionsMethod); -#endif GPTR_DECL(MethodDesc, g_pExecuteBackoutCodeHelperMethod); GPTR_DECL(MethodDesc, g_pObjectCtorMD); |