src/share/vm/prims/jvmtiCodeBlobEvents.cpp

changeset 1988
65b0c03b165d
parent 1971
38e8278318ca
child 2004
a528509c992b
     1.1 --- a/src/share/vm/prims/jvmtiCodeBlobEvents.cpp	Tue Jun 29 16:09:57 2010 -0700
     1.2 +++ b/src/share/vm/prims/jvmtiCodeBlobEvents.cpp	Fri Jul 02 15:01:47 2010 -0700
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -118,34 +118,13 @@
    1.11    for (int i=0; i<_global_code_blobs->length(); i++) {
    1.12      JvmtiCodeBlobDesc* scb = _global_code_blobs->at(i);
    1.13      if (addr == scb->code_begin()) {
    1.14 +      ShouldNotReachHere();
    1.15        return;
    1.16      }
    1.17    }
    1.18  
    1.19 -  // we must name the CodeBlob - some CodeBlobs already have names :-
    1.20 -  // - stubs used by compiled code to call a (static) C++ runtime routine
    1.21 -  // - non-relocatable machine code such as the interpreter, stubroutines, etc.
    1.22 -  // - various singleton blobs
    1.23 -  //
    1.24 -  // others are unnamed so we create a name :-
    1.25 -  // - OSR adapter (interpreter frame that has been on-stack replaced)
    1.26 -  // - I2C and C2I adapters
    1.27 -  const char* name = NULL;
    1.28 -  if (cb->is_runtime_stub()) {
    1.29 -    name = ((RuntimeStub*)cb)->name();
    1.30 -  }
    1.31 -  if (cb->is_buffer_blob()) {
    1.32 -    name = ((BufferBlob*)cb)->name();
    1.33 -  }
    1.34 -  if (cb->is_deoptimization_stub() || cb->is_safepoint_stub()) {
    1.35 -    name = ((SingletonBlob*)cb)->name();
    1.36 -  }
    1.37 -  if (cb->is_uncommon_trap_stub() || cb->is_exception_stub()) {
    1.38 -    name = ((SingletonBlob*)cb)->name();
    1.39 -  }
    1.40 -
    1.41    // record the CodeBlob details as a JvmtiCodeBlobDesc
    1.42 -  JvmtiCodeBlobDesc* scb = new JvmtiCodeBlobDesc(name, cb->instructions_begin(),
    1.43 +  JvmtiCodeBlobDesc* scb = new JvmtiCodeBlobDesc(cb->name(), cb->instructions_begin(),
    1.44                                                   cb->instructions_end());
    1.45    _global_code_blobs->append(scb);
    1.46  }
    1.47 @@ -197,7 +176,10 @@
    1.48  jvmtiError JvmtiCodeBlobEvents::generate_dynamic_code_events(JvmtiEnv* env) {
    1.49    CodeBlobCollector collector;
    1.50  
    1.51 -  // first collect all the code blobs
    1.52 +  // First collect all the code blobs.  This has to be done in a
    1.53 +  // single pass over the code cache with CodeCache_lock held because
    1.54 +  // there isn't any safe way to iterate over regular CodeBlobs since
    1.55 +  // they can be freed at any point.
    1.56    {
    1.57      MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
    1.58      collector.collect();
    1.59 @@ -213,166 +195,28 @@
    1.60  }
    1.61  
    1.62  
    1.63 -// Support class to describe a nmethod in the CodeCache
    1.64 -
    1.65 -class nmethodDesc: public CHeapObj {
    1.66 - private:
    1.67 -  jmethodID _jmethod_id;
    1.68 -  address _code_begin;
    1.69 -  address _code_end;
    1.70 -  jvmtiAddrLocationMap* _map;
    1.71 -  jint _map_length;
    1.72 - public:
    1.73 -  nmethodDesc(jmethodID jmethod_id, address code_begin, address code_end,
    1.74 -              jvmtiAddrLocationMap* map, jint map_length) {
    1.75 -    _jmethod_id = jmethod_id;
    1.76 -    _code_begin = code_begin;
    1.77 -    _code_end = code_end;
    1.78 -    _map = map;
    1.79 -    _map_length = map_length;
    1.80 -  }
    1.81 -  jmethodID jmethod_id() const          { return _jmethod_id; }
    1.82 -  address code_begin() const            { return _code_begin; }
    1.83 -  address code_end() const              { return _code_end; }
    1.84 -  jvmtiAddrLocationMap* map() const     { return _map; }
    1.85 -  jint map_length() const               { return _map_length; }
    1.86 -};
    1.87 -
    1.88 -
    1.89 -// Support class to collect a list of the nmethod CodeBlobs in
    1.90 -// the CodeCache.
    1.91 -//
    1.92 -// Usage :-
    1.93 -//
    1.94 -// nmethodCollector collector;
    1.95 -//
    1.96 -// collector.collect();
    1.97 -// JvmtiCodeBlobDesc* blob = collector.first();
    1.98 -// while (blob != NULL) {
    1.99 -//   :
   1.100 -//   blob = collector.next();
   1.101 -// }
   1.102 -//
   1.103 -class nmethodCollector : StackObj {
   1.104 - private:
   1.105 -  GrowableArray<nmethodDesc*>* _nmethods;           // collect nmethods
   1.106 -  int _pos;                                         // iteration support
   1.107 -
   1.108 -  // used during a collection
   1.109 -  static GrowableArray<nmethodDesc*>* _global_nmethods;
   1.110 -  static void do_nmethod(nmethod* nm);
   1.111 - public:
   1.112 -  nmethodCollector() {
   1.113 -    _nmethods = NULL;
   1.114 -    _pos = -1;
   1.115 -  }
   1.116 -  ~nmethodCollector() {
   1.117 -    if (_nmethods != NULL) {
   1.118 -      for (int i=0; i<_nmethods->length(); i++) {
   1.119 -        nmethodDesc* blob = _nmethods->at(i);
   1.120 -        if (blob->map()!= NULL) {
   1.121 -          FREE_C_HEAP_ARRAY(jvmtiAddrLocationMap, blob->map());
   1.122 -        }
   1.123 -      }
   1.124 -      delete _nmethods;
   1.125 -    }
   1.126 -  }
   1.127 -
   1.128 -  // collect list of nmethods in the cache
   1.129 -  void collect();
   1.130 -
   1.131 -  // iteration support - return first code blob
   1.132 -  nmethodDesc* first() {
   1.133 -    assert(_nmethods != NULL, "not collected");
   1.134 -    if (_nmethods->length() == 0) {
   1.135 -      return NULL;
   1.136 -    }
   1.137 -    _pos = 0;
   1.138 -    return _nmethods->at(0);
   1.139 -  }
   1.140 -
   1.141 -  // iteration support - return next code blob
   1.142 -  nmethodDesc* next() {
   1.143 -    assert(_pos >= 0, "iteration not started");
   1.144 -    if (_pos+1 >= _nmethods->length()) {
   1.145 -      return NULL;
   1.146 -    }
   1.147 -    return _nmethods->at(++_pos);
   1.148 -  }
   1.149 -};
   1.150 -
   1.151 -// used during collection
   1.152 -GrowableArray<nmethodDesc*>* nmethodCollector::_global_nmethods;
   1.153 -
   1.154 -
   1.155 -// called for each nmethod in the CodeCache
   1.156 -//
   1.157 -// This function simply adds a descriptor for each nmethod to the global list.
   1.158 -
   1.159 -void nmethodCollector::do_nmethod(nmethod* nm) {
   1.160 -  // ignore zombies
   1.161 -  if (!nm->is_alive()) {
   1.162 -    return;
   1.163 -  }
   1.164 -
   1.165 -  assert(nm->method() != NULL, "checking");
   1.166 -
   1.167 -  // create the location map for the nmethod.
   1.168 -  jvmtiAddrLocationMap* map;
   1.169 -  jint map_length;
   1.170 -  JvmtiCodeBlobEvents::build_jvmti_addr_location_map(nm, &map, &map_length);
   1.171 -
   1.172 -  // record the nmethod details
   1.173 -  nmethodDesc* snm = new nmethodDesc(nm->get_and_cache_jmethod_id(),
   1.174 -                                     nm->code_begin(),
   1.175 -                                     nm->code_end(),
   1.176 -                                     map,
   1.177 -                                     map_length);
   1.178 -  _global_nmethods->append(snm);
   1.179 -}
   1.180 -
   1.181 -// collects a list of nmethod in the CodeCache.
   1.182 -//
   1.183 -// The created list is growable array of nmethodDesc - each one describes
   1.184 -// a nmethod and includs its JVMTI address location map.
   1.185 -
   1.186 -void nmethodCollector::collect() {
   1.187 -  assert_locked_or_safepoint(CodeCache_lock);
   1.188 -  assert(_global_nmethods == NULL, "checking");
   1.189 -
   1.190 -  // create the list
   1.191 -  _global_nmethods = new (ResourceObj::C_HEAP) GrowableArray<nmethodDesc*>(100,true);
   1.192 -
   1.193 -  // any a descriptor for each nmethod to the list.
   1.194 -  CodeCache::nmethods_do(do_nmethod);
   1.195 -
   1.196 -  // make the list the instance list
   1.197 -  _nmethods = _global_nmethods;
   1.198 -  _global_nmethods = NULL;
   1.199 -}
   1.200 -
   1.201  // Generate a COMPILED_METHOD_LOAD event for each nnmethod
   1.202 -
   1.203  jvmtiError JvmtiCodeBlobEvents::generate_compiled_method_load_events(JvmtiEnv* env) {
   1.204    HandleMark hm;
   1.205 -  nmethodCollector collector;
   1.206  
   1.207 -  // first collect all nmethods
   1.208 -  {
   1.209 -    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   1.210 -    collector.collect();
   1.211 -  }
   1.212 +  // Walk the CodeCache notifying for live nmethods.  The code cache
   1.213 +  // may be changing while this is happening which is ok since newly
   1.214 +  // created nmethod will notify normally and nmethods which are freed
   1.215 +  // can be safely skipped.
   1.216 +  MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   1.217 +  nmethod* current = CodeCache::first_nmethod();
   1.218 +  while (current != NULL) {
   1.219 +    // Lock the nmethod so it can't be freed
   1.220 +    nmethodLocker nml(current);
   1.221  
   1.222 -  // iterate over the  list and post an event for each nmethod
   1.223 -  nmethodDesc* nm_desc = collector.first();
   1.224 -  while (nm_desc != NULL) {
   1.225 -    jmethodID mid = nm_desc->jmethod_id();
   1.226 -    assert(mid != NULL, "checking");
   1.227 -    JvmtiExport::post_compiled_method_load(env, mid,
   1.228 -                                           (jint)(nm_desc->code_end() - nm_desc->code_begin()),
   1.229 -                                           nm_desc->code_begin(), nm_desc->map_length(),
   1.230 -                                           nm_desc->map());
   1.231 -    nm_desc = collector.next();
   1.232 +    // Only notify for live nmethods
   1.233 +    if (current->is_alive()) {
   1.234 +      // Don't hold the lock over the notify or jmethodID creation
   1.235 +      MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   1.236 +      current->get_and_cache_jmethod_id();
   1.237 +      JvmtiExport::post_compiled_method_load(current);
   1.238 +    }
   1.239 +    current = CodeCache::next_nmethod(current);
   1.240    }
   1.241    return JVMTI_ERROR_NONE;
   1.242  }

mercurial