Index: src/third_party/vtune/jitprofiling.cc |
=================================================================== |
--- src/third_party/vtune/jitprofiling.cc (revision 0) |
+++ src/third_party/vtune/jitprofiling.cc (revision 0) |
@@ -0,0 +1,499 @@ |
+/* |
+ This file is provided under a dual BSD/GPLv2 license. When using or |
+ redistributing this file, you may do so under either license. |
+ |
+ GPL LICENSE SUMMARY |
+ |
+ Copyright(c) 2005-2012 Intel Corporation. All rights reserved. |
+ |
+ This program is free software; you can redistribute it and/or modify |
+ it under the terms of version 2 of the GNU General Public License as |
+ published by the Free Software Foundation. |
+ |
+ This program is distributed in the hope that it will be useful, but |
+ WITHOUT ANY WARRANTY; without even the implied warranty of |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
+ General Public License for more details. |
+ |
+ You should have received a copy of the GNU General Public License |
+ along with this program; if not, write to the Free Software |
+ Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |
+ The full GNU General Public License is included in this distribution |
+ in the file called LICENSE.GPL. |
+ |
+ Contact Information: |
+ http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/ |
+ |
+ BSD LICENSE |
+ |
+ Copyright(c) 2005-2012 Intel Corporation. All rights reserved. |
+ All rights reserved. |
+ |
+ Redistribution and use in source and binary forms, with or without |
+ modification, are permitted provided that the following conditions |
+ are met: |
+ |
+ * Redistributions of source code must retain the above copyright |
+ notice, this list of conditions and the following disclaimer. |
+ * Redistributions in binary form must reproduce the above copyright |
+ notice, this list of conditions and the following disclaimer in |
+ the documentation and/or other materials provided with the |
+ distribution. |
+ * Neither the name of Intel Corporation nor the names of its |
+ contributors may be used to endorse or promote products derived |
+ from this software without specific prior written permission. |
+ |
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+*/ |
+#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> |
+#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ |
+#include <malloc.h> |
+#include <stdlib.h> |
+ |
+#include "jitprofiling.h" |
+ |
+static const char rcsid[] = "\n@(#) $Revision: 234474 $\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; |
+} |
+ |
+ITT_EXTERN_C void JITAPI iJIT_RegisterCallbackEx(void *userdata, iJIT_ModeChangedEx NewModeCallBackFuncEx) // The new mode call back routine |
+{ |
+ // is it already missing... or the load of functions from the DLL failed |
+ if (iJIT_DLL_is_missing || !loadiJIT_Funcs()) |
+ { |
+ NewModeCallBackFuncEx(userdata, iJIT_NO_NOTIFICATIONS); // then do not bother with 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; |
+} |
+#include <stdio.h> |
+/* 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 = reinterpret_cast<TPNotify>(reinterpret_cast<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 = reinterpret_cast<TPInitialize>(reinterpret_cast<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(); |
+ if (executionMode != iJIT_SAMPLING_ON) |
+ executionMode = iJIT_SAMPLING_ON; |
+ |
+ 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++; |
+} |
+ |