diff a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp
--- a/src/hotspot/share/opto/output.cpp
+++ b/src/hotspot/share/opto/output.cpp
@@ -240,16 +240,23 @@
     _code_offsets(),
     _node_bundling_limit(0),
     _node_bundling_base(NULL),
     _orig_pc_slot(0),
     _orig_pc_slot_offset_in_bytes(0),
+    _sp_inc_slot(0),
+    _sp_inc_slot_offset_in_bytes(0),
     _buf_sizes(),
     _block(NULL),
     _index(0) {
   C->set_output(this);
   if (C->stub_name() == NULL) {
-    _orig_pc_slot = C->fixed_slots() - (sizeof(address) / VMRegImpl::stack_slot_size);
+    int fixed_slots = C->fixed_slots();
+    if (C->needs_stack_repair()) {
+      fixed_slots -= 2;
+      _sp_inc_slot = fixed_slots;
+    }
+    _orig_pc_slot = fixed_slots - (sizeof(address) / VMRegImpl::stack_slot_size);
   }
 }
 
 PhaseOutput::~PhaseOutput() {
   C->set_output(NULL);
@@ -284,28 +291,38 @@
   Block *broot = C->cfg()->get_root_block();
 
   const StartNode *start = entry->head()->as_Start();
 
   // Replace StartNode with prolog
-  MachPrologNode *prolog = new MachPrologNode();
+  Label verified_entry;
+  MachPrologNode* prolog = new MachPrologNode(&verified_entry);
   entry->map_node(prolog, 0);
   C->cfg()->map_node_to_block(prolog, entry);
   C->cfg()->unmap_node_from_block(start); // start is no longer in any block
 
   // Virtual methods need an unverified entry point
-
-  if( C->is_osr_compilation() ) {
-    if( PoisonOSREntry ) {
+  if (C->is_osr_compilation()) {
+    if (PoisonOSREntry) {
       // TODO: Should use a ShouldNotReachHereNode...
       C->cfg()->insert( broot, 0, new MachBreakpointNode() );
     }
   } else {
-    if( C->method() && !C->method()->flags().is_static() ) {
-      // Insert unvalidated entry point
-      C->cfg()->insert( broot, 0, new MachUEPNode() );
+    if (C->method()) {
+      if (C->method()->has_scalarized_args()) {
+        // Add entry point to unpack all inline type arguments
+        C->cfg()->insert(broot, 0, new MachVEPNode(&verified_entry, /* verified */ true, /* receiver_only */ false));
+        if (!C->method()->is_static()) {
+          // Add verified/unverified entry points to only unpack inline type receiver at interface calls
+          C->cfg()->insert(broot, 0, new MachVEPNode(&verified_entry, /* verified */ false, /* receiver_only */ false));
+          C->cfg()->insert(broot, 0, new MachVEPNode(&verified_entry, /* verified */ true,  /* receiver_only */ true));
+          C->cfg()->insert(broot, 0, new MachVEPNode(&verified_entry, /* verified */ false, /* receiver_only */ true));
+        }
+      } else if (!C->method()->is_static()) {
+        // Insert unvalidated entry point
+        C->cfg()->insert(broot, 0, new MachUEPNode());
+      }
     }
-
   }
 
   // Break before main entry point
   if ((C->method() && C->directive()->BreakAtExecuteOption) ||
       (OptoBreakpoint && C->is_method_compilation())       ||
@@ -341,10 +358,35 @@
   // Must be done before ScheduleAndBundle due to SPARC delay slots
   uint* blk_starts = NEW_RESOURCE_ARRAY(uint, C->cfg()->number_of_blocks() + 1);
   blk_starts[0] = 0;
   shorten_branches(blk_starts);
 
+  if (!C->is_osr_compilation() && C->has_scalarized_args()) {
+    // Compute the offsets of the entry points required by the inline type calling convention
+    if (!C->method()->is_static()) {
+      // We have entries at the beginning of the method, implemented by the first 4 nodes.
+      // Entry                     (unverified) @ offset 0
+      // Verified_Inline_Entry_RO
+      // Inline_Entry              (unverified)
+      // Verified_Inline_Entry
+      uint offset = 0;
+      _code_offsets.set_value(CodeOffsets::Entry, offset);
+
+      offset += ((MachVEPNode*)broot->get_node(0))->size(C->regalloc());
+      _code_offsets.set_value(CodeOffsets::Verified_Inline_Entry_RO, offset);
+
+      offset += ((MachVEPNode*)broot->get_node(1))->size(C->regalloc());
+      _code_offsets.set_value(CodeOffsets::Inline_Entry, offset);
+
+      offset += ((MachVEPNode*)broot->get_node(2))->size(C->regalloc());
+      _code_offsets.set_value(CodeOffsets::Verified_Inline_Entry, offset);
+    } else {
+      _code_offsets.set_value(CodeOffsets::Entry, -1); // will be patched later
+      _code_offsets.set_value(CodeOffsets::Verified_Inline_Entry, 0);
+    }
+  }
+
   ScheduleAndBundle();
   if (C->failing()) {
     return;
   }
 
@@ -498,11 +540,13 @@
           reloc_size += CallStubImpl::reloc_call_trampoline();
 
           MachCallNode *mcall = mach->as_MachCall();
           // This destination address is NOT PC-relative
 
-          mcall->method_set((intptr_t)mcall->entry_point());
+          if (mcall->entry_point() != NULL) {
+            mcall->method_set((intptr_t)mcall->entry_point());
+          }
 
           if (mcall->is_MachCallJava() && mcall->as_MachCallJava()->_method) {
             stub_size  += CompiledStaticCall::to_interp_stub_size();
             reloc_size += CompiledStaticCall::reloc_to_interp_stub();
 #if INCLUDE_AOT
@@ -931,10 +975,11 @@
   MachCallNode      *mcall;
 
   int safepoint_pc_offset = current_offset;
   bool is_method_handle_invoke = false;
   bool return_oop = false;
+  bool return_vt = false;
 
   // Add the safepoint in the DebugInfoRecorder
   if( !mach->is_MachCall() ) {
     mcall = NULL;
     C->debug_info()->add_safepoint(safepoint_pc_offset, sfn->_oop_map);
@@ -948,13 +993,16 @@
         is_method_handle_invoke = true;
       }
     }
 
     // Check if a call returns an object.
-    if (mcall->returns_pointer()) {
+    if (mcall->returns_pointer() || mcall->returns_vt()) {
       return_oop = true;
     }
+    if (mcall->returns_vt()) {
+      return_vt = true;
+    }
     safepoint_pc_offset += mcall->ret_addr_offset();
     C->debug_info()->add_safepoint(safepoint_pc_offset, mcall->_oop_map);
   }
 
   // Loop over the JVMState list to add scope information
@@ -1065,11 +1113,11 @@
     assert(jvms->bci() >= InvocationEntryBci && jvms->bci() <= 0x10000, "must be a valid or entry BCI");
     assert(!jvms->should_reexecute() || depth == max_depth, "reexecute allowed only for the youngest");
     // Now we can describe the scope.
     methodHandle null_mh;
     bool rethrow_exception = false;
-    C->debug_info()->describe_scope(safepoint_pc_offset, null_mh, scope_method, jvms->bci(), jvms->should_reexecute(), rethrow_exception, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
+    C->debug_info()->describe_scope(safepoint_pc_offset, null_mh, scope_method, jvms->bci(), jvms->should_reexecute(), rethrow_exception, is_method_handle_invoke, return_oop, return_vt, locvals, expvals, monvals);
   } // End jvms loop
 
   // Mark the end of the scope set.
   C->debug_info()->end_safepoint(safepoint_pc_offset);
 }
@@ -1170,10 +1218,14 @@
 
   // Compute the byte offset where we can store the deopt pc.
   if (C->fixed_slots() != 0) {
     _orig_pc_slot_offset_in_bytes = C->regalloc()->reg2offset(OptoReg::stack2reg(_orig_pc_slot));
   }
+  if (C->needs_stack_repair()) {
+    // Compute the byte offset of the stack increment value
+    _sp_inc_slot_offset_in_bytes = C->regalloc()->reg2offset(OptoReg::stack2reg(_sp_inc_slot));
+  }
 
   // Compute prolog code size
   _method_size = 0;
   _frame_slots = OptoReg::reg2stack(C->matcher()->_old_SP) + C->regalloc()->_framesize;
 #if defined(IA64) && !defined(AIX)
@@ -1446,12 +1498,14 @@
 
         // Remember the start of the last call in a basic block
         if (is_mcall) {
           MachCallNode *mcall = mach->as_MachCall();
 
-          // This destination address is NOT PC-relative
-          mcall->method_set((intptr_t)mcall->entry_point());
+          if (mcall->entry_point() != NULL) {
+            // This destination address is NOT PC-relative
+            mcall->method_set((intptr_t)mcall->entry_point());
+          }
 
           // Save the return address
           call_returns[block->_pre_order] = current_offset + mcall->ret_addr_offset();
 
           if (mcall->is_MachCallLeaf()) {
@@ -3178,10 +3232,16 @@
     }
 
     ResourceMark rm;
     _scratch_const_size = const_size;
     int size = C2Compiler::initial_code_buffer_size(const_size);
+#ifdef ASSERT
+    if (C->has_scalarized_args()) {
+      // Oop verification for loading object fields from scalarized inline types in the new entry point requires lots of space
+      size += 5120;
+    }
+#endif
     blob = BufferBlob::create("Compile::scratch_buffer", size);
     // Record the buffer blob for next time.
     set_scratch_buffer_blob(blob);
     // Have we run out of code space?
     if (scratch_buffer_blob() == NULL) {
@@ -3242,18 +3302,30 @@
   if (is_branch) {
     MacroAssembler masm(&buf);
     masm.bind(fakeL);
     n->as_MachBranch()->save_label(&saveL, &save_bnum);
     n->as_MachBranch()->label_set(&fakeL, 0);
+  } else if (n->is_MachProlog()) {
+    saveL = ((MachPrologNode*)n)->_verified_entry;
+    ((MachPrologNode*)n)->_verified_entry = &fakeL;
+  } else if (n->is_MachVEP()) {
+    saveL = ((MachVEPNode*)n)->_verified_entry;
+    ((MachVEPNode*)n)->_verified_entry = &fakeL;
   }
   n->emit(buf, C->regalloc());
 
   // Emitting into the scratch buffer should not fail
   assert (!C->failing(), "Must not have pending failure. Reason is: %s", C->failure_reason());
 
-  if (is_branch) // Restore label.
+  // Restore label.
+  if (is_branch) {
     n->as_MachBranch()->label_set(saveL, save_bnum);
+  } else if (n->is_MachProlog()) {
+    ((MachPrologNode*)n)->_verified_entry = saveL;
+  } else if (n->is_MachVEP()) {
+    ((MachVEPNode*)n)->_verified_entry = saveL;
+  }
 
   // End scratch_emit_size section.
   set_in_scratch_emit_size(false);
 
   return buf.insts_size();
@@ -3294,26 +3366,35 @@
     if (C->is_osr_compilation()) {
       _code_offsets.set_value(CodeOffsets::Verified_Entry, 0);
       _code_offsets.set_value(CodeOffsets::OSR_Entry, _first_block_size);
     } else {
       _code_offsets.set_value(CodeOffsets::Verified_Entry, _first_block_size);
+      if (_code_offsets.value(CodeOffsets::Verified_Inline_Entry) == -1) {
+        _code_offsets.set_value(CodeOffsets::Verified_Inline_Entry, _first_block_size);
+      }
+      if (_code_offsets.value(CodeOffsets::Verified_Inline_Entry_RO) == -1) {
+        _code_offsets.set_value(CodeOffsets::Verified_Inline_Entry_RO, _first_block_size);
+      }
+      if (_code_offsets.value(CodeOffsets::Entry) == -1) {
+        _code_offsets.set_value(CodeOffsets::Entry, _first_block_size);
+      }
       _code_offsets.set_value(CodeOffsets::OSR_Entry, 0);
     }
 
     C->env()->register_method(target,
-                                     entry_bci,
-                                     &_code_offsets,
-                                     _orig_pc_slot_offset_in_bytes,
-                                     code_buffer(),
-                                     frame_size_in_words(),
-                                     oop_map_set(),
-                                     &_handler_table,
-                                     inc_table(),
-                                     compiler,
-                                     has_unsafe_access,
-                                     SharedRuntime::is_wide_vector(C->max_vector_size()),
-                                     C->rtm_state());
+                              entry_bci,
+                              &_code_offsets,
+                              _orig_pc_slot_offset_in_bytes,
+                              code_buffer(),
+                              frame_size_in_words(),
+                              _oop_map_set,
+                              &_handler_table,
+                              &_inc_table,
+                              compiler,
+                              has_unsafe_access,
+                              SharedRuntime::is_wide_vector(C->max_vector_size()),
+                              C->rtm_state());
 
     if (C->log() != NULL) { // Print code cache state into compiler log
       C->log()->code_cache_state();
     }
   }
