diff a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp
--- a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp
+++ b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp
@@ -185,11 +185,14 @@
   }
 
   // all non-native method kinds
   method_entry(zerolocals)
   method_entry(zerolocals_synchronized)
+  method_entry(zerolocals_upcalls)
+  method_entry(zerolocals_synchronized_upcalls)
   method_entry(empty)
+  method_entry(empty_upcalls)
   method_entry(getter)
   method_entry(setter)
   method_entry(abstract)
   method_entry(java_lang_math_sin  )
   method_entry(java_lang_math_cos  )
@@ -221,10 +224,12 @@
     Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind, true); \
   }
 
   native_method_entry(native)
   native_method_entry(native_synchronized)
+  native_method_entry(native_upcalls)
+  native_method_entry(native_synchronized_upcalls)
 
   // Entries to intrinsics for native methods should follow
   // entries for `native` methods to use the same address in case
   // intrinsic is disabled.
   native_method_entry(java_lang_Thread_currentThread)
@@ -369,14 +374,16 @@
 
 
 //------------------------------------------------------------------------------------------------------------------------
 
 void TemplateInterpreterGenerator::generate_and_dispatch(Template* t, TosState tos_out) {
+  if (CountBytecodes || CountBytecodesPerThread || TraceBytecodes || StopInterpreterAt > 0) {
+    count_bytecode();
+  }
+  if (PrintBytecodeHistogram)                                    histogram_bytecode(t);
 #ifndef PRODUCT
   // debugging code
-  if (CountBytecodes || TraceBytecodes || StopInterpreterAt > 0) count_bytecode();
-  if (PrintBytecodeHistogram)                                    histogram_bytecode(t);
   if (PrintBytecodePairHistogram)                                histogram_bytecode_pair(t);
   if (TraceBytecodes)                                            trace_bytecode(t);
   if (StopInterpreterAt > 0)                                     stop_interpreter_at();
   __ verify_FPU(1, t->tos_in());
 #endif // !PRODUCT
@@ -405,46 +412,101 @@
     // dispatch to next bytecode
     __ dispatch_epilog(tos_out, step);
   }
 }
 
+bool TemplateInterpreterGenerator::is_synchronized_method(AbstractInterpreter::MethodKind kind) {
+  switch (kind) {
+    case Interpreter::zerolocals_synchronized        : // fall thru
+    case Interpreter::zerolocals_synchronized_upcalls: // fall thru
+    case Interpreter::native_synchronized            : // fall thru
+    case Interpreter::native_synchronized_upcalls    :
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool TemplateInterpreterGenerator::is_runtime_upcalls_method(AbstractInterpreter::MethodKind kind) {
+  switch (kind) {
+    case Interpreter::zerolocals_upcalls             : // fall thru
+    case Interpreter::zerolocals_synchronized_upcalls: // fall thru
+    case Interpreter::native_upcalls                 : // fall thru
+    case Interpreter::native_synchronized_upcalls    : // fall thru
+    case Interpreter::empty_upcalls                  :
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool TemplateInterpreterGenerator::is_intrinsic_method(AbstractInterpreter::MethodKind kind) {
+  switch (kind) {
+    case Interpreter::zerolocals                     : // fall thru
+    case Interpreter::zerolocals_synchronized        : // fall thru
+    case Interpreter::zerolocals_upcalls             : // fall thru
+    case Interpreter::zerolocals_synchronized_upcalls: // fall thru
+    case Interpreter::native                         : // fall thru
+    case Interpreter::native_synchronized            : // fall thru
+    case Interpreter::native_upcalls                 : // fall thru
+    case Interpreter::native_synchronized_upcalls    : // fall thru
+    case Interpreter::empty                          : // fall thru
+    case Interpreter::empty_upcalls                  : // fall thru
+    case Interpreter::getter                         : // fall thru
+    case Interpreter::setter                         : // fall thru
+    case Interpreter::abstract                       :
+      return false;
+    default:
+      return true;
+  }
+}
+
+bool TemplateInterpreterGenerator::is_abstract_method(AbstractInterpreter::MethodKind kind) {
+  switch (kind) {
+    case Interpreter::abstract:
+      return true;
+    default:
+      return false;
+  }
+}
+
 // Generate method entries
 address TemplateInterpreterGenerator::generate_method_entry(
                                         AbstractInterpreter::MethodKind kind, bool native) {
-  // determine code generation flags
-  bool synchronized = false;
   address entry_point = nullptr;
 
-  switch (kind) {
-  case Interpreter::zerolocals             :                           break;
-  case Interpreter::zerolocals_synchronized: synchronized = true;      break;
-  case Interpreter::native                 :                           break;
-  case Interpreter::native_synchronized    : synchronized = true;      break;
-  case Interpreter::empty                  : break;
-  case Interpreter::getter                 : break;
-  case Interpreter::setter                 : break;
-  case Interpreter::abstract               : entry_point = generate_abstract_entry(); break;
-  default:
-    entry_point = generate_intrinsic_entry(kind); // process the rest
-    break;
+  if (is_abstract_method(kind)) {
+    entry_point = generate_abstract_entry();
+  } else if (is_intrinsic_method(kind)) {
+    entry_point = generate_intrinsic_entry(kind);
   }
 
   if (entry_point) {
     return entry_point;
   }
 
+  bool synchronized = is_synchronized_method(kind);
+  bool upcalls = is_runtime_upcalls_method(kind);
+
   // We expect the normal and native entry points to be generated first so we can reuse them.
-  if (native) {
-    entry_point = Interpreter::entry_for_kind(synchronized ? Interpreter::native_synchronized : Interpreter::native);
-    if (entry_point == nullptr) {
-      entry_point = generate_native_entry(synchronized);
-    }
-  } else {
-    entry_point = Interpreter::entry_for_kind(synchronized ? Interpreter::zerolocals_synchronized : Interpreter::zerolocals);
-    if (entry_point == nullptr) {
-      entry_point = generate_normal_entry(synchronized);
-    }
+  if (!synchronized && !upcalls) {
+    entry_point = Interpreter::entry_for_kind(native ? Interpreter::native
+                                                     : Interpreter::zerolocals);
+  } else if (synchronized && !upcalls) {
+    entry_point = Interpreter::entry_for_kind(native ? Interpreter::native_synchronized
+                                                     : Interpreter::zerolocals_synchronized);
+  } else if (!synchronized && upcalls) {
+    entry_point = Interpreter::entry_for_kind(native ? Interpreter::native_upcalls
+                                                     : Interpreter::zerolocals_upcalls);
+  } else if (synchronized && upcalls) {
+    entry_point = Interpreter::entry_for_kind(native ? Interpreter::native_synchronized_upcalls
+                                                     : Interpreter::zerolocals_synchronized_upcalls);
+  }
+
+  if (entry_point == nullptr) {
+      entry_point = native ? generate_native_entry(synchronized, upcalls)
+                           : generate_normal_entry(synchronized, upcalls);
   }
 
   return entry_point;
 }
 
