void Utf8SourceInfo::EnsureInitialized(int initialFunctionCount) { ThreadContext* threadContext = ThreadContext::GetContextForCurrentThread(); Recycler* recycler = threadContext->GetRecycler(); if (this->functionBodyDictionary == nullptr) { // This collection is allocated with leaf allocation policy. The references to the function body // here does not keep the function alive. However, the functions remove themselves at finalize // so if a function actually is in this map, it means that it is alive. this->functionBodyDictionary = RecyclerNew(recycler, FunctionBodyDictionary, recycler, initialFunctionCount, threadContext->GetEtwRundownCriticalSection()); } if (CONFIG_FLAG(DeferTopLevelTillFirstCall) && !m_deferredFunctionsInitialized) { Assert(this->m_deferredFunctionsDictionary == nullptr); this->m_deferredFunctionsDictionary = RecyclerNew(recycler, DeferredFunctionsDictionary, recycler, initialFunctionCount, threadContext->GetEtwRundownCriticalSection()); m_deferredFunctionsInitialized = true; } }
// // Enumerate through all the script contexts in the process and log events // for each function loaded. Depending on the argument, start or end events are logged. // In particular, a rundown is needed for the 'Attach' scenario of profiling. // void EtwTrace::PerformRundown(bool start) { // Lock threadContext list during etw rundown AutoCriticalSection autoThreadContextCs(ThreadContext::GetCriticalSection()); ThreadContext * threadContext = ThreadContext::GetThreadContextList(); if(start) { JS_ETW(EventWriteDCStartInit()); } else { JS_ETW(EventWriteDCEndInit()); } while(threadContext != nullptr) { // Take etw rundown lock on this thread context AutoCriticalSection autoEtwRundownCs(threadContext->GetEtwRundownCriticalSection()); ScriptContext* scriptContext = threadContext->GetScriptContextList(); while(scriptContext != NULL) { if(scriptContext->IsClosed()) { scriptContext = scriptContext->next; continue; } if(start) { JS_ETW(EventWriteScriptContextDCStart(scriptContext)); if(scriptContext->GetSourceContextInfoMap() != nullptr) { scriptContext->GetSourceContextInfoMap()->Map( [=] (DWORD_PTR sourceContext, SourceContextInfo * sourceContextInfo) { if (sourceContext != Constants::NoHostSourceContext) { JS_ETW(LogSourceEvent(EventWriteSourceDCStart, sourceContext, scriptContext, /* sourceFlags*/ 0, sourceContextInfo->url)); } }); } } else { JS_ETW(EventWriteScriptContextDCEnd(scriptContext)); if(scriptContext->GetSourceContextInfoMap() != nullptr) { scriptContext->GetSourceContextInfoMap()->Map( [=] (DWORD_PTR sourceContext, SourceContextInfo * sourceContextInfo) { if (sourceContext != Constants::NoHostSourceContext) { JS_ETW(LogSourceEvent(EventWriteSourceDCEnd, sourceContext, scriptContext, /* sourceFlags*/ 0, sourceContextInfo->url)); } }); } } scriptContext->MapFunction([&start] (FunctionBody* body) { #if DYNAMIC_INTERPRETER_THUNK if(body->HasInterpreterThunkGenerated()) { if(start) { LogMethodInterpretedThunkEvent(EventWriteMethodDCStart, body); } else { LogMethodInterpretedThunkEvent(EventWriteMethodDCEnd, body); } } #endif #if ENABLE_NATIVE_CODEGEN body->MapEntryPoints([&](int index, FunctionEntryPointInfo * entryPoint) { if(entryPoint->IsCodeGenDone()) { if (start) { LogMethodNativeEvent(EventWriteMethodDCStart, body, entryPoint); } else { LogMethodNativeEvent(EventWriteMethodDCEnd, body, entryPoint); } } }); body->MapLoopHeadersWithLock([&](uint loopNumber, LoopHeader* header) { header->MapEntryPoints([&](int index, LoopEntryPointInfo * entryPoint) { if(entryPoint->IsCodeGenDone()) { if(start) { LogLoopBodyEventBG(EventWriteMethodDCStart, body, header, entryPoint, ((uint16)body->GetLoopNumberWithLock(header))); } else { LogLoopBodyEventBG(EventWriteMethodDCEnd, body, header, entryPoint, ((uint16)body->GetLoopNumberWithLock(header))); } } }); }); #endif }); scriptContext = scriptContext->next; } #ifdef NTBUILD if (EventEnabledJSCRIPT_HOSTING_CEO_START()) { threadContext->EtwLogPropertyIdList(); } #endif threadContext = threadContext->Next(); } if(start) { JS_ETW(EventWriteDCStartComplete()); } else { JS_ETW(EventWriteDCEndComplete()); } }