diff a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp
--- a/src/hotspot/share/code/nmethod.cpp
+++ b/src/hotspot/share/code/nmethod.cpp
@@ -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"
@@ -782,10 +783,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");
@@ -1130,10 +1133,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
@@ -1174,11 +1178,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
+            handler_table, nul_chk_table, compiler, comp_level, scc_entry
 #if INCLUDE_JVMCI
             , speculations,
             speculations_len,
             jvmci_data
 #endif
@@ -1210,10 +1214,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;
@@ -1236,11 +1252,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);
@@ -1308,10 +1327,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
@@ -1368,11 +1389,11 @@
       print(); // print the header part only.
     }
 #if defined(SUPPORT_DATA_STRUCTS)
     if (AbstractDisassembler::show_structs()) {
       if (PrintRelocations) {
-        print_relocations();
+        print_relocations_on(tty);
         tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
       }
     }
 #endif
     if (xtty != nullptr) {
@@ -1411,10 +1432,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
@@ -1430,10 +1452,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;
@@ -1561,16 +1585,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) {
@@ -1687,11 +1712,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();
+      print_relocations_on(tty);
       tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
     }
     if (printmethod || PrintDependencies || CompilerOracle::has_option(mh, CompileCommandEnum::PrintDependencies)) {
       print_dependencies_on(tty);
       tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
@@ -1935,10 +1960,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) {
@@ -1980,11 +2013,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
@@ -2043,10 +2076,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 Patching lock
   JVMCINMethodData* nmethod_data = jvmci_nmethod_data();
@@ -2182,10 +2222,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);
@@ -3120,10 +3166,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;
@@ -3219,15 +3268,15 @@
   }
 }
 #endif
 
 #ifndef PRODUCT  // RelocIterator does support printing only then.
-void nmethod::print_relocations() {
+void nmethod::print_relocations_on(outputStream* st) {
   ResourceMark m;       // in case methods get printed via the debugger
-  tty->print_cr("relocations:");
+  st->print_cr("relocations:");
   RelocIterator iter(this);
-  iter.print();
+  iter.print_on(st);
 }
 #endif
 
 void nmethod::print_pcs_on(outputStream* st) {
   ResourceMark m;       // in case methods get printed via debugger
@@ -3578,10 +3627,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;
