Merge

Wed, 07 Jul 2010 12:40:01 -0700

author
never
date
Wed, 07 Jul 2010 12:40:01 -0700
changeset 1990
a693e51ac197
parent 1983
a00567c82f02
parent 1989
60a14ad85270
child 1991
cf647374e044
child 1994
9ee05c8ab82f
child 1999
2a47bd84841f

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  }

mercurial