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 }