brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.4 KiB · 50d64d7 Raw
481 lines · c
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-exception6 *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 LLVM13 * source base since  this is a piece of code shared from Intel(R)14 * products.  Please do not reformat / re-style this code to make15 * subsequent merges and contributions from the original source base eaiser.16 *17 *===----------------------------------------------------------------------===*/18#include "ittnotify_config.h"19 20#if ITT_PLATFORM==ITT_PLATFORM_WIN21#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 32static const char rcsid[] = "\n@(#) $Revision: 243501 $\n";33 34#define DLL_ENVIRONMENT_VAR             "VS_PROFILER"35 36#ifndef NEW_DLL_ENVIRONMENT_VAR37#if ITT_ARCH==ITT_ARCH_IA3238#define NEW_DLL_ENVIRONMENT_VAR	        "INTEL_JIT_PROFILER32"39#else40#define NEW_DLL_ENVIRONMENT_VAR	        "INTEL_JIT_PROFILER64"41#endif42#endif /* NEW_DLL_ENVIRONMENT_VAR */43 44#if ITT_PLATFORM==ITT_PLATFORM_WIN45#define DEFAULT_DLLNAME                 "JitPI.dll"46HINSTANCE m_libHandle = NULL;47#else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */48#define DEFAULT_DLLNAME                 "libJitPI.so"49void* 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 */56typedef unsigned int(*TPInitialize)(void);57static TPInitialize FUNC_Initialize=NULL;58 59typedef unsigned int(*TPNotify)(unsigned int, void*);60static TPNotify FUNC_NotifyEvent=NULL;61 62static 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.dll68 * result:69 *  on success: the functions loads, iJIT_DLL_is_missing=0, return value = 170 *  on failure: the functions are NULL, iJIT_DLL_is_missing=1, return value = 071 */ 72static int loadiJIT_Funcs(void);73 74/* global representing whether the BistroJavaCollector can't be loaded */75static 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_WIN86static DWORD threadLocalStorageHandle = 0;87#else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */88static pthread_key_t threadLocalStorageHandle = (pthread_key_t)0;89#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */90 91#define INIT_TOP_Stack 1000092 93typedef 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 111ITT_EXTERN_C int JITAPI 112iJIT_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 part134     *        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 it151     */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_WIN165        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_WIN183            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 occurs195     * 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_WIN203        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 */242ITT_EXTERN_C void JITAPI 243iJIT_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 running260 */261ITT_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 = 1274 * on failure: all functions are NULL, iJIT_DLL_is_missing = 1, return value = 0275 */ 276static 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_WIN281    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_WIN297        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_WIN306    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 ANDROID342    if (!dllName)343        dllName = ANDROID_JIT_AGENT_PATH;344#endif345    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_WIN355        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_WIN371    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_WIN382    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 storage399     * (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_WIN406            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" storage418 */419ITT_EXTERN_C void JITAPI FinalizeThread(void)420{421    if (threadLocalStorageHandle)422    {423#if ITT_PLATFORM==ITT_PLATFORM_WIN424        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_WIN435            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 index446*/447ITT_EXTERN_C void JITAPI FinalizeProcess(void)448{449    if (m_libHandle) 450    {451#if ITT_PLATFORM==ITT_PLATFORM_WIN452        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_WIN461        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 method471 */472ITT_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