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