jitprofiling.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /*===-- jitprofiling.c - JIT (Just-In-Time) Profiling API----------*- C -*-===*
  2. *
  3. * The LLVM Compiler Infrastructure
  4. *
  5. * This file is distributed under the University of Illinois Open Source
  6. * License. See LICENSE.TXT for details.
  7. *
  8. *===----------------------------------------------------------------------===*
  9. *
  10. * This file provides Intel(R) Performance Analyzer JIT (Just-In-Time)
  11. * Profiling API implementation.
  12. *
  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.
  17. *
  18. *===----------------------------------------------------------------------===*/
  19. #include "ittnotify_config.h"
  20. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  21. #include <windows.h>
  22. #pragma optimize("", off)
  23. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  24. #include <pthread.h>
  25. #include <dlfcn.h>
  26. #include <stdint.h>
  27. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  28. #include <malloc.h>
  29. #include <stdlib.h>
  30. #include "jitprofiling.h"
  31. static const char rcsid[] = "\n@(#) $Revision: 243501 $\n";
  32. #define DLL_ENVIRONMENT_VAR "VS_PROFILER"
  33. #ifndef NEW_DLL_ENVIRONMENT_VAR
  34. #if ITT_ARCH==ITT_ARCH_IA32
  35. #define NEW_DLL_ENVIRONMENT_VAR "INTEL_JIT_PROFILER32"
  36. #else
  37. #define NEW_DLL_ENVIRONMENT_VAR "INTEL_JIT_PROFILER64"
  38. #endif
  39. #endif /* NEW_DLL_ENVIRONMENT_VAR */
  40. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  41. #define DEFAULT_DLLNAME "JitPI.dll"
  42. HINSTANCE m_libHandle = NULL;
  43. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  44. #define DEFAULT_DLLNAME "libJitPI.so"
  45. void* m_libHandle = NULL;
  46. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  47. /* default location of JIT profiling agent on Android */
  48. #define ANDROID_JIT_AGENT_PATH "/data/intel/libittnotify.so"
  49. /* the function pointers */
  50. typedef unsigned int(*TPInitialize)(void);
  51. static TPInitialize FUNC_Initialize=NULL;
  52. typedef unsigned int(*TPNotify)(unsigned int, void*);
  53. static TPNotify FUNC_NotifyEvent=NULL;
  54. static iJIT_IsProfilingActiveFlags executionMode = iJIT_NOTHING_RUNNING;
  55. /* end collector dll part. */
  56. /* loadiJIT_Funcs() : this function is called just in the beginning
  57. * and is responsible to load the functions from BistroJavaCollector.dll
  58. * result:
  59. * on success: the functions loads, iJIT_DLL_is_missing=0, return value = 1
  60. * on failure: the functions are NULL, iJIT_DLL_is_missing=1, return value = 0
  61. */
  62. static int loadiJIT_Funcs(void);
  63. /* global representing whether the BistroJavaCollector can't be loaded */
  64. static int iJIT_DLL_is_missing = 0;
  65. /* Virtual stack - the struct is used as a virtual stack for each thread.
  66. * Every thread initializes with a stack of size INIT_TOP_STACK.
  67. * Every method entry decreases from the current stack point,
  68. * and when a thread stack reaches its top of stack (return from the global
  69. * function), the top of stack and the current stack increase. Notice that
  70. * when returning from a function the stack pointer is the address of
  71. * the function return.
  72. */
  73. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  74. static DWORD threadLocalStorageHandle = 0;
  75. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  76. static pthread_key_t threadLocalStorageHandle = (pthread_key_t)0;
  77. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  78. #define INIT_TOP_Stack 10000
  79. typedef struct
  80. {
  81. unsigned int TopStack;
  82. unsigned int CurrentStack;
  83. } ThreadStack, *pThreadStack;
  84. /* end of virtual stack. */
  85. /*
  86. * The function for reporting virtual-machine related events to VTune.
  87. * Note: when reporting iJVM_EVENT_TYPE_ENTER_NIDS, there is no need to fill
  88. * in the stack_id field in the iJIT_Method_NIDS structure, as VTune fills it.
  89. * The return value in iJVM_EVENT_TYPE_ENTER_NIDS &&
  90. * iJVM_EVENT_TYPE_LEAVE_NIDS events will be 0 in case of failure.
  91. * in iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED event
  92. * it will be -1 if EventSpecificData == 0 otherwise it will be 0.
  93. */
  94. ITT_EXTERN_C int JITAPI
  95. iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData)
  96. {
  97. int ReturnValue;
  98. /*
  99. * This section is for debugging outside of VTune.
  100. * It creates the environment variables that indicates call graph mode.
  101. * If running outside of VTune remove the remark.
  102. *
  103. *
  104. * static int firstTime = 1;
  105. * char DoCallGraph[12] = "DoCallGraph";
  106. * if (firstTime)
  107. * {
  108. * firstTime = 0;
  109. * SetEnvironmentVariable( "BISTRO_COLLECTORS_DO_CALLGRAPH", DoCallGraph);
  110. * }
  111. *
  112. * end of section.
  113. */
  114. /* initialization part - the functions have not been loaded yet. This part
  115. * will load the functions, and check if we are in Call Graph mode.
  116. * (for special treatment).
  117. */
  118. if (!FUNC_NotifyEvent)
  119. {
  120. if (iJIT_DLL_is_missing)
  121. return 0;
  122. /* load the Function from the DLL */
  123. if (!loadiJIT_Funcs())
  124. return 0;
  125. /* Call Graph initialization. */
  126. }
  127. /* If the event is method entry/exit, check that in the current mode
  128. * VTune is allowed to receive it
  129. */
  130. if ((event_type == iJVM_EVENT_TYPE_ENTER_NIDS ||
  131. event_type == iJVM_EVENT_TYPE_LEAVE_NIDS) &&
  132. (executionMode != iJIT_CALLGRAPH_ON))
  133. {
  134. return 0;
  135. }
  136. /* This section is performed when method enter event occurs.
  137. * It updates the virtual stack, or creates it if this is the first
  138. * method entry in the thread. The stack pointer is decreased.
  139. */
  140. if (event_type == iJVM_EVENT_TYPE_ENTER_NIDS)
  141. {
  142. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  143. pThreadStack threadStack =
  144. (pThreadStack)TlsGetValue (threadLocalStorageHandle);
  145. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  146. pThreadStack threadStack =
  147. (pThreadStack)pthread_getspecific(threadLocalStorageHandle);
  148. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  149. /* check for use of reserved method IDs */
  150. if ( ((piJIT_Method_NIDS) EventSpecificData)->method_id <= 999 )
  151. return 0;
  152. if (!threadStack)
  153. {
  154. /* initialize the stack. */
  155. threadStack = (pThreadStack) calloc (sizeof(ThreadStack), 1);
  156. threadStack->TopStack = INIT_TOP_Stack;
  157. threadStack->CurrentStack = INIT_TOP_Stack;
  158. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  159. TlsSetValue(threadLocalStorageHandle,(void*)threadStack);
  160. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  161. pthread_setspecific(threadLocalStorageHandle,(void*)threadStack);
  162. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  163. }
  164. /* decrease the stack. */
  165. ((piJIT_Method_NIDS) EventSpecificData)->stack_id =
  166. (threadStack->CurrentStack)--;
  167. }
  168. /* This section is performed when method leave event occurs
  169. * It updates the virtual stack.
  170. * Increases the stack pointer.
  171. * If the stack pointer reached the top (left the global function)
  172. * increase the pointer and the top pointer.
  173. */
  174. if (event_type == iJVM_EVENT_TYPE_LEAVE_NIDS)
  175. {
  176. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  177. pThreadStack threadStack =
  178. (pThreadStack)TlsGetValue (threadLocalStorageHandle);
  179. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  180. pThreadStack threadStack =
  181. (pThreadStack)pthread_getspecific(threadLocalStorageHandle);
  182. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  183. /* check for use of reserved method IDs */
  184. if ( ((piJIT_Method_NIDS) EventSpecificData)->method_id <= 999 )
  185. return 0;
  186. if (!threadStack)
  187. {
  188. /* Error: first report in this thread is method exit */
  189. exit (1);
  190. }
  191. ((piJIT_Method_NIDS) EventSpecificData)->stack_id =
  192. ++(threadStack->CurrentStack) + 1;
  193. if (((piJIT_Method_NIDS) EventSpecificData)->stack_id
  194. > threadStack->TopStack)
  195. ((piJIT_Method_NIDS) EventSpecificData)->stack_id =
  196. (unsigned int)-1;
  197. }
  198. if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED)
  199. {
  200. /* check for use of reserved method IDs */
  201. if ( ((piJIT_Method_Load) EventSpecificData)->method_id <= 999 )
  202. return 0;
  203. }
  204. ReturnValue = (int)FUNC_NotifyEvent(event_type, EventSpecificData);
  205. return ReturnValue;
  206. }
  207. /* The new mode call back routine */
  208. ITT_EXTERN_C void JITAPI
  209. iJIT_RegisterCallbackEx(void *userdata, iJIT_ModeChangedEx
  210. NewModeCallBackFuncEx)
  211. {
  212. /* is it already missing... or the load of functions from the DLL failed */
  213. if (iJIT_DLL_is_missing || !loadiJIT_Funcs())
  214. {
  215. /* then do not bother with notifications */
  216. NewModeCallBackFuncEx(userdata, iJIT_NO_NOTIFICATIONS);
  217. /* Error: could not load JIT functions. */
  218. return;
  219. }
  220. /* nothing to do with the callback */
  221. }
  222. /*
  223. * This function allows the user to query in which mode, if at all,
  224. *VTune is running
  225. */
  226. ITT_EXTERN_C iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive()
  227. {
  228. if (!iJIT_DLL_is_missing)
  229. {
  230. loadiJIT_Funcs();
  231. }
  232. return executionMode;
  233. }
  234. /* this function loads the collector dll (BistroJavaCollector)
  235. * and the relevant functions.
  236. * on success: all functions load, iJIT_DLL_is_missing = 0, return value = 1
  237. * on failure: all functions are NULL, iJIT_DLL_is_missing = 1, return value = 0
  238. */
  239. static int loadiJIT_Funcs()
  240. {
  241. static int bDllWasLoaded = 0;
  242. char *dllName = (char*)rcsid; /* !! Just to avoid unused code elimination */
  243. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  244. DWORD dNameLength = 0;
  245. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  246. if(bDllWasLoaded)
  247. {
  248. /* dll was already loaded, no need to do it for the second time */
  249. return 1;
  250. }
  251. /* Assumes that the DLL will not be found */
  252. iJIT_DLL_is_missing = 1;
  253. FUNC_NotifyEvent = NULL;
  254. if (m_libHandle)
  255. {
  256. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  257. FreeLibrary(m_libHandle);
  258. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  259. dlclose(m_libHandle);
  260. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  261. m_libHandle = NULL;
  262. }
  263. /* Try to get the dll name from the environment */
  264. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  265. dNameLength = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR, NULL, 0);
  266. if (dNameLength)
  267. {
  268. DWORD envret = 0;
  269. dllName = (char*)malloc(sizeof(char) * (dNameLength + 1));
  270. envret = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR,
  271. dllName, dNameLength);
  272. if (envret)
  273. {
  274. /* Try to load the dll from the PATH... */
  275. m_libHandle = LoadLibraryExA(dllName,
  276. NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
  277. }
  278. free(dllName);
  279. } else {
  280. /* Try to use old VS_PROFILER variable */
  281. dNameLength = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR, NULL, 0);
  282. if (dNameLength)
  283. {
  284. DWORD envret = 0;
  285. dllName = (char*)malloc(sizeof(char) * (dNameLength + 1));
  286. envret = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR,
  287. dllName, dNameLength);
  288. if (envret)
  289. {
  290. /* Try to load the dll from the PATH... */
  291. m_libHandle = LoadLibraryA(dllName);
  292. }
  293. free(dllName);
  294. }
  295. }
  296. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  297. dllName = getenv(NEW_DLL_ENVIRONMENT_VAR);
  298. if (!dllName)
  299. dllName = getenv(DLL_ENVIRONMENT_VAR);
  300. #ifdef ANDROID
  301. if (!dllName)
  302. dllName = ANDROID_JIT_AGENT_PATH;
  303. #endif
  304. if (dllName)
  305. {
  306. /* Try to load the dll from the PATH... */
  307. m_libHandle = dlopen(dllName, RTLD_LAZY);
  308. }
  309. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  310. if (!m_libHandle)
  311. {
  312. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  313. m_libHandle = LoadLibraryA(DEFAULT_DLLNAME);
  314. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  315. m_libHandle = dlopen(DEFAULT_DLLNAME, RTLD_LAZY);
  316. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  317. }
  318. /* if the dll wasn't loaded - exit. */
  319. if (!m_libHandle)
  320. {
  321. iJIT_DLL_is_missing = 1; /* don't try to initialize
  322. * JIT agent the second time
  323. */
  324. return 0;
  325. }
  326. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  327. FUNC_NotifyEvent = (TPNotify)GetProcAddress(m_libHandle, "NotifyEvent");
  328. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  329. FUNC_NotifyEvent = (TPNotify)(intptr_t)dlsym(m_libHandle, "NotifyEvent");
  330. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  331. if (!FUNC_NotifyEvent)
  332. {
  333. FUNC_Initialize = NULL;
  334. return 0;
  335. }
  336. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  337. FUNC_Initialize = (TPInitialize)GetProcAddress(m_libHandle, "Initialize");
  338. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  339. FUNC_Initialize = (TPInitialize)(intptr_t)dlsym(m_libHandle, "Initialize");
  340. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  341. if (!FUNC_Initialize)
  342. {
  343. FUNC_NotifyEvent = NULL;
  344. return 0;
  345. }
  346. executionMode = (iJIT_IsProfilingActiveFlags)FUNC_Initialize();
  347. bDllWasLoaded = 1;
  348. iJIT_DLL_is_missing = 0; /* DLL is ok. */
  349. /*
  350. * Call Graph mode: init the thread local storage
  351. * (need to store the virtual stack there).
  352. */
  353. if ( executionMode == iJIT_CALLGRAPH_ON )
  354. {
  355. /* Allocate a thread local storage slot for the thread "stack" */
  356. if (!threadLocalStorageHandle)
  357. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  358. threadLocalStorageHandle = TlsAlloc();
  359. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  360. pthread_key_create(&threadLocalStorageHandle, NULL);
  361. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  362. }
  363. return 1;
  364. }
  365. /*
  366. * This function should be called by the user whenever a thread ends,
  367. * to free the thread "virtual stack" storage
  368. */
  369. ITT_EXTERN_C void JITAPI FinalizeThread()
  370. {
  371. if (threadLocalStorageHandle)
  372. {
  373. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  374. pThreadStack threadStack =
  375. (pThreadStack)TlsGetValue (threadLocalStorageHandle);
  376. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  377. pThreadStack threadStack =
  378. (pThreadStack)pthread_getspecific(threadLocalStorageHandle);
  379. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  380. if (threadStack)
  381. {
  382. free (threadStack);
  383. threadStack = NULL;
  384. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  385. TlsSetValue (threadLocalStorageHandle, threadStack);
  386. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  387. pthread_setspecific(threadLocalStorageHandle, threadStack);
  388. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  389. }
  390. }
  391. }
  392. /*
  393. * This function should be called by the user when the process ends,
  394. * to free the local storage index
  395. */
  396. ITT_EXTERN_C void JITAPI FinalizeProcess()
  397. {
  398. if (m_libHandle)
  399. {
  400. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  401. FreeLibrary(m_libHandle);
  402. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  403. dlclose(m_libHandle);
  404. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  405. m_libHandle = NULL;
  406. }
  407. if (threadLocalStorageHandle)
  408. #if ITT_PLATFORM==ITT_PLATFORM_WIN
  409. TlsFree (threadLocalStorageHandle);
  410. #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  411. pthread_key_delete(threadLocalStorageHandle);
  412. #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
  413. }
  414. /*
  415. * This function should be called by the user for any method once.
  416. * The function will return a unique method ID, the user should maintain
  417. * the ID for each method
  418. */
  419. ITT_EXTERN_C unsigned int JITAPI iJIT_GetNewMethodID()
  420. {
  421. static unsigned int methodID = 0x100000;
  422. if (methodID == 0)
  423. return 0; /* ERROR : this is not a valid value */
  424. return methodID++;
  425. }