#include "ittnotify_config.h"
#if ITT_PLATFORM==ITT_PLATFORM_WIN
#include <windows.h>
#pragma optimize("", off)
#else
#include <dlfcn.h>
#include <pthread.h>
#include <stdint.h>
#endif
#include <stdlib.h>
#include "jitprofiling.h"
static const char rcsid[] = "\n@(#) $Revision: 243501 $\n";
#define DLL_ENVIRONMENT_VAR "VS_PROFILER"
#ifndef NEW_DLL_ENVIRONMENT_VAR
#if ITT_ARCH==ITT_ARCH_IA32
#define NEW_DLL_ENVIRONMENT_VAR "INTEL_JIT_PROFILER32"
#else
#define NEW_DLL_ENVIRONMENT_VAR "INTEL_JIT_PROFILER64"
#endif
#endif
#if ITT_PLATFORM==ITT_PLATFORM_WIN
#define DEFAULT_DLLNAME "JitPI.dll"
HINSTANCE m_libHandle = NULL;
#else
#define DEFAULT_DLLNAME "libJitPI.so"
void* m_libHandle = NULL;
#endif
#define ANDROID_JIT_AGENT_PATH "/data/intel/libittnotify.so"
typedef unsigned int(*TPInitialize)(void);
static TPInitialize FUNC_Initialize=NULL;
typedef unsigned int(*TPNotify)(unsigned int, void*);
static TPNotify FUNC_NotifyEvent=NULL;
static iJIT_IsProfilingActiveFlags executionMode = iJIT_NOTHING_RUNNING;
static int loadiJIT_Funcs(void);
static int iJIT_DLL_is_missing = 0;
#if ITT_PLATFORM==ITT_PLATFORM_WIN
static DWORD threadLocalStorageHandle = 0;
#else
static pthread_key_t threadLocalStorageHandle = (pthread_key_t)0;
#endif
#define INIT_TOP_Stack 10000
typedef struct
{
unsigned int TopStack;
unsigned int CurrentStack;
} ThreadStack, *pThreadStack;
ITT_EXTERN_C int JITAPI
iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData)
{
int ReturnValue;
if (!FUNC_NotifyEvent)
{
if (iJIT_DLL_is_missing)
return 0;
if (!loadiJIT_Funcs())
return 0;
}
if ((event_type == iJVM_EVENT_TYPE_ENTER_NIDS ||
event_type == iJVM_EVENT_TYPE_LEAVE_NIDS) &&
(executionMode != iJIT_CALLGRAPH_ON))
{
return 0;
}
if (event_type == iJVM_EVENT_TYPE_ENTER_NIDS)
{
#if ITT_PLATFORM==ITT_PLATFORM_WIN
pThreadStack threadStack =
(pThreadStack)TlsGetValue (threadLocalStorageHandle);
#else
pThreadStack threadStack =
(pThreadStack)pthread_getspecific(threadLocalStorageHandle);
#endif
if ( ((piJIT_Method_NIDS) EventSpecificData)->method_id <= 999 )
return 0;
if (!threadStack)
{
threadStack = (pThreadStack) calloc (sizeof(ThreadStack), 1);
threadStack->TopStack = INIT_TOP_Stack;
threadStack->CurrentStack = INIT_TOP_Stack;
#if ITT_PLATFORM==ITT_PLATFORM_WIN
TlsSetValue(threadLocalStorageHandle,(void*)threadStack);
#else
pthread_setspecific(threadLocalStorageHandle,(void*)threadStack);
#endif
}
((piJIT_Method_NIDS) EventSpecificData)->stack_id =
(threadStack->CurrentStack)--;
}
if (event_type == iJVM_EVENT_TYPE_LEAVE_NIDS)
{
#if ITT_PLATFORM==ITT_PLATFORM_WIN
pThreadStack threadStack =
(pThreadStack)TlsGetValue (threadLocalStorageHandle);
#else
pThreadStack threadStack =
(pThreadStack)pthread_getspecific(threadLocalStorageHandle);
#endif
if ( ((piJIT_Method_NIDS) EventSpecificData)->method_id <= 999 )
return 0;
if (!threadStack)
{
exit (1);
}
((piJIT_Method_NIDS) EventSpecificData)->stack_id =
++(threadStack->CurrentStack) + 1;
if (((piJIT_Method_NIDS) EventSpecificData)->stack_id
> threadStack->TopStack)
((piJIT_Method_NIDS) EventSpecificData)->stack_id =
(unsigned int)-1;
}
if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED)
{
if ( ((piJIT_Method_Load) EventSpecificData)->method_id <= 999 )
return 0;
}
ReturnValue = (int)FUNC_NotifyEvent(event_type, EventSpecificData);
return ReturnValue;
}
ITT_EXTERN_C void JITAPI
iJIT_RegisterCallbackEx(void *userdata, iJIT_ModeChangedEx
NewModeCallBackFuncEx)
{
if (iJIT_DLL_is_missing || !loadiJIT_Funcs())
{
NewModeCallBackFuncEx(userdata, iJIT_NO_NOTIFICATIONS);
return;
}
}
ITT_EXTERN_C iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive()
{
if (!iJIT_DLL_is_missing)
{
loadiJIT_Funcs();
}
return executionMode;
}
static int loadiJIT_Funcs()
{
static int bDllWasLoaded = 0;
char *dllName = (char*)rcsid;
#if ITT_PLATFORM==ITT_PLATFORM_WIN
DWORD dNameLength = 0;
#endif
if(bDllWasLoaded)
{
return 1;
}
iJIT_DLL_is_missing = 1;
FUNC_NotifyEvent = NULL;
if (m_libHandle)
{
#if ITT_PLATFORM==ITT_PLATFORM_WIN
FreeLibrary(m_libHandle);
#else
dlclose(m_libHandle);
#endif
m_libHandle = NULL;
}
#if ITT_PLATFORM==ITT_PLATFORM_WIN
dNameLength = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR, NULL, 0);
if (dNameLength)
{
DWORD envret = 0;
dllName = (char*)malloc(sizeof(char) * (dNameLength + 1));
envret = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR,
dllName, dNameLength);
if (envret)
{
m_libHandle = LoadLibraryExA(dllName,
NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}
free(dllName);
} else {
dNameLength = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR, NULL, 0);
if (dNameLength)
{
DWORD envret = 0;
dllName = (char*)malloc(sizeof(char) * (dNameLength + 1));
envret = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR,
dllName, dNameLength);
if (envret)
{
m_libHandle = LoadLibraryA(dllName);
}
free(dllName);
}
}
#else
dllName = getenv(NEW_DLL_ENVIRONMENT_VAR);
if (!dllName)
dllName = getenv(DLL_ENVIRONMENT_VAR);
#ifdef ANDROID
if (!dllName)
dllName = ANDROID_JIT_AGENT_PATH;
#endif
if (dllName)
{
m_libHandle = dlopen(dllName, RTLD_LAZY);
}
#endif
if (!m_libHandle)
{
#if ITT_PLATFORM==ITT_PLATFORM_WIN
m_libHandle = LoadLibraryA(DEFAULT_DLLNAME);
#else
m_libHandle = dlopen(DEFAULT_DLLNAME, RTLD_LAZY);
#endif
}
if (!m_libHandle)
{
iJIT_DLL_is_missing = 1;
return 0;
}
#if ITT_PLATFORM==ITT_PLATFORM_WIN
FUNC_NotifyEvent = (TPNotify)GetProcAddress(m_libHandle, "NotifyEvent");
#else
FUNC_NotifyEvent = (TPNotify)(intptr_t)dlsym(m_libHandle, "NotifyEvent");
#endif
if (!FUNC_NotifyEvent)
{
FUNC_Initialize = NULL;
return 0;
}
#if ITT_PLATFORM==ITT_PLATFORM_WIN
FUNC_Initialize = (TPInitialize)GetProcAddress(m_libHandle, "Initialize");
#else
FUNC_Initialize = (TPInitialize)(intptr_t)dlsym(m_libHandle, "Initialize");
#endif
if (!FUNC_Initialize)
{
FUNC_NotifyEvent = NULL;
return 0;
}
executionMode = (iJIT_IsProfilingActiveFlags)FUNC_Initialize();
bDllWasLoaded = 1;
iJIT_DLL_is_missing = 0;
if ( executionMode == iJIT_CALLGRAPH_ON )
{
if (!threadLocalStorageHandle)
#if ITT_PLATFORM==ITT_PLATFORM_WIN
threadLocalStorageHandle = TlsAlloc();
#else
pthread_key_create(&threadLocalStorageHandle, NULL);
#endif
}
return 1;
}
ITT_EXTERN_C void JITAPI FinalizeThread()
{
if (threadLocalStorageHandle)
{
#if ITT_PLATFORM==ITT_PLATFORM_WIN
pThreadStack threadStack =
(pThreadStack)TlsGetValue (threadLocalStorageHandle);
#else
pThreadStack threadStack =
(pThreadStack)pthread_getspecific(threadLocalStorageHandle);
#endif
if (threadStack)
{
free (threadStack);
threadStack = NULL;
#if ITT_PLATFORM==ITT_PLATFORM_WIN
TlsSetValue (threadLocalStorageHandle, threadStack);
#else
pthread_setspecific(threadLocalStorageHandle, threadStack);
#endif
}
}
}
ITT_EXTERN_C void JITAPI FinalizeProcess()
{
if (m_libHandle)
{
#if ITT_PLATFORM==ITT_PLATFORM_WIN
FreeLibrary(m_libHandle);
#else
dlclose(m_libHandle);
#endif
m_libHandle = NULL;
}
if (threadLocalStorageHandle)
#if ITT_PLATFORM==ITT_PLATFORM_WIN
TlsFree (threadLocalStorageHandle);
#else
pthread_key_delete(threadLocalStorageHandle);
#endif
}
ITT_EXTERN_C unsigned int JITAPI iJIT_GetNewMethodID()
{
static unsigned int methodID = 0x100000;
if (methodID == 0)
return 0;
return methodID++;
}