Repository: dotnet/runtime
File: src/coreclr/vm/perfmap.cpp (C++)

Code before:
            {
                // PerfMap does not log R2R methods so only proceed if we are emitting jitdumps
                if (type == PerfMapType::ALL || type == PerfMapType::JITDUMP)
                {
                    Module *pModule = pAssembly->GetModule();
                    if (pModule->IsReadyToRun())
                    {
                        ReadyToRunInfo::MethodIterator mi(pModule->GetReadyToRunInfo());

                        while (mi.Next())
                        {
                            // Call GetMethodDesc_NoRestore instead of GetMethodDesc to avoid restoring methods.
                            MethodDesc *hotDesc = (MethodDesc *)mi.GetMethodDesc_NoRestore();
                            if (hotDesc != nullptr && hotDesc->GetNativeCode() != (PCODE)NULL)
                            {
                                PerfMap::LogPreCompiledMethod(hotDesc, hotDesc->GetNativeCode());
                            }
                        }
                    }
                }
            }
        }

        // Similarly, the EEJitManager may not exist yet if called before ExecutionManager::Init().
        // In this case, there's no JIT'd code to log anyway.
        EEJitManager *pJitManager = ExecutionManager::GetEEJitManager();
        if (pJitManager != nullptr)
        {
#ifdef FEATURE_CODE_VERSIONING
            CodeVersionManager::LockHolder codeVersioningLockHolder;
#endif // FEATURE_CODE_VERSIONING
            CodeHeapIterator heapIterator = pJitManager->GetCodeHeapIterator();
            while (heapIterator.Next())
            {
                MethodDesc * pMethod = heapIterator.GetMethod();
                if (pMethod == nullptr)
                {
                    continue;
                }

                PCODE codeStart = PINSTRToPCODE(heapIterator.GetMethodCode());
#ifdef FEATURE_CODE_VERSIONING
                NativeCodeVersion nativeCodeVersion;
                nativeCodeVersion = pMethod->GetCodeVersionManager()->GetNativeCodeVersion(pMethod, codeStart);
                if (nativeCodeVersion.IsNull() && codeStart != pMethod->GetNativeCode())
                {
                    continue;
                }
#endif // FEATURE_CODE_VERSIONING

                EECodeInfo codeInfo(codeStart);

Review comment (bug):
`m_pEEJitManager` that this returns is not `Volatile` so this still has a race conditions due to memory model issues. I do not think we want to make the statics like m_pEEJitManager `Volatile`.

I assume that we have a good reason to start listening to initialize perfmap very early before basic subsystems like code manager are ready. Is that correct?

If it is the case, I would introduce a new `static Volatile<bool> s_perfmapReady` set after we have everything in place to JIT managed code, and do an early out check using this bool variable.

Code after:
        }

        AppDomain::AssemblyIterator assemblyIterator = GetAppDomain()->IterateAssembliesEx(
            (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution));
        CollectibleAssemblyHolder<Assembly *> pAssembly;
        while (assemblyIterator.Next(pAssembly.This()))
        {
            // PerfMap does not log R2R methods so only proceed if we are emitting jitdumps
            if (type == PerfMapType::ALL || type == PerfMapType::JITDUMP)
            {
                Module *pModule = pAssembly->GetModule();
                if (pModule->IsReadyToRun())
                {
                    ReadyToRunInfo::MethodIterator mi(pModule->GetReadyToRunInfo());

                    while (mi.Next())
                    {
                        // Call GetMethodDesc_NoRestore instead of GetMethodDesc to avoid restoring methods.
                        MethodDesc *hotDesc = (MethodDesc *)mi.GetMethodDesc_NoRestore();
                        if (hotDesc != nullptr && hotDesc->GetNativeCode() != (PCODE)NULL)
                        {
                            PerfMap::LogPreCompiledMethod(hotDesc, hotDesc->GetNativeCode());
                        }
                    }
                }
            }
        }

        {
#ifdef FEATURE_CODE_VERSIONING
            CodeVersionManager::LockHolder codeVersioningLockHolder;
#endif // FEATURE_CODE_VERSIONING
            CodeHeapIterator heapIterator = ExecutionManager::GetEEJitManager()->GetCodeHeapIterator();
            while (heapIterator.Next())
            {
                MethodDesc * pMethod = heapIterator.GetMethod();
                if (pMethod == nullptr)
                {
                    continue;
                }

                PCODE codeStart = PINSTRToPCODE(heapIterator.GetMethodCode());
#ifdef FEATURE_CODE_VERSIONING
                NativeCodeVersion nativeCodeVersion;
                nativeCodeVersion = pMethod->GetCodeVersionManager()->GetNativeCodeVersion(pMethod, codeStart);
                if (nativeCodeVersion.IsNull() && codeStart != pMethod->GetNativeCode())
                {
                    continue;
                }
#endif // FEATURE_CODE_VERSIONING