< prev index next >

src/hotspot/share/code/nmethod.cpp

Print this page
*** 28,10 ***
--- 28,11 ---
  #include "code/compiledIC.hpp"
  #include "code/dependencies.hpp"
  #include "code/nativeInst.hpp"
  #include "code/nmethod.inline.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"

*** 783,10 ***
--- 784,12 ---
        klass = ((Klass*)md);
      } else if (md->is_method()) {
        klass = ((Method*)md)->method_holder();
      } else if (md->is_methodData()) {
        klass = ((MethodData*)md)->method()->method_holder();
+     } else if (md->is_methodCounters()) {
+       klass = ((MethodCounters*)md)->method()->method_holder();
      } else {
        md->print();
        ShouldNotReachHere();
      }
      assert(klass->is_loader_alive(), "must be alive");

*** 1131,10 ***
--- 1134,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

*** 1175,11 ***
  
      nm = new (nmethod_size, comp_level)
      nmethod(method(), compiler->type(), nmethod_size, immutable_data_size,
              compile_id, entry_bci, immutable_data, offsets, orig_pc_offset,
              debug_info, dependencies, code_buffer, frame_size, oop_maps,
!             handler_table, nul_chk_table, compiler, comp_level
  #if INCLUDE_JVMCI
              , speculations,
              speculations_len,
              jvmci_data
  #endif
--- 1179,11 ---
  
      nm = new (nmethod_size, comp_level)
      nmethod(method(), compiler->type(), nmethod_size, immutable_data_size,
              compile_id, entry_bci, immutable_data, offsets, orig_pc_offset,
              debug_info, dependencies, code_buffer, frame_size, oop_maps,
!             handler_table, nul_chk_table, compiler, comp_level, scc_entry
  #if INCLUDE_JVMCI
              , speculations,
              speculations_len,
              jvmci_data
  #endif

*** 1211,10 ***
--- 1215,22 ---
        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()) {
+       LogStream out(log);
+       out.print_cr("== new_nmethod 2");
+       FlagSetting fs(PrintRelocations, true);
+       nm->print(&out);
+       nm->decode(&out);
+     }
+ #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;

*** 1237,11 ***
--- 1253,14 ---
    _has_monitors               = 0;
    _has_scoped_access          = 0;
    _has_flushed_dependencies   = 0;
    _is_unlinked                = 0;
    _load_reported              = 0; // jvmti state
+   _preloaded                  = 0;
+   _has_clinit_barriers        = 0;
  
+   _used                       = false;
    _deoptimization_status      = not_marked;
  
    // SECT_CONSTS is first in code buffer so the offset should be 0.
    int consts_offset = code_buffer->total_offset_of(code_buffer->consts());
    assert(consts_offset == 0, "const_offset: %d", consts_offset);

*** 1309,10 ***
--- 1328,12 ---
      }
      // Native wrappers do not have deopt handlers. Make the values
      // something that will never match a pc like the nmethod vtable entry
      _deopt_handler_offset    = 0;
      _deopt_mh_handler_offset = 0;
+     _scc_entry               = nullptr;
+     _method_profiling_count  = 0;
      _unwind_handler_offset   = 0;
  
      CHECKED_CAST(_metadata_offset, uint16_t, (align_up(code_buffer->total_oop_size(), oopSize)));
      int data_end_offset = _metadata_offset + align_up(code_buffer->total_metadata_size(), wordSize);
  #if INCLUDE_JVMCI

*** 1369,11 ***
        print(); // print the header part only.
      }
  #if defined(SUPPORT_DATA_STRUCTS)
      if (AbstractDisassembler::show_structs()) {
        if (PrintRelocations) {
!         print_relocations();
          tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
        }
      }
  #endif
      if (xtty != nullptr) {
--- 1390,11 ---
        print(); // print the header part only.
      }
  #if defined(SUPPORT_DATA_STRUCTS)
      if (AbstractDisassembler::show_structs()) {
        if (PrintRelocations) {
!         print_relocations_on(tty);
          tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
        }
      }
  #endif
      if (xtty != nullptr) {

*** 1412,10 ***
--- 1433,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

*** 1431,10 ***
--- 1453,12 ---
    {
      debug_only(NoSafepointVerifier nsv;)
      assert_locked_or_safepoint(CodeCache_lock);
  
      init_defaults(code_buffer, offsets);
+     _scc_entry      = scc_entry;
+     _method_profiling_count  = 0;
  
      _osr_entry_point = code_begin() + offsets->value(CodeOffsets::OSR_Entry);
      _entry_bci       = entry_bci;
      _compile_id      = compile_id;
      _comp_level      = comp_level;

*** 1562,16 ***
  }
  
  // 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());
    const char* nm_kind = compile_kind();
!   if (nm_kind != nullptr)  log->print(" compile_kind='%s'", nm_kind);
!   log->print(" compiler='%s'", compiler_name());
    if (TieredCompilation) {
!     log->print(" level='%d'", comp_level());
    }
  #if INCLUDE_JVMCI
    if (jvmci_nmethod_data() != nullptr) {
      const char* jvmci_name = jvmci_nmethod_data()->name();
      if (jvmci_name != nullptr) {
--- 1586,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 {
!   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(" code_compile_kind='%s'", nm_kind);
!   log->print(" code_compiler='%s'", compiler_name());
    if (TieredCompilation) {
!     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) {

*** 1688,11 ***
      if (printmethod || PrintDebugInfo || CompilerOracle::has_option(mh, CompileCommandEnum::PrintDebugInfo)) {
        print_scopes();
        tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
      }
      if (printmethod || PrintRelocations || CompilerOracle::has_option(mh, CompileCommandEnum::PrintRelocations)) {
!       print_relocations();
        tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
      }
      if (printmethod || PrintDependencies || CompilerOracle::has_option(mh, CompileCommandEnum::PrintDependencies)) {
        print_dependencies_on(tty);
        tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
--- 1713,11 ---
      if (printmethod || PrintDebugInfo || CompilerOracle::has_option(mh, CompileCommandEnum::PrintDebugInfo)) {
        print_scopes();
        tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
      }
      if (printmethod || PrintRelocations || CompilerOracle::has_option(mh, CompileCommandEnum::PrintRelocations)) {
!       print_relocations_on(tty);
        tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
      }
      if (printmethod || PrintDependencies || CompilerOracle::has_option(mh, CompileCommandEnum::PrintDependencies)) {
        print_dependencies_on(tty);
        tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");

*** 1936,10 ***
--- 1961,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(NMethodState_lock);
    signed char old_state = _state;
    if (old_state >= new_state) {

*** 1981,11 ***
      method()->unlink_code(this);
    }
  }
  
  // Invalidate code
! bool nmethod::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
--- 2014,11 ---
      method()->unlink_code(this);
    }
  }
  
  // Invalidate code
! 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

*** 2044,10 ***
--- 2077,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 NMethodState_lock
  
  #if INCLUDE_JVMCI
    // Invalidate can't occur while holding the NMethodState_lock
    JVMCINMethodData* nmethod_data = jvmci_nmethod_data();

*** 2183,10 ***
--- 2223,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);

*** 3121,10 ***
--- 3167,13 ---
    if (speculations_size () > 0) st->print_cr(" speculations   [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
                                               p2i(speculations_begin()),
                                               p2i(speculations_end()),
                                               speculations_size());
  #endif
+   if (SCCache::is_on() && _scc_entry != nullptr) {
+     _scc_entry->print(st);
+   }
  }
  
  void nmethod::print_code() {
    ResourceMark m;
    ttyLocker ttyl;

*** 3220,15 ***
    }
  }
  #endif
  
  #ifndef PRODUCT  // RelocIterator does support printing only then.
! void nmethod::print_relocations() {
    ResourceMark m;       // in case methods get printed via the debugger
!   tty->print_cr("relocations:");
    RelocIterator iter(this);
!   iter.print();
  }
  #endif
  
  void nmethod::print_pcs_on(outputStream* st) {
    ResourceMark m;       // in case methods get printed via debugger
--- 3269,15 ---
    }
  }
  #endif
  
  #ifndef PRODUCT  // RelocIterator does support printing only then.
! void nmethod::print_relocations_on(outputStream* st) {
    ResourceMark m;       // in case methods get printed via the debugger
!   st->print_cr("relocations:");
    RelocIterator iter(this);
!   iter.print_on(st);
  }
  #endif
  
  void nmethod::print_pcs_on(outputStream* st) {
    ResourceMark m;       // in case methods get printed via debugger

*** 3579,10 ***
--- 3628,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 >