changeset 9748:0316b41ccb2f

Merge
author jwilhelm
date Tue, 08 Sep 2015 16:10:37 +0200
parents 8f5648c43725 (diff) 9a8f97037119 (current diff)
children bef52fbeb8ae
files src/cpu/aarch64/vm/stubGenerator_aarch64.cpp src/cpu/sparc/vm/stubGenerator_sparc.cpp src/cpu/sparc/vm/vm_version_sparc.cpp src/share/vm/classfile/imageDecompressor.cpp src/share/vm/classfile/imageDecompressor.hpp src/share/vm/classfile/imageFile.cpp src/share/vm/classfile/imageFile.hpp src/share/vm/runtime/arguments.cpp src/share/vm/runtime/globals.hpp src/share/vm/utilities/endian.cpp src/share/vm/utilities/endian.hpp test/runtime/modules/ImageFile/ImageAttributeOffsetsTest.java test/runtime/modules/ImageFile/ImageCloseTest.java test/runtime/modules/ImageFile/ImageFileHeaderTest.java test/runtime/modules/ImageFile/ImageFindAttributesTest.java test/runtime/modules/ImageFile/ImageGetAttributesTest.java test/runtime/modules/ImageFile/ImageGetDataAddressTest.java test/runtime/modules/ImageFile/ImageGetIndexAddressTest.java test/runtime/modules/ImageFile/ImageGetStringBytesTest.java test/runtime/modules/ImageFile/ImageOpenTest.java test/runtime/modules/ImageFile/ImageReadTest.java test/runtime/modules/ImageFile/LocationConstants.java
diffstat 54 files changed, 1548 insertions(+), 696 deletions(-) [+]
line wrap: on
line diff
--- a/make/Makefile	Mon Sep 07 20:03:56 2015 +0200
+++ b/make/Makefile	Tue Sep 08 16:10:37 2015 +0200
@@ -633,9 +633,9 @@
 
 update_jdk: export_product_jdk export_fastdebug_jdk test_jdk
 
-copy_jdk: $(JDK_IMAGE_DIR)/jre/lib/rt.jar
+copy_jdk: $(JDK_IMAGE_DIR)/bin/java
 
-$(JDK_IMAGE_DIR)/jre/lib/rt.jar:
+$(JDK_IMAGE_DIR)/bin/java:
 	$(RM) -r $(JDK_IMAGE_DIR)
 	$(MKDIR) -p $(JDK_IMAGE_DIR)
 	($(CD) $(JDK_IMPORT_PATH) && \
--- a/make/bsd/makefiles/vm.make	Mon Sep 07 20:03:56 2015 +0200
+++ b/make/bsd/makefiles/vm.make	Tue Sep 08 16:10:37 2015 +0200
@@ -131,7 +131,7 @@
 # By default, link the *.o into the library, not the executable.
 LINK_INTO$(LINK_INTO) = LIBJVM
 
-JDK_LIBDIR = $(JAVA_HOME)/jre/lib/$(LIBARCH)
+JDK_LIBDIR = $(JAVA_HOME)/lib/$(LIBARCH)
 
 #----------------------------------------------------------------------
 # jvm_db & dtrace
--- a/make/build.sh	Mon Sep 07 20:03:56 2015 +0200
+++ b/make/build.sh	Tue Sep 08 16:10:37 2015 +0200
@@ -49,7 +49,7 @@
 # Just in case:
 JAVA_HOME=`( cd $JAVA_HOME; pwd )`
 
-if [ "${ALT_BOOTDIR-}" = ""  -o  ! -d "${ALT_BOOTDIR-}" -o ! -d ${ALT_BOOTDIR-}/jre/lib/ ]; then
+if [ "${ALT_BOOTDIR-}" = ""  -o  ! -d "${ALT_BOOTDIR-}" -o ! -d ${ALT_BOOTDIR-}/lib/ ]; then
     ALT_BOOTDIR=${JAVA_HOME}
 fi
 
--- a/make/hotspot.script	Mon Sep 07 20:03:56 2015 +0200
+++ b/make/hotspot.script	Tue Sep 08 16:10:37 2015 +0200
@@ -127,7 +127,7 @@
 #     o		$JRE/lib/$ARCH
 # followed by the user's previous effective LD_LIBRARY_PATH, if
 # any.
-JRE=$JDK/jre
+JRE=$JDK
 JAVA_HOME=$JDK
 export JAVA_HOME
 
--- a/make/solaris/makefiles/buildtree.make	Mon Sep 07 20:03:56 2015 +0200
+++ b/make/solaris/makefiles/buildtree.make	Tue Sep 08 16:10:37 2015 +0200
@@ -270,6 +270,7 @@
 	echo "CP ?= cp"; \
 	echo "MV ?= mv"; \
 	echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \
+	echo "include \$$(GAMMADIR)/make/excludeSrc.make"; \
 	echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \
 	) > $@
 
--- a/make/solaris/makefiles/vm.make	Mon Sep 07 20:03:56 2015 +0200
+++ b/make/solaris/makefiles/vm.make	Tue Sep 08 16:10:37 2015 +0200
@@ -197,7 +197,7 @@
 Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS)
 Src_Dirs/TIERED    := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS)
 Src_Dirs/ZERO      := $(CORE_PATHS)
-Src_Dirs/SHARK     := $(CORE_PATHS)
+Src_Dirs/SHARK     := $(CORE_PATHS) $(SHARK_PATHS)
 Src_Dirs := $(Src_Dirs/$(TYPE))
 
 COMPILER2_SPECIFIC_FILES := opto libadt bcEscapeAnalyzer.cpp c2_\* runtime_\*
@@ -206,7 +206,7 @@
 ZERO_SPECIFIC_FILES      := zero
 
 # Always exclude these.
-Src_Files_EXCLUDE := dtrace jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp
+Src_Files_EXCLUDE += dtrace jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp
 
 # Exclude per type.
 Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
--- a/src/cpu/aarch64/vm/aarch64.ad	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/cpu/aarch64/vm/aarch64.ad	Tue Sep 08 16:10:37 2015 +0200
@@ -4373,12 +4373,12 @@
       return;
     }
 
-    if (UseBiasedLocking) {
-      __ biased_locking_enter(disp_hdr, oop, box, tmp, true, cont);
+    if (UseBiasedLocking && !UseOptoBiasInlining) {
+      __ biased_locking_enter(box, oop, disp_hdr, tmp, true, cont);
     }
 
     // Handle existing monitor
-    if (EmitSync & 0x02) {
+    if ((EmitSync & 0x02) == 0) {
       // we can use AArch64's bit test and branch here but
       // markoopDesc does not define a bit index just the bit value
       // so assert in case the bit pos changes
@@ -4518,7 +4518,7 @@
       return;
     }
 
-    if (UseBiasedLocking) {
+    if (UseBiasedLocking && !UseOptoBiasInlining) {
       __ biased_locking_exit(oop, tmp, cont);
     }
 
--- a/src/cpu/aarch64/vm/assembler_aarch64.hpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/cpu/aarch64/vm/assembler_aarch64.hpp	Tue Sep 08 16:10:37 2015 +0200
@@ -1210,7 +1210,7 @@
 
   INSN(ldrs, 0b00, 1);
   INSN(ldrd, 0b01, 1);
-  INSN(ldrq, 0x10, 1);
+  INSN(ldrq, 0b10, 1);
 
 #undef INSN
 
@@ -2285,13 +2285,13 @@
 #undef INSN
 
   // Table vector lookup
-#define INSN(NAME, op)                                                                                       \
-  void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, unsigned registers, FloatRegister Vm) {  \
-    starti;                                                                                                  \
-    assert(T == T8B || T == T16B, "invalid arrangement");                                                    \
-    assert(0 < registers && registers <= 4, "invalid number of registers");                                  \
-    f(0, 31), f((int)T & 1, 30), f(0b001110000, 29, 21), rf(Vm, 16), f(0, 15);                               \
-    f(registers - 1, 14, 13), f(op, 12),f(0b00, 11, 10), rf(Vn, 5), rf(Vd, 0);                               \
+#define INSN(NAME, op)                                                  \
+  void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, unsigned registers, FloatRegister Vm) { \
+    starti;                                                             \
+    assert(T == T8B || T == T16B, "invalid arrangement");               \
+    assert(0 < registers && registers <= 4, "invalid number of registers"); \
+    f(0, 31), f((int)T & 1, 30), f(0b001110000, 29, 21), rf(Vm, 16), f(0, 15); \
+    f(registers - 1, 14, 13), f(op, 12),f(0b00, 11, 10), rf(Vn, 5), rf(Vd, 0); \
   }
 
   INSN(tbl, 0);
@@ -2299,6 +2299,7 @@
 
 #undef INSN
 
+  // AdvSIMD two-reg misc
 #define INSN(NAME, U, opcode)                                                       \
   void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {               \
        starti;                                                                      \
@@ -2316,10 +2317,19 @@
 
 #define ASSERTION (T == T8B || T == T16B || T == T4H || T == T8H)
   INSN(rev32, 1, 0b00000);
+private:
+  INSN(_rbit, 1, 0b00101);
+public:
+
 #undef ASSERTION
 
 #define ASSERTION (T == T8B || T == T16B)
   INSN(rev16, 0, 0b00001);
+  // RBIT only allows T8B and T16B but encodes them oddly.  Argh...
+  void rbit(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {
+    assert((ASSERTION), MSG);
+    _rbit(Vd, SIMD_Arrangement(T & 1 | 0b010), Vn);
+  }
 #undef ASSERTION
 
 #undef MSG
--- a/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -2364,7 +2364,7 @@
    *   c_rarg3   - int* table
    *
    * Ouput:
-   *       rax   - int crc result
+   *       r0   - int crc result
    */
   address generate_updateBytesCRC32C() {
     assert(UseCRC32CIntrinsics, "what are we doing here?");
@@ -2435,6 +2435,69 @@
     return start;
   }
 
+  void ghash_multiply(FloatRegister result_lo, FloatRegister result_hi,
+                      FloatRegister a, FloatRegister b, FloatRegister a1_xor_a0,
+                      FloatRegister tmp1, FloatRegister tmp2, FloatRegister tmp3, FloatRegister tmp4) {
+    // Karatsuba multiplication performs a 128*128 -> 256-bit
+    // multiplication in three 128-bit multiplications and a few
+    // additions.
+    //
+    // (C1:C0) = A1*B1, (D1:D0) = A0*B0, (E1:E0) = (A0+A1)(B0+B1)
+    // (A1:A0)(B1:B0) = C1:(C0+C1+D1+E1):(D1+C0+D0+E0):D0
+    //
+    // Inputs:
+    //
+    // A0 in a.d[0]     (subkey)
+    // A1 in a.d[1]
+    // (A1+A0) in a1_xor_a0.d[0]
+    //
+    // B0 in b.d[0]     (state)
+    // B1 in b.d[1]
+
+    __ ext(tmp1, __ T16B, b, b, 0x08);
+    __ pmull2(result_hi, __ T1Q, b, a, __ T2D);  // A1*B1
+    __ eor(tmp1, __ T16B, tmp1, b);            // (B1+B0)
+    __ pmull(result_lo,  __ T1Q, b, a, __ T1D);  // A0*B0
+    __ pmull(tmp2, __ T1Q, tmp1, a1_xor_a0, __ T1D); // (A1+A0)(B1+B0)
+
+    __ ext(tmp4, __ T16B, result_lo, result_hi, 0x08);
+    __ eor(tmp3, __ T16B, result_hi, result_lo); // A1*B1+A0*B0
+    __ eor(tmp2, __ T16B, tmp2, tmp4);
+    __ eor(tmp2, __ T16B, tmp2, tmp3);
+
+    // Register pair <result_hi:result_lo> holds the result of carry-less multiplication
+    __ ins(result_hi, __ D, tmp2, 0, 1);
+    __ ins(result_lo, __ D, tmp2, 1, 0);
+  }
+
+  void ghash_reduce(FloatRegister result, FloatRegister lo, FloatRegister hi,
+                    FloatRegister p, FloatRegister z, FloatRegister t1) {
+    const FloatRegister t0 = result;
+
+    // The GCM field polynomial f is z^128 + p(z), where p =
+    // z^7+z^2+z+1.
+    //
+    //    z^128 === -p(z)  (mod (z^128 + p(z)))
+    //
+    // so, given that the product we're reducing is
+    //    a == lo + hi * z^128
+    // substituting,
+    //      === lo - hi * p(z)  (mod (z^128 + p(z)))
+    //
+    // we reduce by multiplying hi by p(z) and subtracting the result
+    // from (i.e. XORing it with) lo.  Because p has no nonzero high
+    // bits we can do this with two 64-bit multiplications, lo*p and
+    // hi*p.
+
+    __ pmull2(t0, __ T1Q, hi, p, __ T2D);
+    __ ext(t1, __ T16B, t0, z, 8);
+    __ eor(hi, __ T16B, hi, t1);
+    __ ext(t1, __ T16B, z, t0, 8);
+    __ eor(lo, __ T16B, lo, t1);
+    __ pmull(t0, __ T1Q, hi, p, __ T1D);
+    __ eor(result, __ T16B, lo, t0);
+  }
+
   /**
    *  Arguments:
    *
@@ -2448,10 +2511,27 @@
    *  Updated state at c_rarg0
    */
   address generate_ghash_processBlocks() {
-    __ align(CodeEntryAlignment);
-    Label L_ghash_loop, L_exit;
+    // Bafflingly, GCM uses little-endian for the byte order, but
+    // big-endian for the bit order.  For example, the polynomial 1 is
+    // represented as the 16-byte string 80 00 00 00 | 12 bytes of 00.
+    //
+    // So, we must either reverse the bytes in each word and do
+    // everything big-endian or reverse the bits in each byte and do
+    // it little-endian.  On AArch64 it's more idiomatic to reverse
+    // the bits in each byte (we have an instruction, RBIT, to do
+    // that) and keep the data in little-endian bit order throught the
+    // calculation, bit-reversing the inputs and outputs.
 
     StubCodeMark mark(this, "StubRoutines", "ghash_processBlocks");
+    __ align(wordSize * 2);
+    address p = __ pc();
+    __ emit_int64(0x87);  // The low-order bits of the field
+                          // polynomial (i.e. p = z^7+z^2+z+1)
+                          // repeated in the low and high parts of a
+                          // 128-bit vector
+    __ emit_int64(0x87);
+
+    __ align(CodeEntryAlignment);
     address start = __ pc();
 
     Register state   = c_rarg0;
@@ -2462,104 +2542,43 @@
     FloatRegister vzr = v30;
     __ eor(vzr, __ T16B, vzr, vzr); // zero register
 
-    __ mov(v26, __ T16B, 1);
-    __ mov(v27, __ T16B, 63);
-    __ mov(v28, __ T16B, 62);
-    __ mov(v29, __ T16B, 57);
-
-    __ ldrq(v6, Address(state));
-    __ ldrq(v16, Address(subkeyH));
-
-    __ ext(v0, __ T16B, v6, v6, 0x08);
-    __ ext(v1, __ T16B, v16, v16, 0x08);
-    __ eor(v16, __ T16B, v16, v1);
-
-    __ bind(L_ghash_loop);
-
-    __ ldrq(v2, Address(__ post(data, 0x10)));
-    __ rev64(v2, __ T16B, v2); // swap data
-
-    __ ext(v6, __ T16B, v0, v0, 0x08);
-    __ eor(v6, __ T16B, v6, v2);
-    __ ext(v2, __ T16B, v6, v6, 0x08);
-
-    __ pmull2(v7, __ T1Q, v2, v1, __ T2D);  // A1*B1
-    __ eor(v6, __ T16B, v6, v2);
-    __ pmull(v5,  __ T1Q, v2, v1, __ T1D);  // A0*B0
-    __ pmull(v20, __ T1Q, v6, v16, __ T1D);  // (A1 + A0)(B1 + B0)
-
-    __ ext(v21, __ T16B, v5, v7, 0x08);
-    __ eor(v18, __ T16B, v7, v5); // A1*B1 xor A0*B0
-    __ eor(v20, __ T16B, v20, v21);
-    __ eor(v20, __ T16B, v20, v18);
-
-    // Registers pair <v7:v5> holds the result of carry-less multiplication
-    __ ins(v7, __ D, v20, 0, 1);
-    __ ins(v5, __ D, v20, 1, 0);
-
-    // Result of the multiplication is shifted by one bit position
-    // [X3:X2:X1:X0] = [X3:X2:X1:X0] << 1
-    __ ushr(v18, __ T2D, v5, -63 & 63);
-    __ ins(v25, __ D, v18, 1, 0);
-    __ ins(v25, __ D, vzr, 0, 0);
-    __ ushl(v5, __ T2D, v5, v26);
-    __ orr(v5, __ T16B, v5, v25);
-
-    __ ushr(v19, __ T2D, v7, -63 & 63);
-    __ ins(v19, __ D, v19, 1, 0);
-    __ ins(v19, __ D, v18, 0, 1);
-    __ ushl(v7, __ T2D, v7, v26);
-    __ orr(v6, __ T16B, v7, v19);
-
-    __ ins(v24, __ D, v5, 0, 1);
-
-    // A = X0 << 63
-    __ ushl(v21, __ T2D, v5, v27);
-
-    // A = X0 << 62
-    __ ushl(v22, __ T2D, v5, v28);
-
-    // A = X0 << 57
-    __ ushl(v23, __ T2D, v5, v29);
-
-    // D = X1^A^B^C
-    __ eor(v21, __ T16B, v21, v22);
-    __ eor(v21, __ T16B, v21, v23);
-    __ eor(v21, __ T16B, v21, v24);
-    __ ins(v5, __ D, v21, 1, 0);
-
-    // [E1:E0] = [D:X0] >> 1
-    __ ushr(v20, __ T2D, v5, -1 & 63);
-    __ ushl(v18, __ T2D, v5, v27);
-    __ ext(v25, __ T16B, v18, vzr, 0x08);
-    __ orr(v19, __ T16B, v20, v25);
-
-    __ eor(v7, __ T16B, v5, v19);
-
-    // [F1:F0] = [D:X0] >> 2
-    __ ushr(v20, __ T2D, v5, -2 & 63);
-    __ ushl(v18, __ T2D, v5, v28);
-    __ ins(v25, __ D, v18, 0, 1);
-    __ orr(v19, __ T16B, v20, v25);
-
-    __ eor(v7, __ T16B, v7, v19);
-
-    // [G1:G0] = [D:X0] >> 7
-    __ ushr(v20, __ T2D, v5, -7 & 63);
-    __ ushl(v18, __ T2D, v5, v29);
-    __ ins(v25, __ D, v18, 0, 1);
-    __ orr(v19, __ T16B, v20, v25);
-
-    // [H1:H0] = [D^E1^F1^G1:X0^E0^F0^G0]
-    __ eor(v7, __ T16B, v7, v19);
-
-    // Result = [H1:H0]^[X3:X2]
-    __ eor(v0, __ T16B, v7, v6);
-
-    __ subs(blocks, blocks, 1);
-    __ cbnz(blocks, L_ghash_loop);
-
-    __ ext(v1, __ T16B, v0, v0, 0x08);
+    __ ldrq(v0, Address(state));
+    __ ldrq(v1, Address(subkeyH));
+
+    __ rev64(v0, __ T16B, v0);          // Bit-reverse words in state and subkeyH
+    __ rbit(v0, __ T16B, v0);
+    __ rev64(v1, __ T16B, v1);
+    __ rbit(v1, __ T16B, v1);
+
+    __ ldrq(v26, p);
+
+    __ ext(v16, __ T16B, v1, v1, 0x08); // long-swap subkeyH into v1
+    __ eor(v16, __ T16B, v16, v1);      // xor subkeyH into subkeyL (Karatsuba: (A1+A0))
+
+    {
+      Label L_ghash_loop;
+      __ bind(L_ghash_loop);
+
+      __ ldrq(v2, Address(__ post(data, 0x10))); // Load the data, bit
+                                                 // reversing each byte
+      __ rbit(v2, __ T16B, v2);
+      __ eor(v2, __ T16B, v0, v2);   // bit-swapped data ^ bit-swapped state
+
+      // Multiply state in v2 by subkey in v1
+      ghash_multiply(/*result_lo*/v5, /*result_hi*/v7,
+                     /*a*/v1, /*b*/v2, /*a1_xor_a0*/v16,
+                     /*temps*/v6, v20, v18, v21);
+      // Reduce v7:v5 by the field polynomial
+      ghash_reduce(v0, v5, v7, v26, vzr, v20);
+
+      __ sub(blocks, blocks, 1);
+      __ cbnz(blocks, L_ghash_loop);
+    }
+
+    // The bit-reversed result is at this point in v0
+    __ rev64(v1, __ T16B, v0);
+    __ rbit(v1, __ T16B, v1);
+
     __ st1(v1, __ T16B, state);
     __ ret(lr);
 
--- a/src/cpu/aarch64/vm/vm_version_aarch64.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/cpu/aarch64/vm/vm_version_aarch64.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -177,6 +177,12 @@
   if (UseCRC32 && (auxv & HWCAP_CRC32) == 0) {
     warning("UseCRC32 specified, but not supported on this CPU");
   }
+
+  if (UseAdler32Intrinsics) {
+    warning("Adler32Intrinsics not available on this CPU.");
+    FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
+  }
+
   if (auxv & HWCAP_AES) {
     UseAES = UseAES || FLAG_IS_DEFAULT(UseAES);
     UseAESIntrinsics =
--- a/src/cpu/ppc/vm/vm_version_ppc.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/cpu/ppc/vm/vm_version_ppc.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -200,6 +200,11 @@
     FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
   }
 
+  if (UseAdler32Intrinsics) {
+    warning("Adler32Intrinsics not available on this CPU.");
+    FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
+  }
+
   if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
     UseMultiplyToLenIntrinsic = true;
   }
--- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -5110,6 +5110,188 @@
     return start;
   }
 
+#define ADLER32_NUM_TEMPS 16
+
+  /**
+   *  Arguments:
+   *
+   * Inputs:
+   *   O0   - int   adler
+   *   O1   - byte* buff
+   *   O2   - int   len
+   *
+   * Output:
+   *   O0   - int adler result
+   */
+  address generate_updateBytesAdler32() {
+    __ align(CodeEntryAlignment);
+    StubCodeMark mark(this, "StubRoutines", "updateBytesAdler32");
+    address start = __ pc();
+
+    Label L_cleanup_loop, L_cleanup_loop_check;
+    Label L_main_loop_check, L_main_loop, L_inner_loop, L_inner_loop_check;
+    Label L_nmax_check_done;
+
+    // Aliases
+    Register s1     = O0;
+    Register s2     = O3;
+    Register buff   = O1;
+    Register len    = O2;
+    Register temp[ADLER32_NUM_TEMPS] = {L0, L1, L2, L3, L4, L5, L6, L7, I0, I1, I2, I3, I4, I5, G3, I7};
+
+    // Max number of bytes we can process before having to take the mod
+    // 0x15B0 is 5552 in decimal, the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+    unsigned long NMAX = 0x15B0;
+
+    // Zero-out the upper bits of len
+    __ clruwu(len);
+
+    // Create the mask 0xFFFF
+    __ set64(0x00FFFF, O4, O5); // O5 is the temp register
+
+    // s1 is initialized to the lower 16 bits of adler
+    // s2 is initialized to the upper 16 bits of adler
+    __ srlx(O0, 16, O5); // adler >> 16
+    __ and3(O0, O4, s1); // s1  = (adler & 0xFFFF)
+    __ and3(O5, O4, s2); // s2  = ((adler >> 16) & 0xFFFF)
+
+    // The pipelined loop needs at least 16 elements for 1 iteration
+    // It does check this, but it is more effective to skip to the cleanup loop
+    // Setup the constant for cutoff checking
+    __ mov(15, O4);
+
+    // Check if we are above the cutoff, if not go to the cleanup loop immediately
+    __ cmp_and_br_short(len, O4, Assembler::lessEqualUnsigned, Assembler::pt, L_cleanup_loop_check);
+
+    // Free up some registers for our use
+    for (int i = 0; i < ADLER32_NUM_TEMPS; i++) {
+      __ movxtod(temp[i], as_FloatRegister(2*i));
+    }
+
+    // Loop maintenance stuff is done at the end of the loop, so skip to there
+    __ ba_short(L_main_loop_check);
+
+    __ BIND(L_main_loop);
+
+    // Prologue for inner loop
+    __ ldub(buff, 0, L0);
+    __ dec(O5);
+
+    for (int i = 1; i < 8; i++) {
+      __ ldub(buff, i, temp[i]);
+    }
+
+    __ inc(buff, 8);
+
+    // Inner loop processes 16 elements at a time, might never execute if only 16 elements
+    // to be processed by the outter loop
+    __ ba_short(L_inner_loop_check);
+
+    __ BIND(L_inner_loop);
+
+    for (int i = 0; i < 8; i++) {
+      __ ldub(buff, (2*i), temp[(8+(2*i)) % ADLER32_NUM_TEMPS]);
+      __ add(s1, temp[i], s1);
+      __ ldub(buff, (2*i)+1, temp[(8+(2*i)+1) % ADLER32_NUM_TEMPS]);
+      __ add(s2, s1, s2);
+    }
+
+    // Original temp 0-7 used and new loads to temp 0-7 issued
+    // temp 8-15 ready to be consumed
+    __ add(s1, I0, s1);
+    __ dec(O5);
+    __ add(s2, s1, s2);
+    __ add(s1, I1, s1);
+    __ inc(buff, 16);
+    __ add(s2, s1, s2);
+
+    for (int i = 0; i < 6; i++) {
+      __ add(s1, temp[10+i], s1);
+      __ add(s2, s1, s2);
+    }
+
+    __ BIND(L_inner_loop_check);
+    __ nop();
+    __ cmp_and_br_short(O5, 0, Assembler::notEqual, Assembler::pt, L_inner_loop);
+
+    // Epilogue
+    for (int i = 0; i < 4; i++) {
+      __ ldub(buff, (2*i), temp[8+(2*i)]);
+      __ add(s1, temp[i], s1);
+      __ ldub(buff, (2*i)+1, temp[8+(2*i)+1]);
+      __ add(s2, s1, s2);
+    }
+
+    __ add(s1, temp[4], s1);
+    __ inc(buff, 8);
+
+    for (int i = 0; i < 11; i++) {
+      __ add(s2, s1, s2);
+      __ add(s1, temp[5+i], s1);
+    }
+
+    __ add(s2, s1, s2);
+
+    // Take the mod for s1 and s2
+    __ set64(0xFFF1, L0, L1);
+    __ udivx(s1, L0, L1);
+    __ udivx(s2, L0, L2);
+    __ mulx(L0, L1, L1);
+    __ mulx(L0, L2, L2);
+    __ sub(s1, L1, s1);
+    __ sub(s2, L2, s2);
+
+    // Make sure there is something left to process
+    __ BIND(L_main_loop_check);
+    __ set64(NMAX, L0, L1);
+    // k = len < NMAX ? len : NMAX
+    __ cmp_and_br_short(len, L0, Assembler::greaterEqualUnsigned, Assembler::pt, L_nmax_check_done);
+    __ andn(len, 0x0F, L0); // only loop a multiple of 16 times
+    __ BIND(L_nmax_check_done);
+    __ mov(L0, O5);
+    __ sub(len, L0, len); // len -= k
+
+    __ srlx(O5, 4, O5); // multiplies of 16
+    __ cmp_and_br_short(O5, 0, Assembler::notEqual, Assembler::pt, L_main_loop);
+
+    // Restore anything we used, take the mod one last time, combine and return
+    // Restore any registers we saved
+    for (int i = 0; i < ADLER32_NUM_TEMPS; i++) {
+      __ movdtox(as_FloatRegister(2*i), temp[i]);
+    }
+
+    // There might be nothing left to process
+    __ ba_short(L_cleanup_loop_check);
+
+    __ BIND(L_cleanup_loop);
+    __ ldub(buff, 0, O4); // load single byte form buffer
+    __ inc(buff); // buff++
+    __ add(s1, O4, s1); // s1 += *buff++;
+    __ dec(len); // len--
+    __ add(s1, s2, s2); // s2 += s1;
+    __ BIND(L_cleanup_loop_check);
+    __ nop();
+    __ cmp_and_br_short(len, 0, Assembler::notEqual, Assembler::pt, L_cleanup_loop);
+
+    // Take the mod one last time
+    __ set64(0xFFF1, O1, O2);
+    __ udivx(s1, O1, O2);
+    __ udivx(s2, O1, O5);
+    __ mulx(O1, O2, O2);
+    __ mulx(O1, O5, O5);
+    __ sub(s1, O2, s1);
+    __ sub(s2, O5, s2);
+
+    // Combine lower bits and higher bits
+    __ sllx(s2, 16, s2); // s2 = s2 << 16
+    __ or3(s1, s2, s1);  // adler = s2 | s1
+    // Final return value is in O0
+    __ retl();
+    __ delayed()->nop();
+
+    return start;
+  }
+
   void generate_initial() {
     // Generates all stubs and initializes the entry points
 
@@ -5206,6 +5388,11 @@
     if (UseCRC32CIntrinsics) {
       StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C();
     }
+
+    // generate Adler32 intrinsics code
+    if (UseAdler32Intrinsics) {
+      StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32();
+    }
   }
 
 
--- a/src/cpu/sparc/vm/stubRoutines_sparc.hpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/cpu/sparc/vm/stubRoutines_sparc.hpp	Tue Sep 08 16:10:37 2015 +0200
@@ -41,7 +41,7 @@
 enum /* platform_dependent_constants */ {
   // %%%%%%%% May be able to shrink this a lot
   code_size1 = 20000,           // simply increase if too small (assembler will crash if too small)
-  code_size2 = 24000            // simply increase if too small (assembler will crash if too small)
+  code_size2 = 27000            // simply increase if too small (assembler will crash if too small)
 };
 
 class Sparc {
--- a/src/cpu/sparc/vm/vm_version_sparc.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/cpu/sparc/vm/vm_version_sparc.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -356,6 +356,15 @@
     FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
   }
 
+  if (UseVIS > 2) {
+    if (FLAG_IS_DEFAULT(UseAdler32Intrinsics)) {
+      FLAG_SET_DEFAULT(UseAdler32Intrinsics, true);
+    }
+  } else if (UseAdler32Intrinsics) {
+    warning("SPARC Adler32 intrinsics require VIS3 instruction support. Intrinsics will be disabled.");
+    FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
+  }
+
   if (FLAG_IS_DEFAULT(ContendedPaddingWidth) &&
     (cache_line_size > ContendedPaddingWidth))
     ContendedPaddingWidth = cache_line_size;
--- a/src/cpu/x86/vm/vm_version_x86.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/cpu/x86/vm/vm_version_x86.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -714,6 +714,11 @@
     FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
   }
 
+  if (UseAdler32Intrinsics) {
+    warning("Adler32Intrinsics not available on this CPU.");
+    FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
+  }
+
   // Adjust RTM (Restricted Transactional Memory) flags
   if (!supports_rtm() && UseRTMLocking) {
     // Can't continue because UseRTMLocking affects UseBiasedLocking flag
--- a/src/share/vm/adlc/Doc/Syntax.doc	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/adlc/Doc/Syntax.doc	Tue Sep 08 16:10:37 2015 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2015, 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
@@ -33,7 +33,7 @@
 the architecture of a processor, and is the input to the ADL Compiler.  The
 ADL Compiler compiles an ADL file into code which is incorporated into the
 Optimizing Just In Time Compiler (OJIT) to generate efficient and correct code
-for the target architecture.  The ADL describes three bassic different types
+for the target architecture.  The ADL describes three basic different types
 of architectural features.  It describes the instruction set (and associated
 operands) of the target architecture.  It describes the register set of the
 target architecture along with relevant information for the register allocator.
--- a/src/share/vm/c1/c1_Compiler.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/c1/c1_Compiler.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -32,7 +32,6 @@
 #include "c1/c1_Runtime1.hpp"
 #include "c1/c1_ValueType.hpp"
 #include "compiler/compileBroker.hpp"
-#include "compiler/compilerOracle.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -4212,7 +4212,7 @@
   if (!PrintInlining && !compilation()->method()->has_option("PrintInlining")) {
     return;
   }
-  CompileTask::print_inlining(callee, scope()->level(), bci(), msg);
+  CompileTask::print_inlining_tty(callee, scope()->level(), bci(), msg);
   if (success && CIPrintMethodCodes) {
     callee->print_codes();
   }
--- a/src/share/vm/ci/bcEscapeAnalyzer.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -1447,7 +1447,6 @@
 
     if (methodData() == NULL)
       return;
-    bool printit = _method->should_print_assembly();
     if (methodData()->has_escape_info()) {
       TRACE_BCEA(2, tty->print_cr("[EA] Reading previous results for %s.%s",
                                   method->holder()->name()->as_utf8(),
--- a/src/share/vm/classfile/javaClasses.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/classfile/javaClasses.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -29,7 +29,6 @@
 #include "classfile/vmSymbols.hpp"
 #include "code/debugInfo.hpp"
 #include "code/pcDesc.hpp"
-#include "compiler/compilerOracle.hpp"
 #include "interpreter/interpreter.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
--- a/src/share/vm/classfile/vmSymbols.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/classfile/vmSymbols.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -625,6 +625,10 @@
   case vmIntrinsics::_updateDirectByteBufferCRC32C:
     if (!UseCRC32CIntrinsics) return true;
     break;
+  case vmIntrinsics::_updateBytesAdler32:
+  case vmIntrinsics::_updateByteBufferAdler32:
+    if (!UseAdler32Intrinsics) return true;
+    break;
   case vmIntrinsics::_copyMemory:
     if (!InlineArrayCopy || !InlineUnsafeOps) return true;
     break;
--- a/src/share/vm/classfile/vmSymbols.hpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Tue Sep 08 16:10:37 2015 +0200
@@ -927,6 +927,12 @@
   do_intrinsic(_updateDirectByteBufferCRC32C, java_util_zip_CRC32C, updateDirectByteBuffer_C_name, updateByteBuffer_signature, F_S) \
    do_name(    updateDirectByteBuffer_C_name,                     "updateDirectByteBuffer")                             \
                                                                                                                         \
+   /* support for java.util.zip.Adler32 */                                                                              \
+  do_class(java_util_zip_Adler32,        "java/util/zip/Adler32")                                                       \
+  do_intrinsic(_updateBytesAdler32,       java_util_zip_Adler32,  updateBytes_C_name,  updateBytes_signature,  F_SN)    \
+  do_intrinsic(_updateByteBufferAdler32,  java_util_zip_Adler32,  updateByteBuffer_A_name,  updateByteBuffer_signature,  F_SN) \
+   do_name(     updateByteBuffer_A_name,                          "updateByteBuffer")                                   \
+                                                                                                                        \
   /* support for sun.misc.Unsafe */                                                                                     \
   do_class(sun_misc_Unsafe,               "sun/misc/Unsafe")                                                            \
                                                                                                                         \
--- a/src/share/vm/code/codeCache.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/code/codeCache.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -745,13 +745,12 @@
 
 void CodeCache::gc_epilogue() {
   assert_locked_or_safepoint(CodeCache_lock);
-  NMethodIterator iter;
-  while(iter.next()) {
-    nmethod* nm = iter.method();
-    if (!nm->is_zombie()) {
-      if (needs_cache_clean()) {
-        // Clean ICs of unloaded nmethods as well because they may reference other
-        // unloaded nmethods that may be flushed earlier in the sweeper cycle.
+  NOT_DEBUG(if (needs_cache_clean())) {
+    NMethodIterator iter;
+    while(iter.next_alive()) {
+      nmethod* nm = iter.method();
+      assert(!nm->is_unloaded(), "Tautology");
+      DEBUG_ONLY(if (needs_cache_clean())) {
         nm->cleanup_inline_caches();
       }
       DEBUG_ONLY(nm->verify());
--- a/src/share/vm/code/compiledIC.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/code/compiledIC.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -287,6 +287,7 @@
   assert( is_c1_method ||
          !is_monomorphic ||
          is_optimized() ||
+         !caller->is_alive() ||
          (cached_metadata() != NULL && cached_metadata()->is_klass()), "sanity check");
 #endif // ASSERT
   return is_monomorphic;
@@ -321,7 +322,7 @@
 }
 
 
-void CompiledIC::set_to_clean() {
+void CompiledIC::set_to_clean(bool in_use) {
   assert(SafepointSynchronize::is_at_safepoint() || CompiledIC_lock->is_locked() , "MT-unsafe call");
   if (TraceInlineCacheClearing || TraceICs) {
     tty->print_cr("IC@" INTPTR_FORMAT ": set to clean", p2i(instruction_address()));
@@ -337,7 +338,7 @@
 
   // A zombie transition will always be safe, since the metadata has already been set to NULL, so
   // we only need to patch the destination
-  bool safe_transition = is_optimized() || SafepointSynchronize::is_at_safepoint();
+  bool safe_transition = !in_use || is_optimized() || SafepointSynchronize::is_at_safepoint();
 
   if (safe_transition) {
     // Kill any leftover stub we might have too
--- a/src/share/vm/code/compiledIC.hpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/code/compiledIC.hpp	Tue Sep 08 16:10:37 2015 +0200
@@ -214,7 +214,7 @@
   //
   // They all takes a TRAP argument, since they can cause a GC if the inline-cache buffer is full.
   //
-  void set_to_clean();
+  void set_to_clean(bool in_use = true);
   void set_to_monomorphic(CompiledICInfo& info);
   void clear_ic_stub();
 
--- a/src/share/vm/code/nmethod.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/code/nmethod.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -848,10 +848,10 @@
   if (st != NULL) {
     ttyLocker ttyl;
     if (WizardMode) {
-      CompileTask::print_compilation(st, this, msg, /*short_form:*/ true);
+      CompileTask::print(st, this, msg, /*short_form:*/ true);
       st->print_cr(" (" INTPTR_FORMAT ")", this);
     } else {
-      CompileTask::print_compilation(st, this, msg, /*short_form:*/ false);
+      CompileTask::print(st, this, msg, /*short_form:*/ false);
     }
   }
 }
@@ -1050,7 +1050,7 @@
         if( cb != NULL && cb->is_nmethod() ) {
           nmethod* nm = (nmethod*)cb;
           // Clean inline caches pointing to zombie, non-entrant and unloaded methods
-          if (!nm->is_in_use() || (nm->method()->code() != nm)) ic->set_to_clean();
+          if (!nm->is_in_use() || (nm->method()->code() != nm)) ic->set_to_clean(is_alive());
         }
         break;
       }
@@ -1150,7 +1150,7 @@
 // Tell if a non-entrant method can be converted to a zombie (i.e.,
 // there are no activations on the stack, not in use by the VM,
 // and not in use by the ServiceThread)
-bool nmethod::can_not_entrant_be_converted() {
+bool nmethod::can_convert_to_zombie() {
   assert(is_not_entrant(), "must be a non-entrant method");
 
   // Since the nmethod sweeper only does partial sweep the sweeper's traversal
--- a/src/share/vm/code/nmethod.hpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/code/nmethod.hpp	Tue Sep 08 16:10:37 2015 +0200
@@ -577,7 +577,7 @@
 
   // See comment at definition of _last_seen_on_stack
   void mark_as_seen_on_stack();
-  bool can_not_entrant_be_converted();
+  bool can_convert_to_zombie();
 
   // Evolution support. We make old (discarded) compiled methods point to new Method*s.
   void set_method(Method* method) { _method = method; }
--- a/src/share/vm/compiler/compileBroker.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/compiler/compileBroker.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -157,7 +157,6 @@
 CompileQueue* CompileBroker::_c2_compile_queue   = NULL;
 CompileQueue* CompileBroker::_c1_compile_queue   = NULL;
 
-
 class CompilationLog : public StringEventLog {
  public:
   CompilationLog() : StringEventLog("Compilation events") {
@@ -167,7 +166,7 @@
     StringLogMessage lm;
     stringStream sstr = lm.stream();
     // msg.time_stamp().update_to(tty->time_stamp().ticks());
-    task->print_compilation(&sstr, NULL, true, false);
+    task->print(&sstr, NULL, true, false);
     log(thread, "%s", (const char*)lm);
   }
 
@@ -233,371 +232,6 @@
   }
 }
 
-
-CompileTask*  CompileTask::_task_free_list = NULL;
-#ifdef ASSERT
-int CompileTask::_num_allocated_tasks = 0;
-#endif
-/**
- * Allocate a CompileTask, from the free list if possible.
- */
-CompileTask* CompileTask::allocate() {
-  MutexLocker locker(CompileTaskAlloc_lock);
-  CompileTask* task = NULL;
-
-  if (_task_free_list != NULL) {
-    task = _task_free_list;
-    _task_free_list = task->next();
-    task->set_next(NULL);
-  } else {
-    task = new CompileTask();
-    DEBUG_ONLY(_num_allocated_tasks++;)
-    assert (WhiteBoxAPI || _num_allocated_tasks < 10000, "Leaking compilation tasks?");
-    task->set_next(NULL);
-    task->set_is_free(true);
-  }
-  assert(task->is_free(), "Task must be free.");
-  task->set_is_free(false);
-  return task;
-}
-
-
-/**
- * Add a task to the free list.
- */
-void CompileTask::free(CompileTask* task) {
-  MutexLocker locker(CompileTaskAlloc_lock);
-  if (!task->is_free()) {
-    task->set_code(NULL);
-    assert(!task->lock()->is_locked(), "Should not be locked when freed");
-    JNIHandles::destroy_global(task->_method_holder);
-    JNIHandles::destroy_global(task->_hot_method_holder);
-
-    task->set_is_free(true);
-    task->set_next(_task_free_list);
-    _task_free_list = task;
-  }
-}
-
-void CompileTask::initialize(int compile_id,
-                             methodHandle method,
-                             int osr_bci,
-                             int comp_level,
-                             methodHandle hot_method,
-                             int hot_count,
-                             const char* comment,
-                             bool is_blocking) {
-  assert(!_lock->is_locked(), "bad locking");
-
-  _compile_id = compile_id;
-  _method = method();
-  _method_holder = JNIHandles::make_global(method->method_holder()->klass_holder());
-  _osr_bci = osr_bci;
-  _is_blocking = is_blocking;
-  _comp_level = comp_level;
-  _num_inlined_bytecodes = 0;
-
-  _is_complete = false;
-  _is_success = false;
-  _code_handle = NULL;
-
-  _hot_method = NULL;
-  _hot_method_holder = NULL;
-  _hot_count = hot_count;
-  _time_queued = 0;  // tidy
-  _comment = comment;
-  _failure_reason = NULL;
-
-  if (LogCompilation) {
-    _time_queued = os::elapsed_counter();
-    if (hot_method.not_null()) {
-      if (hot_method == method) {
-        _hot_method = _method;
-      } else {
-        _hot_method = hot_method();
-        // only add loader or mirror if different from _method_holder
-        _hot_method_holder = JNIHandles::make_global(hot_method->method_holder()->klass_holder());
-      }
-    }
-  }
-
-  _next = NULL;
-}
-
-// ------------------------------------------------------------------
-// CompileTask::code/set_code
-nmethod* CompileTask::code() const {
-  if (_code_handle == NULL)  return NULL;
-  return _code_handle->code();
-}
-void CompileTask::set_code(nmethod* nm) {
-  if (_code_handle == NULL && nm == NULL)  return;
-  guarantee(_code_handle != NULL, "");
-  _code_handle->set_code(nm);
-  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);
-  if (_hot_method != NULL) {
-    _hot_method->set_on_stack(true);
-  }
-}
-
-// RedefineClasses support
-void CompileTask::metadata_do(void f(Metadata*)) {
-  f(method());
-  if (hot_method() != NULL && hot_method() != method()) {
-    f(hot_method());
-  }
-}
-
-// ------------------------------------------------------------------
-// CompileTask::print_line_on_error
-//
-// This function is called by fatal error handler when the thread
-// causing troubles is a compiler thread.
-//
-// Do not grab any lock, do not allocate memory.
-//
-// Otherwise it's the same as CompileTask::print_line()
-//
-void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) {
-  // print compiler name
-  st->print("%s:", CompileBroker::compiler_name(comp_level()));
-  print_compilation(st);
-}
-
-// ------------------------------------------------------------------
-// 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(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, bool cr) {
-  if (!short_form) {
-    st->print("%7d ", (int) st->time_stamp().milliseconds());  // print timestamp
-  }
-  st->print("%4d ", compile_id);    // print compilation number
-
-  // For unloaded methods the transition to zombie occurs after the
-  // method is cleared so it's impossible to report accurate
-  // information for that case.
-  bool is_synchronized = false;
-  bool has_exception_handler = false;
-  bool is_native = false;
-  if (method != NULL) {
-    is_synchronized       = method->is_synchronized();
-    has_exception_handler = method->has_exception_handler();
-    is_native             = method->is_native();
-  }
-  // method attributes
-  const char compile_type   = is_osr_method                   ? '%' : ' ';
-  const char sync_char      = is_synchronized                 ? 's' : ' ';
-  const char exception_char = has_exception_handler           ? '!' : ' ';
-  const char blocking_char  = is_blocking                     ? 'b' : ' ';
-  const char native_char    = is_native                       ? 'n' : ' ';
-
-  // print method attributes
-  st->print("%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, native_char);
-
-  if (TieredCompilation) {
-    if (comp_level != -1)  st->print("%d ", comp_level);
-    else                   st->print("- ");
-  }
-  st->print("     ");  // more indent
-
-  if (method == NULL) {
-    st->print("(method)");
-  } else {
-    method->print_short_name(st);
-    if (is_osr_method) {
-      st->print(" @ %d", osr_bci);
-    }
-    if (method->is_native())
-      st->print(" (native)");
-    else
-      st->print(" (%d bytes)", method->code_size());
-  }
-
-  if (msg != NULL) {
-    st->print("   %s", msg);
-  }
-  if (cr) {
-    st->cr();
-  }
-}
-
-// ------------------------------------------------------------------
-// CompileTask::print_inlining
-void CompileTask::print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) {
-  //         1234567
-  st->print("        ");     // print timestamp
-  //         1234
-  st->print("     ");        // print compilation number
-
-  // method attributes
-  if (method->is_loaded()) {
-    const char sync_char      = method->is_synchronized()        ? 's' : ' ';
-    const char exception_char = method->has_exception_handlers() ? '!' : ' ';
-    const char monitors_char  = method->has_monitor_bytecodes()  ? 'm' : ' ';
-
-    // print method attributes
-    st->print(" %c%c%c  ", sync_char, exception_char, monitors_char);
-  } else {
-    //         %s!bn
-    st->print("      ");     // print method attributes
-  }
-
-  if (TieredCompilation) {
-    st->print("  ");
-  }
-  st->print("     ");        // more indent
-  st->print("    ");         // initial inlining indent
-
-  for (int i = 0; i < inline_level; i++)  st->print("  ");
-
-  st->print("@ %d  ", bci);  // print bci
-  method->print_short_name(st);
-  if (method->is_loaded())
-    st->print(" (%d bytes)", method->code_size());
-  else
-    st->print(" (not loaded)");
-
-  if (msg != NULL) {
-    st->print("   %s", msg);
-  }
-  st->cr();
-}
-
-// ------------------------------------------------------------------
-// CompileTask::print_inline_indent
-void CompileTask::print_inline_indent(int inline_level, outputStream* st) {
-  //         1234567
-  st->print("        ");     // print timestamp
-  //         1234
-  st->print("     ");        // print compilation number
-  //         %s!bn
-  st->print("      ");       // print method attributes
-  if (TieredCompilation) {
-    st->print("  ");
-  }
-  st->print("     ");        // more indent
-  st->print("    ");         // initial inlining indent
-  for (int i = 0; i < inline_level; i++)  st->print("  ");
-}
-
-// ------------------------------------------------------------------
-// CompileTask::print_compilation
-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, cr);
-}
-
-// ------------------------------------------------------------------
-// CompileTask::log_task
-void CompileTask::log_task(xmlStream* log) {
-  Thread* thread = Thread::current();
-  methodHandle method(thread, this->method());
-  ResourceMark rm(thread);
-
-  // <task compiler='Cx' id='9' method='M' osr_bci='X' level='1' blocking='1' stamp='1.234'>
-  log->print(" compiler='%s' compile_id='%d'", _comp_level <= CompLevel_full_profile ? "C1" : "C2", _compile_id);
-  if (_osr_bci != CompileBroker::standard_entry_bci) {
-    log->print(" compile_kind='osr'");  // same as nmethod::compile_kind
-  } // else compile_kind='c2c'
-  if (!method.is_null())  log->method(method);
-  if (_osr_bci != CompileBroker::standard_entry_bci) {
-    log->print(" osr_bci='%d'", _osr_bci);
-  }
-  if (_comp_level != CompLevel_highest_tier) {
-    log->print(" level='%d'", _comp_level);
-  }
-  if (_is_blocking) {
-    log->print(" blocking='1'");
-  }
-  log->stamp();
-}
-
-
-// ------------------------------------------------------------------
-// CompileTask::log_task_queued
-void CompileTask::log_task_queued() {
-  Thread* thread = Thread::current();
-  ttyLocker ttyl;
-  ResourceMark rm(thread);
-
-  xtty->begin_elem("task_queued");
-  log_task(xtty);
-  if (_comment != NULL) {
-    xtty->print(" comment='%s'", _comment);
-  }
-  if (_hot_method != NULL) {
-    methodHandle hot(thread, _hot_method);
-    methodHandle method(thread, _method);
-    if (hot() != method()) {
-      xtty->method(hot);
-    }
-  }
-  if (_hot_count != 0) {
-    xtty->print(" hot_count='%d'", _hot_count);
-  }
-  xtty->end_elem();
-}
-
-
-// ------------------------------------------------------------------
-// CompileTask::log_task_start
-void CompileTask::log_task_start(CompileLog* log)   {
-  log->begin_head("task");
-  log_task(log);
-  log->end_head();
-}
-
-
-// ------------------------------------------------------------------
-// CompileTask::log_task_done
-void CompileTask::log_task_done(CompileLog* log) {
-  Thread* thread = Thread::current();
-  methodHandle method(thread, this->method());
-  ResourceMark rm(thread);
-
-  if (!_is_success) {
-    const char* reason = _failure_reason != NULL ? _failure_reason : "unknown";
-    log->elem("failure reason='%s'", reason);
-  }
-
-  // <task_done ... stamp='1.234'>  </task>
-  nmethod* nm = code();
-  log->begin_elem("task_done success='%d' nmsize='%d' count='%d'",
-                  _is_success, nm == NULL ? 0 : nm->content_size(),
-                  method->invocation_count());
-  int bec = method->backedge_count();
-  if (bec != 0)  log->print(" backedge_count='%d'", bec);
-  // Note:  "_is_complete" is about to be set, but is not.
-  if (_num_inlined_bytecodes != 0) {
-    log->print(" inlined_bytes='%d'", _num_inlined_bytecodes);
-  }
-  log->stamp();
-  log->end_elem();
-  log->tail("task");
-  log->clear_identities();   // next task will have different CI
-  if (log->unflushed_count() > 2000) {
-    log->flush();
-  }
-  log->mark_file_end();
-}
-
-
-
 /**
  * Add a CompileTask to a CompileQueue.
  */
@@ -807,7 +441,7 @@
     st->print_cr("Empty");
   } else {
     while (task != NULL) {
-      task->print_compilation(st, NULL, true, true);
+      task->print(st, NULL, true, true);
       task = task->next();
     }
   }
@@ -1349,7 +983,7 @@
 #ifndef TIERED
     // seems like an assert of dubious value
     assert(comp_level == CompLevel_highest_tier,
-           "all OSR compiles are assumed to be at a single compilation lavel");
+           "all OSR compiles are assumed to be at a single compilation level");
 #endif // TIERED
     // We accept a higher level osr method
     nmethod* nm = method->lookup_osr_nmethod_for(osr_bci, comp_level, false);
@@ -2037,7 +1671,7 @@
         FormatBufferResource msg = retry_message != NULL ?
             err_msg_res("COMPILE SKIPPED: %s (%s)", ci_env.failure_reason(), retry_message) :
             err_msg_res("COMPILE SKIPPED: %s",      ci_env.failure_reason());
-        task->print_compilation(tty, msg);
+        task->print(tty, msg);
       }
     } else {
       task->mark_success();
--- a/src/share/vm/compiler/compileBroker.hpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/compiler/compileBroker.hpp	Tue Sep 08 16:10:37 2015 +0200
@@ -27,127 +27,12 @@
 
 #include "ci/compilerInterface.hpp"
 #include "compiler/abstractCompiler.hpp"
+#include "compiler/compileTask.hpp"
 #include "runtime/perfData.hpp"
 
 class nmethod;
 class nmethodLocker;
 
-// CompileTask
-//
-// An entry in the compile queue.  It represents a pending or current
-// compilation.
-class CompileTask : public CHeapObj<mtCompiler> {
-  friend class VMStructs;
-
- private:
-  static CompileTask* _task_free_list;
-#ifdef ASSERT
-  static int          _num_allocated_tasks;
-#endif
-
-  Monitor*     _lock;
-  uint         _compile_id;
-  Method*      _method;
-  jobject      _method_holder;
-  int          _osr_bci;
-  bool         _is_complete;
-  bool         _is_success;
-  bool         _is_blocking;
-  int          _comp_level;
-  int          _num_inlined_bytecodes;
-  nmethodLocker* _code_handle;  // holder of eventual result
-  CompileTask* _next, *_prev;
-  bool         _is_free;
-  // Fields used for logging why the compilation was initiated:
-  jlong        _time_queued;  // in units of os::elapsed_counter()
-  Method*      _hot_method;   // which method actually triggered this task
-  jobject      _hot_method_holder;
-  int          _hot_count;    // information about its invocation counter
-  const char*  _comment;      // more info about the task
-  const char*  _failure_reason;
-
- public:
-  CompileTask() {
-    _lock = new Monitor(Mutex::nonleaf+2, "CompileTaskLock");
-  }
-
-  void initialize(int compile_id, methodHandle method, int osr_bci, int comp_level,
-                  methodHandle hot_method, int hot_count, const char* comment,
-                  bool is_blocking);
-
-  static CompileTask* allocate();
-  static void         free(CompileTask* task);
-
-  int          compile_id() const                { return _compile_id; }
-  Method*      method() const                    { return _method; }
-  Method*      hot_method() const                { return _hot_method; }
-  int          osr_bci() const                   { return _osr_bci; }
-  bool         is_complete() const               { return _is_complete; }
-  bool         is_blocking() const               { return _is_blocking; }
-  bool         is_success() const                { return _is_success; }
-
-  nmethodLocker* code_handle() const             { return _code_handle; }
-  void         set_code_handle(nmethodLocker* l) { _code_handle = l; }
-  nmethod*     code() const;                     // _code_handle->code()
-  void         set_code(nmethod* nm);            // _code_handle->set_code(nm)
-
-  Monitor*     lock() const                      { return _lock; }
-
-  void         mark_complete()                   { _is_complete = true; }
-  void         mark_success()                    { _is_success = true; }
-
-  int          comp_level()                      { return _comp_level;}
-  void         set_comp_level(int comp_level)    { _comp_level = comp_level;}
-
-  int          num_inlined_bytecodes() const     { return _num_inlined_bytecodes; }
-  void         set_num_inlined_bytecodes(int n)  { _num_inlined_bytecodes = n; }
-
-  CompileTask* next() const                      { return _next; }
-  void         set_next(CompileTask* next)       { _next = next; }
-  CompileTask* prev() const                      { return _prev; }
-  void         set_prev(CompileTask* prev)       { _prev = prev; }
-  bool         is_free() const                   { return _is_free; }
-  void         set_is_free(bool val)             { _is_free = val; }
-
-  // RedefineClasses support
-  void         metadata_do(void f(Metadata*));
-
-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, bool cr = true);
-
-public:
-  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, cr);
-  }
-
-  static void  print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg = NULL);
-  static void  print_inlining(ciMethod* method, int inline_level, int bci, const char* msg = NULL) {
-    print_inlining(tty, method, inline_level, bci, msg);
-  }
-
-  // Redefine Classes support
-  void mark_on_stack();
-
-  static void  print_inline_indent(int inline_level, outputStream* st = tty);
-
-  void         print_tty();
-  void         print_line_on_error(outputStream* st, char* buf, int buflen);
-
-  void         log_task(xmlStream* log);
-  void         log_task_queued();
-  void         log_task_start(CompileLog* log);
-  void         log_task_done(CompileLog* log);
-
-  void         set_failure_reason(const char* reason) {
-    _failure_reason = reason;
-  }
-};
-
 // CompilerCounters
 //
 // Per Compiler Performance Counters.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/compiler/compileTask.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -0,0 +1,391 @@
+/*
+ * 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
+ * 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "compiler/compileTask.hpp"
+#include "compiler/compileLog.hpp"
+#include "compiler/compileBroker.hpp"
+
+CompileTask*  CompileTask::_task_free_list = NULL;
+#ifdef ASSERT
+int CompileTask::_num_allocated_tasks = 0;
+#endif
+
+/**
+ * Allocate a CompileTask, from the free list if possible.
+ */
+CompileTask* CompileTask::allocate() {
+  MutexLocker locker(CompileTaskAlloc_lock);
+  CompileTask* task = NULL;
+
+  if (_task_free_list != NULL) {
+    task = _task_free_list;
+    _task_free_list = task->next();
+    task->set_next(NULL);
+  } else {
+    task = new CompileTask();
+    DEBUG_ONLY(_num_allocated_tasks++;)
+    assert (WhiteBoxAPI || _num_allocated_tasks < 10000, "Leaking compilation tasks?");
+    task->set_next(NULL);
+    task->set_is_free(true);
+  }
+  assert(task->is_free(), "Task must be free.");
+  task->set_is_free(false);
+  return task;
+}
+
+/**
+* Add a task to the free list.
+*/
+
+void CompileTask::free(CompileTask* task) {
+ MutexLocker locker(CompileTaskAlloc_lock);
+ if (!task->is_free()) {
+   task->set_code(NULL);
+   assert(!task->lock()->is_locked(), "Should not be locked when freed");
+   JNIHandles::destroy_global(task->_method_holder);
+   JNIHandles::destroy_global(task->_hot_method_holder);
+
+   task->set_is_free(true);
+   task->set_next(_task_free_list);
+   _task_free_list = task;
+ }
+}
+
+
+void CompileTask::initialize(int compile_id,
+                             methodHandle method,
+                             int osr_bci,
+                             int comp_level,
+                             methodHandle hot_method,
+                             int hot_count,
+                             const char* comment,
+                             bool is_blocking) {
+  assert(!_lock->is_locked(), "bad locking");
+
+  _compile_id = compile_id;
+  _method = method();
+  _method_holder = JNIHandles::make_global(method->method_holder()->klass_holder());
+  _osr_bci = osr_bci;
+  _is_blocking = is_blocking;
+  _comp_level = comp_level;
+  _num_inlined_bytecodes = 0;
+
+  _is_complete = false;
+  _is_success = false;
+  _code_handle = NULL;
+
+  _hot_method = NULL;
+  _hot_method_holder = NULL;
+  _hot_count = hot_count;
+  _time_queued = 0;  // tidy
+  _comment = comment;
+  _failure_reason = NULL;
+
+  if (LogCompilation) {
+    _time_queued = os::elapsed_counter();
+    if (hot_method.not_null()) {
+      if (hot_method == method) {
+        _hot_method = _method;
+      } else {
+        _hot_method = hot_method();
+        // only add loader or mirror if different from _method_holder
+        _hot_method_holder = JNIHandles::make_global(hot_method->method_holder()->klass_holder());
+      }
+    }
+  }
+
+  _next = NULL;
+}
+
+// ------------------------------------------------------------------
+// CompileTask::code/set_code
+//
+nmethod* CompileTask::code() const {
+  if (_code_handle == NULL)  return NULL;
+  return _code_handle->code();
+}
+
+void CompileTask::set_code(nmethod* nm) {
+  if (_code_handle == NULL && nm == NULL)  return;
+  guarantee(_code_handle != NULL, "");
+  _code_handle->set_code(nm);
+  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);
+  if (_hot_method != NULL) {
+    _hot_method->set_on_stack(true);
+  }
+}
+
+// RedefineClasses support
+void CompileTask::metadata_do(void f(Metadata*)) {
+  f(method());
+  if (hot_method() != NULL && hot_method() != method()) {
+    f(hot_method());
+  }
+}
+
+// ------------------------------------------------------------------
+// CompileTask::print_line_on_error
+//
+// This function is called by fatal error handler when the thread
+// causing troubles is a compiler thread.
+//
+// Do not grab any lock, do not allocate memory.
+//
+// Otherwise it's the same as CompileTask::print_line()
+//
+void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) {
+  // print compiler name
+  st->print("%s:", CompileBroker::compiler_name(comp_level()));
+  print(st);
+}
+
+// ------------------------------------------------------------------
+// CompileTask::print_tty
+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(tty);
+}
+
+// ------------------------------------------------------------------
+// CompileTask::print_impl
+void CompileTask::print_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, bool cr) {
+  if (!short_form) {
+    st->print("%7d ", (int) st->time_stamp().milliseconds());  // print timestamp
+  }
+  st->print("%4d ", compile_id);    // print compilation number
+
+  // For unloaded methods the transition to zombie occurs after the
+  // method is cleared so it's impossible to report accurate
+  // information for that case.
+  bool is_synchronized = false;
+  bool has_exception_handler = false;
+  bool is_native = false;
+  if (method != NULL) {
+    is_synchronized       = method->is_synchronized();
+    has_exception_handler = method->has_exception_handler();
+    is_native             = method->is_native();
+  }
+  // method attributes
+  const char compile_type   = is_osr_method                   ? '%' : ' ';
+  const char sync_char      = is_synchronized                 ? 's' : ' ';
+  const char exception_char = has_exception_handler           ? '!' : ' ';
+  const char blocking_char  = is_blocking                     ? 'b' : ' ';
+  const char native_char    = is_native                       ? 'n' : ' ';
+
+  // print method attributes
+  st->print("%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, native_char);
+
+  if (TieredCompilation) {
+    if (comp_level != -1)  st->print("%d ", comp_level);
+    else                   st->print("- ");
+  }
+  st->print("     ");  // more indent
+
+  if (method == NULL) {
+    st->print("(method)");
+  } else {
+    method->print_short_name(st);
+    if (is_osr_method) {
+      st->print(" @ %d", osr_bci);
+    }
+    if (method->is_native())
+      st->print(" (native)");
+    else
+      st->print(" (%d bytes)", method->code_size());
+  }
+
+  if (msg != NULL) {
+    st->print("   %s", msg);
+  }
+  if (cr) {
+    st->cr();
+  }
+}
+
+void CompileTask::print_inline_indent(int inline_level, outputStream* st) {
+  //         1234567
+  st->print("        ");     // print timestamp
+  //         1234
+  st->print("     ");        // print compilation number
+  //         %s!bn
+  st->print("      ");       // print method attributes
+  if (TieredCompilation) {
+    st->print("  ");
+  }
+  st->print("     ");        // more indent
+  st->print("    ");         // initial inlining indent
+  for (int i = 0; i < inline_level; i++)  st->print("  ");
+}
+
+// ------------------------------------------------------------------
+// CompileTask::print_compilation
+void CompileTask::print(outputStream* st, const char* msg, bool short_form, bool cr) {
+  bool is_osr_method = osr_bci() != InvocationEntryBci;
+  print_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form, cr);
+}
+
+// ------------------------------------------------------------------
+// CompileTask::log_task
+void CompileTask::log_task(xmlStream* log) {
+  Thread* thread = Thread::current();
+  methodHandle method(thread, this->method());
+  ResourceMark rm(thread);
+
+  // <task id='9' method='M' osr_bci='X' level='1' blocking='1' stamp='1.234'>
+  log->print(" compile_id='%d'", _compile_id);
+  if (_osr_bci != CompileBroker::standard_entry_bci) {
+    log->print(" compile_kind='osr'");  // same as nmethod::compile_kind
+  } // else compile_kind='c2c'
+  if (!method.is_null())  log->method(method);
+  if (_osr_bci != CompileBroker::standard_entry_bci) {
+    log->print(" osr_bci='%d'", _osr_bci);
+  }
+  if (_comp_level != CompLevel_highest_tier) {
+    log->print(" level='%d'", _comp_level);
+  }
+  if (_is_blocking) {
+    log->print(" blocking='1'");
+  }
+  log->stamp();
+}
+
+// ------------------------------------------------------------------
+// CompileTask::log_task_queued
+void CompileTask::log_task_queued() {
+  Thread* thread = Thread::current();
+  ttyLocker ttyl;
+  ResourceMark rm(thread);
+
+  xtty->begin_elem("task_queued");
+  log_task(xtty);
+  if (_comment != NULL) {
+    xtty->print(" comment='%s'", _comment);
+  }
+  if (_hot_method != NULL) {
+    methodHandle hot(thread, _hot_method);
+    methodHandle method(thread, _method);
+    if (hot() != method()) {
+      xtty->method(hot);
+    }
+  }
+  if (_hot_count != 0) {
+    xtty->print(" hot_count='%d'", _hot_count);
+  }
+  xtty->end_elem();
+}
+
+
+// ------------------------------------------------------------------
+// CompileTask::log_task_start
+void CompileTask::log_task_start(CompileLog* log)   {
+  log->begin_head("task");
+  log_task(log);
+  log->end_head();
+}
+
+
+// ------------------------------------------------------------------
+// CompileTask::log_task_done
+void CompileTask::log_task_done(CompileLog* log) {
+  Thread* thread = Thread::current();
+  methodHandle method(thread, this->method());
+  ResourceMark rm(thread);
+
+  if (!_is_success) {
+    const char* reason = _failure_reason != NULL ? _failure_reason : "unknown";
+    log->elem("failure reason='%s'", reason);
+  }
+
+  // <task_done ... stamp='1.234'>  </task>
+  nmethod* nm = code();
+  log->begin_elem("task_done success='%d' nmsize='%d' count='%d'",
+                  _is_success, nm == NULL ? 0 : nm->content_size(),
+                  method->invocation_count());
+  int bec = method->backedge_count();
+  if (bec != 0)  log->print(" backedge_count='%d'", bec);
+  // Note:  "_is_complete" is about to be set, but is not.
+  if (_num_inlined_bytecodes != 0) {
+    log->print(" inlined_bytes='%d'", _num_inlined_bytecodes);
+  }
+  log->stamp();
+  log->end_elem();
+  log->clear_identities();   // next task will have different CI
+  log->tail("task");
+  if (log->unflushed_count() > 2000) {
+    log->flush();
+  }
+  log->mark_file_end();
+}
+
+// ------------------------------------------------------------------
+// CompileTask::print_inlining
+void CompileTask::print_inlining_inner(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) {
+  //         1234567
+  st->print("        ");     // print timestamp
+  //         1234
+  st->print("     ");        // print compilation number
+
+  // method attributes
+  if (method->is_loaded()) {
+    const char sync_char      = method->is_synchronized()        ? 's' : ' ';
+    const char exception_char = method->has_exception_handlers() ? '!' : ' ';
+    const char monitors_char  = method->has_monitor_bytecodes()  ? 'm' : ' ';
+
+    // print method attributes
+    st->print(" %c%c%c  ", sync_char, exception_char, monitors_char);
+  } else {
+    //         %s!bn
+    st->print("      ");     // print method attributes
+  }
+
+  if (TieredCompilation) {
+    st->print("  ");
+  }
+  st->print("     ");        // more indent
+  st->print("    ");         // initial inlining indent
+
+  for (int i = 0; i < inline_level; i++)  st->print("  ");
+
+  st->print("@ %d  ", bci);  // print bci
+  method->print_short_name(st);
+  if (method->is_loaded())
+    st->print(" (%d bytes)", method->code_size());
+  else
+    st->print(" (not loaded)");
+
+  if (msg != NULL) {
+    st->print("   %s", msg);
+  }
+  st->cr();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/compiler/compileTask.hpp	Tue Sep 08 16:10:37 2015 +0200
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 1998, 2015, 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.
+ *
+ */
+
+#ifndef SHARE_VM_COMPILER_COMPILETASK_HPP
+#define SHARE_VM_COMPILER_COMPILETASK_HPP
+
+#include "code/nmethod.hpp"
+#include "ci/ciMethod.hpp"
+#include "compiler/compileLog.hpp"
+#include "memory/allocation.inline.hpp"
+#include "utilities/xmlstream.hpp"
+
+// CompileTask
+//
+// An entry in the compile queue.  It represents a pending or current
+// compilation.
+
+class CompileTask : public CHeapObj<mtCompiler> {
+  friend class VMStructs;
+
+ private:
+  static CompileTask* _task_free_list;
+#ifdef ASSERT
+  static int          _num_allocated_tasks;
+#endif
+
+  Monitor*     _lock;
+  uint         _compile_id;
+  Method*      _method;
+  jobject      _method_holder;
+  int          _osr_bci;
+  bool         _is_complete;
+  bool         _is_success;
+  bool         _is_blocking;
+  int          _comp_level;
+  int          _num_inlined_bytecodes;
+  nmethodLocker* _code_handle;  // holder of eventual result
+  CompileTask* _next, *_prev;
+  bool         _is_free;
+  // Fields used for logging why the compilation was initiated:
+  jlong        _time_queued;  // in units of os::elapsed_counter()
+  Method*      _hot_method;   // which method actually triggered this task
+  jobject      _hot_method_holder;
+  int          _hot_count;    // information about its invocation counter
+  const char*  _comment;      // more info about the task
+  const char*  _failure_reason;
+
+ public:
+  CompileTask() {
+    _lock = new Monitor(Mutex::nonleaf+2, "CompileTaskLock");
+  }
+
+  void initialize(int compile_id, methodHandle method, int osr_bci, int comp_level,
+                  methodHandle hot_method, int hot_count, const char* comment,
+                  bool is_blocking);
+
+  static CompileTask* allocate();
+  static void         free(CompileTask* task);
+
+  int          compile_id() const                { return _compile_id; }
+  Method*      method() const                    { return _method; }
+  Method*      hot_method() const                { return _hot_method; }
+  int          osr_bci() const                   { return _osr_bci; }
+  bool         is_complete() const               { return _is_complete; }
+  bool         is_blocking() const               { return _is_blocking; }
+  bool         is_success() const                { return _is_success; }
+
+  nmethodLocker* code_handle() const             { return _code_handle; }
+  void         set_code_handle(nmethodLocker* l) { _code_handle = l; }
+  nmethod*     code() const;                     // _code_handle->code()
+  void         set_code(nmethod* nm);            // _code_handle->set_code(nm)
+
+  Monitor*     lock() const                      { return _lock; }
+
+  void         mark_complete()                   { _is_complete = true; }
+  void         mark_success()                    { _is_success = true; }
+
+  int          comp_level()                      { return _comp_level;}
+  void         set_comp_level(int comp_level)    { _comp_level = comp_level;}
+
+  int          num_inlined_bytecodes() const     { return _num_inlined_bytecodes; }
+  void         set_num_inlined_bytecodes(int n)  { _num_inlined_bytecodes = n; }
+
+  CompileTask* next() const                      { return _next; }
+  void         set_next(CompileTask* next)       { _next = next; }
+  CompileTask* prev() const                      { return _prev; }
+  void         set_prev(CompileTask* prev)       { _prev = prev; }
+  bool         is_free() const                   { return _is_free; }
+  void         set_is_free(bool val)             { _is_free = val; }
+
+  // RedefineClasses support
+  void         metadata_do(void f(Metadata*));
+  void         mark_on_stack();
+
+private:
+  static void  print_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, bool cr = true);
+
+public:
+  void         print(outputStream* st = tty, const char* msg = NULL, bool short_form = false, bool cr = true);
+  static void  print(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false, bool cr = true) {
+    print_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, cr);
+  }
+
+  static void  print_inline_indent(int inline_level, outputStream* st = tty);
+
+  void         print_tty();
+  void         print_line_on_error(outputStream* st, char* buf, int buflen);
+
+  void         log_task(xmlStream* log);
+  void         log_task_queued();
+  void         log_task_start(CompileLog* log);
+  void         log_task_done(CompileLog* log);
+
+  void         set_failure_reason(const char* reason) {
+    _failure_reason = reason;
+  }
+
+  bool         check_break_at_flags();
+
+  static void print_inlining_inner(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg = NULL);
+  static void print_inlining_tty(ciMethod* method, int inline_level, int bci, const char* msg = NULL) {
+    print_inlining_inner(tty, method, inline_level, bci, msg);
+  }
+};
+
+#endif // SHARE_VM_COMPILER_COMPILETASK_HPP
--- a/src/share/vm/opto/arraycopynode.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/opto/arraycopynode.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -681,10 +681,10 @@
     uint header = arrayOopDesc::base_offset_in_bytes(ary_elem);
     uint elemsize = type2aelembytes(ary_elem);
 
-    intptr_t dest_pos_plus_len_lo = (((intptr_t)dest_pos_t->_lo) + len_t->_lo) * elemsize + header;
-    intptr_t dest_pos_plus_len_hi = (((intptr_t)dest_pos_t->_hi) + len_t->_hi) * elemsize + header;
-    intptr_t dest_pos_lo = ((intptr_t)dest_pos_t->_lo) * elemsize + header;
-    intptr_t dest_pos_hi = ((intptr_t)dest_pos_t->_hi) * elemsize + header;
+    jlong dest_pos_plus_len_lo = (((jlong)dest_pos_t->_lo) + len_t->_lo) * elemsize + header;
+    jlong dest_pos_plus_len_hi = (((jlong)dest_pos_t->_hi) + len_t->_hi) * elemsize + header;
+    jlong dest_pos_lo = ((jlong)dest_pos_t->_lo) * elemsize + header;
+    jlong dest_pos_hi = ((jlong)dest_pos_t->_hi) * elemsize + header;
 
     if (must_modify) {
       if (offset_lo >= dest_pos_hi && offset_hi < dest_pos_plus_len_lo) {
--- a/src/share/vm/opto/c2compiler.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/opto/c2compiler.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -419,6 +419,8 @@
   case vmIntrinsics::_updateByteBufferCRC32:
   case vmIntrinsics::_updateBytesCRC32C:
   case vmIntrinsics::_updateDirectByteBufferCRC32C:
+  case vmIntrinsics::_updateBytesAdler32:
+  case vmIntrinsics::_updateByteBufferAdler32:
   case vmIntrinsics::_profileBoolean:
   case vmIntrinsics::_isCompileConstant:
     break;
--- a/src/share/vm/opto/compile.hpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/opto/compile.hpp	Tue Sep 08 16:10:37 2015 +0200
@@ -523,7 +523,7 @@
 
   void print_inlining(ciMethod* method, int inline_level, int bci, const char* msg = NULL) {
     stringStream ss;
-    CompileTask::print_inlining(&ss, method, inline_level, bci, msg);
+    CompileTask::print_inlining_inner(&ss, method, inline_level, bci, msg);
     print_inlining_stream()->print("%s", ss.as_string());
   }
 
--- a/src/share/vm/opto/doCall.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/opto/doCall.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -49,7 +49,7 @@
         method->print_short_name();
         tty->cr();
       }
-      CompileTask::print_inlining(prof_method, depth, bci);
+      CompileTask::print_inlining_tty(prof_method, depth, bci);
     } else {
       out = C->print_inlining_stream();
     }
--- a/src/share/vm/opto/escape.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/opto/escape.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -963,6 +963,7 @@
                   strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "updateBytesCRC32") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "updateBytesCRC32C") == 0 ||
+                  strcmp(call->as_CallLeaf()->_name, "updateBytesAdler32") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "aescrypt_encryptBlock") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "aescrypt_decryptBlock") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_encryptAESCrypt") == 0 ||
@@ -3241,7 +3242,7 @@
     // Note 2: MergeMem may already contains instance memory slices added
     // during find_inst_mem() call when memory nodes were processed above.
     igvn->hash_delete(nmm);
-    uint nslices = nmm->req();
+    uint nslices = MIN2(nmm->req(), new_index_start);
     for (uint i = Compile::AliasIdxRaw+1; i < nslices; i++) {
       Node* mem = nmm->in(i);
       Node* cur = NULL;
--- a/src/share/vm/opto/library_call.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/opto/library_call.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -296,6 +296,8 @@
   Node* get_table_from_crc32c_class(ciInstanceKlass *crc32c_class);
   bool inline_updateBytesCRC32C();
   bool inline_updateDirectByteBufferCRC32C();
+  bool inline_updateBytesAdler32();
+  bool inline_updateByteBufferAdler32();
   bool inline_multiplyToLen();
   bool inline_squareToLen();
   bool inline_mulAdd();
@@ -699,6 +701,11 @@
   case vmIntrinsics::_updateDirectByteBufferCRC32C:
     return inline_updateDirectByteBufferCRC32C();
 
+  case vmIntrinsics::_updateBytesAdler32:
+    return inline_updateBytesAdler32();
+  case vmIntrinsics::_updateByteBufferAdler32:
+    return inline_updateByteBufferAdler32();
+
   case vmIntrinsics::_profileBoolean:
     return inline_profileBoolean();
   case vmIntrinsics::_isCompileConstant:
@@ -5547,6 +5554,87 @@
   return true;
 }
 
+//------------------------------inline_updateBytesAdler32----------------------
+//
+// Calculate Adler32 checksum for byte[] array.
+// int java.util.zip.Adler32.updateBytes(int crc, byte[] buf, int off, int len)
+//
+bool LibraryCallKit::inline_updateBytesAdler32() {
+  assert(UseAdler32Intrinsics, "Adler32 Instrinsic support need"); // check if we actually need to check this flag or check a different one
+  assert(callee()->signature()->size() == 4, "updateBytes has 4 parameters");
+  assert(callee()->holder()->is_loaded(), "Adler32 class must be loaded");
+  // no receiver since it is static method
+  Node* crc     = argument(0); // type: int
+  Node* src     = argument(1); // type: oop
+  Node* offset  = argument(2); // type: int
+  Node* length  = argument(3); // type: int
+
+  const Type* src_type = src->Value(&_gvn);
+  const TypeAryPtr* top_src = src_type->isa_aryptr();
+  if (top_src  == NULL || top_src->klass()  == NULL) {
+    // failed array check
+    return false;
+  }
+
+  // Figure out the size and type of the elements we will be copying.
+  BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  if (src_elem != T_BYTE) {
+    return false;
+  }
+
+  // 'src_start' points to src array + scaled offset
+  Node* src_start = array_element_address(src, offset, src_elem);
+
+  // We assume that range check is done by caller.
+  // TODO: generate range check (offset+length < src.length) in debug VM.
+
+  // Call the stub.
+  address stubAddr = StubRoutines::updateBytesAdler32();
+  const char *stubName = "updateBytesAdler32";
+
+  Node* call = make_runtime_call(RC_LEAF, OptoRuntime::updateBytesAdler32_Type(),
+                                 stubAddr, stubName, TypePtr::BOTTOM,
+                                 crc, src_start, length);
+  Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
+  set_result(result);
+  return true;
+}
+
+//------------------------------inline_updateByteBufferAdler32---------------
+//
+// Calculate Adler32 checksum for DirectByteBuffer.
+// int java.util.zip.Adler32.updateByteBuffer(int crc, long buf, int off, int len)
+//
+bool LibraryCallKit::inline_updateByteBufferAdler32() {
+  assert(UseAdler32Intrinsics, "Adler32 Instrinsic support need"); // check if we actually need to check this flag or check a different one
+  assert(callee()->signature()->size() == 5, "updateByteBuffer has 4 parameters and one is long");
+  assert(callee()->holder()->is_loaded(), "Adler32 class must be loaded");
+  // no receiver since it is static method
+  Node* crc     = argument(0); // type: int
+  Node* src     = argument(1); // type: long
+  Node* offset  = argument(3); // type: int
+  Node* length  = argument(4); // type: int
+
+  src = ConvL2X(src);  // adjust Java long to machine word
+  Node* base = _gvn.transform(new CastX2PNode(src));
+  offset = ConvI2X(offset);
+
+  // 'src_start' points to src array + scaled offset
+  Node* src_start = basic_plus_adr(top(), base, offset);
+
+  // Call the stub.
+  address stubAddr = StubRoutines::updateBytesAdler32();
+  const char *stubName = "updateBytesAdler32";
+
+  Node* call = make_runtime_call(RC_LEAF, OptoRuntime::updateBytesAdler32_Type(),
+                                 stubAddr, stubName, TypePtr::BOTTOM,
+                                 crc, src_start, length);
+
+  Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
+  set_result(result);
+  return true;
+}
+
 //----------------------------inline_reference_get----------------------------
 // public T java.lang.ref.Reference.get();
 bool LibraryCallKit::inline_reference_get() {
--- a/src/share/vm/opto/loopopts.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/opto/loopopts.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -673,8 +673,7 @@
 Node* PhaseIdealLoop::try_move_store_before_loop(Node* n, Node *n_ctrl) {
   // Store has to be first in the loop body
   IdealLoopTree *n_loop = get_loop(n_ctrl);
-  if (n->is_Store() && n_loop != _ltree_root && n_loop->is_loop()) {
-    assert(n->in(0), "store should have control set");
+  if (n->is_Store() && n_loop != _ltree_root && n_loop->is_loop() && n->in(0) != NULL) {
     Node* address = n->in(MemNode::Address);
     Node* value = n->in(MemNode::ValueIn);
     Node* mem = n->in(MemNode::Memory);
@@ -748,8 +747,7 @@
 
 // Try moving a store out of a loop, right after the loop
 void PhaseIdealLoop::try_move_store_after_loop(Node* n) {
-  if (n->is_Store()) {
-    assert(n->in(0), "store should have control set");
+  if (n->is_Store() && n->in(0) != NULL) {
     Node *n_ctrl = get_ctrl(n);
     IdealLoopTree *n_loop = get_loop(n_ctrl);
     // Store must be in a loop
--- a/src/share/vm/opto/memnode.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/opto/memnode.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -1677,6 +1677,9 @@
     if (klass == env->String_klass() &&
         adr->is_AddP() && off != Type::OffsetBot) {
       // For constant Strings treat the final fields as compile time constants.
+      // While we can list what field types java.lang.String has, it is more
+      // future-proof to handle all possible field types, anticipating future
+      // changes and experiments in String code.
       Node* base = adr->in(AddPNode::Base);
       const TypeOopPtr* t = phase->type(base)->isa_oopptr();
       if (t != NULL && t->singleton()) {
@@ -1684,14 +1687,13 @@
         if (field != NULL && field->is_final()) {
           ciObject* string = t->const_oop();
           ciConstant constant = string->as_instance()->field_value(field);
-          if (constant.basic_type() == T_INT) {
-            return TypeInt::make(constant.as_int());
-          } else if (constant.basic_type() == T_ARRAY) {
-            if (adr->bottom_type()->is_ptr_to_narrowoop()) {
-              return TypeNarrowOop::make_from_constant(constant.as_object(), true);
-            } else {
-              return TypeOopPtr::make_from_constant(constant.as_object(), true);
-            }
+          // Type::make_from_constant does not handle narrow oops, so handle it here.
+          // Everything else can use the factory method.
+          if ((constant.basic_type() == T_ARRAY || constant.basic_type() == T_OBJECT)
+                  && adr->bottom_type()->is_ptr_to_narrowoop()) {
+            return TypeNarrowOop::make_from_constant(constant.as_object(), true);
+          } else {
+            return Type::make_from_constant(constant, true);
           }
         }
       }
--- a/src/share/vm/opto/runtime.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/opto/runtime.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -33,7 +33,6 @@
 #include "code/scopeDesc.hpp"
 #include "code/vtableStubs.hpp"
 #include "compiler/compileBroker.hpp"
-#include "compiler/compilerOracle.hpp"
 #include "compiler/oopMap.hpp"
 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc/g1/heapRegion.hpp"
@@ -921,6 +920,28 @@
   return TypeFunc::make(domain, range);
 }
 
+/**
+*  int updateBytesAdler32(int adler, bytes* b, int off, int len)
+*/
+const TypeFunc* OptoRuntime::updateBytesAdler32_Type() {
+  // create input type (domain)
+  int num_args      = 3;
+  int argcnt = num_args;
+  const Type** fields = TypeTuple::fields(argcnt);
+  int argp = TypeFunc::Parms;
+  fields[argp++] = TypeInt::INT;        // crc
+  fields[argp++] = TypePtr::NOTNULL;    // src + offset
+  fields[argp++] = TypeInt::INT;        // len
+  assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
+  const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
+
+  // result type needed
+  fields = TypeTuple::fields(1);
+  fields[TypeFunc::Parms+0] = TypeInt::INT; // crc result
+  const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+1, fields);
+  return TypeFunc::make(domain, range);
+}
+
 // for cipherBlockChaining calls of aescrypt encrypt/decrypt, four pointers and a length, returning int
 const TypeFunc* OptoRuntime::cipherBlockChaining_aescrypt_Type() {
   // create input type (domain)
--- a/src/share/vm/opto/runtime.hpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/opto/runtime.hpp	Tue Sep 08 16:10:37 2015 +0200
@@ -331,6 +331,8 @@
   static const TypeFunc* updateBytesCRC32_Type();
   static const TypeFunc* updateBytesCRC32C_Type();
 
+  static const TypeFunc* updateBytesAdler32_Type();
+
   // leaf on stack replacement interpreter accessor types
   static const TypeFunc* osr_end_Type();
 
--- a/src/share/vm/opto/stringopts.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/opto/stringopts.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -1576,51 +1576,58 @@
 
   Node* result;
   if (!kit.stopped()) {
+    Node* char_array = NULL;
+    if (sc->num_arguments() == 1 &&
+          (sc->mode(0) == StringConcat::StringMode ||
+           sc->mode(0) == StringConcat::StringNullCheckMode)) {
+      // Handle the case when there is only a single String argument.
+      // In this case, we can just pull the value from the String itself.
+      char_array = kit.load_String_value(kit.control(), sc->argument(0));
+    } else {
+      // length now contains the number of characters needed for the
+      // char[] so create a new AllocateArray for the char[]
+      {
+        PreserveReexecuteState preexecs(&kit);
+        // The original jvms is for an allocation of either a String or
+        // StringBuffer so no stack adjustment is necessary for proper
+        // reexecution.  If we deoptimize in the slow path the bytecode
+        // will be reexecuted and the char[] allocation will be thrown away.
+        kit.jvms()->set_should_reexecute(true);
+        char_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_CHAR))),
+                                   length, 1);
+      }
 
-    // length now contains the number of characters needed for the
-    // char[] so create a new AllocateArray for the char[]
-    Node* char_array = NULL;
-    {
-      PreserveReexecuteState preexecs(&kit);
-      // The original jvms is for an allocation of either a String or
-      // StringBuffer so no stack adjustment is necessary for proper
-      // reexecution.  If we deoptimize in the slow path the bytecode
-      // will be reexecuted and the char[] allocation will be thrown away.
-      kit.jvms()->set_should_reexecute(true);
-      char_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_CHAR))),
-                                 length, 1);
-    }
-
-    // Mark the allocation so that zeroing is skipped since the code
-    // below will overwrite the entire array
-    AllocateArrayNode* char_alloc = AllocateArrayNode::Ideal_array_allocation(char_array, _gvn);
-    char_alloc->maybe_set_complete(_gvn);
+      // Mark the allocation so that zeroing is skipped since the code
+      // below will overwrite the entire array
+      AllocateArrayNode* char_alloc = AllocateArrayNode::Ideal_array_allocation(char_array, _gvn);
+      char_alloc->maybe_set_complete(_gvn);
 
-    // Now copy the string representations into the final char[]
-    Node* start = __ intcon(0);
-    for (int argi = 0; argi < sc->num_arguments(); argi++) {
-      Node* arg = sc->argument(argi);
-      switch (sc->mode(argi)) {
-        case StringConcat::IntMode: {
-          Node* end = __ AddI(start, string_sizes->in(argi));
-          // getChars words backwards so pass the ending point as well as the start
-          int_getChars(kit, arg, char_array, start, end);
-          start = end;
-          break;
+      // Now copy the string representations into the final char[]
+      Node* start = __ intcon(0);
+      for (int argi = 0; argi < sc->num_arguments(); argi++) {
+        Node* arg = sc->argument(argi);
+        switch (sc->mode(argi)) {
+          case StringConcat::IntMode: {
+            Node* end = __ AddI(start, string_sizes->in(argi));
+            // getChars words backwards so pass the ending point as well as the start
+            int_getChars(kit, arg, char_array, start, end);
+            start = end;
+            break;
+          }
+          case StringConcat::StringNullCheckMode:
+          case StringConcat::StringMode: {
+            start = copy_string(kit, arg, char_array, start);
+            break;
+          }
+          case StringConcat::CharMode: {
+            __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR),
+                               arg, T_CHAR, char_adr_idx, MemNode::unordered);
+            start = __ AddI(start, __ intcon(1));
+            break;
+          }
+          default:
+            ShouldNotReachHere();
         }
-        case StringConcat::StringNullCheckMode:
-        case StringConcat::StringMode: {
-          start = copy_string(kit, arg, char_array, start);
-          break;
-        }
-        case StringConcat::CharMode: {
-          __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR),
-                             arg, T_CHAR, char_adr_idx, MemNode::unordered);
-          start = __ AddI(start, __ intcon(1));
-          break;
-        }
-        default:
-          ShouldNotReachHere();
       }
     }
 
--- a/src/share/vm/runtime/arguments.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -28,7 +28,6 @@
 #include "classfile/stringTable.hpp"
 #include "classfile/symbolTable.hpp"
 #include "code/codeCacheExtensions.hpp"
-#include "compiler/compilerOracle.hpp"
 #include "gc/shared/cardTableRS.hpp"
 #include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/referenceProcessor.hpp"
--- a/src/share/vm/runtime/compilationPolicy.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/runtime/compilationPolicy.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -26,7 +26,6 @@
 #include "code/compiledIC.hpp"
 #include "code/nmethod.hpp"
 #include "code/scopeDesc.hpp"
-#include "compiler/compilerOracle.hpp"
 #include "interpreter/interpreter.hpp"
 #include "oops/methodData.hpp"
 #include "oops/method.hpp"
--- a/src/share/vm/runtime/globals.hpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/runtime/globals.hpp	Tue Sep 08 16:10:37 2015 +0200
@@ -832,6 +832,9 @@
   product(bool, UseCRC32CIntrinsics, false,                                 \
           "use intrinsics for java.util.zip.CRC32C")                        \
                                                                             \
+  product(bool, UseAdler32Intrinsics, false,                                \
+          "use intrinsics for java.util.zip.Adler32")                       \
+                                                                            \
   diagnostic(ccstrlist, DisableIntrinsic, "",                               \
          "do not expand intrinsics whose (internal) names appear here")     \
                                                                             \
--- a/src/share/vm/runtime/sharedRuntime.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -32,7 +32,6 @@
 #include "code/vtableStubs.hpp"
 #include "compiler/abstractCompiler.hpp"
 #include "compiler/compileBroker.hpp"
-#include "compiler/compilerOracle.hpp"
 #include "compiler/disassembler.hpp"
 #include "gc/shared/gcLocker.inline.hpp"
 #include "interpreter/interpreter.hpp"
@@ -2622,7 +2621,7 @@
   if (nm != NULL) {
     if (PrintCompilation) {
       ttyLocker ttyl;
-      CompileTask::print_compilation(tty, nm, method->is_static() ? "(static)" : "");
+      CompileTask::print(tty, nm, method->is_static() ? "(static)" : "");
     }
     nm->post_compiled_method_load_event();
   }
--- a/src/share/vm/runtime/stubRoutines.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/runtime/stubRoutines.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -139,6 +139,7 @@
 address StubRoutines::_crc_table_adr = NULL;
 
 address StubRoutines::_updateBytesCRC32C = NULL;
+address StubRoutines::_updateBytesAdler32 = NULL;
 
 address StubRoutines::_multiplyToLen = NULL;
 address StubRoutines::_squareToLen = NULL;
--- a/src/share/vm/runtime/stubRoutines.hpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/runtime/stubRoutines.hpp	Tue Sep 08 16:10:37 2015 +0200
@@ -198,6 +198,7 @@
   static address _crc_table_adr;
 
   static address _updateBytesCRC32C;
+  static address _updateBytesAdler32;
 
   static address _multiplyToLen;
   static address _squareToLen;
@@ -364,6 +365,7 @@
   static address crc_table_addr()      { return _crc_table_adr; }
 
   static address updateBytesCRC32C()   { return _updateBytesCRC32C; }
+  static address updateBytesAdler32()  { return _updateBytesAdler32; }
 
   static address multiplyToLen()       {return _multiplyToLen; }
   static address squareToLen()         {return _squareToLen; }
--- a/src/share/vm/runtime/sweeper.cpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/runtime/sweeper.cpp	Tue Sep 08 16:10:37 2015 +0200
@@ -611,7 +611,7 @@
   } else if (nm->is_not_entrant()) {
     // If there are no current activations of this method on the
     // stack we can safely convert it to a zombie method
-    if (nm->can_not_entrant_be_converted()) {
+    if (nm->can_convert_to_zombie()) {
       // Clear ICStubs to prevent back patching stubs of zombie or unloaded
       // nmethods during the next safepoint (see ICStub::finalize).
       {
@@ -645,6 +645,12 @@
       assert(result == None, "sanity");
       result = Flushed;
     } else {
+      {
+        // Clean ICs of unloaded nmethods as well because they may reference other
+        // unloaded nmethods that may be flushed earlier in the sweeper cycle.
+        MutexLocker cl(CompiledIC_lock);
+        nm->cleanup_inline_caches();
+      }
       // Code cache state change is tracked in make_zombie()
       nm->make_zombie();
       SWEEP(nm);
--- a/src/share/vm/runtime/thread.hpp	Mon Sep 07 20:03:56 2015 +0200
+++ b/src/share/vm/runtime/thread.hpp	Tue Sep 08 16:10:37 2015 +0200
@@ -368,9 +368,17 @@
   inline void clear_critical_native_unlock();
 
   // Support for Unhandled Oop detection
+  // Add the field for both, fastdebug and debug, builds to keep
+  // Thread's fields layout the same.
+  // Note: CHECK_UNHANDLED_OOPS is defined only for fastdebug build.
 #ifdef CHECK_UNHANDLED_OOPS
  private:
   UnhandledOops* _unhandled_oops;
+#elif defined(ASSERT)
+ private:
+  void* _unhandled_oops;
+#endif
+#ifdef CHECK_UNHANDLED_OOPS
  public:
   UnhandledOops* unhandled_oops() { return _unhandled_oops; }
   // Mark oop safe for gc.  It may be stack allocated but won't move.
@@ -383,12 +391,12 @@
   }
 #endif // CHECK_UNHANDLED_OOPS
 
+ public:
 #ifndef PRODUCT
   bool skip_gcalot()           { return _skip_gcalot; }
   void set_skip_gcalot(bool v) { _skip_gcalot = v;    }
 #endif
 
- public:
   // Installs a pending exception to be inserted later
   static void send_async_exception(oop thread_oop, oop java_throwable);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/TestMoveStoresOutOfLoopsStoreNoCtrl.java	Tue Sep 08 16:10:37 2015 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, 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 8134288
+ * @summary Store nodes may not have a control if used to update profiling
+ * @run main/othervm -XX:-ProfileInterpreter -XX:-TieredCompilation -XX:-BackgroundCompilation TestMoveStoresOutOfLoopsStoreNoCtrl
+ *
+ */
+
+public class TestMoveStoresOutOfLoopsStoreNoCtrl {
+
+    static void test(boolean flag) {
+        for (int i = 0; i < 20000; i++) {
+            if (flag) {
+                int j = 0;
+                do {
+                    j++;
+                } while(j < 10);
+            }
+        }
+    }
+
+    static public void main(String[] args) {
+        test(false);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/arraycopy/TestArrayCopyOverflowInBoundChecks.java	Tue Sep 08 16:10:37 2015 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, 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 8134468
+ * @summary test that checks whether an array load falls into the range of an arraycopy is incorrect on 32bits
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArrayCopyOverflowInBoundChecks
+ *
+ */
+public class TestArrayCopyOverflowInBoundChecks {
+
+    static byte[] src_array = { 'a', 'b', 'c', 'd', 'e' };
+
+    static byte test(int copy_len) {
+        byte[] dst_array = new byte[10];
+        System.arraycopy(src_array, 0, dst_array, 1, copy_len);
+        return dst_array[1];
+    }
+
+    static public void main(String[] args) {
+        for (int i = 0; i < 20000; i++) {
+            if (test(src_array.length - 1) != src_array[0]) {
+                throw new RuntimeException("Test failed");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/escapeAnalysis/TestEABadMergeMem.java	Tue Sep 08 16:10:37 2015 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015, 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 8134031
+ * @summary Bad rewiring of memory edges when we split unique types during EA
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:CompileCommand=dontinline,TestEABadMergeMem::m_notinlined TestEABadMergeMem
+ *
+ */
+
+public class TestEABadMergeMem {
+
+    static class Box {
+        int i;
+    }
+
+    static void m_notinlined() {
+    }
+
+    static float dummy1;
+    static float dummy2;
+
+    static int test(Box a, Box c, int i, int j, int k, boolean flag1, boolean flag2) {
+        Box b = new Box(); // non escaping
+        a.i = i;
+        b.i = j;
+        c.i = k;
+
+        m_notinlined();
+
+        boolean flag3 = false;
+        if (flag1) {
+            for (int ii = 0; ii < 100; ii++) {
+                if (flag2) {
+                    dummy1 = (float)ii;
+                } else {
+                    dummy2 = (float)ii;
+                }
+            }
+            flag3 = true;
+        }
+        // Memory Phi here with projection of not inlined call as one edge, MergeMem as other
+
+        if (flag3) { // will split through Phi during loopopts
+            int res = c.i + b.i;
+            m_notinlined(); // prevents split through phi during igvn
+            return res;
+        } else {
+            return 44 + 43;
+        }
+    }
+
+    static public void main(String[] args) {
+        for (int i = 0; i < 20000; i++) {
+            // m(2);
+            Box a = new Box();
+            Box c = new Box();
+            int res = test(a, c, 42, 43, 44, (i%2) == 0, (i%3) == 0);
+            if (res != 44 + 43) {
+                throw new RuntimeException("Bad result " + res);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/intrinsics/adler32/TestAdler32.java	Tue Sep 08 16:10:37 2015 +0200
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2015, 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 8132081
+ * @summary C2 support for Adler32 on SPARC
+ *
+ * @run main/othervm/timeout=600 -Xbatch TestAdler32 -m
+ */
+
+import java.nio.ByteBuffer;
+import java.util.zip.Checksum;
+import java.util.zip.Adler32;
+
+public class TestAdler32 {
+    public static void main(String[] args) {
+        int offset = Integer.getInteger("offset", 0);
+        int msgSize = Integer.getInteger("msgSize", 512);
+        boolean multi = false;
+        int iters = 20000;
+        int warmupIters = 20000;
+
+        if (args.length > 0) {
+            if (args[0].equals("-m")) {
+                multi = true;
+            } else {
+                iters = Integer.valueOf(args[0]);
+            }
+            if (args.length > 1) {
+                warmupIters = Integer.valueOf(args[1]);
+            }
+        }
+
+        if (multi) {
+            test_multi(warmupIters);
+            return;
+        }
+
+        System.out.println(" offset = " + offset);
+        System.out.println("msgSize = " + msgSize + " bytes");
+        System.out.println("  iters = " + iters);
+
+        byte[] b = initializedBytes(msgSize, offset);
+
+        Adler32 adler0 = new Adler32();
+        Adler32 adler1 = new Adler32();
+        Adler32 adler2 = new Adler32();
+
+        adler0.update(b, offset, msgSize);
+
+        System.out.println("-------------------------------------------------------");
+
+        /* warm up */
+        for (int i = 0; i < warmupIters; i++) {
+            adler1.reset();
+            adler1.update(b, offset, msgSize);
+        }
+
+        /* measure performance */
+        long start = System.nanoTime();
+        for (int i = 0; i < iters; i++) {
+            adler1.reset();
+            adler1.update(b, offset, msgSize);
+        }
+        long end = System.nanoTime();
+        double total = (double)(end - start)/1e9;         // in seconds
+        double thruput = (double)msgSize*iters/1e6/total; // in MB/s
+        System.out.println("Adler32.update(byte[]) runtime = " + total + " seconds");
+        System.out.println("Adler32.update(byte[]) throughput = " + thruput + " MB/s");
+
+        /* check correctness */
+        for (int i = 0; i < iters; i++) {
+            adler1.reset();
+            adler1.update(b, offset, msgSize);
+            if (!check(adler0, adler1)) break;
+        }
+        report("Adlers", adler0, adler1);
+
+        System.out.println("-------------------------------------------------------");
+
+        ByteBuffer buf = ByteBuffer.allocateDirect(msgSize);
+        buf.put(b, offset, msgSize);
+        buf.flip();
+
+        /* warm up */
+        for (int i = 0; i < warmupIters; i++) {
+            adler2.reset();
+            adler2.update(buf);
+            buf.rewind();
+        }
+
+        /* measure performance */
+        start = System.nanoTime();
+        for (int i = 0; i < iters; i++) {
+            adler2.reset();
+            adler2.update(buf);
+            buf.rewind();
+        }
+        end = System.nanoTime();
+        total = (double)(end - start)/1e9;         // in seconds
+        thruput = (double)msgSize*iters/1e6/total; // in MB/s
+        System.out.println("Adler32.update(ByteBuffer) runtime = " + total + " seconds");
+        System.out.println("Adler32.update(ByteBuffer) throughput = " + thruput + " MB/s");
+
+        /* check correctness */
+        for (int i = 0; i < iters; i++) {
+            adler2.reset();
+            adler2.update(buf);
+            buf.rewind();
+            if (!check(adler0, adler2)) break;
+        }
+        report("Adlers", adler0, adler1);
+
+        System.out.println("-------------------------------------------------------");
+    }
+
+    private static void report(String s, Checksum adler0, Checksum adler1) {
+        System.out.printf("%s: adler0 = %08x, adler1 = %08x\n",
+                          s, adler0.getValue(), adler1.getValue());
+    }
+
+    private static boolean check(Checksum adler0, Checksum adler1) {
+        if (adler0.getValue() != adler1.getValue()) {
+            System.err.printf("ERROR: adler0 = %08x, adler1 = %08x\n",
+                              adler0.getValue(), adler1.getValue());
+            return false;
+        }
+        return true;
+    }
+
+    private static byte[] initializedBytes(int M, int offset) {
+        byte[] bytes = new byte[M + offset];
+        for (int i = 0; i < offset; i++) {
+            bytes[i] = (byte) i;
+        }
+        for (int i = offset; i < bytes.length; i++) {
+            bytes[i] = (byte) (i - offset);
+        }
+        return bytes;
+    }
+
+    private static void test_multi(int iters) {
+        int len1 = 8;    // the  8B/iteration loop
+        int len2 = 32;   // the 32B/iteration loop
+        int len3 = 4096; // the 4KB/iteration loop
+
+        byte[] b = initializedBytes(len3*16, 0);
+        int[] offsets = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 256, 512 };
+        int[] sizes = { 0, 1, 2, 3, 4, 5, 6, 7,
+                        len1, len1+1, len1+2, len1+3, len1+4, len1+5, len1+6, len1+7,
+                        len1*2, len1*2+1, len1*2+3, len1*2+5, len1*2+7,
+                        len2, len2+1, len2+3, len2+5, len2+7,
+                        len2*2, len2*4, len2*8, len2*16, len2*32, len2*64,
+                        len3, len3+1, len3+3, len3+5, len3+7,
+                        len3*2, len3*4, len3*8,
+                        len1+len2, len1+len2+1, len1+len2+3, len1+len2+5, len1+len2+7,
+                        len1+len3, len1+len3+1, len1+len3+3, len1+len3+5, len1+len3+7,
+                        len2+len3, len2+len3+1, len2+len3+3, len2+len3+5, len2+len3+7,
+                        len1+len2+len3, len1+len2+len3+1, len1+len2+len3+3,
+                        len1+len2+len3+5, len1+len2+len3+7,
+                        (len1+len2+len3)*2, (len1+len2+len3)*2+1, (len1+len2+len3)*2+3,
+                        (len1+len2+len3)*2+5, (len1+len2+len3)*2+7,
+                        (len1+len2+len3)*3, (len1+len2+len3)*3-1, (len1+len2+len3)*3-3,
+                        (len1+len2+len3)*3-5, (len1+len2+len3)*3-7 };
+        Adler32[] adler0 = new Adler32[offsets.length*sizes.length];
+        Adler32[] adler1 = new Adler32[offsets.length*sizes.length];
+        int i, j, k;
+
+        System.out.printf("testing %d cases ...\n", offsets.length*sizes.length);
+
+        /* set the result from interpreter as reference */
+        for (i = 0; i < offsets.length; i++) {
+            for (j = 0; j < sizes.length; j++) {
+                adler0[i*sizes.length + j] = new Adler32();
+                adler1[i*sizes.length + j] = new Adler32();
+                adler0[i*sizes.length + j].update(b, offsets[i], sizes[j]);
+            }
+        }
+
+        /* warm up the JIT compiler and get result */
+        for (k = 0; k < iters; k++) {
+            for (i = 0; i < offsets.length; i++) {
+                for (j = 0; j < sizes.length; j++) {
+                    adler1[i*sizes.length + j].reset();
+                    adler1[i*sizes.length + j].update(b, offsets[i], sizes[j]);
+                }
+            }
+        }
+
+        /* check correctness */
+        for (i = 0; i < offsets.length; i++) {
+            for (j = 0; j < sizes.length; j++) {
+                if (!check(adler0[i*sizes.length + j], adler1[i*sizes.length + j])) {
+                    System.out.printf("offsets[%d] = %d", i, offsets[i]);
+                    System.out.printf("\tsizes[%d] = %d\n", j, sizes[j]);
+                }
+            }
+        }
+    }
+}