| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "RuntimeBasePch.h"
- #ifdef VTUNE_PROFILING
- #include "VTuneChakraProfile.h"
- #include "jitprofiling.h"
- static const char LoopStr[] = "Loop";
- const utf8char_t VTuneChakraProfile::DynamicCode[] = "Dynamic code";
- bool VTuneChakraProfile::isJitProfilingActive = false;
- //
- // Registers the VTune profiler, if VTune sampling is running, we will get
- // true value for isJitProfilingActive variable.
- //
- void VTuneChakraProfile::Register()
- {
- #if ENABLE_NATIVE_CODEGEN
- isJitProfilingActive = (iJIT_IsProfilingActive() == iJIT_SAMPLING_ON);
- #endif
- }
- //
- // Unregister and notify VTune that even sampling is done.
- //
- void VTuneChakraProfile::UnRegister()
- {
- #if ENABLE_NATIVE_CODEGEN
- if(isJitProfilingActive)
- {
- iJIT_NotifyEvent(iJVM_EVENT_TYPE_SHUTDOWN, NULL);
- }
- #endif
- }
- //
- // Log JIT method native load event to VTune
- //
- void VTuneChakraProfile::LogMethodNativeLoadEvent(Js::FunctionBody* body, Js::FunctionEntryPointInfo* entryPoint)
- {
- #if ENABLE_NATIVE_CODEGEN
- if (isJitProfilingActive)
- {
- iJIT_Method_Load methodInfo;
- memset(&methodInfo, 0, sizeof(iJIT_Method_Load));
- const char16* methodName = body->GetExternalDisplayName();
- // Append function line number info to method name so that VTune can distinguish between polymorphic methods
- char16 methodNameBuffer[_MAX_PATH];
- ULONG lineNumber = body->GetLineNumber();
- char16 numberBuffer[20];
- _ltow_s(lineNumber, numberBuffer, 10);
- wcscpy_s(methodNameBuffer, methodName);
- if (entryPoint->GetJitMode() == ExecutionMode::SimpleJit)
- {
- wcscat_s(methodNameBuffer, _u(" Simple"));
- }
- wcscat_s(methodNameBuffer, _u(" {line:"));
- wcscat_s(methodNameBuffer, numberBuffer);
- wcscat_s(methodNameBuffer, _u("}"));
- size_t methodLength = wcslen(methodNameBuffer);
- Assert(methodLength < _MAX_PATH);
- size_t length = methodLength * 3 + 1;
- utf8char_t* utf8MethodName = HeapNewNoThrowArray(utf8char_t, length);
- if (utf8MethodName)
- {
- methodInfo.method_id = iJIT_GetNewMethodID();
- utf8::EncodeIntoAndNullTerminate(utf8MethodName, methodNameBuffer, (charcount_t)methodLength);
- methodInfo.method_name = (char*)utf8MethodName;
- methodInfo.method_load_address = (void*)entryPoint->GetNativeAddress();
- methodInfo.method_size = (uint)entryPoint->GetCodeSize(); // Size in memory - Must be exact
- LineNumberInfo numberInfo[1];
- uint lineCount = (entryPoint->GetNativeOffsetMapCount()) * 2 + 1; // may need to record both .begin and .end for all elements
- LineNumberInfo* pLineInfo = HeapNewNoThrowArray(LineNumberInfo, lineCount);
- if (pLineInfo == NULL || Js::Configuration::Global.flags.DisableVTuneSourceLineInfo)
- {
- // resort to original implementation, attribute all samples to first line
- numberInfo[0].LineNumber = lineNumber;
- numberInfo[0].Offset = 0;
- methodInfo.line_number_size = 1;
- methodInfo.line_number_table = numberInfo;
- }
- else
- {
- int size = entryPoint->PopulateLineInfo(pLineInfo, body);
- methodInfo.line_number_size = size;
- methodInfo.line_number_table = pLineInfo;
- }
- size_t urlLength = 0;
- utf8char_t* utf8Url = GetUrl(body, &urlLength);
- methodInfo.source_file_name = (char*)utf8Url;
- OUTPUT_TRACE(Js::ProfilerPhase, _u("Method load event: %s\n"), methodNameBuffer);
- iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &methodInfo);
- HeapDeleteArray(lineCount, pLineInfo);
- if (urlLength > 0)
- {
- HeapDeleteArray(urlLength, utf8Url);
- }
- HeapDeleteArray(length, utf8MethodName);
- }
- }
- #endif
- }
- //
- // Log loop body load event to VTune
- //
- void VTuneChakraProfile::LogLoopBodyLoadEvent(Js::FunctionBody* body, Js::LoopEntryPointInfo* entryPoint, uint16 loopNumber)
- {
- #if ENABLE_NATIVE_CODEGEN
- if (isJitProfilingActive)
- {
- iJIT_Method_Load methodInfo;
- memset(&methodInfo, 0, sizeof(iJIT_Method_Load));
- const char16* methodName = body->GetExternalDisplayName();
- size_t methodLength = wcslen(methodName);
- methodLength = min(methodLength, (size_t)UINT_MAX); // Just truncate if it is too big
- size_t length = methodLength * 3 + /* spaces */ 2 + _countof(LoopStr) + /*size of loop number*/ 10 + /*NULL*/ 1;
- utf8char_t* utf8MethodName = HeapNewNoThrowArray(utf8char_t, length);
- if(utf8MethodName)
- {
- methodInfo.method_id = iJIT_GetNewMethodID();
- size_t len = utf8::EncodeInto(utf8MethodName, methodName, (charcount_t)methodLength);
- sprintf_s((char*)(utf8MethodName + len), length - len," %s %d", LoopStr, loopNumber + 1);
- methodInfo.method_name = (char*)utf8MethodName;
- methodInfo.method_load_address = (void*)entryPoint->GetNativeAddress();
- methodInfo.method_size = (uint)entryPoint->GetCodeSize(); // Size in memory - Must be exact
- size_t urlLength = 0;
- utf8char_t* utf8Url = GetUrl(body, &urlLength);
- methodInfo.source_file_name = (char*)utf8Url;
- iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &methodInfo);
- OUTPUT_TRACE(Js::ProfilerPhase, _u("Loop body load event: %s Loop %d\n"), methodName, loopNumber + 1);
- if(urlLength > 0)
- {
- HeapDeleteArray(urlLength, utf8Url);
- }
- HeapDeleteArray(length, utf8MethodName);
- }
- }
- #endif
- }
- //
- // Get URL from source context, called by LogMethodNativeLoadEvent and LogLoopBodyLoadEvent
- //
- utf8char_t* VTuneChakraProfile::GetUrl(Js::FunctionBody* body, size_t* urlBufferLength )
- {
- utf8char_t* utf8Url = NULL;
- if (!body->GetSourceContextInfo()->IsDynamic())
- {
- const wchar* url = body->GetSourceContextInfo()->url;
- if (url)
- {
- size_t urlCharLength = wcslen(url);
- urlCharLength = min(urlCharLength, (size_t)UINT_MAX); // Just truncate if it is too big
- *urlBufferLength = urlCharLength * 3 + 1;
- utf8Url = HeapNewNoThrowArray(utf8char_t, *urlBufferLength);
- if (utf8Url)
- {
- utf8::EncodeIntoAndNullTerminate(utf8Url, url, (charcount_t)urlCharLength);
- }
- }
- }
- else
- {
- utf8Url = (utf8char_t*)VTuneChakraProfile::DynamicCode;
- }
- return utf8Url;
- }
- #endif /* VTUNE_PROFILING */
|