changeset 5821:bbda609c9d24 icedtea-2.5.5pre01

Merge jdk7u75-b31
author andrew
date Tue, 27 Jan 2015 00:46:17 +0000
parents 5c948ad57906 (current diff) db9672d640ff (diff)
children 0b1e07df4b1b
files .hgtags agent/src/os/linux/libproc.h make/hotspot_version src/cpu/sparc/vm/frame_sparc.inline.hpp src/os/bsd/vm/os_bsd.cpp src/os/linux/vm/os_linux.cpp src/os_cpu/linux_sparc/vm/assembler_linux_sparc.cpp src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp src/os_cpu/linux_x86/vm/os_linux_x86.cpp src/share/vm/classfile/systemDictionary.cpp src/share/vm/classfile/verifier.cpp src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp src/share/vm/memory/threadLocalAllocBuffer.cpp src/share/vm/oops/cpCacheOop.hpp src/share/vm/oops/typeArrayOop.hpp src/share/vm/opto/compile.cpp src/share/vm/opto/compile.hpp src/share/vm/opto/library_call.cpp src/share/vm/opto/loopTransform.cpp src/share/vm/opto/loopnode.cpp src/share/vm/opto/memnode.cpp src/share/vm/opto/node.cpp src/share/vm/prims/jni.cpp src/share/vm/runtime/vmStructs.cpp src/share/vm/runtime/vmThread.cpp src/share/vm/utilities/ostream.cpp src/share/vm/utilities/vmError.cpp
diffstat 30 files changed, 391 insertions(+), 154 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Wed Jan 21 03:56:44 2015 +0000
+++ b/.hgtags	Tue Jan 27 00:46:17 2015 +0000
@@ -725,6 +725,11 @@
 1d8226b3e9896656451801393eb3ae394faeb638 jdk7u65-b40
 cf8b3a090e597e59177c5f67d44cdec12309777f jdk7u65-b31
 df855c3f4d31dd7db081d68e3054518380127893 jdk7u65-b33
+39776d90970221dd260187acb4c37631e41a66a9 jdk7u67-b01
+7152f5f6395c66c8d6389100d880882d5cfe9af3 jdk7u67-b31
+4fb7952ebba8ba45be16bdc64184259e8076ffcf jdk7u67-b32
+a20f1b6311e10b755d949a088e7aeca2ba088a59 jdk7u67-b33
+39c07d2fb4d3d97bf3bb53c1c1e199709c5c49fe jdk7u67-b34
 6b37a189944aaa09e81d97d394496464d16bee42 jdk7u66-b00
 121dc94194d9234e2b13c867d875e23e1bdd6abd jdk7u66-b01
 f28ea516eb0b9e99f1e342954ab4642456af4da1 jdk7u66-b09
@@ -754,3 +759,35 @@
 7a4b0596c5395b5836faee96923b83444cc8a266 icedtea-2.5.4pre02
 606de1136fd1eee950092d6beb14d0b03e8d408e icedtea-2.5.4pre03
 6144ca9b6a72e11575ea5e16751180645d8fbd5d icedtea-2.5.4
+ad909197a1ce2df483a20ff9ac380382f779a9d3 jdk7u71-b14
+1bd3adac3aac3c29c81303812b35f484ff90cb2b jdk7u72-b01
+0caed46767e35c00eff69b22acf984d98eb66b3d jdk7u72-b02
+3a2934191de4bb8ca9d2faca93f3381e521e8cac jdk7u72-b03
+e4708cde2898df4c936595aacb57bc5b4e15869a jdk7u72-b04
+137e0859cd296cb8d9f9e327112ddc793ed59318 jdk7u72-b05
+4d9d227d70f33b70461230172386217317954312 jdk7u72-b06
+ece56f93f37b41b9c8875e54fbd8010277f6b460 jdk7u72-b07
+439c695a7aa03652ab92681120434b9ce8cdd2b7 jdk7u72-b08
+a27f16d45457a68a723acca621cb11bc173a0eb6 jdk7u72-b09
+e6508ab77271d1d3ce7b5f60d91a7334fdacb03a jdk7u72-b10
+c17a8487086433e14cd22373039a8b6b48e7cbb8 jdk7u72-b11
+a9e695f0d831f115720a4dcad3d33e0003b0acad jdk7u72-b12
+ac701f87d1ea46033c69f3e1cb84fc0a971da70c jdk7u72-b13
+d9b56c6bdddb6f9d8242230f5fdd58f9c7d30ea5 jdk7u72-b14
+a6ae698522bfab3c595a4f8c2c3ee7e8939eb1bb jdk7u72-b30
+492a2abed4ca015459e24f7348233531b7e929d2 jdk7u72-b31
+e6b6d91b3934c281086f8efacb0926e7451cc18b jdk7u75-b00
+9096ac248b379a0f3012f18c7289ec47cdef8459 jdk7u75-b01
+a6964b2822d906eab9c923cdd723cf3dd4facfcd jdk7u75-b02
+6c1a8b7ed616311a932715428620e262076bb68a jdk7u75-b03
+2480d9d778301a3f88b0ab8ee35a585df82528e5 jdk7u75-b04
+d81faf9016ce5c9f98264b1f724b3d6d85b12c07 jdk7u75-b05
+2ec4b796b1de3cfe58f051111dfd70ab367e553e jdk7u75-b06
+1d3906064cae18fdb0ff9a2045f2d8d48067bcd1 jdk7u75-b07
+dfcf951330b6f7c1a3cb88c819e94f680054a970 jdk7u75-b08
+ca20e7886db63792593f048f7308aed383775829 jdk7u75-b09
+5a0321dcf89383c31f3c6e4827b3275f9ef09a5e jdk7u75-b10
+82dcfb646bd5bc9f3674cb02ea9ba2598cff6bbe jdk7u75-b11
+18b74ded3ffc2e6fc5a3853f923c8dd49849dee1 jdk7u75-b12
+384fba17a49738baddeb55a4bfcf00b01af199ef jdk7u75-b13
+0c7d7c067c46fa0ddcb9170bed1d52f52a9ec831 jdk7u75-b30
--- a/agent/src/os/linux/libproc.h	Wed Jan 21 03:56:44 2015 +0000
+++ b/agent/src/os/linux/libproc.h	Tue Jan 27 00:46:17 2015 +0000
@@ -34,44 +34,7 @@
 #include "libproc_md.h"
 #endif
 
-#if defined(sparc) || defined(sparcv9)
-/*
-  If _LP64 is defined ptrace.h should be taken from /usr/include/asm-sparc64
-  otherwise it should be from /usr/include/asm-sparc
-  These two files define pt_regs structure differently
-*/
-#ifdef _LP64
-struct pt_regs {
-	unsigned long u_regs[16]; /* globals and ins */
-	unsigned long tstate;
-	unsigned long tpc;
-	unsigned long tnpc;
-	unsigned int y;
-
-	/* We encode a magic number, PT_REGS_MAGIC, along
-	 * with the %tt (trap type) register value at trap
-	 * entry time.  The magic number allows us to identify
-	 * accurately a trap stack frame in the stack
-	 * unwinder, and the %tt value allows us to test
-	 * things like "in a system call" etc. for an arbitray
-	 * process.
-	 *
-	 * The PT_REGS_MAGIC is chosen such that it can be
-	 * loaded completely using just a sethi instruction.
-	 */
-	unsigned int magic;
-};
-#else
-struct pt_regs {
-	unsigned long psr;
-	unsigned long pc;
-	unsigned long npc;
-	unsigned long y;
-	unsigned long u_regs[16]; /* globals and ins */
-};
-#endif
-
-#endif //sparc or sparcv9
+#include <linux/ptrace.h>
 
 /************************************************************************************
 
--- a/src/cpu/sparc/vm/assembler_sparc.hpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/cpu/sparc/vm/assembler_sparc.hpp	Tue Jan 27 00:46:17 2015 +0000
@@ -1745,7 +1745,7 @@
 
   inline void swap( Register s1, Register s2, Register d );
   inline void swap( Register s1, int simm13a, Register d);
-  inline void swap( Address& a,               Register d, int offset = 0 );
+  inline void swap( const Address& a, Register d, int offset = 0 );
 
   // pp 232
 
--- a/src/cpu/sparc/vm/assembler_sparc.inline.hpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/cpu/sparc/vm/assembler_sparc.inline.hpp	Tue Jan 27 00:46:17 2015 +0000
@@ -347,7 +347,7 @@
 inline void Assembler::swap(    Register s1, Register s2, Register d) { v9_dep();  emit_long( op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | rs2(s2) ); }
 inline void Assembler::swap(    Register s1, int simm13a, Register d) { v9_dep();  emit_data( op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
 
-inline void Assembler::swap(    Address& a, Register d, int offset ) {
+inline void Assembler::swap(    const Address& a, Register d, int offset ) {
   relocate(a.rspec(offset));
   if (a.has_index()) { assert(offset == 0, ""); swap( a.base(), a.index(), d         ); }
   else               {                          swap( a.base(), a.disp() + offset, d ); }
--- a/src/cpu/sparc/vm/copy_sparc.hpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/cpu/sparc/vm/copy_sparc.hpp	Tue Jan 27 00:46:17 2015 +0000
@@ -184,7 +184,7 @@
   assert(MinObjAlignmentInBytes >= BytesPerLong, "need alternate implementation");
 
   if (value == 0 && UseBlockZeroing &&
-      (count > (BlockZeroingLowLimit >> LogHeapWordSize))) {
+      (count > (size_t)(BlockZeroingLowLimit >> LogHeapWordSize))) {
    // Call it only when block zeroing is used
    ((_zero_Fn)StubRoutines::zero_aligned_words())(tohw, count);
   } else {
--- a/src/cpu/sparc/vm/frame_sparc.hpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/cpu/sparc/vm/frame_sparc.hpp	Tue Jan 27 00:46:17 2015 +0000
@@ -282,8 +282,8 @@
 
   // next two fns read and write Lmonitors value,
  private:
-  BasicObjectLock* interpreter_frame_monitors()           const  { return *interpreter_frame_monitors_addr(); }
-  void interpreter_frame_set_monitors(BasicObjectLock* monitors) {        *interpreter_frame_monitors_addr() = monitors; }
+  BasicObjectLock* interpreter_frame_monitors() const;
+  void interpreter_frame_set_monitors(BasicObjectLock* monitors);
 #else
  public:
   inline interpreterState get_interpreterState() const {
--- a/src/cpu/sparc/vm/frame_sparc.inline.hpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/cpu/sparc/vm/frame_sparc.inline.hpp	Tue Jan 27 00:46:17 2015 +0000
@@ -217,6 +217,13 @@
   return (methodOop*)sp_addr_at( Lmethod->sp_offset_in_saved_window());
 }
 
+inline BasicObjectLock* frame::interpreter_frame_monitors() const {
+  return *interpreter_frame_monitors_addr();
+}
+
+inline void frame::interpreter_frame_set_monitors(BasicObjectLock* monitors) {
+  *interpreter_frame_monitors_addr() = monitors;
+}
 
 // Constant pool cache
 
--- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -89,7 +89,7 @@
  private:
 
 #ifdef PRODUCT
-#define inc_counter_np(a,b,c) (0)
+#define inc_counter_np(a,b,c)
 #else
 #define inc_counter_np(counter, t1, t2) \
   BLOCK_COMMENT("inc_counter " #counter); \
@@ -1126,7 +1126,7 @@
                                               Label& L_loop, bool use_prefetch, bool use_bis);
 
   void disjoint_copy_core(Register from, Register to, Register count, int log2_elem_size,
-                          int iter_size, CopyLoopFunc copy_loop_func) {
+                          int iter_size, StubGenerator::CopyLoopFunc copy_loop_func) {
     Label L_copy;
 
     assert(log2_elem_size <= 3, "the following code should be changed");
@@ -1277,7 +1277,7 @@
     __ inc(from, 8);
     __ sllx(O3, left_shift,  O3);
 
-    disjoint_copy_core(from, to, count, log2_elem_size, 16, copy_16_bytes_shift_loop);
+    disjoint_copy_core(from, to, count, log2_elem_size, 16, &StubGenerator::copy_16_bytes_shift_loop);
 
     __ inccc(count, count_dec>>1 ); // + 8 bytes
     __ brx(Assembler::negative, true, Assembler::pn, L_copy_last_bytes);
@@ -2156,7 +2156,7 @@
       __ dec(count, 4);   // The cmp at the beginning guaranty count >= 4
       __ sllx(O3, 32,  O3);
 
-      disjoint_copy_core(from, to, count, 2, 16, copy_16_bytes_loop);
+      disjoint_copy_core(from, to, count, 2, 16, &StubGenerator::copy_16_bytes_loop);
 
       __ br(Assembler::always, false, Assembler::pt, L_copy_4_bytes);
       __ delayed()->inc(count, 4); // restore 'count'
@@ -2437,7 +2437,7 @@
     // count >= 0 (original count - 8)
     __ mov(from, from64);
 
-    disjoint_copy_core(from64, to64, count, 3, 64, copy_64_bytes_loop);
+    disjoint_copy_core(from64, to64, count, 3, 64, &StubGenerator::copy_64_bytes_loop);
 
       // Restore O4(offset0), O5(offset8)
       __ sub(from64, from, offset0);
--- a/src/cpu/sparc/vm/vm_version_sparc.hpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/cpu/sparc/vm/vm_version_sparc.hpp	Tue Jan 27 00:46:17 2015 +0000
@@ -48,7 +48,8 @@
     sparc64_family       = 14,
     M_family             = 15,
     T_family             = 16,
-    T1_model             = 17
+    T1_model             = 17,
+    sparc5_instructions  = 18
   };
 
   enum Feature_Flag_Set {
@@ -73,6 +74,7 @@
     M_family_m              = 1 << M_family,
     T_family_m              = 1 << T_family,
     T1_model_m              = 1 << T1_model,
+    sparc5_instructions_m   = 1 << sparc5_instructions,
 
     generic_v8_m        = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m,
     generic_v9_m        = generic_v8_m | v9_instructions_m,
@@ -117,6 +119,7 @@
   static bool has_vis3()                { return (_features & vis3_instructions_m) != 0; }
   static bool has_blk_init()            { return (_features & blk_init_instructions_m) != 0; }
   static bool has_cbcond()              { return (_features & cbcond_instructions_m) != 0; }
+  static bool has_sparc5_instr()        { return (_features & sparc5_instructions_m) != 0; }
 
   static bool supports_compare_and_exchange()
                                         { return has_v9(); }
@@ -127,6 +130,7 @@
 
   static bool is_M_series()             { return is_M_family(_features); }
   static bool is_T4()                   { return is_T_family(_features) && has_cbcond(); }
+  static bool is_T7()                   { return is_T_family(_features) && has_sparc5_instr(); }
 
   // Fujitsu SPARC64
   static bool is_sparc64()              { return (_features & sparc64_family_m) != 0; }
@@ -146,7 +150,7 @@
   static const char* cpu_features()     { return _features_str; }
 
   static intx prefetch_data_size()  {
-    return is_T4() ? 32 : 64;  // default prefetch block size on sparc
+    return is_T4() && !is_T7() ? 32 : 64;  // default prefetch block size on sparc
   }
 
   // Prefetch
--- a/src/os/bsd/vm/os_bsd.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/os/bsd/vm/os_bsd.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -1297,9 +1297,20 @@
 //////////////////////////////////////////////////////////////////////////////
 // thread local storage
 
+// Restore the thread pointer if the destructor is called. This is in case
+// someone from JNI code sets up a destructor with pthread_key_create to run
+// detachCurrentThread on thread death. Unless we restore the thread pointer we
+// will hang or crash. When detachCurrentThread is called the key will be set
+// to null and we will not be called again. If detachCurrentThread is never
+// called we could loop forever depending on the pthread implementation.
+static void restore_thread_pointer(void* p) {
+  Thread* thread = (Thread*) p;
+  os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread);
+}
+
 int os::allocate_thread_local_storage() {
   pthread_key_t key;
-  int rslt = pthread_key_create(&key, NULL);
+  int rslt = pthread_key_create(&key, restore_thread_pointer);
   assert(rslt == 0, "cannot allocate thread local storage");
   return (int)key;
 }
--- a/src/os/linux/vm/os_linux.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/os/linux/vm/os_linux.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -1113,9 +1113,20 @@
 //////////////////////////////////////////////////////////////////////////////
 // thread local storage
 
+// Restore the thread pointer if the destructor is called. This is in case
+// someone from JNI code sets up a destructor with pthread_key_create to run
+// detachCurrentThread on thread death. Unless we restore the thread pointer we
+// will hang or crash. When detachCurrentThread is called the key will be set
+// to null and we will not be called again. If detachCurrentThread is never
+// called we could loop forever depending on the pthread implementation.
+static void restore_thread_pointer(void* p) {
+  Thread* thread = (Thread*) p;
+  os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread);
+}
+
 int os::allocate_thread_local_storage() {
   pthread_key_t key;
-  int rslt = pthread_key_create(&key, NULL);
+  int rslt = pthread_key_create(&key, restore_thread_pointer);
   assert(rslt == 0, "cannot allocate thread local storage");
   return (int)key;
 }
--- a/src/os_cpu/linux_sparc/vm/assembler_linux_sparc.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/os_cpu/linux_sparc/vm/assembler_linux_sparc.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -28,16 +28,7 @@
 #include "runtime/os.hpp"
 #include "runtime/threadLocalStorage.hpp"
 
-/* Headers for 32bit sparc with a 32bit userland end up in asm/
- * Headers for 32bit sparc with a 64bit userland end up in asm-sparc/
- * There is no traps.h in asm-sparc64/
- */
-
-#if defined(__sparc__) && defined(__arch64__)
-# include <asm-sparc/traps.h>
-#else 
-# include <asm/traps.h>
-#endif
+#include <asm/traps.h>
 
 void MacroAssembler::read_ccr_trap(Register ccr_save) {
   // No implementation
--- a/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp	Tue Jan 27 00:46:17 2015 +0000
@@ -79,12 +79,12 @@
   __asm__ volatile(
     "1: \n\t"
     " ldx    [%2], %%o2\n\t"
-    " add    %0, %%o2, %%o3\n\t"
+    " add    %1, %%o2, %%o3\n\t"
     " casx   [%2], %%o2, %%o3\n\t"
     " cmp    %%o2, %%o3\n\t"
     " bne    %%xcc, 1b\n\t"
     "  nop\n\t"
-    " add    %0, %%o2, %0\n\t"
+    " add    %1, %%o2, %0\n\t"
     : "=r" (rv)
     : "r" (add_value), "r" (dest)
     : "memory", "o2", "o3");
--- a/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -118,7 +118,7 @@
       *ret_sp = os::Linux::ucontext_get_sp(uc);
     }
     if (ret_fp) {
-      *ret_fp = os::Linux::ucontext_get_fp(uc);
+      *ret_fp = (intptr_t*)NULL;
     }
   } else {
     // construct empty ExtendedPC for return value checking
@@ -136,18 +136,15 @@
 
 frame os::fetch_frame_from_context(void* ucVoid) {
   intptr_t* sp;
-  intptr_t* fp;
-  ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
-  return frame(sp, fp, epc.pc());
+  ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, NULL);
+  return frame(sp, frame::unpatchable, epc.pc());
 }
 
 frame os::get_sender_for_C_frame(frame* fr) {
-  return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
+  return frame(fr->sender_sp(), frame::unpatchable, fr->sender_pc());
 }
 
 frame os::current_frame() {
-  fprintf(stderr, "current_frame()");
-
   intptr_t* sp = StubRoutines::Sparc::flush_callers_register_windows_func()();
   frame myframe(sp, frame::unpatchable,
                 CAST_FROM_FN_PTR(address, os::current_frame));
@@ -526,7 +523,7 @@
   if (nativeInstruction_at(*pc)->is_ic_miss_trap()) {
 #ifdef ASSERT
 #ifdef TIERED
-    CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
+    CodeBlob* cb = CodeCache::find_blob_unsafe(*pc);
     assert(cb->is_compiled_by_c2(), "Wrong compiler");
 #endif // TIERED
 #endif // ASSERT
--- a/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -55,7 +55,7 @@
 
   if (detect_niagara()) {
     NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Detected Linux on Niagara");)
-    features = niagara1_m;
+    features = niagara1_m | T_family_m;
   }
 
   return features;
--- a/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -75,13 +75,19 @@
     do_sysinfo(SI_ARCHITECTURE_64, "sparcv9", &features, generic_v9_m);
 
     // Extract valid instruction set extensions.
-    uint_t av;
-    uint_t avn = os::Solaris::getisax(&av, 1);
-    assert(avn == 1, "should only return one av");
+    uint_t avs[2];
+    uint_t avn = os::Solaris::getisax(avs, 2);
+    assert(avn <= 2, "should return two or less av's");
+    uint_t av = avs[0];
 
 #ifndef PRODUCT
-    if (PrintMiscellaneous && Verbose)
-      tty->print_cr("getisax(2) returned: " PTR32_FORMAT, av);
+    if (PrintMiscellaneous && Verbose) {
+      tty->print("getisax(2) returned: " PTR32_FORMAT, av);
+      if (avn > 1) {
+        tty->print(", " PTR32_FORMAT, avs[1]);
+      }
+      tty->cr();
+    }
 #endif
 
     if (av & AV_SPARC_MUL32)  features |= hardware_mul32_m;
@@ -91,6 +97,13 @@
     if (av & AV_SPARC_POPC)   features |= hardware_popc_m;
     if (av & AV_SPARC_VIS)    features |= vis1_instructions_m;
     if (av & AV_SPARC_VIS2)   features |= vis2_instructions_m;
+    if (avn > 1) {
+      uint_t av2 = avs[1];
+#ifndef AV2_SPARC_SPARC5
+#define AV2_SPARC_SPARC5 0x00000008 /* The 29 new fp and sub instructions */
+#endif
+      if (av2 & AV2_SPARC_SPARC5)       features |= sparc5_instructions_m;
+    }
 
     // Next values are not defined before Solaris 10
     // but Solaris 8 is used for jdk6 update builds.
--- a/src/share/vm/oops/cpCacheOop.hpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/share/vm/oops/cpCacheOop.hpp	Tue Jan 27 00:46:17 2015 +0000
@@ -140,14 +140,15 @@
     oop_store(&_f1, f1);
   }
   void release_set_f1(oop f1);
-  void set_f2(intx f2) { 
-    assert(_f2 == 0 || _f2 == f2, "illegal field change"); 
-    _f2 = f2; 
+  void set_f2(intx f2) {
+    intx existing_f2 = _f2; // read once
+    assert(existing_f2 == 0 || existing_f2 == f2, "illegal field change");
+    _f2 = f2;
   }
-  void set_f2_as_vfinal_method(methodOop f2) { 
-    assert(_f2 == 0 || _f2 == (intptr_t) f2, "illegal field change"); 
-    assert(is_vfinal(), "flags must be set"); 
-    _f2 = (intptr_t) f2; }
+  void set_f2_as_vfinal_method(methodOop f2) {
+    assert(is_vfinal(), "flags must be set");
+    set_f2((intx)f2);
+  }
   int make_flags(TosState state, int option_bits, int field_index_or_method_params);
   void set_flags(intx flags)                     { _flags = flags; }
   bool init_flags_atomic(intx flags);
--- a/src/share/vm/oops/typeArrayOop.hpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/share/vm/oops/typeArrayOop.hpp	Tue Jan 27 00:46:17 2015 +0000
@@ -165,7 +165,7 @@
     DEBUG_ONLY(BasicType etype = Klass::layout_helper_element_type(lh));
     assert(length <= arrayOopDesc::max_array_length(etype), "no overflow");
 
-    julong size_in_bytes = length;
+    julong size_in_bytes = (juint)length;
     size_in_bytes <<= element_shift;
     size_in_bytes += instance_header_size;
     julong size_in_words = ((size_in_bytes + (HeapWordSize-1)) >> LogHeapWordSize);
--- a/src/share/vm/opto/compile.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/share/vm/opto/compile.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -688,6 +688,7 @@
 #endif
   set_print_inlining(PrintInlining || method()->has_option("PrintInlining") NOT_PRODUCT( || PrintOptoInlining));
   set_print_intrinsics(PrintIntrinsics || method()->has_option("PrintIntrinsics"));
+  set_has_irreducible_loop(true); // conservative until build_loop_tree() reset it
 
   if (ProfileTraps) {
     // Make sure the method being compiled gets its own MDO,
@@ -956,6 +957,8 @@
   set_print_assembly(PrintFrameConverterAssembly);
   set_parsed_irreducible_loop(false);
 #endif
+  set_has_irreducible_loop(false); // no loops
+
   CompileWrapper cw(this);
   Init(/*AliasLevel=*/ 0);
   init_tf((*generator)());
@@ -1129,7 +1132,7 @@
     if( start->is_Start() )
       return start->as_Start();
   }
-  ShouldNotReachHere();
+  fatal("Did not find Start node!");
   return NULL;
 }
 
--- a/src/share/vm/opto/compile.hpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/share/vm/opto/compile.hpp	Tue Jan 27 00:46:17 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -293,6 +293,7 @@
   bool                  _trace_opto_output;
   bool                  _parsed_irreducible_loop; // True if ciTypeFlow detected irreducible loops during parsing
 #endif
+  bool                  _has_irreducible_loop;  // Found irreducible loops
 
   // JSR 292
   bool                  _has_method_handle_invokes; // True if this method has MethodHandle invokes.
@@ -555,6 +556,8 @@
   void          set_parsed_irreducible_loop(bool z) { _parsed_irreducible_loop = z; }
   int _in_dump_cnt;  // Required for dumping ir nodes.
 #endif
+  bool              has_irreducible_loop() const { return _has_irreducible_loop; }
+  void          set_has_irreducible_loop(bool z) { _has_irreducible_loop = z; }
 
   // JSR 292
   bool              has_method_handle_invokes() const { return _has_method_handle_invokes;     }
--- a/src/share/vm/opto/library_call.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/share/vm/opto/library_call.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -3715,8 +3715,11 @@
 }
 
 
-//------------------------------inline_native_hashcode--------------------
-// Build special case code for calls to hashCode on an object.
+/**
+ * Build special case code for calls to hashCode on an object. This call may
+ * be virtual (invokevirtual) or bound (invokespecial). For each case we generate
+ * slightly different code.
+ */
 bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) {
   assert(is_static == callee()->is_static(), "correct intrinsic selection");
   assert(!(is_virtual && is_static), "either virtual, special, or static");
@@ -3724,11 +3727,9 @@
   enum { _slow_path = 1, _fast_path, _null_path, PATH_LIMIT };
 
   RegionNode* result_reg = new(C) RegionNode(PATH_LIMIT);
-  PhiNode*    result_val = new(C) PhiNode(result_reg,
-                                          TypeInt::INT);
+  PhiNode*    result_val = new(C) PhiNode(result_reg, TypeInt::INT);
   PhiNode*    result_io  = new(C) PhiNode(result_reg, Type::ABIO);
-  PhiNode*    result_mem = new(C) PhiNode(result_reg, Type::MEMORY,
-                                          TypePtr::BOTTOM);
+  PhiNode*    result_mem = new(C) PhiNode(result_reg, Type::MEMORY, TypePtr::BOTTOM);
   Node* obj = NULL;
   if (!is_static) {
     // Check for hashing null object
@@ -3754,12 +3755,6 @@
     return true;
   }
 
-  // After null check, get the object's klass.
-  Node* obj_klass = load_object_klass(obj);
-
-  // This call may be virtual (invokevirtual) or bound (invokespecial).
-  // For each case we generate slightly different code.
-
   // We only go to the fast case code if we pass a number of guards.  The
   // paths which do not pass are accumulated in the slow_region.
   RegionNode* slow_region = new (C) RegionNode(1);
@@ -3772,19 +3767,24 @@
   // guard for non-virtual calls -- the caller is known to be the native
   // Object hashCode().
   if (is_virtual) {
+    // After null check, get the object's klass.
+    Node* obj_klass = load_object_klass(obj);
     generate_virtual_guard(obj_klass, slow_region);
   }
 
   // Get the header out of the object, use LoadMarkNode when available
   Node* header_addr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes());
-  Node* header = make_load(control(), header_addr, TypeX_X, TypeX_X->basic_type());
+  // The control of the load must be NULL. Otherwise, the load can move before
+  // the null check after castPP removal.
+  Node* no_ctrl = NULL;
+  Node* header = make_load(no_ctrl, header_addr, TypeX_X, TypeX_X->basic_type());
 
   // Test the header to see if it is unlocked.
-  Node *lock_mask      = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place);
-  Node *lmasked_header = _gvn.transform( new (C) AndXNode(header, lock_mask) );
-  Node *unlocked_val   = _gvn.MakeConX(markOopDesc::unlocked_value);
-  Node *chk_unlocked   = _gvn.transform( new (C) CmpXNode( lmasked_header, unlocked_val));
-  Node *test_unlocked  = _gvn.transform( new (C) BoolNode( chk_unlocked, BoolTest::ne) );
+  Node* lock_mask      = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place);
+  Node* lmasked_header = _gvn.transform(new (C) AndXNode(header, lock_mask));
+  Node* unlocked_val   = _gvn.MakeConX(markOopDesc::unlocked_value);
+  Node* chk_unlocked   = _gvn.transform(new (C) CmpXNode( lmasked_header, unlocked_val));
+  Node* test_unlocked  = _gvn.transform(new (C) BoolNode( chk_unlocked, BoolTest::ne));
 
   generate_slow_guard(test_unlocked, slow_region);
 
@@ -3792,19 +3792,19 @@
   // We depend on hash_mask being at most 32 bits and avoid the use of
   // hash_mask_in_place because it could be larger than 32 bits in a 64-bit
   // vm: see markOop.hpp.
-  Node *hash_mask      = _gvn.intcon(markOopDesc::hash_mask);
-  Node *hash_shift     = _gvn.intcon(markOopDesc::hash_shift);
-  Node *hshifted_header= _gvn.transform( new (C) URShiftXNode(header, hash_shift) );
+  Node* hash_mask      = _gvn.intcon(markOopDesc::hash_mask);
+  Node* hash_shift     = _gvn.intcon(markOopDesc::hash_shift);
+  Node* hshifted_header= _gvn.transform(new (C) URShiftXNode(header, hash_shift));
   // This hack lets the hash bits live anywhere in the mark object now, as long
   // as the shift drops the relevant bits into the low 32 bits.  Note that
   // Java spec says that HashCode is an int so there's no point in capturing
   // an 'X'-sized hashcode (32 in 32-bit build or 64 in 64-bit build).
   hshifted_header      = ConvX2I(hshifted_header);
-  Node *hash_val       = _gvn.transform( new (C) AndINode(hshifted_header, hash_mask) );
-
-  Node *no_hash_val    = _gvn.intcon(markOopDesc::no_hash);
-  Node *chk_assigned   = _gvn.transform( new (C) CmpINode( hash_val, no_hash_val));
-  Node *test_assigned  = _gvn.transform( new (C) BoolNode( chk_assigned, BoolTest::eq) );
+  Node* hash_val       = _gvn.transform(new (C) AndINode(hshifted_header, hash_mask));
+
+  Node* no_hash_val    = _gvn.intcon(markOopDesc::no_hash);
+  Node* chk_assigned   = _gvn.transform(new (C) CmpINode( hash_val, no_hash_val));
+  Node* test_assigned  = _gvn.transform(new (C) BoolNode( chk_assigned, BoolTest::eq));
 
   generate_slow_guard(test_assigned, slow_region);
 
--- a/src/share/vm/opto/loopTransform.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/share/vm/opto/loopTransform.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -1127,6 +1127,7 @@
   // Now force out all loop-invariant dominating tests.  The optimizer
   // finds some, but we _know_ they are all useless.
   peeled_dom_test_elim(loop,old_new);
+  loop->record_for_igvn();
 }
 
 //------------------------------is_invariant-----------------------------
--- a/src/share/vm/opto/loopnode.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/share/vm/opto/loopnode.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -266,9 +266,9 @@
 
   // Counted loop head must be a good RegionNode with only 3 not NULL
   // control input edges: Self, Entry, LoopBack.
-  if (x->in(LoopNode::Self) == NULL || x->req() != 3)
+  if (x->in(LoopNode::Self) == NULL || x->req() != 3 || loop->_irreducible) {
     return false;
-
+  }
   Node *init_control = x->in(LoopNode::EntryControl);
   Node *back_control = x->in(LoopNode::LoopBackControl);
   if (init_control == NULL || back_control == NULL)    // Partially dead
@@ -1522,11 +1522,11 @@
 
   // If I have one hot backedge, peel off myself loop.
   // I better be the outermost loop.
-  if( _head->req() > 3 ) {
+  if (_head->req() > 3 && !_irreducible) {
     split_outer_loop( phase );
     result = true;
 
-  } else if( !_head->is_Loop() && !_irreducible ) {
+  } else if (!_head->is_Loop() && !_irreducible) {
     // Make a new LoopNode to replace the old loop head
     Node *l = new (phase->C) LoopNode( _head->in(1), _head->in(2) );
     l = igvn.register_new_node_with_optimizer(l, _head);
@@ -2938,6 +2938,7 @@
           return pre_order;
         }
       }
+      C->set_has_irreducible_loop(_has_irreducible_loops);
     }
 
     // This Node might be a decision point for loops.  It is only if
@@ -3171,17 +3172,16 @@
   bool had_error = false;
 #ifdef ASSERT
   if (early != C->root()) {
-    // Make sure that there's a dominance path from use to LCA
-    Node* d = use;
-    while (d != LCA) {
-      d = idom(d);
+    // Make sure that there's a dominance path from LCA to early
+    Node* d = LCA;
+    while (d != early) {
       if (d == C->root()) {
-        tty->print_cr("*** Use %d isn't dominated by def %s", use->_idx, n->_idx);
-        n->dump();
-        use->dump();
+        dump_bad_graph("Bad graph detected in compute_lca_of_uses", n, early, LCA);
+        tty->print_cr("*** Use %d isn't dominated by def %d ***", use->_idx, n->_idx);
         had_error = true;
         break;
       }
+      d = idom(d);
     }
   }
 #endif
@@ -3434,6 +3434,13 @@
     _igvn._worklist.push(n);  // Maybe we'll normalize it, if no more loops.
   }
 
+#ifdef ASSERT
+  if (_verify_only && !n->is_CFG()) {
+    // Check def-use domination.
+    compute_lca_of_uses(n, get_ctrl(n), true /* verify */);
+  }
+#endif
+
   // CFG and pinned nodes already handled
   if( n->in(0) ) {
     if( n->in(0)->is_top() ) return; // Dead?
--- a/src/share/vm/opto/loopopts.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/share/vm/opto/loopopts.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -2684,6 +2684,7 @@
   // Inhibit more partial peeling on this loop
   new_head_clone->set_partial_peel_loop();
   C->set_major_progress();
+  loop->record_for_igvn();
 
 #if !defined(PRODUCT)
   if (TracePartialPeeling) {
--- a/src/share/vm/opto/memnode.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/share/vm/opto/memnode.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -292,33 +292,16 @@
     int alias_idx = phase->C->get_alias_index(t_adr->is_ptr());
   }
 
-#ifdef ASSERT
   Node* base = NULL;
-  if (address->is_AddP())
+  if (address->is_AddP()) {
     base = address->in(AddPNode::Base);
+  }
   if (base != NULL && phase->type(base)->higher_equal(TypePtr::NULL_PTR) &&
       !t_adr->isa_rawptr()) {
     // Note: raw address has TOP base and top->higher_equal(TypePtr::NULL_PTR) is true.
-    Compile* C = phase->C;
-    tty->cr();
-    tty->print_cr("===== NULL+offs not RAW address =====");
-    if (C->is_dead_node(this->_idx))    tty->print_cr("'this' is dead");
-    if ((ctl != NULL) && C->is_dead_node(ctl->_idx)) tty->print_cr("'ctl' is dead");
-    if (C->is_dead_node(mem->_idx))     tty->print_cr("'mem' is dead");
-    if (C->is_dead_node(address->_idx)) tty->print_cr("'address' is dead");
-    if (C->is_dead_node(base->_idx))    tty->print_cr("'base' is dead");
-    tty->cr();
-    base->dump(1);
-    tty->cr();
-    this->dump(2);
-    tty->print("this->adr_type():     "); adr_type()->dump(); tty->cr();
-    tty->print("phase->type(address): "); t_adr->dump(); tty->cr();
-    tty->print("phase->type(base):    "); phase->type(address)->dump(); tty->cr();
-    tty->cr();
+    // Skip this node optimization if its address has TOP base.
+    return NodeSentinel; // caller will return NULL
   }
-  assert(base == NULL || t_adr->isa_rawptr() ||
-        !phase->type(base)->higher_equal(TypePtr::NULL_PTR), "NULL+offs not RAW address?");
-#endif
 
   // Avoid independent memory operations
   Node* old_mem = mem;
--- a/src/share/vm/opto/node.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/share/vm/opto/node.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -27,6 +27,7 @@
 #include "memory/allocation.inline.hpp"
 #include "opto/cfgnode.hpp"
 #include "opto/connode.hpp"
+#include "opto/loopnode.hpp"
 #include "opto/machnode.hpp"
 #include "opto/matcher.hpp"
 #include "opto/node.hpp"
@@ -1228,6 +1229,7 @@
 
   Node *top = igvn->C->top();
   nstack.push(dead);
+  bool has_irreducible_loop = igvn->C->has_irreducible_loop();
 
   while (nstack.size() > 0) {
     dead = nstack.pop();
@@ -1242,13 +1244,31 @@
           assert (!use->is_Con(), "Control for Con node should be Root node.");
           use->set_req(0, top);       // Cut dead edge to prevent processing
           nstack.push(use);           // the dead node again.
+        } else if (!has_irreducible_loop && // Backedge could be alive in irreducible loop
+                   use->is_Loop() && !use->is_Root() &&       // Don't kill Root (RootNode extends LoopNode)
+                   use->in(LoopNode::EntryControl) == dead) { // Dead loop if its entry is dead
+          use->set_req(LoopNode::EntryControl, top);          // Cut dead edge to prevent processing
+          use->set_req(0, top);       // Cut self edge
+          nstack.push(use);
         } else {                      // Else found a not-dead user
+          // Dead if all inputs are top or null
+          bool dead_use = !use->is_Root(); // Keep empty graph alive
           for (uint j = 1; j < use->req(); j++) {
-            if (use->in(j) == dead) { // Turn all dead inputs into TOP
+            Node* in = use->in(j);
+            if (in == dead) {         // Turn all dead inputs into TOP
               use->set_req(j, top);
+            } else if (in != NULL && !in->is_top()) {
+              dead_use = false;
             }
           }
-          igvn->_worklist.push(use);
+          if (dead_use) {
+            if (use->is_Region()) {
+              use->set_req(0, top);   // Cut self edge
+            }
+            nstack.push(use);
+          } else {
+            igvn->_worklist.push(use);
+          }
         }
         // Refresh the iterator, since any number of kills might have happened.
         k = dead->last_outs(kmin);
--- a/src/share/vm/runtime/vmThread.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/share/vm/runtime/vmThread.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -330,6 +330,9 @@
     _terminate_lock->notify();
   }
 
+  // Thread destructor usually does this.
+  ThreadLocalStorage::set_thread(NULL);
+
   // Deletion must be done synchronously by the JNI DestroyJavaVM thread
   // so that the VMThread deletion completes before the main thread frees
   // up the CodeHeap.
--- a/src/share/vm/services/heapDumper.cpp	Wed Jan 21 03:56:44 2015 +0000
+++ b/src/share/vm/services/heapDumper.cpp	Tue Jan 27 00:46:17 2015 +0000
@@ -720,7 +720,7 @@
 
       // reflection and sun.misc.Unsafe classes may have a reference to a
       // klassOop so filter it out.
-      if (o != NULL && o->is_klass()) {
+      if (o != NULL && o->is_perm() && o->is_klass()) {
         o = NULL;
       }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/intrinsics/hashcode/TestHashCode.java	Tue Jan 27 00:46:17 2015 +0000
@@ -0,0 +1,73 @@
+/*
+ * 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
+ * @bug 8011646
+ * @summary SEGV in compiled code with loop predication
+ * @run main/othervm  -XX:-TieredCompilation -XX:CompileOnly=TestHashCode.m1,Object.hashCode TestHashCode
+ *
+ */
+
+public class TestHashCode {
+    static class A {
+        int i;
+    }
+
+    static class B extends A {
+    }
+
+    static boolean crash = false;
+
+    static A m2() {
+        if (crash) {
+            return null;
+        }
+        return new A();
+    }
+
+    static int m1(A aa) {
+        int res = 0;
+        for (int i = 0; i < 10; i++) {
+            A a = m2();
+            int j = a.i;
+            if (aa instanceof B) {
+            }
+            res += a.hashCode();
+        }
+        return res;
+    }
+
+    public static void main(String[] args) {
+        A a = new A();
+        for (int i = 0; i < 20000; i++) {
+            m1(a);
+        }
+        crash = true;
+        try {
+          m1(a);
+        } catch (NullPointerException e) {
+            System.out.println("Test passed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/heap_inspection/TestG1ConcurrentGCHeapDump.java	Tue Jan 27 00:46:17 2015 +0000
@@ -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 TestG1ConcurrentGCHeapDump
+ * @bug 8038925
+ * @summary Checks that a heap dump can be made with G1 when no fullgc
+ *          has been made
+ * @run main/othervm -Xms512m -Xmx1024m -XX:+ExplicitGCInvokesConcurrent TestG1ConcurrentGCHeapDump
+ */
+import java.util.List;
+import java.util.ArrayList;
+import java.util.LinkedList;
+
+import javax.management.MBeanServer;
+import java.lang.management.ManagementFactory;
+import java.lang.management.GarbageCollectorMXBean;
+
+import sun.management.ManagementFactoryHelper;
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+
+import java.io.IOException;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.Files;
+
+public class TestG1ConcurrentGCHeapDump {
+
+  private static final String HOTSPOT_BEAN_NAME =
+    "com.sun.management:type=HotSpotDiagnostic";
+
+  private static final String G1_OLD_BEAN_NAME =
+    "java.lang:type=GarbageCollector,name=G1 Old Generation";
+
+  private static MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+  private static void dumpHeap() throws IOException {
+    HotSpotDiagnosticMXBean hotspot_bean =
+      ManagementFactory.newPlatformMXBeanProxy(server,
+          HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean.class);
+
+    Path dir = Files.createTempDirectory("JDK-8038925_");
+    String file = dir + File.separator + "heapdump";
+    hotspot_bean.dumpHeap(file, false);
+    Files.delete(Paths.get(file));
+    Files.delete(dir);
+  }
+
+  private static void verifyNoFullGC() throws IOException {
+    GarbageCollectorMXBean g1_old_bean =
+      ManagementFactory.newPlatformMXBeanProxy(server,
+          G1_OLD_BEAN_NAME, GarbageCollectorMXBean.class);
+
+    if (g1_old_bean.getCollectionCount() != 0) {
+      throw new RuntimeException("A full GC has occured, this test will not work.");
+    }
+  }
+
+  public static void main(String[] args) throws IOException {
+    HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean();
+    VMOption option = diagnostic.getVMOption("UseG1GC");
+    if (option.getValue().equals("false")) {
+      System.out.println("Skipping this test. It is only a G1 test.");
+      return;
+    }
+
+    // Create some dead objects
+    ArrayList<List<Integer>> arraylist = new ArrayList<List<Integer>>();
+    for (int i = 0; i < 2; i++) {
+      for (int j = 0; j < 100; j++) {
+        LinkedList<Integer> li = new LinkedList<Integer>();
+        arraylist.add(li);
+        for (int k = 0; k < 10000; k++) {
+          li.add(k);
+        }
+      }
+      arraylist = new ArrayList<List<Integer>>();
+      System.gc();
+    }
+    // Try to dump heap
+    dumpHeap();
+    // Make sure no full GC has happened, since test won't work if that is the case
+    verifyNoFullGC();
+  }
+}