summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
authorDavid Mason <davmason@microsoft.com>2019-06-25 20:13:31 -0700
committerGitHub <noreply@github.com>2019-06-25 20:13:31 -0700
commitb497f76f9ab6a4f351bc9ec24437b0e2c5e4a1af (patch)
tree1faaac7409606c6dfb0f88cefcb1bb9c7e8063cc /src/vm
parent4d8ab39b383e5300adf9b1be451d4d46a982f586 (diff)
downloadcoreclr-b497f76f9ab6a4f351bc9ec24437b0e2c5e4a1af.tar.gz
coreclr-b497f76f9ab6a4f351bc9ec24437b0e2c5e4a1af.tar.bz2
coreclr-b497f76f9ab6a4f351bc9ec24437b0e2c5e4a1af.zip
emit rundown event for generic methods in R2R images (#25371)
* emit rundown event for generic methods in R2R images * fix mac build * Code Review Feedback
Diffstat (limited to 'src/vm')
-rw-r--r--src/vm/eventtrace.cpp11
-rw-r--r--src/vm/nativeformatreader.h60
-rw-r--r--src/vm/readytoruninfo.cpp92
-rw-r--r--src/vm/readytoruninfo.h30
4 files changed, 190 insertions, 3 deletions
diff --git a/src/vm/eventtrace.cpp b/src/vm/eventtrace.cpp
index c314375e8b..da3bc0db27 100644
--- a/src/vm/eventtrace.cpp
+++ b/src/vm/eventtrace.cpp
@@ -6845,6 +6845,17 @@ VOID ETW::MethodLog::SendEventsForNgenMethods(Module *pModule, DWORD dwEventOpti
}
}
+ ReadyToRunInfo::GenericMethodIterator gmi(pModule->GetReadyToRunInfo());
+ while (gmi.Next())
+ {
+ // Call GetMethodDesc_NoRestore instead of GetMethodDesc to avoid restoring methods at shutdown.
+ MethodDesc *hotDesc = (MethodDesc *)gmi.GetMethodDesc_NoRestore();
+ if (hotDesc != NULL)
+ {
+ ETW::MethodLog::SendMethodEvent(hotDesc, dwEventOptions, FALSE);
+ }
+ }
+
return;
}
#endif // FEATURE_READYTORUN
diff --git a/src/vm/nativeformatreader.h b/src/vm/nativeformatreader.h
index c97f324b59..34f46a6c54 100644
--- a/src/vm/nativeformatreader.h
+++ b/src/vm/nativeformatreader.h
@@ -42,7 +42,9 @@
namespace NativeFormat
{
class NativeReader;
- typedef DPTR(NativeReader) PTR_NativeReader;
+ class NativeHashtable;
+ typedef DPTR(NativeReader) PTR_NativeReader;
+ typedef DPTR(NativeHashtable) PTR_NativeHashtable;
class NativeReader
{
@@ -275,6 +277,8 @@ namespace NativeFormat
_offset = offset;
}
+ bool IsNull() { return _pReader == NULL; }
+
NativeReader * GetNativeReader() { return _pReader; }
uint GetOffset() { return _offset; }
@@ -482,6 +486,60 @@ namespace NativeFormat
bool IsNull() { return _pReader == NULL; }
+ class AllEntriesEnumerator
+ {
+ PTR_NativeHashtable _table;
+ NativeParser _parser;
+ uint _currentBucket;
+ uint _endOffset;
+
+ public:
+ AllEntriesEnumerator() :
+ _table(dac_cast<PTR_NativeHashtable>(nullptr)),
+ _parser(),
+ _currentBucket(0),
+ _endOffset(0)
+ {
+
+ }
+
+ AllEntriesEnumerator(PTR_NativeHashtable table)
+ {
+ _table = table;
+ _currentBucket = 0;
+ if (_table != NULL)
+ {
+ _parser = _table->GetParserForBucket(_currentBucket, &_endOffset);
+ }
+ }
+
+ NativeParser GetNext()
+ {
+ if (_table == NULL)
+ {
+ return NativeParser();
+ }
+
+ for (; ; )
+ {
+ if (_parser.GetOffset() < _endOffset)
+ {
+ // Skip hashcode to get to the offset
+ _parser.GetUInt8();
+ return _parser.GetParserFromRelativeOffset();
+ }
+
+ if (_currentBucket >= _table->_bucketMask)
+ {
+ return NativeParser();
+ }
+
+ _currentBucket++;
+ _parser = _table->GetParserForBucket(_currentBucket, &_endOffset);
+ }
+ }
+ };
+
//
// The enumerator does not conform to the regular C# enumerator pattern to avoid paying
// its performance penalty (allocation, multiple calls per iteration)
diff --git a/src/vm/readytoruninfo.cpp b/src/vm/readytoruninfo.cpp
index e0eebb41c3..f995193ebc 100644
--- a/src/vm/readytoruninfo.cpp
+++ b/src/vm/readytoruninfo.cpp
@@ -890,6 +890,98 @@ PCODE ReadyToRunInfo::MethodIterator::GetMethodStartAddress()
return ret;
}
+BOOL ReadyToRunInfo::GenericMethodIterator::Next()
+{
+ m_current = m_enum.GetNext();
+ return !m_current.IsNull();
+}
+
+MethodDesc *ReadyToRunInfo::GenericMethodIterator::GetMethodDesc_NoRestore()
+{
+ _ASSERTE(!m_current.IsNull());
+
+ HRESULT hr = S_OK;
+
+ PCCOR_SIGNATURE pBlob = (PCCOR_SIGNATURE)m_current.GetBlob();
+ SigPointer sig(pBlob);
+
+ DWORD methodFlags = 0;
+ // Skip the signature so we can get to the offset
+ hr = sig.GetData(&methodFlags);
+ if (FAILED(hr))
+ {
+ return NULL;
+ }
+
+ if (methodFlags & ENCODE_METHOD_SIG_OwnerType)
+ {
+ hr = sig.SkipExactlyOne();
+ if (FAILED(hr))
+ {
+ return NULL;
+ }
+ }
+
+ _ASSERTE((methodFlags & ENCODE_METHOD_SIG_SlotInsteadOfToken) == 0);
+ _ASSERTE((methodFlags & ENCODE_METHOD_SIG_MemberRefToken) == 0);
+
+ RID rid;
+ hr = sig.GetData(&rid);
+ if (FAILED(hr))
+ {
+ return NULL;
+ }
+
+ if (methodFlags & ENCODE_METHOD_SIG_MethodInstantiation)
+ {
+ DWORD numGenericArgs;
+ hr = sig.GetData(&numGenericArgs);
+ if (FAILED(hr))
+ {
+ return NULL;
+ }
+
+ for (DWORD i = 0; i < numGenericArgs; i++)
+ {
+ hr = sig.SkipExactlyOne();
+ if (FAILED(hr))
+ {
+ return NULL;
+ }
+ }
+ }
+
+ // Now that we have the size of the signature we can grab the offset and decode it
+ PCCOR_SIGNATURE pSigNew;
+ DWORD cbSigNew;
+ sig.GetSignature(&pSigNew, &cbSigNew);
+ uint offset = m_current.GetOffset() + (uint)(pSigNew - pBlob);
+
+ uint id;
+ offset = m_pInfo->m_nativeReader.DecodeUnsigned(offset, &id);
+
+ if (id & 1)
+ {
+ if (id & 2)
+ {
+ uint val;
+ m_pInfo->m_nativeReader.DecodeUnsigned(offset, &val);
+ offset -= val;
+ }
+
+ id >>= 2;
+ }
+ else
+ {
+ id >>= 1;
+ }
+
+ _ASSERTE(id < m_pInfo->m_nRuntimeFunctions);
+ PCODE pEntryPoint = dac_cast<TADDR>(m_pInfo->m_pLayout->GetBase()) + m_pInfo->m_pRuntimeFunctions[id].BeginAddress;
+
+ return m_pInfo->GetMethodDescForEntryPoint(pEntryPoint);
+}
+
DWORD ReadyToRunInfo::GetFieldBaseOffset(MethodTable * pMT)
{
STANDARD_VM_CONTRACT;
diff --git a/src/vm/readytoruninfo.h b/src/vm/readytoruninfo.h
index 65b49a6174..597bf68b11 100644
--- a/src/vm/readytoruninfo.h
+++ b/src/vm/readytoruninfo.h
@@ -118,8 +118,9 @@ public:
int m_methodDefIndex;
public:
- MethodIterator(ReadyToRunInfo * pInfo)
- : m_pInfo(pInfo), m_methodDefIndex(-1)
+ MethodIterator(ReadyToRunInfo * pInfo) :
+ m_pInfo(pInfo),
+ m_methodDefIndex(-1)
{
}
@@ -130,6 +131,31 @@ public:
PCODE GetMethodStartAddress();
};
+ class GenericMethodIterator
+ {
+ ReadyToRunInfo *m_pInfo;
+ NativeFormat::NativeHashtable::AllEntriesEnumerator m_enum;
+ NativeFormat::NativeParser m_current;
+
+ public:
+ GenericMethodIterator(ReadyToRunInfo *pInfo) :
+ m_pInfo(pInfo),
+ m_enum(),
+ m_current()
+ {
+ NativeFormat::PTR_NativeHashtable pHash = NULL;
+ if (!pInfo->m_instMethodEntryPoints.IsNull())
+ {
+ pHash = NativeFormat::PTR_NativeHashtable(&pInfo->m_instMethodEntryPoints);
+ }
+
+ m_enum = NativeFormat::NativeHashtable::AllEntriesEnumerator(pHash);
+ }
+
+ BOOL Next();
+ MethodDesc * GetMethodDesc_NoRestore();
+ };
+
static DWORD GetFieldBaseOffset(MethodTable * pMT);
PTR_PersistentInlineTrackingMapR2R GetInlineTrackingMap()