Add support for ready to run to NGEN rundown.
authorBrian Robbins <brianrob@microsoft.com>
Sun, 17 Apr 2016 21:56:12 +0000 (14:56 -0700)
committerBrian Robbins <brianrob@microsoft.com>
Tue, 19 Apr 2016 05:33:53 +0000 (22:33 -0700)
src/vm/eventtrace.cpp
src/vm/readytoruninfo.cpp
src/vm/readytoruninfo.h

index 5e35f9a..b9d12a7 100644 (file)
@@ -6805,15 +6805,38 @@ VOID ETW::MethodLog::SendEventsForNgenMethods(Module *pModule, DWORD dwEventOpti
     } CONTRACTL_END;
 
 #ifdef FEATURE_PREJIT
-    if(!pModule || !pModule->HasNativeImage())
+    if (!pModule)
         return;
 
-    MethodIterator mi(pModule);
+    PEImageLayout * pLoadedLayout = pModule->GetFile()->GetLoaded();
+    _ASSERTE(pLoadedLayout != NULL);
 
-    while(mi.Next())
+#ifdef FEATURE_READYTORUN
+    if (pLoadedLayout->HasReadyToRunHeader())
     {
-        MethodDesc *hotDesc = (MethodDesc *)mi.GetMethodDesc();
-        ETW::MethodLog::SendMethodEvent(hotDesc, dwEventOptions, FALSE);
+        ReadyToRunInfo::MethodIterator mi(pModule->GetReadyToRunInfo());
+        while (mi.Next())
+        {
+            // Call GetMethodDesc_NoRestore instead of GetMethodDesc to avoid restoring methods at shutdown.
+            MethodDesc *hotDesc = (MethodDesc *)mi.GetMethodDesc_NoRestore();
+            if (hotDesc != NULL)
+            {
+                ETW::MethodLog::SendMethodEvent(hotDesc, dwEventOptions, FALSE);
+            }
+        }
+
+        return;
+    }
+#endif // FEATURE_READYTORUN
+    if (pModule->HasNativeImage())
+    {
+        MethodIterator mi(pModule);
+
+        while (mi.Next())
+        {
+            MethodDesc *hotDesc = (MethodDesc *)mi.GetMethodDesc();
+            ETW::MethodLog::SendMethodEvent(hotDesc, dwEventOptions, FALSE);
+        }
     }
 #endif // FEATURE_PREJIT
 }
index d00db71..50c9243 100644 (file)
@@ -531,7 +531,13 @@ PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, BOOL fFixups /*=TRUE*/)
 
 BOOL ReadyToRunInfo::MethodIterator::Next()
 {
-    STANDARD_VM_CONTRACT;
+    CONTRACTL
+    {
+        GC_TRIGGERS;
+        THROWS;
+        MODE_ANY;
+    }
+    CONTRACTL_END;
 
     while (++m_methodDefIndex < (int)m_pInfo->m_methodDefEntryPoints.GetCount())
     {
@@ -549,6 +555,47 @@ MethodDesc * ReadyToRunInfo::MethodIterator::GetMethodDesc()
     return MemberLoader::GetMethodDescFromMethodDef(m_pInfo->m_pModule, mdtMethodDef | (m_methodDefIndex + 1), FALSE);
 }
 
+MethodDesc * ReadyToRunInfo::MethodIterator::GetMethodDesc_NoRestore()
+{
+    CONTRACTL
+    {
+        GC_TRIGGERS;
+        THROWS;
+        MODE_ANY;
+    }
+    CONTRACTL_END;
+
+    uint offset;
+    if (!m_pInfo->m_methodDefEntryPoints.TryGetAt(m_methodDefIndex, &offset))
+    {
+        return NULL;
+    }
+
+    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);
+}
+
 PCODE ReadyToRunInfo::MethodIterator::GetMethodStartAddress()
 {
     STANDARD_VM_CONTRACT;
index 9ca4050..ae903ce 100644 (file)
@@ -111,6 +111,7 @@ public:
         BOOL Next();
 
         MethodDesc * GetMethodDesc();
+        MethodDesc * GetMethodDesc_NoRestore();
         PCODE GetMethodStartAddress();
     };