--- a/hotspot/make/Makefile Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/make/Makefile Fri Sep 05 15:53:02 2014 -0700
@@ -337,7 +337,7 @@
export_product_jdk::
$(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) generic_export
export_optimized_jdk::
- $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) generic_export
+ $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) generic_export
export_fastdebug_jdk::
$(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) generic_export
export_debug_jdk::
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -4937,6 +4937,26 @@
emit_arith(0x03, 0xC0, dst, src);
}
+void Assembler::adcxq(Register dst, Register src) {
+ //assert(VM_Version::supports_adx(), "adx instructions not supported");
+ emit_int8((unsigned char)0x66);
+ int encode = prefixq_and_encode(dst->encoding(), src->encoding());
+ emit_int8(0x0F);
+ emit_int8(0x38);
+ emit_int8((unsigned char)0xF6);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
+void Assembler::adoxq(Register dst, Register src) {
+ //assert(VM_Version::supports_adx(), "adx instructions not supported");
+ emit_int8((unsigned char)0xF3);
+ int encode = prefixq_and_encode(dst->encoding(), src->encoding());
+ emit_int8(0x0F);
+ emit_int8(0x38);
+ emit_int8((unsigned char)0xF6);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
void Assembler::andq(Address dst, int32_t imm32) {
InstructionMark im(this);
prefixq(dst);
@@ -5444,6 +5464,26 @@
emit_int8((unsigned char)(0xC0 | encode));
}
+void Assembler::mulq(Address src) {
+ InstructionMark im(this);
+ prefixq(src);
+ emit_int8((unsigned char)0xF7);
+ emit_operand(rsp, src);
+}
+
+void Assembler::mulq(Register src) {
+ int encode = prefixq_and_encode(src->encoding());
+ emit_int8((unsigned char)0xF7);
+ emit_int8((unsigned char)(0xE0 | encode));
+}
+
+void Assembler::mulxq(Register dst1, Register dst2, Register src) {
+ assert(VM_Version::supports_bmi2(), "bit manipulation instructions not supported");
+ int encode = vex_prefix_and_encode(dst1->encoding(), dst2->encoding(), src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_38, true, false);
+ emit_int8((unsigned char)0xF6);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
void Assembler::negq(Register dst) {
int encode = prefixq_and_encode(dst->encoding());
emit_int8((unsigned char)0xF7);
@@ -5572,6 +5612,28 @@
emit_int8(imm8);
}
}
+
+void Assembler::rorq(Register dst, int imm8) {
+ assert(isShiftCount(imm8 >> 1), "illegal shift count");
+ int encode = prefixq_and_encode(dst->encoding());
+ if (imm8 == 1) {
+ emit_int8((unsigned char)0xD1);
+ emit_int8((unsigned char)(0xC8 | encode));
+ } else {
+ emit_int8((unsigned char)0xC1);
+ emit_int8((unsigned char)(0xc8 | encode));
+ emit_int8(imm8);
+ }
+}
+
+void Assembler::rorxq(Register dst, Register src, int imm8) {
+ assert(VM_Version::supports_bmi2(), "bit manipulation instructions not supported");
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_3A, true, false);
+ emit_int8((unsigned char)0xF0);
+ emit_int8((unsigned char)(0xC0 | encode));
+ emit_int8(imm8);
+}
+
void Assembler::sarq(Register dst, int imm8) {
assert(isShiftCount(imm8 >> 1), "illegal shift count");
int encode = prefixq_and_encode(dst->encoding());
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -888,6 +888,14 @@
void addq(Register dst, Address src);
void addq(Register dst, Register src);
+#ifdef _LP64
+ //Add Unsigned Integers with Carry Flag
+ void adcxq(Register dst, Register src);
+
+ //Add Unsigned Integers with Overflow Flag
+ void adoxq(Register dst, Register src);
+#endif
+
void addr_nop_4();
void addr_nop_5();
void addr_nop_7();
@@ -1204,19 +1212,20 @@
void idivl(Register src);
void divl(Register src); // Unsigned division
+#ifdef _LP64
void idivq(Register src);
+#endif
void imull(Register dst, Register src);
void imull(Register dst, Register src, int value);
void imull(Register dst, Address src);
+#ifdef _LP64
void imulq(Register dst, Register src);
void imulq(Register dst, Register src, int value);
-#ifdef _LP64
void imulq(Register dst, Address src);
#endif
-
// jcc is the generic conditional branch generator to run-
// time routines, jcc is used for branches to labels. jcc
// takes a branch opcode (cc) and a label (L) and generates
@@ -1408,9 +1417,16 @@
void movzwq(Register dst, Register src);
#endif
+ // Unsigned multiply with RAX destination register
void mull(Address src);
void mull(Register src);
+#ifdef _LP64
+ void mulq(Address src);
+ void mulq(Register src);
+ void mulxq(Register dst1, Register dst2, Register src);
+#endif
+
// Multiply Scalar Double-Precision Floating-Point Values
void mulsd(XMMRegister dst, Address src);
void mulsd(XMMRegister dst, XMMRegister src);
@@ -1541,6 +1557,11 @@
void ret(int imm16);
+#ifdef _LP64
+ void rorq(Register dst, int imm8);
+ void rorxq(Register dst, Register src, int imm8);
+#endif
+
void sahf();
void sarl(Register dst, int imm8);
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -176,6 +176,8 @@
"Use count trailing zeros instruction") \
\
product(bool, UseBMI1Instructions, false, \
- "Use BMI instructions")
-
+ "Use BMI1 instructions") \
+ \
+ product(bool, UseBMI2Instructions, false, \
+ "Use BMI2 instructions")
#endif // CPU_X86_VM_GLOBALS_X86_HPP
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -7293,6 +7293,467 @@
bind(L_done);
}
+#ifdef _LP64
+/**
+ * Helper for multiply_to_len().
+ */
+void MacroAssembler::add2_with_carry(Register dest_hi, Register dest_lo, Register src1, Register src2) {
+ addq(dest_lo, src1);
+ adcq(dest_hi, 0);
+ addq(dest_lo, src2);
+ adcq(dest_hi, 0);
+}
+
+/**
+ * Multiply 64 bit by 64 bit first loop.
+ */
+void MacroAssembler::multiply_64_x_64_loop(Register x, Register xstart, Register x_xstart,
+ Register y, Register y_idx, Register z,
+ Register carry, Register product,
+ Register idx, Register kdx) {
+ //
+ // jlong carry, x[], y[], z[];
+ // for (int idx=ystart, kdx=ystart+1+xstart; idx >= 0; idx-, kdx--) {
+ // huge_128 product = y[idx] * x[xstart] + carry;
+ // z[kdx] = (jlong)product;
+ // carry = (jlong)(product >>> 64);
+ // }
+ // z[xstart] = carry;
+ //
+
+ Label L_first_loop, L_first_loop_exit;
+ Label L_one_x, L_one_y, L_multiply;
+
+ decrementl(xstart);
+ jcc(Assembler::negative, L_one_x);
+
+ movq(x_xstart, Address(x, xstart, Address::times_4, 0));
+ rorq(x_xstart, 32); // convert big-endian to little-endian
+
+ bind(L_first_loop);
+ decrementl(idx);
+ jcc(Assembler::negative, L_first_loop_exit);
+ decrementl(idx);
+ jcc(Assembler::negative, L_one_y);
+ movq(y_idx, Address(y, idx, Address::times_4, 0));
+ rorq(y_idx, 32); // convert big-endian to little-endian
+ bind(L_multiply);
+ movq(product, x_xstart);
+ mulq(y_idx); // product(rax) * y_idx -> rdx:rax
+ addq(product, carry);
+ adcq(rdx, 0);
+ subl(kdx, 2);
+ movl(Address(z, kdx, Address::times_4, 4), product);
+ shrq(product, 32);
+ movl(Address(z, kdx, Address::times_4, 0), product);
+ movq(carry, rdx);
+ jmp(L_first_loop);
+
+ bind(L_one_y);
+ movl(y_idx, Address(y, 0));
+ jmp(L_multiply);
+
+ bind(L_one_x);
+ movl(x_xstart, Address(x, 0));
+ jmp(L_first_loop);
+
+ bind(L_first_loop_exit);
+}
+
+/**
+ * Multiply 64 bit by 64 bit and add 128 bit.
+ */
+void MacroAssembler::multiply_add_128_x_128(Register x_xstart, Register y, Register z,
+ Register yz_idx, Register idx,
+ Register carry, Register product, int offset) {
+ // huge_128 product = (y[idx] * x_xstart) + z[kdx] + carry;
+ // z[kdx] = (jlong)product;
+
+ movq(yz_idx, Address(y, idx, Address::times_4, offset));
+ rorq(yz_idx, 32); // convert big-endian to little-endian
+ movq(product, x_xstart);
+ mulq(yz_idx); // product(rax) * yz_idx -> rdx:product(rax)
+ movq(yz_idx, Address(z, idx, Address::times_4, offset));
+ rorq(yz_idx, 32); // convert big-endian to little-endian
+
+ add2_with_carry(rdx, product, carry, yz_idx);
+
+ movl(Address(z, idx, Address::times_4, offset+4), product);
+ shrq(product, 32);
+ movl(Address(z, idx, Address::times_4, offset), product);
+
+}
+
+/**
+ * Multiply 128 bit by 128 bit. Unrolled inner loop.
+ */
+void MacroAssembler::multiply_128_x_128_loop(Register x_xstart, Register y, Register z,
+ Register yz_idx, Register idx, Register jdx,
+ Register carry, Register product,
+ Register carry2) {
+ // jlong carry, x[], y[], z[];
+ // int kdx = ystart+1;
+ // for (int idx=ystart-2; idx >= 0; idx -= 2) { // Third loop
+ // huge_128 product = (y[idx+1] * x_xstart) + z[kdx+idx+1] + carry;
+ // z[kdx+idx+1] = (jlong)product;
+ // jlong carry2 = (jlong)(product >>> 64);
+ // product = (y[idx] * x_xstart) + z[kdx+idx] + carry2;
+ // z[kdx+idx] = (jlong)product;
+ // carry = (jlong)(product >>> 64);
+ // }
+ // idx += 2;
+ // if (idx > 0) {
+ // product = (y[idx] * x_xstart) + z[kdx+idx] + carry;
+ // z[kdx+idx] = (jlong)product;
+ // carry = (jlong)(product >>> 64);
+ // }
+ //
+
+ Label L_third_loop, L_third_loop_exit, L_post_third_loop_done;
+
+ movl(jdx, idx);
+ andl(jdx, 0xFFFFFFFC);
+ shrl(jdx, 2);
+
+ bind(L_third_loop);
+ subl(jdx, 1);
+ jcc(Assembler::negative, L_third_loop_exit);
+ subl(idx, 4);
+
+ multiply_add_128_x_128(x_xstart, y, z, yz_idx, idx, carry, product, 8);
+ movq(carry2, rdx);
+
+ multiply_add_128_x_128(x_xstart, y, z, yz_idx, idx, carry2, product, 0);
+ movq(carry, rdx);
+ jmp(L_third_loop);
+
+ bind (L_third_loop_exit);
+
+ andl (idx, 0x3);
+ jcc(Assembler::zero, L_post_third_loop_done);
+
+ Label L_check_1;
+ subl(idx, 2);
+ jcc(Assembler::negative, L_check_1);
+
+ multiply_add_128_x_128(x_xstart, y, z, yz_idx, idx, carry, product, 0);
+ movq(carry, rdx);
+
+ bind (L_check_1);
+ addl (idx, 0x2);
+ andl (idx, 0x1);
+ subl(idx, 1);
+ jcc(Assembler::negative, L_post_third_loop_done);
+
+ movl(yz_idx, Address(y, idx, Address::times_4, 0));
+ movq(product, x_xstart);
+ mulq(yz_idx); // product(rax) * yz_idx -> rdx:product(rax)
+ movl(yz_idx, Address(z, idx, Address::times_4, 0));
+
+ add2_with_carry(rdx, product, yz_idx, carry);
+
+ movl(Address(z, idx, Address::times_4, 0), product);
+ shrq(product, 32);
+
+ shlq(rdx, 32);
+ orq(product, rdx);
+ movq(carry, product);
+
+ bind(L_post_third_loop_done);
+}
+
+/**
+ * Multiply 128 bit by 128 bit using BMI2. Unrolled inner loop.
+ *
+ */
+void MacroAssembler::multiply_128_x_128_bmi2_loop(Register y, Register z,
+ Register carry, Register carry2,
+ Register idx, Register jdx,
+ Register yz_idx1, Register yz_idx2,
+ Register tmp, Register tmp3, Register tmp4) {
+ assert(UseBMI2Instructions, "should be used only when BMI2 is available");
+
+ // jlong carry, x[], y[], z[];
+ // int kdx = ystart+1;
+ // for (int idx=ystart-2; idx >= 0; idx -= 2) { // Third loop
+ // huge_128 tmp3 = (y[idx+1] * rdx) + z[kdx+idx+1] + carry;
+ // jlong carry2 = (jlong)(tmp3 >>> 64);
+ // huge_128 tmp4 = (y[idx] * rdx) + z[kdx+idx] + carry2;
+ // carry = (jlong)(tmp4 >>> 64);
+ // z[kdx+idx+1] = (jlong)tmp3;
+ // z[kdx+idx] = (jlong)tmp4;
+ // }
+ // idx += 2;
+ // if (idx > 0) {
+ // yz_idx1 = (y[idx] * rdx) + z[kdx+idx] + carry;
+ // z[kdx+idx] = (jlong)yz_idx1;
+ // carry = (jlong)(yz_idx1 >>> 64);
+ // }
+ //
+
+ Label L_third_loop, L_third_loop_exit, L_post_third_loop_done;
+
+ movl(jdx, idx);
+ andl(jdx, 0xFFFFFFFC);
+ shrl(jdx, 2);
+
+ bind(L_third_loop);
+ subl(jdx, 1);
+ jcc(Assembler::negative, L_third_loop_exit);
+ subl(idx, 4);
+
+ movq(yz_idx1, Address(y, idx, Address::times_4, 8));
+ rorxq(yz_idx1, yz_idx1, 32); // convert big-endian to little-endian
+ movq(yz_idx2, Address(y, idx, Address::times_4, 0));
+ rorxq(yz_idx2, yz_idx2, 32);
+
+ mulxq(tmp4, tmp3, yz_idx1); // yz_idx1 * rdx -> tmp4:tmp3
+ mulxq(carry2, tmp, yz_idx2); // yz_idx2 * rdx -> carry2:tmp
+
+ movq(yz_idx1, Address(z, idx, Address::times_4, 8));
+ rorxq(yz_idx1, yz_idx1, 32);
+ movq(yz_idx2, Address(z, idx, Address::times_4, 0));
+ rorxq(yz_idx2, yz_idx2, 32);
+
+ if (VM_Version::supports_adx()) {
+ adcxq(tmp3, carry);
+ adoxq(tmp3, yz_idx1);
+
+ adcxq(tmp4, tmp);
+ adoxq(tmp4, yz_idx2);
+
+ movl(carry, 0); // does not affect flags
+ adcxq(carry2, carry);
+ adoxq(carry2, carry);
+ } else {
+ add2_with_carry(tmp4, tmp3, carry, yz_idx1);
+ add2_with_carry(carry2, tmp4, tmp, yz_idx2);
+ }
+ movq(carry, carry2);
+
+ movl(Address(z, idx, Address::times_4, 12), tmp3);
+ shrq(tmp3, 32);
+ movl(Address(z, idx, Address::times_4, 8), tmp3);
+
+ movl(Address(z, idx, Address::times_4, 4), tmp4);
+ shrq(tmp4, 32);
+ movl(Address(z, idx, Address::times_4, 0), tmp4);
+
+ jmp(L_third_loop);
+
+ bind (L_third_loop_exit);
+
+ andl (idx, 0x3);
+ jcc(Assembler::zero, L_post_third_loop_done);
+
+ Label L_check_1;
+ subl(idx, 2);
+ jcc(Assembler::negative, L_check_1);
+
+ movq(yz_idx1, Address(y, idx, Address::times_4, 0));
+ rorxq(yz_idx1, yz_idx1, 32);
+ mulxq(tmp4, tmp3, yz_idx1); // yz_idx1 * rdx -> tmp4:tmp3
+ movq(yz_idx2, Address(z, idx, Address::times_4, 0));
+ rorxq(yz_idx2, yz_idx2, 32);
+
+ add2_with_carry(tmp4, tmp3, carry, yz_idx2);
+
+ movl(Address(z, idx, Address::times_4, 4), tmp3);
+ shrq(tmp3, 32);
+ movl(Address(z, idx, Address::times_4, 0), tmp3);
+ movq(carry, tmp4);
+
+ bind (L_check_1);
+ addl (idx, 0x2);
+ andl (idx, 0x1);
+ subl(idx, 1);
+ jcc(Assembler::negative, L_post_third_loop_done);
+ movl(tmp4, Address(y, idx, Address::times_4, 0));
+ mulxq(carry2, tmp3, tmp4); // tmp4 * rdx -> carry2:tmp3
+ movl(tmp4, Address(z, idx, Address::times_4, 0));
+
+ add2_with_carry(carry2, tmp3, tmp4, carry);
+
+ movl(Address(z, idx, Address::times_4, 0), tmp3);
+ shrq(tmp3, 32);
+
+ shlq(carry2, 32);
+ orq(tmp3, carry2);
+ movq(carry, tmp3);
+
+ bind(L_post_third_loop_done);
+}
+
+/**
+ * Code for BigInteger::multiplyToLen() instrinsic.
+ *
+ * rdi: x
+ * rax: xlen
+ * rsi: y
+ * rcx: ylen
+ * r8: z
+ * r11: zlen
+ * r12: tmp1
+ * r13: tmp2
+ * r14: tmp3
+ * r15: tmp4
+ * rbx: tmp5
+ *
+ */
+void MacroAssembler::multiply_to_len(Register x, Register xlen, Register y, Register ylen, Register z, Register zlen,
+ Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5) {
+ ShortBranchVerifier sbv(this);
+ assert_different_registers(x, xlen, y, ylen, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx);
+
+ push(tmp1);
+ push(tmp2);
+ push(tmp3);
+ push(tmp4);
+ push(tmp5);
+
+ push(xlen);
+ push(zlen);
+
+ const Register idx = tmp1;
+ const Register kdx = tmp2;
+ const Register xstart = tmp3;
+
+ const Register y_idx = tmp4;
+ const Register carry = tmp5;
+ const Register product = xlen;
+ const Register x_xstart = zlen; // reuse register
+
+ // First Loop.
+ //
+ // final static long LONG_MASK = 0xffffffffL;
+ // int xstart = xlen - 1;
+ // int ystart = ylen - 1;
+ // long carry = 0;
+ // for (int idx=ystart, kdx=ystart+1+xstart; idx >= 0; idx-, kdx--) {
+ // long product = (y[idx] & LONG_MASK) * (x[xstart] & LONG_MASK) + carry;
+ // z[kdx] = (int)product;
+ // carry = product >>> 32;
+ // }
+ // z[xstart] = (int)carry;
+ //
+
+ movl(idx, ylen); // idx = ylen;
+ movl(kdx, zlen); // kdx = xlen+ylen;
+ xorq(carry, carry); // carry = 0;
+
+ Label L_done;
+
+ movl(xstart, xlen);
+ decrementl(xstart);
+ jcc(Assembler::negative, L_done);
+
+ multiply_64_x_64_loop(x, xstart, x_xstart, y, y_idx, z, carry, product, idx, kdx);
+
+ Label L_second_loop;
+ testl(kdx, kdx);
+ jcc(Assembler::zero, L_second_loop);
+
+ Label L_carry;
+ subl(kdx, 1);
+ jcc(Assembler::zero, L_carry);
+
+ movl(Address(z, kdx, Address::times_4, 0), carry);
+ shrq(carry, 32);
+ subl(kdx, 1);
+
+ bind(L_carry);
+ movl(Address(z, kdx, Address::times_4, 0), carry);
+
+ // Second and third (nested) loops.
+ //
+ // for (int i = xstart-1; i >= 0; i--) { // Second loop
+ // carry = 0;
+ // for (int jdx=ystart, k=ystart+1+i; jdx >= 0; jdx--, k--) { // Third loop
+ // long product = (y[jdx] & LONG_MASK) * (x[i] & LONG_MASK) +
+ // (z[k] & LONG_MASK) + carry;
+ // z[k] = (int)product;
+ // carry = product >>> 32;
+ // }
+ // z[i] = (int)carry;
+ // }
+ //
+ // i = xlen, j = tmp1, k = tmp2, carry = tmp5, x[i] = rdx
+
+ const Register jdx = tmp1;
+
+ bind(L_second_loop);
+ xorl(carry, carry); // carry = 0;
+ movl(jdx, ylen); // j = ystart+1
+
+ subl(xstart, 1); // i = xstart-1;
+ jcc(Assembler::negative, L_done);
+
+ push (z);
+
+ Label L_last_x;
+ lea(z, Address(z, xstart, Address::times_4, 4)); // z = z + k - j
+ subl(xstart, 1); // i = xstart-1;
+ jcc(Assembler::negative, L_last_x);
+
+ if (UseBMI2Instructions) {
+ movq(rdx, Address(x, xstart, Address::times_4, 0));
+ rorxq(rdx, rdx, 32); // convert big-endian to little-endian
+ } else {
+ movq(x_xstart, Address(x, xstart, Address::times_4, 0));
+ rorq(x_xstart, 32); // convert big-endian to little-endian
+ }
+
+ Label L_third_loop_prologue;
+ bind(L_third_loop_prologue);
+
+ push (x);
+ push (xstart);
+ push (ylen);
+
+
+ if (UseBMI2Instructions) {
+ multiply_128_x_128_bmi2_loop(y, z, carry, x, jdx, ylen, product, tmp2, x_xstart, tmp3, tmp4);
+ } else { // !UseBMI2Instructions
+ multiply_128_x_128_loop(x_xstart, y, z, y_idx, jdx, ylen, carry, product, x);
+ }
+
+ pop(ylen);
+ pop(xlen);
+ pop(x);
+ pop(z);
+
+ movl(tmp3, xlen);
+ addl(tmp3, 1);
+ movl(Address(z, tmp3, Address::times_4, 0), carry);
+ subl(tmp3, 1);
+ jccb(Assembler::negative, L_done);
+
+ shrq(carry, 32);
+ movl(Address(z, tmp3, Address::times_4, 0), carry);
+ jmp(L_second_loop);
+
+ // Next infrequent code is moved outside loops.
+ bind(L_last_x);
+ if (UseBMI2Instructions) {
+ movl(rdx, Address(x, 0));
+ } else {
+ movl(x_xstart, Address(x, 0));
+ }
+ jmp(L_third_loop_prologue);
+
+ bind(L_done);
+
+ pop(zlen);
+ pop(xlen);
+
+ pop(tmp5);
+ pop(tmp4);
+ pop(tmp3);
+ pop(tmp2);
+ pop(tmp1);
+}
+#endif
+
/**
* Emits code to update CRC-32 with a byte value according to constants in table
*
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -1221,6 +1221,28 @@
XMMRegister tmp1, XMMRegister tmp2, XMMRegister tmp3,
XMMRegister tmp4, Register tmp5, Register result);
+#ifdef _LP64
+ void add2_with_carry(Register dest_hi, Register dest_lo, Register src1, Register src2);
+ void multiply_64_x_64_loop(Register x, Register xstart, Register x_xstart,
+ Register y, Register y_idx, Register z,
+ Register carry, Register product,
+ Register idx, Register kdx);
+ void multiply_add_128_x_128(Register x_xstart, Register y, Register z,
+ Register yz_idx, Register idx,
+ Register carry, Register product, int offset);
+ void multiply_128_x_128_bmi2_loop(Register y, Register z,
+ Register carry, Register carry2,
+ Register idx, Register jdx,
+ Register yz_idx1, Register yz_idx2,
+ Register tmp, Register tmp3, Register tmp4);
+ void multiply_128_x_128_loop(Register x_xstart, Register y, Register z,
+ Register yz_idx, Register idx, Register jdx,
+ Register carry, Register product,
+ Register carry2);
+ void multiply_to_len(Register x, Register xlen, Register y, Register ylen, Register z, Register zlen,
+ Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5);
+#endif
+
// CRC32 code for java.util.zip.CRC32::updateBytes() instrinsic.
void update_byte_crc32(Register crc, Register val, Register table);
void kernel_crc32(Register crc, Register buf, Register len, Register table, Register tmp);
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -3677,6 +3677,70 @@
return start;
}
+
+ /**
+ * Arguments:
+ *
+ * Input:
+ * c_rarg0 - x address
+ * c_rarg1 - x length
+ * c_rarg2 - y address
+ * c_rarg3 - y lenth
+ * not Win64
+ * c_rarg4 - z address
+ * c_rarg5 - z length
+ * Win64
+ * rsp+40 - z address
+ * rsp+48 - z length
+ */
+ address generate_multiplyToLen() {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "multiplyToLen");
+
+ address start = __ pc();
+ // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
+ // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
+ const Register x = rdi;
+ const Register xlen = rax;
+ const Register y = rsi;
+ const Register ylen = rcx;
+ const Register z = r8;
+ const Register zlen = r11;
+
+ // Next registers will be saved on stack in multiply_to_len().
+ const Register tmp1 = r12;
+ const Register tmp2 = r13;
+ const Register tmp3 = r14;
+ const Register tmp4 = r15;
+ const Register tmp5 = rbx;
+
+ BLOCK_COMMENT("Entry:");
+ __ enter(); // required for proper stackwalking of RuntimeStub frame
+
+#ifndef _WIN64
+ __ movptr(zlen, r9); // Save r9 in r11 - zlen
+#endif
+ setup_arg_regs(4); // x => rdi, xlen => rsi, y => rdx
+ // ylen => rcx, z => r8, zlen => r11
+ // r9 and r10 may be used to save non-volatile registers
+#ifdef _WIN64
+ // last 2 arguments (#4, #5) are on stack on Win64
+ __ movptr(z, Address(rsp, 6 * wordSize));
+ __ movptr(zlen, Address(rsp, 7 * wordSize));
+#endif
+
+ __ movptr(xlen, rsi);
+ __ movptr(y, rdx);
+ __ multiply_to_len(x, xlen, y, ylen, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5);
+
+ restore_arg_regs();
+
+ __ leave(); // required for proper stackwalking of RuntimeStub frame
+ __ ret(0);
+
+ return start;
+ }
+
#undef __
#define __ masm->
@@ -3917,6 +3981,11 @@
generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry,
&StubRoutines::_safefetchN_fault_pc,
&StubRoutines::_safefetchN_continuation_pc);
+#ifdef COMPILER2
+ if (UseMultiplyToLenIntrinsic) {
+ StubRoutines::_multiplyToLen = generate_multiplyToLen();
+ }
+#endif
}
public:
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -485,7 +485,7 @@
}
char buf[256];
- jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
cores_per_cpu(), threads_per_core(),
cpu_family(), _model, _stepping,
(supports_cmov() ? ", cmov" : ""),
@@ -514,7 +514,8 @@
(supports_tscinv_bit() ? ", tscinvbit": ""),
(supports_tscinv() ? ", tscinv": ""),
(supports_bmi1() ? ", bmi1" : ""),
- (supports_bmi2() ? ", bmi2" : ""));
+ (supports_bmi2() ? ", bmi2" : ""),
+ (supports_adx() ? ", adx" : ""));
_features_str = os::strdup(buf);
// UseSSE is set to the smaller of what hardware supports and what
@@ -566,7 +567,7 @@
}
} else if (UseCRC32Intrinsics) {
if (!FLAG_IS_DEFAULT(UseCRC32Intrinsics))
- warning("CRC32 Intrinsics requires AVX and CLMUL instructions (not available on this CPU)");
+ warning("CRC32 Intrinsics requires CLMUL instructions (not available on this CPU)");
FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
}
@@ -689,7 +690,20 @@
}
#endif
}
+
+#ifdef _LP64
+ if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
+ UseMultiplyToLenIntrinsic = true;
+ }
+#else
+ if (UseMultiplyToLenIntrinsic) {
+ if (!FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
+ warning("multiplyToLen intrinsic is not available in 32-bit VM");
+ }
+ FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false);
+ }
#endif
+#endif // COMPILER2
// On new cpus instructions which update whole XMM register should be used
// to prevent partial register stall due to dependencies on high half.
@@ -832,6 +846,9 @@
}
}
}
+ if(FLAG_IS_DEFAULT(AllocatePrefetchInstr) && supports_3dnow_prefetch()) {
+ AllocatePrefetchInstr = 3;
+ }
}
// Use count leading zeros count instruction if available.
@@ -844,23 +861,35 @@
FLAG_SET_DEFAULT(UseCountLeadingZerosInstruction, false);
}
+ // Use count trailing zeros instruction if available
if (supports_bmi1()) {
+ // tzcnt does not require VEX prefix
+ if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstruction)) {
+ UseCountTrailingZerosInstruction = true;
+ }
+ } else if (UseCountTrailingZerosInstruction) {
+ warning("tzcnt instruction is not available on this CPU");
+ FLAG_SET_DEFAULT(UseCountTrailingZerosInstruction, false);
+ }
+
+ // BMI instructions use an encoding with VEX prefix.
+ // VEX prefix is generated only when AVX > 0.
+ if (supports_bmi1() && supports_avx()) {
if (FLAG_IS_DEFAULT(UseBMI1Instructions)) {
UseBMI1Instructions = true;
}
} else if (UseBMI1Instructions) {
- warning("BMI1 instructions are not available on this CPU");
+ warning("BMI1 instructions are not available on this CPU (AVX is also required)");
FLAG_SET_DEFAULT(UseBMI1Instructions, false);
}
- // Use count trailing zeros instruction if available
- if (supports_bmi1()) {
- if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstruction)) {
- UseCountTrailingZerosInstruction = UseBMI1Instructions;
+ if (supports_bmi2() && supports_avx()) {
+ if (FLAG_IS_DEFAULT(UseBMI2Instructions)) {
+ UseBMI2Instructions = true;
}
- } else if (UseCountTrailingZerosInstruction) {
- warning("tzcnt instruction is not available on this CPU");
- FLAG_SET_DEFAULT(UseCountTrailingZerosInstruction, false);
+ } else if (UseBMI2Instructions) {
+ warning("BMI2 instructions are not available on this CPU (AVX is also required)");
+ FLAG_SET_DEFAULT(UseBMI2Instructions, false);
}
// Use population count instruction if available.
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -209,7 +209,9 @@
erms : 1,
: 1,
rtm : 1,
- : 20;
+ : 7,
+ adx : 1,
+ : 12;
} bits;
};
@@ -260,7 +262,8 @@
CPU_CLMUL = (1 << 21), // carryless multiply for CRC
CPU_BMI1 = (1 << 22),
CPU_BMI2 = (1 << 23),
- CPU_RTM = (1 << 24) // Restricted Transactional Memory instructions
+ CPU_RTM = (1 << 24), // Restricted Transactional Memory instructions
+ CPU_ADX = (1 << 25)
} cpuFeatureFlags;
enum {
@@ -465,10 +468,16 @@
}
// Intel features.
if(is_intel()) {
+ if(_cpuid_info.sef_cpuid7_ebx.bits.adx != 0)
+ result |= CPU_ADX;
if(_cpuid_info.sef_cpuid7_ebx.bits.bmi2 != 0)
result |= CPU_BMI2;
if(_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0)
result |= CPU_LZCNT;
+ // for Intel, ecx.bits.misalignsse bit (bit 8) indicates support for prefetchw
+ if (_cpuid_info.ext_cpuid1_ecx.bits.misalignsse != 0) {
+ result |= CPU_3DNOW_PREFETCH;
+ }
}
return result;
@@ -625,6 +634,7 @@
static bool supports_rtm() { return (_cpuFeatures & CPU_RTM) != 0; }
static bool supports_bmi1() { return (_cpuFeatures & CPU_BMI1) != 0; }
static bool supports_bmi2() { return (_cpuFeatures & CPU_BMI2) != 0; }
+ static bool supports_adx() { return (_cpuFeatures & CPU_ADX) != 0; }
// Intel features
static bool is_intel_family_core() { return is_intel() &&
extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
--- a/hotspot/src/share/vm/asm/codeBuffer.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/asm/codeBuffer.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -134,6 +134,10 @@
// free any overflow storage
delete _overflow_arena;
+ // Claim is that stack allocation ensures resources are cleaned up.
+ // This is resource clean up, let's hope that all were properly copied out.
+ free_strings();
+
#ifdef ASSERT
// Save allocation type to execute assert in ~ResourceObj()
// which is called after this destructor.
@@ -705,7 +709,7 @@
relocate_code_to(&dest);
// transfer strings and comments from buffer to blob
- dest_blob->set_strings(_strings);
+ dest_blob->set_strings(_code_strings);
// Done moving code bytes; were they the right size?
assert(round_to(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity");
@@ -1005,11 +1009,11 @@
void CodeBuffer::block_comment(intptr_t offset, const char * comment) {
- _strings.add_comment(offset, comment);
+ _code_strings.add_comment(offset, comment);
}
const char* CodeBuffer::code_string(const char* str) {
- return _strings.add_string(str);
+ return _code_strings.add_string(str);
}
class CodeString: public CHeapObj<mtCode> {
@@ -1075,6 +1079,7 @@
}
void CodeStrings::add_comment(intptr_t offset, const char * comment) {
+ check_valid();
CodeString* c = new CodeString(comment, offset);
CodeString* inspos = (_strings == NULL) ? NULL : find_last(offset);
@@ -1090,11 +1095,32 @@
}
void CodeStrings::assign(CodeStrings& other) {
+ other.check_valid();
+ // Cannot do following because CodeStrings constructor is not alway run!
+ assert(is_null(), "Cannot assign onto non-empty CodeStrings");
_strings = other._strings;
+ other.set_null_and_invalidate();
+}
+
+// Deep copy of CodeStrings for consistent memory management.
+// Only used for actual disassembly so this is cheaper than reference counting
+// for the "normal" fastdebug case.
+void CodeStrings::copy(CodeStrings& other) {
+ other.check_valid();
+ check_valid();
+ assert(is_null(), "Cannot copy onto non-empty CodeStrings");
+ CodeString* n = other._strings;
+ CodeString** ps = &_strings;
+ while (n != NULL) {
+ *ps = new CodeString(n->string(),n->offset());
+ ps = &((*ps)->_next);
+ n = n->next();
+ }
}
void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) const {
- if (_strings != NULL) {
+ check_valid();
+ if (_strings != NULL) {
CodeString* c = find(offset);
while (c && c->offset() == offset) {
stream->bol();
@@ -1105,7 +1131,7 @@
}
}
-
+// Also sets isNull()
void CodeStrings::free() {
CodeString* n = _strings;
while (n) {
@@ -1115,10 +1141,11 @@
delete n;
n = p;
}
- _strings = NULL;
+ set_null_and_invalidate();
}
const char* CodeStrings::add_string(const char * string) {
+ check_valid();
CodeString* s = new CodeString(string);
s->set_next(_strings);
_strings = s;
--- a/hotspot/src/share/vm/asm/codeBuffer.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/asm/codeBuffer.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -27,6 +27,7 @@
#include "code/oopRecorder.hpp"
#include "code/relocInfo.hpp"
+#include "utilities/debug.hpp"
class CodeStrings;
class PhaseCFG;
@@ -245,15 +246,39 @@
private:
#ifndef PRODUCT
CodeString* _strings;
+#ifdef ASSERT
+ // Becomes true after copy-out, forbids further use.
+ bool _defunct; // Zero bit pattern is "valid", see memset call in decode_env::decode_env
+#endif
#endif
CodeString* find(intptr_t offset) const;
CodeString* find_last(intptr_t offset) const;
+ void set_null_and_invalidate() {
+#ifndef PRODUCT
+ _strings = NULL;
+#ifdef ASSERT
+ _defunct = true;
+#endif
+#endif
+ }
+
public:
CodeStrings() {
#ifndef PRODUCT
_strings = NULL;
+#ifdef ASSERT
+ _defunct = false;
+#endif
+#endif
+ }
+
+ bool is_null() {
+#ifdef ASSERT
+ return _strings == NULL;
+#else
+ return true;
#endif
}
@@ -261,8 +286,17 @@
void add_comment(intptr_t offset, const char * comment) PRODUCT_RETURN;
void print_block_comment(outputStream* stream, intptr_t offset) const PRODUCT_RETURN;
+ // MOVE strings from other to this; invalidate other.
void assign(CodeStrings& other) PRODUCT_RETURN;
+ // COPY strings from other to this; leave other valid.
+ void copy(CodeStrings& other) PRODUCT_RETURN;
void free() PRODUCT_RETURN;
+ // Guarantee that _strings are used at most once; assign invalidates a buffer.
+ inline void check_valid() const {
+#ifdef ASSERT
+ assert(!_defunct, "Use of invalid CodeStrings");
+#endif
+ }
};
// A CodeBuffer describes a memory space into which assembly
@@ -330,7 +364,7 @@
csize_t _total_size; // size in bytes of combined memory buffer
OopRecorder* _oop_recorder;
- CodeStrings _strings;
+ CodeStrings _code_strings;
OopRecorder _default_oop_recorder; // override with initialize_oop_recorder
Arena* _overflow_arena;
@@ -531,7 +565,13 @@
void initialize_oop_recorder(OopRecorder* r);
OopRecorder* oop_recorder() const { return _oop_recorder; }
- CodeStrings& strings() { return _strings; }
+ CodeStrings& strings() { return _code_strings; }
+
+ void free_strings() {
+ if (!_code_strings.is_null()) {
+ _code_strings.free(); // sets _strings Null as a side-effect.
+ }
+ }
// Code generation
void relocate(address at, RelocationHolder const& rspec, int format = 0) {
--- a/hotspot/src/share/vm/asm/register.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/asm/register.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -275,4 +275,101 @@
);
}
+inline void assert_different_registers(
+ AbstractRegister a,
+ AbstractRegister b,
+ AbstractRegister c,
+ AbstractRegister d,
+ AbstractRegister e,
+ AbstractRegister f,
+ AbstractRegister g,
+ AbstractRegister h,
+ AbstractRegister i,
+ AbstractRegister j
+) {
+ assert(
+ a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j
+ && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j
+ && c != d && c != e && c != f && c != g && c != h && c != i && c != j
+ && d != e && d != f && d != g && d != h && d != i && d != j
+ && e != f && e != g && e != h && e != i && e != j
+ && f != g && f != h && f != i && f != j
+ && g != h && g != i && g != j
+ && h != i && h != j
+ && i != j,
+ err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
+ ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
+ ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT
+ ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT "",
+ p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j))
+ );
+}
+
+inline void assert_different_registers(
+ AbstractRegister a,
+ AbstractRegister b,
+ AbstractRegister c,
+ AbstractRegister d,
+ AbstractRegister e,
+ AbstractRegister f,
+ AbstractRegister g,
+ AbstractRegister h,
+ AbstractRegister i,
+ AbstractRegister j,
+ AbstractRegister k
+) {
+ assert(
+ a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j && a !=k
+ && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j && b !=k
+ && c != d && c != e && c != f && c != g && c != h && c != i && c != j && c !=k
+ && d != e && d != f && d != g && d != h && d != i && d != j && d !=k
+ && e != f && e != g && e != h && e != i && e != j && e !=k
+ && f != g && f != h && f != i && f != j && f !=k
+ && g != h && g != i && g != j && g !=k
+ && h != i && h != j && h !=k
+ && i != j && i !=k
+ && j !=k,
+ err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
+ ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
+ ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT
+ ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT ", k=" INTPTR_FORMAT "",
+ p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j), p2i(k))
+ );
+}
+
+inline void assert_different_registers(
+ AbstractRegister a,
+ AbstractRegister b,
+ AbstractRegister c,
+ AbstractRegister d,
+ AbstractRegister e,
+ AbstractRegister f,
+ AbstractRegister g,
+ AbstractRegister h,
+ AbstractRegister i,
+ AbstractRegister j,
+ AbstractRegister k,
+ AbstractRegister l
+) {
+ assert(
+ a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j && a !=k && a !=l
+ && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j && b !=k && b !=l
+ && c != d && c != e && c != f && c != g && c != h && c != i && c != j && c !=k && c !=l
+ && d != e && d != f && d != g && d != h && d != i && d != j && d !=k && d !=l
+ && e != f && e != g && e != h && e != i && e != j && e !=k && e !=l
+ && f != g && f != h && f != i && f != j && f !=k && f !=l
+ && g != h && g != i && g != j && g !=k && g !=l
+ && h != i && h != j && h !=k && h !=l
+ && i != j && i !=k && i !=l
+ && j !=k && j !=l
+ && k !=l,
+ err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
+ ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
+ ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT
+ ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT ", k=" INTPTR_FORMAT
+ ", l=" INTPTR_FORMAT "",
+ p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j), p2i(k), p2i(l))
+ );
+}
+
#endif // SHARE_VM_ASM_REGISTER_HPP
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -1102,6 +1102,22 @@
}
// ------------------------------------------------------------------
+// ciMethod::has_option_value
+//
+template<typename T>
+bool ciMethod::has_option_value(const char* option, T& value) {
+ check_is_loaded();
+ VM_ENTRY_MARK;
+ methodHandle mh(THREAD, get_Method());
+ return CompilerOracle::has_option_value(mh, option, value);
+}
+// Explicit instantiation for all OptionTypes supported.
+template bool ciMethod::has_option_value<intx>(const char* option, intx& value);
+template bool ciMethod::has_option_value<uintx>(const char* option, uintx& value);
+template bool ciMethod::has_option_value<bool>(const char* option, bool& value);
+template bool ciMethod::has_option_value<ccstr>(const char* option, ccstr& value);
+
+// ------------------------------------------------------------------
// ciMethod::can_be_compiled
//
// Have previous compilations of this method succeeded?
--- a/hotspot/src/share/vm/ci/ciMethod.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -269,6 +269,8 @@
bool should_print_assembly();
bool break_at_execute();
bool has_option(const char *option);
+ template<typename T>
+ bool has_option_value(const char* option, T& value);
bool can_be_compiled();
bool can_be_osr_compiled(int entry_bci);
void set_not_compilable(const char* reason = NULL);
--- a/hotspot/src/share/vm/ci/ciMethodData.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/ci/ciMethodData.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -81,19 +81,38 @@
void ciMethodData::load_extra_data() {
MethodData* mdo = get_MethodData();
+ MutexLocker(mdo->extra_data_lock());
+
// speculative trap entries also hold a pointer to a Method so need to be translated
DataLayout* dp_src = mdo->extra_data_base();
- DataLayout* end_src = mdo->extra_data_limit();
+ DataLayout* end_src = mdo->args_data_limit();
DataLayout* dp_dst = extra_data_base();
for (;; dp_src = MethodData::next_extra(dp_src), dp_dst = MethodData::next_extra(dp_dst)) {
assert(dp_src < end_src, "moved past end of extra data");
- // New traps in the MDO can be added as we translate the copy so
- // look at the entries in the copy.
- switch(dp_dst->tag()) {
+ assert(((intptr_t)dp_dst) - ((intptr_t)extra_data_base()) == ((intptr_t)dp_src) - ((intptr_t)mdo->extra_data_base()), "source and destination don't match");
+
+ // New traps in the MDO may have been added since we copied the
+ // data (concurrent deoptimizations before we acquired
+ // extra_data_lock above) or can be removed (a safepoint may occur
+ // in the translate_from call below) as we translate the copy:
+ // update the copy as we go.
+ int tag = dp_src->tag();
+ if (tag != DataLayout::arg_info_data_tag) {
+ memcpy(dp_dst, dp_src, ((intptr_t)MethodData::next_extra(dp_src)) - ((intptr_t)dp_src));
+ }
+
+ switch(tag) {
case DataLayout::speculative_trap_data_tag: {
ciSpeculativeTrapData* data_dst = new ciSpeculativeTrapData(dp_dst);
SpeculativeTrapData* data_src = new SpeculativeTrapData(dp_src);
+
data_dst->translate_from(data_src);
+
+#ifdef ASSERT
+ SpeculativeTrapData* data_src2 = new SpeculativeTrapData(dp_src);
+ assert(data_src2->method() == data_src->method() && data_src2->bci() == data_src->bci(), "entries changed while translating");
+#endif
+
break;
}
case DataLayout::bit_data_tag:
@@ -244,8 +263,8 @@
}
ciProfileData* ciMethodData::bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots) {
- DataLayout* dp = data_layout_at(data_size());
- DataLayout* end = data_layout_at(data_size() + extra_data_size());
+ DataLayout* dp = extra_data_base();
+ DataLayout* end = args_data_limit();
two_free_slots = false;
for (;dp < end; dp = MethodData::next_extra(dp)) {
switch(dp->tag()) {
@@ -492,8 +511,8 @@
ciArgInfoData *ciMethodData::arg_info() const {
// Should be last, have to skip all traps.
- DataLayout* dp = data_layout_at(data_size());
- DataLayout* end = data_layout_at(data_size() + extra_data_size());
+ DataLayout* dp = extra_data_base();
+ DataLayout* end = args_data_limit();
for (; dp < end; dp = MethodData::next_extra(dp)) {
if (dp->tag() == DataLayout::arg_info_data_tag)
return new ciArgInfoData(dp);
@@ -535,8 +554,8 @@
}
void ciMethodData::dump_replay_data_extra_data_helper(outputStream* out, int round, int& count) {
- DataLayout* dp = data_layout_at(data_size());
- DataLayout* end = data_layout_at(data_size() + extra_data_size());
+ DataLayout* dp = extra_data_base();
+ DataLayout* end = args_data_limit();
for (;dp < end; dp = MethodData::next_extra(dp)) {
switch(dp->tag()) {
@@ -653,8 +672,8 @@
data->print_data_on(st);
}
st->print_cr("--- Extra data:");
- DataLayout* dp = data_layout_at(data_size());
- DataLayout* end = data_layout_at(data_size() + extra_data_size());
+ DataLayout* dp = extra_data_base();
+ DataLayout* end = args_data_limit();
for (;; dp = MethodData::next_extra(dp)) {
assert(dp < end, "moved past end of extra data");
switch (dp->tag()) {
--- a/hotspot/src/share/vm/ci/ciMethodData.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/ci/ciMethodData.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -410,6 +410,9 @@
// Area dedicated to parameters. NULL if no parameter profiling for
// this method.
DataLayout* _parameters;
+ int parameters_size() const {
+ return _parameters == NULL ? 0 : parameters_type_data()->size_in_bytes();
+ }
ciMethodData(MethodData* md);
ciMethodData();
@@ -461,9 +464,6 @@
address data_base() const {
return (address) _data;
}
- DataLayout* limit_data_position() const {
- return (DataLayout*)((address)data_base() + _data_size);
- }
void load_extra_data();
ciProfileData* bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots);
@@ -524,7 +524,9 @@
ciProfileData* next_data(ciProfileData* current);
bool is_valid(ciProfileData* current) { return current != NULL; }
- DataLayout* extra_data_base() const { return limit_data_position(); }
+ DataLayout* extra_data_base() const { return data_layout_at(data_size()); }
+ DataLayout* args_data_limit() const { return data_layout_at(data_size() + extra_data_size() -
+ parameters_size()); }
// Get the data at an arbitrary bci, or NULL if there is none. If m
// is not NULL look for a SpeculativeTrapData if any first.
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -332,27 +332,6 @@
}
}
-#ifdef ASSERT
-class AllAliveClosure : public OopClosure {
- BoolObjectClosure* _is_alive_closure;
- bool _found_dead;
- public:
- AllAliveClosure(BoolObjectClosure* is_alive_closure) : _is_alive_closure(is_alive_closure), _found_dead(false) {}
- template <typename T> void do_oop_work(T* p) {
- T heap_oop = oopDesc::load_heap_oop(p);
- if (!oopDesc::is_null(heap_oop)) {
- oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
- if (!_is_alive_closure->do_object_b(obj)) {
- _found_dead = true;
- }
- }
- }
- void do_oop(oop* p) { do_oop_work<oop>(p); }
- void do_oop(narrowOop* p) { do_oop_work<narrowOop>(p); }
- bool found_dead() { return _found_dead; }
-};
-#endif
-
oop ClassLoaderData::keep_alive_object() const {
assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
return is_anonymous() ? _klasses->java_mirror() : class_loader();
@@ -362,15 +341,6 @@
bool alive = keep_alive() // null class loader and incomplete anonymous klasses.
|| is_alive_closure->do_object_b(keep_alive_object());
-#ifdef ASSERT
- if (alive) {
- AllAliveClosure all_alive_closure(is_alive_closure);
- KlassToOopClosure klass_closure(&all_alive_closure);
- const_cast<ClassLoaderData*>(this)->oops_do(&all_alive_closure, &klass_closure, false);
- assert(!all_alive_closure.found_dead(), err_msg("Found dead oop in alive cld: " PTR_FORMAT, p2i(this)));
- }
-#endif
-
return alive;
}
--- a/hotspot/src/share/vm/classfile/stringTable.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/classfile/stringTable.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -109,7 +109,7 @@
}
}
// If the bucket size is too deep check if this hash code is insufficient.
- if (count >= BasicHashtable<mtSymbol>::rehash_count && !needs_rehashing()) {
+ if (count >= rehash_count && !needs_rehashing()) {
_needs_rehashing = check_rehash_table(count);
}
return NULL;
--- a/hotspot/src/share/vm/classfile/stringTable.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/classfile/stringTable.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -28,7 +28,7 @@
#include "memory/allocation.inline.hpp"
#include "utilities/hashtable.hpp"
-class StringTable : public Hashtable<oop, mtSymbol> {
+class StringTable : public RehashableHashtable<oop, mtSymbol> {
friend class VMStructs;
friend class Symbol;
@@ -55,11 +55,11 @@
// in the range [start_idx, end_idx).
static void buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, int* processed, int* removed);
- StringTable() : Hashtable<oop, mtSymbol>((int)StringTableSize,
+ StringTable() : RehashableHashtable<oop, mtSymbol>((int)StringTableSize,
sizeof (HashtableEntry<oop, mtSymbol>)) {}
StringTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
- : Hashtable<oop, mtSymbol>((int)StringTableSize, sizeof (HashtableEntry<oop, mtSymbol>), t,
+ : RehashableHashtable<oop, mtSymbol>((int)StringTableSize, sizeof (HashtableEntry<oop, mtSymbol>), t,
number_of_entries) {}
public:
// The string table
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -201,7 +201,7 @@
}
}
// If the bucket size is too deep check if this hash code is insufficient.
- if (count >= BasicHashtable<mtSymbol>::rehash_count && !needs_rehashing()) {
+ if (count >= rehash_count && !needs_rehashing()) {
_needs_rehashing = check_rehash_table(count);
}
return NULL;
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/classfile/symbolTable.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -73,7 +73,7 @@
operator Symbol*() { return _temp; }
};
-class SymbolTable : public Hashtable<Symbol*, mtSymbol> {
+class SymbolTable : public RehashableHashtable<Symbol*, mtSymbol> {
friend class VMStructs;
friend class ClassFileParser;
@@ -109,10 +109,10 @@
Symbol* lookup(int index, const char* name, int len, unsigned int hash);
SymbolTable()
- : Hashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {}
+ : RehashableHashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {}
SymbolTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
- : Hashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
+ : RehashableHashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
number_of_entries) {}
// Arena for permanent symbols (null class loader) that are never unloaded
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -785,6 +785,11 @@
do_name( encodeISOArray_name, "encodeISOArray") \
do_signature(encodeISOArray_signature, "([CI[BII)I") \
\
+ do_class(java_math_BigInteger, "java/math/BigInteger") \
+ do_intrinsic(_multiplyToLen, java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_R) \
+ do_name( multiplyToLen_name, "multiplyToLen") \
+ do_signature(multiplyToLen_signature, "([II[II[I)[I") \
+ \
/* java/lang/ref/Reference */ \
do_intrinsic(_Reference_get, java_lang_ref_Reference, get_name, void_object_signature, F_R) \
\
--- a/hotspot/src/share/vm/code/codeBlob.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/code/codeBlob.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -238,6 +238,7 @@
void BufferBlob::free( BufferBlob *blob ) {
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
+ blob->flush();
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
CodeCache::free((CodeBlob*)blob);
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -168,48 +168,134 @@
}
}
+enum OptionType {
+ IntxType,
+ UintxType,
+ BoolType,
+ CcstrType,
+ UnknownType
+};
-class MethodOptionMatcher: public MethodMatcher {
- const char * option;
- public:
- MethodOptionMatcher(Symbol* class_name, Mode class_mode,
- Symbol* method_name, Mode method_mode,
- Symbol* signature, const char * opt, MethodMatcher* next):
- MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next) {
- option = os::strdup_check_oom(opt);
+/* Methods to map real type names to OptionType */
+template<typename T>
+static OptionType get_type_for() {
+ return UnknownType;
+};
+
+template<> OptionType get_type_for<intx>() {
+ return IntxType;
+}
+
+template<> OptionType get_type_for<uintx>() {
+ return UintxType;
+}
+
+template<> OptionType get_type_for<bool>() {
+ return BoolType;
+}
+
+template<> OptionType get_type_for<ccstr>() {
+ return CcstrType;
+}
+
+template<typename T>
+static const T copy_value(const T value) {
+ return value;
+}
+
+template<> const ccstr copy_value<ccstr>(const ccstr value) {
+ return (const ccstr)os::strdup_check_oom(value);
+}
+
+template <typename T>
+class TypedMethodOptionMatcher : public MethodMatcher {
+ const char* _option;
+ OptionType _type;
+ const T _value;
+
+public:
+ TypedMethodOptionMatcher(Symbol* class_name, Mode class_mode,
+ Symbol* method_name, Mode method_mode,
+ Symbol* signature, const char* opt,
+ const T value, MethodMatcher* next) :
+ MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next),
+ _type(get_type_for<T>()), _value(copy_value<T>(value)) {
+ _option = os::strdup_check_oom(opt);
}
- virtual ~MethodOptionMatcher() {
- os::free((void*)option);
+ ~TypedMethodOptionMatcher() {
+ os::free((void*)_option);
}
- bool match(methodHandle method, const char* opt) {
- MethodOptionMatcher* current = this;
+ TypedMethodOptionMatcher* match(methodHandle method, const char* opt) {
+ TypedMethodOptionMatcher* current = this;
while (current != NULL) {
- current = (MethodOptionMatcher*)current->find(method);
+ current = (TypedMethodOptionMatcher*)current->find(method);
if (current == NULL) {
- return false;
+ return NULL;
}
- if (strcmp(current->option, opt) == 0) {
- return true;
+ if (strcmp(current->_option, opt) == 0) {
+ return current;
}
current = current->next();
}
- return false;
+ return NULL;
+ }
+
+ TypedMethodOptionMatcher* next() {
+ return (TypedMethodOptionMatcher*)_next;
}
- MethodOptionMatcher* next() {
- return (MethodOptionMatcher*)_next;
- }
+ OptionType get_type(void) {
+ return _type;
+ };
+
+ T value() { return _value; }
- virtual void print() {
+ void print() {
+ ttyLocker ttyl;
print_base();
- tty->print(" %s", option);
+ tty->print(" %s", _option);
+ tty->print(" <unknown option type>");
tty->cr();
}
};
+template<>
+void TypedMethodOptionMatcher<intx>::print() {
+ ttyLocker ttyl;
+ print_base();
+ tty->print(" intx %s", _option);
+ tty->print(" = " INTX_FORMAT, _value);
+ tty->cr();
+};
+template<>
+void TypedMethodOptionMatcher<uintx>::print() {
+ ttyLocker ttyl;
+ print_base();
+ tty->print(" uintx %s", _option);
+ tty->print(" = " UINTX_FORMAT, _value);
+ tty->cr();
+};
+
+template<>
+void TypedMethodOptionMatcher<bool>::print() {
+ ttyLocker ttyl;
+ print_base();
+ tty->print(" bool %s", _option);
+ tty->print(" = %s", _value ? "true" : "false");
+ tty->cr();
+};
+
+template<>
+void TypedMethodOptionMatcher<ccstr>::print() {
+ ttyLocker ttyl;
+ print_base();
+ tty->print(" const char* %s", _option);
+ tty->print(" = '%s'", _value);
+ tty->cr();
+};
// this must parallel the command_names below
enum OracleCommand {
@@ -264,23 +350,46 @@
return lists[command];
}
-
-
+template<typename T>
static MethodMatcher* add_option_string(Symbol* class_name, MethodMatcher::Mode c_mode,
Symbol* method_name, MethodMatcher::Mode m_mode,
Symbol* signature,
- const char* option) {
- lists[OptionCommand] = new MethodOptionMatcher(class_name, c_mode, method_name, m_mode,
- signature, option, lists[OptionCommand]);
+ const char* option,
+ T value) {
+ lists[OptionCommand] = new TypedMethodOptionMatcher<T>(class_name, c_mode, method_name, m_mode,
+ signature, option, value, lists[OptionCommand]);
return lists[OptionCommand];
}
+template<typename T>
+static bool get_option_value(methodHandle method, const char* option, T& value) {
+ TypedMethodOptionMatcher<T>* m;
+ if (lists[OptionCommand] != NULL
+ && (m = ((TypedMethodOptionMatcher<T>*)lists[OptionCommand])->match(method, option)) != NULL
+ && m->get_type() == get_type_for<T>()) {
+ value = m->value();
+ return true;
+ } else {
+ return false;
+ }
+}
bool CompilerOracle::has_option_string(methodHandle method, const char* option) {
- return lists[OptionCommand] != NULL &&
- ((MethodOptionMatcher*)lists[OptionCommand])->match(method, option);
+ bool value = false;
+ get_option_value(method, option, value);
+ return value;
}
+template<typename T>
+bool CompilerOracle::has_option_value(methodHandle method, const char* option, T& value) {
+ return ::get_option_value(method, option, value);
+}
+
+// Explicit instantiation for all OptionTypes supported.
+template bool CompilerOracle::has_option_value<intx>(methodHandle method, const char* option, intx& value);
+template bool CompilerOracle::has_option_value<uintx>(methodHandle method, const char* option, uintx& value);
+template bool CompilerOracle::has_option_value<bool>(methodHandle method, const char* option, bool& value);
+template bool CompilerOracle::has_option_value<ccstr>(methodHandle method, const char* option, ccstr& value);
bool CompilerOracle::should_exclude(methodHandle method, bool& quietly) {
quietly = true;
@@ -422,6 +531,94 @@
+// Scan next flag and value in line, return MethodMatcher object on success, NULL on failure.
+// On failure, error_msg contains description for the first error.
+// For future extensions: set error_msg on first error.
+static MethodMatcher* scan_flag_and_value(const char* type, const char* line, int& total_bytes_read,
+ Symbol* c_name, MethodMatcher::Mode c_match,
+ Symbol* m_name, MethodMatcher::Mode m_match,
+ Symbol* signature,
+ char* errorbuf, const int buf_size) {
+ total_bytes_read = 0;
+ int bytes_read = 0;
+ char flag[256];
+
+ // Read flag name.
+ if (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", flag, &bytes_read) == 1) {
+ line += bytes_read;
+ total_bytes_read += bytes_read;
+
+ // Read value.
+ if (strcmp(type, "intx") == 0) {
+ intx value;
+ if (sscanf(line, "%*[ \t]" INTX_FORMAT "%n", &value, &bytes_read) == 1) {
+ total_bytes_read += bytes_read;
+ return add_option_string(c_name, c_match, m_name, m_match, signature, flag, value);
+ } else {
+ jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s ", flag, type);
+ }
+ } else if (strcmp(type, "uintx") == 0) {
+ uintx value;
+ if (sscanf(line, "%*[ \t]" UINTX_FORMAT "%n", &value, &bytes_read) == 1) {
+ total_bytes_read += bytes_read;
+ return add_option_string(c_name, c_match, m_name, m_match, signature, flag, value);
+ } else {
+ jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
+ }
+ } else if (strcmp(type, "ccstr") == 0) {
+ ResourceMark rm;
+ char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1);
+ if (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", value, &bytes_read) == 1) {
+ total_bytes_read += bytes_read;
+ return add_option_string(c_name, c_match, m_name, m_match, signature, flag, (ccstr)value);
+ } else {
+ jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
+ }
+ } else if (strcmp(type, "ccstrlist") == 0) {
+ // Accumulates several strings into one. The internal type is ccstr.
+ ResourceMark rm;
+ char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1);
+ char* next_value = value;
+ if (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", next_value, &bytes_read) == 1) {
+ total_bytes_read += bytes_read;
+ line += bytes_read;
+ next_value += bytes_read;
+ char* end_value = next_value-1;
+ while (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", next_value, &bytes_read) == 1) {
+ total_bytes_read += bytes_read;
+ line += bytes_read;
+ *end_value = ' '; // override '\0'
+ next_value += bytes_read;
+ end_value = next_value-1;
+ }
+ return add_option_string(c_name, c_match, m_name, m_match, signature, flag, (ccstr)value);
+ } else {
+ jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
+ }
+ } else if (strcmp(type, "bool") == 0) {
+ char value[256];
+ if (sscanf(line, "%*[ \t]%255[a-zA-Z]%n", value, &bytes_read) == 1) {
+ if (strcmp(value, "true") == 0) {
+ total_bytes_read += bytes_read;
+ return add_option_string(c_name, c_match, m_name, m_match, signature, flag, true);
+ } else if (strcmp(value, "false") == 0) {
+ total_bytes_read += bytes_read;
+ return add_option_string(c_name, c_match, m_name, m_match, signature, flag, false);
+ } else {
+ jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
+ }
+ } else {
+ jio_snprintf(errorbuf, sizeof(errorbuf), " Value cannot be read for flag %s of type %s", flag, type);
+ }
+ } else {
+ jio_snprintf(errorbuf, sizeof(errorbuf), " Type %s not supported ", type);
+ }
+ } else {
+ jio_snprintf(errorbuf, sizeof(errorbuf), " Flag name for type %s should be alphanumeric ", type);
+ }
+ return NULL;
+}
+
void CompilerOracle::parse_from_line(char* line) {
if (line[0] == '\0') return;
if (line[0] == '#') return;
@@ -451,8 +648,10 @@
int bytes_read;
OracleCommand command = parse_command_name(line, &bytes_read);
line += bytes_read;
+ ResourceMark rm;
if (command == UnknownCommand) {
+ ttyLocker ttyl;
tty->print_cr("CompilerOracle: unrecognized line");
tty->print_cr(" \"%s\"", original_line);
return;
@@ -474,7 +673,7 @@
char method_name[256];
char sig[1024];
char errorbuf[1024];
- const char* error_msg = NULL;
+ const char* error_msg = NULL; // description of first error that appears
MethodMatcher* match = NULL;
if (scan_line(line, class_name, &c_match, method_name, &m_match, &bytes_read, error_msg)) {
@@ -493,43 +692,77 @@
}
if (command == OptionCommand) {
- // Look for trailing options to support
- // ciMethod::has_option("string") to control features in the
- // compiler. Multiple options may follow the method name.
- char option[256];
+ // Look for trailing options.
+ //
+ // Two types of trailing options are
+ // supported:
+ //
+ // (1) CompileCommand=option,Klass::method,flag
+ // (2) CompileCommand=option,Klass::method,type,flag,value
+ //
+ // Type (1) is used to support ciMethod::has_option("someflag")
+ // (i.e., to check if a flag "someflag" is enabled for a method).
+ //
+ // Type (2) is used to support options with a value. Values can have the
+ // the following types: intx, uintx, bool, ccstr, and ccstrlist.
+ //
+ // For future extensions: extend scan_flag_and_value()
+ char option[256]; // stores flag for Type (1) and type of Type (2)
while (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", option, &bytes_read) == 1) {
if (match != NULL && !_quiet) {
// Print out the last match added
+ ttyLocker ttyl;
tty->print("CompilerOracle: %s ", command_names[command]);
match->print();
}
- match = add_option_string(c_name, c_match, m_name, m_match, signature, option);
line += bytes_read;
- }
+
+ if (strcmp(option, "intx") == 0
+ || strcmp(option, "uintx") == 0
+ || strcmp(option, "bool") == 0
+ || strcmp(option, "ccstr") == 0
+ || strcmp(option, "ccstrlist") == 0
+ ) {
+
+ // Type (2) option: parse flag name and value.
+ match = scan_flag_and_value(option, line, bytes_read,
+ c_name, c_match, m_name, m_match, signature,
+ errorbuf, sizeof(errorbuf));
+ if (match == NULL) {
+ error_msg = errorbuf;
+ break;
+ }
+ line += bytes_read;
+ } else {
+ // Type (1) option
+ match = add_option_string(c_name, c_match, m_name, m_match, signature, option, true);
+ }
+ } // while(
} else {
- bytes_read = 0;
- sscanf(line, "%*[ \t]%n", &bytes_read);
- if (line[bytes_read] != '\0') {
- jio_snprintf(errorbuf, sizeof(errorbuf), " Unrecognized text after command: %s", line);
- error_msg = errorbuf;
- } else {
- match = add_predicate(command, c_name, c_match, m_name, m_match, signature);
- }
+ match = add_predicate(command, c_name, c_match, m_name, m_match, signature);
}
}
- if (match != NULL) {
- if (!_quiet) {
- ResourceMark rm;
- tty->print("CompilerOracle: %s ", command_names[command]);
- match->print();
- }
- } else {
+ ttyLocker ttyl;
+ if (error_msg != NULL) {
+ // an error has happened
tty->print_cr("CompilerOracle: unrecognized line");
tty->print_cr(" \"%s\"", original_line);
if (error_msg != NULL) {
tty->print_cr("%s", error_msg);
}
+ } else {
+ // check for remaining characters
+ bytes_read = 0;
+ sscanf(line, "%*[ \t]%n", &bytes_read);
+ if (line[bytes_read] != '\0') {
+ tty->print_cr("CompilerOracle: unrecognized line");
+ tty->print_cr(" \"%s\"", original_line);
+ tty->print_cr(" Unrecognized text %s after command ", line);
+ } else if (match != NULL && !_quiet) {
+ tty->print("CompilerOracle: %s ", command_names[command]);
+ match->print();
+ }
}
}
--- a/hotspot/src/share/vm/compiler/compilerOracle.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/compiler/compilerOracle.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -64,6 +64,11 @@
// Check to see if this method has option set for it
static bool has_option_string(methodHandle method, const char * option);
+ // Check if method has option and value set. If yes, overwrite value and return true,
+ // otherwise leave value unchanged and return false.
+ template<typename T>
+ static bool has_option_value(methodHandle method, const char* option, T& value);
+
// Reads from string instead of file
static void parse_from_string(const char* command_string, void (*parser)(char*));
--- a/hotspot/src/share/vm/compiler/disassembler.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/compiler/disassembler.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -246,12 +246,12 @@
};
decode_env::decode_env(CodeBlob* code, outputStream* output, CodeStrings c) {
- memset(this, 0, sizeof(*this));
+ memset(this, 0, sizeof(*this)); // Beware, this zeroes bits of fields.
_output = output ? output : tty;
_code = code;
if (code != NULL && code->is_nmethod())
_nm = (nmethod*) code;
- _strings.assign(c);
+ _strings.copy(c);
// by default, output pc but not bytes:
_print_pc = true;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -22,372 +22,375 @@
*
*/
-
#include "precompiled.hpp"
+#include "code/codeCache.hpp"
#include "code/nmethod.hpp"
#include "gc_implementation/g1/g1CodeCacheRemSet.hpp"
+#include "gc_implementation/g1/heapRegion.hpp"
+#include "memory/heap.hpp"
#include "memory/iterator.hpp"
+#include "oops/oop.inline.hpp"
+#include "utilities/hashtable.inline.hpp"
+#include "utilities/stack.inline.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-G1CodeRootChunk::G1CodeRootChunk() : _top(NULL), _next(NULL), _prev(NULL), _free(NULL) {
- _top = bottom();
+class CodeRootSetTable : public Hashtable<nmethod*, mtGC> {
+ friend class G1CodeRootSetTest;
+ typedef HashtableEntry<nmethod*, mtGC> Entry;
+
+ static CodeRootSetTable* volatile _purge_list;
+
+ CodeRootSetTable* _purge_next;
+
+ unsigned int compute_hash(nmethod* nm) {
+ uintptr_t hash = (uintptr_t)nm;
+ return hash ^ (hash >> 7); // code heap blocks are 128byte aligned
+ }
+
+ Entry* new_entry(nmethod* nm);
+
+ public:
+ CodeRootSetTable(int size) : Hashtable<nmethod*, mtGC>(size, sizeof(Entry)), _purge_next(NULL) {}
+ ~CodeRootSetTable();
+
+ // Needs to be protected locks
+ bool add(nmethod* nm);
+ bool remove(nmethod* nm);
+
+ // Can be called without locking
+ bool contains(nmethod* nm);
+
+ int entry_size() const { return BasicHashtable<mtGC>::entry_size(); }
+
+ void copy_to(CodeRootSetTable* new_table);
+ void nmethods_do(CodeBlobClosure* blk);
+
+ template<typename CB>
+ void remove_if(CB& should_remove);
+
+ static void purge_list_append(CodeRootSetTable* tbl);
+ static void purge();
+
+ static size_t static_mem_size() {
+ return sizeof(_purge_list);
+ }
+};
+
+CodeRootSetTable* volatile CodeRootSetTable::_purge_list = NULL;
+
+CodeRootSetTable::Entry* CodeRootSetTable::new_entry(nmethod* nm) {
+ unsigned int hash = compute_hash(nm);
+ Entry* entry = (Entry*) new_entry_free_list();
+ if (entry == NULL) {
+ entry = (Entry*) NEW_C_HEAP_ARRAY2(char, entry_size(), mtGC, CURRENT_PC);
+ }
+ entry->set_next(NULL);
+ entry->set_hash(hash);
+ entry->set_literal(nm);
+ return entry;
}
-void G1CodeRootChunk::reset() {
- _next = _prev = NULL;
- _free = NULL;
- _top = bottom();
-}
-
-void G1CodeRootChunk::nmethods_do(CodeBlobClosure* cl) {
- NmethodOrLink* cur = bottom();
- while (cur != _top) {
- if (is_nmethod(cur)) {
- cl->do_code_blob(cur->_nmethod);
+CodeRootSetTable::~CodeRootSetTable() {
+ for (int index = 0; index < table_size(); ++index) {
+ for (Entry* e = bucket(index); e != NULL; ) {
+ Entry* to_remove = e;
+ // read next before freeing.
+ e = e->next();
+ unlink_entry(to_remove);
+ FREE_C_HEAP_ARRAY(char, to_remove, mtGC);
}
- cur++;
+ }
+ assert(number_of_entries() == 0, "should have removed all entries");
+ free_buckets();
+ for (BasicHashtableEntry<mtGC>* e = new_entry_free_list(); e != NULL; e = new_entry_free_list()) {
+ FREE_C_HEAP_ARRAY(char, e, mtGC);
}
}
-bool G1CodeRootChunk::remove_lock_free(nmethod* method) {
- NmethodOrLink* cur = bottom();
-
- for (NmethodOrLink* cur = bottom(); cur != _top; cur++) {
- if (cur->_nmethod == method) {
- bool result = Atomic::cmpxchg_ptr(NULL, &cur->_nmethod, method) == method;
+bool CodeRootSetTable::add(nmethod* nm) {
+ if (!contains(nm)) {
+ Entry* e = new_entry(nm);
+ int index = hash_to_index(e->hash());
+ add_entry(index, e);
+ return true;
+ }
+ return false;
+}
- if (!result) {
- // Someone else cleared out this entry.
- return false;
- }
+bool CodeRootSetTable::contains(nmethod* nm) {
+ int index = hash_to_index(compute_hash(nm));
+ for (Entry* e = bucket(index); e != NULL; e = e->next()) {
+ if (e->literal() == nm) {
+ return true;
+ }
+ }
+ return false;
+}
- // The method was cleared. Time to link it into the free list.
- NmethodOrLink* prev_free;
- do {
- prev_free = (NmethodOrLink*)_free;
- cur->_link = prev_free;
- } while (Atomic::cmpxchg_ptr(cur, &_free, prev_free) != prev_free);
-
+bool CodeRootSetTable::remove(nmethod* nm) {
+ int index = hash_to_index(compute_hash(nm));
+ Entry* previous = NULL;
+ for (Entry* e = bucket(index); e != NULL; previous = e, e = e->next()) {
+ if (e->literal() == nm) {
+ if (previous != NULL) {
+ previous->set_next(e->next());
+ } else {
+ set_entry(index, e->next());
+ }
+ free_entry(e);
return true;
}
}
-
return false;
}
-G1CodeRootChunkManager::G1CodeRootChunkManager() : _free_list(), _num_chunks_handed_out(0) {
- _free_list.initialize();
- _free_list.set_size(G1CodeRootChunk::word_size());
+void CodeRootSetTable::copy_to(CodeRootSetTable* new_table) {
+ for (int index = 0; index < table_size(); ++index) {
+ for (Entry* e = bucket(index); e != NULL; e = e->next()) {
+ new_table->add(e->literal());
+ }
+ }
+ new_table->copy_freelist(this);
}
-size_t G1CodeRootChunkManager::fl_mem_size() {
- return _free_list.count() * _free_list.size();
-}
-
-void G1CodeRootChunkManager::free_all_chunks(FreeList<G1CodeRootChunk>* list) {
- _num_chunks_handed_out -= list->count();
- _free_list.prepend(list);
+void CodeRootSetTable::nmethods_do(CodeBlobClosure* blk) {
+ for (int index = 0; index < table_size(); ++index) {
+ for (Entry* e = bucket(index); e != NULL; e = e->next()) {
+ blk->do_code_blob(e->literal());
+ }
+ }
}
-void G1CodeRootChunkManager::free_chunk(G1CodeRootChunk* chunk) {
- _free_list.return_chunk_at_head(chunk);
- _num_chunks_handed_out--;
+template<typename CB>
+void CodeRootSetTable::remove_if(CB& should_remove) {
+ for (int index = 0; index < table_size(); ++index) {
+ Entry* previous = NULL;
+ Entry* e = bucket(index);
+ while (e != NULL) {
+ Entry* next = e->next();
+ if (should_remove(e->literal())) {
+ if (previous != NULL) {
+ previous->set_next(next);
+ } else {
+ set_entry(index, next);
+ }
+ free_entry(e);
+ } else {
+ previous = e;
+ }
+ e = next;
+ }
+ }
+}
+
+G1CodeRootSet::~G1CodeRootSet() {
+ delete _table;
}
-void G1CodeRootChunkManager::purge_chunks(size_t keep_ratio) {
- size_t keep = _num_chunks_handed_out * keep_ratio / 100;
- if (keep >= (size_t)_free_list.count()) {
- return;
- }
+CodeRootSetTable* G1CodeRootSet::load_acquire_table() {
+ return (CodeRootSetTable*) OrderAccess::load_ptr_acquire(&_table);
+}
+
+void G1CodeRootSet::allocate_small_table() {
+ _table = new CodeRootSetTable(SmallSize);
+}
- FreeList<G1CodeRootChunk> temp;
- temp.initialize();
- temp.set_size(G1CodeRootChunk::word_size());
+void CodeRootSetTable::purge_list_append(CodeRootSetTable* table) {
+ for (;;) {
+ table->_purge_next = _purge_list;
+ CodeRootSetTable* old = (CodeRootSetTable*) Atomic::cmpxchg_ptr(table, &_purge_list, table->_purge_next);
+ if (old == table->_purge_next) {
+ break;
+ }
+ }
+}
- _free_list.getFirstNChunksFromList((size_t)_free_list.count() - keep, &temp);
-
- G1CodeRootChunk* cur = temp.get_chunk_at_head();
- while (cur != NULL) {
- delete cur;
- cur = temp.get_chunk_at_head();
+void CodeRootSetTable::purge() {
+ CodeRootSetTable* table = _purge_list;
+ _purge_list = NULL;
+ while (table != NULL) {
+ CodeRootSetTable* to_purge = table;
+ table = table->_purge_next;
+ delete to_purge;
}
}
-size_t G1CodeRootChunkManager::static_mem_size() {
- return sizeof(G1CodeRootChunkManager);
+void G1CodeRootSet::move_to_large() {
+ CodeRootSetTable* temp = new CodeRootSetTable(LargeSize);
+
+ _table->copy_to(temp);
+
+ CodeRootSetTable::purge_list_append(_table);
+
+ OrderAccess::release_store_ptr(&_table, temp);
}
-G1CodeRootChunk* G1CodeRootChunkManager::new_chunk() {
- G1CodeRootChunk* result = _free_list.get_chunk_at_head();
- if (result == NULL) {
- result = new G1CodeRootChunk();
+void G1CodeRootSet::purge() {
+ CodeRootSetTable::purge();
+}
+
+size_t G1CodeRootSet::static_mem_size() {
+ return CodeRootSetTable::static_mem_size();
+}
+
+void G1CodeRootSet::add(nmethod* method) {
+ bool added = false;
+ if (is_empty()) {
+ allocate_small_table();
+ }
+ added = _table->add(method);
+ if (_length == Threshold) {
+ move_to_large();
+ }
+ if (added) {
+ ++_length;
+ }
+}
+
+bool G1CodeRootSet::remove(nmethod* method) {
+ bool removed = false;
+ if (_table != NULL) {
+ removed = _table->remove(method);
+ }
+ if (removed) {
+ _length--;
+ if (_length == 0) {
+ clear();
+ }
+ }
+ return removed;
+}
+
+bool G1CodeRootSet::contains(nmethod* method) {
+ CodeRootSetTable* table = load_acquire_table();
+ if (table != NULL) {
+ return table->contains(method);
}
- _num_chunks_handed_out++;
- result->reset();
- return result;
+ return false;
+}
+
+void G1CodeRootSet::clear() {
+ delete _table;
+ _table = NULL;
+ _length = 0;
+}
+
+size_t G1CodeRootSet::mem_size() {
+ return sizeof(*this) +
+ (_table != NULL ? sizeof(CodeRootSetTable) + _table->entry_size() * _length : 0);
+}
+
+void G1CodeRootSet::nmethods_do(CodeBlobClosure* blk) const {
+ if (_table != NULL) {
+ _table->nmethods_do(blk);
+ }
+}
+
+class CleanCallback : public StackObj {
+ class PointsIntoHRDetectionClosure : public OopClosure {
+ HeapRegion* _hr;
+ public:
+ bool _points_into;
+ PointsIntoHRDetectionClosure(HeapRegion* hr) : _hr(hr), _points_into(false) {}
+
+ void do_oop(narrowOop* o) {
+ do_oop_work(o);
+ }
+
+ void do_oop(oop* o) {
+ do_oop_work(o);
+ }
+
+ template <typename T>
+ void do_oop_work(T* p) {
+ if (_hr->is_in(oopDesc::load_decode_heap_oop(p))) {
+ _points_into = true;
+ }
+ }
+ };
+
+ PointsIntoHRDetectionClosure _detector;
+ CodeBlobToOopClosure _blobs;
+
+ public:
+ CleanCallback(HeapRegion* hr) : _detector(hr), _blobs(&_detector, !CodeBlobToOopClosure::FixRelocations) {}
+
+ bool operator() (nmethod* nm) {
+ _detector._points_into = false;
+ _blobs.do_code_blob(nm);
+ return _detector._points_into;
+ }
+};
+
+void G1CodeRootSet::clean(HeapRegion* owner) {
+ CleanCallback should_clean(owner);
+ if (_table != NULL) {
+ _table->remove_if(should_clean);
+ }
}
#ifndef PRODUCT
-size_t G1CodeRootChunkManager::num_chunks_handed_out() const {
- return _num_chunks_handed_out;
-}
+class G1CodeRootSetTest {
+ public:
+ static void test() {
+ {
+ G1CodeRootSet set1;
+ assert(set1.is_empty(), "Code root set must be initially empty but is not.");
+
+ assert(G1CodeRootSet::static_mem_size() == sizeof(void*),
+ err_msg("The code root set's static memory usage is incorrect, "SIZE_FORMAT" bytes", G1CodeRootSet::static_mem_size()));
+
+ set1.add((nmethod*)1);
+ assert(set1.length() == 1, err_msg("Added exactly one element, but set contains "
+ SIZE_FORMAT" elements", set1.length()));
+
+ const size_t num_to_add = (size_t)G1CodeRootSet::Threshold + 1;
+
+ for (size_t i = 1; i <= num_to_add; i++) {
+ set1.add((nmethod*)1);
+ }
+ assert(set1.length() == 1,
+ err_msg("Duplicate detection should not have increased the set size but "
+ "is "SIZE_FORMAT, set1.length()));
-size_t G1CodeRootChunkManager::num_free_chunks() const {
- return (size_t)_free_list.count();
+ for (size_t i = 2; i <= num_to_add; i++) {
+ set1.add((nmethod*)(uintptr_t)(i));
+ }
+ assert(set1.length() == num_to_add,
+ err_msg("After adding in total "SIZE_FORMAT" distinct code roots, they "
+ "need to be in the set, but there are only "SIZE_FORMAT,
+ num_to_add, set1.length()));
+
+ assert(CodeRootSetTable::_purge_list != NULL, "should have grown to large hashtable");
+
+ size_t num_popped = 0;
+ for (size_t i = 1; i <= num_to_add; i++) {
+ bool removed = set1.remove((nmethod*)i);
+ if (removed) {
+ num_popped += 1;
+ } else {
+ break;
+ }
+ }
+ assert(num_popped == num_to_add,
+ err_msg("Managed to pop "SIZE_FORMAT" code roots, but only "SIZE_FORMAT" "
+ "were added", num_popped, num_to_add));
+ assert(CodeRootSetTable::_purge_list != NULL, "should have grown to large hashtable");
+
+ G1CodeRootSet::purge();
+
+ assert(CodeRootSetTable::_purge_list == NULL, "should have purged old small tables");
+
+ }
+
+ }
+};
+
+void TestCodeCacheRemSet_test() {
+ G1CodeRootSetTest::test();
}
#endif
-
-G1CodeRootChunkManager G1CodeRootSet::_default_chunk_manager;
-
-void G1CodeRootSet::purge_chunks(size_t keep_ratio) {
- _default_chunk_manager.purge_chunks(keep_ratio);
-}
-
-size_t G1CodeRootSet::free_chunks_static_mem_size() {
- return _default_chunk_manager.static_mem_size();
-}
-
-size_t G1CodeRootSet::free_chunks_mem_size() {
- return _default_chunk_manager.fl_mem_size();
-}
-
-G1CodeRootSet::G1CodeRootSet(G1CodeRootChunkManager* manager) : _manager(manager), _list(), _length(0) {
- if (_manager == NULL) {
- _manager = &_default_chunk_manager;
- }
- _list.initialize();
- _list.set_size(G1CodeRootChunk::word_size());
-}
-
-G1CodeRootSet::~G1CodeRootSet() {
- clear();
-}
-
-void G1CodeRootSet::add(nmethod* method) {
- if (!contains(method)) {
- // Find the first chunk that isn't full.
- G1CodeRootChunk* cur = _list.head();
- while (cur != NULL) {
- if (!cur->is_full()) {
- break;
- }
- cur = cur->next();
- }
-
- // All chunks are full, get a new chunk.
- if (cur == NULL) {
- cur = new_chunk();
- _list.return_chunk_at_head(cur);
- }
-
- // Add the nmethod.
- bool result = cur->add(method);
-
- guarantee(result, err_msg("Not able to add nmethod "PTR_FORMAT" to newly allocated chunk.", method));
-
- _length++;
- }
-}
-
-void G1CodeRootSet::remove_lock_free(nmethod* method) {
- G1CodeRootChunk* found = find(method);
- if (found != NULL) {
- bool result = found->remove_lock_free(method);
- if (result) {
- Atomic::dec_ptr((volatile intptr_t*)&_length);
- }
- }
- assert(!contains(method), err_msg(PTR_FORMAT" still contains nmethod "PTR_FORMAT, this, method));
-}
-
-nmethod* G1CodeRootSet::pop() {
- while (true) {
- G1CodeRootChunk* cur = _list.head();
- if (cur == NULL) {
- assert(_length == 0, "when there are no chunks, there should be no elements");
- return NULL;
- }
- nmethod* result = cur->pop();
- if (result != NULL) {
- _length--;
- return result;
- } else {
- free(_list.get_chunk_at_head());
- }
- }
-}
-
-G1CodeRootChunk* G1CodeRootSet::find(nmethod* method) {
- G1CodeRootChunk* cur = _list.head();
- while (cur != NULL) {
- if (cur->contains(method)) {
- return cur;
- }
- cur = (G1CodeRootChunk*)cur->next();
- }
- return NULL;
-}
-
-void G1CodeRootSet::free(G1CodeRootChunk* chunk) {
- free_chunk(chunk);
-}
-
-bool G1CodeRootSet::contains(nmethod* method) {
- return find(method) != NULL;
-}
-
-void G1CodeRootSet::clear() {
- free_all_chunks(&_list);
- _length = 0;
-}
-
-void G1CodeRootSet::nmethods_do(CodeBlobClosure* blk) const {
- G1CodeRootChunk* cur = _list.head();
- while (cur != NULL) {
- cur->nmethods_do(blk);
- cur = (G1CodeRootChunk*)cur->next();
- }
-}
-
-size_t G1CodeRootSet::static_mem_size() {
- return sizeof(G1CodeRootSet);
-}
-
-size_t G1CodeRootSet::mem_size() {
- return G1CodeRootSet::static_mem_size() + _list.count() * _list.size();
-}
-
-#ifndef PRODUCT
-
-void G1CodeRootSet::test() {
- G1CodeRootChunkManager mgr;
-
- assert(mgr.num_chunks_handed_out() == 0, "Must not have handed out chunks yet");
-
- assert(G1CodeRootChunkManager::static_mem_size() > sizeof(void*),
- err_msg("The chunk manager's static memory usage seems too small, is only "SIZE_FORMAT" bytes.", G1CodeRootChunkManager::static_mem_size()));
-
- // The number of chunks that we allocate for purge testing.
- size_t const num_chunks = 10;
-
- {
- G1CodeRootSet set1(&mgr);
- assert(set1.is_empty(), "Code root set must be initially empty but is not.");
-
- assert(G1CodeRootSet::static_mem_size() > sizeof(void*),
- err_msg("The code root set's static memory usage seems too small, is only "SIZE_FORMAT" bytes", G1CodeRootSet::static_mem_size()));
-
- set1.add((nmethod*)1);
- assert(mgr.num_chunks_handed_out() == 1,
- err_msg("Must have allocated and handed out one chunk, but handed out "
- SIZE_FORMAT" chunks", mgr.num_chunks_handed_out()));
- assert(set1.length() == 1, err_msg("Added exactly one element, but set contains "
- SIZE_FORMAT" elements", set1.length()));
-
- // G1CodeRootChunk::word_size() is larger than G1CodeRootChunk::num_entries which
- // we cannot access.
- for (uint i = 0; i < G1CodeRootChunk::word_size() + 1; i++) {
- set1.add((nmethod*)1);
- }
- assert(mgr.num_chunks_handed_out() == 1,
- err_msg("Duplicate detection must have prevented allocation of further "
- "chunks but allocated "SIZE_FORMAT, mgr.num_chunks_handed_out()));
- assert(set1.length() == 1,
- err_msg("Duplicate detection should not have increased the set size but "
- "is "SIZE_FORMAT, set1.length()));
-
- size_t num_total_after_add = G1CodeRootChunk::word_size() + 1;
- for (size_t i = 0; i < num_total_after_add - 1; i++) {
- set1.add((nmethod*)(uintptr_t)(2 + i));
- }
- assert(mgr.num_chunks_handed_out() > 1,
- "After adding more code roots, more than one additional chunk should have been handed out");
- assert(set1.length() == num_total_after_add,
- err_msg("After adding in total "SIZE_FORMAT" distinct code roots, they "
- "need to be in the set, but there are only "SIZE_FORMAT,
- num_total_after_add, set1.length()));
-
- size_t num_popped = 0;
- while (set1.pop() != NULL) {
- num_popped++;
- }
- assert(num_popped == num_total_after_add,
- err_msg("Managed to pop "SIZE_FORMAT" code roots, but only "SIZE_FORMAT" "
- "were added", num_popped, num_total_after_add));
- assert(mgr.num_chunks_handed_out() == 0,
- err_msg("After popping all elements, all chunks must have been returned "
- "but there are still "SIZE_FORMAT" additional", mgr.num_chunks_handed_out()));
-
- mgr.purge_chunks(0);
- assert(mgr.num_free_chunks() == 0,
- err_msg("After purging everything, the free list must be empty but still "
- "contains "SIZE_FORMAT" chunks", mgr.num_free_chunks()));
-
- // Add some more handed out chunks.
- size_t i = 0;
- while (mgr.num_chunks_handed_out() < num_chunks) {
- set1.add((nmethod*)i);
- i++;
- }
-
- {
- // Generate chunks on the free list.
- G1CodeRootSet set2(&mgr);
- size_t i = 0;
- while (mgr.num_chunks_handed_out() < (num_chunks * 2)) {
- set2.add((nmethod*)i);
- i++;
- }
- // Exit of the scope of the set2 object will call the destructor that generates
- // num_chunks elements on the free list.
- }
-
- assert(mgr.num_chunks_handed_out() == num_chunks,
- err_msg("Deletion of the second set must have resulted in giving back "
- "those, but there are still "SIZE_FORMAT" additional handed out, expecting "
- SIZE_FORMAT, mgr.num_chunks_handed_out(), num_chunks));
- assert(mgr.num_free_chunks() == num_chunks,
- err_msg("After freeing "SIZE_FORMAT" chunks, they must be on the free list "
- "but there are only "SIZE_FORMAT, num_chunks, mgr.num_free_chunks()));
-
- size_t const test_percentage = 50;
- mgr.purge_chunks(test_percentage);
- assert(mgr.num_chunks_handed_out() == num_chunks,
- err_msg("Purging must not hand out chunks but there are "SIZE_FORMAT,
- mgr.num_chunks_handed_out()));
- assert(mgr.num_free_chunks() == (size_t)(mgr.num_chunks_handed_out() * test_percentage / 100),
- err_msg("Must have purged "SIZE_FORMAT" percent of "SIZE_FORMAT" chunks"
- "but there are "SIZE_FORMAT, test_percentage, num_chunks,
- mgr.num_free_chunks()));
- // Purge the remainder of the chunks on the free list.
- mgr.purge_chunks(0);
- assert(mgr.num_free_chunks() == 0, "Free List must be empty");
- assert(mgr.num_chunks_handed_out() == num_chunks,
- err_msg("Expected to be "SIZE_FORMAT" chunks handed out from the first set "
- "but there are "SIZE_FORMAT, num_chunks, mgr.num_chunks_handed_out()));
-
- // Exit of the scope of the set1 object will call the destructor that generates
- // num_chunks additional elements on the free list.
- }
-
- assert(mgr.num_chunks_handed_out() == 0,
- err_msg("Deletion of the only set must have resulted in no chunks handed "
- "out, but there is still "SIZE_FORMAT" handed out", mgr.num_chunks_handed_out()));
- assert(mgr.num_free_chunks() == num_chunks,
- err_msg("After freeing "SIZE_FORMAT" chunks, they must be on the free list "
- "but there are only "SIZE_FORMAT, num_chunks, mgr.num_free_chunks()));
-
- // Restore initial state.
- mgr.purge_chunks(0);
- assert(mgr.num_free_chunks() == 0, "Free List must be empty");
- assert(mgr.num_chunks_handed_out() == 0, "No additional elements must have been handed out yet");
-}
-
-void TestCodeCacheRemSet_test() {
- G1CodeRootSet::test();
-}
-#endif
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -26,222 +26,64 @@
#define SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP
#include "memory/allocation.hpp"
-#include "memory/freeList.hpp"
-#include "runtime/globals.hpp"
class CodeBlobClosure;
-
-// The elements of the G1CodeRootChunk is either:
-// 1) nmethod pointers
-// 2) nodes in an internally chained free list
-typedef union {
- nmethod* _nmethod;
- void* _link;
-} NmethodOrLink;
-
-class G1CodeRootChunk : public CHeapObj<mtGC> {
- private:
- static const int NUM_ENTRIES = 32;
- public:
- G1CodeRootChunk* _next;
- G1CodeRootChunk* _prev;
-
- NmethodOrLink* _top;
- // First free position within the chunk.
- volatile NmethodOrLink* _free;
-
- NmethodOrLink _data[NUM_ENTRIES];
-
- NmethodOrLink* bottom() const {
- return (NmethodOrLink*) &(_data[0]);
- }
-
- NmethodOrLink* end() const {
- return (NmethodOrLink*) &(_data[NUM_ENTRIES]);
- }
-
- bool is_link(NmethodOrLink* nmethod_or_link) {
- return nmethod_or_link->_link == NULL ||
- (bottom() <= nmethod_or_link->_link
- && nmethod_or_link->_link < end());
- }
-
- bool is_nmethod(NmethodOrLink* nmethod_or_link) {
- return !is_link(nmethod_or_link);
- }
-
- public:
- G1CodeRootChunk();
- ~G1CodeRootChunk() {}
-
- static size_t word_size() { return (size_t)(align_size_up_(sizeof(G1CodeRootChunk), HeapWordSize) / HeapWordSize); }
-
- // FreeList "interface" methods
-
- G1CodeRootChunk* next() const { return _next; }
- G1CodeRootChunk* prev() const { return _prev; }
- void set_next(G1CodeRootChunk* v) { _next = v; assert(v != this, "Boom");}
- void set_prev(G1CodeRootChunk* v) { _prev = v; assert(v != this, "Boom");}
- void clear_next() { set_next(NULL); }
- void clear_prev() { set_prev(NULL); }
-
- size_t size() const { return word_size(); }
-
- void link_next(G1CodeRootChunk* ptr) { set_next(ptr); }
- void link_prev(G1CodeRootChunk* ptr) { set_prev(ptr); }
- void link_after(G1CodeRootChunk* ptr) {
- link_next(ptr);
- if (ptr != NULL) ptr->link_prev((G1CodeRootChunk*)this);
- }
-
- bool is_free() { return true; }
-
- // New G1CodeRootChunk routines
-
- void reset();
-
- bool is_empty() const {
- return _top == bottom();
- }
-
- bool is_full() const {
- return _top == end() && _free == NULL;
- }
-
- bool contains(nmethod* method) {
- NmethodOrLink* cur = bottom();
- while (cur != _top) {
- if (cur->_nmethod == method) return true;
- cur++;
- }
- return false;
- }
-
- bool add(nmethod* method) {
- if (is_full()) {
- return false;
- }
-
- if (_free != NULL) {
- // Take from internally chained free list
- NmethodOrLink* first_free = (NmethodOrLink*)_free;
- _free = (NmethodOrLink*)_free->_link;
- first_free->_nmethod = method;
- } else {
- // Take from top.
- _top->_nmethod = method;
- _top++;
- }
-
- return true;
- }
-
- bool remove_lock_free(nmethod* method);
-
- void nmethods_do(CodeBlobClosure* blk);
-
- nmethod* pop() {
- if (_free != NULL) {
- // Kill the free list.
- _free = NULL;
- }
-
- while (!is_empty()) {
- _top--;
- if (is_nmethod(_top)) {
- return _top->_nmethod;
- }
- }
-
- return NULL;
- }
-};
-
-// Manages free chunks.
-class G1CodeRootChunkManager VALUE_OBJ_CLASS_SPEC {
- private:
- // Global free chunk list management
- FreeList<G1CodeRootChunk> _free_list;
- // Total number of chunks handed out
- size_t _num_chunks_handed_out;
-
- public:
- G1CodeRootChunkManager();
-
- G1CodeRootChunk* new_chunk();
- void free_chunk(G1CodeRootChunk* chunk);
- // Free all elements of the given list.
- void free_all_chunks(FreeList<G1CodeRootChunk>* list);
-
- void initialize();
- void purge_chunks(size_t keep_ratio);
-
- static size_t static_mem_size();
- size_t fl_mem_size();
-
-#ifndef PRODUCT
- size_t num_chunks_handed_out() const;
- size_t num_free_chunks() const;
-#endif
-};
+class CodeRootSetTable;
+class HeapRegion;
+class nmethod;
// Implements storage for a set of code roots.
// All methods that modify the set are not thread-safe except if otherwise noted.
class G1CodeRootSet VALUE_OBJ_CLASS_SPEC {
+ friend class G1CodeRootSetTest;
private:
- // Global default free chunk manager instance.
- static G1CodeRootChunkManager _default_chunk_manager;
- G1CodeRootChunk* new_chunk() { return _manager->new_chunk(); }
- void free_chunk(G1CodeRootChunk* chunk) { _manager->free_chunk(chunk); }
- // Free all elements of the given list.
- void free_all_chunks(FreeList<G1CodeRootChunk>* list) { _manager->free_all_chunks(list); }
+ const static size_t SmallSize = 32;
+ const static size_t Threshold = 24;
+ const static size_t LargeSize = 512;
- // Return the chunk that contains the given nmethod, NULL otherwise.
- // Scans the list of chunks backwards, as this method is used to add new
- // entries, which are typically added in bulk for a single nmethod.
- G1CodeRootChunk* find(nmethod* method);
- void free(G1CodeRootChunk* chunk);
+ CodeRootSetTable* _table;
+ CodeRootSetTable* load_acquire_table();
size_t _length;
- FreeList<G1CodeRootChunk> _list;
- G1CodeRootChunkManager* _manager;
+
+ void move_to_large();
+ void allocate_small_table();
public:
- // If an instance is initialized with a chunk manager of NULL, use the global
- // default one.
- G1CodeRootSet(G1CodeRootChunkManager* manager = NULL);
+ G1CodeRootSet() : _table(NULL), _length(0) {}
~G1CodeRootSet();
- static void purge_chunks(size_t keep_ratio);
+ static void purge();
- static size_t free_chunks_static_mem_size();
- static size_t free_chunks_mem_size();
+ static size_t static_mem_size();
- // Search for the code blob from the recently allocated ones to find duplicates more quickly, as this
- // method is likely to be repeatedly called with the same nmethod.
void add(nmethod* method);
- void remove_lock_free(nmethod* method);
- nmethod* pop();
+ bool remove(nmethod* method);
+ // Safe to call without synchronization, but may return false negatives.
bool contains(nmethod* method);
void clear();
void nmethods_do(CodeBlobClosure* blk) const;
- bool is_empty() { return length() == 0; }
+ // Remove all nmethods which no longer contain pointers into our "owner" region
+ void clean(HeapRegion* owner);
+
+ bool is_empty() {
+ bool empty = length() == 0;
+ assert(empty == (_table == NULL), "is empty only if table is deallocated");
+ return empty;
+ }
// Length in elements
size_t length() const { return _length; }
- // Static data memory size in bytes of this set.
- static size_t static_mem_size();
// Memory size in bytes taken by this set.
size_t mem_size();
- static void test() PRODUCT_RETURN;
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -4670,6 +4670,56 @@
}
};
+class G1CodeBlobClosure : public CodeBlobClosure {
+ class HeapRegionGatheringOopClosure : public OopClosure {
+ G1CollectedHeap* _g1h;
+ OopClosure* _work;
+ nmethod* _nm;
+
+ template <typename T>
+ void do_oop_work(T* p) {
+ _work->do_oop(p);
+ T oop_or_narrowoop = oopDesc::load_heap_oop(p);
+ if (!oopDesc::is_null(oop_or_narrowoop)) {
+ oop o = oopDesc::decode_heap_oop_not_null(oop_or_narrowoop);
+ HeapRegion* hr = _g1h->heap_region_containing_raw(o);
+ assert(!_g1h->obj_in_cs(o) || hr->rem_set()->strong_code_roots_list_contains(_nm), "if o still in CS then evacuation failed and nm must already be in the remset");
+ hr->add_strong_code_root(_nm);
+ }
+ }
+
+ public:
+ HeapRegionGatheringOopClosure(OopClosure* oc) : _g1h(G1CollectedHeap::heap()), _work(oc), _nm(NULL) {}
+
+ void do_oop(oop* o) {
+ do_oop_work(o);
+ }
+
+ void do_oop(narrowOop* o) {
+ do_oop_work(o);
+ }
+
+ void set_nm(nmethod* nm) {
+ _nm = nm;
+ }
+ };
+
+ HeapRegionGatheringOopClosure _oc;
+public:
+ G1CodeBlobClosure(OopClosure* oc) : _oc(oc) {}
+
+ void do_code_blob(CodeBlob* cb) {
+ nmethod* nm = cb->as_nmethod_or_null();
+ if (nm != NULL) {
+ if (!nm->test_set_oops_do_mark()) {
+ _oc.set_nm(nm);
+ nm->oops_do(&_oc);
+ nm->fix_oop_relocations();
+ }
+ }
+ }
+};
+
class G1ParTask : public AbstractGangTask {
protected:
G1CollectedHeap* _g1h;
@@ -4738,22 +4788,6 @@
}
};
- class G1CodeBlobClosure: public CodeBlobClosure {
- OopClosure* _f;
-
- public:
- G1CodeBlobClosure(OopClosure* f) : _f(f) {}
- void do_code_blob(CodeBlob* blob) {
- nmethod* that = blob->as_nmethod_or_null();
- if (that != NULL) {
- if (!that->test_set_oops_do_mark()) {
- that->oops_do(_f);
- that->fix_oop_relocations();
- }
- }
- }
- };
-
void work(uint worker_id) {
if (worker_id >= _n_workers) return; // no work needed this round
@@ -4944,7 +4978,7 @@
g1_policy()->phase_times()->record_satb_filtering_time(worker_i, satb_filtering_ms);
// Now scan the complement of the collection set.
- MarkingCodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots, CodeBlobToOopClosure::FixRelocations);
+ G1CodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots);
g1_rem_set()->oops_into_collection_set_do(scan_rs, &scavenge_cs_nmethods, worker_i);
@@ -5991,12 +6025,6 @@
hot_card_cache->reset_hot_cache();
hot_card_cache->set_use_cache(true);
- // Migrate the strong code roots attached to each region in
- // the collection set. Ideally we would like to do this
- // after we have finished the scanning/evacuation of the
- // strong code roots for a particular heap region.
- migrate_strong_code_roots();
-
purge_code_root_memory();
if (g1_policy()->during_initial_mark_pause()) {
@@ -7049,13 +7077,8 @@
" starting at "HR_FORMAT,
_nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region())));
- // HeapRegion::add_strong_code_root() avoids adding duplicate
- // entries but having duplicates is OK since we "mark" nmethods
- // as visited when we scan the strong code root lists during the GC.
- hr->add_strong_code_root(_nm);
- assert(hr->rem_set()->strong_code_roots_list_contains(_nm),
- err_msg("failed to add code root "PTR_FORMAT" to remembered set of region "HR_FORMAT,
- _nm, HR_FORMAT_PARAMS(hr)));
+ // HeapRegion::add_strong_code_root_locked() avoids adding duplicate entries.
+ hr->add_strong_code_root_locked(_nm);
}
}
@@ -7082,9 +7105,6 @@
_nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region())));
hr->remove_strong_code_root(_nm);
- assert(!hr->rem_set()->strong_code_roots_list_contains(_nm),
- err_msg("failed to remove code root "PTR_FORMAT" of region "HR_FORMAT,
- _nm, HR_FORMAT_PARAMS(hr)));
}
}
@@ -7112,28 +7132,9 @@
nm->oops_do(®_cl, true);
}
-class MigrateCodeRootsHeapRegionClosure: public HeapRegionClosure {
-public:
- bool doHeapRegion(HeapRegion *hr) {
- assert(!hr->isHumongous(),
- err_msg("humongous region "HR_FORMAT" should not have been added to collection set",
- HR_FORMAT_PARAMS(hr)));
- hr->migrate_strong_code_roots();
- return false;
- }
-};
-
-void G1CollectedHeap::migrate_strong_code_roots() {
- MigrateCodeRootsHeapRegionClosure cl;
- double migrate_start = os::elapsedTime();
- collection_set_iterate(&cl);
- double migration_time_ms = (os::elapsedTime() - migrate_start) * 1000.0;
- g1_policy()->phase_times()->record_strong_code_root_migration_time(migration_time_ms);
-}
-
void G1CollectedHeap::purge_code_root_memory() {
double purge_start = os::elapsedTime();
- G1CodeRootSet::purge_chunks(G1CodeRootsChunkCacheKeepPercent);
+ G1CodeRootSet::purge();
double purge_time_ms = (os::elapsedTime() - purge_start) * 1000.0;
g1_policy()->phase_times()->record_strong_code_root_purge_time(purge_time_ms);
}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -1662,12 +1662,6 @@
// Unregister the given nmethod from the G1 heap.
virtual void unregister_nmethod(nmethod* nm);
- // Migrate the nmethods in the code root lists of the regions
- // in the collection set to regions in to-space. In the event
- // of an evacuation failure, nmethods that reference objects
- // that were not successfully evacuated are not migrated.
- void migrate_strong_code_roots();
-
// Free up superfluous code root memory.
void purge_code_root_memory();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -217,6 +217,8 @@
_update_rset_cl->set_region(hr);
hr->object_iterate(&rspc);
+ hr->rem_set()->clean_strong_code_roots(hr);
+
hr->note_self_forwarding_removal_end(during_initial_mark,
during_conc_mark,
rspc.marked_bytes());
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -275,9 +275,6 @@
// Now subtract the time taken to fix up roots in generated code
misc_time_ms += _cur_collection_code_root_fixup_time_ms;
- // Strong code root migration time
- misc_time_ms += _cur_strong_code_root_migration_time_ms;
-
// Strong code root purge time
misc_time_ms += _cur_strong_code_root_purge_time_ms;
@@ -328,7 +325,6 @@
_last_obj_copy_times_ms.print(1, "Object Copy (ms)");
}
print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms);
- print_stats(1, "Code Root Migration", _cur_strong_code_root_migration_time_ms);
print_stats(1, "Code Root Purge", _cur_strong_code_root_purge_time_ms);
if (G1StringDedup::is_enabled()) {
print_stats(1, "String Dedup Fixup", _cur_string_dedup_fixup_time_ms, _active_gc_threads);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -129,7 +129,6 @@
double _cur_collection_par_time_ms;
double _cur_collection_code_root_fixup_time_ms;
- double _cur_strong_code_root_migration_time_ms;
double _cur_strong_code_root_purge_time_ms;
double _cur_evac_fail_recalc_used;
@@ -233,10 +232,6 @@
_cur_collection_code_root_fixup_time_ms = ms;
}
- void record_strong_code_root_migration_time(double ms) {
- _cur_strong_code_root_migration_time_ms = ms;
- }
-
void record_strong_code_root_purge_time(double ms) {
_cur_strong_code_root_purge_time_ms = ms;
}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -110,7 +110,7 @@
G1CollectedHeap* _g1h;
OopsInHeapRegionClosure* _oc;
- CodeBlobToOopClosure* _code_root_cl;
+ CodeBlobClosure* _code_root_cl;
G1BlockOffsetSharedArray* _bot_shared;
G1SATBCardTableModRefBS *_ct_bs;
@@ -122,7 +122,7 @@
public:
ScanRSClosure(OopsInHeapRegionClosure* oc,
- CodeBlobToOopClosure* code_root_cl,
+ CodeBlobClosure* code_root_cl,
uint worker_i) :
_oc(oc),
_code_root_cl(code_root_cl),
@@ -242,7 +242,7 @@
};
void G1RemSet::scanRS(OopsInHeapRegionClosure* oc,
- CodeBlobToOopClosure* code_root_cl,
+ CodeBlobClosure* code_root_cl,
uint worker_i) {
double rs_time_start = os::elapsedTime();
HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
@@ -321,7 +321,7 @@
}
void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
- CodeBlobToOopClosure* code_root_cl,
+ CodeBlobClosure* code_root_cl,
uint worker_i) {
#if CARD_REPEAT_HISTO
ct_freq_update_histo_and_reset();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -96,7 +96,7 @@
// the "i" passed to the calling thread's work(i) function.
// In the sequential case this param will be ignored.
void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
- CodeBlobToOopClosure* code_root_cl,
+ CodeBlobClosure* code_root_cl,
uint worker_i);
// Prepare for and cleanup after an oops_into_collection_set_do
@@ -108,7 +108,7 @@
void cleanup_after_oops_into_collection_set_do();
void scanRS(OopsInHeapRegionClosure* oc,
- CodeBlobToOopClosure* code_root_cl,
+ CodeBlobClosure* code_root_cl,
uint worker_i);
void updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -253,6 +253,7 @@
size_t occupied_cards = hrrs->occupied();
size_t code_root_mem_sz = hrrs->strong_code_roots_mem_size();
if (code_root_mem_sz > max_code_root_mem_sz()) {
+ _max_code_root_mem_sz = code_root_mem_sz;
_max_code_root_mem_sz_region = r;
}
size_t code_root_elems = hrrs->strong_code_roots_list_length();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -277,10 +277,6 @@
product(uintx, G1MixedGCCountTarget, 8, \
"The target number of mixed GCs after a marking cycle.") \
\
- experimental(uintx, G1CodeRootsChunkCacheKeepPercent, 10, \
- "The amount of code root chunks that should be kept at most " \
- "as percentage of already allocated.") \
- \
experimental(bool, G1ReclaimDeadHumongousObjectsAtYoungGC, true, \
"Try to reclaim dead large objects at every young GC.") \
\
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -540,21 +540,17 @@
hrrs->add_strong_code_root(nm);
}
+void HeapRegion::add_strong_code_root_locked(nmethod* nm) {
+ assert_locked_or_safepoint(CodeCache_lock);
+ HeapRegionRemSet* hrrs = rem_set();
+ hrrs->add_strong_code_root_locked(nm);
+}
+
void HeapRegion::remove_strong_code_root(nmethod* nm) {
HeapRegionRemSet* hrrs = rem_set();
hrrs->remove_strong_code_root(nm);
}
-void HeapRegion::migrate_strong_code_roots() {
- assert(in_collection_set(), "only collection set regions");
- assert(!isHumongous(),
- err_msg("humongous region "HR_FORMAT" should not have been added to collection set",
- HR_FORMAT_PARAMS(this)));
-
- HeapRegionRemSet* hrrs = rem_set();
- hrrs->migrate_strong_code_roots();
-}
-
void HeapRegion::strong_code_roots_do(CodeBlobClosure* blk) const {
HeapRegionRemSet* hrrs = rem_set();
hrrs->strong_code_roots_do(blk);
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -756,14 +756,9 @@
// Routines for managing a list of code roots (attached to the
// this region's RSet) that point into this heap region.
void add_strong_code_root(nmethod* nm);
+ void add_strong_code_root_locked(nmethod* nm);
void remove_strong_code_root(nmethod* nm);
- // During a collection, migrate the successfully evacuated
- // strong code roots that referenced into this region to the
- // new regions that they now point into. Unsuccessfully
- // evacuated code roots are not migrated.
- void migrate_strong_code_roots();
-
// Applies blk->do_code_blob() to each of the entries in
// the strong code roots list for this region
void strong_code_roots_do(CodeBlobClosure* blk) const;
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -448,10 +448,10 @@
// Note that this may be a continued H region.
HeapRegion* from_hr = _g1h->heap_region_containing_raw(from);
- RegionIdx_t from_hrs_ind = (RegionIdx_t) from_hr->hrm_index();
+ RegionIdx_t from_hrm_ind = (RegionIdx_t) from_hr->hrm_index();
// If the region is already coarsened, return.
- if (_coarse_map.at(from_hrs_ind)) {
+ if (_coarse_map.at(from_hrm_ind)) {
if (G1TraceHeapRegionRememberedSet) {
gclog_or_tty->print_cr(" coarse map hit.");
}
@@ -460,7 +460,7 @@
}
// Otherwise find a per-region table to add it to.
- size_t ind = from_hrs_ind & _mod_max_fine_entries_mask;
+ size_t ind = from_hrm_ind & _mod_max_fine_entries_mask;
PerRegionTable* prt = find_region_table(ind, from_hr);
if (prt == NULL) {
MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
@@ -475,7 +475,7 @@
assert(0 <= card_index && (size_t)card_index < HeapRegion::CardsPerRegion,
"Must be in range.");
if (G1HRRSUseSparseTable &&
- _sparse_table.add_card(from_hrs_ind, card_index)) {
+ _sparse_table.add_card(from_hrm_ind, card_index)) {
if (G1RecordHRRSOops) {
HeapRegionRemSet::record(hr(), from);
if (G1TraceHeapRegionRememberedSet) {
@@ -495,7 +495,7 @@
if (G1TraceHeapRegionRememberedSet) {
gclog_or_tty->print_cr(" [tid %d] sparse table entry "
"overflow(f: %d, t: %u)",
- tid, from_hrs_ind, cur_hrm_ind);
+ tid, from_hrm_ind, cur_hrm_ind);
}
}
@@ -516,7 +516,7 @@
if (G1HRRSUseSparseTable) {
// Transfer from sparse to fine-grain.
- SparsePRTEntry *sprt_entry = _sparse_table.get_entry(from_hrs_ind);
+ SparsePRTEntry *sprt_entry = _sparse_table.get_entry(from_hrm_ind);
assert(sprt_entry != NULL, "There should have been an entry");
for (int i = 0; i < SparsePRTEntry::cards_num(); i++) {
CardIdx_t c = sprt_entry->card(i);
@@ -525,7 +525,7 @@
}
}
// Now we can delete the sparse entry.
- bool res = _sparse_table.delete_entry(from_hrs_ind);
+ bool res = _sparse_table.delete_entry(from_hrm_ind);
assert(res, "It should have been there.");
}
}
@@ -926,9 +926,25 @@
}
// Code roots support
+//
+// The code root set is protected by two separate locking schemes
+// When at safepoint the per-hrrs lock must be held during modifications
+// except when doing a full gc.
+// When not at safepoint the CodeCache_lock must be held during modifications.
+// When concurrent readers access the contains() function
+// (during the evacuation phase) no removals are allowed.
void HeapRegionRemSet::add_strong_code_root(nmethod* nm) {
assert(nm != NULL, "sanity");
+ // Optimistic unlocked contains-check
+ if (!_code_roots.contains(nm)) {
+ MutexLockerEx ml(&_m, Mutex::_no_safepoint_check_flag);
+ add_strong_code_root_locked(nm);
+ }
+}
+
+void HeapRegionRemSet::add_strong_code_root_locked(nmethod* nm) {
+ assert(nm != NULL, "sanity");
_code_roots.add(nm);
}
@@ -936,96 +952,19 @@
assert(nm != NULL, "sanity");
assert_locked_or_safepoint(CodeCache_lock);
- _code_roots.remove_lock_free(nm);
+ MutexLockerEx ml(CodeCache_lock->owned_by_self() ? NULL : &_m, Mutex::_no_safepoint_check_flag);
+ _code_roots.remove(nm);
// Check that there were no duplicates
guarantee(!_code_roots.contains(nm), "duplicate entry found");
}
-class NMethodMigrationOopClosure : public OopClosure {
- G1CollectedHeap* _g1h;
- HeapRegion* _from;
- nmethod* _nm;
-
- uint _num_self_forwarded;
-
- template <class T> void do_oop_work(T* p) {
- T heap_oop = oopDesc::load_heap_oop(p);
- if (!oopDesc::is_null(heap_oop)) {
- oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
- if (_from->is_in(obj)) {
- // Reference still points into the source region.
- // Since roots are immediately evacuated this means that
- // we must have self forwarded the object
- assert(obj->is_forwarded(),
- err_msg("code roots should be immediately evacuated. "
- "Ref: "PTR_FORMAT", "
- "Obj: "PTR_FORMAT", "
- "Region: "HR_FORMAT,
- p, (void*) obj, HR_FORMAT_PARAMS(_from)));
- assert(obj->forwardee() == obj,
- err_msg("not self forwarded? obj = "PTR_FORMAT, (void*)obj));
-
- // The object has been self forwarded.
- // Note, if we're during an initial mark pause, there is
- // no need to explicitly mark object. It will be marked
- // during the regular evacuation failure handling code.
- _num_self_forwarded++;
- } else {
- // The reference points into a promotion or to-space region
- HeapRegion* to = _g1h->heap_region_containing(obj);
- to->rem_set()->add_strong_code_root(_nm);
- }
- }
- }
-
-public:
- NMethodMigrationOopClosure(G1CollectedHeap* g1h, HeapRegion* from, nmethod* nm):
- _g1h(g1h), _from(from), _nm(nm), _num_self_forwarded(0) {}
-
- void do_oop(narrowOop* p) { do_oop_work(p); }
- void do_oop(oop* p) { do_oop_work(p); }
-
- uint retain() { return _num_self_forwarded > 0; }
-};
-
-void HeapRegionRemSet::migrate_strong_code_roots() {
- assert(hr()->in_collection_set(), "only collection set regions");
- assert(!hr()->isHumongous(),
- err_msg("humongous region "HR_FORMAT" should not have been added to the collection set",
- HR_FORMAT_PARAMS(hr())));
-
- ResourceMark rm;
-
- // List of code blobs to retain for this region
- GrowableArray<nmethod*> to_be_retained(10);
- G1CollectedHeap* g1h = G1CollectedHeap::heap();
-
- while (!_code_roots.is_empty()) {
- nmethod *nm = _code_roots.pop();
- if (nm != NULL) {
- NMethodMigrationOopClosure oop_cl(g1h, hr(), nm);
- nm->oops_do(&oop_cl);
- if (oop_cl.retain()) {
- to_be_retained.push(nm);
- }
- }
- }
-
- // Now push any code roots we need to retain
- assert(to_be_retained.is_empty() || hr()->evacuation_failed(),
- "Retained nmethod list must be empty or "
- "evacuation of this region failed");
-
- while (to_be_retained.is_nonempty()) {
- nmethod* nm = to_be_retained.pop();
- assert(nm != NULL, "sanity");
- add_strong_code_root(nm);
- }
+void HeapRegionRemSet::strong_code_roots_do(CodeBlobClosure* blk) const {
+ _code_roots.nmethods_do(blk);
}
-void HeapRegionRemSet::strong_code_roots_do(CodeBlobClosure* blk) const {
- _code_roots.nmethods_do(blk);
+void HeapRegionRemSet::clean_strong_code_roots(HeapRegion* hr) {
+ _code_roots.clean(hr);
}
size_t HeapRegionRemSet::strong_code_roots_mem_size() {
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -349,13 +349,13 @@
// Returns the memory occupancy of all static data structures associated
// with remembered sets.
static size_t static_mem_size() {
- return OtherRegionsTable::static_mem_size() + G1CodeRootSet::free_chunks_static_mem_size();
+ return OtherRegionsTable::static_mem_size() + G1CodeRootSet::static_mem_size();
}
// Returns the memory occupancy of all free_list data structures associated
// with remembered sets.
static size_t fl_mem_size() {
- return OtherRegionsTable::fl_mem_size() + G1CodeRootSet::free_chunks_mem_size();
+ return OtherRegionsTable::fl_mem_size();
}
bool contains_reference(OopOrNarrowOopStar from) const {
@@ -365,18 +365,15 @@
// Routines for managing the list of code roots that point into
// the heap region that owns this RSet.
void add_strong_code_root(nmethod* nm);
+ void add_strong_code_root_locked(nmethod* nm);
void remove_strong_code_root(nmethod* nm);
- // During a collection, migrate the successfully evacuated strong
- // code roots that referenced into the region that owns this RSet
- // to the RSets of the new regions that they now point into.
- // Unsuccessfully evacuated code roots are not migrated.
- void migrate_strong_code_roots();
-
// Applies blk->do_code_blob() to each of the entries in
// the strong code roots list
void strong_code_roots_do(CodeBlobClosure* blk) const;
+ void clean_strong_code_roots(HeapRegion* hr);
+
// Returns the number of elements in the strong code roots list
size_t strong_code_roots_list_length() const {
return _code_roots.length();
--- a/hotspot/src/share/vm/interpreter/interpreter.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/interpreter/interpreter.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -55,7 +55,9 @@
public:
// Initialization/finalization
void initialize(int size,
- CodeStrings& strings) { _size = size; DEBUG_ONLY(_strings.assign(strings);) }
+ CodeStrings& strings) { _size = size;
+ DEBUG_ONLY(::new(&_strings) CodeStrings();)
+ DEBUG_ONLY(_strings.assign(strings);) }
void finalize() { ShouldNotCallThis(); }
// General info/converters
--- a/hotspot/src/share/vm/memory/freeList.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/memory/freeList.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -34,7 +34,6 @@
#if INCLUDE_ALL_GCS
#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
-#include "gc_implementation/g1/g1CodeCacheRemSet.hpp"
#endif // INCLUDE_ALL_GCS
// Free list. A FreeList is used to access a linked list of chunks
@@ -333,5 +332,4 @@
template class FreeList<Metachunk>;
#if INCLUDE_ALL_GCS
template class FreeList<FreeChunk>;
-template class FreeList<G1CodeRootChunk>;
#endif // INCLUDE_ALL_GCS
--- a/hotspot/src/share/vm/oops/methodData.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/oops/methodData.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -86,7 +86,7 @@
char* ProfileData::print_data_on_helper(const MethodData* md) const {
DataLayout* dp = md->extra_data_base();
- DataLayout* end = md->extra_data_limit();
+ DataLayout* end = md->args_data_limit();
stringStream ss;
for (;; dp = MethodData::next_extra(dp)) {
assert(dp < end, "moved past end of extra data");
@@ -1048,14 +1048,15 @@
stream->next();
data->post_initialize(stream, this);
}
- if (_parameters_type_data_di != -1) {
+ if (_parameters_type_data_di != no_parameters) {
parameters_type_data()->post_initialize(NULL, this);
}
}
// Initialize the MethodData* corresponding to a given method.
MethodData::MethodData(methodHandle method, int size, TRAPS)
- : _extra_data_lock(Monitor::leaf, "MDO extra data lock") {
+ : _extra_data_lock(Monitor::leaf, "MDO extra data lock"),
+ _parameters_type_data_di(parameters_uninitialized) {
No_Safepoint_Verifier no_safepoint; // init function atomic wrt GC
ResourceMark rm;
// Set the method back-pointer.
@@ -1111,7 +1112,7 @@
DataLayout *dp = data_layout_at(data_size + extra_size + arg_data_size);
dp->initialize(DataLayout::parameters_type_data_tag, 0, parms_cell);
} else {
- _parameters_type_data_di = -1;
+ _parameters_type_data_di = no_parameters;
}
// Set an initial hint. Don't use set_hint_di() because
@@ -1236,7 +1237,7 @@
}
ProfileData* MethodData::bci_to_extra_data_helper(int bci, Method* m, DataLayout*& dp, bool concurrent) {
- DataLayout* end = extra_data_limit();
+ DataLayout* end = args_data_limit();
for (;; dp = next_extra(dp)) {
assert(dp < end, "moved past end of extra data");
@@ -1285,7 +1286,7 @@
"code needs to be adjusted");
DataLayout* dp = extra_data_base();
- DataLayout* end = extra_data_limit();
+ DataLayout* end = args_data_limit();
// Allocation in the extra data space has to be atomic because not
// all entries have the same size and non atomic concurrent
@@ -1330,7 +1331,7 @@
ArgInfoData *MethodData::arg_info() {
DataLayout* dp = extra_data_base();
- DataLayout* end = extra_data_limit();
+ DataLayout* end = args_data_limit();
for (; dp < end; dp = next_extra(dp)) {
if (dp->tag() == DataLayout::arg_info_data_tag)
return new ArgInfoData(dp);
@@ -1357,7 +1358,7 @@
void MethodData::print_data_on(outputStream* st) const {
ResourceMark rm;
ProfileData* data = first_data();
- if (_parameters_type_data_di != -1) {
+ if (_parameters_type_data_di != no_parameters) {
parameters_type_data()->print_data_on(st);
}
for ( ; is_valid(data); data = next_data(data)) {
@@ -1367,7 +1368,7 @@
}
st->print_cr("--- Extra data:");
DataLayout* dp = extra_data_base();
- DataLayout* end = extra_data_limit();
+ DataLayout* end = args_data_limit();
for (;; dp = next_extra(dp)) {
assert(dp < end, "moved past end of extra data");
// No need for "OrderAccess::load_acquire" ops,
@@ -1565,7 +1566,7 @@
// redefined method
void MethodData::clean_extra_data(CleanExtraDataClosure* cl) {
DataLayout* dp = extra_data_base();
- DataLayout* end = extra_data_limit();
+ DataLayout* end = args_data_limit();
int shift = 0;
for (; dp < end; dp = next_extra(dp)) {
@@ -1610,7 +1611,7 @@
void MethodData::verify_extra_data_clean(CleanExtraDataClosure* cl) {
#ifdef ASSERT
DataLayout* dp = extra_data_base();
- DataLayout* end = extra_data_limit();
+ DataLayout* end = args_data_limit();
for (; dp < end; dp = next_extra(dp)) {
switch(dp->tag()) {
--- a/hotspot/src/share/vm/oops/methodData.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/oops/methodData.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -2107,7 +2107,12 @@
// data index for the area dedicated to parameters. -1 if no
// parameter profiling.
+ enum { no_parameters = -2, parameters_uninitialized = -1 };
int _parameters_type_data_di;
+ int parameters_size_in_bytes() const {
+ ParametersTypeData* param = parameters_type_data();
+ return param == NULL ? 0 : param->size_in_bytes();
+ }
// Beginning of the data entries
intptr_t _data[1];
@@ -2130,7 +2135,7 @@
// Helper for data_at
DataLayout* limit_data_position() const {
- return (DataLayout*)((address)data_base() + _data_size);
+ return data_layout_at(_data_size);
}
bool out_of_bounds(int data_index) const {
return data_index >= data_size();
@@ -2371,10 +2376,11 @@
}
// Add a handful of extra data records, for trap tracking.
- DataLayout* extra_data_base() const { return limit_data_position(); }
+ DataLayout* extra_data_base() const { return limit_data_position(); }
DataLayout* extra_data_limit() const { return (DataLayout*)((address)this + size_in_bytes()); }
- int extra_data_size() const { return (address)extra_data_limit()
- - (address)extra_data_base(); }
+ DataLayout* args_data_limit() const { return (DataLayout*)((address)this + size_in_bytes() -
+ parameters_size_in_bytes()); }
+ int extra_data_size() const { return (address)extra_data_limit() - (address)extra_data_base(); }
static DataLayout* next_extra(DataLayout* dp);
// Return (uint)-1 for overflow.
@@ -2429,11 +2435,12 @@
// Return pointer to area dedicated to parameters in MDO
ParametersTypeData* parameters_type_data() const {
- return _parameters_type_data_di != -1 ? data_layout_at(_parameters_type_data_di)->data_in()->as_ParametersTypeData() : NULL;
+ assert(_parameters_type_data_di != parameters_uninitialized, "called too early");
+ return _parameters_type_data_di != no_parameters ? data_layout_at(_parameters_type_data_di)->data_in()->as_ParametersTypeData() : NULL;
}
int parameters_type_data_di() const {
- assert(_parameters_type_data_di != -1, "no args type data");
+ assert(_parameters_type_data_di != parameters_uninitialized && _parameters_type_data_di != no_parameters, "no args type data");
return _parameters_type_data_di;
}
@@ -2480,8 +2487,8 @@
static bool profile_return_jsr292_only();
void clean_method_data(BoolObjectClosure* is_alive);
-
void clean_weak_method_links();
+ Mutex* extra_data_lock() { return &_extra_data_lock; }
};
#endif // SHARE_VM_OOPS_METHODDATAOOP_HPP
--- a/hotspot/src/share/vm/opto/c2_globals.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -650,6 +650,9 @@
product(bool, UseMathExactIntrinsics, true, \
"Enables intrinsification of various java.lang.Math functions") \
\
+ product(bool, UseMultiplyToLenIntrinsic, false, \
+ "Enables intrinsification of BigInteger.multiplyToLen()") \
+ \
product(bool, UseTypeSpeculation, true, \
"Speculatively propagate types from profiles") \
\
--- a/hotspot/src/share/vm/opto/callnode.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/opto/callnode.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -1830,8 +1830,8 @@
Node* dest, Node* dest_offset,
Node* length,
bool alloc_tightly_coupled,
- Node* src_length, Node* dest_length,
- Node* src_klass, Node* dest_klass) {
+ Node* src_klass, Node* dest_klass,
+ Node* src_length, Node* dest_length) {
ArrayCopyNode* ac = new ArrayCopyNode(kit->C, alloc_tightly_coupled);
Node* prev_mem = kit->set_predefined_input_for_runtime_call(ac);
--- a/hotspot/src/share/vm/opto/callnode.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/opto/callnode.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -1138,8 +1138,8 @@
Node* dest, Node* dest_offset,
Node* length,
bool alloc_tightly_coupled,
- Node* src_length = NULL, Node* dest_length = NULL,
- Node* src_klass = NULL, Node* dest_klass = NULL);
+ Node* src_klass = NULL, Node* dest_klass = NULL,
+ Node* src_length = NULL, Node* dest_length = NULL);
void connect_outputs(GraphKit* kit);
--- a/hotspot/src/share/vm/opto/compile.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/opto/compile.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -601,6 +601,10 @@
bool method_has_option(const char * option) {
return method() != NULL && method()->has_option(option);
}
+ template<typename T>
+ bool method_has_option_value(const char * option, T& value) {
+ return method() != NULL && method()->has_option_value(option, value);
+ }
#ifndef PRODUCT
bool trace_opto_output() const { return _trace_opto_output; }
bool parsed_irreducible_loop() const { return _parsed_irreducible_loop; }
--- a/hotspot/src/share/vm/opto/escape.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/opto/escape.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -945,7 +945,8 @@
strcmp(call->as_CallLeaf()->_name, "sha256_implCompress") == 0 ||
strcmp(call->as_CallLeaf()->_name, "sha256_implCompressMB") == 0 ||
strcmp(call->as_CallLeaf()->_name, "sha512_implCompress") == 0 ||
- strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0)
+ strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0 ||
+ strcmp(call->as_CallLeaf()->_name, "multiplyToLen") == 0)
))) {
call->dump();
fatal(err_msg_res("EA unexpected CallLeaf %s", call->as_CallLeaf()->_name));
--- a/hotspot/src/share/vm/opto/library_call.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/opto/library_call.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -285,6 +285,7 @@
bool inline_updateCRC32();
bool inline_updateBytesCRC32();
bool inline_updateByteBufferCRC32();
+ bool inline_multiplyToLen();
};
@@ -293,8 +294,12 @@
vmIntrinsics::ID id = m->intrinsic_id();
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
- if (DisableIntrinsic[0] != '\0'
- && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) {
+ ccstr disable_intr = NULL;
+
+ if ((DisableIntrinsic[0] != '\0'
+ && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) ||
+ (method_has_option_value("DisableIntrinsic", disable_intr)
+ && strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)) {
// disabled by a user request on the command line:
// example: -XX:DisableIntrinsic=_hashCode,_getClass
return NULL;
@@ -477,6 +482,10 @@
if (!UseAESIntrinsics) return NULL;
break;
+ case vmIntrinsics::_multiplyToLen:
+ if (!UseMultiplyToLenIntrinsic) return NULL;
+ break;
+
case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
if (!UseAESIntrinsics) return NULL;
@@ -875,6 +884,9 @@
case vmIntrinsics::_digestBase_implCompressMB:
return inline_digestBase_implCompressMB(predicate);
+ case vmIntrinsics::_multiplyToLen:
+ return inline_multiplyToLen();
+
case vmIntrinsics::_encodeISOArray:
return inline_encodeISOArray();
@@ -3843,7 +3855,7 @@
Node* orig_tail = _gvn.transform(new SubINode(orig_length, start));
Node* moved = generate_min_max(vmIntrinsics::_min, orig_tail, length);
- newcopy = new_array(klass_node, length, 0); // no argments to push
+ newcopy = new_array(klass_node, length, 0); // no arguments to push
// Generate a direct call to the right arraycopy function(s).
// We know the copy is disjoint but we might not know if the
@@ -3853,7 +3865,8 @@
Node* alloc = tightly_coupled_allocation(newcopy, NULL);
- ArrayCopyNode* ac = ArrayCopyNode::make(this, true, original, start, newcopy, intcon(0), moved, alloc != NULL);
+ ArrayCopyNode* ac = ArrayCopyNode::make(this, true, original, start, newcopy, intcon(0), moved, alloc != NULL,
+ load_object_klass(original), klass_node);
if (!is_copyOfRange) {
ac->set_copyof();
} else {
@@ -4776,8 +4789,8 @@
// Create LoadRange and LoadKlass nodes for use during macro expansion here
// so the compiler has a chance to eliminate them: during macro expansion,
// we have to set their control (CastPP nodes are eliminated).
- load_array_length(src), load_array_length(dest),
- load_object_klass(src), load_object_klass(dest));
+ load_object_klass(src), load_object_klass(dest),
+ load_array_length(src), load_array_length(dest));
if (notest) {
ac->set_arraycopy_notest();
@@ -4908,6 +4921,106 @@
return true;
}
+//-------------inline_multiplyToLen-----------------------------------
+bool LibraryCallKit::inline_multiplyToLen() {
+ assert(UseMultiplyToLenIntrinsic, "not implementated on this platform");
+
+ address stubAddr = StubRoutines::multiplyToLen();
+ if (stubAddr == NULL) {
+ return false; // Intrinsic's stub is not implemented on this platform
+ }
+ const char* stubName = "multiplyToLen";
+
+ assert(callee()->signature()->size() == 5, "multiplyToLen has 5 parameters");
+
+ Node* x = argument(1);
+ Node* xlen = argument(2);
+ Node* y = argument(3);
+ Node* ylen = argument(4);
+ Node* z = argument(5);
+
+ const Type* x_type = x->Value(&_gvn);
+ const Type* y_type = y->Value(&_gvn);
+ const TypeAryPtr* top_x = x_type->isa_aryptr();
+ const TypeAryPtr* top_y = y_type->isa_aryptr();
+ if (top_x == NULL || top_x->klass() == NULL ||
+ top_y == NULL || top_y->klass() == NULL) {
+ // failed array check
+ return false;
+ }
+
+ BasicType x_elem = x_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+ BasicType y_elem = y_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+ if (x_elem != T_INT || y_elem != T_INT) {
+ return false;
+ }
+
+ // Set the original stack and the reexecute bit for the interpreter to reexecute
+ // the bytecode that invokes BigInteger.multiplyToLen() if deoptimization happens
+ // on the return from z array allocation in runtime.
+ { PreserveReexecuteState preexecs(this);
+ jvms()->set_should_reexecute(true);
+
+ Node* x_start = array_element_address(x, intcon(0), x_elem);
+ Node* y_start = array_element_address(y, intcon(0), y_elem);
+ // 'x_start' points to x array + scaled xlen
+ // 'y_start' points to y array + scaled ylen
+
+ // Allocate the result array
+ Node* zlen = _gvn.transform(new AddINode(xlen, ylen));
+ Node* klass_node = makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_INT)));
+
+ IdealKit ideal(this);
+
+#define __ ideal.
+ Node* one = __ ConI(1);
+ Node* zero = __ ConI(0);
+ IdealVariable need_alloc(ideal), z_alloc(ideal); __ declarations_done();
+ __ set(need_alloc, zero);
+ __ set(z_alloc, z);
+ __ if_then(z, BoolTest::eq, null()); {
+ __ increment (need_alloc, one);
+ } __ else_(); {
+ // Update graphKit memory and control from IdealKit.
+ sync_kit(ideal);
+ Node* zlen_arg = load_array_length(z);
+ // Update IdealKit memory and control from graphKit.
+ __ sync_kit(this);
+ __ if_then(zlen_arg, BoolTest::lt, zlen); {
+ __ increment (need_alloc, one);
+ } __ end_if();
+ } __ end_if();
+
+ __ if_then(__ value(need_alloc), BoolTest::ne, zero); {
+ // Update graphKit memory and control from IdealKit.
+ sync_kit(ideal);
+ Node * narr = new_array(klass_node, zlen, 1);
+ // Update IdealKit memory and control from graphKit.
+ __ sync_kit(this);
+ __ set(z_alloc, narr);
+ } __ end_if();
+
+ sync_kit(ideal);
+ z = __ value(z_alloc);
+ _gvn.set_type(z, TypeAryPtr::INTS);
+ // Final sync IdealKit and GraphKit.
+ final_sync(ideal);
+#undef __
+
+ Node* z_start = array_element_address(z, intcon(0), T_INT);
+
+ Node* call = make_runtime_call(RC_LEAF|RC_NO_FP,
+ OptoRuntime::multiplyToLen_Type(),
+ stubAddr, stubName, TypePtr::BOTTOM,
+ x_start, xlen, y_start, ylen, z_start, zlen);
+ } // original reexecute is set back here
+
+ C->set_has_split_ifs(true); // Has chance for split-if optimization
+ set_result(z);
+ return true;
+}
+
+
/**
* Calculate CRC32 for byte.
* int java.util.zip.CRC32.update(int crc, int b)
--- a/hotspot/src/share/vm/opto/macroArrayCopy.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/opto/macroArrayCopy.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -506,6 +506,8 @@
Node* src_klass = ac->in(ArrayCopyNode::SrcKlass);
Node* dest_klass = ac->in(ArrayCopyNode::DestKlass);
+ assert(src_klass != NULL && dest_klass != NULL, "should have klasses");
+
// Generate the subtype check.
// This might fold up statically, or then again it might not.
//
@@ -1209,6 +1211,7 @@
// (7) src_offset + length must not exceed length of src.
Node* alen = ac->in(ArrayCopyNode::SrcLen);
+ assert(alen != NULL, "need src len");
generate_limit_guard(&ctrl,
src_offset, length,
alen,
@@ -1216,6 +1219,7 @@
// (8) dest_offset + length must not exceed length of dest.
alen = ac->in(ArrayCopyNode::DestLen);
+ assert(alen != NULL, "need dest len");
generate_limit_guard(&ctrl,
dest_offset, length,
alen,
--- a/hotspot/src/share/vm/opto/memnode.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/opto/memnode.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -2786,9 +2786,10 @@
assert(n->is_ClearArray(), "sanity");
intptr_t offset;
AllocateNode* alloc = AllocateNode::Ideal_allocation(n->in(3), phase, offset);
- // This method is called only before Allocate nodes are expanded during
- // macro nodes expansion. Before that ClearArray nodes are only generated
- // in LibraryCallKit::generate_arraycopy() which follows allocations.
+ // This method is called only before Allocate nodes are expanded
+ // during macro nodes expansion. Before that ClearArray nodes are
+ // only generated in PhaseMacroExpand::generate_arraycopy() (before
+ // Allocate nodes are expanded) which follows allocations.
assert(alloc != NULL, "should have allocation");
if (alloc->_idx == instance_id) {
// Can not bypass initialization of the instance we are looking for.
--- a/hotspot/src/share/vm/opto/phaseX.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/opto/phaseX.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -42,10 +42,14 @@
_max( round_up(est_max_size < NODE_HASH_MINIMUM_SIZE ? NODE_HASH_MINIMUM_SIZE : est_max_size) ),
_a(Thread::current()->resource_area()),
_table( NEW_ARENA_ARRAY( _a , Node* , _max ) ), // (Node**)_a->Amalloc(_max * sizeof(Node*)) ),
- _inserts(0), _insert_limit( insert_limit() ),
- _look_probes(0), _lookup_hits(0), _lookup_misses(0),
+ _inserts(0), _insert_limit( insert_limit() )
+#ifndef PRODUCT
+ ,_look_probes(0), _lookup_hits(0), _lookup_misses(0),
+ _delete_probes(0), _delete_hits(0), _delete_misses(0),
_total_insert_probes(0), _total_inserts(0),
- _insert_probes(0), _grows(0) {
+ _insert_probes(0), _grows(0)
+#endif
+{
// _sentinel must be in the current node space
_sentinel = new ProjNode(NULL, TypeFunc::Control);
memset(_table,0,sizeof(Node*)*_max);
@@ -56,11 +60,14 @@
_max( round_up(est_max_size < NODE_HASH_MINIMUM_SIZE ? NODE_HASH_MINIMUM_SIZE : est_max_size) ),
_a(arena),
_table( NEW_ARENA_ARRAY( _a , Node* , _max ) ),
- _inserts(0), _insert_limit( insert_limit() ),
- _look_probes(0), _lookup_hits(0), _lookup_misses(0),
+ _inserts(0), _insert_limit( insert_limit() )
+#ifndef PRODUCT
+ ,_look_probes(0), _lookup_hits(0), _lookup_misses(0),
_delete_probes(0), _delete_hits(0), _delete_misses(0),
_total_insert_probes(0), _total_inserts(0),
- _insert_probes(0), _grows(0) {
+ _insert_probes(0), _grows(0)
+#endif
+{
// _sentinel must be in the current node space
_sentinel = new ProjNode(NULL, TypeFunc::Control);
memset(_table,0,sizeof(Node*)*_max);
@@ -87,15 +94,15 @@
// ((Node*)n)->set_hash( n->hash() );
uint hash = n->hash();
if (hash == Node::NO_HASH) {
- debug_only( _lookup_misses++ );
+ NOT_PRODUCT( _lookup_misses++ );
return NULL;
}
uint key = hash & (_max-1);
uint stride = key | 0x01;
- debug_only( _look_probes++ );
+ NOT_PRODUCT( _look_probes++ );
Node *k = _table[key]; // Get hashed value
if( !k ) { // ?Miss?
- debug_only( _lookup_misses++ );
+ NOT_PRODUCT( _lookup_misses++ );
return NULL; // Miss!
}
@@ -108,16 +115,16 @@
if( n->in(i)!=k->in(i)) // Different inputs?
goto collision; // "goto" is a speed hack...
if( n->cmp(*k) ) { // Check for any special bits
- debug_only( _lookup_hits++ );
+ NOT_PRODUCT( _lookup_hits++ );
return k; // Hit!
}
}
collision:
- debug_only( _look_probes++ );
+ NOT_PRODUCT( _look_probes++ );
key = (key + stride/*7*/) & (_max-1); // Stride through table with relative prime
k = _table[key]; // Get hashed value
if( !k ) { // ?Miss?
- debug_only( _lookup_misses++ );
+ NOT_PRODUCT( _lookup_misses++ );
return NULL; // Miss!
}
}
@@ -132,16 +139,16 @@
// n->set_hash( );
uint hash = n->hash();
if (hash == Node::NO_HASH) {
- debug_only( _lookup_misses++ );
+ NOT_PRODUCT( _lookup_misses++ );
return NULL;
}
uint key = hash & (_max-1);
uint stride = key | 0x01; // stride must be relatively prime to table siz
uint first_sentinel = 0; // replace a sentinel if seen.
- debug_only( _look_probes++ );
+ NOT_PRODUCT( _look_probes++ );
Node *k = _table[key]; // Get hashed value
if( !k ) { // ?Miss?
- debug_only( _lookup_misses++ );
+ NOT_PRODUCT( _lookup_misses++ );
_table[key] = n; // Insert into table!
debug_only(n->enter_hash_lock()); // Lock down the node while in the table.
check_grow(); // Grow table if insert hit limit
@@ -160,16 +167,16 @@
if( n->in(i)!=k->in(i)) // Different inputs?
goto collision; // "goto" is a speed hack...
if( n->cmp(*k) ) { // Check for any special bits
- debug_only( _lookup_hits++ );
+ NOT_PRODUCT( _lookup_hits++ );
return k; // Hit!
}
}
collision:
- debug_only( _look_probes++ );
+ NOT_PRODUCT( _look_probes++ );
key = (key + stride) & (_max-1); // Stride through table w/ relative prime
k = _table[key]; // Get hashed value
if( !k ) { // ?Miss?
- debug_only( _lookup_misses++ );
+ NOT_PRODUCT( _lookup_misses++ );
key = (first_sentinel == 0) ? key : first_sentinel; // ?saw sentinel?
_table[key] = n; // Insert into table!
debug_only(n->enter_hash_lock()); // Lock down the node while in the table.
@@ -200,7 +207,7 @@
uint stride = key | 0x01;
while( 1 ) { // While probing hash table
- debug_only( _insert_probes++ );
+ NOT_PRODUCT( _insert_probes++ );
Node *k = _table[key]; // Get hashed value
if( !k || (k == _sentinel) ) break; // Found a slot
assert( k != n, "already inserted" );
@@ -218,7 +225,7 @@
Node *k;
uint hash = n->hash();
if (hash == Node::NO_HASH) {
- debug_only( _delete_misses++ );
+ NOT_PRODUCT( _delete_misses++ );
return false;
}
uint key = hash & (_max-1);
@@ -226,10 +233,10 @@
debug_only( uint counter = 0; );
for( ; /* (k != NULL) && (k != _sentinel) */; ) {
debug_only( counter++ );
- debug_only( _delete_probes++ );
+ NOT_PRODUCT( _delete_probes++ );
k = _table[key]; // Get hashed value
if( !k ) { // Miss?
- debug_only( _delete_misses++ );
+ NOT_PRODUCT( _delete_misses++ );
#ifdef ASSERT
if( VerifyOpto ) {
for( uint i=0; i < _max; i++ )
@@ -239,7 +246,7 @@
return false; // Miss! Not in chain
}
else if( n == k ) {
- debug_only( _delete_hits++ );
+ NOT_PRODUCT( _delete_hits++ );
_table[key] = _sentinel; // Hit! Label as deleted entry
debug_only(((Node*)n)->exit_hash_lock()); // Unlock the node upon removal from table.
return true;
@@ -271,11 +278,13 @@
uint old_max = _max;
Node **old_table = _table;
// Construct new table with twice the space
+#ifndef PRODUCT
_grows++;
_total_inserts += _inserts;
_total_insert_probes += _insert_probes;
+ _insert_probes = 0;
+#endif
_inserts = 0;
- _insert_probes = 0;
_max = _max << 1;
_table = NEW_ARENA_ARRAY( _a , Node* , _max ); // (Node**)_a->Amalloc( _max * sizeof(Node*) );
memset(_table,0,sizeof(Node*)*_max);
--- a/hotspot/src/share/vm/opto/phaseX.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/opto/phaseX.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -100,7 +100,6 @@
#ifndef PRODUCT
Node *find_index(uint idx); // For debugging
void dump(); // For debugging, dump statistics
-#endif
uint _grows; // For debugging, count of table grow()s
uint _look_probes; // For debugging, count of hash probes
uint _lookup_hits; // For debugging, count of hash_finds
@@ -111,6 +110,7 @@
uint _delete_misses; // For debugging, count of hash probes for deletes
uint _total_inserts; // For debugging, total inserts into hash table
uint _total_insert_probes; // For debugging, total probes while inserting
+#endif
};
--- a/hotspot/src/share/vm/opto/runtime.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/opto/runtime.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -922,6 +922,30 @@
return TypeFunc::make(domain, range);
}
+const TypeFunc* OptoRuntime::multiplyToLen_Type() {
+ // create input type (domain)
+ int num_args = 6;
+ int argcnt = num_args;
+ const Type** fields = TypeTuple::fields(argcnt);
+ int argp = TypeFunc::Parms;
+ fields[argp++] = TypePtr::NOTNULL; // x
+ fields[argp++] = TypeInt::INT; // xlen
+ fields[argp++] = TypePtr::NOTNULL; // y
+ fields[argp++] = TypeInt::INT; // ylen
+ fields[argp++] = TypePtr::NOTNULL; // z
+ fields[argp++] = TypeInt::INT; // zlen
+ assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
+ const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
+
+ // no result type needed
+ fields = TypeTuple::fields(1);
+ fields[TypeFunc::Parms+0] = NULL;
+ const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields);
+ return TypeFunc::make(domain, range);
+}
+
+
+
//------------- Interpreter state access for on stack replacement
const TypeFunc* OptoRuntime::osr_end_Type() {
// create input type (domain)
--- a/hotspot/src/share/vm/opto/runtime.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/opto/runtime.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -310,6 +310,8 @@
static const TypeFunc* sha_implCompress_Type();
static const TypeFunc* digestBase_implCompressMB_Type();
+ static const TypeFunc* multiplyToLen_Type();
+
static const TypeFunc* updateBytesCRC32_Type();
// leaf on stack replacement interpreter accessor types
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -191,7 +191,8 @@
// It is not guaranteed that we can get such information here only
// by analyzing bytecode in deoptimized frames. This is why this flag
// is set during method compilation (see Compile::Process_OopMap_Node()).
- bool save_oop_result = chunk->at(0)->scope()->return_oop();
+ // If the previous frame was popped, we don't have a result.
+ bool save_oop_result = chunk->at(0)->scope()->return_oop() && !thread->popframe_forcing_deopt_reexecution();
Handle return_value;
if (save_oop_result) {
// Reallocation may trigger GC. If deoptimization happened on return from
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -135,6 +135,8 @@
address StubRoutines::_updateBytesCRC32 = NULL;
address StubRoutines::_crc_table_adr = NULL;
+address StubRoutines::_multiplyToLen = NULL;
+
double (* StubRoutines::_intrinsic_log )(double) = NULL;
double (* StubRoutines::_intrinsic_log10 )(double) = NULL;
double (* StubRoutines::_intrinsic_exp )(double) = NULL;
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -202,6 +202,8 @@
static address _updateBytesCRC32;
static address _crc_table_adr;
+ static address _multiplyToLen;
+
// These are versions of the java.lang.Math methods which perform
// the same operations as the intrinsic version. They are used for
// constant folding in the compiler to ensure equivalence. If the
@@ -358,6 +360,8 @@
static address updateBytesCRC32() { return _updateBytesCRC32; }
static address crc_table_addr() { return _crc_table_adr; }
+ static address multiplyToLen() {return _multiplyToLen; }
+
static address select_fill_function(BasicType t, bool aligned, const char* &name);
static address zero_aligned_words() { return _zero_aligned_words; }
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -810,6 +810,7 @@
static_field(StubRoutines, _cipherBlockChaining_decryptAESCrypt, address) \
static_field(StubRoutines, _updateBytesCRC32, address) \
static_field(StubRoutines, _crc_table_adr, address) \
+ static_field(StubRoutines, _multiplyToLen, address) \
\
/*****************/ \
/* SharedRuntime */ \
--- a/hotspot/src/share/vm/utilities/hashtable.cpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/utilities/hashtable.cpp Fri Sep 05 15:53:02 2014 -0700
@@ -37,21 +37,22 @@
#include "utilities/numberSeq.hpp"
-// This is a generic hashtable, designed to be used for the symbol
-// and string tables.
-//
-// It is implemented as an open hash table with a fixed number of buckets.
-//
-// %note:
-// - HashtableEntrys are allocated in blocks to reduce the space overhead.
+// This hashtable is implemented as an open hash table with a fixed number of buckets.
-template <MEMFLAGS F> BasicHashtableEntry<F>* BasicHashtable<F>::new_entry(unsigned int hashValue) {
- BasicHashtableEntry<F>* entry;
-
- if (_free_list) {
+template <MEMFLAGS F> BasicHashtableEntry<F>* BasicHashtable<F>::new_entry_free_list() {
+ BasicHashtableEntry<F>* entry = NULL;
+ if (_free_list != NULL) {
entry = _free_list;
_free_list = _free_list->next();
- } else {
+ }
+ return entry;
+}
+
+// HashtableEntrys are allocated in blocks to reduce the space overhead.
+template <MEMFLAGS F> BasicHashtableEntry<F>* BasicHashtable<F>::new_entry(unsigned int hashValue) {
+ BasicHashtableEntry<F>* entry = new_entry_free_list();
+
+ if (entry == NULL) {
if (_first_free_entry + _entry_size >= _end_block) {
int block_size = MIN2(512, MAX2((int)_table_size / 2, (int)_number_of_entries));
int len = _entry_size * block_size;
@@ -84,9 +85,9 @@
// This is somewhat an arbitrary heuristic but if one bucket gets to
// rehash_count which is currently 100, there's probably something wrong.
-template <MEMFLAGS F> bool BasicHashtable<F>::check_rehash_table(int count) {
- assert(table_size() != 0, "underflow");
- if (count > (((double)number_of_entries()/(double)table_size())*rehash_multiple)) {
+template <class T, MEMFLAGS F> bool RehashableHashtable<T, F>::check_rehash_table(int count) {
+ assert(this->table_size() != 0, "underflow");
+ if (count > (((double)this->number_of_entries()/(double)this->table_size())*rehash_multiple)) {
// Set a flag for the next safepoint, which should be at some guaranteed
// safepoint interval.
return true;
@@ -94,13 +95,13 @@
return false;
}
-template <class T, MEMFLAGS F> juint Hashtable<T, F>::_seed = 0;
+template <class T, MEMFLAGS F> juint RehashableHashtable<T, F>::_seed = 0;
// Create a new table and using alternate hash code, populate the new table
// with the existing elements. This can be used to change the hash code
// and could in the future change the size of the table.
-template <class T, MEMFLAGS F> void Hashtable<T, F>::move_to(Hashtable<T, F>* new_table) {
+template <class T, MEMFLAGS F> void RehashableHashtable<T, F>::move_to(RehashableHashtable<T, F>* new_table) {
// Initialize the global seed for hashing.
_seed = AltHashing::compute_seed();
@@ -110,7 +111,7 @@
// Iterate through the table and create a new entry for the new table
for (int i = 0; i < new_table->table_size(); ++i) {
- for (HashtableEntry<T, F>* p = bucket(i); p != NULL; ) {
+ for (HashtableEntry<T, F>* p = this->bucket(i); p != NULL; ) {
HashtableEntry<T, F>* next = p->next();
T string = p->literal();
// Use alternate hashing algorithm on the symbol in the first table
@@ -239,11 +240,11 @@
}
}
-template <class T, MEMFLAGS F> int Hashtable<T, F>::literal_size(Symbol *symbol) {
+template <class T, MEMFLAGS F> int RehashableHashtable<T, F>::literal_size(Symbol *symbol) {
return symbol->size() * HeapWordSize;
}
-template <class T, MEMFLAGS F> int Hashtable<T, F>::literal_size(oop oop) {
+template <class T, MEMFLAGS F> int RehashableHashtable<T, F>::literal_size(oop oop) {
// NOTE: this would over-count if (pre-JDK8) java_lang_Class::has_offset_field() is true,
// and the String.value array is shared by several Strings. However, starting from JDK8,
// the String.value array is not shared anymore.
@@ -256,12 +257,12 @@
// Note: if you create a new subclass of Hashtable<MyNewType, F>, you will need to
// add a new function Hashtable<T, F>::literal_size(MyNewType lit)
-template <class T, MEMFLAGS F> void Hashtable<T, F>::dump_table(outputStream* st, const char *table_name) {
+template <class T, MEMFLAGS F> void RehashableHashtable<T, F>::dump_table(outputStream* st, const char *table_name) {
NumberSeq summary;
int literal_bytes = 0;
for (int i = 0; i < this->table_size(); ++i) {
int count = 0;
- for (HashtableEntry<T, F>* e = bucket(i);
+ for (HashtableEntry<T, F>* e = this->bucket(i);
e != NULL; e = e->next()) {
count++;
literal_bytes += literal_size(e->literal());
@@ -271,7 +272,7 @@
double num_buckets = summary.num();
double num_entries = summary.sum();
- int bucket_bytes = (int)num_buckets * sizeof(bucket(0));
+ int bucket_bytes = (int)num_buckets * sizeof(HashtableBucket<F>);
int entry_bytes = (int)num_entries * sizeof(HashtableEntry<T, F>);
int total_bytes = literal_bytes + bucket_bytes + entry_bytes;
@@ -354,12 +355,20 @@
// Explicitly instantiate these types
+#if INCLUDE_ALL_GCS
+template class Hashtable<nmethod*, mtGC>;
+template class HashtableEntry<nmethod*, mtGC>;
+template class BasicHashtable<mtGC>;
+#endif
template class Hashtable<ConstantPool*, mtClass>;
+template class RehashableHashtable<Symbol*, mtSymbol>;
+template class RehashableHashtable<oopDesc*, mtSymbol>;
template class Hashtable<Symbol*, mtSymbol>;
template class Hashtable<Klass*, mtClass>;
template class Hashtable<oop, mtClass>;
#if defined(SOLARIS) || defined(CHECK_UNHANDLED_OOPS)
template class Hashtable<oop, mtSymbol>;
+template class RehashableHashtable<oop, mtSymbol>;
#endif // SOLARIS || CHECK_UNHANDLED_OOPS
template class Hashtable<oopDesc*, mtSymbol>;
template class Hashtable<Symbol*, mtClass>;
--- a/hotspot/src/share/vm/utilities/hashtable.hpp Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/src/share/vm/utilities/hashtable.hpp Fri Sep 05 15:53:02 2014 -0700
@@ -178,11 +178,6 @@
void verify_lookup_length(double load);
#endif
- enum {
- rehash_count = 100,
- rehash_multiple = 60
- };
-
void initialize(int table_size, int entry_size, int number_of_entries);
// Accessor
@@ -194,12 +189,12 @@
// The following method is not MT-safe and must be done under lock.
BasicHashtableEntry<F>** bucket_addr(int i) { return _buckets[i].entry_addr(); }
+ // Attempt to get an entry from the free list
+ BasicHashtableEntry<F>* new_entry_free_list();
+
// Table entry management
BasicHashtableEntry<F>* new_entry(unsigned int hashValue);
- // Check that the table is unbalanced
- bool check_rehash_table(int count);
-
// Used when moving the entry to another table
// Clean up links, but do not add to free_list
void unlink_entry(BasicHashtableEntry<F>* entry) {
@@ -277,8 +272,30 @@
return (HashtableEntry<T, F>**)BasicHashtable<F>::bucket_addr(i);
}
+};
+
+template <class T, MEMFLAGS F> class RehashableHashtable : public Hashtable<T, F> {
+ protected:
+
+ enum {
+ rehash_count = 100,
+ rehash_multiple = 60
+ };
+
+ // Check that the table is unbalanced
+ bool check_rehash_table(int count);
+
+ public:
+ RehashableHashtable(int table_size, int entry_size)
+ : Hashtable<T, F>(table_size, entry_size) { }
+
+ RehashableHashtable(int table_size, int entry_size,
+ HashtableBucket<F>* buckets, int number_of_entries)
+ : Hashtable<T, F>(table_size, entry_size, buckets, number_of_entries) { }
+
+
// Function to move these elements into the new table.
- void move_to(Hashtable<T, F>* new_table);
+ void move_to(RehashableHashtable<T, F>* new_table);
static bool use_alternate_hashcode() { return _seed != 0; }
static juint seed() { return _seed; }
@@ -292,7 +309,6 @@
static int literal_size(ConstantPool *cp) {Unimplemented(); return 0;}
static int literal_size(Klass *k) {Unimplemented(); return 0;}
-public:
void dump_table(outputStream* st, const char *table_name);
private:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arraycopy/TestArrayOfNoTypeCheck.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8055910
+ * @summary Arrays.copyOf doesn't perform subtype check
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArrayOfNoTypeCheck
+ *
+ */
+
+import java.util.Arrays;
+
+public class TestArrayOfNoTypeCheck {
+
+ static class A {
+ }
+
+ static class B extends A {
+ }
+
+ static B[] test(A[] arr) {
+ return Arrays.copyOf(arr, 10, B[].class);
+ }
+
+ static public void main(String[] args) {
+ A[] arr = new A[20];
+ for (int i = 0; i < 20000; i++) {
+ test(arr);
+ }
+ A[] arr2 = new A[20];
+ arr2[0] = new A();
+ boolean exception = false;
+ try {
+ test(arr2);
+ } catch (ArrayStoreException ase) {
+ exception = true;
+ }
+ if (!exception) {
+ throw new RuntimeException("TEST FAILED: ArrayStoreException not thrown");
+ }
+ }
+}
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java Fri Sep 05 15:53:02 2014 -0700
@@ -24,6 +24,7 @@
/*
* @test
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * /compiler/testlibrary
* @build AddExactIntTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
* -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics AddExactIntTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
*/
public class AddExactIntTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java Fri Sep 05 15:53:02 2014 -0700
@@ -24,6 +24,7 @@
/*
* @test
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * /compiler/testlibrary
* @build AddExactLongTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
* -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics AddExactLongTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
*/
public class AddExactLongTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java Fri Sep 05 15:53:02 2014 -0700
@@ -24,6 +24,7 @@
/*
* @test
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * /compiler/testlibrary
* @build DecrementExactIntTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
* -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics DecrementExactIntTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
*/
public class DecrementExactIntTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java Fri Sep 05 15:53:02 2014 -0700
@@ -24,6 +24,7 @@
/*
* @test
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * /compiler/testlibrary
* @build DecrementExactLongTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
* -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics DecrementExactLongTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
*/
public class DecrementExactLongTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java Fri Sep 05 15:53:02 2014 -0700
@@ -24,6 +24,7 @@
/*
* @test
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * /compiler/testlibrary
* @build IncrementExactIntTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
* -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics IncrementExactIntTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
*/
public class IncrementExactIntTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java Fri Sep 05 15:53:02 2014 -0700
@@ -24,6 +24,7 @@
/*
* @test
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * /compiler/testlibrary
* @build IncrementExactLongTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
* -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics IncrementExactLongTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
*/
public class IncrementExactLongTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java Fri Sep 05 15:53:02 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -22,6 +22,7 @@
*/
import com.oracle.java.testlibrary.Platform;
+import intrinsics.Verifier;
import java.io.FileOutputStream;
import java.lang.reflect.Executable;
@@ -79,10 +80,10 @@
System.out.println("Expected intrinsic count is " + expectedIntrinsicCount + " name " + getIntrinsicId());
- final FileOutputStream out = new FileOutputStream(getVMOption("LogFile") + ".verify.properties");
+ final FileOutputStream out = new FileOutputStream(getVMOption("LogFile") + Verifier.PROPERTY_FILE_SUFFIX);
Properties expectedProps = new Properties();
- expectedProps.setProperty("intrinsic.name", getIntrinsicId());
- expectedProps.setProperty("intrinsic.expectedCount", String.valueOf(expectedIntrinsicCount));
+ expectedProps.setProperty(Verifier.INTRINSIC_NAME_PROPERTY, getIntrinsicId());
+ expectedProps.setProperty(Verifier.INTRINSIC_EXPECTED_COUNT_PROPERTY, String.valueOf(expectedIntrinsicCount));
expectedProps.store(out, null);
out.close();
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java Fri Sep 05 15:53:02 2014 -0700
@@ -24,6 +24,7 @@
/*
* @test
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * /compiler/testlibrary
* @build MultiplyExactIntTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
* -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics MultiplyExactIntTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
*/
public class MultiplyExactIntTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java Fri Sep 05 15:53:02 2014 -0700
@@ -24,6 +24,7 @@
/*
* @test
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * /compiler/testlibrary
* @build MultiplyExactLongTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
* -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics MultiplyExactLongTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
*/
public class MultiplyExactLongTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java Fri Sep 05 15:53:02 2014 -0700
@@ -24,6 +24,7 @@
/*
* @test
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * /compiler/testlibrary
* @build NegateExactIntTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
* -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics NegateExactIntTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
*/
public class NegateExactIntTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java Fri Sep 05 15:53:02 2014 -0700
@@ -24,6 +24,7 @@
/*
* @test
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * /compiler/testlibrary
* @build NegateExactLongTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
* -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics NegateExactLongTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
*/
public class NegateExactLongTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java Fri Sep 05 15:53:02 2014 -0700
@@ -24,6 +24,7 @@
/*
* @test
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * /compiler/testlibrary
* @build SubtractExactIntTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
* -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics SubtractExactIntTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
*/
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java Fri Sep 05 08:08:51 2014 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java Fri Sep 05 15:53:02 2014 -0700
@@ -24,6 +24,7 @@
/*
* @test
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * /compiler/testlibrary
* @build SubtractExactLongTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
@@ -35,7 +36,7 @@
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
* -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics SubtractExactLongTest
- * @run main Verifier hs_neg.log hs.log
+ * @run main intrinsics.Verifier hs_neg.log hs.log
*/
public class SubtractExactLongTest {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/Verifier.java Fri Sep 05 08:08:51 2014 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.util.Properties;
-
-public class Verifier {
-
- public static void main(String[] args) throws Exception {
- if (args.length == 0)
- throw new RuntimeException("Test bug, nothing to verify");
- for (String hsLogFile : args) {
- verify(hsLogFile);
- }
- }
-
- private static void verify(String hsLogFile) throws Exception {
- System.out.println("Verifying " + hsLogFile);
-
- final Properties expectedProperties = new Properties();
- final FileReader reader = new FileReader(hsLogFile + ".verify.properties");
- expectedProperties.load(reader);
- reader.close();
-
- int fullMatchCnt = 0;
- int suspectCnt = 0;
- final String intrinsicId = expectedProperties.getProperty("intrinsic.name");
- final String prefix = "<intrinsic id='";
- final String prefixWithId = prefix + intrinsicId + "'";
- final int expectedCount = Integer.parseInt(expectedProperties.getProperty("intrinsic.expectedCount"));
-
- BufferedReader r = new BufferedReader(new FileReader(hsLogFile));
- String s;
- while ((s = r.readLine()) != null) {
- if (s.startsWith(prefix)) {
- if (s.startsWith(prefixWithId)) {
- fullMatchCnt++;
- } else {
- suspectCnt++;
- System.out.println("WARNING: Other intrinsic detected " + s);
- }
- }
- }
- r.close();
-
- System.out.println("Intrinsic " + intrinsicId + " verification, expected: " + expectedCount + ", matched: " + fullMatchCnt + ", suspected: " + suspectCnt);
- if (expectedCount != fullMatchCnt)
- throw new RuntimeException("Unexpected count of intrinsic " + prefixWithId + " expected:" + expectedCount + ", matched: " + fullMatchCnt + ", suspected: " + suspectCnt);
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/multiplytolen/TestMultiplyToLen.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8055494
+ * @summary Add C2 x86 intrinsic for BigInteger::multiplyToLen() method
+ *
+ * @run main/othervm/timeout=600 -XX:-TieredCompilation -Xbatch
+ * -XX:CompileCommand=exclude,TestMultiplyToLen::main
+ * -XX:CompileCommand=option,TestMultiplyToLen::base_multiply,ccstr,DisableIntrinsic,_multiplyToLen
+ * -XX:CompileCommand=option,java.math.BigInteger::multiply,ccstr,DisableIntrinsic,_multiplyToLen
+ * -XX:CompileCommand=inline,java.math.BigInteger::multiply TestMultiplyToLen
+ */
+
+import java.util.Random;
+import java.math.*;
+
+public class TestMultiplyToLen {
+
+ // Avoid intrinsic by preventing inlining multiply() and multiplyToLen().
+ public static BigInteger base_multiply(BigInteger op1, BigInteger op2) {
+ return op1.multiply(op2);
+ }
+
+ // Generate multiplyToLen() intrinsic by inlining multiply().
+ public static BigInteger new_multiply(BigInteger op1, BigInteger op2) {
+ return op1.multiply(op2);
+ }
+
+ public static boolean bytecompare(BigInteger b1, BigInteger b2) {
+ byte[] data1 = b1.toByteArray();
+ byte[] data2 = b2.toByteArray();
+ if (data1.length != data2.length)
+ return false;
+ for (int i = 0; i < data1.length; i++) {
+ if (data1[i] != data2[i])
+ return false;
+ }
+ return true;
+ }
+
+ public static String stringify(BigInteger b) {
+ String strout= "";
+ byte [] data = b.toByteArray();
+ for (int i = 0; i < data.length; i++) {
+ strout += (String.format("%02x",data[i]) + " ");
+ }
+ return strout;
+ }
+
+ public static void main(String args[]) throws Exception {
+
+ BigInteger oldsum = new BigInteger("0");
+ BigInteger newsum = new BigInteger("0");
+
+ BigInteger b1, b2, oldres, newres;
+
+ Random rand = new Random();
+ long seed = System.nanoTime();
+ Random rand1 = new Random();
+ long seed1 = System.nanoTime();
+ rand.setSeed(seed);
+ rand1.setSeed(seed1);
+
+ for (int j = 0; j < 1000000; j++) {
+ int rand_int = rand1.nextInt(3136)+32;
+ int rand_int1 = rand1.nextInt(3136)+32;
+ b1 = new BigInteger(rand_int, rand);
+ b2 = new BigInteger(rand_int1, rand);
+
+ oldres = base_multiply(b1,b2);
+ newres = new_multiply(b1,b2);
+
+ oldsum = oldsum.add(oldres);
+ newsum = newsum.add(newres);
+
+ if (!bytecompare(oldres,newres)) {
+ System.out.print("mismatch for:b1:" + stringify(b1) + " :b2:" + stringify(b2) + " :oldres:" + stringify(oldres) + " :newres:" + stringify(newres));
+ System.out.println(b1);
+ System.out.println(b2);
+ throw new Exception("Failed");
+ }
+ }
+ if (!bytecompare(oldsum,newsum)) {
+ System.out.println("Failure: oldsum:" + stringify(oldsum) + " newsum:" + stringify(newsum));
+ throw new Exception("Failed");
+ } else {
+ System.out.println("Success");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/SHAOptionsBase.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import sha.predicate.IntrinsicPredicates;
+
+import java.util.function.BooleanSupplier;
+
+/**
+ * Base class for all CLI tests on SHA-related options.
+ *
+ * Instead of using huge complex tests for each option, each test is constructed
+ * from several test cases shared among different tests.
+ */
+public class SHAOptionsBase extends CommandLineOptionTest {
+ protected static final String USE_SHA_OPTION = "UseSHA";
+ protected static final String USE_SHA1_INTRINSICS_OPTION
+ = "UseSHA1Intrinsics";
+ protected static final String USE_SHA256_INTRINSICS_OPTION
+ = "UseSHA256Intrinsics";
+ protected static final String USE_SHA512_INTRINSICS_OPTION
+ = "UseSHA512Intrinsics";
+
+ // Note that strings below will be passed to
+ // CommandLineOptionTest.verifySameJVMStartup and thus are regular
+ // expressions, not just a plain strings.
+ protected static final String SHA_INSTRUCTIONS_ARE_NOT_AVAILABLE
+ = "SHA instructions are not available on this CPU";
+ protected static final String SHA1_INSTRUCTION_IS_NOT_AVAILABLE
+ = "SHA1 instruction is not available on this CPU\\.";
+ protected static final String SHA256_INSTRUCTION_IS_NOT_AVAILABLE
+ = "SHA256 instruction \\(for SHA-224 and SHA-256\\) "
+ + "is not available on this CPU\\.";
+ protected static final String SHA512_INSTRUCTION_IS_NOT_AVAILABLE
+ = "SHA512 instruction \\(for SHA-384 and SHA-512\\) "
+ + "is not available on this CPU\\.";
+ protected static final String SHA_INTRINSICS_ARE_NOT_AVAILABLE
+ = "SHA intrinsics are not available on this CPU";
+
+ private final TestCase[] testCases;
+
+ /**
+ * Returns warning message that should occur in VM output if an option with
+ * the name {@code optionName} was turned on and CPU does not support
+ * required instructions.
+ *
+ * @param optionName The name of the option for which warning message should
+ * be returned.
+ * @return A warning message that will be printed out to VM output if CPU
+ * instructions required by the option are not supported.
+ */
+ protected static String getWarningForUnsupportedCPU(String optionName) {
+ if (Platform.isSparc()) {
+ switch (optionName) {
+ case SHAOptionsBase.USE_SHA_OPTION:
+ return SHAOptionsBase.SHA_INSTRUCTIONS_ARE_NOT_AVAILABLE;
+ case SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION:
+ return SHAOptionsBase.SHA1_INSTRUCTION_IS_NOT_AVAILABLE;
+ case SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION:
+ return SHAOptionsBase.SHA256_INSTRUCTION_IS_NOT_AVAILABLE;
+ case SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION:
+ return SHAOptionsBase.SHA512_INSTRUCTION_IS_NOT_AVAILABLE;
+ default:
+ throw new Error("Unexpected option " + optionName);
+ }
+ } else if (Platform.isX64() || Platform.isX86()) {
+ switch (optionName) {
+ case SHAOptionsBase.USE_SHA_OPTION:
+ return SHAOptionsBase.SHA_INSTRUCTIONS_ARE_NOT_AVAILABLE;
+ case SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION:
+ case SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION:
+ case SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION:
+ return SHAOptionsBase.SHA_INTRINSICS_ARE_NOT_AVAILABLE;
+ default:
+ throw new Error("Unexpected option " + optionName);
+ }
+ } else {
+ throw new Error("Support for CPUs other then X86 or SPARC is not "
+ + "implemented.");
+ }
+ }
+
+ /**
+ * Returns the predicate indicating whether or not CPU instructions required
+ * by the option with name {@code optionName} are available.
+ *
+ * @param optionName The name of the option for which a predicate should be
+ * returned.
+ * @return The predicate on availability of CPU instructions required by the
+ * option.
+ */
+ protected static BooleanSupplier getPredicateForOption(String optionName) {
+ switch (optionName) {
+ case SHAOptionsBase.USE_SHA_OPTION:
+ return IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE;
+ case SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION:
+ return IntrinsicPredicates.SHA1_INSTRUCTION_AVAILABLE;
+ case SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION:
+ return IntrinsicPredicates.SHA256_INSTRUCTION_AVAILABLE;
+ case SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION:
+ return IntrinsicPredicates.SHA512_INSTRUCTION_AVAILABLE;
+ default:
+ throw new Error("Unexpected option " + optionName);
+ }
+ }
+
+ public SHAOptionsBase(TestCase... testCases) {
+ super(Boolean.TRUE::booleanValue);
+ this.testCases = testCases;
+ }
+
+ @Override
+ protected void runTestCases() throws Throwable {
+ for (TestCase testCase : testCases) {
+ testCase.test();
+ }
+ }
+
+ public static abstract class TestCase {
+ protected final String optionName;
+ private final BooleanSupplier predicate;
+
+ protected TestCase(String optionName, BooleanSupplier predicate) {
+ this.optionName = optionName;
+ this.predicate = predicate;
+ }
+
+ protected final void test() throws Throwable {
+ String testCaseName = this.getClass().getName();
+ if (!predicate.getAsBoolean()) {
+ System.out.println("Skipping " + testCaseName
+ + " due to predicate failure.");
+ return;
+ } else {
+ System.out.println("Running " + testCaseName);
+ }
+
+ verifyWarnings();
+ verifyOptionValues();
+ }
+
+ protected void verifyWarnings() throws Throwable {
+ }
+
+ protected void verifyOptionValues() throws Throwable {
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnSupportedCPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify UseSHA1Intrinsics option processing on supported CPU,
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHA1IntrinsicsOptionOnSupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI TestUseSHA1IntrinsicsOptionOnSupportedCPU
+ */
+public class TestUseSHA1IntrinsicsOptionOnSupportedCPU {
+ public static void main(String args[]) throws Throwable {
+ new SHAOptionsBase(new GenericTestCaseForSupportedSparcCPU(
+ SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION)).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify UseSHA1Intrinsics option processing on unsupported CPU,
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHA1IntrinsicsOptionOnUnsupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI
+ * TestUseSHA1IntrinsicsOptionOnUnsupportedCPU
+ */
+public class TestUseSHA1IntrinsicsOptionOnUnsupportedCPU {
+ public static void main(String args[]) throws Throwable {
+ new SHAOptionsBase(
+ new GenericTestCaseForUnsupportedSparcCPU(
+ SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION),
+ new UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU(
+ SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION),
+ new GenericTestCaseForUnsupportedX86CPU(
+ SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION),
+ new GenericTestCaseForOtherCPU(
+ SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION)).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnSupportedCPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify UseSHA256Intrinsics option processing on supported CPU,
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHA256IntrinsicsOptionOnSupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI
+ * TestUseSHA256IntrinsicsOptionOnSupportedCPU
+ */
+public class TestUseSHA256IntrinsicsOptionOnSupportedCPU {
+ public static void main(String args[]) throws Throwable {
+ new SHAOptionsBase(new GenericTestCaseForSupportedSparcCPU(
+ SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION)).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify UseSHA256Intrinsics option processing on unsupported CPU,
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHA256IntrinsicsOptionOnUnsupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI
+ * TestUseSHA256IntrinsicsOptionOnUnsupportedCPU
+ */
+public class TestUseSHA256IntrinsicsOptionOnUnsupportedCPU {
+ public static void main(String args[]) throws Throwable {
+ new SHAOptionsBase(
+ new GenericTestCaseForUnsupportedSparcCPU(
+ SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION),
+ new UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU(
+ SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION),
+ new GenericTestCaseForUnsupportedX86CPU(
+ SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION),
+ new GenericTestCaseForOtherCPU(
+ SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION)).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify UseSHA512Intrinsics option processing on supported CPU.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHA512IntrinsicsOptionOnSupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI
+ * TestUseSHA512IntrinsicsOptionOnSupportedCPU
+ */
+public class TestUseSHA512IntrinsicsOptionOnSupportedCPU {
+ public static void main(String args[]) throws Throwable {
+ new SHAOptionsBase(new GenericTestCaseForSupportedSparcCPU(
+ SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION)).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify UseSHA512Intrinsics option processing on unsupported CPU,
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHA512IntrinsicsOptionOnUnsupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI
+ * TestUseSHA512IntrinsicsOptionOnUnsupportedCPU
+ */
+public class TestUseSHA512IntrinsicsOptionOnUnsupportedCPU {
+ public static void main(String args[]) throws Throwable {
+ new SHAOptionsBase(
+ new GenericTestCaseForUnsupportedSparcCPU(
+ SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION),
+ new UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU(
+ SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION),
+ new GenericTestCaseForUnsupportedX86CPU(
+ SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION),
+ new GenericTestCaseForOtherCPU(
+ SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION)).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnSupportedCPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify UseSHA option processing on supported CPU,
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHAOptionOnSupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI TestUseSHAOptionOnSupportedCPU
+ */
+public class TestUseSHAOptionOnSupportedCPU {
+ public static void main(String args[]) throws Throwable {
+ new SHAOptionsBase(
+ new GenericTestCaseForSupportedSparcCPU(
+ SHAOptionsBase.USE_SHA_OPTION),
+ new UseSHASpecificTestCaseForSupportedSparcCPU(
+ SHAOptionsBase.USE_SHA_OPTION)).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify UseSHA option processing on unsupported CPU.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases
+ * @build TestUseSHAOptionOnUnsupportedCPU
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI TestUseSHAOptionOnUnsupportedCPU
+ */
+public class TestUseSHAOptionOnUnsupportedCPU {
+ public static void main(String args[]) throws Throwable {
+ new SHAOptionsBase(
+ new GenericTestCaseForUnsupportedSparcCPU(
+ SHAOptionsBase.USE_SHA_OPTION),
+ new UseSHASpecificTestCaseForUnsupportedSparcCPU(
+ SHAOptionsBase.USE_SHA_OPTION),
+ new GenericTestCaseForUnsupportedX86CPU(
+ SHAOptionsBase.USE_SHA_OPTION),
+ new GenericTestCaseForOtherCPU(
+ SHAOptionsBase.USE_SHA_OPTION)).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import com.oracle.java.testlibrary.cli.predicate.NotPredicate;
+import com.oracle.java.testlibrary.cli.predicate.OrPredicate;
+
+/**
+ * Generic test case for SHA-related options targeted to non-x86 and
+ * non-SPARC CPUs.
+ */
+public class GenericTestCaseForOtherCPU extends
+ SHAOptionsBase.TestCase {
+ public GenericTestCaseForOtherCPU(String optionName) {
+ // Execute the test case on any CPU except SPARC and X86
+ super(optionName, new NotPredicate(new OrPredicate(Platform::isSparc,
+ new OrPredicate(Platform::isX64, Platform::isX86))));
+ }
+
+ @Override
+ protected void verifyWarnings() throws Throwable {
+ // Verify that on non-x86 and non-SPARC CPU usage of SHA-related
+ // options will not cause any warnings.
+ CommandLineOptionTest.verifySameJVMStartup(null,
+ new String[] { ".*" + optionName + ".*" }, ExitCode.OK,
+ CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+
+ CommandLineOptionTest.verifySameJVMStartup(null,
+ new String[] { ".*" + optionName + ".*" }, ExitCode.OK,
+ CommandLineOptionTest.prepareBooleanFlag(optionName, false));
+ }
+
+ @Override
+ protected void verifyOptionValues() throws Throwable {
+ // Verify that option is disabled by default.
+ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false");
+
+ // Verify that option is disabled even if it was explicitly enabled
+ // using CLI options.
+ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+ CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+
+ // Verify that option is disabled when it explicitly disabled
+ // using CLI options.
+ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+ CommandLineOptionTest.prepareBooleanFlag(optionName, false));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedSparcCPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import com.oracle.java.testlibrary.cli.predicate.AndPredicate;
+
+/**
+ * Generic test case for SHA-related options targeted to SPARC CPUs which
+ * support instructions required by the tested option.
+ */
+public class GenericTestCaseForSupportedSparcCPU extends
+ SHAOptionsBase.TestCase {
+ public GenericTestCaseForSupportedSparcCPU(String optionName) {
+ super(optionName, new AndPredicate(Platform::isSparc,
+ SHAOptionsBase.getPredicateForOption(optionName)));
+ }
+
+ @Override
+ protected void verifyWarnings() throws Throwable {
+ // Verify that there are no warning when option is explicitly enabled.
+ CommandLineOptionTest.verifySameJVMStartup(null, new String[] {
+ SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+ }, ExitCode.OK,
+ CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+
+ // Verify that option could be disabled even if +UseSHA was passed to
+ // JVM.
+ CommandLineOptionTest.verifySameJVMStartup(null, new String[] {
+ SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+ }, ExitCode.OK,
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA_OPTION, true),
+ CommandLineOptionTest.prepareBooleanFlag(optionName, false));
+
+ // Verify that it is possible to enable the tested option and disable
+ // all SHA intrinsics via -UseSHA without any warnings.
+ CommandLineOptionTest.verifySameJVMStartup(null, new String[] {
+ SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+ }, ExitCode.OK,
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA_OPTION, false),
+ CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+ }
+
+ @Override
+ protected void verifyOptionValues() throws Throwable {
+ // Verify that on supported CPU option is enabled by default.
+ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true");
+
+ // Verify that it is possible to explicitly enable the option.
+ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true",
+ CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+
+ // Verify that it is possible to explicitly disable the option.
+ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+ CommandLineOptionTest.prepareBooleanFlag(optionName, false));
+
+ // verify that option is disabled when -UseSHA was passed to JVM.
+ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+ CommandLineOptionTest.prepareBooleanFlag(optionName, true),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA_OPTION, false));
+
+ // Verify that it is possible to explicitly disable the tested option
+ // even if +UseSHA was passed to JVM.
+ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA_OPTION, true),
+ CommandLineOptionTest.prepareBooleanFlag(optionName, false));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedSparcCPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import com.oracle.java.testlibrary.cli.predicate.AndPredicate;
+import com.oracle.java.testlibrary.cli.predicate.NotPredicate;
+
+/**
+ * Generic test case for SHA-related options targeted to SPARC CPUs which don't
+ * support instruction required by the tested option.
+ */
+public class GenericTestCaseForUnsupportedSparcCPU extends
+ SHAOptionsBase.TestCase {
+ public GenericTestCaseForUnsupportedSparcCPU(String optionName) {
+ super(optionName, new AndPredicate(Platform::isSparc,
+ new NotPredicate(SHAOptionsBase.getPredicateForOption(
+ optionName))));
+ }
+
+ @Override
+ protected void verifyWarnings() throws Throwable {
+ //Verify that option could be disabled without any warnings.
+ CommandLineOptionTest.verifySameJVMStartup(null, new String[] {
+ SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+ }, ExitCode.OK,
+ CommandLineOptionTest.prepareBooleanFlag(optionName, false));
+ }
+
+ @Override
+ protected void verifyOptionValues() throws Throwable {
+ // Verify that option is disabled by default.
+ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false");
+
+ // Verify that option is disabled even if it was explicitly enabled
+ // using CLI options.
+ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+ CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+
+ // Verify that option is disabled when +UseSHA was passed to JVM.
+ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA_OPTION, true));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedX86CPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import com.oracle.java.testlibrary.cli.predicate.OrPredicate;
+
+/**
+ * Generic test case for SHA-related options targeted to X86 CPUs that don't
+ * support SHA-related instructions.
+ */
+public class GenericTestCaseForUnsupportedX86CPU
+ extends SHAOptionsBase.TestCase {
+ public GenericTestCaseForUnsupportedX86CPU(String optionName) {
+ super(optionName, new OrPredicate(Platform::isX64, Platform::isX86));
+ }
+
+ @Override
+ protected void verifyWarnings() throws Throwable {
+ // Verify that when the tested option is explicitly enabled, then
+ // a warning will occur in VM output.
+ CommandLineOptionTest.verifySameJVMStartup(new String[] {
+ SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+ }, null, ExitCode.OK,
+ CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+
+ // Verify that the tested option could be explicitly disabled without
+ // a warning.
+ CommandLineOptionTest.verifySameJVMStartup(null, new String[] {
+ SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+ }, ExitCode.OK,
+ CommandLineOptionTest.prepareBooleanFlag(optionName, false));
+ }
+
+ @Override
+ protected void verifyOptionValues() throws Throwable {
+ // Verify that the tested option is disabled by default.
+ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false");
+
+ // Verify that it is not possible to explicitly enable the option.
+ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+ CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+
+ // Verify that the tested option is disabled even if +UseSHA was passed
+ // to JVM.
+ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false",
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA_OPTION, true));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import com.oracle.java.testlibrary.cli.predicate.AndPredicate;
+import com.oracle.java.testlibrary.cli.predicate.NotPredicate;
+import sha.predicate.IntrinsicPredicates;
+
+/**
+ * Test case specific to UseSHA*Intrinsics options targeted to SPARC CPUs which
+ * don't support required instruction, but support other SHA-related
+ * instructions.
+ *
+ * For example, CPU support sha1 instruction, but don't support sha256 or
+ * sha512.
+ */
+public class UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU
+ extends SHAOptionsBase.TestCase {
+ public UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU(
+ String optionName) {
+ // execute test case on SPARC CPU that support any sha* instructions,
+ // but does not support sha* instruction required by the tested option.
+ super(optionName, new AndPredicate(Platform::isSparc,
+ new AndPredicate(
+ IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE,
+ new NotPredicate(SHAOptionsBase.getPredicateForOption(
+ optionName)))));
+ }
+ @Override
+ protected void verifyWarnings() throws Throwable {
+ // Verify that attempt to enable the tested option will cause a warning.
+ CommandLineOptionTest.verifySameJVMStartup(new String[] {
+ SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+ }, null, ExitCode.OK,
+ CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForSupportedSparcCPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.oracle.java.testlibrary.Asserts;
+import com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import com.oracle.java.testlibrary.cli.predicate.AndPredicate;
+import sha.predicate.IntrinsicPredicates;
+
+/**
+ * UseSHA specific test case targeted to SPARC CPUs which support any sha*
+ * instruction.
+ */
+public class UseSHASpecificTestCaseForSupportedSparcCPU
+ extends SHAOptionsBase.TestCase {
+ public UseSHASpecificTestCaseForSupportedSparcCPU(String optionName) {
+ super(SHAOptionsBase.USE_SHA_OPTION, new AndPredicate(Platform::isSparc,
+ IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE));
+
+ Asserts.assertEQ(optionName, SHAOptionsBase.USE_SHA_OPTION,
+ "Test case should be used for " + SHAOptionsBase.USE_SHA_OPTION
+ + " option only.");
+ }
+
+ @Override
+ protected void verifyWarnings() throws Throwable {
+ // Verify that there will be no warnings when +UseSHA was passed and
+ // all UseSHA*Intrinsics options were disabled.
+ CommandLineOptionTest.verifySameJVMStartup(
+ null, new String[] { ".*UseSHA.*" }, ExitCode.OK,
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA_OPTION, true),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION, false),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION, false),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION, false));
+ }
+
+ @Override
+ protected void verifyOptionValues() throws Throwable {
+ // Verify that UseSHA is disabled when all UseSHA*Intrinscs are
+ // disabled.
+ CommandLineOptionTest.verifyOptionValueForSameVM(
+ SHAOptionsBase.USE_SHA_OPTION, "false",
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION, false),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION, false),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION, false));
+
+ CommandLineOptionTest.verifyOptionValueForSameVM(
+ // Verify that UseSHA is disabled when all UseSHA*Intrinscs are
+ // disabled even if it was explicitly enabled.
+ SHAOptionsBase.USE_SHA_OPTION, "false",
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA_OPTION, true),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION, false),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION, false),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION, false));
+
+ // Verify that explicitly disabled UseSHA option remains disabled even
+ // if all UseSHA*Intrinsics options were enabled.
+ CommandLineOptionTest.verifyOptionValueForSameVM(
+ SHAOptionsBase.USE_SHA_OPTION, "false",
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA_OPTION, false),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION, true),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION, true),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION, true));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForUnsupportedSparcCPU.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.oracle.java.testlibrary.Asserts;
+import com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+import com.oracle.java.testlibrary.cli.predicate.AndPredicate;
+import com.oracle.java.testlibrary.cli.predicate.NotPredicate;
+import sha.predicate.IntrinsicPredicates;
+
+/**
+ * UseSHA specific test case targeted to SPARC CPUs which don't support all sha*
+ * instructions.
+ */
+public class UseSHASpecificTestCaseForUnsupportedSparcCPU
+ extends SHAOptionsBase.TestCase {
+ public UseSHASpecificTestCaseForUnsupportedSparcCPU(String optionName) {
+ super(SHAOptionsBase.USE_SHA_OPTION, new AndPredicate(Platform::isSparc,
+ new NotPredicate(
+ IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE)));
+
+ Asserts.assertEQ(optionName, SHAOptionsBase.USE_SHA_OPTION,
+ "Test case should be used for " + SHAOptionsBase.USE_SHA_OPTION
+ + " option only.");
+ }
+
+ @Override
+ protected void verifyWarnings() throws Throwable {
+ // Verify that attempt to use UseSHA option will cause a warning.
+ CommandLineOptionTest.verifySameJVMStartup(new String[] {
+ SHAOptionsBase.getWarningForUnsupportedCPU(optionName)
+ }, null, ExitCode.OK,
+ CommandLineOptionTest.prepareBooleanFlag(optionName, true));
+ }
+
+ @Override
+ protected void verifyOptionValues() throws Throwable {
+ // Verify that UseSHA option remains disabled even if all
+ // UseSHA*Intrincs options were enabled.
+ CommandLineOptionTest.verifyOptionValueForSameVM(
+ SHAOptionsBase.USE_SHA_OPTION, "false",
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION, true),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION, true),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION, true));
+
+ // Verify that UseSHA option remains disabled even if all
+ // UseSHA*Intrincs options were enabled and UseSHA was enabled as well.
+ CommandLineOptionTest.verifyOptionValueForSameVM(
+ SHAOptionsBase.USE_SHA_OPTION, "false",
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA_OPTION, true),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION, true),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION, true),
+ CommandLineOptionTest.prepareBooleanFlag(
+ SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION, true));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/sanity/SHASanityTestBase.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import intrinsics.Verifier;
+import sun.hotspot.WhiteBox;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.function.BooleanSupplier;
+
+/**
+ * Base class for sanity tests on SHA intrinsics support.
+ */
+public class SHASanityTestBase {
+ protected static final String SHA1_INTRINSIC_ID
+ = "_sha_implCompress";
+ protected static final String SHA256_INTRINSIC_ID
+ = "_sha2_implCompress";
+ protected static final String SHA512_INTRINSIC_ID
+ = "_sha5_implCompress";
+ protected static final String MB_INTRINSIC_ID
+ = "_digestBase_implCompressMB";
+
+ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+ private static final int MSG_SIZE = 1024;
+ private static final int OFFSET = 0;
+ private static final int ITERATIONS = 10000;
+ private static final int WARMUP_ITERATIONS = 1;
+ private static final String PROVIDER = "SUN";
+
+ private final BooleanSupplier predicate;
+ private final String intrinsicID;
+
+ /**
+ * Construct the new test on intrinsic with ID {@code intrinsicID},
+ * which is expected to be emitted if {@code predicate} is evaluated to
+ * {@code true}.
+ *
+ * @param predicate The predicate indicating if the intrinsic is expected to
+ * be used.
+ * @param intrinsicID The ID of the intrinsic to be tested.
+ */
+ protected SHASanityTestBase(BooleanSupplier predicate, String intrinsicID) {
+ this.predicate = predicate;
+ this.intrinsicID = intrinsicID;
+ }
+
+ /**
+ * Run the test and dump properties to file.
+ *
+ * @throws Exception when something went wrong.
+ */
+ public final void test() throws Exception {
+ String algorithm = Objects.requireNonNull(
+ System.getProperty("algorithm"),
+ "Algorithm name should be specified.");
+
+ dumpProperties();
+
+ TestSHA.testSHA(SHASanityTestBase.PROVIDER, algorithm,
+ SHASanityTestBase.MSG_SIZE, SHASanityTestBase.OFFSET,
+ SHASanityTestBase.ITERATIONS,
+ SHASanityTestBase.WARMUP_ITERATIONS);
+ }
+
+ /**
+ * Dump properties containing information about the tested intrinsic name
+ * and whether or not is should be used to the file
+ * <LogFile value>.verify.properties.
+ *
+ * @throws IOException when something went wrong during dumping to file.
+ */
+ private void dumpProperties() throws IOException {
+ Properties properties = new Properties();
+ properties.setProperty(Verifier.INTRINSIC_NAME_PROPERTY, intrinsicID);
+ properties.setProperty(Verifier.INTRINSIC_IS_EXPECTED_PROPERTY,
+ String.valueOf(predicate.getAsBoolean()));
+
+ String logFileName
+ = SHASanityTestBase.WHITE_BOX.getStringVMFlag("LogFile");
+ FileOutputStream fileOutputStream = new FileOutputStream(logFileName
+ + Verifier.PROPERTY_FILE_SUFFIX);
+
+ properties.store(fileOutputStream, null);
+ fileOutputStream.close();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify that SHA-1 intrinsic is actually used.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../
+ * @build TestSHA intrinsics.Verifier TestSHA1Intrinsics
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA1Intrinsics
+ * -Dalgorithm=SHA-1 TestSHA1Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=negative.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:-UseSHA1Intrinsics
+ * -Dalgorithm=SHA-1 TestSHA1Intrinsics
+ * @run main/othervm -DverificationStrategy=VERIFY_INTRINSIC_USAGE
+ * intrinsics.Verifier positive.log negative.log
+ */
+import sha.predicate.IntrinsicPredicates;
+
+public class TestSHA1Intrinsics {
+ public static void main(String args[]) throws Exception {
+ new SHASanityTestBase(IntrinsicPredicates.SHA1_INTRINSICS_AVAILABLE,
+ SHASanityTestBase.SHA1_INTRINSIC_ID).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import sha.predicate.IntrinsicPredicates;
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify that SHA-1 multi block intrinsic is actually used.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../
+ * @build TestSHA intrinsics.Verifier TestSHA1MultiBlockIntrinsics
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA1Intrinsics -XX:-UseSHA256Intrinsics
+ * -XX:-UseSHA512Intrinsics
+ * -Dalgorithm=SHA-1 TestSHA1MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive_def.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA1Intrinsics -Dalgorithm=SHA-1
+ * TestSHA1MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=negative.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA -XX:-UseSHA
+ * -Dalgorithm=SHA-1 TestSHA1MultiBlockIntrinsics
+ * @run main/othervm -DverificationStrategy=VERIFY_INTRINSIC_USAGE
+ * intrinsics.Verifier positive.log positive_def.log
+ * negative.log
+ */
+public class TestSHA1MultiBlockIntrinsics {
+ public static void main(String args[]) throws Exception {
+ new SHASanityTestBase(IntrinsicPredicates.SHA1_INTRINSICS_AVAILABLE,
+ SHASanityTestBase.MB_INTRINSIC_ID).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import sha.predicate.IntrinsicPredicates;
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify that SHA-256 intrinsic is actually used.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../
+ * @build TestSHA intrinsics.Verifier TestSHA256Intrinsics
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive_224.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA256Intrinsics
+ * -Dalgorithm=SHA-224 TestSHA256Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=negative_224.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:-UseSHA256Intrinsics
+ * -Dalgorithm=SHA-224 TestSHA256Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive_256.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA256Intrinsics
+ * -Dalgorithm=SHA-256 TestSHA256Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=negative_256.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:-UseSHA256Intrinsics
+ * -Dalgorithm=SHA-256 TestSHA256Intrinsics
+ * @run main/othervm -DverificationStrategy=VERIFY_INTRINSIC_USAGE
+ * intrinsics.Verifier positive_224.log positive_256.log
+ * negative_224.log negative_256.log
+ */
+public class TestSHA256Intrinsics {
+ public static void main(String args[]) throws Exception {
+ new SHASanityTestBase(IntrinsicPredicates.SHA256_INTRINSICS_AVAILABLE,
+ SHASanityTestBase.SHA256_INTRINSIC_ID).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import sha.predicate.IntrinsicPredicates;
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify that SHA-256 multi block intrinsic is actually used.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../
+ * @build TestSHA intrinsics.Verifier TestSHA256MultiBlockIntrinsics
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive_224.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA256Intrinsics -XX:-UseSHA1Intrinsics
+ * -XX:-UseSHA512Intrinsics
+ * -Dalgorithm=SHA-224 TestSHA256MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive_224_def.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA256Intrinsics -Dalgorithm=SHA-224
+ * TestSHA256MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=negative_224.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA -XX:-UseSHA
+ * -Dalgorithm=SHA-224 TestSHA256MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive_256.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA256Intrinsics -XX:-UseSHA1Intrinsics
+ * -XX:-UseSHA512Intrinsics
+ * -Dalgorithm=SHA-256 TestSHA256MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive_256_def.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA256Intrinsics -Dalgorithm=SHA-256
+ * TestSHA256MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=negative_256.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA -XX:-UseSHA
+ * -Dalgorithm=SHA-256 TestSHA256MultiBlockIntrinsics
+ * @run main/othervm -DverificationStrategy=VERIFY_INTRINSIC_USAGE
+ * intrinsics.Verifier positive_224.log positive_256.log
+ * positive_224_def.log positive_256_def.log negative_224.log
+ * negative_256.log
+ */
+public class TestSHA256MultiBlockIntrinsics {
+ public static void main(String args[]) throws Exception {
+ new SHASanityTestBase(IntrinsicPredicates.SHA256_INTRINSICS_AVAILABLE,
+ SHASanityTestBase.MB_INTRINSIC_ID).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import sha.predicate.IntrinsicPredicates;
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify that SHA-512 intrinsic is actually used.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../
+ * @build TestSHA intrinsics.Verifier TestSHA512Intrinsics
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive_384.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA512Intrinsics
+ * -Dalgorithm=SHA-384 TestSHA512Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=negative_384.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:-UseSHA512Intrinsics
+ * -Dalgorithm=SHA-384 TestSHA512Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive_512.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA512Intrinsics
+ * -Dalgorithm=SHA-512 TestSHA512Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=negative_512.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:-UseSHA512Intrinsics
+ * -Dalgorithm=SHA-512 TestSHA512Intrinsics
+ * @run main/othervm -DverificationStrategy=VERIFY_INTRINSIC_USAGE
+ * intrinsics.Verifier positive_384.log positive_512.log
+ * negative_384.log negative_512.log
+ */
+public class TestSHA512Intrinsics {
+ public static void main(String args[]) throws Exception {
+ new SHASanityTestBase(IntrinsicPredicates.SHA512_INTRINSICS_AVAILABLE,
+ SHASanityTestBase.SHA512_INTRINSIC_ID).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import sha.predicate.IntrinsicPredicates;
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary Verify that SHA-512 multi block intrinsic is actually used.
+ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../
+ * @build TestSHA intrinsics.Verifier TestSHA512MultiBlockIntrinsics
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive_384.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA512Intrinsics -XX:-UseSHA1Intrinsics
+ * -XX:-UseSHA256Intrinsics
+ * -Dalgorithm=SHA-384 TestSHA512MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive_384_def.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA512Intrinsics -Dalgorithm=SHA-384
+ * TestSHA512MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=negative_384.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA -XX:-UseSHA
+ * -Dalgorithm=SHA-384 TestSHA1Intrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive_512.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA512Intrinsics -XX:-UseSHA1Intrinsics
+ * -XX:-UseSHA256Intrinsics
+ * -Dalgorithm=SHA-512 TestSHA512MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=positive_512_def.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA
+ * -XX:+UseSHA512Intrinsics -Dalgorithm=SHA-512
+ * TestSHA512MultiBlockIntrinsics
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -Xbatch -XX:CompileThreshold=500
+ * -XX:Tier4InvocationThreshold=500
+ * -XX:+LogCompilation -XX:LogFile=negative_512.log
+ * -XX:CompileOnly=sun/security/provider/DigestBase
+ * -XX:CompileOnly=sun/security/provider/SHA -XX:-UseSHA
+ * -Dalgorithm=SHA-512 TestSHA512MultiBlockIntrinsics
+ * @run main/othervm -DverificationStrategy=VERIFY_INTRINSIC_USAGE
+ * intrinsics.Verifier positive_384.log positive_512.log
+ * positive_384_def.log positive_512_def.log negative_384.log
+ * negative_512.log
+ */
+public class TestSHA512MultiBlockIntrinsics {
+ public static void main(String args[]) throws Exception {
+ new SHASanityTestBase(IntrinsicPredicates.SHA512_INTRINSICS_AVAILABLE,
+ SHASanityTestBase.MB_INTRINSIC_ID).test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/intrinsics/Verifier.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+package intrinsics;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.util.Properties;
+
+public class Verifier {
+ enum VerificationStrategy {
+ VERIFY_STRONG_EQUALITY {
+ @Override
+ void verify(Properties expectedProperties, int fullMatchCnt,
+ int suspectCnt) {
+ int expectedCount = Integer.parseInt(
+ expectedProperties.getProperty(
+ Verifier.INTRINSIC_EXPECTED_COUNT_PROPERTY));
+ String intrinsicID = expectedProperties.getProperty(
+ Verifier.INTRINSIC_NAME_PROPERTY);
+
+ System.out.println("Intrinsic " + intrinsicID
+ + " verification, expected: " + expectedCount
+ + ", matched: " + fullMatchCnt
+ + ", suspected: " + suspectCnt);
+ if (expectedCount != fullMatchCnt) {
+ throw new RuntimeException(
+ "Unexpected count of intrinsic "
+ + intrinsicID
+ + " expected:" + expectedCount
+ + ", matched: " + fullMatchCnt
+ + ", suspected: " + suspectCnt);
+ }
+ }
+ },
+
+ VERIFY_INTRINSIC_USAGE {
+ @Override
+ void verify(Properties expectedProperties, int fullMatchCnt,
+ int suspectCnt) {
+ boolean isExpected = Boolean.parseBoolean(
+ expectedProperties.getProperty(
+ Verifier.INTRINSIC_IS_EXPECTED_PROPERTY));
+ String intrinsicID = expectedProperties.getProperty(
+ Verifier.INTRINSIC_NAME_PROPERTY);
+
+ System.out.println("Intrinsic " + intrinsicID
+ + " verification, is expected: " + isExpected
+ + ", matched: " + fullMatchCnt
+ + ", suspected: " + suspectCnt);
+ if ((fullMatchCnt == 0 && isExpected)
+ || (fullMatchCnt > 0 && !isExpected)) {
+ throw new RuntimeException(
+ "Unexpected count of intrinsic "
+ + intrinsicID
+ + " is expected:" + isExpected
+ + ", matched: " + fullMatchCnt
+ + ", suspected: " + suspectCnt);
+ }
+ }
+ };
+
+ void verify(Properties expectedProperties, int fullMathCnt,
+ int suspectCnt) {
+ throw new RuntimeException("Default strategy is not implemented.");
+ }
+ }
+
+ public static final String PROPERTY_FILE_SUFFIX = ".verify.properties";
+ public static final String INTRINSIC_NAME_PROPERTY = "intrinsic.name";
+ public static final String INTRINSIC_IS_EXPECTED_PROPERTY
+ = "intrinsic.expected";
+ public static final String INTRINSIC_EXPECTED_COUNT_PROPERTY
+ = "intrinsic.expectedCount";
+ private static final String DEFAULT_STRATEGY
+ = VerificationStrategy.VERIFY_STRONG_EQUALITY.name();
+
+ public static void main(String[] args) throws Exception {
+ if (args.length == 0) {
+ throw new RuntimeException("Test bug, nothing to verify");
+ }
+ for (String hsLogFile : args) {
+ verify(hsLogFile);
+ }
+ }
+
+ private static void verify(String hsLogFile) throws Exception {
+ System.out.println("Verifying " + hsLogFile);
+
+ Properties expectedProperties = new Properties();
+ FileReader reader = new FileReader(hsLogFile
+ + Verifier.PROPERTY_FILE_SUFFIX);
+ expectedProperties.load(reader);
+ reader.close();
+
+ int fullMatchCnt = 0;
+ int suspectCnt = 0;
+ String intrinsicId = expectedProperties.getProperty(
+ Verifier.INTRINSIC_NAME_PROPERTY);
+ String prefix = "<intrinsic id='";
+ String prefixWithId = prefix + intrinsicId + "'";
+
+ try (BufferedReader compLogReader
+ = new BufferedReader(new FileReader(hsLogFile))) {
+ String logLine;
+ while ((logLine = compLogReader.readLine()) != null) {
+ if (logLine.startsWith(prefix)) {
+ if (logLine.startsWith(prefixWithId)) {
+ fullMatchCnt++;
+ } else {
+ suspectCnt++;
+ System.err.println(
+ "WARNING: Other intrinsic detected " + logLine);
+ }
+ }
+ }
+ }
+
+ VerificationStrategy strategy = VerificationStrategy.valueOf(
+ System.getProperty("verificationStrategy",
+ Verifier.DEFAULT_STRATEGY));
+ strategy.verify(expectedProperties, fullMatchCnt, suspectCnt);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java Fri Sep 05 15:53:02 2014 -0700
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sha.predicate;
+
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.cli.predicate.AndPredicate;
+import com.oracle.java.testlibrary.cli.predicate.CPUSpecificPredicate;
+import com.oracle.java.testlibrary.cli.predicate.OrPredicate;
+import sun.hotspot.WhiteBox;
+
+import java.util.function.BooleanSupplier;
+
+/**
+ * Helper class aimed to provide predicates on availability of SHA-related
+ * CPU instructions and intrinsics.
+ */
+public class IntrinsicPredicates {
+ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+ private static final long TIERED_MAX_LEVEL = 4L;
+ /**
+ * Boolean supplier that check if any method could be compiled by C2.
+ * Method potentially could be compiled by C2 if Server VM is used and
+ * either tiered compilation is disabled or TIERED_MAX_LEVEL tier is
+ * reachable.
+ *
+ * Please don't place this definition after SHA*_INTRINSICS_AVAILABLE
+ * definitions. Otherwise its value will be {@code null} at the time when
+ * all dependent fields will be initialized.
+ */
+ private static final BooleanSupplier COMPILABLE_BY_C2 = () -> {
+ boolean isTiered = IntrinsicPredicates.WHITE_BOX.getBooleanVMFlag(
+ "TieredCompilation");
+ long tieredMaxLevel = IntrinsicPredicates.WHITE_BOX.getIntxVMFlag(
+ "TieredStopAtLevel");
+ boolean maxLevelIsReachable = (tieredMaxLevel
+ == IntrinsicPredicates.TIERED_MAX_LEVEL);
+ return Platform.isServer() && (!isTiered || maxLevelIsReachable);
+ };
+
+ public static final BooleanSupplier SHA1_INSTRUCTION_AVAILABLE
+ = new CPUSpecificPredicate("sparc.*", new String[] { "sha1" },
+ null);
+
+ public static final BooleanSupplier SHA256_INSTRUCTION_AVAILABLE
+ = new CPUSpecificPredicate("sparc.*", new String[] { "sha256" },
+ null);
+
+ public static final BooleanSupplier SHA512_INSTRUCTION_AVAILABLE
+ = new CPUSpecificPredicate("sparc.*", new String[] { "sha512" },
+ null);
+
+ public static final BooleanSupplier ANY_SHA_INSTRUCTION_AVAILABLE
+ = new OrPredicate(IntrinsicPredicates.SHA1_INSTRUCTION_AVAILABLE,
+ new OrPredicate(
+ IntrinsicPredicates.SHA256_INSTRUCTION_AVAILABLE,
+ IntrinsicPredicates.SHA512_INSTRUCTION_AVAILABLE));
+
+ public static final BooleanSupplier SHA1_INTRINSICS_AVAILABLE
+ = new AndPredicate(new AndPredicate(
+ IntrinsicPredicates.SHA1_INSTRUCTION_AVAILABLE,
+ IntrinsicPredicates.COMPILABLE_BY_C2),
+ IntrinsicPredicates.booleanOptionValue("UseSHA1Intrinsics"));
+
+ public static final BooleanSupplier SHA256_INTRINSICS_AVAILABLE
+ = new AndPredicate(new AndPredicate(
+ IntrinsicPredicates.SHA256_INSTRUCTION_AVAILABLE,
+ IntrinsicPredicates.COMPILABLE_BY_C2),
+ IntrinsicPredicates.booleanOptionValue("UseSHA256Intrinsics"));
+
+ public static final BooleanSupplier SHA512_INTRINSICS_AVAILABLE
+ = new AndPredicate(new AndPredicate(
+ IntrinsicPredicates.SHA512_INSTRUCTION_AVAILABLE,
+ IntrinsicPredicates.COMPILABLE_BY_C2),
+ IntrinsicPredicates.booleanOptionValue("UseSHA512Intrinsics"));
+
+ private static BooleanSupplier booleanOptionValue(String option) {
+ return () -> IntrinsicPredicates.WHITE_BOX.getBooleanVMFlag(option);
+ }
+
+ private IntrinsicPredicates() {
+ }
+}