diff --git a/src/coreclr/vm/class.cpp b/src/coreclr/vm/class.cpp index b179bffe9be098..171dda95869cb4 100644 --- a/src/coreclr/vm/class.cpp +++ b/src/coreclr/vm/class.cpp @@ -585,11 +585,13 @@ HRESULT EEClass::AddMethod(MethodTable * pMT, mdMethodDef methodDef, RVA newRVA, LoaderAllocator* pAllocator = pMT->GetLoaderAllocator(); + DWORD classification = mcIL; + // Create a new MethodDescChunk to hold the new MethodDesc // Create the chunk somewhere we'll know is within range of the VTable MethodDescChunk *pChunk = MethodDescChunk::CreateChunk(pAllocator->GetHighFrequencyHeap(), 1, // methodDescCount - mcInstantiated, + classification, TRUE /* fNonVtableSlot */, TRUE /* fNativeCodeSlot */, pMT, @@ -605,20 +607,38 @@ HRESULT EEClass::AddMethod(MethodTable * pMT, mdMethodDef methodDef, RVA newRVA, // Use a local StackingAllocator instead. StackingAllocator stackingAllocator; + MethodTableBuilder::bmtInternalInfo bmtInternal; + bmtInternal.pModule = pMT->GetModule(); + bmtInternal.pInternalImport = NULL; + bmtInternal.pParentMT = NULL; + MethodTableBuilder builder(pMT, pClass, &stackingAllocator, &dummyAmTracker); + + builder.SetBMTData(pMT->GetLoaderAllocator(), + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &bmtInternal); + EX_TRY { INDEBUG(LPCSTR debug_szFieldName); INDEBUG(if (FAILED(pImport->GetNameOfMethodDef(methodDef, &debug_szFieldName))) { debug_szFieldName = "Invalid MethodDef record"; }); builder.InitMethodDesc(pNewMD, - mcInstantiated, // Use instantiated methoddesc for EnC added methods to get space for slot + classification, methodDef, dwImplFlags, dwMemberAttrs, - TRUE, // fEnC + TRUE, // fEnC newRVA, pImport, NULL @@ -628,6 +648,10 @@ HRESULT EEClass::AddMethod(MethodTable * pMT, mdMethodDef methodDef, RVA newRVA, ); pNewMD->SetTemporaryEntryPoint(pAllocator, &dummyAmTracker); + + // [TODO] if an exception is thrown, asserts will fire in EX_CATCH_HRESULT() + // during an EnC operation due to the debugger thread not being able to + // transition to COOP mode. } EX_CATCH_HRESULT(hr); if (S_OK != hr) diff --git a/src/coreclr/vm/clsload.cpp b/src/coreclr/vm/clsload.cpp index 3dd797e4c6ea8e..d7eb67b1bfe44b 100644 --- a/src/coreclr/vm/clsload.cpp +++ b/src/coreclr/vm/clsload.cpp @@ -2010,10 +2010,10 @@ VOID ClassLoader::Init(AllocMemTracker *pamTracker) // type in one of the modules governed by the loader. // The process of creating these types may be reentrant. The ordering has // not yet been sorted out, and when we sort it out we should also modify the - // ordering for m_AvailableTypesLock in BaseDomain. + // ordering for m_AvailableTypesLock below. m_AvailableClassLock.Init( CrstAvailableClass, - CRST_REENTRANCY); + CrstFlags(CRST_REENTRANCY | CRST_DEBUGGER_THREAD)); // This lock is taken within the classloader whenever we have to insert a new param. type into the table. m_AvailableTypesLock.Init( diff --git a/src/coreclr/vm/codeversion.cpp b/src/coreclr/vm/codeversion.cpp index 9bc971033915e0..6a5db21db37f69 100644 --- a/src/coreclr/vm/codeversion.cpp +++ b/src/coreclr/vm/codeversion.cpp @@ -2102,7 +2102,7 @@ bool CodeVersionManager::IsMethodSupported(PTR_MethodDesc pMethodDesc) !pMethodDesc->GetLoaderAllocator()->IsCollectible() && // EnC has its own way of versioning - !pMethodDesc->IsEnCMethod(); + !pMethodDesc->InEnCEnabledModule(); } //--------------------------------------------------------------------------------------- diff --git a/src/coreclr/vm/eetwain.cpp b/src/coreclr/vm/eetwain.cpp index 622db1321b10b4..640591c7d9b71f 100644 --- a/src/coreclr/vm/eetwain.cpp +++ b/src/coreclr/vm/eetwain.cpp @@ -1080,7 +1080,7 @@ HRESULT EECodeManager::FixContextForEnC(PCONTEXT pCtx, } } - oldMethodVarsSortedBase = new (nothrow) ICorDebugInfo::NativeVarInfo[oldNumVars]; + oldMethodVarsSortedBase = new (nothrow) ICorDebugInfo::NativeVarInfo[oldNumVars]; if (!oldMethodVarsSortedBase) { hr = E_FAIL; @@ -1108,7 +1108,8 @@ HRESULT EECodeManager::FixContextForEnC(PCONTEXT pCtx, if (pOldVar->startOffset <= oldMethodOffset && pOldVar->endOffset > oldMethodOffset) { - oldMethodVarsSorted[(int)varNumber] = *pOldVar; + // Indexing should be performed with a signed value - could be negative. + oldMethodVarsSorted[(int32_t)varNumber] = *pOldVar; } } @@ -1160,7 +1161,8 @@ HRESULT EECodeManager::FixContextForEnC(PCONTEXT pCtx, if (pNewVar->startOffset <= newMethodOffset && pNewVar->endOffset > newMethodOffset) { - newMethodVarsSorted[(int)varNumber] = *pNewVar; + // Indexing should be performed with a signed valued - could be negative. + newMethodVarsSorted[(int32_t)varNumber] = *pNewVar; } } @@ -1190,8 +1192,9 @@ HRESULT EECodeManager::FixContextForEnC(PCONTEXT pCtx, memset(rgVal1, 0, sizeof(SIZE_T) * newNumVars); memset(rgVal2, 0, sizeof(SIZE_T) * newNumVars); - unsigned varsToGet = (oldNumVars > newNumVars) ? newNumVars - : oldNumVars; + unsigned varsToGet = (oldNumVars > newNumVars) + ? newNumVars + : oldNumVars; // 2) Get all the info about current variables, registers, etc. diff --git a/src/coreclr/vm/encee.cpp b/src/coreclr/vm/encee.cpp index b959e233a14a2a..37625bbce4bbf4 100644 --- a/src/coreclr/vm/encee.cpp +++ b/src/coreclr/vm/encee.cpp @@ -115,7 +115,7 @@ HRESULT EditAndContinueModule::ApplyEditAndContinue( // Update the module's EnC version number ++m_applyChangesCount; - LOG((LF_ENC, LL_INFO100, "EACM::AEAC:\n")); + LOG((LF_ENC, LL_INFO100, "EACM::AEAC: Apply count %d\n", m_applyChangesCount)); #ifdef _DEBUG // Debugging hook to optionally break when this method is called @@ -130,10 +130,10 @@ HRESULT EditAndContinueModule::ApplyEditAndContinue( static BOOL dumpChanges = -1; if (dumpChanges == -1) - dumpChanges = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_EncDumpApplyChanges); - if (dumpChanges> 0) { + if (dumpChanges> 0) + { SString fn; int ec; fn.Printf("ApplyChanges.%d.dmeta", m_applyChangesCount); @@ -323,7 +323,7 @@ HRESULT EditAndContinueModule::UpdateMethod(MethodDesc *pMethod) // // Note that this only works since we've very carefully made sure that _all_ references // to the Method's code must be to the call/jmp blob immediately in front of the - // MethodDesc itself. See MethodDesc::IsEnCMethod() + // MethodDesc itself. See MethodDesc::InEnCEnabledModule() // pMethod->ResetCodeEntryPointForEnC(); diff --git a/src/coreclr/vm/genmeth.cpp b/src/coreclr/vm/genmeth.cpp index 44f99a84c24fe7..e7687194c6507c 100644 --- a/src/coreclr/vm/genmeth.cpp +++ b/src/coreclr/vm/genmeth.cpp @@ -118,11 +118,17 @@ static MethodDesc* CreateMethodDesc(LoaderAllocator *pAllocator, pMD->SetIsIntrinsic(); } +#ifdef EnC_SUPPORTED + if (pTemplateMD->IsEnCAddedMethod()) + { + pMD->SetIsEnCAddedMethod(); + } +#endif // EnC_SUPPORTED + pMD->SetMemberDef(token); pMD->SetSlot(pTemplateMD->GetSlot()); #ifdef _DEBUG - pMD->m_pszDebugMethodName = pTemplateMD->m_pszDebugMethodName; // more info here pMD->m_pszDebugMethodSignature = ""; pMD->m_pszDebugClassName = ""; @@ -1351,19 +1357,21 @@ MethodDesc * MethodDesc::FindOrCreateTypicalSharedInstantiation(BOOL allowCreate } //@GENERICSVER: Set the typical (ie. formal) instantiation -void InstantiatedMethodDesc::SetupGenericMethodDefinition(IMDInternalImport *pIMDII, +void InstantiatedMethodDesc::SetupGenericMethodDefinition(IMDInternalImport* pIMDII, LoaderAllocator* pAllocator, - AllocMemTracker *pamTracker, - Module *pModule, + AllocMemTracker* pamTracker, + Module* pModule, mdMethodDef tok) { CONTRACTL { THROWS; - GC_TRIGGERS; + GC_NOTRIGGER; INJECT_FAULT(COMPlusThrowOM();); - PRECONDITION(CheckPointer(pModule)); PRECONDITION(CheckPointer(pIMDII)); + PRECONDITION(CheckPointer(pAllocator)); + PRECONDITION(CheckPointer(pamTracker)); + PRECONDITION(CheckPointer(pModule)); } CONTRACTL_END; diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 1c916bbbe8306c..6e31fcda23f316 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -5994,7 +5994,7 @@ bool CEEInfo::getStringChar(CORINFO_OBJECT_HANDLE obj, int index, uint16_t* valu result = true; } } - + EE_TO_JIT_TRANSITION(); return result; @@ -8957,7 +8957,7 @@ void CEEInfo::getFunctionEntryPoint(CORINFO_METHOD_HANDLE ftnHnd, if (ret == NULL) { // should never get here for EnC methods or if interception via remoting stub is required - _ASSERTE(!ftn->IsEnCMethod()); + _ASSERTE(!ftn->InEnCEnabledModule()); ret = (void *)ftn->GetAddrOfSlot(); @@ -11708,7 +11708,7 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t UINT size = field->GetSize(); _ASSERTE(baseAddr > 0); _ASSERTE(size > 0); - + if (size >= (UINT)bufferSize && valueOffset >= 0 && (UINT)valueOffset <= size - (UINT)bufferSize) { memcpy(buffer, (uint8_t*)baseAddr + valueOffset, bufferSize); diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index b4ac30905de798..95631f95b69871 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -2014,9 +2014,8 @@ PCODE MethodDesc::TryGetMultiCallableAddrOfCode(CORINFO_ACCESS_FLAGS accessFlags if (IsWrapperStub() || IsEnCAddedMethod()) return GetStableEntryPoint(); - // For EnC always just return the stable entrypoint so we can update the code - if (IsEnCMethod()) + if (InEnCEnabledModule()) return GetStableEntryPoint(); // If the method has already been jitted, we can give out the direct address @@ -2203,7 +2202,7 @@ void MethodDesc::Reset() // different pieces of data non-atomically. // Use this only if you can guarantee thread-safety somehow. - _ASSERTE(IsEnCMethod() || // The process is frozen by the debugger + _ASSERTE(InEnCEnabledModule() || // The process is frozen by the debugger IsDynamicMethod() || // These are used in a very restricted way GetLoaderModule()->IsReflection()); // Rental methods @@ -2298,7 +2297,7 @@ BOOL MethodDesc::RequiresStableEntryPoint(BOOL fEstimateForChunk /*=FALSE*/) return TRUE; // Create precodes for edit and continue to make methods updateable - if (IsEnCMethod() || IsEnCAddedMethod()) + if (InEnCEnabledModule() || IsEnCAddedMethod()) return TRUE; // Precreate precodes for LCG methods so we do not leak memory when the method descs are recycled @@ -2392,8 +2391,6 @@ void MethodDesc::CheckRestore(ClassLoadLevel level) // it might be out-of-module ClassLoader::EnsureLoaded(TypeHandle(GetMethodTable()), level); - pIMD->m_wFlags2 = pIMD->m_wFlags2 & ~InstantiatedMethodDesc::Unrestored; - if (ETW_PROVIDER_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER)) { ETW::MethodLog::MethodRestored(this); diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index 6df3d0042e3343..ba15382e742801 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -138,7 +138,8 @@ enum MethodDescClassification // Has slot for native code mdcHasNativeCodeSlot = 0x0020, - // unused = 0x0040, + // Method was added via Edit And Continue + mdcEnCAddedMethod = 0x0040, // Method is static mdcStatic = 0x0080, @@ -668,7 +669,7 @@ class MethodDesc // If the method is in an Edit and Continue (EnC) module, then // we DON'T want to backpatch this, ever. We MUST always call // through the precode so that we can update the method. - inline DWORD IsEnCMethod() + inline DWORD InEnCEnabledModule() { WRAPPER_NO_CONTRACT; Module *pModule = GetModule(); @@ -977,11 +978,6 @@ class MethodDesc m_wFlags |= mdcDuplicate; } - //================================================================== - // EnC - - inline BOOL IsEnCAddedMethod(); - //================================================================== // @@ -1384,7 +1380,7 @@ class MethodDesc return false; #endif - return !IsVersionable() && !IsEnCMethod(); + return !IsVersionable() && !InEnCEnabledModule(); } //Is this method currently pointing to native code that will never change? @@ -1736,6 +1732,26 @@ class MethodDesc m_wFlags |= mdcHasNativeCodeSlot; } +#ifdef EnC_SUPPORTED + inline BOOL IsEnCAddedMethod() + { + LIMITED_METHOD_DAC_CONTRACT; + return (m_wFlags & mdcEnCAddedMethod) != 0; + } + + inline void SetIsEnCAddedMethod() + { + LIMITED_METHOD_CONTRACT; + m_wFlags |= mdcEnCAddedMethod; + } +#else + inline BOOL IsEnCAddedMethod() + { + LIMITED_METHOD_DAC_CONTRACT; + return FALSE; + } +#endif // !EnC_SUPPORTED + inline BOOL IsIntrinsic() { LIMITED_METHOD_DAC_CONTRACT; @@ -2801,7 +2817,7 @@ class NDirectMethodDesc : public MethodDesc kEarlyBound = 0x0001, // IJW managed->unmanaged thunk. Standard [sysimport] stuff otherwise. - kHasSuppressUnmanagedCodeAccess = 0x0002, + // unused = 0x0002, kDefaultDllImportSearchPathsIsCached = 0x0004, // set if we cache attribute value. @@ -3095,9 +3111,7 @@ class EEImplMethodDesc : public StoredSigMethodDesc #ifdef FEATURE_COMINTEROP // This is the extra information needed to be associated with a method in order to use it for -// CLR->COM calls. It is currently used by code:ComPlusCallMethodDesc (ordinary CLR->COM calls), -// code:InstantiatedMethodDesc (optional field, CLR->COM calls on shared generic interfaces), -// and code:DelegateEEClass (delegate->COM calls for WinRT). +// CLR->COM calls. It is currently used by code:ComPlusCallMethodDesc (ordinary CLR->COM calls). typedef DPTR(struct ComPlusCallInfo) PTR_ComPlusCallInfo; struct ComPlusCallInfo { @@ -3105,12 +3119,6 @@ struct ComPlusCallInfo // EEImplMethodDesc that has already been initialized for COM interop. inline static ComPlusCallInfo *FromMethodDesc(MethodDesc *pMD); - enum Flags - { - kHasSuppressUnmanagedCodeAccess = 0x1, - kRequiresArgumentWrapping = 0x2, - }; - union { // IL stub for CLR to COM call @@ -3123,7 +3131,10 @@ struct ComPlusCallInfo // method table of the interface which this represents PTR_MethodTable m_pInterfaceMT; - // We need only 3 bits here, see enum Flags below. + enum Flags + { + kRequiresArgumentWrapping = 0x1, + }; BYTE m_flags; // ComSlot() (is cached when we first invoke the method and generate @@ -3298,7 +3309,7 @@ class ComPlusCallMethodDesc : public MethodDesc // parameters (see MethodDesc::IsSharedByGenericInstantiations()). //----------------------------------------------------------------------- -class InstantiatedMethodDesc : public MethodDesc +class InstantiatedMethodDesc final : public MethodDesc { public: @@ -3354,17 +3365,6 @@ class InstantiatedMethodDesc : public MethodDesc return((m_wFlags2 & KindMask) == WrapperStubWithInstantiations); } - BOOL IMD_IsEnCAddedMethod() - { - LIMITED_METHOD_CONTRACT; - -#ifdef EnC_SUPPORTED - return((m_wFlags2 & KindMask) == EnCAddedMethod); -#else - return FALSE; -#endif - } - PTR_DictionaryLayout GetDictLayoutRaw() { LIMITED_METHOD_DAC_CONTRACT; @@ -3423,15 +3423,6 @@ class InstantiatedMethodDesc : public MethodDesc // Setup the IMD as a wrapper around another method desc void SetupWrapperStubWithInstantiations(MethodDesc* wrappedMD,DWORD numGenericArgs, TypeHandle *pGenericMethodInst); - -#ifdef EnC_SUPPORTED - void SetupEnCAddedMethod() - { - LIMITED_METHOD_CONTRACT; - m_wFlags2 = EnCAddedMethod; - } -#endif - private: enum { @@ -3440,17 +3431,6 @@ class InstantiatedMethodDesc : public MethodDesc UnsharedMethodInstantiation = 0x01, SharedMethodInstantiation = 0x02, WrapperStubWithInstantiations = 0x03, - -#ifdef EnC_SUPPORTED - // Non-virtual method added through EditAndContinue. - EnCAddedMethod = 0x07, -#endif // EnC_SUPPORTED - - Unrestored = 0x08, - -#ifdef FEATURE_COMINTEROP - HasComPlusCallInfo = 0x10, // this IMD contains an optional ComPlusCallInfo -#endif // FEATURE_COMINTEROP }; friend class MethodDesc; // this fields are currently accessed by MethodDesc::Save/Restore etc. @@ -3610,13 +3590,6 @@ inline BOOL MethodDesc::SanityCheck() #endif // _DEBUG -inline BOOL MethodDesc::IsEnCAddedMethod() -{ - LIMITED_METHOD_DAC_CONTRACT; - - return (GetClassification() == mcInstantiated) && AsInstantiatedMethodDesc()->IMD_IsEnCAddedMethod(); -} - inline BOOL MethodDesc::HasNonVtableSlot() { LIMITED_METHOD_DAC_CONTRACT; diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index ee58975424767c..632f38d7a39013 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -2009,7 +2009,7 @@ MethodTableBuilder::BuildMethodTableThrowing( } #endif //_DEBUG - STRESS_LOG3(LF_CLASSLOADER, LL_INFO1000, "MethodTableBuilder: finished method table for module %p token %x = %pT \n", + STRESS_LOG3(LF_CLASSLOADER, LL_INFO1000, "MTB:BMTT finished method table for module %p token %x = %p\n", pModule, GetCl(), GetHalfBakedMethodTable()); @@ -5116,7 +5116,7 @@ MethodTableBuilder::InitNewMethodDesc( pMethod->GetMethodSignature().GetToken(), pMethod->GetImplAttrs(), pMethod->GetDeclAttrs(), - FALSE, + FALSE, // fEnC pMethod->GetRVA(), GetMDImport(), pName @@ -6002,8 +6002,8 @@ MethodTableBuilder::InitMethodDesc( } CONTRACTL_END; - LOG((LF_CORDB, LL_EVERYTHING, "EEC::IMD: pNewMD:0x%x for tok:0x%x (%s::%s)\n", - pNewMD, tok, pszDebugClassName, pszDebugMethodName)); + LOG((LF_CORDB, LL_EVERYTHING, "MTB::IMD: pNewMD:%p (%u) EnC: %s tok:%x (%s::%s)\n", + pNewMD, Classification, (fEnC ? "true" : "false"), tok, pszDebugClassName, pszDebugMethodName)); // Now we know the classification we can perform any classification specific initialization. @@ -6097,21 +6097,17 @@ MethodTableBuilder::InitMethodDesc( break; case mcInstantiated: -#ifdef EnC_SUPPORTED - if (fEnC) - { - // We reuse the instantiated methoddescs to get the slot - InstantiatedMethodDesc* pNewIMD = (InstantiatedMethodDesc*) pNewMD; - pNewIMD->SetupEnCAddedMethod(); - } - else -#endif // EnC_SUPPORTED { // Initialize the typical instantiation. - InstantiatedMethodDesc* pNewIMD = (InstantiatedMethodDesc*) pNewMD; + InstantiatedMethodDesc* pNewIMD = pNewMD->AsInstantiatedMethodDesc(); + //data has the same lifetime as method table, use our allocator - pNewIMD->SetupGenericMethodDefinition(pIMDII, GetLoaderAllocator(), GetMemTracker(), GetModule(), - tok); + pNewIMD->SetupGenericMethodDefinition( + pIMDII, + GetLoaderAllocator(), + GetMemTracker(), + GetModule(), + tok); } break; @@ -6127,6 +6123,11 @@ MethodTableBuilder::InitMethodDesc( if (IsMdStatic(dwMemberAttrs)) pNewMD->SetStatic(); +#ifdef EnC_SUPPORTED + if (fEnC) + pNewMD->SetIsEnCAddedMethod(); +#endif // EnC_SUPPORTED + #ifdef _DEBUG // Mark as many methods as synchronized as possible. // diff --git a/src/coreclr/vm/methodtablebuilder.h b/src/coreclr/vm/methodtablebuilder.h index 175fab114b53a7..739a8e530f1320 100644 --- a/src/coreclr/vm/methodtablebuilder.h +++ b/src/coreclr/vm/methodtablebuilder.h @@ -73,22 +73,7 @@ class MethodTableBuilder m_pAllocMemTracker(pAllocMemTracker) { LIMITED_METHOD_CONTRACT; - SetBMTData( - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL); + SetBMTData(); } public: //========================================================================== @@ -2226,21 +2211,21 @@ class MethodTableBuilder bmtEnumFieldInfo *bmtEnumFields; void SetBMTData( - LoaderAllocator *bmtAllocator, - bmtErrorInfo *bmtError, - bmtProperties *bmtProp, - bmtVtable *bmtVT, - bmtParentInfo *bmtParent, - bmtInterfaceInfo *bmtInterface, - bmtMetaDataInfo *bmtMetaData, - bmtMethodInfo *bmtMethod, - bmtMethAndFieldDescs *bmtMFDescs, - bmtFieldPlacement *bmtFP, - bmtInternalInfo *bmtInternal, - bmtGCSeriesInfo *bmtGCSeries, - bmtMethodImplInfo *bmtMethodImpl, - const bmtGenericsInfo *bmtGenerics, - bmtEnumFieldInfo *bmtEnumFields); + LoaderAllocator *bmtAllocator = NULL, + bmtErrorInfo *bmtError = NULL, + bmtProperties *bmtProp = NULL, + bmtVtable *bmtVT = NULL, + bmtParentInfo *bmtParent = NULL, + bmtInterfaceInfo *bmtInterface = NULL, + bmtMetaDataInfo *bmtMetaData = NULL, + bmtMethodInfo *bmtMethod = NULL, + bmtMethAndFieldDescs *bmtMFDescs = NULL, + bmtFieldPlacement *bmtFP = NULL, + bmtInternalInfo *bmtInternal = NULL, + bmtGCSeriesInfo *bmtGCSeries = NULL, + bmtMethodImplInfo *bmtMethodImpl = NULL, + const bmtGenericsInfo *bmtGenerics = NULL, + bmtEnumFieldInfo *bmtEnumFields = NULL); // -------------------------------------------------------------------------------------------- // Returns the parent bmtRTType pointer. Can be null if no parent exists.