diff a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp
--- a/src/hotspot/share/opto/c2compiler.cpp
+++ b/src/hotspot/share/opto/c2compiler.cpp
@@ -22,10 +22,11 @@
  *
  */
 
 #include "precompiled.hpp"
 #include "classfile/vmClasses.hpp"
+#include "code/SCCache.hpp"
 #include "compiler/compilationMemoryStatistic.hpp"
 #include "compiler/compilerDefinitions.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "jfr/support/jfrIntrinsics.hpp"
 #include "opto/c2compiler.hpp"
@@ -59,10 +60,14 @@
 }
 const char* C2Compiler::retry_no_superword() {
   return "retry without SuperWord";
 }
 
+const char* C2Compiler::retry_no_clinit_barriers() {
+  return "retry without class initialization barriers";
+}
+
 void compiler_stubs_init(bool in_compiler_thread);
 
 bool C2Compiler::init_c2_runtime() {
 
 #ifdef ASSERT
@@ -94,11 +99,15 @@
   Compile::pd_compiler2_init();
 
   CompilerThread* thread = CompilerThread::current();
 
   HandleMark handle_mark(thread);
-  return OptoRuntime::generate(thread->env());
+  bool success = OptoRuntime::generate(thread->env());
+  if (success) {
+    SCCache::init_opto_table();
+  }
+  return success;
 }
 
 void C2Compiler::initialize() {
   assert(!CompilerConfig::is_c1_or_interpreter_only_no_jvmci(), "C2 compiler is launched, it's not c1/interpreter only mode");
   // The first compiler thread that gets here will initialize the
@@ -115,31 +124,52 @@
   }
 }
 
 void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, bool install_code, DirectiveSet* directive) {
   assert(is_initialized(), "Compiler thread must be initialized");
-
   CompilationMemoryStatisticMark cmsm(directive);
+  CompileTask* task = env->task();
+  if (install_code && task->is_scc()) {
+    bool success = SCCache::load_nmethod(env, target, entry_bci, this, CompLevel_full_optimization);
+    if (success) {
+      assert(task->is_success(), "sanity");
+      return;
+    }
+    if (!task->preload()) { // Do not mark entry if pre-loading failed - it can pass normal load
+      SCCache::invalidate(task->scc_entry()); // mark sca_entry as not entrant
+    }
+    if (SCCache::is_code_load_thread_on()) {
+      env->record_failure("Failed to load cached code");
+      // Bail out if failed to load cached code in SC thread
+      return;
+    }
+    task->clear_scc();
+  }
 
   bool subsume_loads = SubsumeLoads;
   bool do_escape_analysis = DoEscapeAnalysis;
   bool do_iterative_escape_analysis = DoEscapeAnalysis;
   bool do_reduce_allocation_merges = ReduceAllocationMerges && EliminateAllocations;
   bool eliminate_boxing = EliminateAutoBox;
   bool do_locks_coarsening = EliminateLocks;
   bool do_superword = UseSuperWord;
-
+  bool for_preload = (task->compile_reason() != CompileTask::Reason_Precompile) && // non-preload version is requested
+                     SCCache::gen_preload_code(target, entry_bci);
+  if (task->compile_reason() == CompileTask::Reason_PrecompileForPreload) {
+    assert(for_preload, "required");
+  }
   while (!env->failing()) {
     ResourceMark rm;
     // Attempt to compile while subsuming loads into machine instructions.
     Options options(subsume_loads,
                     do_escape_analysis,
                     do_iterative_escape_analysis,
                     do_reduce_allocation_merges,
                     eliminate_boxing,
                     do_locks_coarsening,
                     do_superword,
+                    for_preload,
                     install_code);
     Compile C(env, target, entry_bci, options, directive);
 
     // Check result and retry if appropriate.
     if (C.failure_reason() != nullptr) {
@@ -171,10 +201,15 @@
         assert(do_locks_coarsening, "must make progress");
         do_locks_coarsening = false;
         env->report_failure(C.failure_reason());
         continue;  // retry
       }
+      if (C.failure_reason_is(retry_no_clinit_barriers())) {
+        assert(for_preload, "must make progress");
+        for_preload = false;
+        continue;
+      }
       if (C.failure_reason_is(retry_no_superword())) {
         assert(do_superword, "must make progress");
         do_superword = false;
         env->report_failure(C.failure_reason());
         continue;  // retry
