summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
authorSwaroop Sridhar <swaroops@microsoft.com>2016-07-15 00:41:30 -0700
committerSwaroop Sridhar <swaroops@microsoft.com>2016-07-20 19:51:50 -0700
commitf915aebaf5db0b829f062dc9940e23bb5c38d575 (patch)
treef1eafbb504ba2a0fa0253ffcce362ed81a0add80 /src/vm
parent34e1626bc3a49b50900ca192bed1f97524d81e6a (diff)
downloadcoreclr-f915aebaf5db0b829f062dc9940e23bb5c38d575.tar.gz
coreclr-f915aebaf5db0b829f062dc9940e23bb5c38d575.tar.bz2
coreclr-f915aebaf5db0b829f062dc9940e23bb5c38d575.zip
GCInfo: Support versioning.
This change enables the VM to support multiple versions GCInfo concurrently. This is necessary in light of upcoming work to add ReturnType and other modifications to the GCInfo format -- so that existing ReadyToRun images will continue to run correctly. The version# is not stored in the GcInfo structure -- because it is wasteful to store the version once for every method. Instead, it is tracked per range-section of generated/loaded methods. The GCInfo version is computed as: 1) The current GCINFO_VERSION for JITted and Ngened images 2) A function of the Ready-to-run major version stored in READYTORUN_HEADER for ready-to-run images. ReadyToRunJitManager::JitTokenToGCInfoVersion() provides the GcInfo version for any Method. Currently, there's only one version of GCInfo. An abstraction GCInfoToken is added to the GcInfo interface, which tracks the {GcInfo, Version} pair in-memory. Several GcInfo APIs are modified to use GCInfoToken in place of GcInfo pointers. Notes: 1) SOS GcDump: The GCDump API has separate dump routines for Header and the pointer-liveness information (DumpGCTable and DumpGCHeader) each of which advance a pointer to the GCInfo block. These APIs are not changed to recieve a GCInfoToken in place of the GcInfo block pointer. Instead, they recieve the GcInfo version at the time of construction. 2) Some routines that are specific to x86 gcInfo (ex: crackMethodInfoHdr) are not yet updated to use versioning, since the development plan is to update the Non-x86 GcInfo structure first. 3) The x86 specific structs defining GcInfo headers are moved to GcInfoTypes.h, along with the non-x86 GcInfo type definitions.
Diffstat (limited to 'src/vm')
-rw-r--r--src/vm/codeman.cpp50
-rw-r--r--src/vm/codeman.h34
-rw-r--r--src/vm/debughelp.cpp10
-rw-r--r--src/vm/eedbginterfaceimpl.cpp6
-rw-r--r--src/vm/eetwain.cpp63
-rw-r--r--src/vm/gccover.cpp20
-rw-r--r--src/vm/gccover.h2
-rw-r--r--src/vm/gcenv.ee.cpp10
-rw-r--r--src/vm/gcinfodecoder.cpp16
-rw-r--r--src/vm/stackwalk.h7
10 files changed, 127 insertions, 91 deletions
diff --git a/src/vm/codeman.cpp b/src/vm/codeman.cpp
index 7eea254646..b66215f5f2 100644
--- a/src/vm/codeman.cpp
+++ b/src/vm/codeman.cpp
@@ -3015,7 +3015,7 @@ void * EEJitManager::allocCodeFragmentBlock(size_t blockSize, unsigned alignment
#endif // !DACCESS_COMPILE
-PTR_VOID EEJitManager::GetGCInfo(const METHODTOKEN& MethodToken)
+GCInfoToken EEJitManager::GetGCInfoToken(const METHODTOKEN& MethodToken)
{
CONTRACTL {
NOTHROW;
@@ -3024,7 +3024,8 @@ PTR_VOID EEJitManager::GetGCInfo(const METHODTOKEN& MethodToken)
SUPPORTS_DAC;
} CONTRACTL_END;
- return GetCodeHeader(MethodToken)->GetGCInfo();
+ // The JIT-ed code always has the current version of GCInfo
+ return{ GetCodeHeader(MethodToken)->GetGCInfo(), GCINFO_VERSION };
}
// creates an enumeration and returns the number of EH clauses
@@ -5035,7 +5036,7 @@ NativeImageJitManager::NativeImageJitManager()
#endif // #ifndef DACCESS_COMPILE
-PTR_VOID NativeImageJitManager::GetGCInfo(const METHODTOKEN& MethodToken)
+GCInfoToken NativeImageJitManager::GetGCInfoToken(const METHODTOKEN& MethodToken)
{
CONTRACTL {
NOTHROW;
@@ -5060,7 +5061,8 @@ PTR_VOID NativeImageJitManager::GetGCInfo(const METHODTOKEN& MethodToken)
PTR_VOID pUnwindData = GetUnwindDataBlob(baseAddress, pRuntimeFunction, &nUnwindDataSize);
// GCInfo immediatelly follows unwind data
- return dac_cast<PTR_BYTE>(pUnwindData) + nUnwindDataSize;
+ // GCInfo from an NGEN-ed image is always the current version
+ return{ dac_cast<PTR_BYTE>(pUnwindData) + nUnwindDataSize, GCINFO_VERSION };
}
unsigned NativeImageJitManager::InitializeEHEnumeration(const METHODTOKEN& MethodToken, EH_CLAUSE_ENUMERATOR* pEnumState)
@@ -5681,7 +5683,7 @@ void NativeImageJitManager::JitTokenToMethodRegionInfo(const METHODTOKEN& Method
//
methodRegionInfo->hotStartAddress = JitTokenToStartAddress(MethodToken);
- methodRegionInfo->hotSize = GetCodeManager()->GetFunctionSize(GetGCInfo(MethodToken));
+ methodRegionInfo->hotSize = GetCodeManager()->GetFunctionSize(GetGCInfoToken(MethodToken));
methodRegionInfo->coldStartAddress = 0;
methodRegionInfo->coldSize = 0;
@@ -6274,14 +6276,17 @@ PTR_MethodDesc MethodIterator::GetMethodDesc()
return NativeUnwindInfoLookupTable::GetMethodDesc(m_pNgenLayout, GetRuntimeFunction(), m_ModuleBase);
}
-PTR_VOID MethodIterator::GetGCInfo()
+GCInfoToken MethodIterator::GetGCInfoToken()
{
LIMITED_METHOD_CONTRACT;
// get the gc info from the RT function
SIZE_T size;
PTR_VOID pUnwindData = GetUnwindDataBlob(m_ModuleBase, GetRuntimeFunction(), &size);
- return (PTR_VOID)((PTR_BYTE)pUnwindData + size);
+ PTR_VOID gcInfo = (PTR_VOID)((PTR_BYTE)pUnwindData + size);
+ // MethodIterator is used to iterate over methods of an NgenImage.
+ // So, GcInfo version is always current
+ return{ gcInfo, GCINFO_VERSION };
}
TADDR MethodIterator::GetMethodStartAddress()
@@ -6359,8 +6364,8 @@ void MethodIterator::GetMethodRegionInfo(IJitManager::MethodRegionInfo *methodRe
methodRegionInfo->hotStartAddress = GetMethodStartAddress();
methodRegionInfo->coldStartAddress = GetMethodColdStartAddress();
-
- methodRegionInfo->hotSize = ExecutionManager::GetNativeImageJitManager()->GetCodeManager()->GetFunctionSize(GetGCInfo());
+ GCInfoToken gcInfoToken = GetGCInfoToken();
+ methodRegionInfo->hotSize = ExecutionManager::GetNativeImageJitManager()->GetCodeManager()->GetFunctionSize(gcInfoToken);
methodRegionInfo->coldSize = 0;
if (methodRegionInfo->coldStartAddress != NULL)
@@ -6408,6 +6413,24 @@ ReadyToRunInfo * ReadyToRunJitManager::JitTokenToReadyToRunInfo(const METHODTOKE
return dac_cast<PTR_Module>(MethodToken.m_pRangeSection->pHeapListOrZapModule)->GetReadyToRunInfo();
}
+UINT32 ReadyToRunJitManager::JitTokenToGCInfoVersion(const METHODTOKEN& MethodToken)
+{
+ CONTRACTL{
+ NOTHROW;
+ GC_NOTRIGGER;
+ HOST_NOCALLS;
+ SUPPORTS_DAC;
+ } CONTRACTL_END;
+
+ READYTORUN_HEADER * header = JitTokenToReadyToRunInfo(MethodToken)->GetImage()->GetReadyToRunHeader();
+ UINT32 gcInfoVersion = header->MajorVersion;
+
+ // Currently there's only one version of GCInfo.
+ _ASSERTE(gcInfoVersion == GCINFO_VERSION);
+
+ return gcInfoVersion;
+}
+
PTR_RUNTIME_FUNCTION ReadyToRunJitManager::JitTokenToRuntimeFunction(const METHODTOKEN& MethodToken)
{
CONTRACTL {
@@ -6433,7 +6456,7 @@ TADDR ReadyToRunJitManager::JitTokenToStartAddress(const METHODTOKEN& MethodToke
RUNTIME_FUNCTION__BeginAddress(dac_cast<PTR_RUNTIME_FUNCTION>(MethodToken.m_pCodeHeader));
}
-PTR_VOID ReadyToRunJitManager::GetGCInfo(const METHODTOKEN& MethodToken)
+GCInfoToken ReadyToRunJitManager::GetGCInfoToken(const METHODTOKEN& MethodToken)
{
CONTRACTL {
NOTHROW;
@@ -6458,7 +6481,10 @@ PTR_VOID ReadyToRunJitManager::GetGCInfo(const METHODTOKEN& MethodToken)
PTR_VOID pUnwindData = GetUnwindDataBlob(baseAddress, pRuntimeFunction, &nUnwindDataSize);
// GCInfo immediatelly follows unwind data
- return dac_cast<PTR_BYTE>(pUnwindData) + nUnwindDataSize;
+ PTR_BYTE gcInfo = dac_cast<PTR_BYTE>(pUnwindData) + nUnwindDataSize;
+ UINT32 gcInfoVersion = JitTokenToGCInfoVersion(MethodToken);
+
+ return{ gcInfo, gcInfoVersion };
}
unsigned ReadyToRunJitManager::InitializeEHEnumeration(const METHODTOKEN& MethodToken, EH_CLAUSE_ENUMERATOR* pEnumState)
@@ -6863,7 +6889,7 @@ void ReadyToRunJitManager::JitTokenToMethodRegionInfo(const METHODTOKEN& MethodT
// READYTORUN: FUTURE: Hot-cold spliting
methodRegionInfo->hotStartAddress = JitTokenToStartAddress(MethodToken);
- methodRegionInfo->hotSize = GetCodeManager()->GetFunctionSize(GetGCInfo(MethodToken));
+ methodRegionInfo->hotSize = GetCodeManager()->GetFunctionSize(GetGCInfoToken(MethodToken));
methodRegionInfo->coldStartAddress = 0;
methodRegionInfo->coldSize = 0;
}
diff --git a/src/vm/codeman.h b/src/vm/codeman.h
index 855c15125a..ae86a25e93 100644
--- a/src/vm/codeman.h
+++ b/src/vm/codeman.h
@@ -24,9 +24,10 @@ Abstract:
An IJitManager knows about which method bodies live in each RangeSection.
It can handle methods of one given CodeType. It can map a method body to
a MethodDesc. It knows where the GCInfo about the method lives.
- Today, we have 2 IJitManagers viz.
+ Today, we have three IJitManagers viz.
1. EEJitManager for JITcompiled code generated by clrjit.dll
2. NativeImageJitManager for ngenned code.
+ 3. ReadyToRunJitManager for version resiliant ReadyToRun code
An ICodeManager knows how to crack a specific format of GCInfo. There is
a default format (handled by ExecutionManager::GetDefaultCodeManager())
@@ -66,6 +67,7 @@ Abstract:
#include "debuginfostore.h"
#include "shash.h"
#include "pedecoder.h"
+#include "gcinfo.h"
class MethodDesc;
class ICorJitCompiler;
@@ -113,6 +115,7 @@ enum StubCodeBlockKind : int
// Method header which exists just before the code.
// Every IJitManager could have its own format for the header.
// Today CodeHeader is used by the EEJitManager.
+// The GCInfo version is always current GCINFO_VERSION in this header.
#ifdef USE_INDIRECT_CODEHEADER
typedef DPTR(struct _hpRealCodeHdr) PTR_RealCodeHeader;
@@ -735,7 +738,11 @@ public:
CrawlFrame *pCf)=0;
#endif // #ifndef DACCESS_COMPILE
- virtual PTR_VOID GetGCInfo(const METHODTOKEN& MethodToken)=0;
+ virtual GCInfoToken GetGCInfoToken(const METHODTOKEN& MethodToken)=0;
+ PTR_VOID GetGCInfo(const METHODTOKEN& MethodToken)
+ {
+ return GetGCInfoToken(MethodToken).Info;
+ }
TADDR JitTokenToModuleBase(const METHODTOKEN& MethodToken);
@@ -965,7 +972,7 @@ public:
virtual TypeHandle ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClause,
CrawlFrame *pCf);
#endif // !DACCESS_COMPILE
- PTR_VOID GetGCInfo(const METHODTOKEN& MethodToken);
+ GCInfoToken GetGCInfoToken(const METHODTOKEN& MethodToken);
#endif // !CROSSGEN_COMPILE
#if !defined DACCESS_COMPILE && !defined CROSSGEN_COMPILE
void RemoveJitData(CodeHeader * pCHdr, size_t GCinfo_len, size_t EHinfo_len);
@@ -1486,7 +1493,7 @@ inline void EEJitManager::JitTokenToMethodRegionInfo(const METHODTOKEN& MethodTo
} CONTRACTL_END;
methodRegionInfo->hotStartAddress = JitTokenToStartAddress(MethodToken);
- methodRegionInfo->hotSize = GetCodeManager()->GetFunctionSize(GetGCInfo(MethodToken));
+ methodRegionInfo->hotSize = GetCodeManager()->GetFunctionSize(GetGCInfoToken(MethodToken));
methodRegionInfo->coldStartAddress = 0;
methodRegionInfo->coldSize = 0;
}
@@ -1543,7 +1550,7 @@ public:
CrawlFrame *pCf);
#endif // #ifndef DACCESS_COMPILE
- virtual PTR_VOID GetGCInfo(const METHODTOKEN& MethodToken);
+ virtual GCInfoToken GetGCInfoToken(const METHODTOKEN& MethodToken);
#if defined(WIN64EXCEPTIONS)
virtual PTR_RUNTIME_FUNCTION LazyGetFunctionEntry(EECodeInfo * pCodeInfo);
@@ -1638,6 +1645,8 @@ public:
virtual PCODE GetCodeAddressForRelOffset(const METHODTOKEN& MethodToken, DWORD relOffset);
static ReadyToRunInfo * JitTokenToReadyToRunInfo(const METHODTOKEN& MethodToken);
+ static UINT32 JitTokenToGCInfoVersion(const METHODTOKEN& MethodToken);
+
static PTR_RUNTIME_FUNCTION JitTokenToRuntimeFunction(const METHODTOKEN& MethodToken);
virtual TADDR JitTokenToStartAddress(const METHODTOKEN& MethodToken);
@@ -1653,7 +1662,7 @@ public:
CrawlFrame *pCf);
#endif // #ifndef DACCESS_COMPILE
- virtual PTR_VOID GetGCInfo(const METHODTOKEN& MethodToken);
+ virtual GCInfoToken GetGCInfoToken(const METHODTOKEN& MethodToken);
#if defined(WIN64EXCEPTIONS)
virtual PTR_RUNTIME_FUNCTION LazyGetFunctionEntry(EECodeInfo * pCodeInfo);
@@ -1754,10 +1763,15 @@ public:
return m_relOffset;
}
- PTR_VOID GetGCInfo()
+ GCInfoToken GetGCInfoToken()
{
WRAPPER_NO_CONTRACT;
- return GetJitManager()->GetGCInfo(GetMethodToken());
+ return GetJitManager()->GetGCInfoToken(GetMethodToken());
+ }
+
+ PTR_VOID GetGCInfo()
+ {
+ return GetGCInfoToken().Info;
}
void GetMethodRegionInfo(IJitManager::MethodRegionInfo *methodRegionInfo)
@@ -1824,7 +1838,7 @@ class MethodSectionIterator;
//
// MethodIterator class is used to iterate all the methods in an ngen image.
// It will match and report hot (and cold, if any) sections of a method at the same time.
-//
+// GcInfo version is always current
class MethodIterator
{
public:
@@ -1852,7 +1866,7 @@ private:
BOOL Next();
PTR_MethodDesc GetMethodDesc();
- PTR_VOID GetGCInfo();
+ GCInfoToken GetGCInfoToken();
TADDR GetMethodStartAddress();
TADDR GetMethodColdStartAddress();
ULONG GetHotCodeSize();
diff --git a/src/vm/debughelp.cpp b/src/vm/debughelp.cpp
index 7e4455a7ff..df769455aa 100644
--- a/src/vm/debughelp.cpp
+++ b/src/vm/debughelp.cpp
@@ -1198,24 +1198,24 @@ void DumpGCInfo(MethodDesc* method)
_ASSERTE(codeInfo.GetRelOffset() == 0);
ICodeManager* codeMan = codeInfo.GetCodeManager();
- BYTE* table = (BYTE*) codeInfo.GetGCInfo();
+ GCInfoToken table = codeInfo.GetGCInfoToken();
unsigned methodSize = (unsigned)codeMan->GetFunctionSize(table);
- GCDump gcDump;
+ GCDump gcDump(table.Version);
+ PTR_CBYTE gcInfo = PTR_CBYTE(table.Info);
gcDump.gcPrintf = printfToDbgOut;
InfoHdr header;
printfToDbgOut ("Method info block:\n");
-
- table += gcDump.DumpInfoHdr(table, &header, &methodSize, 0);
+ gcInfo += gcDump.DumpInfoHdr(gcInfo, &header, &methodSize, 0);
printfToDbgOut ("\n");
printfToDbgOut ("Pointer table:\n");
- table += gcDump.DumpGCTable(table, header, methodSize, 0);
+ gcInfo += gcDump.DumpGCTable(gcInfo, header, methodSize, 0);
}
void DumpGCInfoMD(size_t method)
diff --git a/src/vm/eedbginterfaceimpl.cpp b/src/vm/eedbginterfaceimpl.cpp
index 53cb288319..93decc9b0d 100644
--- a/src/vm/eedbginterfaceimpl.cpp
+++ b/src/vm/eedbginterfaceimpl.cpp
@@ -665,10 +665,8 @@ size_t EEDbgInterfaceImpl::GetFunctionSize(MethodDesc *pFD)
return 0;
EECodeInfo codeInfo(methodStart);
-
- PTR_VOID methodInfo = codeInfo.GetGCInfo();
-
- return codeInfo.GetCodeManager()->GetFunctionSize(methodInfo);
+ GCInfoToken gcInfoToken = codeInfo.GetGCInfoToken();
+ return codeInfo.GetCodeManager()->GetFunctionSize(gcInfoToken);
}
#endif //!DACCESS_COMPILE
diff --git a/src/vm/eetwain.cpp b/src/vm/eetwain.cpp
index 69eb177542..82b76f69e0 100644
--- a/src/vm/eetwain.cpp
+++ b/src/vm/eetwain.cpp
@@ -11,8 +11,6 @@
#define RETURN_ADDR_OFFS 1 // in DWORDS
-#include "gcinfo.h"
-
#ifdef USE_GC_INFO_DECODER
#include "gcinfodecoder.h"
#endif
@@ -942,14 +940,14 @@ HRESULT EECodeManager::FixContextForEnC(PCONTEXT pCtx,
// GCInfo for old method
GcInfoDecoder oldGcDecoder(
- dac_cast<PTR_CBYTE>(pOldCodeInfo->GetGCInfo()),
+ pOldCodeInfo->GetGCInfoToken(),
GcInfoDecoderFlags(DECODE_SECURITY_OBJECT | DECODE_PSP_SYM | DECODE_EDIT_AND_CONTINUE),
0 // Instruction offset (not needed)
);
// GCInfo for new method
GcInfoDecoder newGcDecoder(
- dac_cast<PTR_CBYTE>(pNewCodeInfo->GetGCInfo()),
+ pNewCodeInfo->GetGCInfoToken(),
GcInfoDecoderFlags(DECODE_SECURITY_OBJECT | DECODE_PSP_SYM | DECODE_EDIT_AND_CONTINUE),
0 // Instruction offset (not needed)
);
@@ -1437,8 +1435,10 @@ bool EECodeManager::IsGcSafe( EECodeInfo *pCodeInfo,
GC_NOTRIGGER;
} CONTRACTL_END;
+ GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken();
+
GcInfoDecoder gcInfoDecoder(
- dac_cast<PTR_CBYTE>(pCodeInfo->GetGCInfo()),
+ gcInfoToken,
DECODE_INTERRUPTIBILITY,
dwRelOffset
);
@@ -1502,13 +1502,11 @@ bool FindEndOfLastInterruptibleRegionCB (
*/
unsigned EECodeManager::FindEndOfLastInterruptibleRegion(unsigned curOffset,
unsigned endOffset,
- PTR_VOID methodInfoPtr)
+ GCInfoToken gcInfoToken)
{
#ifndef DACCESS_COMPILE
- BYTE* gcInfoAddr = (BYTE*) methodInfoPtr;
-
GcInfoDecoder gcInfoDecoder(
- gcInfoAddr,
+ gcInfoToken,
DECODE_FOR_RANGES_CALLBACK,
0);
@@ -4758,7 +4756,7 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pRD,
methodName, curOffs));
#endif
- PTR_BYTE gcInfoAddr = dac_cast<PTR_BYTE>(pCodeInfo->GetGCInfo());
+ GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken();
#if defined(STRESS_HEAP) && defined(PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED)
#ifdef USE_GC_INFO_DECODER
@@ -4770,7 +4768,7 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pRD,
if (flags & ActiveStackFrame)
{
GcInfoDecoder _gcInfoDecoder(
- gcInfoAddr,
+ gcInfoToken,
DECODE_INTERRUPTIBILITY,
curOffs
);
@@ -4778,7 +4776,7 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pRD,
{
// This must be the offset after a call
#ifdef _DEBUG
- GcInfoDecoder _safePointDecoder(gcInfoAddr, (GcInfoDecoderFlags)0, 0);
+ GcInfoDecoder _safePointDecoder(gcInfoToken, (GcInfoDecoderFlags)0, 0);
_ASSERTE(_safePointDecoder.IsSafePoint(curOffs));
#endif
flags &= ~((unsigned)ActiveStackFrame);
@@ -4791,7 +4789,7 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pRD,
if (flags & ActiveStackFrame)
{
GcInfoDecoder _gcInfoDecoder(
- gcInfoAddr,
+ gcInfoToken,
DECODE_INTERRUPTIBILITY,
curOffs
);
@@ -4839,7 +4837,7 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pRD,
// We've been given an override offset for GC Info
#ifdef _DEBUG
GcInfoDecoder _gcInfoDecoder(
- gcInfoAddr,
+ gcInfoToken,
DECODE_CODE_LENGTH,
0
);
@@ -4884,7 +4882,7 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pRD,
GcInfoDecoder gcInfoDecoder(
- gcInfoAddr,
+ gcInfoToken,
GcInfoDecoderFlags (DECODE_GC_LIFETIMES | DECODE_SECURITY_OBJECT | DECODE_VARARG),
curOffs
);
@@ -5027,7 +5025,7 @@ OBJECTREF* EECodeManager::GetAddrOfSecurityObject(CrawlFrame *pCF)
unsigned relOffset = pCF->GetRelOffset();
CodeManState* pState = pCF->GetCodeManState();
- PTR_VOID methodInfoPtr = pJitMan->GetGCInfo(methodToken);
+ GCInfoToken gcInfoToken = pJitMan->GetGCInfoToken(methodToken);
_ASSERTE(sizeof(CodeManStateBuf) <= sizeof(pState->stateBuf));
@@ -5035,7 +5033,7 @@ OBJECTREF* EECodeManager::GetAddrOfSecurityObject(CrawlFrame *pCF)
CodeManStateBuf * stateBuf = (CodeManStateBuf*)pState->stateBuf;
/* Extract the necessary information from the info block header */
- stateBuf->hdrInfoSize = (DWORD)crackMethodInfoHdr(methodInfoPtr, // <TODO>truncation</TODO>
+ stateBuf->hdrInfoSize = (DWORD)crackMethodInfoHdr(gcInfoToken.Info, // <TODO>truncation</TODO>
relOffset,
&stateBuf->hdrInfoBody);
@@ -5051,10 +5049,8 @@ OBJECTREF* EECodeManager::GetAddrOfSecurityObject(CrawlFrame *pCF)
}
#elif defined(USE_GC_INFO_DECODER) && !defined(CROSSGEN_COMPILE)
- BYTE* gcInfoAddr = (BYTE*) methodInfoPtr;
-
GcInfoDecoder gcInfoDecoder(
- gcInfoAddr,
+ gcInfoToken,
DECODE_SECURITY_OBJECT,
0
);
@@ -5270,11 +5266,10 @@ GenericParamContextType EECodeManager::GetParamContextType(PREGDISPLAY pCont
}
// On x86 the generic param context parameter is never this.
#elif defined(USE_GC_INFO_DECODER)
- PTR_VOID methodInfoPtr = pCodeInfo->GetGCInfo();
- PTR_CBYTE gcInfoAddr = PTR_CBYTE(methodInfoPtr);
+ GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken();
GcInfoDecoder gcInfoDecoder(
- gcInfoAddr,
+ gcInfoToken,
GcInfoDecoderFlags (DECODE_GENERICS_INST_CONTEXT),
0
);
@@ -5363,11 +5358,10 @@ PTR_VOID EECodeManager::GetExactGenericsToken(SIZE_T baseStackSlot,
WRAPPER_NO_CONTRACT;
SUPPORTS_DAC;
- PTR_VOID methodInfoPtr = pCodeInfo->GetGCInfo();
- PTR_CBYTE gcInfoAddr = PTR_CBYTE(methodInfoPtr);
+ GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken();
GcInfoDecoder gcInfoDecoder(
- gcInfoAddr,
+ gcInfoToken,
GcInfoDecoderFlags (DECODE_PSP_SYM | DECODE_GENERICS_INST_CONTEXT),
0
);
@@ -5432,7 +5426,7 @@ void * EECodeManager::GetGSCookieAddr(PREGDISPLAY pContext,
_ASSERTE(sizeof(CodeManStateBuf) <= sizeof(pState->stateBuf));
- PTR_VOID methodInfoPtr = pCodeInfo->GetGCInfo();
+ GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken();
unsigned relOffset = pCodeInfo->GetRelOffset();
#if defined(_TARGET_X86_)
@@ -5440,7 +5434,7 @@ void * EECodeManager::GetGSCookieAddr(PREGDISPLAY pContext,
/* Extract the necessary information from the info block header */
hdrInfo * info = &stateBuf->hdrInfoBody;
- stateBuf->hdrInfoSize = (DWORD)crackMethodInfoHdr(methodInfoPtr, // <TODO>truncation</TODO>
+ stateBuf->hdrInfoSize = (DWORD)crackMethodInfoHdr(gcInfoToken.Info, // <TODO>truncation</TODO>
relOffset,
info);
@@ -5459,22 +5453,20 @@ void * EECodeManager::GetGSCookieAddr(PREGDISPLAY pContext,
}
else
{
- PTR_CBYTE table = PTR_CBYTE(methodInfoPtr) + stateBuf->hdrInfoSize;
+ PTR_CBYTE table = PTR_CBYTE(gcInfoToken.Info) + stateBuf->hdrInfoSize;
unsigned argSize = GetPushedArgSize(info, table, relOffset);
return PVOID(SIZE_T(pContext->Esp + argSize + info->gsCookieOffset));
}
#elif defined(USE_GC_INFO_DECODER) && !defined(CROSSGEN_COMPILE)
- PTR_CBYTE gcInfoAddr = PTR_CBYTE(methodInfoPtr);
-
if (pCodeInfo->IsFunclet())
{
return NULL;
}
GcInfoDecoder gcInfoDecoder(
- gcInfoAddr,
+ gcInfoToken,
DECODE_GS_COOKIE,
0
);
@@ -5567,7 +5559,7 @@ bool EECodeManager::IsInSynchronizedRegion(
*
* Returns the size of a given function.
*/
-size_t EECodeManager::GetFunctionSize(PTR_VOID methodInfoPtr)
+size_t EECodeManager::GetFunctionSize(GCInfoToken gcInfoToken)
{
CONTRACTL {
NOTHROW;
@@ -5577,16 +5569,15 @@ size_t EECodeManager::GetFunctionSize(PTR_VOID methodInfoPtr)
#if defined(_TARGET_X86_)
hdrInfo info;
+ PTR_VOID methodInfoPtr = gcInfoToken.Info;
crackMethodInfoHdr(methodInfoPtr, 0, &info);
return info.methodSize;
#elif defined(USE_GC_INFO_DECODER)
- PTR_BYTE gcInfoAddr = PTR_BYTE(methodInfoPtr);
-
GcInfoDecoder gcInfoDecoder(
- gcInfoAddr,
+ gcInfoToken,
DECODE_CODE_LENGTH,
0
);
diff --git a/src/vm/gccover.cpp b/src/vm/gccover.cpp
index 2dd7c9e2a5..3220cddd8e 100644
--- a/src/vm/gccover.cpp
+++ b/src/vm/gccover.cpp
@@ -79,7 +79,7 @@ void SetupAndSprinkleBreakpoints(
gcCover->methodRegion = methodRegionInfo;
gcCover->codeMan = pCodeInfo->GetCodeManager();
- gcCover->gcInfo = pCodeInfo->GetGCInfo();
+ gcCover->gcInfoToken = pCodeInfo->GetGCInfoToken();
gcCover->callerThread = 0;
gcCover->doingEpilogChecks = true;
@@ -286,7 +286,7 @@ class GCCoverageRangeEnumerator
private:
ICodeManager *m_pCodeManager;
- LPVOID m_pvGCInfo;
+ GCInfoToken m_pvGCTable;
BYTE *m_codeStart;
BYTE *m_codeEnd;
BYTE *m_curFuncletEnd;
@@ -318,7 +318,7 @@ private:
unsigned ofsLastInterruptible = m_pCodeManager->FindEndOfLastInterruptibleRegion(
static_cast<unsigned int>(pCurFunclet - m_codeStart),
static_cast<unsigned int>(m_curFuncletEnd - m_codeStart),
- m_pvGCInfo);
+ m_pvGCTable);
if (ofsLastInterruptible)
{
@@ -332,10 +332,10 @@ private:
public:
- GCCoverageRangeEnumerator (ICodeManager *pCodeManager, LPVOID pvGCInfo, BYTE *codeStart, SIZE_T codeSize)
+ GCCoverageRangeEnumerator (ICodeManager *pCodeManager, GCInfoToken pvGCTable, BYTE *codeStart, SIZE_T codeSize)
{
m_pCodeManager = pCodeManager;
- m_pvGCInfo = pvGCInfo;
+ m_pvGCTable = pvGCTable;
m_codeStart = codeStart;
m_codeEnd = codeStart + codeSize;
m_nextFunclet = codeStart;
@@ -458,9 +458,9 @@ void GCCoverageInfo::SprinkleBreakpoints(
#ifdef _TARGET_AMD64_
- GCCoverageRangeEnumerator rangeEnum(codeMan, gcInfo, codeStart, codeSize);
+ GCCoverageRangeEnumerator rangeEnum(codeMan, gcInfoToken, codeStart, codeSize);
- GcInfoDecoder safePointDecoder((const BYTE*)gcInfo, (GcInfoDecoderFlags)0, 0);
+ GcInfoDecoder safePointDecoder(gcInfoToken, (GcInfoDecoderFlags)0, 0);
bool fSawPossibleSwitch = false;
#endif
@@ -582,7 +582,7 @@ void GCCoverageInfo::SprinkleBreakpoints(
#ifdef _TARGET_X86_
// we will whack every instruction in the prolog and epilog to make certain
// our unwinding logic works there.
- if (codeMan->IsInPrologOrEpilog((cur - codeStart) + (DWORD)regionOffsetAdj, gcInfo, NULL)) {
+ if (codeMan->IsInPrologOrEpilog((cur - codeStart) + (DWORD)regionOffsetAdj, gcInfoToken.Info, NULL)) {
*cur = INTERRUPT_INSTR;
}
#endif
@@ -632,7 +632,7 @@ void GCCoverageInfo::SprinkleBreakpoints(
}
}
- GcInfoDecoder safePointDecoder((const BYTE*)gcInfo, (GcInfoDecoderFlags)0, 0);
+ GcInfoDecoder safePointDecoder(gcInfoToken, (GcInfoDecoderFlags)0, 0);
assert(methodRegion.hotSize > 0);
@@ -1469,7 +1469,7 @@ void DoGcStress (PCONTEXT regs, MethodDesc *pMD)
/* are we in a prolog or epilog? If so just test the unwind logic
but don't actually do a GC since the prolog and epilog are not
GC safe points */
- if (gcCover->codeMan->IsInPrologOrEpilog(offset, gcCover->gcInfo, NULL))
+ if (gcCover->codeMan->IsInPrologOrEpilog(offset, gcCover->gcInfoToken.Info, NULL))
{
// We are not at a GC safe point so we can't Suspend EE (Suspend EE will yield to GC).
// But we still have to update the GC Stress instruction. We do it directly without suspending
diff --git a/src/vm/gccover.h b/src/vm/gccover.h
index 0308f473f2..b2dedefa31 100644
--- a/src/vm/gccover.h
+++ b/src/vm/gccover.h
@@ -26,7 +26,7 @@ public:
// Following 6 variables are for prolog / epilog walking coverage
ICodeManager* codeMan; // CodeMan for this method
- void* gcInfo; // gcInfo for this method
+ GCInfoToken gcInfoToken; // gcInfo for this method
Thread* callerThread; // Thread associated with context callerRegs
T_CONTEXT callerRegs; // register state when method was entered
diff --git a/src/vm/gcenv.ee.cpp b/src/vm/gcenv.ee.cpp
index aa1edbb555..5ecae4f8fc 100644
--- a/src/vm/gcenv.ee.cpp
+++ b/src/vm/gcenv.ee.cpp
@@ -132,7 +132,7 @@ inline bool SafeToReportGenericParamContext(CrawlFrame* pCF)
#else // USE_GC_INFO_DECODER
- GcInfoDecoder gcInfoDecoder((PTR_CBYTE)pCF->GetGCInfo(),
+ GcInfoDecoder gcInfoDecoder(pCF->GetGCInfoToken(),
DECODE_PROLOG_LENGTH,
0);
UINT32 prologLength = gcInfoDecoder.GetPrologSize();
@@ -199,8 +199,8 @@ bool FindFirstInterruptiblePointStateCB(
// the end is exclusive). Return -1 if no such point exists.
unsigned FindFirstInterruptiblePoint(CrawlFrame* pCF, unsigned offs, unsigned endOffs)
{
- PTR_BYTE gcInfoAddr = dac_cast<PTR_BYTE>(pCF->GetCodeInfo()->GetGCInfo());
- GcInfoDecoder gcInfoDecoder(gcInfoAddr, DECODE_FOR_RANGES_CALLBACK, 0);
+ GCInfoToken gcInfoToken = pCF->GetGCInfoToken();
+ GcInfoDecoder gcInfoDecoder(gcInfoToken, DECODE_FOR_RANGES_CALLBACK, 0);
FindFirstInterruptiblePointState state;
state.offs = offs;
@@ -281,9 +281,9 @@ StackWalkAction GcStackCrawlCallBack(CrawlFrame* pCF, VOID* pData)
#if defined(WIN64EXCEPTIONS)
if (pCF->ShouldParentToFuncletUseUnwindTargetLocationForGCReporting())
{
- PTR_BYTE gcInfoAddr = dac_cast<PTR_BYTE>(pCF->GetCodeInfo()->GetGCInfo());
+ GCInfoToken gcInfoToken = pCF->GetGCInfoToken();
GcInfoDecoder _gcInfoDecoder(
- gcInfoAddr,
+ gcInfoToken,
DECODE_CODE_LENGTH,
0
);
diff --git a/src/vm/gcinfodecoder.cpp b/src/vm/gcinfodecoder.cpp
index 5a3bbd94eb..b2f5640331 100644
--- a/src/vm/gcinfodecoder.cpp
+++ b/src/vm/gcinfodecoder.cpp
@@ -6,7 +6,6 @@
#include "common.h"
#include "gcinfodecoder.h"
-
#ifdef USE_GC_INFO_DECODER
#ifndef CHECK_APP_DOMAIN
@@ -84,11 +83,11 @@ bool GcInfoDecoder::SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset,
GcInfoDecoder::GcInfoDecoder(
- PTR_CBYTE gcInfoAddr,
+ GCInfoToken gcInfoToken,
GcInfoDecoderFlags flags,
UINT32 breakOffset
)
- : m_Reader( gcInfoAddr
+ : m_Reader(dac_cast<PTR_CBYTE>(gcInfoToken.Info)
#ifdef VERIFY_GCINFO
+ sizeof(size_t)
#endif
@@ -97,13 +96,14 @@ GcInfoDecoder::GcInfoDecoder(
, m_IsInterruptible(false)
#ifdef _DEBUG
, m_Flags( flags )
- , m_GcInfoAddress(gcInfoAddr)
+ , m_GcInfoAddress(dac_cast<PTR_CBYTE>(gcInfoToken.Info))
+ , m_Version(gcInfoToken.Version)
#endif
#ifdef VERIFY_GCINFO
- , m_DbgDecoder(gcInfoAddr+
- (((UINT32)((PTR_BYTE)(TADDR)gcInfoAddr)[3])<<24)+
- (((UINT32)((PTR_BYTE)(TADDR)gcInfoAddr)[2])<<16)+
- (((UINT32)((PTR_BYTE)(TADDR)gcInfoAddr)[1])<<8)+
+ , m_DbgDecoder(dac_cast<PTR_CBYTE>(gcInfoToken.Info) +
+ (((UINT32)((PTR_BYTE)(TADDR)gcInfoToken.Info)[3])<<24)+
+ (((UINT32)((PTR_BYTE)(TADDR)gcInfoToken.Info)[2])<<16)+
+ (((UINT32)((PTR_BYTE)(TADDR)gcInfoToken.Info)[1])<<8)+
((PTR_BYTE)(TADDR)gcInfoAddr)[0],
flags, breakOffset)
#endif
diff --git a/src/vm/stackwalk.h b/src/vm/stackwalk.h
index 3d6dbdcb14..004d673a2a 100644
--- a/src/vm/stackwalk.h
+++ b/src/vm/stackwalk.h
@@ -324,6 +324,13 @@ public:
return &codeInfo;
}
+ GCInfoToken GetGCInfoToken()
+ {
+ LIMITED_METHOD_DAC_CONTRACT;
+ _ASSERTE(isFrameless);
+ return codeInfo.GetGCInfoToken();
+ }
+
PTR_VOID GetGCInfo()
{
LIMITED_METHOD_DAC_CONTRACT;