emit rundown event for generic methods in R2R images (#25371)
authorDavid Mason <davmason@microsoft.com>
Wed, 26 Jun 2019 03:13:31 +0000 (20:13 -0700)
committerGitHub <noreply@github.com>
Wed, 26 Jun 2019 03:13:31 +0000 (20:13 -0700)
* emit rundown event for generic methods in R2R images

* fix mac build

* Code Review Feedback

src/vm/eventtrace.cpp
src/vm/nativeformatreader.h
src/vm/readytoruninfo.cpp
src/vm/readytoruninfo.h

index c314375..da3bc0d 100644 (file)
@@ -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
index c97f324..34f46a6 100644 (file)
@@ -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)
index e0eebb4..f995193 100644 (file)
@@ -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;
index 65b49a6..597bf68 100644 (file)
@@ -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()