5057818: codecache full and compiler disabled in bigapps fastdebug run

Wed, 16 Dec 2009 22:15:12 -0800

author
never
date
Wed, 16 Dec 2009 22:15:12 -0800
changeset 1544
032260830071
parent 1543
85f13cdfbc1d
child 1545
1ea456c6f2b7

5057818: codecache full and compiler disabled in bigapps fastdebug run
Reviewed-by: kvn

src/share/vm/code/nmethod.cpp file | annotate | diff | comparison | revisions
src/share/vm/code/nmethod.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/code/nmethod.cpp	Wed Dec 16 12:48:04 2009 +0100
     1.2 +++ b/src/share/vm/code/nmethod.cpp	Wed Dec 16 22:15:12 2009 -0800
     1.3 @@ -414,9 +414,8 @@
     1.4  }
     1.5  
     1.6  const char* nmethod::compile_kind() const {
     1.7 -  if (method() == NULL)    return "unloaded";
     1.8 -  if (is_native_method())  return "c2n";
     1.9    if (is_osr_method())     return "osr";
    1.10 +  if (method() != NULL && is_native_method())  return "c2n";
    1.11    return NULL;
    1.12  }
    1.13  
    1.14 @@ -1127,6 +1126,9 @@
    1.15    }
    1.16    flags.state = unloaded;
    1.17  
    1.18 +  // Log the unloading.
    1.19 +  log_state_change();
    1.20 +
    1.21    // The methodOop is gone at this point
    1.22    assert(_method == NULL, "Tautology");
    1.23  
    1.24 @@ -1137,8 +1139,6 @@
    1.25  
    1.26  void nmethod::invalidate_osr_method() {
    1.27    assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod");
    1.28 -  if (_entry_bci != InvalidOSREntryBci)
    1.29 -    inc_decompile_count();
    1.30    // Remove from list of active nmethods
    1.31    if (method() != NULL)
    1.32      instanceKlass::cast(method()->method_holder())->remove_osr_nmethod(this);
    1.33 @@ -1146,59 +1146,63 @@
    1.34    _entry_bci = InvalidOSREntryBci;
    1.35  }
    1.36  
    1.37 -void nmethod::log_state_change(int state) const {
    1.38 +void nmethod::log_state_change() const {
    1.39    if (LogCompilation) {
    1.40      if (xtty != NULL) {
    1.41        ttyLocker ttyl;  // keep the following output all in one block
    1.42 -      xtty->begin_elem("make_not_entrant %sthread='" UINTX_FORMAT "'",
    1.43 -                       (state == zombie ? "zombie='1' " : ""),
    1.44 -                       os::current_thread_id());
    1.45 +      if (flags.state == unloaded) {
    1.46 +        xtty->begin_elem("make_unloaded thread='" UINTX_FORMAT "'",
    1.47 +                         os::current_thread_id());
    1.48 +      } else {
    1.49 +        xtty->begin_elem("make_not_entrant thread='" UINTX_FORMAT "'%s",
    1.50 +                         os::current_thread_id(),
    1.51 +                         (flags.state == zombie ? " zombie='1'" : ""));
    1.52 +      }
    1.53        log_identity(xtty);
    1.54        xtty->stamp();
    1.55        xtty->end_elem();
    1.56      }
    1.57    }
    1.58 -  if (PrintCompilation) {
    1.59 -    print_on(tty, state == zombie ? "made zombie " : "made not entrant ");
    1.60 +  if (PrintCompilation && flags.state != unloaded) {
    1.61 +    print_on(tty, flags.state == zombie ? "made zombie " : "made not entrant ");
    1.62      tty->cr();
    1.63    }
    1.64  }
    1.65  
    1.66  // Common functionality for both make_not_entrant and make_zombie
    1.67 -void nmethod::make_not_entrant_or_zombie(int state) {
    1.68 +bool nmethod::make_not_entrant_or_zombie(int state) {
    1.69    assert(state == zombie || state == not_entrant, "must be zombie or not_entrant");
    1.70  
    1.71 -  // Code for an on-stack-replacement nmethod is removed when a class gets unloaded.
    1.72 -  // They never become zombie/non-entrant, so the nmethod sweeper will never remove
    1.73 -  // them. Instead the entry_bci is set to InvalidOSREntryBci, so the osr nmethod
    1.74 -  // will never be used anymore. That the nmethods only gets removed when class unloading
    1.75 -  // happens, make life much simpler, since the nmethods are not just going to disappear
    1.76 -  // out of the blue.
    1.77 -  if (is_osr_method()) {
    1.78 -    if (osr_entry_bci() != InvalidOSREntryBci) {
    1.79 -      // only log this once
    1.80 -      log_state_change(state);
    1.81 -    }
    1.82 -    invalidate_osr_method();
    1.83 -    return;
    1.84 +  // If the method is already zombie there is nothing to do
    1.85 +  if (is_zombie()) {
    1.86 +    return false;
    1.87    }
    1.88  
    1.89 -  // If the method is already zombie or set to the state we want, nothing to do
    1.90 -  if (is_zombie() || (state == not_entrant && is_not_entrant())) {
    1.91 -    return;
    1.92 -  }
    1.93 -
    1.94 -  log_state_change(state);
    1.95 -
    1.96    // Make sure the nmethod is not flushed in case of a safepoint in code below.
    1.97    nmethodLocker nml(this);
    1.98  
    1.99    {
   1.100 +    // invalidate osr nmethod before acquiring the patching lock since
   1.101 +    // they both acquire leaf locks and we don't want a deadlock.
   1.102 +    // This logic is equivalent to the logic below for patching the
   1.103 +    // verified entry point of regular methods.
   1.104 +    if (is_osr_method()) {
   1.105 +      // this effectively makes the osr nmethod not entrant
   1.106 +      invalidate_osr_method();
   1.107 +    }
   1.108 +
   1.109      // Enter critical section.  Does not block for safepoint.
   1.110      MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
   1.111 +
   1.112 +    if (flags.state == state) {
   1.113 +      // another thread already performed this transition so nothing
   1.114 +      // to do, but return false to indicate this.
   1.115 +      return false;
   1.116 +    }
   1.117 +
   1.118      // The caller can be calling the method statically or through an inline
   1.119      // cache call.
   1.120 -    if (!is_not_entrant()) {
   1.121 +    if (!is_osr_method() && !is_not_entrant()) {
   1.122        NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
   1.123                    SharedRuntime::get_handle_wrong_method_stub());
   1.124        assert (NativeJump::instruction_size == nmethod::_zombie_instruction_size, "");
   1.125 @@ -1217,6 +1221,10 @@
   1.126  
   1.127      // Change state
   1.128      flags.state = state;
   1.129 +
   1.130 +    // Log the transition once
   1.131 +    log_state_change();
   1.132 +
   1.133    } // leave critical region under Patching_lock
   1.134  
   1.135    if (state == not_entrant) {
   1.136 @@ -1240,7 +1248,6 @@
   1.137    // It's a true state change, so mark the method as decompiled.
   1.138    inc_decompile_count();
   1.139  
   1.140 -
   1.141    // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event
   1.142    // and it hasn't already been reported for this nmethod then report it now.
   1.143    // (the event may have been reported earilier if the GC marked it for unloading).
   1.144 @@ -1268,7 +1275,7 @@
   1.145  
   1.146    // Check whether method got unloaded at a safepoint before this,
   1.147    // if so we can skip the flushing steps below
   1.148 -  if (method() == NULL) return;
   1.149 +  if (method() == NULL) return true;
   1.150  
   1.151    // Remove nmethod from method.
   1.152    // We need to check if both the _code and _from_compiled_code_entry_point
   1.153 @@ -1282,6 +1289,8 @@
   1.154      HandleMark hm;
   1.155      method()->clear_code();
   1.156    }
   1.157 +
   1.158 +  return true;
   1.159  }
   1.160  
   1.161  
     2.1 --- a/src/share/vm/code/nmethod.hpp	Wed Dec 16 12:48:04 2009 +0100
     2.2 +++ b/src/share/vm/code/nmethod.hpp	Wed Dec 16 22:15:12 2009 -0800
     2.3 @@ -252,7 +252,9 @@
     2.4    void* operator new(size_t size, int nmethod_size);
     2.5  
     2.6    const char* reloc_string_for(u_char* begin, u_char* end);
     2.7 -  void make_not_entrant_or_zombie(int state);
     2.8 +  // Returns true if this thread changed the state of the nmethod or
     2.9 +  // false if another thread performed the transition.
    2.10 +  bool make_not_entrant_or_zombie(int state);
    2.11    void inc_decompile_count();
    2.12  
    2.13    // used to check that writes to nmFlags are done consistently.
    2.14 @@ -375,10 +377,12 @@
    2.15    bool  is_zombie() const                         { return flags.state == zombie; }
    2.16    bool  is_unloaded() const                       { return flags.state == unloaded;   }
    2.17  
    2.18 -  // Make the nmethod non entrant. The nmethod will continue to be alive.
    2.19 -  // It is used when an uncommon trap happens.
    2.20 -  void  make_not_entrant()                        { make_not_entrant_or_zombie(not_entrant); }
    2.21 -  void  make_zombie()                             { make_not_entrant_or_zombie(zombie); }
    2.22 +  // Make the nmethod non entrant. The nmethod will continue to be
    2.23 +  // alive.  It is used when an uncommon trap happens.  Returns true
    2.24 +  // if this thread changed the state of the nmethod or false if
    2.25 +  // another thread performed the transition.
    2.26 +  bool  make_not_entrant()                        { return make_not_entrant_or_zombie(not_entrant); }
    2.27 +  bool  make_zombie()                             { return make_not_entrant_or_zombie(zombie); }
    2.28  
    2.29    // used by jvmti to track if the unload event has been reported
    2.30    bool  unload_reported()                         { return _unload_reported; }
    2.31 @@ -563,7 +567,7 @@
    2.32    // Logging
    2.33    void log_identity(xmlStream* log) const;
    2.34    void log_new_nmethod() const;
    2.35 -  void log_state_change(int state) const;
    2.36 +  void log_state_change() const;
    2.37  
    2.38    // Prints a comment for one native instruction (reloc info, pc desc)
    2.39    void print_code_comment_on(outputStream* st, int column, address begin, address end);

mercurial