| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- /*===-- jitprofiling.c - JIT (Just-In-Time) Profiling API----------*- C -*-===*
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
- *
- *===----------------------------------------------------------------------===*
- *
- * This file provides Intel(R) Performance Analyzer JIT (Just-In-Time)
- * Profiling API implementation.
- *
- * NOTE: This file comes in a style different from the rest of LLVM
- * source base since this is a piece of code shared from Intel(R)
- * products. Please do not reformat / re-style this code to make
- * subsequent merges and contributions from the original source base eaiser.
- *
- *===----------------------------------------------------------------------===*/
- #include "ittnotify_config.h"
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- #include <windows.h>
- #pragma optimize("", off)
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- #include <pthread.h>
- #include <dlfcn.h>
- #include <stdint.h>
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- #include <malloc.h>
- #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 /* NEW_DLL_ENVIRONMENT_VAR */
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- #define DEFAULT_DLLNAME "JitPI.dll"
- HINSTANCE m_libHandle = NULL;
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- #define DEFAULT_DLLNAME "libJitPI.so"
- void* m_libHandle = NULL;
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- /* default location of JIT profiling agent on Android */
- #define ANDROID_JIT_AGENT_PATH "/data/intel/libittnotify.so"
- /* the function pointers */
- 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;
- /* end collector dll part. */
- /* loadiJIT_Funcs() : this function is called just in the beginning
- * and is responsible to load the functions from BistroJavaCollector.dll
- * result:
- * on success: the functions loads, iJIT_DLL_is_missing=0, return value = 1
- * on failure: the functions are NULL, iJIT_DLL_is_missing=1, return value = 0
- */
- static int loadiJIT_Funcs(void);
- /* global representing whether the BistroJavaCollector can't be loaded */
- static int iJIT_DLL_is_missing = 0;
- /* Virtual stack - the struct is used as a virtual stack for each thread.
- * Every thread initializes with a stack of size INIT_TOP_STACK.
- * Every method entry decreases from the current stack point,
- * and when a thread stack reaches its top of stack (return from the global
- * function), the top of stack and the current stack increase. Notice that
- * when returning from a function the stack pointer is the address of
- * the function return.
- */
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- static DWORD threadLocalStorageHandle = 0;
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- static pthread_key_t threadLocalStorageHandle = (pthread_key_t)0;
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- #define INIT_TOP_Stack 10000
- typedef struct
- {
- unsigned int TopStack;
- unsigned int CurrentStack;
- } ThreadStack, *pThreadStack;
- /* end of virtual stack. */
- /*
- * The function for reporting virtual-machine related events to VTune.
- * Note: when reporting iJVM_EVENT_TYPE_ENTER_NIDS, there is no need to fill
- * in the stack_id field in the iJIT_Method_NIDS structure, as VTune fills it.
- * The return value in iJVM_EVENT_TYPE_ENTER_NIDS &&
- * iJVM_EVENT_TYPE_LEAVE_NIDS events will be 0 in case of failure.
- * in iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED event
- * it will be -1 if EventSpecificData == 0 otherwise it will be 0.
- */
- ITT_EXTERN_C int JITAPI
- iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData)
- {
- int ReturnValue;
- /*
- * This section is for debugging outside of VTune.
- * It creates the environment variables that indicates call graph mode.
- * If running outside of VTune remove the remark.
- *
- *
- * static int firstTime = 1;
- * char DoCallGraph[12] = "DoCallGraph";
- * if (firstTime)
- * {
- * firstTime = 0;
- * SetEnvironmentVariable( "BISTRO_COLLECTORS_DO_CALLGRAPH", DoCallGraph);
- * }
- *
- * end of section.
- */
- /* initialization part - the functions have not been loaded yet. This part
- * will load the functions, and check if we are in Call Graph mode.
- * (for special treatment).
- */
- if (!FUNC_NotifyEvent)
- {
- if (iJIT_DLL_is_missing)
- return 0;
- /* load the Function from the DLL */
- if (!loadiJIT_Funcs())
- return 0;
- /* Call Graph initialization. */
- }
- /* If the event is method entry/exit, check that in the current mode
- * VTune is allowed to receive it
- */
- if ((event_type == iJVM_EVENT_TYPE_ENTER_NIDS ||
- event_type == iJVM_EVENT_TYPE_LEAVE_NIDS) &&
- (executionMode != iJIT_CALLGRAPH_ON))
- {
- return 0;
- }
- /* This section is performed when method enter event occurs.
- * It updates the virtual stack, or creates it if this is the first
- * method entry in the thread. The stack pointer is decreased.
- */
- if (event_type == iJVM_EVENT_TYPE_ENTER_NIDS)
- {
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- pThreadStack threadStack =
- (pThreadStack)TlsGetValue (threadLocalStorageHandle);
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- pThreadStack threadStack =
- (pThreadStack)pthread_getspecific(threadLocalStorageHandle);
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- /* check for use of reserved method IDs */
- if ( ((piJIT_Method_NIDS) EventSpecificData)->method_id <= 999 )
- return 0;
- if (!threadStack)
- {
- /* initialize the stack. */
- 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 /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- pthread_setspecific(threadLocalStorageHandle,(void*)threadStack);
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- }
- /* decrease the stack. */
- ((piJIT_Method_NIDS) EventSpecificData)->stack_id =
- (threadStack->CurrentStack)--;
- }
- /* This section is performed when method leave event occurs
- * It updates the virtual stack.
- * Increases the stack pointer.
- * If the stack pointer reached the top (left the global function)
- * increase the pointer and the top pointer.
- */
- if (event_type == iJVM_EVENT_TYPE_LEAVE_NIDS)
- {
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- pThreadStack threadStack =
- (pThreadStack)TlsGetValue (threadLocalStorageHandle);
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- pThreadStack threadStack =
- (pThreadStack)pthread_getspecific(threadLocalStorageHandle);
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- /* check for use of reserved method IDs */
- if ( ((piJIT_Method_NIDS) EventSpecificData)->method_id <= 999 )
- return 0;
- if (!threadStack)
- {
- /* Error: first report in this thread is method exit */
- 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)
- {
- /* check for use of reserved method IDs */
- if ( ((piJIT_Method_Load) EventSpecificData)->method_id <= 999 )
- return 0;
- }
- ReturnValue = (int)FUNC_NotifyEvent(event_type, EventSpecificData);
- return ReturnValue;
- }
- /* The new mode call back routine */
- ITT_EXTERN_C void JITAPI
- iJIT_RegisterCallbackEx(void *userdata, iJIT_ModeChangedEx
- NewModeCallBackFuncEx)
- {
- /* is it already missing... or the load of functions from the DLL failed */
- if (iJIT_DLL_is_missing || !loadiJIT_Funcs())
- {
- /* then do not bother with notifications */
- NewModeCallBackFuncEx(userdata, iJIT_NO_NOTIFICATIONS);
- /* Error: could not load JIT functions. */
- return;
- }
- /* nothing to do with the callback */
- }
- /*
- * This function allows the user to query in which mode, if at all,
- *VTune is running
- */
- ITT_EXTERN_C iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive()
- {
- if (!iJIT_DLL_is_missing)
- {
- loadiJIT_Funcs();
- }
- return executionMode;
- }
- /* this function loads the collector dll (BistroJavaCollector)
- * and the relevant functions.
- * on success: all functions load, iJIT_DLL_is_missing = 0, return value = 1
- * on failure: all functions are NULL, iJIT_DLL_is_missing = 1, return value = 0
- */
- static int loadiJIT_Funcs()
- {
- static int bDllWasLoaded = 0;
- char *dllName = (char*)rcsid; /* !! Just to avoid unused code elimination */
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- DWORD dNameLength = 0;
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- if(bDllWasLoaded)
- {
- /* dll was already loaded, no need to do it for the second time */
- return 1;
- }
- /* Assumes that the DLL will not be found */
- iJIT_DLL_is_missing = 1;
- FUNC_NotifyEvent = NULL;
- if (m_libHandle)
- {
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- FreeLibrary(m_libHandle);
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- dlclose(m_libHandle);
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- m_libHandle = NULL;
- }
- /* Try to get the dll name from the environment */
- #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)
- {
- /* Try to load the dll from the PATH... */
- m_libHandle = LoadLibraryExA(dllName,
- NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
- }
- free(dllName);
- } else {
- /* Try to use old VS_PROFILER variable */
- 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)
- {
- /* Try to load the dll from the PATH... */
- m_libHandle = LoadLibraryA(dllName);
- }
- free(dllName);
- }
- }
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- 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)
- {
- /* Try to load the dll from the PATH... */
- m_libHandle = dlopen(dllName, RTLD_LAZY);
- }
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- if (!m_libHandle)
- {
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- m_libHandle = LoadLibraryA(DEFAULT_DLLNAME);
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- m_libHandle = dlopen(DEFAULT_DLLNAME, RTLD_LAZY);
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- }
- /* if the dll wasn't loaded - exit. */
- if (!m_libHandle)
- {
- iJIT_DLL_is_missing = 1; /* don't try to initialize
- * JIT agent the second time
- */
- return 0;
- }
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- FUNC_NotifyEvent = (TPNotify)GetProcAddress(m_libHandle, "NotifyEvent");
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- FUNC_NotifyEvent = (TPNotify)(intptr_t)dlsym(m_libHandle, "NotifyEvent");
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- if (!FUNC_NotifyEvent)
- {
- FUNC_Initialize = NULL;
- return 0;
- }
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- FUNC_Initialize = (TPInitialize)GetProcAddress(m_libHandle, "Initialize");
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- FUNC_Initialize = (TPInitialize)(intptr_t)dlsym(m_libHandle, "Initialize");
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- if (!FUNC_Initialize)
- {
- FUNC_NotifyEvent = NULL;
- return 0;
- }
- executionMode = (iJIT_IsProfilingActiveFlags)FUNC_Initialize();
- bDllWasLoaded = 1;
- iJIT_DLL_is_missing = 0; /* DLL is ok. */
- /*
- * Call Graph mode: init the thread local storage
- * (need to store the virtual stack there).
- */
- if ( executionMode == iJIT_CALLGRAPH_ON )
- {
- /* Allocate a thread local storage slot for the thread "stack" */
- if (!threadLocalStorageHandle)
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- threadLocalStorageHandle = TlsAlloc();
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- pthread_key_create(&threadLocalStorageHandle, NULL);
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- }
- return 1;
- }
- /*
- * This function should be called by the user whenever a thread ends,
- * to free the thread "virtual stack" storage
- */
- ITT_EXTERN_C void JITAPI FinalizeThread()
- {
- if (threadLocalStorageHandle)
- {
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- pThreadStack threadStack =
- (pThreadStack)TlsGetValue (threadLocalStorageHandle);
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- pThreadStack threadStack =
- (pThreadStack)pthread_getspecific(threadLocalStorageHandle);
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- if (threadStack)
- {
- free (threadStack);
- threadStack = NULL;
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- TlsSetValue (threadLocalStorageHandle, threadStack);
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- pthread_setspecific(threadLocalStorageHandle, threadStack);
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- }
- }
- }
- /*
- * This function should be called by the user when the process ends,
- * to free the local storage index
- */
- ITT_EXTERN_C void JITAPI FinalizeProcess()
- {
- if (m_libHandle)
- {
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- FreeLibrary(m_libHandle);
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- dlclose(m_libHandle);
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- m_libHandle = NULL;
- }
- if (threadLocalStorageHandle)
- #if ITT_PLATFORM==ITT_PLATFORM_WIN
- TlsFree (threadLocalStorageHandle);
- #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- pthread_key_delete(threadLocalStorageHandle);
- #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
- }
- /*
- * This function should be called by the user for any method once.
- * The function will return a unique method ID, the user should maintain
- * the ID for each method
- */
- ITT_EXTERN_C unsigned int JITAPI iJIT_GetNewMethodID()
- {
- static unsigned int methodID = 0x100000;
- if (methodID == 0)
- return 0; /* ERROR : this is not a valid value */
- return methodID++;
- }
|