hotspot/src/os/windows/vm/vtune_windows.cpp
changeset 5930 f172b22065d7
parent 5923 e133cd8675f7
parent 5929 279fd26a4b68
child 5931 9dfa2b7f8640
child 6060 f93277335d21
child 6063 50591d23b844
child 6171 726692f4de19
equal deleted inserted replaced
5923:e133cd8675f7 5930:f172b22065d7
     1 /*
       
     2  * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #include "incls/_precompiled.incl"
       
    26 #include "incls/_vtune_windows.cpp.incl"
       
    27 
       
    28 static int current_method_ID = 0;
       
    29 
       
    30 // ------------- iJITProf.h -------------------
       
    31 // defined by Intel -- do not change
       
    32 
       
    33 #include "windows.h"
       
    34 
       
    35 extern "C" {
       
    36   enum iJITP_Event {
       
    37     ExceptionOccurred_S,                  // Java exception
       
    38     ExceptionOccurred_IDS,
       
    39 
       
    40     Shutdown,                             // VM exit
       
    41 
       
    42     ThreadCreate,                         // threads
       
    43     ThreadDestroy,
       
    44     ThreadSwitch,
       
    45 
       
    46     ClassLoadStart,                       // class loading
       
    47     ClassLoadEnd,
       
    48 
       
    49     GCStart,                              // GC
       
    50     GCEnd,
       
    51 
       
    52     NMethodCreate = 13,                   // nmethod creation
       
    53     NMethodDelete
       
    54 
       
    55     // rest of event types omitted (call profiling not supported yet)
       
    56   };
       
    57 
       
    58   // version number -- 0 if VTune not installed
       
    59   int WINAPI iJitP_VersionNumber();
       
    60 
       
    61   enum iJITP_ModeFlags {
       
    62     NoNotification = 0x0,                // don't call vtune
       
    63     NotifyNMethodCreate   = 0x1,         // notify NMethod_Create
       
    64     NotifyNMethodDelete   = 0x2,         // notify NMethod_Create
       
    65     NotifyMethodEnter     = 0x4,         // method entry
       
    66     NotifyMethodExit      = 0x8,         // method exit
       
    67     NotifyShutdown        = 0x10,        // VM exit
       
    68     NotifyGC              = 0x20,        // GC
       
    69   };
       
    70 
       
    71   // call back function type
       
    72   typedef void (WINAPI *ModeChangedFn)(iJITP_ModeFlags flags);
       
    73 
       
    74   // -------------  VTune method interfaces ----------------------
       
    75   typedef void  (WINAPI *RegisterCallbackFn)(ModeChangedFn fn);   // register callback
       
    76   typedef int   (WINAPI *NotifyEventFn)(iJITP_Event, void* event_data);
       
    77 
       
    78   // specific event data structures
       
    79 
       
    80   // data for NMethodCreate
       
    81 
       
    82   struct VTuneObj {                       // base class for allocation
       
    83                                           // (can't use CHeapObj -- has vtable ptr)
       
    84     void* operator new(size_t size) { return os::malloc(size); }
       
    85     void  operator delete(void* p)  { fatal("never delete VTune data"); }
       
    86   };
       
    87 
       
    88   struct LineNumberInfo : VTuneObj {      // PC-to-line number mapping
       
    89     unsigned long offset;                 // byte offset from start of method
       
    90     unsigned long line_num;               // corresponding line number
       
    91   };
       
    92 
       
    93   struct MethodLoadInfo : VTuneObj {
       
    94     unsigned long methodID;               // unique method ID
       
    95     const char* name;                     // method name
       
    96     unsigned long instr_start;            // start address
       
    97     unsigned long instr_size;             // length in bytes
       
    98     unsigned long line_number_size;       // size of line number table
       
    99     LineNumberInfo* line_number_table;    // line number mapping
       
   100     unsigned long classID;                // unique class ID
       
   101     char* class_file_name;                // fully qualified class file name
       
   102     char* source_file_name;               // fully qualified source file name
       
   103 
       
   104     MethodLoadInfo(nmethod* nm);          // for real nmethods
       
   105     MethodLoadInfo(const char* vm_name, address start, address end);
       
   106                                           // for "nmethods" like stubs, interpreter, etc
       
   107 
       
   108   };
       
   109 
       
   110   // data for NMethodDelete
       
   111   struct MethodInfo : VTuneObj {
       
   112     unsigned long methodID;               // unique method ID
       
   113     unsigned long classID;                // (added for convenience -- not part of Intel interface)
       
   114 
       
   115     MethodInfo(methodOop m);
       
   116   };
       
   117 };
       
   118 
       
   119 MethodInfo::MethodInfo(methodOop m) {
       
   120   // just give it a new ID -- we're not compiling methods twice (usually)
       
   121   // (and even if we did, one might want to see the two versions separately)
       
   122   methodID = ++current_method_ID;
       
   123 }
       
   124 
       
   125 MethodLoadInfo::MethodLoadInfo(const char* vm_name, address start, address end) {
       
   126   classID  = 0;
       
   127   methodID = ++current_method_ID;
       
   128   name = vm_name;
       
   129   instr_start = (unsigned long)start;
       
   130   instr_size = end - start;
       
   131   line_number_size = 0;
       
   132   line_number_table = NULL;
       
   133   class_file_name = source_file_name = "HotSpot JVM";
       
   134 }
       
   135 
       
   136 MethodLoadInfo::MethodLoadInfo(nmethod* nm) {
       
   137   methodOop m = nm->method();
       
   138   MethodInfo info(m);
       
   139   classID  = info.classID;
       
   140   methodID = info.methodID;
       
   141   name = strdup(m->name()->as_C_string());
       
   142   instr_start = (unsigned long)nm->instructions_begin();
       
   143   instr_size = nm->code_size();
       
   144   line_number_size = 0;
       
   145   line_number_table = NULL;
       
   146   klassOop kl = m->method_holder();
       
   147   char* class_name = Klass::cast(kl)->name()->as_C_string();
       
   148   char* file_name = NEW_C_HEAP_ARRAY(char, strlen(class_name) + 1);
       
   149   strcpy(file_name, class_name);
       
   150   class_file_name = file_name;
       
   151   char* src_name = NEW_C_HEAP_ARRAY(char, strlen(class_name) + strlen(".java") + 1);
       
   152   strcpy(src_name, class_name);
       
   153   strcat(src_name, ".java");
       
   154   source_file_name = src_name;
       
   155 }
       
   156 
       
   157 // --------------------- DLL loading functions ------------------------
       
   158 
       
   159 #define DLLNAME "iJitProf.dll"
       
   160 
       
   161 static HINSTANCE load_lib(char* name) {
       
   162   HINSTANCE lib = NULL;
       
   163   HKEY hk;
       
   164 
       
   165   // try to get VTune directory from the registry
       
   166   if (RegOpenKey(HKEY_CURRENT_USER, "Software\\VB and VBA Program Settings\\VTune\\StartUp", &hk) == ERROR_SUCCESS) {
       
   167     for (int i = 0; true; i++) {
       
   168       char szName[MAX_PATH + 1];
       
   169       char szVal [MAX_PATH + 1];
       
   170       DWORD cbName, cbVal;
       
   171 
       
   172       cbName = cbVal = MAX_PATH + 1;
       
   173       if (RegEnumValue(hk, i, szName, &cbName, NULL, NULL, (LPBYTE)szVal, &cbVal) == ERROR_SUCCESS) {
       
   174         // get VTune directory
       
   175         if (!strcmp(szName, name)) {
       
   176           char*p = szVal;
       
   177           while (*p == ' ') p++;    // trim
       
   178           char* q = p + strlen(p) - 1;
       
   179           while (*q == ' ') *(q--) = '\0';
       
   180 
       
   181           // chdir to the VTune dir
       
   182           GetCurrentDirectory(MAX_PATH + 1, szName);
       
   183           SetCurrentDirectory(p);
       
   184           // load lib
       
   185           lib = LoadLibrary(strcat(strcat(p, "\\"), DLLNAME));
       
   186           if (lib != NULL && WizardMode) tty->print_cr("*loaded VTune DLL %s", p);
       
   187           // restore current dir
       
   188           SetCurrentDirectory(szName);
       
   189           break;
       
   190         }
       
   191       } else {
       
   192         break;
       
   193       }
       
   194     }
       
   195   }
       
   196   return lib;
       
   197 }
       
   198 
       
   199 static RegisterCallbackFn iJIT_RegisterCallback = NULL;
       
   200 static NotifyEventFn      iJIT_NotifyEvent      = NULL;
       
   201 
       
   202 static bool load_iJIT_funcs() {
       
   203   // first try to load from PATH
       
   204   HINSTANCE lib = LoadLibrary(DLLNAME);
       
   205   if (lib != NULL && WizardMode) tty->print_cr("*loaded VTune DLL %s via PATH", DLLNAME);
       
   206 
       
   207   // if not successful, try to look in the VTUNE directory
       
   208   if (lib == NULL) lib = load_lib("VTUNEDIR30");
       
   209   if (lib == NULL) lib = load_lib("VTUNEDIR25");
       
   210   if (lib == NULL) lib = load_lib("VTUNEDIR");
       
   211 
       
   212   if (lib == NULL) return false;    // unsuccessful
       
   213 
       
   214   // try to load the functions
       
   215   iJIT_RegisterCallback = (RegisterCallbackFn)GetProcAddress(lib, "iJIT_RegisterCallback");
       
   216   iJIT_NotifyEvent      = (NotifyEventFn)     GetProcAddress(lib, "iJIT_NotifyEvent");
       
   217 
       
   218   if (!iJIT_RegisterCallback) tty->print_cr("*couldn't find VTune entry point iJIT_RegisterCallback");
       
   219   if (!iJIT_NotifyEvent)      tty->print_cr("*couldn't find VTune entry point iJIT_NotifyEvent");
       
   220   return iJIT_RegisterCallback != NULL && iJIT_NotifyEvent != NULL;
       
   221 }
       
   222 
       
   223 // --------------------- VTune class ------------------------
       
   224 
       
   225 static bool active = false;
       
   226 static int  flags  = 0;
       
   227 
       
   228 void VTune::start_GC() {
       
   229   if (active && (flags & NotifyGC)) iJIT_NotifyEvent(GCStart, NULL);
       
   230 }
       
   231 
       
   232 void VTune::end_GC() {
       
   233   if (active && (flags & NotifyGC)) iJIT_NotifyEvent(GCEnd, NULL);
       
   234 }
       
   235 
       
   236 void VTune::start_class_load() {
       
   237   // not yet implemented in VTune
       
   238 }
       
   239 
       
   240 void VTune::end_class_load() {
       
   241   // not yet implemented in VTune
       
   242 }
       
   243 
       
   244 void VTune::exit() {
       
   245   if (active && (flags & NotifyShutdown)) iJIT_NotifyEvent(Shutdown, NULL);
       
   246 }
       
   247 
       
   248 void VTune::register_stub(const char* name, address start, address end) {
       
   249   if (flags & NotifyNMethodCreate) {
       
   250     MethodLoadInfo* info = new MethodLoadInfo(name, start, end);
       
   251     if (PrintMiscellaneous && WizardMode && Verbose) {
       
   252       tty->print_cr("NMethodCreate %s (%d): %#x..%#x", info->name, info->methodID,
       
   253                     info->instr_start, info->instr_start + info->instr_size);
       
   254     }
       
   255     iJIT_NotifyEvent(NMethodCreate, info);
       
   256   }
       
   257 }
       
   258 
       
   259 void VTune::create_nmethod(nmethod* nm) {
       
   260   if (flags & NotifyNMethodCreate) {
       
   261     MethodLoadInfo* info = new MethodLoadInfo(nm);
       
   262     if (PrintMiscellaneous && WizardMode && Verbose) {
       
   263       tty->print_cr("NMethodCreate %s (%d): %#x..%#x", info->name, info->methodID,
       
   264                     info->instr_start, info->instr_start + info->instr_size);
       
   265     }
       
   266     iJIT_NotifyEvent(NMethodCreate, info);
       
   267   }
       
   268 }
       
   269 
       
   270 void VTune::delete_nmethod(nmethod* nm) {
       
   271   if (flags & NotifyNMethodDelete) {
       
   272     MethodInfo* info = new MethodInfo(nm->method());
       
   273     iJIT_NotifyEvent(NMethodDelete, info);
       
   274   }
       
   275 }
       
   276 
       
   277 static void set_flags(int new_flags) {
       
   278   flags = new_flags;
       
   279   // if (WizardMode) tty->print_cr("*new VTune flags: %#x", flags);
       
   280 }
       
   281 
       
   282 void vtune_init() {
       
   283   if (!UseVTune) return;
       
   284   active = load_iJIT_funcs();
       
   285   if (active) {
       
   286     iJIT_RegisterCallback((ModeChangedFn)set_flags);
       
   287   } else {
       
   288     assert(flags == 0, "flags shouldn't be set");
       
   289   }
       
   290 }