< prev index next >

src/hotspot/share/code/nmethod.cpp

Print this page
@@ -29,10 +29,11 @@
  #include "code/compiledMethod.inline.hpp"
  #include "code/dependencies.hpp"
  #include "code/nativeInst.hpp"
  #include "code/nmethod.hpp"
  #include "code/scopeDesc.hpp"
+ #include "code/SCCache.hpp"
  #include "compiler/abstractCompiler.hpp"
  #include "compiler/compilationLog.hpp"
  #include "compiler/compileBroker.hpp"
  #include "compiler/compileLog.hpp"
  #include "compiler/compileTask.hpp"

@@ -443,10 +444,11 @@
  // Fill in default values for various flag fields
  void nmethod::init_defaults() {
    _state                      = not_installed;
    _has_flushed_dependencies   = 0;
    _load_reported              = false; // jvmti state
+   _used                       = false;
  
    _oops_do_mark_link       = nullptr;
    _osr_link                = nullptr;
  #if INCLUDE_RTM_OPT
    _rtm_state               = NoRTM;

@@ -547,10 +549,11 @@
    OopMapSet* oop_maps,
    ExceptionHandlerTable* handler_table,
    ImplicitExceptionTable* nul_chk_table,
    AbstractCompiler* compiler,
    CompLevel comp_level
+   , SCCEntry* scc_entry
  #if INCLUDE_JVMCI
    , char* speculations,
    int speculations_len,
    JVMCINMethodData* jvmci_data
  #endif

@@ -583,10 +586,11 @@
              oop_maps,
              handler_table,
              nul_chk_table,
              compiler,
              comp_level
+             , scc_entry
  #if INCLUDE_JVMCI
              , speculations,
              speculations_len,
              jvmci_data
  #endif

@@ -618,10 +622,21 @@
        NOT_PRODUCT(if (nm != nullptr)  note_java_nmethod(nm));
      }
    }
    // Do verification and logging outside CodeCache_lock.
    if (nm != nullptr) {
+ 
+ #ifdef ASSERT
+     LogTarget(Debug, scc, nmethod) log;
+     if (log.is_enabled()) {
+       tty->print_cr("== new_nmethod 2");
+       FlagSetting fs(PrintRelocations, true);
+       nm->print();
+       nm->decode(tty);
+     }
+ #endif
+ 
      // Safepoints in nmethod::verify aren't allowed because nm hasn't been installed yet.
      DEBUG_ONLY(nm->verify();)
      nm->log_new_nmethod();
    }
    return nm;

@@ -660,10 +675,12 @@
      // We have no exception handler or deopt handler make the
      // values something that will never match a pc like the nmethod vtable entry
      _exception_offset        = 0;
      _orig_pc_offset          = 0;
      _gc_epoch                = CodeCache::gc_epoch();
+     _scc_entry               = nullptr;
+     _method_profiling_count  = 0;
  
      _consts_offset           = content_offset()      + code_buffer->total_offset_of(code_buffer->consts());
      _stub_offset             = content_offset()      + code_buffer->total_offset_of(code_buffer->stubs());
      _oops_offset             = data_offset();
      _metadata_offset         = _oops_offset          + align_up(code_buffer->total_oop_size(), oopSize);

@@ -776,10 +793,11 @@
    OopMapSet* oop_maps,
    ExceptionHandlerTable* handler_table,
    ImplicitExceptionTable* nul_chk_table,
    AbstractCompiler* compiler,
    CompLevel comp_level
+   , SCCEntry* scc_entry
  #if INCLUDE_JVMCI
    , char* speculations,
    int speculations_len,
    JVMCINMethodData* jvmci_data
  #endif

@@ -803,10 +821,12 @@
      _entry_bci               = entry_bci;
      _compile_id              = compile_id;
      _comp_level              = comp_level;
      _orig_pc_offset          = orig_pc_offset;
      _gc_epoch                = CodeCache::gc_epoch();
+     _scc_entry               = scc_entry;
+     _method_profiling_count  = 0;
  
      // Section offsets
      _consts_offset           = content_offset()      + code_buffer->total_offset_of(code_buffer->consts());
      _stub_offset             = content_offset()      + code_buffer->total_offset_of(code_buffer->stubs());
      set_ctable_begin(header_begin() + _consts_offset);

@@ -916,16 +936,17 @@
  }
  
  // Print a short set of xml attributes to identify this nmethod.  The
  // output should be embedded in some other element.
  void nmethod::log_identity(xmlStream* log) const {
-   log->print(" compile_id='%d'", compile_id());
+   assert(log->inside_attrs_or_error(), "printing attributes");
+   log->print(" code_compile_id='%d'", compile_id());
    const char* nm_kind = compile_kind();
-   if (nm_kind != nullptr)  log->print(" compile_kind='%s'", nm_kind);
-   log->print(" compiler='%s'", compiler_name());
+   if (nm_kind != nullptr)  log->print(" code_compile_kind='%s'", nm_kind);
+   log->print(" code_compiler='%s'", compiler_name());
    if (TieredCompilation) {
-     log->print(" level='%d'", comp_level());
+     log->print(" code_compile_level='%d'", comp_level());
    }
  #if INCLUDE_JVMCI
    if (jvmci_nmethod_data() != nullptr) {
      const char* jvmci_name = jvmci_nmethod_data()->name();
      if (jvmci_name != nullptr) {

@@ -1290,10 +1311,18 @@
    if (mdo == nullptr)  return;
    // There is a benign race here.  See comments in methodData.hpp.
    mdo->inc_decompile_count();
  }
  
+ void nmethod::inc_method_profiling_count() {
+   Atomic::inc(&_method_profiling_count);
+ }
+ 
+ uint64_t nmethod::method_profiling_count() {
+   return _method_profiling_count;
+ }
+ 
  bool nmethod::try_transition(signed char new_state_int) {
    signed char new_state = new_state_int;
    assert_lock_strong(CompiledMethod_lock);
    signed char old_state = _state;
    if (old_state >= new_state) {

@@ -1335,11 +1364,11 @@
      method()->unlink_code(this);
    }
  }
  
  // Invalidate code
- bool nmethod::make_not_entrant() {
+ bool nmethod::make_not_entrant(bool make_not_entrant) {
    // This can be called while the system is already at a safepoint which is ok
    NoSafepointVerifier nsv;
  
    if (is_unloading()) {
      // If the nmethod is unloading, then it is already not entrant through

@@ -1398,10 +1427,17 @@
      log_state_change();
  
      // Remove nmethod from method.
      unlink_from_method();
  
+     if (make_not_entrant) {
+       // Keep cached code if it was simply replaced
+       // otherwise make it not entrant too.
+       SCCache::invalidate(_scc_entry);
+     }
+ 
+     CompileBroker::log_not_entrant(this);
    } // leave critical region under CompiledMethod_lock
  
  #if INCLUDE_JVMCI
    // Invalidate can't occur while holding the Patching lock
    JVMCINMethodData* nmethod_data = jvmci_nmethod_data();

@@ -1532,10 +1568,16 @@
    task->mark_success();
    task->set_nm_content_size(content_size());
    task->set_nm_insts_size(insts_size());
    task->set_nm_total_size(total_size());
  
+   // task->is_scc() is true only for loaded cached code.
+   // nmethod::_scc_entry is set for loaded and stored cached code
+   // to invalidate the entry when nmethod is deoptimized.
+   // There is option to not store in archive cached code.
+   guarantee((_scc_entry != nullptr) || !task->is_scc() || VerifyCachedCode, "sanity");
+ 
    // JVMTI -- compiled method notification (must be done outside lock)
    post_compiled_method_load_event();
  
    if (CompilationLog::log() != nullptr) {
      CompilationLog::log()->log_nmethod(JavaThread::current(), this);

@@ -2445,10 +2487,13 @@
    if (jvmci_data_size   () > 0) st->print_cr(" JVMCI data     [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
                                               p2i(jvmci_data_begin()),
                                               p2i(jvmci_data_end()),
                                               jvmci_data_size());
  #endif
+   if (SCCache::is_on() && _scc_entry != nullptr) {
+     _scc_entry->print(st);
+   }
  }
  
  void nmethod::print_code() {
    ResourceMark m;
    ttyLocker ttyl;

@@ -2903,10 +2948,20 @@
          case relocInfo::runtime_call_w_cp_type: {
            stringStream st;
            st.print("runtime_call");
            CallRelocation* r = (CallRelocation*)iter.reloc();
            address dest = r->destination();
+           if (StubRoutines::contains(dest)) {
+             StubCodeDesc* desc = StubCodeDesc::desc_for(dest);
+             if (desc == nullptr) {
+               desc = StubCodeDesc::desc_for(dest + frame::pc_return_offset);
+             }
+             if (desc != nullptr) {
+               st.print(" Stub::%s", desc->name());
+               return st.as_string();
+             }
+           }
            CodeBlob* cb = CodeCache::find_blob(dest);
            if (cb != nullptr) {
              st.print(" %s", cb->name());
            } else {
              ResourceMark rm;
< prev index next >