1 /*
   2  * Copyright 2003-2009 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  *
  23  */
  24 
  25 # include "incls/_precompiled.incl"
  26 # include "incls/_jvmtiCodeBlobEvents.cpp.incl"
  27 
  28 // Support class to collect a list of the non-nmethod CodeBlobs in
  29 // the CodeCache.
  30 //
  31 // This class actually creates a list of JvmtiCodeBlobDesc - each JvmtiCodeBlobDesc
  32 // describes a single CodeBlob in the CodeCache. Note that collection is
  33 // done to a static list - this is because CodeCache::blobs_do is defined
  34 // as void CodeCache::blobs_do(void f(CodeBlob* nm)) and hence requires
  35 // a C or static method.
  36 //
  37 // Usage :-
  38 //
  39 // CodeBlobCollector collector;
  40 //
  41 // collector.collect();
  42 // JvmtiCodeBlobDesc* blob = collector.first();
  43 // while (blob != NULL) {
  44 //   :
  45 //   blob = collector.next();
  46 // }
  47 //
  48 
  49 class CodeBlobCollector : StackObj {
  50  private:
  51   GrowableArray<JvmtiCodeBlobDesc*>* _code_blobs;   // collected blobs
  52   int _pos;                                         // iterator position
  53 
  54   // used during a collection
  55   static GrowableArray<JvmtiCodeBlobDesc*>* _global_code_blobs;
  56   static void do_blob(CodeBlob* cb);
  57  public:
  58   CodeBlobCollector() {
  59     _code_blobs = NULL;
  60     _pos = -1;
  61   }
  62   ~CodeBlobCollector() {
  63     if (_code_blobs != NULL) {
  64       for (int i=0; i<_code_blobs->length(); i++) {
  65         FreeHeap(_code_blobs->at(i));
  66       }
  67       delete _code_blobs;
  68     }
  69   }
  70 
  71   // collect list of code blobs in the cache
  72   void collect();
  73 
  74   // iteration support - return first code blob
  75   JvmtiCodeBlobDesc* first() {
  76     assert(_code_blobs != NULL, "not collected");
  77     if (_code_blobs->length() == 0) {
  78       return NULL;
  79     }
  80     _pos = 0;
  81     return _code_blobs->at(0);
  82   }
  83 
  84   // iteration support - return next code blob
  85   JvmtiCodeBlobDesc* next() {
  86     assert(_pos >= 0, "iteration not started");
  87     if (_pos+1 >= _code_blobs->length()) {
  88       return NULL;
  89     }
  90     return _code_blobs->at(++_pos);
  91   }
  92 
  93 };
  94 
  95 // used during collection
  96 GrowableArray<JvmtiCodeBlobDesc*>* CodeBlobCollector::_global_code_blobs;
  97 
  98 
  99 // called for each CodeBlob in the CodeCache
 100 //
 101 // This function filters out nmethods as it is only interested in
 102 // other CodeBlobs. This function also filters out CodeBlobs that have
 103 // a duplicate starting address as previous blobs. This is needed to
 104 // handle the case where multiple stubs are generated into a single
 105 // BufferBlob.
 106 
 107 void CodeBlobCollector::do_blob(CodeBlob* cb) {
 108 
 109   // ignore nmethods
 110   if (cb->is_nmethod()) {
 111     return;
 112   }
 113 
 114   // check if this starting address has been seen already - the
 115   // assumption is that stubs are inserted into the list before the
 116   // enclosing BufferBlobs.
 117   address addr = cb->instructions_begin();
 118   for (int i=0; i<_global_code_blobs->length(); i++) {
 119     JvmtiCodeBlobDesc* scb = _global_code_blobs->at(i);
 120     if (addr == scb->code_begin()) {
 121       return;
 122     }
 123   }
 124 
 125   // we must name the CodeBlob - some CodeBlobs already have names :-
 126   // - stubs used by compiled code to call a (static) C++ runtime routine
 127   // - non-relocatable machine code such as the interpreter, stubroutines, etc.
 128   // - various singleton blobs
 129   //
 130   // others are unnamed so we create a name :-
 131   // - OSR adapter (interpreter frame that has been on-stack replaced)
 132   // - I2C and C2I adapters
 133   const char* name = NULL;
 134   if (cb->is_runtime_stub()) {
 135     name = ((RuntimeStub*)cb)->name();
 136   }
 137   if (cb->is_buffer_blob()) {
 138     name = ((BufferBlob*)cb)->name();
 139   }
 140   if (cb->is_deoptimization_stub() || cb->is_safepoint_stub()) {
 141     name = ((SingletonBlob*)cb)->name();
 142   }
 143   if (cb->is_uncommon_trap_stub() || cb->is_exception_stub()) {
 144     name = ((SingletonBlob*)cb)->name();
 145   }
 146 
 147   // record the CodeBlob details as a JvmtiCodeBlobDesc
 148   JvmtiCodeBlobDesc* scb = new JvmtiCodeBlobDesc(name, cb->instructions_begin(),
 149                                                  cb->instructions_end());
 150   _global_code_blobs->append(scb);
 151 }
 152 
 153 
 154 // collects a list of CodeBlobs in the CodeCache.
 155 //
 156 // The created list is growable array of JvmtiCodeBlobDesc - each one describes
 157 // a CodeBlob. Note that the list is static - this is because CodeBlob::blobs_do
 158 // requires a a C or static function so we can't use an instance function. This
 159 // isn't a problem as the iteration is serial anyway as we need the CodeCache_lock
 160 // to iterate over the code cache.
 161 //
 162 // Note that the CodeBlobs in the CodeCache will include BufferBlobs that may
 163 // contain multiple stubs. As a profiler is interested in the stubs rather than
 164 // the enclosing container we first iterate over the stub code descriptors so
 165 // that the stubs go into the list first. do_blob will then filter out the
 166 // enclosing blobs if the starting address of the enclosing blobs matches the
 167 // starting address of first stub generated in the enclosing blob.
 168 
 169 void CodeBlobCollector::collect() {
 170   assert_locked_or_safepoint(CodeCache_lock);
 171   assert(_global_code_blobs == NULL, "checking");
 172 
 173   // create the global list
 174   _global_code_blobs = new (ResourceObj::C_HEAP) GrowableArray<JvmtiCodeBlobDesc*>(50,true);
 175 
 176   // iterate over the stub code descriptors and put them in the list first.
 177   int index = 0;
 178   StubCodeDesc* desc;
 179   while ((desc = StubCodeDesc::desc_for_index(++index)) != NULL) {
 180     _global_code_blobs->append(new JvmtiCodeBlobDesc(desc->name(), desc->begin(), desc->end()));
 181   }
 182 
 183   // next iterate over all the non-nmethod code blobs and add them to
 184   // the list - as noted above this will filter out duplicates and
 185   // enclosing blobs.
 186   CodeCache::blobs_do(do_blob);
 187 
 188   // make the global list the instance list so that it can be used
 189   // for other iterations.
 190   _code_blobs = _global_code_blobs;
 191   _global_code_blobs = NULL;
 192 }
 193 
 194 
 195 // Generate a DYNAMIC_CODE_GENERATED event for each non-nmethod code blob.
 196 
 197 jvmtiError JvmtiCodeBlobEvents::generate_dynamic_code_events(JvmtiEnv* env) {
 198   CodeBlobCollector collector;
 199 
 200   // first collect all the code blobs
 201   {
 202     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 203     collector.collect();
 204   }
 205 
 206   // iterate over the collected list and post an event for each blob
 207   JvmtiCodeBlobDesc* blob = collector.first();
 208   while (blob != NULL) {
 209     JvmtiExport::post_dynamic_code_generated(env, blob->name(), blob->code_begin(), blob->code_end());
 210     blob = collector.next();
 211   }
 212   return JVMTI_ERROR_NONE;
 213 }
 214 
 215 
 216 // Support class to describe a nmethod in the CodeCache
 217 
 218 class nmethodDesc: public CHeapObj {
 219  private:
 220   methodHandle _method;
 221   address _code_begin;
 222   address _code_end;
 223   jvmtiAddrLocationMap* _map;
 224   jint _map_length;
 225  public:
 226   nmethodDesc(methodHandle method, address code_begin, address code_end,
 227               jvmtiAddrLocationMap* map, jint map_length) {
 228     _method = method;
 229     _code_begin = code_begin;
 230     _code_end = code_end;
 231     _map = map;
 232     _map_length = map_length;
 233   }
 234   methodHandle method() const           { return _method; }
 235   address code_begin() const            { return _code_begin; }
 236   address code_end() const              { return _code_end; }
 237   jvmtiAddrLocationMap* map() const     { return _map; }
 238   jint map_length() const               { return _map_length; }
 239 };
 240 
 241 
 242 // Support class to collect a list of the nmethod CodeBlobs in
 243 // the CodeCache.
 244 //
 245 // Usage :-
 246 //
 247 // nmethodCollector collector;
 248 //
 249 // collector.collect();
 250 // JvmtiCodeBlobDesc* blob = collector.first();
 251 // while (blob != NULL) {
 252 //   :
 253 //   blob = collector.next();
 254 // }
 255 //
 256 class nmethodCollector : StackObj {
 257  private:
 258   GrowableArray<nmethodDesc*>* _nmethods;           // collect nmethods
 259   int _pos;                                         // iteration support
 260 
 261   // used during a collection
 262   static GrowableArray<nmethodDesc*>* _global_nmethods;
 263   static void do_nmethod(nmethod* nm);
 264  public:
 265   nmethodCollector() {
 266     _nmethods = NULL;
 267     _pos = -1;
 268   }
 269   ~nmethodCollector() {
 270     if (_nmethods != NULL) {
 271       for (int i=0; i<_nmethods->length(); i++) {
 272         nmethodDesc* blob = _nmethods->at(i);
 273         if (blob->map()!= NULL) {
 274           FREE_C_HEAP_ARRAY(jvmtiAddrLocationMap, blob->map());
 275         }
 276       }
 277       delete _nmethods;
 278     }
 279   }
 280 
 281   // collect list of nmethods in the cache
 282   void collect();
 283 
 284   // iteration support - return first code blob
 285   nmethodDesc* first() {
 286     assert(_nmethods != NULL, "not collected");
 287     if (_nmethods->length() == 0) {
 288       return NULL;
 289     }
 290     _pos = 0;
 291     return _nmethods->at(0);
 292   }
 293 
 294   // iteration support - return next code blob
 295   nmethodDesc* next() {
 296     assert(_pos >= 0, "iteration not started");
 297     if (_pos+1 >= _nmethods->length()) {
 298       return NULL;
 299     }
 300     return _nmethods->at(++_pos);
 301   }
 302 };
 303 
 304 // used during collection
 305 GrowableArray<nmethodDesc*>* nmethodCollector::_global_nmethods;
 306 
 307 
 308 // called for each nmethod in the CodeCache
 309 //
 310 // This function simply adds a descriptor for each nmethod to the global list.
 311 
 312 void nmethodCollector::do_nmethod(nmethod* nm) {
 313   // ignore zombies
 314   if (!nm->is_alive()) {
 315     return;
 316   }
 317 
 318   assert(nm->method() != NULL, "checking");
 319 
 320   // create the location map for the nmethod.
 321   jvmtiAddrLocationMap* map;
 322   jint map_length;
 323   JvmtiCodeBlobEvents::build_jvmti_addr_location_map(nm, &map, &map_length);
 324 
 325   // record the nmethod details
 326   methodHandle mh(nm->method());
 327   nmethodDesc* snm = new nmethodDesc(mh,
 328                                      nm->code_begin(),
 329                                      nm->code_end(),
 330                                      map,
 331                                      map_length);
 332   _global_nmethods->append(snm);
 333 }
 334 
 335 // collects a list of nmethod in the CodeCache.
 336 //
 337 // The created list is growable array of nmethodDesc - each one describes
 338 // a nmethod and includs its JVMTI address location map.
 339 
 340 void nmethodCollector::collect() {
 341   assert_locked_or_safepoint(CodeCache_lock);
 342   assert(_global_nmethods == NULL, "checking");
 343 
 344   // create the list
 345   _global_nmethods = new (ResourceObj::C_HEAP) GrowableArray<nmethodDesc*>(100,true);
 346 
 347   // any a descriptor for each nmethod to the list.
 348   CodeCache::nmethods_do(do_nmethod);
 349 
 350   // make the list the instance list
 351   _nmethods = _global_nmethods;
 352   _global_nmethods = NULL;
 353 }
 354 
 355 // Generate a COMPILED_METHOD_LOAD event for each nnmethod
 356 
 357 jvmtiError JvmtiCodeBlobEvents::generate_compiled_method_load_events(JvmtiEnv* env) {
 358   HandleMark hm;
 359   nmethodCollector collector;
 360 
 361   // first collect all nmethods
 362   {
 363     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 364     collector.collect();
 365   }
 366 
 367   // iterate over the  list and post an event for each nmethod
 368   nmethodDesc* nm_desc = collector.first();
 369   while (nm_desc != NULL) {
 370     methodOop method = nm_desc->method()();
 371     jmethodID mid = method->jmethod_id();
 372     assert(mid != NULL, "checking");
 373     JvmtiExport::post_compiled_method_load(env, mid,
 374                                            (jint)(nm_desc->code_end() - nm_desc->code_begin()),
 375                                            nm_desc->code_begin(), nm_desc->map_length(),
 376                                            nm_desc->map());
 377     nm_desc = collector.next();
 378   }
 379   return JVMTI_ERROR_NONE;
 380 }
 381 
 382 
 383 // create a C-heap allocated address location map for an nmethod
 384 void JvmtiCodeBlobEvents::build_jvmti_addr_location_map(nmethod *nm,
 385                                                         jvmtiAddrLocationMap** map_ptr,
 386                                                         jint *map_length_ptr)
 387 {
 388   ResourceMark rm;
 389   jvmtiAddrLocationMap* map = NULL;
 390   jint map_length = 0;
 391 
 392 
 393   // Generate line numbers using PcDesc and ScopeDesc info
 394   methodHandle mh(nm->method());
 395 
 396   if (!mh->is_native()) {
 397     PcDesc *pcd;
 398     int pcds_in_method;
 399 
 400     pcds_in_method = (nm->scopes_pcs_end() - nm->scopes_pcs_begin());
 401     map = NEW_C_HEAP_ARRAY(jvmtiAddrLocationMap, pcds_in_method);
 402 
 403     address scopes_data = nm->scopes_data_begin();
 404     for( pcd = nm->scopes_pcs_begin(); pcd < nm->scopes_pcs_end(); ++pcd ) {
 405       ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute());
 406       ScopeDesc *sd  = &sc0;
 407       while( !sd->is_top() ) { sd = sd->sender(); }
 408       int bci = sd->bci();
 409       if (bci != InvocationEntryBci) {
 410         assert(map_length < pcds_in_method, "checking");
 411         map[map_length].start_address = (const void*)pcd->real_pc(nm);
 412         map[map_length].location = bci;
 413         ++map_length;
 414       }
 415     }
 416   }
 417 
 418   *map_ptr = map;
 419   *map_length_ptr = map_length;
 420 }