Merge
authoradlertz
Fri, 12 Sep 2014 09:17:58 +0200
changeset 26589 7ee62410eae6
parent 26575 9d01d41f1aa7 (current diff)
parent 26588 b14c202acbe6 (diff)
child 26590 adcfefdf5bb4
Merge
hotspot/make/Makefile
hotspot/src/share/vm/runtime/os.hpp
--- a/hotspot/make/Makefile	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/make/Makefile	Fri Sep 12 09:17:58 2014 +0200
@@ -95,6 +95,7 @@
 COMMON_VM_PRODUCT_TARGETS=product product1 docs export_product
 COMMON_VM_FASTDEBUG_TARGETS=fastdebug fastdebug1 docs export_fastdebug
 COMMON_VM_DEBUG_TARGETS=debug debug1 docs export_debug
+COMMON_VM_OPTIMIZED_TARGETS=optimized optimized1 docs export_optimized
 
 # JDK directory list
 JDK_DIRS=bin include jre lib demo
@@ -111,20 +112,21 @@
 all_product:   product1 docs export_product
 all_fastdebug: fastdebug1 docs export_fastdebug
 all_debug:     debug1 docs export_debug
+all_optimized: optimized1 docs export_optimized
 else
 ifeq ($(MACOSX_UNIVERSAL),true)
 all_product:   universal_product
 all_fastdebug: universal_fastdebug
 all_debug:     universal_debug
+all_optimized: universal_optimized
 else
 all_product:   $(COMMON_VM_PRODUCT_TARGETS)
 all_fastdebug: $(COMMON_VM_FASTDEBUG_TARGETS)
 all_debug:     $(COMMON_VM_DEBUG_TARGETS)
+all_optimized: $(COMMON_VM_OPTIMIZED_TARGETS)
 endif
 endif
 
-all_optimized: optimized optimized1 docs export_optimized
-
 allzero:           all_productzero all_fastdebugzero
 all_productzero:   productzero docs export_product
 all_fastdebugzero: fastdebugzero docs export_fastdebug
--- a/hotspot/make/bsd/makefiles/universal.gmk	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/make/bsd/makefiles/universal.gmk	Fri Sep 12 09:17:58 2014 +0200
@@ -25,6 +25,8 @@
 # macosx universal builds
 universal_product:
 	$(MAKE) MACOSX_UNIVERSAL=true all_product_universal
+universal_optimized:
+	$(MAKE) MACOSX_UNIVERSAL=true all_optimized_universal
 universal_fastdebug:
 	$(MAKE) MACOSX_UNIVERSAL=true all_fastdebug_universal
 universal_debug:
@@ -36,6 +38,10 @@
 #	$(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_PRODUCT_TARGETS)
 	$(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_PRODUCT_TARGETS)
 	$(QUIETLY) $(MAKE) BUILD_FLAVOR=product EXPORT_SUBDIR= universalize
+all_optimized_universal:
+#	$(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_OPTIMIZED_TARGETS)
+	$(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_OPTIMIZED_TARGETS)
+	$(QUIETLY) $(MAKE) BUILD_FLAVOR=optimized EXPORT_SUBDIR=/optimized universalize
 all_fastdebug_universal:
 #	$(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_FASTDEBUG_TARGETS)
 	$(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_FASTDEBUG_TARGETS)
@@ -98,13 +104,15 @@
 export_product_jdk::
 	$(MAKE) EXPORT_SUBDIR=           export_universal
 export_optimized_jdk::
-	$(MAKE) EXPORT_SUBDIR=           export_universal
+	$(MAKE) EXPORT_SUBDIR=/optimized export_universal
 export_fastdebug_jdk::
 	$(MAKE) EXPORT_SUBDIR=/fastdebug export_universal
 export_debug_jdk::
 	$(MAKE) EXPORT_SUBDIR=/debug     export_universal
 copy_product_jdk::
 	$(MAKE) COPY_SUBDIR=             copy_universal
+copy_optimized_jdk::
+	$(MAKE) COPY_SUBDIR=/optimized   copy_universal
 copy_fastdebug_jdk::
 	$(MAKE) COPY_SUBDIR=/fastdebug   copy_universal
 copy_debug_jdk::
@@ -112,5 +120,6 @@
 
 .PHONY:	universal_product universal_fastdebug universal_debug \
 	all_product_universal all_fastdebug_universal all_debug_universal \
+	universal_optimized all_optimized_universal \
 	universalize export_universal copy_universal \
 	$(UNIVERSAL_LIPO_LIST) $(UNIVERSAL_COPY_LIST)
--- a/hotspot/make/solaris/makefiles/vm.make	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/make/solaris/makefiles/vm.make	Fri Sep 12 09:17:58 2014 +0200
@@ -143,7 +143,7 @@
 LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle
 endif # sparcWorks
 
-LIBS += -lkstat
+LIBS += -lkstat -lpicl
 
 # By default, link the *.o into the library, not the executable.
 LINK_INTO$(LINK_INTO) = LIBJVM
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -32,6 +32,7 @@
 
 int VM_Version::_features = VM_Version::unknown_m;
 const char* VM_Version::_features_str = "";
+unsigned int VM_Version::_L2_cache_line_size = 0;
 
 void VM_Version::initialize() {
   _features = determine_features();
@@ -192,7 +193,7 @@
   }
 
   assert(BlockZeroingLowLimit > 0, "invalid value");
-  if (has_block_zeroing()) {
+  if (has_block_zeroing() && cache_line_size > 0) {
     if (FLAG_IS_DEFAULT(UseBlockZeroing)) {
       FLAG_SET_DEFAULT(UseBlockZeroing, true);
     }
@@ -202,7 +203,7 @@
   }
 
   assert(BlockCopyLowLimit > 0, "invalid value");
-  if (has_block_zeroing()) { // has_blk_init() && is_T4(): core's local L2 cache
+  if (has_block_zeroing() && cache_line_size > 0) { // has_blk_init() && is_T4(): core's local L2 cache
     if (FLAG_IS_DEFAULT(UseBlockCopy)) {
       FLAG_SET_DEFAULT(UseBlockCopy, true);
     }
@@ -252,49 +253,6 @@
   // buf is started with ", " or is empty
   _features_str = os::strdup(strlen(buf) > 2 ? buf + 2 : buf);
 
-  // There are three 64-bit SPARC families that do not overlap, e.g.,
-  // both is_ultra3() and is_sparc64() cannot be true at the same time.
-  // Within these families, there can be more than one chip, e.g.,
-  // is_T4() and is_T7() machines are also is_niagara().
-  if (is_ultra3()) {
-    assert(_L1_data_cache_line_size == 0, "overlap with Ultra3 family");
-    // Ref: UltraSPARC III Cu Processor
-    _L1_data_cache_line_size = 64;
-  }
-  if (is_niagara()) {
-    assert(_L1_data_cache_line_size == 0, "overlap with niagara family");
-    // All Niagara's are sun4v's, but not all sun4v's are Niagaras, e.g.,
-    // Fujitsu SPARC64 is sun4v, but we don't want it in this block.
-    //
-    // Ref: UltraSPARC T1 Supplement to the UltraSPARC Architecture 2005
-    // Appendix F.1.3.1 Cacheable Accesses
-    // -> 16-byte L1 cache line size
-    //
-    // Ref: UltraSPARC T2: A Highly-Threaded, Power-Efficient, SPARC SOC
-    // Section III: SPARC Processor Core
-    // -> 16-byte L1 cache line size
-    //
-    // Ref: Oracle's SPARC T4-1, SPARC T4-2, SPARC T4-4, and SPARC T4-1B Server Architecture
-    // Section SPARC T4 Processor Cache Architecture
-    // -> 32-byte L1 cache line size (no longer see that info on this ref)
-    //
-    // XXX - still need a T7 reference here
-    //
-    if (is_T7()) {  // T7 or newer
-      _L1_data_cache_line_size = 64;
-    } else if (is_T4()) {  // T4 or newer (until T7)
-      _L1_data_cache_line_size = 32;
-    } else {  // T1 or newer (until T4)
-      _L1_data_cache_line_size = 16;
-    }
-  }
-  if (is_sparc64()) {
-    guarantee(_L1_data_cache_line_size == 0, "overlap with SPARC64 family");
-    // Ref: Fujitsu SPARC64 VII Processor
-    // Section 4 Cache System
-    _L1_data_cache_line_size = 64;
-  }
-
   // UseVIS is set to the smallest of what hardware supports and what
   // the command line requires.  I.e., you cannot set UseVIS to 3 on
   // older UltraSparc which do not support it.
@@ -401,6 +359,7 @@
 #ifndef PRODUCT
   if (PrintMiscellaneous && Verbose) {
     tty->print_cr("L1 data cache line size: %u", L1_data_cache_line_size());
+    tty->print_cr("L2 cache line size: %u", L2_cache_line_size());
     tty->print("Allocation");
     if (AllocatePrefetchStyle <= 0) {
       tty->print_cr(": no prefetching");
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp	Fri Sep 12 09:17:58 2014 +0200
@@ -96,6 +96,9 @@
   static int  _features;
   static const char* _features_str;
 
+  static unsigned int _L2_cache_line_size;
+  static unsigned int L2_cache_line_size() { return _L2_cache_line_size; }
+
   static void print_features();
   static int  determine_features();
   static int  platform_features(int features);
@@ -167,9 +170,8 @@
 
   static const char* cpu_features()     { return _features_str; }
 
-  static intx prefetch_data_size()  {
-    return is_T4() && !is_T7() ? 32 : 64;  // default prefetch block size on sparc
-  }
+  // default prefetch block size on sparc
+  static intx prefetch_data_size()      { return L2_cache_line_size();  }
 
   // Prefetch
   static intx prefetch_copy_interval_in_bytes() {
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Fri Sep 12 09:17:58 2014 +0200
@@ -26,6 +26,7 @@
 #define CPU_X86_VM_ASSEMBLER_X86_HPP
 
 #include "asm/register.hpp"
+#include "vm_version_x86.hpp"
 
 class BiasedLockingCounters;
 
@@ -1292,14 +1293,34 @@
       if (order_constraint & StoreLoad) {
         // All usable chips support "locked" instructions which suffice
         // as barriers, and are much faster than the alternative of
-        // using cpuid instruction. We use here a locked add [esp],0.
+        // using cpuid instruction. We use here a locked add [esp-C],0.
         // This is conveniently otherwise a no-op except for blowing
-        // flags.
+        // flags, and introducing a false dependency on target memory
+        // location. We can't do anything with flags, but we can avoid
+        // memory dependencies in the current method by locked-adding
+        // somewhere else on the stack. Doing [esp+C] will collide with
+        // something on stack in current method, hence we go for [esp-C].
+        // It is convenient since it is almost always in data cache, for
+        // any small C.  We need to step back from SP to avoid data
+        // dependencies with other things on below SP (callee-saves, for
+        // example). Without a clear way to figure out the minimal safe
+        // distance from SP, it makes sense to step back the complete
+        // cache line, as this will also avoid possible second-order effects
+        // with locked ops against the cache line. Our choice of offset
+        // is bounded by x86 operand encoding, which should stay within
+        // [-128; +127] to have the 8-byte displacement encoding.
+        //
         // Any change to this code may need to revisit other places in
         // the code where this idiom is used, in particular the
         // orderAccess code.
+
+        int offset = -VM_Version::L1_line_size();
+        if (offset < -128) {
+          offset = -128;
+        }
+
         lock();
-        addl(Address(rsp, 0), 0);// Assert the lock# signal here
+        addl(Address(rsp, offset), 0);// Assert the lock# signal here
       }
     }
   }
--- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -563,3 +563,8 @@
   assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
 }
 #endif
+
+int os::extra_bang_size_in_bytes() {
+  // PPC does not require the additional stack bang.
+  return 0;
+}
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -1030,3 +1030,8 @@
 void os::verify_stack_alignment() {
 }
 #endif
+
+int os::extra_bang_size_in_bytes() {
+  // JDK-8050147 requires the full cache line bang for x86.
+  return VM_Version::L1_line_size();
+}
--- a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -465,3 +465,8 @@
 void os::verify_stack_alignment() {
 }
 #endif
+
+int os::extra_bang_size_in_bytes() {
+  // Zero does not require an additional stack bang.
+  return 0;
+}
--- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -612,3 +612,8 @@
   assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
 }
 #endif
+
+int os::extra_bang_size_in_bytes() {
+  // PPC does not require the additional stack bang.
+  return 0;
+}
--- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -752,3 +752,8 @@
 void os::verify_stack_alignment() {
 }
 #endif
+
+int os::extra_bang_size_in_bytes() {
+  // SPARC does not require the additional stack bang.
+  return 0;
+}
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -930,3 +930,8 @@
   // keep the page mapped so CS limit isn't reduced.
 #endif
 }
+
+int os::extra_bang_size_in_bytes() {
+  // JDK-8050147 requires the full cache line bang for x86.
+  return VM_Version::L1_line_size();
+}
--- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -495,3 +495,8 @@
 void os::verify_stack_alignment() {
 }
 #endif
+
+int os::extra_bang_size_in_bytes() {
+  // Zero does not require an additional stack banging.
+  return 0;
+}
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -774,3 +774,8 @@
 void os::verify_stack_alignment() {
 }
 #endif
+
+int os::extra_bang_size_in_bytes() {
+  // SPARC does not require an additional stack bang.
+  return 0;
+}
--- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -28,10 +28,140 @@
 #include "runtime/os.hpp"
 #include "vm_version_sparc.hpp"
 
-# include <sys/auxv.h>
-# include <sys/auxv_SPARC.h>
-# include <sys/systeminfo.h>
-# include <kstat.h>
+#include <sys/auxv.h>
+#include <sys/auxv_SPARC.h>
+#include <sys/systeminfo.h>
+#include <kstat.h>
+#include <picl.h>
+
+extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
+extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
+
+class PICL {
+  // Get a value of the integer property. The value in the tree can be either 32 or 64 bit
+  // depending on the platform. The result is converted to int.
+  static int get_int_property(picl_nodehdl_t nodeh, const char* name, int* result) {
+    picl_propinfo_t pinfo;
+    picl_prophdl_t proph;
+    if (picl_get_prop_by_name(nodeh, name, &proph) != PICL_SUCCESS ||
+        picl_get_propinfo(proph, &pinfo) != PICL_SUCCESS) {
+      return PICL_FAILURE;
+    }
+
+    if (pinfo.type != PICL_PTYPE_INT && pinfo.type != PICL_PTYPE_UNSIGNED_INT) {
+      assert(false, "Invalid property type");
+      return PICL_FAILURE;
+    }
+    if (pinfo.size == sizeof(int64_t)) {
+      int64_t val;
+      if (picl_get_propval(proph, &val, sizeof(int64_t)) != PICL_SUCCESS) {
+        return PICL_FAILURE;
+      }
+      *result = static_cast<int>(val);
+    } else if (pinfo.size == sizeof(int32_t)) {
+      int32_t val;
+      if (picl_get_propval(proph, &val, sizeof(int32_t)) != PICL_SUCCESS) {
+        return PICL_FAILURE;
+      }
+      *result = static_cast<int>(val);
+    } else {
+      assert(false, "Unexpected integer property size");
+      return PICL_FAILURE;
+    }
+    return PICL_SUCCESS;
+  }
+
+  // Visitor and a state machine that visits integer properties and verifies that the
+  // values are the same. Stores the unique value observed.
+  class UniqueValueVisitor {
+    enum {
+      INITIAL,        // Start state, no assignments happened
+      ASSIGNED,       // Assigned a value
+      INCONSISTENT    // Inconsistent value seen
+    } _state;
+    int _value;
+  public:
+    UniqueValueVisitor() : _state(INITIAL) { }
+    int value() {
+      assert(_state == ASSIGNED, "Precondition");
+      return _value;
+    }
+    void set_value(int value) {
+      assert(_state == INITIAL, "Precondition");
+      _value = value;
+      _state = ASSIGNED;
+    }
+    bool is_initial()       { return _state == INITIAL;      }
+    bool is_assigned()      { return _state == ASSIGNED;     }
+    bool is_inconsistent()  { return _state == INCONSISTENT; }
+    void set_inconsistent() { _state = INCONSISTENT;         }
+
+    static int visit(picl_nodehdl_t nodeh, const char* name, void *arg) {
+      UniqueValueVisitor *state = static_cast<UniqueValueVisitor*>(arg);
+      assert(!state->is_inconsistent(), "Precondition");
+      int curr;
+      if (PICL::get_int_property(nodeh, name, &curr) == PICL_SUCCESS) {
+        if (!state->is_assigned()) { // first iteration
+          state->set_value(curr);
+        } else if (curr != state->value()) { // following iterations
+          state->set_inconsistent();
+        }
+      }
+      if (state->is_inconsistent()) {
+        return PICL_WALK_TERMINATE;
+      }
+      return PICL_WALK_CONTINUE;
+    }
+  };
+
+  int _L1_data_cache_line_size;
+  int _L2_cache_line_size;
+public:
+  static int get_l1_data_cache_line_size(picl_nodehdl_t nodeh, void *state) {
+    return UniqueValueVisitor::visit(nodeh, "l1-dcache-line-size", state);
+  }
+  static int get_l2_cache_line_size(picl_nodehdl_t nodeh, void *state) {
+    return UniqueValueVisitor::visit(nodeh, "l2-cache-line-size", state);
+  }
+
+  PICL() : _L1_data_cache_line_size(0), _L2_cache_line_size(0) {
+    if (picl_initialize() == PICL_SUCCESS) {
+      picl_nodehdl_t rooth;
+      if (picl_get_root(&rooth) == PICL_SUCCESS) {
+        UniqueValueVisitor L1_state;
+        // Visit all "cpu" class instances
+        picl_walk_tree_by_class(rooth, "cpu", &L1_state, PICL_get_l1_data_cache_line_size_helper);
+        if (L1_state.is_initial()) { // Still initial, iteration found no values
+          // Try walk all "core" class instances, it might be a Fujitsu machine
+          picl_walk_tree_by_class(rooth, "core", &L1_state, PICL_get_l1_data_cache_line_size_helper);
+        }
+        if (L1_state.is_assigned()) { // Is there a value?
+          _L1_data_cache_line_size = L1_state.value();
+        }
+
+        UniqueValueVisitor L2_state;
+        picl_walk_tree_by_class(rooth, "cpu", &L2_state, PICL_get_l2_cache_line_size_helper);
+        if (L2_state.is_initial()) {
+          picl_walk_tree_by_class(rooth, "core", &L2_state, PICL_get_l2_cache_line_size_helper);
+        }
+        if (L2_state.is_assigned()) {
+          _L2_cache_line_size = L2_state.value();
+        }
+      }
+      picl_shutdown();
+    }
+  }
+
+  unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; }
+  unsigned int L2_cache_line_size() const      { return _L2_cache_line_size;      }
+};
+
+extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
+  return PICL::get_l1_data_cache_line_size(nodeh, result);
+}
+extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
+  return PICL::get_l2_cache_line_size(nodeh, result);
+}
 
 // We need to keep these here as long as we have to build on Solaris
 // versions before 10.
@@ -211,5 +341,10 @@
     kstat_close(kc);
   }
 
+  // Figure out cache line sizes using PICL
+  PICL picl;
+  _L1_data_cache_line_size = picl.L1_data_cache_line_size();
+  _L2_cache_line_size      = picl.L2_cache_line_size();
+
   return features;
 }
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -918,3 +918,8 @@
 #endif
 }
 #endif
+
+int os::extra_bang_size_in_bytes() {
+  // JDK-8050147 requires the full cache line bang for x86.
+  return VM_Version::L1_line_size();
+}
--- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -639,3 +639,8 @@
 #endif
 }
 #endif
+
+int os::extra_bang_size_in_bytes() {
+  // JDK-8050147 requires the full cache line bang for x86.
+  return VM_Version::L1_line_size();
+}
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -170,7 +170,7 @@
 // removes the need to bang the stack in the deoptimization blob which
 // in turn simplifies stack overflow handling.
 int LIR_Assembler::bang_size_in_bytes() const {
-  return MAX2(initial_frame_size_in_bytes(), _compilation->interpreter_frame_size());
+  return MAX2(initial_frame_size_in_bytes() + os::extra_bang_size_in_bytes(), _compilation->interpreter_frame_size());
 }
 
 void LIR_Assembler::emit_exception_entries(ExceptionInfoList* info_list) {
--- a/hotspot/src/share/vm/ci/ciEnv.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -926,7 +926,7 @@
 #ifdef ASSERT
     if (!counter_changed && !PrintCompilation) {
       // Print out the compile task that failed
-      _task->print_line();
+      _task->print_tty();
     }
 #endif
     assert(counter_changed, "failed dependencies, but counter didn't change");
--- a/hotspot/src/share/vm/classfile/classLoader.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -1528,7 +1528,7 @@
               if (TieredCompilation && TieredStopAtLevel >= CompLevel_full_optimization) {
                 // Clobber the first compile and force second tier compilation
                 nmethod* nm = m->code();
-                if (nm != NULL) {
+                if (nm != NULL && !m->is_method_handle_intrinsic()) {
                   // Throw out the code so that the code cache doesn't fill up
                   nm->make_not_entrant();
                   m->clear_code();
@@ -1547,7 +1547,7 @@
             }
 
             nmethod* nm = m->code();
-            if (nm != NULL) {
+            if (nm != NULL && !m->is_method_handle_intrinsic()) {
               // Throw out the code so that the code cache doesn't fill up
               nm->make_not_entrant();
               m->clear_code();
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -52,6 +52,7 @@
 #include "oops/typeArrayKlass.hpp"
 #include "prims/jvmtiEnvBase.hpp"
 #include "prims/methodHandles.hpp"
+#include "runtime/arguments.hpp"
 #include "runtime/biasedLocking.hpp"
 #include "runtime/fieldType.hpp"
 #include "runtime/handles.inline.hpp"
@@ -2274,7 +2275,11 @@
     m = Method::make_method_handle_intrinsic(iid, signature, CHECK_(empty));
     CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_highest_tier,
                                   methodHandle(), CompileThreshold, "MH", CHECK_(empty));
-
+    // Check if we need to have compiled code but we don't.
+    if (!Arguments::is_interpreter_only() && !m->has_compiled_code()) {
+      THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(),
+                 "out of space in CodeCache for method handle intrinsic", empty);
+    }
     // Now grab the lock.  We might have to throw away the new method,
     // if a racing thread has managed to install one at the same time.
     {
@@ -2288,6 +2293,9 @@
   }
 
   assert(spe != NULL && spe->method() != NULL, "");
+  assert(Arguments::is_interpreter_only() || (spe->method()->has_compiled_code() &&
+         spe->method()->code()->entry_point() == spe->method()->from_compiled_entry()),
+         "MH intrinsic invariant");
   return spe->method();
 }
 
--- a/hotspot/src/share/vm/code/codeCache.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/code/codeCache.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -249,6 +249,7 @@
 #define FOR_ALL_BLOBS(var)       for (CodeBlob *var =       first() ; var != NULL; var =       next(var) )
 #define FOR_ALL_ALIVE_BLOBS(var) for (CodeBlob *var = alive(first()); var != NULL; var = alive(next(var)))
 #define FOR_ALL_ALIVE_NMETHODS(var) for (nmethod *var = alive_nmethod(first()); var != NULL; var = alive_nmethod(next(var)))
+#define FOR_ALL_NMETHODS(var) for (nmethod *var = first_nmethod(); var != NULL; var = next_nmethod(var))
 
 
 bool CodeCache::contains(void *p) {
@@ -687,7 +688,9 @@
 void CodeCache::mark_all_nmethods_for_deoptimization() {
   MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   FOR_ALL_ALIVE_NMETHODS(nm) {
-    nm->mark_for_deoptimization();
+    if (!nm->method()->is_method_handle_intrinsic()) {
+      nm->mark_for_deoptimization();
+    }
   }
 }
 
@@ -967,6 +970,25 @@
   }
 }
 
+void CodeCache::print_codelist(outputStream* st) {
+  assert_locked_or_safepoint(CodeCache_lock);
+
+  FOR_ALL_NMETHODS(p) {
+    ResourceMark rm;
+    char *method_name = p->method()->name_and_sig_as_C_string();
+    st->print_cr("%d %d %s ["INTPTR_FORMAT", "INTPTR_FORMAT" - "INTPTR_FORMAT"]",
+                 p->compile_id(), p->comp_level(), method_name, (intptr_t)p->header_begin(),
+                 (intptr_t)p->code_begin(), (intptr_t)p->code_end());
+  }
+}
+
+void CodeCache::print_layout(outputStream* st) {
+  assert_locked_or_safepoint(CodeCache_lock);
+  ResourceMark rm;
+
+  print_summary(st, true);
+}
+
 void CodeCache::log_state(outputStream* st) {
   st->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'"
             " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
--- a/hotspot/src/share/vm/code/codeCache.hpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/code/codeCache.hpp	Fri Sep 12 09:17:58 2014 +0200
@@ -152,6 +152,10 @@
   static void print_summary(outputStream* st, bool detailed = true); // Prints a summary of the code cache usage
   static void log_state(outputStream* st);
 
+  // Dcmd (Diagnostic commands)
+  static void print_codelist(outputStream* st);
+  static void print_layout(outputStream* st);
+
   // The full limits of the codeCache
   static address  low_bound()                    { return (address) _heap->low_boundary(); }
   static address  high_bound()                   { return (address) _heap->high_boundary(); }
--- a/hotspot/src/share/vm/code/compiledIC.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/code/compiledIC.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -595,6 +595,7 @@
   } else {
     // Callee is interpreted code.  In any case entering the interpreter
     // puts a converter-frame on the stack to save arguments.
+    assert(!m->is_method_handle_intrinsic(), "Compiled code should never call interpreter MH intrinsics");
     info._to_interpreter = true;
     info._entry      = m()->get_c2i_entry();
   }
--- a/hotspot/src/share/vm/code/nmethod.hpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/code/nmethod.hpp	Fri Sep 12 09:17:58 2014 +0200
@@ -448,7 +448,10 @@
   // alive.  It is used when an uncommon trap happens.  Returns true
   // if this thread changed the state of the nmethod or false if
   // another thread performed the transition.
-  bool  make_not_entrant() { return make_not_entrant_or_zombie(not_entrant); }
+  bool  make_not_entrant() {
+    assert(!method()->is_method_handle_intrinsic(), "Cannot make MH intrinsic not entrant");
+    return make_not_entrant_or_zombie(not_entrant);
+  }
   bool  make_zombie()      { return make_not_entrant_or_zombie(zombie); }
 
   // used by jvmti to track if the unload event has been reported
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -166,7 +166,7 @@
     StringLogMessage lm;
     stringStream sstr = lm.stream();
     // msg.time_stamp().update_to(tty->time_stamp().ticks());
-    task->print_compilation(&sstr, NULL, true);
+    task->print_compilation(&sstr, NULL, true, false);
     log(thread, "%s", (const char*)lm);
   }
 
@@ -328,7 +328,6 @@
   if (nm == NULL)  _code_handle = NULL;  // drop the handle also
 }
 
-
 void CompileTask::mark_on_stack() {
   // Mark these methods as something redefine classes cannot remove.
   _method->set_on_stack(true);
@@ -338,18 +337,6 @@
 }
 
 // ------------------------------------------------------------------
-// CompileTask::print
-void CompileTask::print() {
-  tty->print("<CompileTask compile_id=%d ", _compile_id);
-  tty->print("method=");
-  _method->print_name(tty);
-  tty->print_cr(" osr_bci=%d is_blocking=%s is_complete=%s is_success=%s>",
-             _osr_bci, bool_to_str(_is_blocking),
-             bool_to_str(_is_complete), bool_to_str(_is_success));
-}
-
-
-// ------------------------------------------------------------------
 // CompileTask::print_line_on_error
 //
 // This function is called by fatal error handler when the thread
@@ -367,19 +354,18 @@
 
 // ------------------------------------------------------------------
 // CompileTask::print_line
-void CompileTask::print_line() {
+void CompileTask::print_tty() {
   ttyLocker ttyl;  // keep the following output all in one block
   // print compiler name if requested
   if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level()));
-  print_compilation();
+    print_compilation(tty);
 }
 
-
 // ------------------------------------------------------------------
 // CompileTask::print_compilation_impl
 void CompileTask::print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level,
                                          bool is_osr_method, int osr_bci, bool is_blocking,
-                                         const char* msg, bool short_form) {
+                                         const char* msg, bool short_form, bool cr) {
   if (!short_form) {
     st->print("%7d ", (int) st->time_stamp().milliseconds());  // print timestamp
   }
@@ -428,7 +414,7 @@
   if (msg != NULL) {
     st->print("   %s", msg);
   }
-  if (!short_form) {
+  if (cr) {
     st->cr();
   }
 }
@@ -494,9 +480,9 @@
 
 // ------------------------------------------------------------------
 // CompileTask::print_compilation
-void CompileTask::print_compilation(outputStream* st, const char* msg, bool short_form) {
+void CompileTask::print_compilation(outputStream* st, const char* msg, bool short_form, bool cr) {
   bool is_osr_method = osr_bci() != InvocationEntryBci;
-  print_compilation_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form);
+  print_compilation_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form, cr);
 }
 
 // ------------------------------------------------------------------
@@ -621,7 +607,9 @@
   // Mark the method as being in the compile queue.
   task->method()->set_queued_for_compilation();
 
-  NOT_PRODUCT(print();)
+  if (CIPrintCompileQueue) {
+    print_tty();
+  }
 
   if (LogCompilation && xtty != NULL) {
     task->log_task_queued();
@@ -786,24 +774,40 @@
   }
 }
 
-#ifndef PRODUCT
-/**
- * Print entire compilation queue.
- */
-void CompileQueue::print() {
-  if (CIPrintCompileQueue) {
-    ttyLocker ttyl;
-    tty->print_cr("Contents of %s", name());
-    tty->print_cr("----------------------");
-    CompileTask* task = _first;
+
+CompileQueue* CompileBroker::compile_queue(int comp_level) {
+  if (is_c2_compile(comp_level)) return _c2_compile_queue;
+  if (is_c1_compile(comp_level)) return _c1_compile_queue;
+  return NULL;
+}
+
+
+void CompileBroker::print_compile_queues(outputStream* st) {
+  _c1_compile_queue->print(st);
+  _c2_compile_queue->print(st);
+}
+
+
+void CompileQueue::print(outputStream* st) {
+  assert_locked_or_safepoint(lock());
+  st->print_cr("Contents of %s", name());
+  st->print_cr("----------------------------");
+  CompileTask* task = _first;
+  if (task == NULL) {
+    st->print_cr("Empty");;
+  } else {
     while (task != NULL) {
-      task->print_line();
+      task->print_compilation(st, NULL, true, true);
       task = task->next();
     }
-    tty->print_cr("----------------------");
   }
+  st->print_cr("----------------------------");
 }
-#endif // PRODUCT
+
+void CompileQueue::print_tty() {
+  ttyLocker ttyl;
+  print(tty);
+}
 
 CompilerCounters::CompilerCounters(const char* thread_name, int instance, TRAPS) {
 
@@ -1068,11 +1072,11 @@
 #endif // !ZERO && !SHARK
   // Initialize the compilation queue
   if (c2_compiler_count > 0) {
-    _c2_compile_queue  = new CompileQueue("C2 CompileQueue",  MethodCompileQueue_lock);
+    _c2_compile_queue  = new CompileQueue("C2 compile queue",  MethodCompileQueue_lock);
     _compilers[1]->set_num_compiler_threads(c2_compiler_count);
   }
   if (c1_compiler_count > 0) {
-    _c1_compile_queue  = new CompileQueue("C1 CompileQueue",  MethodCompileQueue_lock);
+    _c1_compile_queue  = new CompileQueue("C1 compile queue",  MethodCompileQueue_lock);
     _compilers[0]->set_num_compiler_threads(c1_compiler_count);
   }
 
@@ -1892,7 +1896,7 @@
 void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
   if (PrintCompilation) {
     ResourceMark rm;
-    task->print_line();
+    task->print_tty();
   }
   elapsedTimer time;
 
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/compiler/compileBroker.hpp	Fri Sep 12 09:17:58 2014 +0200
@@ -111,14 +111,14 @@
 private:
   static void  print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level,
                                       bool is_osr_method = false, int osr_bci = -1, bool is_blocking = false,
-                                      const char* msg = NULL, bool short_form = false);
+                                      const char* msg = NULL, bool short_form = false, bool cr = true);
 
 public:
-  void         print_compilation(outputStream* st = tty, const char* msg = NULL, bool short_form = false);
-  static void  print_compilation(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false) {
+  void         print_compilation(outputStream* st = tty, const char* msg = NULL, bool short_form = false, bool cr = true);
+  static void  print_compilation(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false, bool cr = true) {
     print_compilation_impl(st, nm->method(), nm->compile_id(), nm->comp_level(),
                            nm->is_osr_method(), nm->is_osr_method() ? nm->osr_entry_bci() : -1, /*is_blocking*/ false,
-                           msg, short_form);
+                           msg, short_form, cr);
   }
 
   static void  print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg = NULL);
@@ -131,8 +131,7 @@
 
   static void  print_inline_indent(int inline_level, outputStream* st = tty);
 
-  void         print();
-  void         print_line();
+  void         print_tty();
   void         print_line_on_error(outputStream* st, char* buf, int buflen);
 
   void         log_task(xmlStream* log);
@@ -234,7 +233,8 @@
   // Redefine Classes support
   void mark_on_stack();
   void free_all();
-  NOT_PRODUCT (void print();)
+  void print_tty();
+  void print(outputStream* st = tty);
 
   ~CompileQueue() {
     assert (is_empty(), " Compile Queue must be empty");
@@ -341,7 +341,7 @@
   static void init_compiler_threads(int c1_compiler_count, int c2_compiler_count);
   static bool compilation_is_complete  (methodHandle method, int osr_bci, int comp_level);
   static bool compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level);
-  static bool is_compile_blocking      ();
+  static bool is_compile_blocking();
   static void preload_classes          (methodHandle method, TRAPS);
 
   static CompileTask* create_compile_task(CompileQueue* queue,
@@ -369,11 +369,8 @@
                                   int hot_count,
                                   const char* comment,
                                   Thread* thread);
-  static CompileQueue* compile_queue(int comp_level) {
-    if (is_c2_compile(comp_level)) return _c2_compile_queue;
-    if (is_c1_compile(comp_level)) return _c1_compile_queue;
-    return NULL;
-  }
+
+  static CompileQueue* compile_queue(int comp_level);
   static bool init_compiler_runtime();
   static void shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread);
 
@@ -390,6 +387,7 @@
   }
 
   static bool compilation_is_in_queue(methodHandle method);
+  static void print_compile_queues(outputStream* st);
   static int queue_size(int comp_level) {
     CompileQueue *q = compile_queue(comp_level);
     return q != NULL ? q->size() : 0;
--- a/hotspot/src/share/vm/oops/method.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/oops/method.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -1635,34 +1635,34 @@
 }
 
 int Method::highest_comp_level() const {
-  const MethodData* mdo = method_data();
-  if (mdo != NULL) {
-    return mdo->highest_comp_level();
+  const MethodCounters* mcs = method_counters();
+  if (mcs != NULL) {
+    return mcs->highest_comp_level();
   } else {
     return CompLevel_none;
   }
 }
 
 int Method::highest_osr_comp_level() const {
-  const MethodData* mdo = method_data();
-  if (mdo != NULL) {
-    return mdo->highest_osr_comp_level();
+  const MethodCounters* mcs = method_counters();
+  if (mcs != NULL) {
+    return mcs->highest_osr_comp_level();
   } else {
     return CompLevel_none;
   }
 }
 
 void Method::set_highest_comp_level(int level) {
-  MethodData* mdo = method_data();
-  if (mdo != NULL) {
-    mdo->set_highest_comp_level(level);
+  MethodCounters* mcs = method_counters();
+  if (mcs != NULL) {
+    mcs->set_highest_comp_level(level);
   }
 }
 
 void Method::set_highest_osr_comp_level(int level) {
-  MethodData* mdo = method_data();
-  if (mdo != NULL) {
-    mdo->set_highest_osr_comp_level(level);
+  MethodCounters* mcs = method_counters();
+  if (mcs != NULL) {
+    mcs->set_highest_osr_comp_level(level);
   }
 }
 
--- a/hotspot/src/share/vm/oops/methodCounters.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/oops/methodCounters.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -35,4 +35,40 @@
   set_interpreter_throwout_count(0);
   set_interpreter_invocation_count(0);
   set_nmethod_age(INT_MAX);
+#ifdef TIERED
+  set_prev_time(0);
+  set_rate(0);
+  set_highest_comp_level(0);
+  set_highest_osr_comp_level(0);
+#endif
 }
+
+
+int MethodCounters::highest_comp_level() const {
+#ifdef TIERED
+  return _highest_comp_level;
+#else
+  return CompLevel_none;
+#endif
+}
+
+void MethodCounters::set_highest_comp_level(int level) {
+#ifdef TIERED
+  _highest_comp_level = level;
+#endif
+}
+
+int MethodCounters::highest_osr_comp_level() const {
+#ifdef TIERED
+  return _highest_osr_comp_level;
+#else
+  return CompLevel_none;
+#endif
+}
+
+void MethodCounters::set_highest_osr_comp_level(int level) {
+#ifdef TIERED
+  _highest_osr_comp_level = level;
+#endif
+}
+
--- a/hotspot/src/share/vm/oops/methodCounters.hpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/oops/methodCounters.hpp	Fri Sep 12 09:17:58 2014 +0200
@@ -49,6 +49,8 @@
 #ifdef TIERED
   float             _rate;                        // Events (invocation and backedge counter increments) per millisecond
   jlong             _prev_time;                   // Previous time the rate was acquired
+  u1                _highest_comp_level;          // Highest compile level this method has ever seen.
+  u1                _highest_osr_comp_level;      // Same for OSR level
 #endif
 
   MethodCounters() : _interpreter_invocation_count(0),
@@ -57,7 +59,9 @@
                      _nmethod_age(INT_MAX)
 #ifdef TIERED
                    , _rate(0),
-                     _prev_time(0)
+                     _prev_time(0),
+                     _highest_comp_level(0),
+                     _highest_osr_comp_level(0)
 #endif
   {
     invocation_counter()->init();
@@ -114,6 +118,11 @@
   void set_rate(float rate)                      { _rate = rate; }
 #endif
 
+  int highest_comp_level() const;
+  void set_highest_comp_level(int level);
+  int highest_osr_comp_level() const;
+  void set_highest_osr_comp_level(int level);
+
   // invocation counter
   InvocationCounter* invocation_counter() { return &_invocation_counter; }
   InvocationCounter* backedge_counter()   { return &_backedge_counter; }
--- a/hotspot/src/share/vm/oops/methodData.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/oops/methodData.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -1134,8 +1134,6 @@
   _tenure_traps = 0;
   _num_loops = 0;
   _num_blocks = 0;
-  _highest_comp_level = 0;
-  _highest_osr_comp_level = 0;
   _would_profile = true;
 
 #if INCLUDE_RTM_OPT
--- a/hotspot/src/share/vm/oops/methodData.hpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/oops/methodData.hpp	Fri Sep 12 09:17:58 2014 +0200
@@ -2095,10 +2095,6 @@
   // time with C1. It is used to determine if method is trivial.
   short             _num_loops;
   short             _num_blocks;
-  // Highest compile level this method has ever seen.
-  u1                _highest_comp_level;
-  // Same for OSR level
-  u1                _highest_osr_comp_level;
   // Does this method contain anything worth profiling?
   bool              _would_profile;
 
@@ -2277,11 +2273,6 @@
   void set_would_profile(bool p)              { _would_profile = p;    }
   bool would_profile() const                  { return _would_profile; }
 
-  int highest_comp_level() const              { return _highest_comp_level;      }
-  void set_highest_comp_level(int level)      { _highest_comp_level = level;     }
-  int highest_osr_comp_level() const          { return _highest_osr_comp_level;  }
-  void set_highest_osr_comp_level(int level)  { _highest_osr_comp_level = level; }
-
   int num_loops() const                       { return _num_loops;  }
   void set_num_loops(int n)                   { _num_loops = n;     }
   int num_blocks() const                      { return _num_blocks; }
--- a/hotspot/src/share/vm/opto/compile.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/opto/compile.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -430,7 +430,7 @@
 // removes the need to bang the stack in the deoptimization blob which
 // in turn simplifies stack overflow handling.
 int Compile::bang_size_in_bytes() const {
-  return MAX2(_interpreter_frame_size, frame_size_in_bytes());
+  return MAX2(frame_size_in_bytes() + os::extra_bang_size_in_bytes(), _interpreter_frame_size);
 }
 
 // ============================================================================
--- a/hotspot/src/share/vm/opto/library_call.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -4968,7 +4968,8 @@
 
     // Allocate the result array
     Node* zlen = _gvn.transform(new AddINode(xlen, ylen));
-    Node* klass_node = makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_INT)));
+    ciKlass* klass = ciTypeArrayKlass::make(T_INT);
+    Node* klass_node = makecon(TypeKlassPtr::make(klass));
 
     IdealKit ideal(this);
 
@@ -5002,7 +5003,8 @@
 
      sync_kit(ideal);
      z = __ value(z_alloc);
-     _gvn.set_type(z, TypeAryPtr::INTS);
+     // Can't use TypeAryPtr::INTS which uses Bottom offset.
+     _gvn.set_type(z, TypeOopPtr::make_from_klass(klass));
      // Final sync IdealKit and GraphKit.
      final_sync(ideal);
 #undef __
--- a/hotspot/src/share/vm/runtime/arguments.hpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.hpp	Fri Sep 12 09:17:58 2014 +0200
@@ -590,7 +590,9 @@
   static void  fix_appclasspath();
 
   // Operation modi
-  static Mode mode()                        { return _mode; }
+  static Mode mode()                { return _mode; }
+  static bool is_interpreter_only() { return mode() == _int; }
+
 
   // Utility: copies src into buf, replacing "%%" with "%" and "%p" with pid.
   static bool copy_expand_pid(const char* src, size_t srclen, char* buf, size_t buflen);
--- a/hotspot/src/share/vm/runtime/globals.hpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Fri Sep 12 09:17:58 2014 +0200
@@ -2473,7 +2473,7 @@
   develop(bool, CIPrintCompilerName, false,                                 \
           "when CIPrint is active, print the name of the active compiler")  \
                                                                             \
-  develop(bool, CIPrintCompileQueue, false,                                 \
+  diagnostic(bool, CIPrintCompileQueue, false,                              \
           "display the contents of the compile queue whenever a "           \
           "compilation is enqueued")                                        \
                                                                             \
--- a/hotspot/src/share/vm/runtime/os.hpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/runtime/os.hpp	Fri Sep 12 09:17:58 2014 +0200
@@ -771,6 +771,9 @@
   // Hook for os specific jvm options that we don't want to abort on seeing
   static bool obsolete_option(const JavaVMOption *option);
 
+  // Amount beyond the callee frame size that we bang the stack.
+  static int extra_bang_size_in_bytes();
+
   // Extensions
 #include "runtime/os_ext.hpp"
 
--- a/hotspot/src/share/vm/runtime/sweeper.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -618,7 +618,7 @@
         if (mc == NULL) {
           // Sometimes we can get here without MethodCounters. For example if we run with -Xcomp.
           // Try to allocate them.
-          mc = Method::build_method_counters(nm->method(), Thread::current());
+          mc = nm->method()->get_method_counters(Thread::current());
         }
         if (mc != NULL) {
           // Snapshot the value as it's changed concurrently
--- a/hotspot/src/share/vm/runtime/vm_operations.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/runtime/vm_operations.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -470,3 +470,15 @@
     ShouldNotReachHere();
   }
 }
+
+void VM_PrintCompileQueue::doit() {
+  CompileBroker::print_compile_queues(_out);
+}
+
+void VM_PrintCodeList::doit() {
+  CodeCache::print_codelist(_out);
+}
+
+void VM_PrintCodeCache::doit() {
+  CodeCache::print_layout(_out);
+}
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp	Fri Sep 12 09:17:58 2014 +0200
@@ -99,6 +99,9 @@
   template(RotateGCLog)                           \
   template(WhiteBoxOperation)                     \
   template(ClassLoaderStatsOperation)             \
+  template(PrintCompileQueue)                     \
+  template(PrintCodeList)                         \
+  template(PrintCodeCache)                        \
 
 class VM_Operation: public CHeapObj<mtInternal> {
  public:
@@ -413,4 +416,35 @@
   void doit() { gclog_or_tty->rotate_log(true, _out); }
 };
 
+class VM_PrintCompileQueue: public VM_Operation {
+ private:
+  outputStream* _out;
+
+ public:
+  VM_PrintCompileQueue(outputStream* st) : _out(st) {}
+  VMOp_Type type() const { return VMOp_PrintCompileQueue; }
+  void doit();
+};
+
+class VM_PrintCodeList: public VM_Operation {
+ private:
+  outputStream* _out;
+
+ public:
+  VM_PrintCodeList(outputStream* st) : _out(st) {}
+  VMOp_Type type() const { return VMOp_PrintCodeList; }
+  void doit();
+};
+
+class VM_PrintCodeCache: public VM_Operation {
+ private:
+  outputStream* _out;
+
+ public:
+  VM_PrintCodeCache(outputStream* st) : _out(st) {}
+  VMOp_Type type() const { return VMOp_PrintCodeCache; }
+  void doit();
+};
+
+
 #endif // SHARE_VM_RUNTIME_VM_OPERATIONS_HPP
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp	Fri Sep 12 09:17:58 2014 +0200
@@ -60,6 +60,9 @@
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RotateGCLogDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderStatsDCmd>(full_export, true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompileQueueDCmd>(full_export, true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeListDCmd>(full_export, true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeCacheDCmd>(full_export, true, false));
 
   // Enhanced JMX Agent Support
   // These commands won't be exported via the DiagnosticCommandMBean until an
@@ -674,3 +677,18 @@
   }
 }
 
+void CompileQueueDCmd::execute(DCmdSource source, TRAPS) {
+  VM_PrintCompileQueue printCompileQueueOp(output());
+  VMThread::execute(&printCompileQueueOp);
+}
+
+void CodeListDCmd::execute(DCmdSource source, TRAPS) {
+  VM_PrintCodeList printCodeListOp(output());
+  VMThread::execute(&printCodeListOp);
+}
+
+void CodeCacheDCmd::execute(DCmdSource source, TRAPS) {
+  VM_PrintCodeCache printCodeCacheOp(output());
+  VMThread::execute(&printCodeCacheOp);
+}
+
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp	Wed Sep 10 23:14:13 2014 +0000
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp	Fri Sep 12 09:17:58 2014 +0200
@@ -399,4 +399,68 @@
   }
 };
 
+class CompileQueueDCmd : public DCmd {
+public:
+  CompileQueueDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+  static const char* name() {
+    return "Compiler.queue";
+  }
+  static const char* description() {
+    return "Print methods queued for compilation.";
+  }
+  static const char* impact() {
+    return "Low";
+  }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "monitor", NULL};
+    return p;
+  }
+  static int num_arguments() { return 0; }
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
+class CodeListDCmd : public DCmd {
+public:
+  CodeListDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+  static const char* name() {
+    return "Compiler.codelist";
+  }
+  static const char* description() {
+    return "Print all compiled methods in code cache.";
+  }
+  static const char* impact() {
+    return "Medium";
+  }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "monitor", NULL};
+    return p;
+  }
+  static int num_arguments() { return 0; }
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
+
+class CodeCacheDCmd : public DCmd {
+public:
+  CodeCacheDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+  static const char* name() {
+    return "Compiler.codecache";
+  }
+  static const char* description() {
+    return "Print code cache layout and bounds.";
+  }
+  static const char* impact() {
+    return "Low";
+  }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "monitor", NULL};
+    return p;
+  }
+  static int num_arguments() { return 0; }
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
 #endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/CodeCacheTest.java	Fri Sep 12 09:17:58 2014 +0200
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test CodeCacheTest
+ * @bug 8054889
+ * @build DcmdUtil CodeCacheTest
+ * @run main CodeCacheTest
+ * @summary Test of diagnostic command Compiler.codecache
+ */
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CodeCacheTest {
+
+    /**
+     * This test calls Jcmd (diagnostic command tool) Compiler.codecache and then parses the output,
+     * making sure that all number look ok
+     *
+     *
+     * Expected output:
+     *
+     * CodeCache: size=245760Kb used=4680Kb max_used=4680Kb free=241079Kb
+     * bounds [0x00007f5bd9000000, 0x00007f5bd94a0000, 0x00007f5be8000000]
+     * total_blobs=575 nmethods=69 adapters=423
+     * compilation: enabled
+     */
+
+    static Pattern line1 = Pattern.compile("CodeCache: size=(\\p{Digit}*)Kb used=(\\p{Digit}*)Kb max_used=(\\p{Digit}*)Kb free=(\\p{Digit}*)Kb");
+    static Pattern line2 = Pattern.compile(" bounds \\[0x(\\p{XDigit}*), 0x(\\p{XDigit}*), 0x(\\p{XDigit}*)\\]");
+    static Pattern line3 = Pattern.compile(" total_blobs=(\\p{Digit}*) nmethods=(\\p{Digit}*) adapters=(\\p{Digit}*)");
+    static Pattern line4 = Pattern.compile(" compilation: (\\w*)");
+
+    public static void main(String arg[]) throws Exception {
+
+        // Get output from dcmd (diagnostic command)
+        String result = DcmdUtil.executeDcmd("Compiler.codecache");
+        BufferedReader r = new BufferedReader(new StringReader(result));
+
+        // Validate first line
+        String line;
+        line = r.readLine();
+        Matcher m = line1.matcher(line);
+        if (m.matches()) {
+            for(int i = 1; i <= 4; i++) {
+                int val = Integer.parseInt(m.group(i));
+                if (val < 0) {
+                    throw new Exception("Failed parsing dcmd codecache output");
+                }
+            }
+        } else {
+            throw new Exception("Regexp 1 failed");
+        }
+
+        // Validate second line
+        line = r.readLine();
+        m = line2.matcher(line);
+        if (m.matches()) {
+            long start = Long.parseLong(m.group(1), 16);
+            if (start < 0) {
+                throw new Exception("Failed parsing dcmd codecache output");
+            }
+            long mark = Long.parseLong(m.group(2), 16);
+            if (mark < 0) {
+                throw new Exception("Failed parsing dcmd codecache output");
+            }
+            long top = Long.parseLong(m.group(3), 16);
+            if (top < 0) {
+                throw new Exception("Failed parsing dcmd codecache output");
+            }
+            if (start > mark) {
+                throw new Exception("Failed parsing dcmd codecache output");
+            }
+            if (mark > top) {
+                throw new Exception("Failed parsing dcmd codecache output");
+            }
+        } else {
+            throw new Exception("Regexp 2 failed line: " + line);
+        }
+
+        // Validate third line
+        line = r.readLine();
+        m = line3.matcher(line);
+        if (m.matches()) {
+            int blobs = Integer.parseInt(m.group(1));
+            if (blobs <= 0) {
+                throw new Exception("Failed parsing dcmd codecache output");
+            }
+            int nmethods = Integer.parseInt(m.group(2));
+            if (nmethods <= 0) {
+                throw new Exception("Failed parsing dcmd codecache output");
+            }
+            int adapters = Integer.parseInt(m.group(3));
+            if (adapters <= 0) {
+                throw new Exception("Failed parsing dcmd codecache output");
+            }
+            if (blobs < (nmethods + adapters)) {
+                throw new Exception("Failed parsing dcmd codecache output");
+            }
+        } else {
+            throw new Exception("Regexp 3 failed");
+        }
+
+        // Validate fourth line
+        line = r.readLine();
+        m = line4.matcher(line);
+        if (m.matches()) {
+            if (!m.group(1).equals("enabled")) {
+                throw new Exception("Invalid message: '" + m.group(1) + "'");
+            }
+        } else {
+            throw new Exception("Regexp 4 failed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/CodelistTest.java	Fri Sep 12 09:17:58 2014 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test CodelistTest
+ * @bug 8054889
+ * @build DcmdUtil MethodIdentifierParser CodelistTest
+ * @run main CodelistTest
+ * @summary Test of diagnostic command Compiler.codelist
+ */
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+
+public class CodelistTest {
+
+    /**
+     * This test calls Jcmd (diagnostic command tool) Compiler.codelist and then parses the output,
+     * making sure that the first methods in the list is valid by reflection.
+     *
+     * Output example:
+     *
+     * 6 0 java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V [0x00007f7b49200910, 0x00007f7b49200aa0 - 0x00007f7b49200d30]
+     * 2 3 java.lang.String.indexOf(II)I [0x00007f7b49200d90, 0x00007f7b49200f60 - 0x00007f7b49201490]
+     * 7 3 java.lang.Math.min(II)I [0x00007f7b4922f010, 0x00007f7b4922f180 - 0x00007f7b4922f338]
+     * 8 3 java.lang.String.equals(Ljava/lang/Object;)Z [0x00007f7b4922fb10, 0x00007f7b4922fd40 - 0x00007f7b49230698]
+     * 9 3 java.lang.AbstractStringBuilder.ensureCapacityInternal(I)V [0x00007f7b49232010, 0x00007f7b492321a0 - 0x00007f7b49232510]
+     * 10 1 java.lang.Object.<init>()V [0x00007f7b49233e90, 0x00007f7b49233fe0 - 0x00007f7b49234118]
+     *
+     */
+
+    public static void main(String arg[]) throws Exception {
+        int ok   = 0;
+        int fail = 0;
+
+        // Get output from dcmd (diagnostic command)
+        String result = DcmdUtil.executeDcmd("Compiler.codelist");
+        BufferedReader r = new BufferedReader(new StringReader(result));
+
+        // Grab a method name from the output
+        String line;
+        int count = 0;
+
+        while((line = r.readLine()) != null) {
+            count++;
+
+            String[] parts = line.split(" ");
+            // int compileID = Integer.parseInt(parts[0]);
+            // int compileLevel = Integer.parseInt(parts[1]);
+            String methodPrintedInLogFormat = parts[2];
+
+            // skip inits and clinits - they can not be reflected
+            if (methodPrintedInLogFormat.contains("<init>")) {
+                continue;
+            }
+            if (methodPrintedInLogFormat.contains("<clinit>")) {
+                continue;
+            }
+
+            MethodIdentifierParser mf = new MethodIdentifierParser(methodPrintedInLogFormat);
+            Method m;
+            try {
+                m = mf.getMethod();
+            } catch (NoSuchMethodException e) {
+                m = null;
+            }
+            if (m == null) {
+                throw new Exception("Test failed");
+            }
+            if (count > 10) {
+                // Testing 10 entries is enough. Lets not waste time.
+                break;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/CompilerQueueTest.java	Fri Sep 12 09:17:58 2014 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test CompilerQueueTest
+ * @bug 8054889
+ * @build DcmdUtil CompilerQueueTest
+ * @run main CompilerQueueTest
+ * @summary Test of diagnostic command Compiler.queue
+ */
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+
+public class CompilerQueueTest {
+
+    /**
+     * This test calls Jcmd (diagnostic command tool) Compiler.queue and
+     * then parses the output, making sure that the output look ok.
+     *
+     *
+     * Output example:
+     *
+     * Contents of C1 compile queue
+     * ----------------------------
+     * 73       3       java.lang.AbstractStringBuilder::append (50 bytes)
+     * 74       1       java.util.TreeMap::size (5 bytes)
+     * 75       3       java.lang.StringBuilder::append (8 bytes)
+     * 83       3       java.util.TreeMap$ValueIterator::next (8 bytes)
+     * 84       1       javax.management.MBeanFeatureInfo::getName (5 bytes)
+     * ----------------------------
+     * Contents of C2 compile queue
+     * ----------------------------
+     * Empty
+     * ----------------------------
+     *
+     **/
+
+    public static void main(String arg[]) throws Exception {
+
+        // Get output from dcmd (diagnostic command)
+        String result = DcmdUtil.executeDcmd("Compiler.queue");
+        BufferedReader r = new BufferedReader(new StringReader(result));
+
+        String line;
+        match(r.readLine(), "Contents of C1 compile queue");
+        match(r.readLine(), "----------------------------");
+        String str = r.readLine();
+        if (!str.equals("Empty")) {
+            while (str.charAt(0) != '-') {
+                validateMethodLine(str);
+                str = r.readLine();
+            }
+        } else {
+            str = r.readLine();
+        }
+
+        match(str,          "----------------------------");
+        match(r.readLine(), "Contents of C2 compile queue");
+        match(r.readLine(), "----------------------------");
+        str = r.readLine();
+        if (!str.equals("Empty")) {
+            while (str.charAt(0) != '-') {
+                validateMethodLine(str);
+                str = r.readLine();
+            }
+        } else {
+            str = r.readLine();
+        }
+        match(str, "----------------------------");
+    }
+
+    private static void validateMethodLine(String str)  throws Exception {
+        String name = str.substring(19);
+        int sep = name.indexOf("::");
+        try {
+            Class.forName(name.substring(0, sep));
+        } catch (ClassNotFoundException e) {
+            throw new Exception("Failed parsing dcmd queue");
+        }
+    }
+
+    public static void match(String line, String str) throws Exception {
+        if (!line.equals(str)) {
+            throw new Exception("String equals: " + line + ", " + str);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/MethodIdentifierParser.java	Fri Sep 12 09:17:58 2014 +0200
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+public class MethodIdentifierParser {
+
+    private String logString;
+    private String className;
+    private String methodName;
+    private String methodDescriptor;
+
+    /**
+     * This is a utility class for parsing the log entries for a method. It supplies
+     * a few select methods for reflecting the class and method from that information.
+     *
+     * Example log entries:
+     * "java.util.TreeMap.successor(Ljava/util/TreeMap$Entry;)Ljava/util/TreeMap$Entry;"
+     */
+
+    public MethodIdentifierParser(String logString) {
+        this.logString = logString;
+
+        int i      = logString.lastIndexOf("."); // find start of method name
+        className  = logString.substring(0, i);  // classname is everything before
+        int i2     = logString.indexOf("(");     // Signature starts with an '('
+        methodName = logString.substring(i+1, i2);
+        methodDescriptor  = logString.substring(i2, logString.length());
+
+        // Add sanity check for extracted fields
+    }
+
+    public Method getMethod() throws NoSuchMethodException, SecurityException, ClassNotFoundException, Exception {
+        try {
+            return Class.forName(className).getDeclaredMethod(methodName, getParamenterDescriptorArray());
+        } catch (UnexpectedTokenException e) {
+            throw new Exception("Parse failed");
+        }
+    }
+
+    public Class<?>[] getParamenterDescriptorArray() throws ClassNotFoundException, UnexpectedTokenException {
+        ParameterDecriptorIterator s = new ParameterDecriptorIterator(methodDescriptor);
+        Class<?> paramType;
+        ArrayList<Class<?>> list = new ArrayList<Class<?>>();
+        while ((paramType = s.nextParamType()) != null) {
+            list.add(paramType);
+        }
+        if (list.size() > 0) {
+            return list.toArray(new Class<?>[list.size()]);
+        } else {
+            return null;
+        }
+    }
+
+    class ParameterDecriptorIterator {
+
+        // This class uses charAt() indexing for startMark and i
+        // That is when i points to the last char it can be retrieved with
+        // charAt(i). Including the last char for a subString requires
+        // substring(startMark, i+1);
+
+        private String methodDescriptor;
+        private int startMark;
+
+        public ParameterDecriptorIterator(String signature) {
+            this.methodDescriptor = signature;
+            this.startMark = 0;
+            if (signature.charAt(0) == '(') {
+                this.startMark = 1;
+            }
+        }
+
+        public Class<?> nextParamType() throws UnexpectedTokenException {
+            int i = startMark;
+            while (methodDescriptor.length() > i) {
+                switch (methodDescriptor.charAt(i)) {
+                case 'C':
+                case 'B':
+                case 'I':
+                case 'J':
+                case 'Z':
+                case 'F':
+                case 'D':
+                case 'S':
+                    // Primitive class case, but we may have gotten here with [ as first token
+                    break;
+                case 'L':
+                    // Internal class name suffixed by ';'
+                    while (methodDescriptor.charAt(i) != ';') {
+                        i++;
+                    }
+                    break;
+                case '[':
+                    i++;         // arrays -> do another pass
+                    continue;
+                case ')':
+                    return null; // end found
+                case 'V':
+                case ';':
+                default:
+                    throw new UnexpectedTokenException(methodDescriptor, i);
+                }
+                break;
+            }
+            if (i == startMark) {
+                // Single char -> primitive class case
+                startMark++; // Update for next iteration
+                switch (methodDescriptor.charAt(i)) {
+                case 'C':
+                    return char.class;
+                case 'B':
+                    return byte.class;
+                case 'I':
+                    return int.class;
+                case 'J':
+                    return long.class;
+                case 'F':
+                    return float.class;
+                case 'D':
+                    return double.class;
+                case 'S':
+                    return short.class;
+                case 'Z':
+                    return boolean.class;
+                default:
+                    throw new UnexpectedTokenException(methodDescriptor, i);
+                }
+            } else {
+                // Multi char case
+                String nextParam;
+                if (methodDescriptor.charAt(startMark) == 'L') {
+                    // When reflecting a class the leading 'L' and trailing';' must be removed.
+                    // (When reflecting an array of classes, they must remain...)
+                    nextParam = methodDescriptor.substring(startMark+1, i);
+                } else {
+                    // Any kind of array - simple case, use whole descriptor when reflecting.
+                    nextParam = methodDescriptor.substring(startMark, i+1);
+                }
+                startMark = ++i; // Update for next iteration
+                try {
+                    // The parameter descriptor uses JVM internal class identifier with '/' as
+                    // package separator, but Class.forName expects '.'.
+                    nextParam = nextParam.replace('/', '.');
+                    return Class.forName(nextParam);
+                } catch (ClassNotFoundException e) {
+                    System.out.println("Class not Found: " + nextParam);
+                    return null;
+                }
+            }
+        }
+    }
+
+    class UnexpectedTokenException extends Exception {
+        String descriptor;
+        int i;
+        public UnexpectedTokenException(String descriptor, int i) {
+            this.descriptor = descriptor;
+            this.i = i;
+        }
+
+        @Override
+        public String toString() {
+            return "Unexpected token at: " + i + " in signature: " + descriptor;
+        }
+
+        private static final long serialVersionUID = 1L;
+    }
+
+    public void debugPrint() {
+        System.out.println("mlf in:               " + logString);
+        System.out.println("mlf class:            " + className);
+        System.out.println("mlf method:           " + methodName);
+        System.out.println("mlf methodDescriptor: " + methodDescriptor);
+    }
+}