Wed, 07 Jul 2010 12:40:01 -0700
Merge
1.1 --- a/src/share/vm/opto/callnode.cpp Wed Jun 30 11:52:10 2010 -0400 1.2 +++ b/src/share/vm/opto/callnode.cpp Wed Jul 07 12:40:01 2010 -0700 1.3 @@ -1524,7 +1524,7 @@ 1.4 ConnectionGraph *cgr = phase->C->congraph(); 1.5 PointsToNode::EscapeState es = PointsToNode::GlobalEscape; 1.6 if (cgr != NULL) 1.7 - es = cgr->escape_state(obj_node(), phase); 1.8 + es = cgr->escape_state(obj_node()); 1.9 if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) { 1.10 // Mark it eliminated to update any counters 1.11 this->set_eliminated(); 1.12 @@ -1627,7 +1627,7 @@ 1.13 ConnectionGraph *cgr = phase->C->congraph(); 1.14 PointsToNode::EscapeState es = PointsToNode::GlobalEscape; 1.15 if (cgr != NULL) 1.16 - es = cgr->escape_state(obj_node(), phase); 1.17 + es = cgr->escape_state(obj_node()); 1.18 if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) { 1.19 // Mark it eliminated to update any counters 1.20 this->set_eliminated();
2.1 --- a/src/share/vm/opto/compile.cpp Wed Jun 30 11:52:10 2010 -0400 2.2 +++ b/src/share/vm/opto/compile.cpp Wed Jul 07 12:40:01 2010 -0700 2.3 @@ -637,34 +637,6 @@ 2.4 if (failing()) return; 2.5 NOT_PRODUCT( verify_graph_edges(); ) 2.6 2.7 - // Perform escape analysis 2.8 - if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) { 2.9 - TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true); 2.10 - // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction. 2.11 - PhaseGVN* igvn = initial_gvn(); 2.12 - Node* oop_null = igvn->zerocon(T_OBJECT); 2.13 - Node* noop_null = igvn->zerocon(T_NARROWOOP); 2.14 - 2.15 - _congraph = new(comp_arena()) ConnectionGraph(this); 2.16 - bool has_non_escaping_obj = _congraph->compute_escape(); 2.17 - 2.18 -#ifndef PRODUCT 2.19 - if (PrintEscapeAnalysis) { 2.20 - _congraph->dump(); 2.21 - } 2.22 -#endif 2.23 - // Cleanup. 2.24 - if (oop_null->outcnt() == 0) 2.25 - igvn->hash_delete(oop_null); 2.26 - if (noop_null->outcnt() == 0) 2.27 - igvn->hash_delete(noop_null); 2.28 - 2.29 - if (!has_non_escaping_obj) { 2.30 - _congraph = NULL; 2.31 - } 2.32 - 2.33 - if (failing()) return; 2.34 - } 2.35 // Now optimize 2.36 Optimize(); 2.37 if (failing()) return; 2.38 @@ -1601,6 +1573,20 @@ 2.39 2.40 if (failing()) return; 2.41 2.42 + // Perform escape analysis 2.43 + if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) { 2.44 + TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true); 2.45 + ConnectionGraph::do_analysis(this, &igvn); 2.46 + 2.47 + if (failing()) return; 2.48 + 2.49 + igvn.optimize(); 2.50 + print_method("Iter GVN 3", 2); 2.51 + 2.52 + if (failing()) return; 2.53 + 2.54 + } 2.55 + 2.56 // Loop transforms on the ideal graph. Range Check Elimination, 2.57 // peeling, unrolling, etc. 2.58
3.1 --- a/src/share/vm/opto/compile.hpp Wed Jun 30 11:52:10 2010 -0400 3.2 +++ b/src/share/vm/opto/compile.hpp Wed Jul 07 12:40:01 2010 -0700 3.3 @@ -362,6 +362,7 @@ 3.4 Node* macro_node(int idx) { return _macro_nodes->at(idx); } 3.5 Node* predicate_opaque1_node(int idx) { return _predicate_opaqs->at(idx);} 3.6 ConnectionGraph* congraph() { return _congraph;} 3.7 + void set_congraph(ConnectionGraph* congraph) { _congraph = congraph;} 3.8 void add_macro_node(Node * n) { 3.9 //assert(n->is_macro(), "must be a macro node"); 3.10 assert(!_macro_nodes->contains(n), " duplicate entry in expand list");
4.1 --- a/src/share/vm/opto/escape.cpp Wed Jun 30 11:52:10 2010 -0400 4.2 +++ b/src/share/vm/opto/escape.cpp Wed Jul 07 12:40:01 2010 -0700 4.3 @@ -81,18 +81,18 @@ 4.4 } 4.5 #endif 4.6 4.7 -ConnectionGraph::ConnectionGraph(Compile * C) : 4.8 +ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) : 4.9 _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()), 4.10 _processed(C->comp_arena()), 4.11 _collecting(true), 4.12 _compile(C), 4.13 + _igvn(igvn), 4.14 _node_map(C->comp_arena()) { 4.15 4.16 _phantom_object = C->top()->_idx, 4.17 add_node(C->top(), PointsToNode::JavaObject, PointsToNode::GlobalEscape,true); 4.18 4.19 // Add ConP(#NULL) and ConN(#NULL) nodes. 4.20 - PhaseGVN* igvn = C->initial_gvn(); 4.21 Node* oop_null = igvn->zerocon(T_OBJECT); 4.22 _oop_null = oop_null->_idx; 4.23 assert(_oop_null < C->unique(), "should be created already"); 4.24 @@ -182,7 +182,7 @@ 4.25 _processed.set(n->_idx); 4.26 } 4.27 4.28 -PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n, PhaseTransform *phase) { 4.29 +PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n) { 4.30 uint idx = n->_idx; 4.31 PointsToNode::EscapeState es; 4.32 4.33 @@ -207,22 +207,26 @@ 4.34 if (n->uncast()->_idx >= nodes_size()) 4.35 return PointsToNode::UnknownEscape; 4.36 4.37 + PointsToNode::EscapeState orig_es = es; 4.38 + 4.39 // compute max escape state of anything this node could point to 4.40 VectorSet ptset(Thread::current()->resource_area()); 4.41 - PointsTo(ptset, n, phase); 4.42 + PointsTo(ptset, n); 4.43 for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) { 4.44 uint pt = i.elem; 4.45 PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state(); 4.46 if (pes > es) 4.47 es = pes; 4.48 } 4.49 - // cache the computed escape state 4.50 - assert(es != PointsToNode::UnknownEscape, "should have computed an escape state"); 4.51 - ptnode_adr(idx)->set_escape_state(es); 4.52 + if (orig_es != es) { 4.53 + // cache the computed escape state 4.54 + assert(es != PointsToNode::UnknownEscape, "should have computed an escape state"); 4.55 + ptnode_adr(idx)->set_escape_state(es); 4.56 + } // orig_es could be PointsToNode::UnknownEscape 4.57 return es; 4.58 } 4.59 4.60 -void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase) { 4.61 +void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) { 4.62 VectorSet visited(Thread::current()->resource_area()); 4.63 GrowableArray<uint> worklist; 4.64 4.65 @@ -990,7 +994,7 @@ 4.66 GrowableArray<Node *> memnode_worklist; 4.67 GrowableArray<PhiNode *> orig_phis; 4.68 4.69 - PhaseGVN *igvn = _compile->initial_gvn(); 4.70 + PhaseGVN *igvn = _igvn; 4.71 uint new_index_start = (uint) _compile->num_alias_types(); 4.72 Arena* arena = Thread::current()->resource_area(); 4.73 VectorSet visited(arena); 4.74 @@ -1012,7 +1016,7 @@ 4.75 CallNode *alloc = n->as_Call(); 4.76 // copy escape information to call node 4.77 PointsToNode* ptn = ptnode_adr(alloc->_idx); 4.78 - PointsToNode::EscapeState es = escape_state(alloc, igvn); 4.79 + PointsToNode::EscapeState es = escape_state(alloc); 4.80 // We have an allocation or call which returns a Java object, 4.81 // see if it is unescaped. 4.82 if (es != PointsToNode::NoEscape || !ptn->_scalar_replaceable) 4.83 @@ -1123,7 +1127,7 @@ 4.84 } 4.85 } else if (n->is_AddP()) { 4.86 ptset.Clear(); 4.87 - PointsTo(ptset, get_addp_base(n), igvn); 4.88 + PointsTo(ptset, get_addp_base(n)); 4.89 assert(ptset.Size() == 1, "AddP address is unique"); 4.90 uint elem = ptset.getelem(); // Allocation node's index 4.91 if (elem == _phantom_object) { 4.92 @@ -1143,7 +1147,7 @@ 4.93 continue; // already processed 4.94 } 4.95 ptset.Clear(); 4.96 - PointsTo(ptset, n, igvn); 4.97 + PointsTo(ptset, n); 4.98 if (ptset.Size() == 1) { 4.99 uint elem = ptset.getelem(); // Allocation node's index 4.100 if (elem == _phantom_object) { 4.101 @@ -1478,6 +1482,26 @@ 4.102 return false; 4.103 } 4.104 4.105 +void ConnectionGraph::do_analysis(Compile *C, PhaseIterGVN *igvn) { 4.106 + // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction 4.107 + // to create space for them in ConnectionGraph::_nodes[]. 4.108 + Node* oop_null = igvn->zerocon(T_OBJECT); 4.109 + Node* noop_null = igvn->zerocon(T_NARROWOOP); 4.110 + 4.111 + ConnectionGraph* congraph = new(C->comp_arena()) ConnectionGraph(C, igvn); 4.112 + // Perform escape analysis 4.113 + if (congraph->compute_escape()) { 4.114 + // There are non escaping objects. 4.115 + C->set_congraph(congraph); 4.116 + } 4.117 + 4.118 + // Cleanup. 4.119 + if (oop_null->outcnt() == 0) 4.120 + igvn->hash_delete(oop_null); 4.121 + if (noop_null->outcnt() == 0) 4.122 + igvn->hash_delete(noop_null); 4.123 +} 4.124 + 4.125 bool ConnectionGraph::compute_escape() { 4.126 Compile* C = _compile; 4.127 4.128 @@ -1492,7 +1516,7 @@ 4.129 } 4.130 4.131 GrowableArray<int> cg_worklist; 4.132 - PhaseGVN* igvn = C->initial_gvn(); 4.133 + PhaseGVN* igvn = _igvn; 4.134 bool has_allocations = false; 4.135 4.136 // Push all useful nodes onto CG list and set their type. 4.137 @@ -1661,6 +1685,12 @@ 4.138 _collecting = false; 4.139 assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build"); 4.140 4.141 +#ifndef PRODUCT 4.142 + if (PrintEscapeAnalysis) { 4.143 + dump(); // Dump ConnectionGraph 4.144 + } 4.145 +#endif 4.146 + 4.147 bool has_scalar_replaceable_candidates = alloc_worklist.length() > 0; 4.148 if ( has_scalar_replaceable_candidates && 4.149 C->AliasLevel() >= 3 && EliminateAllocations ) { 4.150 @@ -1671,10 +1701,6 @@ 4.151 4.152 if (C->failing()) return false; 4.153 4.154 - // Clean up after split unique types. 4.155 - ResourceMark rm; 4.156 - PhaseRemoveUseless pru(C->initial_gvn(), C->for_igvn()); 4.157 - 4.158 C->print_method("After Escape Analysis", 2); 4.159 4.160 #ifdef ASSERT 4.161 @@ -1711,7 +1737,7 @@ 4.162 int offset = ptn->offset(); 4.163 Node* base = get_addp_base(n); 4.164 ptset.Clear(); 4.165 - PointsTo(ptset, base, phase); 4.166 + PointsTo(ptset, base); 4.167 int ptset_size = ptset.Size(); 4.168 4.169 // Check if a oop field's initializing value is recorded and add 4.170 @@ -1889,7 +1915,7 @@ 4.171 arg = get_addp_base(arg); 4.172 } 4.173 ptset.Clear(); 4.174 - PointsTo(ptset, arg, phase); 4.175 + PointsTo(ptset, arg); 4.176 for( VectorSetI j(&ptset); j.test(); ++j ) { 4.177 uint pt = j.elem; 4.178 set_escape_state(pt, PointsToNode::ArgEscape); 4.179 @@ -1934,7 +1960,7 @@ 4.180 } 4.181 4.182 ptset.Clear(); 4.183 - PointsTo(ptset, arg, phase); 4.184 + PointsTo(ptset, arg); 4.185 for( VectorSetI j(&ptset); j.test(); ++j ) { 4.186 uint pt = j.elem; 4.187 if (global_escapes) { 4.188 @@ -1970,7 +1996,7 @@ 4.189 Node *arg = call->in(i)->uncast(); 4.190 set_escape_state(arg->_idx, PointsToNode::GlobalEscape); 4.191 ptset.Clear(); 4.192 - PointsTo(ptset, arg, phase); 4.193 + PointsTo(ptset, arg); 4.194 for( VectorSetI j(&ptset); j.test(); ++j ) { 4.195 uint pt = j.elem; 4.196 set_escape_state(pt, PointsToNode::GlobalEscape); 4.197 @@ -2433,7 +2459,7 @@ 4.198 Node *base = get_addp_base(n); 4.199 // Create a field edge to this node from everything base could point to. 4.200 VectorSet ptset(Thread::current()->resource_area()); 4.201 - PointsTo(ptset, base, phase); 4.202 + PointsTo(ptset, base); 4.203 for( VectorSetI i(&ptset); i.test(); ++i ) { 4.204 uint pt = i.elem; 4.205 add_field_edge(pt, n_idx, address_offset(n, phase)); 4.206 @@ -2501,7 +2527,7 @@ 4.207 // For everything "adr_base" could point to, create a deferred edge from 4.208 // this node to each field with the same offset. 4.209 VectorSet ptset(Thread::current()->resource_area()); 4.210 - PointsTo(ptset, adr_base, phase); 4.211 + PointsTo(ptset, adr_base); 4.212 int offset = address_offset(adr, phase); 4.213 for( VectorSetI i(&ptset); i.test(); ++i ) { 4.214 uint pt = i.elem; 4.215 @@ -2594,7 +2620,7 @@ 4.216 // For everything "adr_base" could point to, create a deferred edge 4.217 // to "val" from each field with the same offset. 4.218 VectorSet ptset(Thread::current()->resource_area()); 4.219 - PointsTo(ptset, adr_base, phase); 4.220 + PointsTo(ptset, adr_base); 4.221 for( VectorSetI i(&ptset); i.test(); ++i ) { 4.222 uint pt = i.elem; 4.223 add_edge_from_fields(pt, val->_idx, address_offset(adr, phase)); 4.224 @@ -2638,7 +2664,6 @@ 4.225 4.226 #ifndef PRODUCT 4.227 void ConnectionGraph::dump() { 4.228 - PhaseGVN *igvn = _compile->initial_gvn(); 4.229 bool first = true; 4.230 4.231 uint size = nodes_size(); 4.232 @@ -2648,7 +2673,7 @@ 4.233 4.234 if (ptn_type != PointsToNode::JavaObject || ptn->_node == NULL) 4.235 continue; 4.236 - PointsToNode::EscapeState es = escape_state(ptn->_node, igvn); 4.237 + PointsToNode::EscapeState es = escape_state(ptn->_node); 4.238 if (ptn->_node->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) { 4.239 if (first) { 4.240 tty->cr();
5.1 --- a/src/share/vm/opto/escape.hpp Wed Jun 30 11:52:10 2010 -0400 5.2 +++ b/src/share/vm/opto/escape.hpp Wed Jul 07 12:40:01 2010 -0700 5.3 @@ -227,6 +227,7 @@ 5.4 uint _noop_null; // ConN(#NULL) 5.5 5.6 Compile * _compile; // Compile object for current compilation 5.7 + PhaseIterGVN * _igvn; // Value numbering 5.8 5.9 // Address of an element in _nodes. Used when the element is to be modified 5.10 PointsToNode *ptnode_adr(uint idx) const { 5.11 @@ -257,7 +258,7 @@ 5.12 // walk the connection graph starting at the node corresponding to "n" and 5.13 // add the index of everything it could point to, to "ptset". This may cause 5.14 // Phi's encountered to get (re)processed (which requires "phase".) 5.15 - void PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase); 5.16 + void PointsTo(VectorSet &ptset, Node * n); 5.17 5.18 // Edge manipulation. The "from_i" and "to_i" arguments are the 5.19 // node indices of the source and destination of the edge 5.20 @@ -310,7 +311,7 @@ 5.21 // Node: This assumes that escape analysis is run before 5.22 // PhaseIterGVN creation 5.23 void record_for_optimizer(Node *n) { 5.24 - _compile->record_for_igvn(n); 5.25 + _igvn->_worklist.push(n); 5.26 } 5.27 5.28 // Set the escape state of a node 5.29 @@ -320,16 +321,20 @@ 5.30 void verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase); 5.31 5.32 public: 5.33 - ConnectionGraph(Compile *C); 5.34 + ConnectionGraph(Compile *C, PhaseIterGVN *igvn); 5.35 5.36 // Check for non-escaping candidates 5.37 static bool has_candidates(Compile *C); 5.38 5.39 + // Perform escape analysis 5.40 + static void do_analysis(Compile *C, PhaseIterGVN *igvn); 5.41 + 5.42 // Compute the escape information 5.43 bool compute_escape(); 5.44 5.45 // escape state of a node 5.46 - PointsToNode::EscapeState escape_state(Node *n, PhaseTransform *phase); 5.47 + PointsToNode::EscapeState escape_state(Node *n); 5.48 + 5.49 // other information we have collected 5.50 bool is_scalar_replaceable(Node *n) { 5.51 if (_collecting || (n->_idx >= nodes_size()))
6.1 --- a/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Wed Jun 30 11:52:10 2010 -0400 6.2 +++ b/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Wed Jul 07 12:40:01 2010 -0700 6.3 @@ -1,5 +1,5 @@ 6.4 /* 6.5 - * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved. 6.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 6.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.8 * 6.9 * This code is free software; you can redistribute it and/or modify it 6.10 @@ -118,34 +118,13 @@ 6.11 for (int i=0; i<_global_code_blobs->length(); i++) { 6.12 JvmtiCodeBlobDesc* scb = _global_code_blobs->at(i); 6.13 if (addr == scb->code_begin()) { 6.14 + ShouldNotReachHere(); 6.15 return; 6.16 } 6.17 } 6.18 6.19 - // we must name the CodeBlob - some CodeBlobs already have names :- 6.20 - // - stubs used by compiled code to call a (static) C++ runtime routine 6.21 - // - non-relocatable machine code such as the interpreter, stubroutines, etc. 6.22 - // - various singleton blobs 6.23 - // 6.24 - // others are unnamed so we create a name :- 6.25 - // - OSR adapter (interpreter frame that has been on-stack replaced) 6.26 - // - I2C and C2I adapters 6.27 - const char* name = NULL; 6.28 - if (cb->is_runtime_stub()) { 6.29 - name = ((RuntimeStub*)cb)->name(); 6.30 - } 6.31 - if (cb->is_buffer_blob()) { 6.32 - name = ((BufferBlob*)cb)->name(); 6.33 - } 6.34 - if (cb->is_deoptimization_stub() || cb->is_safepoint_stub()) { 6.35 - name = ((SingletonBlob*)cb)->name(); 6.36 - } 6.37 - if (cb->is_uncommon_trap_stub() || cb->is_exception_stub()) { 6.38 - name = ((SingletonBlob*)cb)->name(); 6.39 - } 6.40 - 6.41 // record the CodeBlob details as a JvmtiCodeBlobDesc 6.42 - JvmtiCodeBlobDesc* scb = new JvmtiCodeBlobDesc(name, cb->instructions_begin(), 6.43 + JvmtiCodeBlobDesc* scb = new JvmtiCodeBlobDesc(cb->name(), cb->instructions_begin(), 6.44 cb->instructions_end()); 6.45 _global_code_blobs->append(scb); 6.46 } 6.47 @@ -197,7 +176,10 @@ 6.48 jvmtiError JvmtiCodeBlobEvents::generate_dynamic_code_events(JvmtiEnv* env) { 6.49 CodeBlobCollector collector; 6.50 6.51 - // first collect all the code blobs 6.52 + // First collect all the code blobs. This has to be done in a 6.53 + // single pass over the code cache with CodeCache_lock held because 6.54 + // there isn't any safe way to iterate over regular CodeBlobs since 6.55 + // they can be freed at any point. 6.56 { 6.57 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 6.58 collector.collect(); 6.59 @@ -213,166 +195,28 @@ 6.60 } 6.61 6.62 6.63 -// Support class to describe a nmethod in the CodeCache 6.64 - 6.65 -class nmethodDesc: public CHeapObj { 6.66 - private: 6.67 - jmethodID _jmethod_id; 6.68 - address _code_begin; 6.69 - address _code_end; 6.70 - jvmtiAddrLocationMap* _map; 6.71 - jint _map_length; 6.72 - public: 6.73 - nmethodDesc(jmethodID jmethod_id, address code_begin, address code_end, 6.74 - jvmtiAddrLocationMap* map, jint map_length) { 6.75 - _jmethod_id = jmethod_id; 6.76 - _code_begin = code_begin; 6.77 - _code_end = code_end; 6.78 - _map = map; 6.79 - _map_length = map_length; 6.80 - } 6.81 - jmethodID jmethod_id() const { return _jmethod_id; } 6.82 - address code_begin() const { return _code_begin; } 6.83 - address code_end() const { return _code_end; } 6.84 - jvmtiAddrLocationMap* map() const { return _map; } 6.85 - jint map_length() const { return _map_length; } 6.86 -}; 6.87 - 6.88 - 6.89 -// Support class to collect a list of the nmethod CodeBlobs in 6.90 -// the CodeCache. 6.91 -// 6.92 -// Usage :- 6.93 -// 6.94 -// nmethodCollector collector; 6.95 -// 6.96 -// collector.collect(); 6.97 -// JvmtiCodeBlobDesc* blob = collector.first(); 6.98 -// while (blob != NULL) { 6.99 -// : 6.100 -// blob = collector.next(); 6.101 -// } 6.102 -// 6.103 -class nmethodCollector : StackObj { 6.104 - private: 6.105 - GrowableArray<nmethodDesc*>* _nmethods; // collect nmethods 6.106 - int _pos; // iteration support 6.107 - 6.108 - // used during a collection 6.109 - static GrowableArray<nmethodDesc*>* _global_nmethods; 6.110 - static void do_nmethod(nmethod* nm); 6.111 - public: 6.112 - nmethodCollector() { 6.113 - _nmethods = NULL; 6.114 - _pos = -1; 6.115 - } 6.116 - ~nmethodCollector() { 6.117 - if (_nmethods != NULL) { 6.118 - for (int i=0; i<_nmethods->length(); i++) { 6.119 - nmethodDesc* blob = _nmethods->at(i); 6.120 - if (blob->map()!= NULL) { 6.121 - FREE_C_HEAP_ARRAY(jvmtiAddrLocationMap, blob->map()); 6.122 - } 6.123 - } 6.124 - delete _nmethods; 6.125 - } 6.126 - } 6.127 - 6.128 - // collect list of nmethods in the cache 6.129 - void collect(); 6.130 - 6.131 - // iteration support - return first code blob 6.132 - nmethodDesc* first() { 6.133 - assert(_nmethods != NULL, "not collected"); 6.134 - if (_nmethods->length() == 0) { 6.135 - return NULL; 6.136 - } 6.137 - _pos = 0; 6.138 - return _nmethods->at(0); 6.139 - } 6.140 - 6.141 - // iteration support - return next code blob 6.142 - nmethodDesc* next() { 6.143 - assert(_pos >= 0, "iteration not started"); 6.144 - if (_pos+1 >= _nmethods->length()) { 6.145 - return NULL; 6.146 - } 6.147 - return _nmethods->at(++_pos); 6.148 - } 6.149 -}; 6.150 - 6.151 -// used during collection 6.152 -GrowableArray<nmethodDesc*>* nmethodCollector::_global_nmethods; 6.153 - 6.154 - 6.155 -// called for each nmethod in the CodeCache 6.156 -// 6.157 -// This function simply adds a descriptor for each nmethod to the global list. 6.158 - 6.159 -void nmethodCollector::do_nmethod(nmethod* nm) { 6.160 - // ignore zombies 6.161 - if (!nm->is_alive()) { 6.162 - return; 6.163 - } 6.164 - 6.165 - assert(nm->method() != NULL, "checking"); 6.166 - 6.167 - // create the location map for the nmethod. 6.168 - jvmtiAddrLocationMap* map; 6.169 - jint map_length; 6.170 - JvmtiCodeBlobEvents::build_jvmti_addr_location_map(nm, &map, &map_length); 6.171 - 6.172 - // record the nmethod details 6.173 - nmethodDesc* snm = new nmethodDesc(nm->get_and_cache_jmethod_id(), 6.174 - nm->code_begin(), 6.175 - nm->code_end(), 6.176 - map, 6.177 - map_length); 6.178 - _global_nmethods->append(snm); 6.179 -} 6.180 - 6.181 -// collects a list of nmethod in the CodeCache. 6.182 -// 6.183 -// The created list is growable array of nmethodDesc - each one describes 6.184 -// a nmethod and includs its JVMTI address location map. 6.185 - 6.186 -void nmethodCollector::collect() { 6.187 - assert_locked_or_safepoint(CodeCache_lock); 6.188 - assert(_global_nmethods == NULL, "checking"); 6.189 - 6.190 - // create the list 6.191 - _global_nmethods = new (ResourceObj::C_HEAP) GrowableArray<nmethodDesc*>(100,true); 6.192 - 6.193 - // any a descriptor for each nmethod to the list. 6.194 - CodeCache::nmethods_do(do_nmethod); 6.195 - 6.196 - // make the list the instance list 6.197 - _nmethods = _global_nmethods; 6.198 - _global_nmethods = NULL; 6.199 -} 6.200 - 6.201 // Generate a COMPILED_METHOD_LOAD event for each nnmethod 6.202 - 6.203 jvmtiError JvmtiCodeBlobEvents::generate_compiled_method_load_events(JvmtiEnv* env) { 6.204 HandleMark hm; 6.205 - nmethodCollector collector; 6.206 6.207 - // first collect all nmethods 6.208 - { 6.209 - MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 6.210 - collector.collect(); 6.211 - } 6.212 + // Walk the CodeCache notifying for live nmethods. The code cache 6.213 + // may be changing while this is happening which is ok since newly 6.214 + // created nmethod will notify normally and nmethods which are freed 6.215 + // can be safely skipped. 6.216 + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 6.217 + nmethod* current = CodeCache::first_nmethod(); 6.218 + while (current != NULL) { 6.219 + // Lock the nmethod so it can't be freed 6.220 + nmethodLocker nml(current); 6.221 6.222 - // iterate over the list and post an event for each nmethod 6.223 - nmethodDesc* nm_desc = collector.first(); 6.224 - while (nm_desc != NULL) { 6.225 - jmethodID mid = nm_desc->jmethod_id(); 6.226 - assert(mid != NULL, "checking"); 6.227 - JvmtiExport::post_compiled_method_load(env, mid, 6.228 - (jint)(nm_desc->code_end() - nm_desc->code_begin()), 6.229 - nm_desc->code_begin(), nm_desc->map_length(), 6.230 - nm_desc->map()); 6.231 - nm_desc = collector.next(); 6.232 + // Only notify for live nmethods 6.233 + if (current->is_alive()) { 6.234 + // Don't hold the lock over the notify or jmethodID creation 6.235 + MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 6.236 + current->get_and_cache_jmethod_id(); 6.237 + JvmtiExport::post_compiled_method_load(current); 6.238 + } 6.239 + current = CodeCache::next_nmethod(current); 6.240 } 6.241 return JVMTI_ERROR_NONE; 6.242 }