1 /*===-- jitprofiling.c - JIT (Just-In-Time) Profiling API----------*- C -*-===*
3 * The LLVM Compiler Infrastructure
5 * This file is distributed under the University of Illinois Open Source
6 * License. See LICENSE.TXT for details.
8 *===----------------------------------------------------------------------===*
10 * This file provides Intel(R) Performance Analyzer JIT (Just-In-Time)
11 * Profiling API implementation.
13 * NOTE: This file comes in a style different from the rest of LLVM
14 * source base since this is a piece of code shared from Intel(R)
15 * products. Please do not reformat / re-style this code to make
16 * subsequent merges and contributions from the original source base eaiser.
18 *===----------------------------------------------------------------------===*/
19 #include "ittnotify_config.h"
21 #if ITT_PLATFORM==ITT_PLATFORM_WIN
23 #pragma optimize("", off)
24 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
27 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
31 #include "jitprofiling.h"
33 static const char rcsid[] = "\n@(#) $Revision: 243501 $\n";
35 #define DLL_ENVIRONMENT_VAR "VS_PROFILER"
37 #ifndef NEW_DLL_ENVIRONMENT_VAR
38 #if ITT_ARCH==ITT_ARCH_IA32
39 #define NEW_DLL_ENVIRONMENT_VAR "INTEL_JIT_PROFILER32"
41 #define NEW_DLL_ENVIRONMENT_VAR "INTEL_JIT_PROFILER64"
43 #endif /* NEW_DLL_ENVIRONMENT_VAR */
45 #if ITT_PLATFORM==ITT_PLATFORM_WIN
46 #define DEFAULT_DLLNAME "JitPI.dll"
47 HINSTANCE m_libHandle = NULL;
48 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
49 #define DEFAULT_DLLNAME "libJitPI.so"
50 void* m_libHandle = NULL;
51 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
53 /* default location of JIT profiling agent on Android */
54 #define ANDROID_JIT_AGENT_PATH "/data/intel/libittnotify.so"
56 /* the function pointers */
57 typedef unsigned int(*TPInitialize)(void);
58 static TPInitialize FUNC_Initialize=NULL;
60 typedef unsigned int(*TPNotify)(unsigned int, void*);
61 static TPNotify FUNC_NotifyEvent=NULL;
63 static iJIT_IsProfilingActiveFlags executionMode = iJIT_NOTHING_RUNNING;
65 /* end collector dll part. */
67 /* loadiJIT_Funcs() : this function is called just in the beginning
68 * and is responsible to load the functions from BistroJavaCollector.dll
70 * on success: the functions loads, iJIT_DLL_is_missing=0, return value = 1
71 * on failure: the functions are NULL, iJIT_DLL_is_missing=1, return value = 0
73 static int loadiJIT_Funcs(void);
75 /* global representing whether the BistroJavaCollector can't be loaded */
76 static int iJIT_DLL_is_missing = 0;
78 /* Virtual stack - the struct is used as a virtual stack for each thread.
79 * Every thread initializes with a stack of size INIT_TOP_STACK.
80 * Every method entry decreases from the current stack point,
81 * and when a thread stack reaches its top of stack (return from the global
82 * function), the top of stack and the current stack increase. Notice that
83 * when returning from a function the stack pointer is the address of
84 * the function return.
86 #if ITT_PLATFORM==ITT_PLATFORM_WIN
87 static DWORD threadLocalStorageHandle = 0;
88 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
89 static pthread_key_t threadLocalStorageHandle = (pthread_key_t)0;
90 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
92 #define INIT_TOP_Stack 10000
96 unsigned int TopStack;
97 unsigned int CurrentStack;
98 } ThreadStack, *pThreadStack;
100 /* end of virtual stack. */
103 * The function for reporting virtual-machine related events to VTune.
104 * Note: when reporting iJVM_EVENT_TYPE_ENTER_NIDS, there is no need to fill
105 * in the stack_id field in the iJIT_Method_NIDS structure, as VTune fills it.
106 * The return value in iJVM_EVENT_TYPE_ENTER_NIDS &&
107 * iJVM_EVENT_TYPE_LEAVE_NIDS events will be 0 in case of failure.
108 * in iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED event
109 * it will be -1 if EventSpecificData == 0 otherwise it will be 0.
112 ITT_EXTERN_C int JITAPI
113 iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData)
118 * This section is for debugging outside of VTune.
119 * It creates the environment variables that indicates call graph mode.
120 * If running outside of VTune remove the remark.
123 * static int firstTime = 1;
124 * char DoCallGraph[12] = "DoCallGraph";
128 * SetEnvironmentVariable( "BISTRO_COLLECTORS_DO_CALLGRAPH", DoCallGraph);
134 /* initialization part - the functions have not been loaded yet. This part
135 * will load the functions, and check if we are in Call Graph mode.
136 * (for special treatment).
138 if (!FUNC_NotifyEvent)
140 if (iJIT_DLL_is_missing)
143 /* load the Function from the DLL */
144 if (!loadiJIT_Funcs())
147 /* Call Graph initialization. */
150 /* If the event is method entry/exit, check that in the current mode
151 * VTune is allowed to receive it
153 if ((event_type == iJVM_EVENT_TYPE_ENTER_NIDS ||
154 event_type == iJVM_EVENT_TYPE_LEAVE_NIDS) &&
155 (executionMode != iJIT_CALLGRAPH_ON))
159 /* This section is performed when method enter event occurs.
160 * It updates the virtual stack, or creates it if this is the first
161 * method entry in the thread. The stack pointer is decreased.
163 if (event_type == iJVM_EVENT_TYPE_ENTER_NIDS)
165 #if ITT_PLATFORM==ITT_PLATFORM_WIN
166 pThreadStack threadStack =
167 (pThreadStack)TlsGetValue (threadLocalStorageHandle);
168 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
169 pThreadStack threadStack =
170 (pThreadStack)pthread_getspecific(threadLocalStorageHandle);
171 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
173 /* check for use of reserved method IDs */
174 if ( ((piJIT_Method_NIDS) EventSpecificData)->method_id <= 999 )
179 /* initialize the stack. */
180 threadStack = (pThreadStack) calloc (sizeof(ThreadStack), 1);
181 threadStack->TopStack = INIT_TOP_Stack;
182 threadStack->CurrentStack = INIT_TOP_Stack;
183 #if ITT_PLATFORM==ITT_PLATFORM_WIN
184 TlsSetValue(threadLocalStorageHandle,(void*)threadStack);
185 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
186 pthread_setspecific(threadLocalStorageHandle,(void*)threadStack);
187 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
190 /* decrease the stack. */
191 ((piJIT_Method_NIDS) EventSpecificData)->stack_id =
192 (threadStack->CurrentStack)--;
195 /* This section is performed when method leave event occurs
196 * It updates the virtual stack.
197 * Increases the stack pointer.
198 * If the stack pointer reached the top (left the global function)
199 * increase the pointer and the top pointer.
201 if (event_type == iJVM_EVENT_TYPE_LEAVE_NIDS)
203 #if ITT_PLATFORM==ITT_PLATFORM_WIN
204 pThreadStack threadStack =
205 (pThreadStack)TlsGetValue (threadLocalStorageHandle);
206 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
207 pThreadStack threadStack =
208 (pThreadStack)pthread_getspecific(threadLocalStorageHandle);
209 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
211 /* check for use of reserved method IDs */
212 if ( ((piJIT_Method_NIDS) EventSpecificData)->method_id <= 999 )
217 /* Error: first report in this thread is method exit */
221 ((piJIT_Method_NIDS) EventSpecificData)->stack_id =
222 ++(threadStack->CurrentStack) + 1;
224 if (((piJIT_Method_NIDS) EventSpecificData)->stack_id
225 > threadStack->TopStack)
226 ((piJIT_Method_NIDS) EventSpecificData)->stack_id =
230 if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED)
232 /* check for use of reserved method IDs */
233 if ( ((piJIT_Method_Load) EventSpecificData)->method_id <= 999 )
237 ReturnValue = (int)FUNC_NotifyEvent(event_type, EventSpecificData);
242 /* The new mode call back routine */
243 ITT_EXTERN_C void JITAPI
244 iJIT_RegisterCallbackEx(void *userdata, iJIT_ModeChangedEx
245 NewModeCallBackFuncEx)
247 /* is it already missing... or the load of functions from the DLL failed */
248 if (iJIT_DLL_is_missing || !loadiJIT_Funcs())
250 /* then do not bother with notifications */
251 NewModeCallBackFuncEx(userdata, iJIT_NO_NOTIFICATIONS);
252 /* Error: could not load JIT functions. */
255 /* nothing to do with the callback */
259 * This function allows the user to query in which mode, if at all,
262 ITT_EXTERN_C iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive()
264 if (!iJIT_DLL_is_missing)
269 return executionMode;
272 /* this function loads the collector dll (BistroJavaCollector)
273 * and the relevant functions.
274 * on success: all functions load, iJIT_DLL_is_missing = 0, return value = 1
275 * on failure: all functions are NULL, iJIT_DLL_is_missing = 1, return value = 0
277 static int loadiJIT_Funcs()
279 static int bDllWasLoaded = 0;
280 char *dllName = (char*)rcsid; /* !! Just to avoid unused code elimination */
281 #if ITT_PLATFORM==ITT_PLATFORM_WIN
282 DWORD dNameLength = 0;
283 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
287 /* dll was already loaded, no need to do it for the second time */
291 /* Assumes that the DLL will not be found */
292 iJIT_DLL_is_missing = 1;
293 FUNC_NotifyEvent = NULL;
297 #if ITT_PLATFORM==ITT_PLATFORM_WIN
298 FreeLibrary(m_libHandle);
299 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
300 dlclose(m_libHandle);
301 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
305 /* Try to get the dll name from the environment */
306 #if ITT_PLATFORM==ITT_PLATFORM_WIN
307 dNameLength = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR, NULL, 0);
311 dllName = (char*)malloc(sizeof(char) * (dNameLength + 1));
312 envret = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR,
313 dllName, dNameLength);
316 /* Try to load the dll from the PATH... */
317 m_libHandle = LoadLibraryExA(dllName,
318 NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
322 /* Try to use old VS_PROFILER variable */
323 dNameLength = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR, NULL, 0);
327 dllName = (char*)malloc(sizeof(char) * (dNameLength + 1));
328 envret = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR,
329 dllName, dNameLength);
332 /* Try to load the dll from the PATH... */
333 m_libHandle = LoadLibraryA(dllName);
338 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
339 dllName = getenv(NEW_DLL_ENVIRONMENT_VAR);
341 dllName = getenv(DLL_ENVIRONMENT_VAR);
344 dllName = ANDROID_JIT_AGENT_PATH;
348 /* Try to load the dll from the PATH... */
349 m_libHandle = dlopen(dllName, RTLD_LAZY);
351 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
355 #if ITT_PLATFORM==ITT_PLATFORM_WIN
356 m_libHandle = LoadLibraryA(DEFAULT_DLLNAME);
357 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
358 m_libHandle = dlopen(DEFAULT_DLLNAME, RTLD_LAZY);
359 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
362 /* if the dll wasn't loaded - exit. */
365 iJIT_DLL_is_missing = 1; /* don't try to initialize
366 * JIT agent the second time
371 #if ITT_PLATFORM==ITT_PLATFORM_WIN
372 FUNC_NotifyEvent = (TPNotify)GetProcAddress(m_libHandle, "NotifyEvent");
373 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
374 FUNC_NotifyEvent = (TPNotify)dlsym(m_libHandle, "NotifyEvent");
375 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
376 if (!FUNC_NotifyEvent)
378 FUNC_Initialize = NULL;
382 #if ITT_PLATFORM==ITT_PLATFORM_WIN
383 FUNC_Initialize = (TPInitialize)GetProcAddress(m_libHandle, "Initialize");
384 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
385 FUNC_Initialize = (TPInitialize)dlsym(m_libHandle, "Initialize");
386 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
387 if (!FUNC_Initialize)
389 FUNC_NotifyEvent = NULL;
393 executionMode = (iJIT_IsProfilingActiveFlags)FUNC_Initialize();
396 iJIT_DLL_is_missing = 0; /* DLL is ok. */
399 * Call Graph mode: init the thread local storage
400 * (need to store the virtual stack there).
402 if ( executionMode == iJIT_CALLGRAPH_ON )
404 /* Allocate a thread local storage slot for the thread "stack" */
405 if (!threadLocalStorageHandle)
406 #if ITT_PLATFORM==ITT_PLATFORM_WIN
407 threadLocalStorageHandle = TlsAlloc();
408 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
409 pthread_key_create(&threadLocalStorageHandle, NULL);
410 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
417 * This function should be called by the user whenever a thread ends,
418 * to free the thread "virtual stack" storage
420 ITT_EXTERN_C void JITAPI FinalizeThread()
422 if (threadLocalStorageHandle)
424 #if ITT_PLATFORM==ITT_PLATFORM_WIN
425 pThreadStack threadStack =
426 (pThreadStack)TlsGetValue (threadLocalStorageHandle);
427 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
428 pThreadStack threadStack =
429 (pThreadStack)pthread_getspecific(threadLocalStorageHandle);
430 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
435 #if ITT_PLATFORM==ITT_PLATFORM_WIN
436 TlsSetValue (threadLocalStorageHandle, threadStack);
437 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
438 pthread_setspecific(threadLocalStorageHandle, threadStack);
439 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
445 * This function should be called by the user when the process ends,
446 * to free the local storage index
448 ITT_EXTERN_C void JITAPI FinalizeProcess()
452 #if ITT_PLATFORM==ITT_PLATFORM_WIN
453 FreeLibrary(m_libHandle);
454 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
455 dlclose(m_libHandle);
456 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
460 if (threadLocalStorageHandle)
461 #if ITT_PLATFORM==ITT_PLATFORM_WIN
462 TlsFree (threadLocalStorageHandle);
463 #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
464 pthread_key_delete(threadLocalStorageHandle);
465 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
469 * This function should be called by the user for any method once.
470 * The function will return a unique method ID, the user should maintain
471 * the ID for each method
473 ITT_EXTERN_C unsigned int JITAPI iJIT_GetNewMethodID()
475 static unsigned int methodID = 0x100000;
478 return 0; /* ERROR : this is not a valid value */