xref: /PHP-8.0/ext/opcache/jit/vtune/jitprofiling.c (revision 3a2cc161)
1 /* <copyright>
2   This file is provided under a dual BSD/GPLv2 license.  When using or
3   redistributing this file, you may do so under either license.
4 
5   GPL LICENSE SUMMARY
6 
7   Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
8 
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of version 2 of the GNU General Public License as
11   published by the Free Software Foundation.
12 
13   This program is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   General Public License for more details.
17 
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21   The full GNU General Public License is included in this distribution
22   in the file called LICENSE.GPL.
23 
24   Contact Information:
25   http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/
26 
27   BSD LICENSE
28 
29   Copyright (c) 2005-2014 Intel Corporation. All rights reserved.
30   All rights reserved.
31 
32   Redistribution and use in source and binary forms, with or without
33   modification, are permitted provided that the following conditions
34   are met:
35 
36     * Redistributions of source code must retain the above copyright
37       notice, this list of conditions and the following disclaimer.
38     * Redistributions in binary form must reproduce the above copyright
39       notice, this list of conditions and the following disclaimer in
40       the documentation and/or other materials provided with the
41       distribution.
42     * Neither the name of Intel Corporation nor the names of its
43       contributors may be used to endorse or promote products derived
44       from this software without specific prior written permission.
45 
46   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
47   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
48   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
49   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
50   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
51   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
52   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
53   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
54   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
55   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
56   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57 </copyright> */
58 
59 #include "ittnotify_config.h"
60 
61 #if ITT_PLATFORM==ITT_PLATFORM_WIN
62 #include <windows.h>
63 #pragma optimize("", off)
64 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
65 #include <stdlib.h>
66 
67 #include "jitprofiling.h"
68 
69 static const char rcsid[] = "\n@(#) $Revision: 463960 $\n";
70 
71 #define DLL_ENVIRONMENT_VAR             "VS_PROFILER"
72 
73 #ifndef NEW_DLL_ENVIRONMENT_VAR
74 #if ITT_ARCH==ITT_ARCH_IA32
75 #define NEW_DLL_ENVIRONMENT_VAR	        "INTEL_JIT_PROFILER32"
76 #else
77 #define NEW_DLL_ENVIRONMENT_VAR	        "INTEL_JIT_PROFILER64"
78 #endif
79 #endif /* NEW_DLL_ENVIRONMENT_VAR */
80 
81 #if ITT_PLATFORM==ITT_PLATFORM_WIN
82 #define DEFAULT_DLLNAME                 "JitPI.dll"
83 HINSTANCE m_libHandle = NULL;
84 #elif ITT_PLATFORM==ITT_PLATFORM_MAC
85 #define DEFAULT_DLLNAME                 "libJitPI.dylib"
86 void* m_libHandle = NULL;
87 #else
88 #define DEFAULT_DLLNAME                 "libJitPI.so"
89 void* m_libHandle = NULL;
90 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
91 
92 /* default location of JIT profiling agent on Android */
93 #define ANDROID_JIT_AGENT_PATH  "/data/intel/libittnotify.so"
94 
95 /* the function pointers */
96 typedef unsigned int(JITAPI *TPInitialize)(void);
97 static TPInitialize FUNC_Initialize=NULL;
98 
99 typedef unsigned int(JITAPI *TPNotify)(unsigned int, void*);
100 static TPNotify FUNC_NotifyEvent=NULL;
101 
102 static iJIT_IsProfilingActiveFlags executionMode = iJIT_NOTHING_RUNNING;
103 
104 /* end collector dll part. */
105 
106 /* loadiJIT_Funcs() : this function is called just in the beginning
107  * and is responsible to load the functions from BistroJavaCollector.dll
108  * result:
109  *  on success: the functions loads, iJIT_DLL_is_missing=0, return value = 1
110  *  on failure: the functions are NULL, iJIT_DLL_is_missing=1, return value = 0
111  */
112 static int loadiJIT_Funcs(void);
113 
114 /* global representing whether the collector can't be loaded */
115 static int iJIT_DLL_is_missing = 0;
116 
117 ITT_EXTERN_C int JITAPI
iJIT_NotifyEvent(iJIT_JVM_EVENT event_type,void * EventSpecificData)118 iJIT_NotifyEvent(iJIT_JVM_EVENT event_type, void *EventSpecificData)
119 {
120     int ReturnValue;
121 
122     /* initialization part - the collector has not been loaded yet. */
123     if (!FUNC_NotifyEvent)
124     {
125         if (iJIT_DLL_is_missing)
126             return 0;
127 
128         if (!loadiJIT_Funcs())
129             return 0;
130     }
131 
132     if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED ||
133         event_type == iJVM_EVENT_TYPE_METHOD_UPDATE)
134     {
135         if (((piJIT_Method_Load)EventSpecificData)->method_id == 0)
136             return 0;
137     }
138     else if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2)
139     {
140         if (((piJIT_Method_Load_V2)EventSpecificData)->method_id == 0)
141             return 0;
142     }
143     else if (event_type == iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V3)
144     {
145         if (((piJIT_Method_Load_V3)EventSpecificData)->method_id == 0)
146             return 0;
147     }
148     else if (event_type == iJVM_EVENT_TYPE_METHOD_INLINE_LOAD_FINISHED)
149     {
150         if (((piJIT_Method_Inline_Load)EventSpecificData)->method_id == 0 ||
151             ((piJIT_Method_Inline_Load)EventSpecificData)->parent_method_id == 0)
152             return 0;
153     }
154 
155     ReturnValue = (int)FUNC_NotifyEvent(event_type, EventSpecificData);
156 
157     return ReturnValue;
158 }
159 
iJIT_IsProfilingActive()160 ITT_EXTERN_C iJIT_IsProfilingActiveFlags JITAPI iJIT_IsProfilingActive()
161 {
162     if (!iJIT_DLL_is_missing)
163     {
164         loadiJIT_Funcs();
165     }
166 
167     return executionMode;
168 }
169 
170 /* This function loads the collector dll and the relevant functions.
171  * on success: all functions load,     iJIT_DLL_is_missing = 0, return value = 1
172  * on failure: all functions are NULL, iJIT_DLL_is_missing = 1, return value = 0
173  */
loadiJIT_Funcs()174 static int loadiJIT_Funcs()
175 {
176     static int bDllWasLoaded = 0;
177     char *dllName = (char*)rcsid; /* !! Just to avoid unused code elimination */
178 #if ITT_PLATFORM==ITT_PLATFORM_WIN
179     DWORD dNameLength = 0;
180 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
181 
182     if(bDllWasLoaded)
183     {
184         /* dll was already loaded, no need to do it for the second time */
185         return 1;
186     }
187 
188     /* Assumes that the DLL will not be found */
189     iJIT_DLL_is_missing = 1;
190     FUNC_NotifyEvent = NULL;
191 
192     if (m_libHandle)
193     {
194 #if ITT_PLATFORM==ITT_PLATFORM_WIN
195         FreeLibrary(m_libHandle);
196 #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
197         dlclose(m_libHandle);
198 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
199         m_libHandle = NULL;
200     }
201 
202     /* Try to get the dll name from the environment */
203 #if ITT_PLATFORM==ITT_PLATFORM_WIN
204     dNameLength = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR, NULL, 0);
205     if (dNameLength)
206     {
207         DWORD envret = 0;
208         dllName = (char*)malloc(sizeof(char) * (dNameLength + 1));
209         if(dllName != NULL)
210         {
211             envret = GetEnvironmentVariableA(NEW_DLL_ENVIRONMENT_VAR,
212                                              dllName, dNameLength);
213             if (envret)
214             {
215                 /* Try to load the dll from the PATH... */
216                 m_libHandle = LoadLibraryExA(dllName,
217                                              NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
218             }
219             free(dllName);
220         }
221     } else {
222         /* Try to use old VS_PROFILER variable */
223         dNameLength = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR, NULL, 0);
224         if (dNameLength)
225         {
226             DWORD envret = 0;
227             dllName = (char*)malloc(sizeof(char) * (dNameLength + 1));
228             if(dllName != NULL)
229             {
230                 envret = GetEnvironmentVariableA(DLL_ENVIRONMENT_VAR,
231                                                  dllName, dNameLength);
232                 if (envret)
233                 {
234                     /* Try to load the dll from the PATH... */
235                     m_libHandle = LoadLibraryA(dllName);
236                 }
237                 free(dllName);
238             }
239         }
240     }
241 #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
242     dllName = getenv(NEW_DLL_ENVIRONMENT_VAR);
243     if (!dllName)
244         dllName = getenv(DLL_ENVIRONMENT_VAR);
245 #if defined(__ANDROID__) || defined(ANDROID)
246     if (!dllName)
247         dllName = ANDROID_JIT_AGENT_PATH;
248 #endif
249     if (dllName)
250     {
251         /* Try to load the dll from the PATH... */
252         m_libHandle = dlopen(dllName, RTLD_LAZY);
253     }
254 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
255 
256     if (!m_libHandle)
257     {
258 #if ITT_PLATFORM==ITT_PLATFORM_WIN
259         m_libHandle = LoadLibraryA(DEFAULT_DLLNAME);
260 #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
261         m_libHandle = dlopen(DEFAULT_DLLNAME, RTLD_LAZY);
262 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
263     }
264 
265     /* if the dll wasn't loaded - exit. */
266     if (!m_libHandle)
267     {
268         iJIT_DLL_is_missing = 1; /* don't try to initialize
269                                   * JIT agent the second time
270                                   */
271         return 0;
272     }
273 
274 #if ITT_PLATFORM==ITT_PLATFORM_WIN
275     FUNC_NotifyEvent = (TPNotify)GetProcAddress(m_libHandle, "NotifyEvent");
276 #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
277     FUNC_NotifyEvent = (TPNotify)dlsym(m_libHandle, "NotifyEvent");
278 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
279     if (!FUNC_NotifyEvent)
280     {
281         FUNC_Initialize = NULL;
282         return 0;
283     }
284 
285 #if ITT_PLATFORM==ITT_PLATFORM_WIN
286     FUNC_Initialize = (TPInitialize)GetProcAddress(m_libHandle, "Initialize");
287 #else  /* ITT_PLATFORM==ITT_PLATFORM_WIN */
288     FUNC_Initialize = (TPInitialize)dlsym(m_libHandle, "Initialize");
289 #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */
290     if (!FUNC_Initialize)
291     {
292         FUNC_NotifyEvent = NULL;
293         return 0;
294     }
295 
296     executionMode = (iJIT_IsProfilingActiveFlags)FUNC_Initialize();
297 
298     bDllWasLoaded = 1;
299     iJIT_DLL_is_missing = 0; /* DLL is ok. */
300 
301     return 1;
302 }
303 
iJIT_GetNewMethodID()304 ITT_EXTERN_C unsigned int JITAPI iJIT_GetNewMethodID()
305 {
306     static unsigned int methodID = 1;
307 
308     if (methodID == 0)
309         return 0;  /* ERROR : this is not a valid value */
310 
311     return methodID++;
312 }
313