--- a/hotspot/make/lib/CompileDtracePostJvm.gmk Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/make/lib/CompileDtracePostJvm.gmk Thu Dec 22 22:07:36 2016 +0100
@@ -188,7 +188,6 @@
LIBS := $(LIBDL) -lc -lthread -ldoor, \
MAPFILE := $(HOTSPOT_TOPDIR)/make/mapfiles/libjvm_dtrace/mapfile-vers, \
OBJECT_DIR := $(LIBJVM_DTRACE_OUTPUTDIR)/objs, \
- STRIP_SYMBOLS := true, \
))
LIBJVM_DB_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_db
@@ -206,7 +205,6 @@
LIBS := -lc, \
MAPFILE := $(HOTSPOT_TOPDIR)/make/mapfiles/libjvm_db/mapfile-vers, \
OBJECT_DIR := $(LIBJVM_DB_OUTPUTDIR)/objs, \
- STRIP_SYMBOLS := true, \
))
# We need the generated JvmOffsets.h before we can compile the libjvm_db source code.
--- a/hotspot/make/lib/CompileGtest.gmk Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/make/lib/CompileGtest.gmk Thu Dec 22 22:07:36 2016 +0100
@@ -54,6 +54,13 @@
# Disabling switch warning for clang because of test source.
+# Note: On AIX, the gtest test classes linked into the libjvm.so push the TOC
+# size beyond 64k, so we need to link with bigtoc. However, this means that
+# -qpic=large would be advisable to lessen the performance effect of bigtoc.
+# But we want to avoid imposing -qpic=large onto the regular libjvm.so, which
+# has no problem with its TOC, so do this only for object files which are
+# exclusive to the gtest libjvm.so.
+
$(eval $(call SetupNativeCompilation, BUILD_GTEST_LIBJVM, \
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
LIBRARY := jvm, \
@@ -72,6 +79,7 @@
CFLAGS_windows := -EHsc, \
CFLAGS_solaris := -DGTEST_HAS_EXCEPTIONS=0 -library=stlport4, \
CFLAGS_macosx := -DGTEST_OS_MAC=1, \
+ CFLAGS_aix := -qpic=large, \
CFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
CXXFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
DISABLED_WARNINGS_gcc := undef, \
@@ -80,12 +88,14 @@
DISABLED_WARNINGS_solstudio := identexpected, \
LDFLAGS := $(JVM_LDFLAGS), \
LDFLAGS_solaris := -library=stlport4 $(call SET_SHARED_LIBRARY_ORIGIN), \
+ LDFLAGS_aix := -bbigtoc, \
LIBS := $(JVM_LIBS), \
OPTIMIZATION := $(JVM_OPTIMIZATION), \
MAPFILE := $(GTEST_JVM_MAPFILE), \
USE_MAPFILE_FOR_SYMBOLS := true, \
COPY_DEBUG_SYMBOLS := $(GTEST_COPY_DEBUG_SYMBOLS), \
ZIP_EXTERNAL_DEBUG_SYMBOLS := false, \
+ STRIP_SYMBOLS := false, \
PRECOMPILED_HEADER := $(JVM_PRECOMPILED_HEADER), \
PRECOMPILED_HEADER_EXCLUDE := gtest-all.cc gtestMain.cpp, \
))
--- a/hotspot/make/lib/Lib-jdk.hotspot.agent.gmk Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/make/lib/Lib-jdk.hotspot.agent.gmk Thu Dec 22 22:07:36 2016 +0100
@@ -113,7 +113,6 @@
LIBS := $(SA_LIBS), \
MAPFILE := $(SA_MAPFILE), \
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libsa, \
- STRIP_SYMBOLS := true, \
))
TARGETS += $(BUILD_LIBSA)
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Thu Dec 22 22:07:36 2016 +0100
@@ -14086,7 +14086,7 @@
format %{ "mul rscratch1, $op1, $op2\t#overflow check long\n\t"
"smulh rscratch2, $op1, $op2\n\t"
- "cmp rscratch2, rscratch1, ASR #31\n\t"
+ "cmp rscratch2, rscratch1, ASR #63\n\t"
"movw rscratch1, #0x80000000\n\t"
"cselw rscratch1, rscratch1, zr, NE\n\t"
"cmpw rscratch1, #1" %}
@@ -14094,7 +14094,7 @@
ins_encode %{
__ mul(rscratch1, $op1$$Register, $op2$$Register); // Result bits 0..63
__ smulh(rscratch2, $op1$$Register, $op2$$Register); // Result bits 64..127
- __ cmp(rscratch2, rscratch1, Assembler::ASR, 31); // Top is pure sign ext
+ __ cmp(rscratch2, rscratch1, Assembler::ASR, 63); // Top is pure sign ext
__ movw(rscratch1, 0x80000000); // Develop 0 (EQ),
__ cselw(rscratch1, rscratch1, zr, Assembler::NE); // or 0x80000000 (NE)
__ cmpw(rscratch1, 1); // 0x80000000 - 1 => VS
@@ -14112,7 +14112,7 @@
format %{ "mul rscratch1, $op1, $op2\t#overflow check long\n\t"
"smulh rscratch2, $op1, $op2\n\t"
- "cmp rscratch2, rscratch1, ASR #31\n\t"
+ "cmp rscratch2, rscratch1, ASR #63\n\t"
"b$cmp $labl" %}
ins_cost(4 * INSN_COST); // Branch is rare so treat as INSN_COST
ins_encode %{
@@ -14120,7 +14120,7 @@
Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
__ mul(rscratch1, $op1$$Register, $op2$$Register); // Result bits 0..63
__ smulh(rscratch2, $op1$$Register, $op2$$Register); // Result bits 64..127
- __ cmp(rscratch2, rscratch1, Assembler::ASR, 31); // Top is pure sign ext
+ __ cmp(rscratch2, rscratch1, Assembler::ASR, 63); // Top is pure sign ext
__ br(cond == Assembler::VS ? Assembler::NE : Assembler::EQ, *L);
%}
--- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -3111,7 +3111,7 @@
}
void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr dest, LIR_Opr tmp_op) {
- Address addr = as_Address(src->as_address_ptr(), noreg);
+ Address addr = as_Address(src->as_address_ptr());
BasicType type = src->type();
bool is_oop = type == T_OBJECT || type == T_ARRAY;
--- a/hotspot/src/cpu/aarch64/vm/c1_MacroAssembler_aarch64.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/aarch64/vm/c1_MacroAssembler_aarch64.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -195,95 +195,22 @@
}
}
-// Zero words; len is in bytes
-// Destroys all registers except addr
-// len must be a nonzero multiple of wordSize
-void C1_MacroAssembler::zero_memory(Register addr, Register len, Register t1) {
- assert_different_registers(addr, len, t1, rscratch1, rscratch2);
-
-#ifdef ASSERT
- { Label L;
- tst(len, BytesPerWord - 1);
- br(Assembler::EQ, L);
- stop("len is not a multiple of BytesPerWord");
- bind(L);
- }
-#endif
-
-#ifndef PRODUCT
- block_comment("zero memory");
-#endif
-
- Label loop;
- Label entry;
-
-// Algorithm:
-//
-// scratch1 = cnt & 7;
-// cnt -= scratch1;
-// p += scratch1;
-// switch (scratch1) {
-// do {
-// cnt -= 8;
-// p[-8] = 0;
-// case 7:
-// p[-7] = 0;
-// case 6:
-// p[-6] = 0;
-// // ...
-// case 1:
-// p[-1] = 0;
-// case 0:
-// p += 8;
-// } while (cnt);
-// }
-
- const int unroll = 8; // Number of str(zr) instructions we'll unroll
-
- lsr(len, len, LogBytesPerWord);
- andr(rscratch1, len, unroll - 1); // tmp1 = cnt % unroll
- sub(len, len, rscratch1); // cnt -= unroll
- // t1 always points to the end of the region we're about to zero
- add(t1, addr, rscratch1, Assembler::LSL, LogBytesPerWord);
- adr(rscratch2, entry);
- sub(rscratch2, rscratch2, rscratch1, Assembler::LSL, 2);
- br(rscratch2);
- bind(loop);
- sub(len, len, unroll);
- for (int i = -unroll; i < 0; i++)
- str(zr, Address(t1, i * wordSize));
- bind(entry);
- add(t1, t1, unroll * wordSize);
- cbnz(len, loop);
-}
-
// preserves obj, destroys len_in_bytes
void C1_MacroAssembler::initialize_body(Register obj, Register len_in_bytes, int hdr_size_in_bytes, Register t1) {
+ assert(hdr_size_in_bytes >= 0, "header size must be positive or 0");
Label done;
- assert(obj != len_in_bytes && obj != t1 && t1 != len_in_bytes, "registers must be different");
- assert((hdr_size_in_bytes & (BytesPerWord - 1)) == 0, "header size is not a multiple of BytesPerWord");
- Register index = len_in_bytes;
- // index is positive and ptr sized
- subs(index, index, hdr_size_in_bytes);
+
+ // len_in_bytes is positive and ptr sized
+ subs(len_in_bytes, len_in_bytes, hdr_size_in_bytes);
br(Assembler::EQ, done);
- // note: for the remaining code to work, index must be a multiple of BytesPerWord
-#ifdef ASSERT
- { Label L;
- tst(index, BytesPerWord - 1);
- br(Assembler::EQ, L);
- stop("index is not a multiple of BytesPerWord");
- bind(L);
- }
-#endif
// Preserve obj
if (hdr_size_in_bytes)
add(obj, obj, hdr_size_in_bytes);
- zero_memory(obj, index, t1);
+ zero_memory(obj, len_in_bytes, t1);
if (hdr_size_in_bytes)
sub(obj, obj, hdr_size_in_bytes);
- // done
bind(done);
}
@@ -294,57 +221,59 @@
try_allocate(obj, noreg, object_size * BytesPerWord, t1, t2, slow_case);
- initialize_object(obj, klass, noreg, object_size * HeapWordSize, t1, t2);
+ initialize_object(obj, klass, noreg, object_size * HeapWordSize, t1, t2, UseTLAB);
}
-void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2) {
+void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2, bool is_tlab_allocated) {
assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0,
"con_size_in_bytes is not multiple of alignment");
const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize;
initialize_header(obj, klass, noreg, t1, t2);
- // clear rest of allocated space
- const Register index = t2;
- const int threshold = 16 * BytesPerWord; // approximate break even point for code size (see comments below)
- if (var_size_in_bytes != noreg) {
- mov(index, var_size_in_bytes);
- initialize_body(obj, index, hdr_size_in_bytes, t1);
- } else if (con_size_in_bytes <= threshold) {
- // use explicit null stores
- int i = hdr_size_in_bytes;
- if (i < con_size_in_bytes && (con_size_in_bytes % (2 * BytesPerWord))) {
- str(zr, Address(obj, i));
- i += BytesPerWord;
- }
- for (; i < con_size_in_bytes; i += 2 * BytesPerWord)
- stp(zr, zr, Address(obj, i));
- } else if (con_size_in_bytes > hdr_size_in_bytes) {
- block_comment("zero memory");
- // use loop to null out the fields
+ if (!(UseTLAB && ZeroTLAB && is_tlab_allocated)) {
+ // clear rest of allocated space
+ const Register index = t2;
+ const int threshold = 16 * BytesPerWord; // approximate break even point for code size (see comments below)
+ if (var_size_in_bytes != noreg) {
+ mov(index, var_size_in_bytes);
+ initialize_body(obj, index, hdr_size_in_bytes, t1);
+ } else if (con_size_in_bytes <= threshold) {
+ // use explicit null stores
+ int i = hdr_size_in_bytes;
+ if (i < con_size_in_bytes && (con_size_in_bytes % (2 * BytesPerWord))) {
+ str(zr, Address(obj, i));
+ i += BytesPerWord;
+ }
+ for (; i < con_size_in_bytes; i += 2 * BytesPerWord)
+ stp(zr, zr, Address(obj, i));
+ } else if (con_size_in_bytes > hdr_size_in_bytes) {
+ block_comment("zero memory");
+ // use loop to null out the fields
- int words = (con_size_in_bytes - hdr_size_in_bytes) / BytesPerWord;
- mov(index, words / 8);
+ int words = (con_size_in_bytes - hdr_size_in_bytes) / BytesPerWord;
+ mov(index, words / 8);
- const int unroll = 8; // Number of str(zr) instructions we'll unroll
- int remainder = words % unroll;
- lea(rscratch1, Address(obj, hdr_size_in_bytes + remainder * BytesPerWord));
+ const int unroll = 8; // Number of str(zr) instructions we'll unroll
+ int remainder = words % unroll;
+ lea(rscratch1, Address(obj, hdr_size_in_bytes + remainder * BytesPerWord));
- Label entry_point, loop;
- b(entry_point);
+ Label entry_point, loop;
+ b(entry_point);
- bind(loop);
- sub(index, index, 1);
- for (int i = -unroll; i < 0; i++) {
- if (-i == remainder)
- bind(entry_point);
- str(zr, Address(rscratch1, i * wordSize));
- }
- if (remainder == 0)
- bind(entry_point);
- add(rscratch1, rscratch1, unroll * wordSize);
- cbnz(index, loop);
+ bind(loop);
+ sub(index, index, 1);
+ for (int i = -unroll; i < 0; i++) {
+ if (-i == remainder)
+ bind(entry_point);
+ str(zr, Address(rscratch1, i * wordSize));
+ }
+ if (remainder == 0)
+ bind(entry_point);
+ add(rscratch1, rscratch1, unroll * wordSize);
+ cbnz(index, loop);
+ }
}
membar(StoreStore);
--- a/hotspot/src/cpu/aarch64/vm/c1_MacroAssembler_aarch64.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/aarch64/vm/c1_MacroAssembler_aarch64.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -36,7 +36,6 @@
// initialization
void pd_init() { _rsp_offset = 0; }
-void zero_memory(Register addr, Register len, Register t1);
public:
void try_allocate(
@@ -75,7 +74,8 @@
Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
int con_size_in_bytes, // object size in bytes if known at compile time
Register t1, // temp register
- Register t2 // temp register
+ Register t2, // temp register
+ bool is_tlab_allocated // the object was allocated in a TLAB; relevant for the implementation of ZeroTLAB
);
// allocation of fixed-size objects
--- a/hotspot/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -728,7 +728,7 @@
__ tlab_allocate(obj, obj_size, 0, t1, t2, slow_path);
- __ initialize_object(obj, klass, obj_size, 0, t1, t2);
+ __ initialize_object(obj, klass, obj_size, 0, t1, t2, /* is_tlab_allocated */ true);
__ verify_oop(obj);
__ ldp(r5, r19, Address(__ post(sp, 2 * wordSize)));
__ ret(lr);
@@ -740,7 +740,7 @@
__ eden_allocate(obj, obj_size, 0, t1, slow_path);
__ incr_allocated_bytes(rthread, obj_size, 0, rscratch1);
- __ initialize_object(obj, klass, obj_size, 0, t1, t2);
+ __ initialize_object(obj, klass, obj_size, 0, t1, t2, /* is_tlab_allocated */ false);
__ verify_oop(obj);
__ ldp(r5, r19, Address(__ post(sp, 2 * wordSize)));
__ ret(lr);
@@ -853,7 +853,9 @@
__ andr(t1, t1, Klass::_lh_header_size_mask);
__ sub(arr_size, arr_size, t1); // body length
__ add(t1, t1, obj); // body start
- __ initialize_body(t1, arr_size, 0, t2);
+ if (!ZeroTLAB) {
+ __ initialize_body(t1, arr_size, 0, t2);
+ }
__ verify_oop(obj);
__ ret(lr);
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -3944,12 +3944,82 @@
add(top, top, t1);
sub(top, top, (int32_t)ThreadLocalAllocBuffer::alignment_reserve_in_bytes());
str(top, Address(rthread, in_bytes(JavaThread::tlab_end_offset())));
+
+ if (ZeroTLAB) {
+ // This is a fast TLAB refill, therefore the GC is not notified of it.
+ // So compiled code must fill the new TLAB with zeroes.
+ ldr(top, Address(rthread, in_bytes(JavaThread::tlab_start_offset())));
+ zero_memory(top,t1,t2);
+ }
+
verify_tlab();
b(retry);
return rthread; // for use by caller
}
+// Zero words; len is in bytes
+// Destroys all registers except addr
+// len must be a nonzero multiple of wordSize
+void MacroAssembler::zero_memory(Register addr, Register len, Register t1) {
+ assert_different_registers(addr, len, t1, rscratch1, rscratch2);
+
+#ifdef ASSERT
+ { Label L;
+ tst(len, BytesPerWord - 1);
+ br(Assembler::EQ, L);
+ stop("len is not a multiple of BytesPerWord");
+ bind(L);
+ }
+#endif
+
+#ifndef PRODUCT
+ block_comment("zero memory");
+#endif
+
+ Label loop;
+ Label entry;
+
+// Algorithm:
+//
+// scratch1 = cnt & 7;
+// cnt -= scratch1;
+// p += scratch1;
+// switch (scratch1) {
+// do {
+// cnt -= 8;
+// p[-8] = 0;
+// case 7:
+// p[-7] = 0;
+// case 6:
+// p[-6] = 0;
+// // ...
+// case 1:
+// p[-1] = 0;
+// case 0:
+// p += 8;
+// } while (cnt);
+// }
+
+ const int unroll = 8; // Number of str(zr) instructions we'll unroll
+
+ lsr(len, len, LogBytesPerWord);
+ andr(rscratch1, len, unroll - 1); // tmp1 = cnt % unroll
+ sub(len, len, rscratch1); // cnt -= unroll
+ // t1 always points to the end of the region we're about to zero
+ add(t1, addr, rscratch1, Assembler::LSL, LogBytesPerWord);
+ adr(rscratch2, entry);
+ sub(rscratch2, rscratch2, rscratch1, Assembler::LSL, 2);
+ br(rscratch2);
+ bind(loop);
+ sub(len, len, unroll);
+ for (int i = -unroll; i < 0; i++)
+ str(zr, Address(t1, i * wordSize));
+ bind(entry);
+ add(t1, t1, unroll * wordSize);
+ cbnz(len, loop);
+}
+
// Defines obj, preserves var_size_in_bytes
void MacroAssembler::eden_allocate(Register obj,
Register var_size_in_bytes,
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -857,6 +857,7 @@
Label& slow_case // continuation point if fast allocation fails
);
Register tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); // returns TLS address
+ void zero_memory(Register addr, Register len, Register t1);
void verify_tlab();
void incr_allocated_bytes(Register thread,
--- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -282,7 +282,7 @@
regs[i].set_bad();
break;
case T_LONG:
- assert(sig_bt[i + 1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half");
// fall through
case T_OBJECT:
case T_ARRAY:
@@ -303,7 +303,7 @@
}
break;
case T_DOUBLE:
- assert(sig_bt[i + 1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half");
if (fp_args < Argument::n_float_register_parameters_j) {
regs[i].set2(FP_ArgReg[fp_args++]->as_VMReg());
} else {
@@ -840,7 +840,7 @@
}
break;
case T_LONG:
- assert(sig_bt[i + 1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half");
// fall through
case T_OBJECT:
case T_ARRAY:
@@ -862,7 +862,7 @@
}
break;
case T_DOUBLE:
- assert(sig_bt[i + 1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half");
if (fp_args < Argument::n_float_register_parameters_c) {
regs[i].set2(FP_ArgReg[fp_args++]->as_VMReg());
} else {
--- a/hotspot/src/cpu/arm/vm/sharedRuntime_arm.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/arm/vm/sharedRuntime_arm.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -453,7 +453,7 @@
}
break;
case T_LONG:
- assert(sig_bt[i+1] == T_VOID, "missing Half" );
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "missing Half" );
// fall through
case T_ARRAY:
case T_OBJECT:
@@ -478,7 +478,7 @@
}
break;
case T_DOUBLE:
- assert(sig_bt[i+1] == T_VOID, "missing Half" );
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "missing Half" );
if (fp_reg < FPR_PARAMS) {
FloatRegister r = as_FloatRegister(fp_reg);
regs[i].set2(r->as_VMReg());
@@ -532,7 +532,7 @@
#ifndef __ABI_HARD__
case T_DOUBLE:
#endif // !__ABI_HARD__
- assert(sig_bt[i+1] == T_VOID, "missing Half" );
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "missing Half" );
if (ireg <= 2) {
#if (ALIGN_WIDE_ARGUMENTS == 1)
if(ireg & 1) ireg++; // Aligned location required
--- a/hotspot/src/cpu/ppc/vm/abstractInterpreter_ppc.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/ppc/vm/abstractInterpreter_ppc.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -51,19 +51,25 @@
return i;
}
-// Support abs and sqrt like in compiler.
-// For others we can use a normal (native) entry.
-bool AbstractInterpreter::math_entry_available(AbstractInterpreter::MethodKind kind) {
- if (!InlineIntrinsics) return false;
-
- return ((kind==Interpreter::java_lang_math_sqrt && VM_Version::has_fsqrt()) ||
- (kind==Interpreter::java_lang_math_abs));
-}
-
// These should never be compiled since the interpreter will prefer
// the compiled version to the intrinsic version.
bool AbstractInterpreter::can_be_compiled(methodHandle m) {
- return !math_entry_available(method_kind(m));
+ switch (method_kind(m)) {
+ case Interpreter::java_lang_math_sin : // fall thru
+ case Interpreter::java_lang_math_cos : // fall thru
+ case Interpreter::java_lang_math_tan : // fall thru
+ case Interpreter::java_lang_math_abs : // fall thru
+ case Interpreter::java_lang_math_log : // fall thru
+ case Interpreter::java_lang_math_log10 : // fall thru
+ case Interpreter::java_lang_math_sqrt : // fall thru
+ case Interpreter::java_lang_math_pow : // fall thru
+ case Interpreter::java_lang_math_exp : // fall thru
+ case Interpreter::java_lang_math_fmaD : // fall thru
+ case Interpreter::java_lang_math_fmaF :
+ return false;
+ default:
+ return true;
+ }
}
// How much stack a method activation needs in stack slots.
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -460,16 +460,15 @@
FCTIWZ_OPCODE = (63u << OPCODE_SHIFT | 15u << 1),
FRSP_OPCODE = (63u << OPCODE_SHIFT | 12u << 1),
- // WARNING: using fmadd results in a non-compliant vm. Some floating
- // point tck tests will fail.
- FMADD_OPCODE = (59u << OPCODE_SHIFT | 29u << 1),
- DMADD_OPCODE = (63u << OPCODE_SHIFT | 29u << 1),
- FMSUB_OPCODE = (59u << OPCODE_SHIFT | 28u << 1),
- DMSUB_OPCODE = (63u << OPCODE_SHIFT | 28u << 1),
- FNMADD_OPCODE = (59u << OPCODE_SHIFT | 31u << 1),
- DNMADD_OPCODE = (63u << OPCODE_SHIFT | 31u << 1),
- FNMSUB_OPCODE = (59u << OPCODE_SHIFT | 30u << 1),
- DNMSUB_OPCODE = (63u << OPCODE_SHIFT | 30u << 1),
+ // Fused multiply-accumulate instructions.
+ FMADD_OPCODE = (63u << OPCODE_SHIFT | 29u << 1),
+ FMADDS_OPCODE = (59u << OPCODE_SHIFT | 29u << 1),
+ FMSUB_OPCODE = (63u << OPCODE_SHIFT | 28u << 1),
+ FMSUBS_OPCODE = (59u << OPCODE_SHIFT | 28u << 1),
+ FNMADD_OPCODE = (63u << OPCODE_SHIFT | 31u << 1),
+ FNMADDS_OPCODE = (59u << OPCODE_SHIFT | 31u << 1),
+ FNMSUB_OPCODE = (63u << OPCODE_SHIFT | 30u << 1),
+ FNMSUBS_OPCODE = (59u << OPCODE_SHIFT | 30u << 1),
LFD_OPCODE = (50u << OPCODE_SHIFT | 00u << 1),
LFDU_OPCODE = (51u << OPCODE_SHIFT | 00u << 1),
@@ -1939,6 +1938,26 @@
inline void fdivs( FloatRegister d, FloatRegister a, FloatRegister b);
inline void fdivs_(FloatRegister d, FloatRegister a, FloatRegister b);
+ // Fused multiply-accumulate instructions.
+ // WARNING: Use only when rounding between the 2 parts is not desired.
+ // Some floating point tck tests will fail if used incorrectly.
+ inline void fmadd( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fmadd_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fmadds( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fmadds_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fmsub( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fmsub_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fmsubs( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fmsubs_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fnmadd( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fnmadd_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fnmadds( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fnmadds_(FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fnmsub( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fnmsub_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fnmsubs( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+ inline void fnmsubs_(FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
+
// PPC 1, section 4.6.6 Floating-Point Rounding and Conversion Instructions
inline void frsp( FloatRegister d, FloatRegister b);
inline void fctid( FloatRegister d, FloatRegister b);
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -700,6 +700,26 @@
inline void Assembler::fdivs( FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FDIVS_OPCODE | frt(d) | fra(a) | frb(b) | rc(0)); }
inline void Assembler::fdivs_(FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FDIVS_OPCODE | frt(d) | fra(a) | frb(b) | rc(1)); }
+// Fused multiply-accumulate instructions.
+// WARNING: Use only when rounding between the 2 parts is not desired.
+// Some floating point tck tests will fail if used incorrectly.
+inline void Assembler::fmadd( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMADD_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
+inline void Assembler::fmadd_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMADD_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
+inline void Assembler::fmadds( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMADDS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
+inline void Assembler::fmadds_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMADDS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
+inline void Assembler::fmsub( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMSUB_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
+inline void Assembler::fmsub_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMSUB_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
+inline void Assembler::fmsubs( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMSUBS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
+inline void Assembler::fmsubs_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMSUBS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
+inline void Assembler::fnmadd( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMADD_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
+inline void Assembler::fnmadd_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMADD_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
+inline void Assembler::fnmadds( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMADDS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
+inline void Assembler::fnmadds_(FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMADDS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
+inline void Assembler::fnmsub( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMSUB_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
+inline void Assembler::fnmsub_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMSUB_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
+inline void Assembler::fnmsubs( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMSUBS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
+inline void Assembler::fnmsubs_(FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMSUBS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
+
// PPC 1, section 4.6.6 Floating-Point Rounding and Conversion Instructions
inline void Assembler::frsp( FloatRegister d, FloatRegister b) { emit_int32( FRSP_OPCODE | frt(d) | frb(b) | rc(0)); }
inline void Assembler::fctid( FloatRegister d, FloatRegister b) { emit_int32( FCTID_OPCODE | frt(d) | frb(b) | rc(0)); }
--- a/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -292,28 +292,28 @@
}
-void LIR_Assembler::emit_op3(LIR_Op3* op) {
- const bool is_int = op->result_opr()->is_single_cpu();
- Register Rdividend = is_int ? op->in_opr1()->as_register() : op->in_opr1()->as_register_lo();
+void LIR_Assembler::arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr temp, LIR_Opr result, CodeEmitInfo* info) {
+ const bool is_int = result->is_single_cpu();
+ Register Rdividend = is_int ? left->as_register() : left->as_register_lo();
Register Rdivisor = noreg;
- Register Rscratch = op->in_opr3()->as_register();
- Register Rresult = is_int ? op->result_opr()->as_register() : op->result_opr()->as_register_lo();
+ Register Rscratch = temp->as_register();
+ Register Rresult = is_int ? result->as_register() : result->as_register_lo();
long divisor = -1;
- if (op->in_opr2()->is_register()) {
- Rdivisor = is_int ? op->in_opr2()->as_register() : op->in_opr2()->as_register_lo();
+ if (right->is_register()) {
+ Rdivisor = is_int ? right->as_register() : right->as_register_lo();
} else {
- divisor = is_int ? op->in_opr2()->as_constant_ptr()->as_jint()
- : op->in_opr2()->as_constant_ptr()->as_jlong();
+ divisor = is_int ? right->as_constant_ptr()->as_jint()
+ : right->as_constant_ptr()->as_jlong();
}
assert(Rdividend != Rscratch, "");
assert(Rdivisor != Rscratch, "");
- assert(op->code() == lir_idiv || op->code() == lir_irem, "Must be irem or idiv");
+ assert(code == lir_idiv || code == lir_irem, "Must be irem or idiv");
if (Rdivisor == noreg) {
if (divisor == 1) { // stupid, but can happen
- if (op->code() == lir_idiv) {
+ if (code == lir_idiv) {
__ mr_if_needed(Rresult, Rdividend);
} else {
__ li(Rresult, 0);
@@ -340,7 +340,7 @@
}
__ add(Rscratch, Rdividend, Rscratch);
- if (op->code() == lir_idiv) {
+ if (code == lir_idiv) {
if (is_int) {
__ srawi(Rresult, Rscratch, log2);
} else {
@@ -352,7 +352,7 @@
}
} else if (divisor == -1) {
- if (op->code() == lir_idiv) {
+ if (code == lir_idiv) {
__ neg(Rresult, Rdividend);
} else {
__ li(Rresult, 0);
@@ -360,7 +360,7 @@
} else {
__ load_const_optimized(Rscratch, divisor);
- if (op->code() == lir_idiv) {
+ if (code == lir_idiv) {
if (is_int) {
__ divw(Rresult, Rdividend, Rscratch); // Can't divide minint/-1.
} else {
@@ -389,7 +389,7 @@
__ cmpdi(CCR0, Rdivisor, -1);
}
__ bne(CCR0, regular);
- if (op->code() == lir_idiv) {
+ if (code == lir_idiv) {
__ neg(Rresult, Rdividend);
__ b(done);
__ bind(regular);
@@ -415,6 +415,26 @@
}
+void LIR_Assembler::emit_op3(LIR_Op3* op) {
+ switch (op->code()) {
+ case lir_idiv:
+ case lir_irem:
+ arithmetic_idiv(op->code(), op->in_opr1(), op->in_opr2(), op->in_opr3(),
+ op->result_opr(), op->info());
+ break;
+ case lir_fmad:
+ __ fmadd(op->result_opr()->as_double_reg(), op->in_opr1()->as_double_reg(),
+ op->in_opr2()->as_double_reg(), op->in_opr3()->as_double_reg());
+ break;
+ case lir_fmaf:
+ __ fmadds(op->result_opr()->as_float_reg(), op->in_opr1()->as_float_reg(),
+ op->in_opr2()->as_float_reg(), op->in_opr3()->as_float_reg());
+ break;
+ default: ShouldNotReachHere(); break;
+ }
+}
+
+
void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) {
#ifdef ASSERT
assert(op->block() == NULL || op->block()->label() == op->label(), "wrong label");
--- a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -1435,7 +1435,26 @@
}
void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) {
- fatal("FMA intrinsic is not implemented on this platform");
+ assert(x->number_of_arguments() == 3, "wrong type");
+ assert(UseFMA, "Needs FMA instructions support.");
+ LIRItem value(x->argument_at(0), this);
+ LIRItem value1(x->argument_at(1), this);
+ LIRItem value2(x->argument_at(2), this);
+
+ value.load_item();
+ value1.load_item();
+ value2.load_item();
+
+ LIR_Opr calc_input = value.result();
+ LIR_Opr calc_input1 = value1.result();
+ LIR_Opr calc_input2 = value2.result();
+ LIR_Opr calc_result = rlock_result(x);
+
+ switch (x->id()) {
+ case vmIntrinsics::_fmaD: __ fmad(calc_input, calc_input1, calc_input2, calc_result); break;
+ case vmIntrinsics::_fmaF: __ fmaf(calc_input, calc_input1, calc_input2, calc_result); break;
+ default: ShouldNotReachHere();
+ }
}
void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {
--- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -42,6 +42,9 @@
#define DEFAULT_STACK_YELLOW_PAGES (2)
#define DEFAULT_STACK_RED_PAGES (1)
+// Java_java_net_SocketOutputStream_socketWrite0() uses a 64k buffer on the
+// stack if compiled for unix and LP64. To pass stack overflow tests we need
+// 20 shadow pages.
#define DEFAULT_STACK_SHADOW_PAGES (20 DEBUG_ONLY(+2))
#define DEFAULT_STACK_RESERVED_PAGES (1)
--- a/hotspot/src/cpu/ppc/vm/ppc.ad Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad Thu Dec 22 22:07:36 2016 +0100
@@ -9569,6 +9569,117 @@
ins_pipe(pipe_class_default);
%}
+
+// Multiply-Accumulate
+// src1 * src2 + src3
+instruct maddF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
+ match(Set dst (FmaF src3 (Binary src1 src2)));
+
+ format %{ "FMADDS $dst, $src1, $src2, $src3" %}
+ size(4);
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_fmadds);
+ __ fmadds($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+// src1 * src2 + src3
+instruct maddD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
+ match(Set dst (FmaD src3 (Binary src1 src2)));
+
+ format %{ "FMADD $dst, $src1, $src2, $src3" %}
+ size(4);
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_fmadd);
+ __ fmadd($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+// -src1 * src2 + src3 = -(src1*src2-src3)
+instruct mnsubF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
+ match(Set dst (FmaF src3 (Binary (NegF src1) src2)));
+ match(Set dst (FmaF src3 (Binary src1 (NegF src2))));
+
+ format %{ "FNMSUBS $dst, $src1, $src2, $src3" %}
+ size(4);
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_fnmsubs);
+ __ fnmsubs($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+// -src1 * src2 + src3 = -(src1*src2-src3)
+instruct mnsubD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
+ match(Set dst (FmaD src3 (Binary (NegD src1) src2)));
+ match(Set dst (FmaD src3 (Binary src1 (NegD src2))));
+
+ format %{ "FNMSUB $dst, $src1, $src2, $src3" %}
+ size(4);
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_fnmsub);
+ __ fnmsub($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+// -src1 * src2 - src3 = -(src1*src2+src3)
+instruct mnaddF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
+ match(Set dst (FmaF (NegF src3) (Binary (NegF src1) src2)));
+ match(Set dst (FmaF (NegF src3) (Binary src1 (NegF src2))));
+
+ format %{ "FNMADDS $dst, $src1, $src2, $src3" %}
+ size(4);
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_fnmadds);
+ __ fnmadds($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+// -src1 * src2 - src3 = -(src1*src2+src3)
+instruct mnaddD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
+ match(Set dst (FmaD (NegD src3) (Binary (NegD src1) src2)));
+ match(Set dst (FmaD (NegD src3) (Binary src1 (NegD src2))));
+
+ format %{ "FNMADD $dst, $src1, $src2, $src3" %}
+ size(4);
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_fnmadd);
+ __ fnmadd($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+// src1 * src2 - src3
+instruct msubF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
+ match(Set dst (FmaF (NegF src3) (Binary src1 src2)));
+
+ format %{ "FMSUBS $dst, $src1, $src2, $src3" %}
+ size(4);
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_fmsubs);
+ __ fmsubs($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+// src1 * src2 - src3
+instruct msubD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
+ match(Set dst (FmaD (NegD src3) (Binary src1 src2)));
+
+ format %{ "FMSUB $dst, $src1, $src2, $src3" %}
+ size(4);
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_fmsub);
+ __ fmsub($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+
//----------Logical Instructions-----------------------------------------------
// And Instructions
--- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -594,7 +594,7 @@
regs[i].set1(reg);
break;
case T_LONG:
- assert(sig_bt[i+1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting half");
if (ireg < num_java_iarg_registers) {
// Put long in register.
reg = java_iarg_reg[ireg];
@@ -637,7 +637,7 @@
regs[i].set1(reg);
break;
case T_DOUBLE:
- assert(sig_bt[i+1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting half");
if (freg < num_java_farg_registers) {
// Put double in register.
reg = java_farg_reg[freg];
@@ -809,7 +809,7 @@
regs[i].set1(reg);
break;
case T_DOUBLE:
- assert(sig_bt[i+1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting half");
if (freg < Argument::n_float_register_parameters_c) {
// Put double in register ...
reg = farg_reg[freg];
--- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -1134,14 +1134,57 @@
// End of helpers
address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) {
- if (!Interpreter::math_entry_available(kind)) {
- NOT_PRODUCT(__ should_not_reach_here();)
- return NULL;
+
+ // Decide what to do: Use same platform specific instructions and runtime calls as compilers.
+ bool use_instruction = false;
+ address runtime_entry = NULL;
+ int num_args = 1;
+ bool double_precision = true;
+
+ // PPC64 specific:
+ switch (kind) {
+ case Interpreter::java_lang_math_sqrt: use_instruction = VM_Version::has_fsqrt(); break;
+ case Interpreter::java_lang_math_abs: use_instruction = true; break;
+ case Interpreter::java_lang_math_fmaF:
+ case Interpreter::java_lang_math_fmaD: use_instruction = UseFMA; break;
+ default: break; // Fall back to runtime call.
}
+ switch (kind) {
+ case Interpreter::java_lang_math_sin : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dsin); break;
+ case Interpreter::java_lang_math_cos : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dcos); break;
+ case Interpreter::java_lang_math_tan : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dtan); break;
+ case Interpreter::java_lang_math_abs : /* run interpreted */ break;
+ case Interpreter::java_lang_math_sqrt : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dsqrt); break;
+ case Interpreter::java_lang_math_log : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dlog); break;
+ case Interpreter::java_lang_math_log10: runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dlog10); break;
+ case Interpreter::java_lang_math_pow : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dpow); num_args = 2; break;
+ case Interpreter::java_lang_math_exp : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dexp); break;
+ case Interpreter::java_lang_math_fmaF : /* run interpreted */ num_args = 3; double_precision = false; break;
+ case Interpreter::java_lang_math_fmaD : /* run interpreted */ num_args = 3; break;
+ default: ShouldNotReachHere();
+ }
+
+ // Use normal entry if neither instruction nor runtime call is used.
+ if (!use_instruction && runtime_entry == NULL) return NULL;
+
address entry = __ pc();
- __ lfd(F1_RET, Interpreter::stackElementSize, R15_esp);
+ // Load arguments
+ assert(num_args <= 13, "passed in registers");
+ if (double_precision) {
+ int offset = (2 * num_args - 1) * Interpreter::stackElementSize;
+ for (int i = 0; i < num_args; ++i) {
+ __ lfd(as_FloatRegister(F1_ARG1->encoding() + i), offset, R15_esp);
+ offset -= 2 * Interpreter::stackElementSize;
+ }
+ } else {
+ int offset = num_args * Interpreter::stackElementSize;
+ for (int i = 0; i < num_args; ++i) {
+ __ lfs(as_FloatRegister(F1_ARG1->encoding() + i), offset, R15_esp);
+ offset -= Interpreter::stackElementSize;
+ }
+ }
// Pop c2i arguments (if any) off when we return.
#ifdef ASSERT
@@ -1152,15 +1195,30 @@
#endif // ASSERT
__ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started.
- if (kind == Interpreter::java_lang_math_sqrt) {
- __ fsqrt(F1_RET, F1_RET);
- } else if (kind == Interpreter::java_lang_math_abs) {
- __ fabs(F1_RET, F1_RET);
+ if (use_instruction) {
+ switch (kind) {
+ case Interpreter::java_lang_math_sqrt: __ fsqrt(F1_RET, F1); break;
+ case Interpreter::java_lang_math_abs: __ fabs(F1_RET, F1); break;
+ case Interpreter::java_lang_math_fmaF: __ fmadds(F1_RET, F1, F2, F3); break;
+ case Interpreter::java_lang_math_fmaD: __ fmadd(F1_RET, F1, F2, F3); break;
+ default: ShouldNotReachHere();
+ }
} else {
- ShouldNotReachHere();
+ // Comment: Can use tail call if the unextended frame is always C ABI compliant:
+ //__ load_const_optimized(R12_scratch2, runtime_entry, R0);
+ //__ call_c_and_return_to_caller(R12_scratch2);
+
+ // Push a new C frame and save LR.
+ __ save_LR_CR(R0);
+ __ push_frame_reg_args(0, R11_scratch1);
+
+ __ call_VM_leaf(runtime_entry);
+
+ // Pop the C frame and restore LR.
+ __ pop_frame();
+ __ restore_LR_CR(R0);
}
- // And we're done.
__ blr();
__ flush();
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -230,9 +230,8 @@
FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
}
- if (UseFMA) {
- warning("FMA instructions are not available on this CPU");
- FLAG_SET_DEFAULT(UseFMA, false);
+ if (FLAG_IS_DEFAULT(UseFMA)) {
+ FLAG_SET_DEFAULT(UseFMA, true);
}
if (UseSHA) {
--- a/hotspot/src/cpu/s390/vm/assembler_s390.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/s390/vm/assembler_s390.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -790,6 +790,16 @@
#define MDB_ZOPC (unsigned long)(237L << 40 | 28)
#define MXDB_ZOPC (unsigned long)(237L << 40 | 7)
+// Multiply-Add
+#define MAEBR_ZOPC (unsigned int)(179 << 24 | 14 << 16)
+#define MADBR_ZOPC (unsigned int)(179 << 24 | 30 << 16)
+#define MSEBR_ZOPC (unsigned int)(179 << 24 | 15 << 16)
+#define MSDBR_ZOPC (unsigned int)(179 << 24 | 31 << 16)
+#define MAEB_ZOPC (unsigned long)(237L << 40 | 14)
+#define MADB_ZOPC (unsigned long)(237L << 40 | 30)
+#define MSEB_ZOPC (unsigned long)(237L << 40 | 15)
+#define MSDB_ZOPC (unsigned long)(237L << 40 | 31)
+
// Divide
// RR, signed
#define DSGFR_ZOPC (unsigned int)(0xb91d << 16)
@@ -2205,6 +2215,20 @@
inline void z_meeb( FloatRegister f1, const Address& a);
inline void z_mdb( FloatRegister f1, const Address& a);
+ // MUL-ADD
+ inline void z_maebr(FloatRegister f1, FloatRegister f3, FloatRegister f2); // f1 = f3 * f2 + f1 ; float
+ inline void z_madbr(FloatRegister f1, FloatRegister f3, FloatRegister f2); // f1 = f3 * f2 + f1 ; double
+ inline void z_msebr(FloatRegister f1, FloatRegister f3, FloatRegister f2); // f1 = f3 * f2 - f1 ; float
+ inline void z_msdbr(FloatRegister f1, FloatRegister f3, FloatRegister f2); // f1 = f3 * f2 - f1 ; double
+ inline void z_maeb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2); // f1 = f3 * *(d2+x2+b2) + f1 ; float
+ inline void z_madb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2); // f1 = f3 * *(d2+x2+b2) + f1 ; double
+ inline void z_mseb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2); // f1 = f3 * *(d2+x2+b2) - f1 ; float
+ inline void z_msdb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2); // f1 = f3 * *(d2+x2+b2) - f1 ; double
+ inline void z_maeb(FloatRegister f1, FloatRegister f3, const Address& a);
+ inline void z_madb(FloatRegister f1, FloatRegister f3, const Address& a);
+ inline void z_mseb(FloatRegister f1, FloatRegister f3, const Address& a);
+ inline void z_msdb(FloatRegister f1, FloatRegister f3, const Address& a);
+
// DIV
inline void z_debr( FloatRegister f1, FloatRegister f2); // f1 = f1 / f2 ; float
inline void z_ddbr( FloatRegister f1, FloatRegister f2); // f1 = f1 / f2 ; double
--- a/hotspot/src/cpu/s390/vm/assembler_s390.inline.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/s390/vm/assembler_s390.inline.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -778,6 +778,23 @@
//---------------
+// MUL-ADD
+//---------------
+inline void Assembler::z_maebr(FloatRegister f1, FloatRegister f3, FloatRegister f2) { emit_32( MAEBR_ZOPC | fregt(f1, 16, 32) | freg(f3, 24, 32) | freg(f2, 28, 32) );}
+inline void Assembler::z_madbr(FloatRegister f1, FloatRegister f3, FloatRegister f2) { emit_32( MADBR_ZOPC | fregt(f1, 16, 32) | freg(f3, 24, 32) | freg(f2, 28, 32) );}
+inline void Assembler::z_msebr(FloatRegister f1, FloatRegister f3, FloatRegister f2) { emit_32( MSEBR_ZOPC | fregt(f1, 16, 32) | freg(f3, 24, 32) | freg(f2, 28, 32) );}
+inline void Assembler::z_msdbr(FloatRegister f1, FloatRegister f3, FloatRegister f2) { emit_32( MSDBR_ZOPC | fregt(f1, 16, 32) | freg(f3, 24, 32) | freg(f2, 28, 32) );}
+inline void Assembler::z_maeb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MAEB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48) );}
+inline void Assembler::z_madb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MADB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48) );}
+inline void Assembler::z_mseb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MSEB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48) );}
+inline void Assembler::z_msdb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MSDB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48) );}
+inline void Assembler::z_maeb(FloatRegister f1, FloatRegister f3, const Address& a) { z_maeb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); }
+inline void Assembler::z_madb(FloatRegister f1, FloatRegister f3, const Address& a) { z_madb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); }
+inline void Assembler::z_mseb(FloatRegister f1, FloatRegister f3, const Address& a) { z_mseb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); }
+inline void Assembler::z_msdb(FloatRegister f1, FloatRegister f3, const Address& a) { z_msdb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); }
+
+
+//---------------
// DIV
//---------------
inline void Assembler::z_debr( FloatRegister f1, FloatRegister f2) { emit_32( DEBR_ZOPC | fregt( f1, 24, 32) | freg( f2, 28, 32));}
--- a/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -324,6 +324,22 @@
op->result_opr(),
op->info());
break;
+ case lir_fmad: {
+ const FloatRegister opr1 = op->in_opr1()->as_double_reg(),
+ opr2 = op->in_opr2()->as_double_reg(),
+ opr3 = op->in_opr3()->as_double_reg(),
+ res = op->result_opr()->as_double_reg();
+ __ z_madbr(opr3, opr1, opr2);
+ if (res != opr3) { __ z_ldr(res, opr3); }
+ } break;
+ case lir_fmaf: {
+ const FloatRegister opr1 = op->in_opr1()->as_float_reg(),
+ opr2 = op->in_opr2()->as_float_reg(),
+ opr3 = op->in_opr3()->as_float_reg(),
+ res = op->result_opr()->as_float_reg();
+ __ z_maebr(opr3, opr1, opr2);
+ if (res != opr3) { __ z_ler(res, opr3); }
+ } break;
default: ShouldNotReachHere(); break;
}
}
--- a/hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -1237,7 +1237,28 @@
}
void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) {
- fatal("FMA intrinsic is not implemented on this platform");
+ assert(x->number_of_arguments() == 3, "wrong type");
+ assert(UseFMA, "Needs FMA instructions support.");
+ LIRItem value(x->argument_at(0), this);
+ LIRItem value1(x->argument_at(1), this);
+ LIRItem value2(x->argument_at(2), this);
+
+ value2.set_destroys_register();
+
+ value.load_item();
+ value1.load_item();
+ value2.load_item();
+
+ LIR_Opr calc_input = value.result();
+ LIR_Opr calc_input1 = value1.result();
+ LIR_Opr calc_input2 = value2.result();
+ LIR_Opr calc_result = rlock_result(x);
+
+ switch (x->id()) {
+ case vmIntrinsics::_fmaD: __ fmad(calc_input, calc_input1, calc_input2, calc_result); break;
+ case vmIntrinsics::_fmaF: __ fmaf(calc_input, calc_input1, calc_input2, calc_result); break;
+ default: ShouldNotReachHere();
+ }
}
void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {
--- a/hotspot/src/cpu/s390/vm/s390.ad Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/s390/vm/s390.ad Thu Dec 22 22:07:36 2016 +0100
@@ -7249,6 +7249,171 @@
ins_pipe(pipe_class_dummy);
%}
+// Multiply-Accumulate
+// src1 * src2 + dst
+instruct maddF_reg_reg(regF dst, regF src1, regF src2) %{
+ match(Set dst (FmaF dst (Binary src1 src2)));
+ // CC unchanged by MUL-ADD.
+ ins_cost(ALU_REG_COST);
+ size(4);
+ format %{ "MAEBR $dst, $src1, $src2" %}
+ ins_encode %{
+ __ z_maebr($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
+ %}
+ ins_pipe(pipe_class_dummy);
+%}
+
+// src1 * src2 + dst
+instruct maddD_reg_reg(regD dst, regD src1, regD src2) %{
+ match(Set dst (FmaD dst (Binary src1 src2)));
+ // CC unchanged by MUL-ADD.
+ ins_cost(ALU_REG_COST);
+ size(4);
+ format %{ "MADBR $dst, $src1, $src2" %}
+ ins_encode %{
+ __ z_madbr($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
+ %}
+ ins_pipe(pipe_class_dummy);
+%}
+
+// src1 * src2 - dst
+instruct msubF_reg_reg(regF dst, regF src1, regF src2) %{
+ match(Set dst (FmaF (NegF dst) (Binary src1 src2)));
+ // CC unchanged by MUL-SUB.
+ ins_cost(ALU_REG_COST);
+ size(4);
+ format %{ "MSEBR $dst, $src1, $src2" %}
+ ins_encode %{
+ __ z_msebr($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
+ %}
+ ins_pipe(pipe_class_dummy);
+%}
+
+// src1 * src2 - dst
+instruct msubD_reg_reg(regD dst, regD src1, regD src2) %{
+ match(Set dst (FmaD (NegD dst) (Binary src1 src2)));
+ // CC unchanged by MUL-SUB.
+ ins_cost(ALU_REG_COST);
+ size(4);
+ format %{ "MSDBR $dst, $src1, $src2" %}
+ ins_encode %{
+ __ z_msdbr($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
+ %}
+ ins_pipe(pipe_class_dummy);
+%}
+
+// src1 * src2 + dst
+instruct maddF_reg_mem(regF dst, regF src1, memoryRX src2) %{
+ match(Set dst (FmaF dst (Binary src1 (LoadF src2))));
+ // CC unchanged by MUL-ADD.
+ ins_cost(ALU_MEMORY_COST);
+ size(6);
+ format %{ "MAEB $dst, $src1, $src2" %}
+ ins_encode %{
+ __ z_maeb($dst$$FloatRegister, $src1$$FloatRegister,
+ Address(reg_to_register_object($src2$$base), $src2$$index$$Register, $src2$$disp));
+ %}
+ ins_pipe(pipe_class_dummy);
+%}
+
+// src1 * src2 + dst
+instruct maddD_reg_mem(regD dst, regD src1, memoryRX src2) %{
+ match(Set dst (FmaD dst (Binary src1 (LoadD src2))));
+ // CC unchanged by MUL-ADD.
+ ins_cost(ALU_MEMORY_COST);
+ size(6);
+ format %{ "MADB $dst, $src1, $src2" %}
+ ins_encode %{
+ __ z_madb($dst$$FloatRegister, $src1$$FloatRegister,
+ Address(reg_to_register_object($src2$$base), $src2$$index$$Register, $src2$$disp));
+ %}
+ ins_pipe(pipe_class_dummy);
+%}
+
+// src1 * src2 - dst
+instruct msubF_reg_mem(regF dst, regF src1, memoryRX src2) %{
+ match(Set dst (FmaF (NegF dst) (Binary src1 (LoadF src2))));
+ // CC unchanged by MUL-SUB.
+ ins_cost(ALU_MEMORY_COST);
+ size(6);
+ format %{ "MSEB $dst, $src1, $src2" %}
+ ins_encode %{
+ __ z_mseb($dst$$FloatRegister, $src1$$FloatRegister,
+ Address(reg_to_register_object($src2$$base), $src2$$index$$Register, $src2$$disp));
+ %}
+ ins_pipe(pipe_class_dummy);
+%}
+
+// src1 * src2 - dst
+instruct msubD_reg_mem(regD dst, regD src1, memoryRX src2) %{
+ match(Set dst (FmaD (NegD dst) (Binary src1 (LoadD src2))));
+ // CC unchanged by MUL-SUB.
+ ins_cost(ALU_MEMORY_COST);
+ size(6);
+ format %{ "MSDB $dst, $src1, $src2" %}
+ ins_encode %{
+ __ z_msdb($dst$$FloatRegister, $src1$$FloatRegister,
+ Address(reg_to_register_object($src2$$base), $src2$$index$$Register, $src2$$disp));
+ %}
+ ins_pipe(pipe_class_dummy);
+%}
+
+// src1 * src2 + dst
+instruct maddF_mem_reg(regF dst, memoryRX src1, regF src2) %{
+ match(Set dst (FmaF dst (Binary (LoadF src1) src2)));
+ // CC unchanged by MUL-ADD.
+ ins_cost(ALU_MEMORY_COST);
+ size(6);
+ format %{ "MAEB $dst, $src1, $src2" %}
+ ins_encode %{
+ __ z_maeb($dst$$FloatRegister, $src2$$FloatRegister,
+ Address(reg_to_register_object($src1$$base), $src1$$index$$Register, $src1$$disp));
+ %}
+ ins_pipe(pipe_class_dummy);
+%}
+
+// src1 * src2 + dst
+instruct maddD_mem_reg(regD dst, memoryRX src1, regD src2) %{
+ match(Set dst (FmaD dst (Binary (LoadD src1) src2)));
+ // CC unchanged by MUL-ADD.
+ ins_cost(ALU_MEMORY_COST);
+ size(6);
+ format %{ "MADB $dst, $src1, $src2" %}
+ ins_encode %{
+ __ z_madb($dst$$FloatRegister, $src2$$FloatRegister,
+ Address(reg_to_register_object($src1$$base), $src1$$index$$Register, $src1$$disp));
+ %}
+ ins_pipe(pipe_class_dummy);
+%}
+
+// src1 * src2 - dst
+instruct msubF_mem_reg(regF dst, memoryRX src1, regF src2) %{
+ match(Set dst (FmaF (NegF dst) (Binary (LoadF src1) src2)));
+ // CC unchanged by MUL-SUB.
+ ins_cost(ALU_MEMORY_COST);
+ size(6);
+ format %{ "MSEB $dst, $src1, $src2" %}
+ ins_encode %{
+ __ z_mseb($dst$$FloatRegister, $src2$$FloatRegister,
+ Address(reg_to_register_object($src1$$base), $src1$$index$$Register, $src1$$disp));
+ %}
+ ins_pipe(pipe_class_dummy);
+%}
+
+// src1 * src2 - dst
+instruct msubD_mem_reg(regD dst, memoryRX src1, regD src2) %{
+ match(Set dst (FmaD (NegD dst) (Binary (LoadD src1) src2)));
+ // CC unchanged by MUL-SUB.
+ ins_cost(ALU_MEMORY_COST);
+ size(6);
+ format %{ "MSDB $dst, $src1, $src2" %}
+ ins_encode %{
+ __ z_msdb($dst$$FloatRegister, $src2$$FloatRegister,
+ Address(reg_to_register_object($src1$$base), $src1$$index$$Register, $src1$$disp));
+ %}
+ ins_pipe(pipe_class_dummy);
+%}
+
// DIV
// Div float single precision
--- a/hotspot/src/cpu/s390/vm/sharedRuntime_s390.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/s390/vm/sharedRuntime_s390.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -683,7 +683,7 @@
}
break;
case T_LONG:
- assert(sig_bt[i+1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting half");
if (ireg < z_num_iarg_registers) {
// Put long in register.
regs[i].set2(z_iarg_reg[ireg]);
@@ -723,7 +723,7 @@
}
break;
case T_DOUBLE:
- assert(sig_bt[i+1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting half");
if (freg < z_num_farg_registers) {
// Put double in register.
regs[i].set2(z_farg_reg[freg]);
@@ -822,7 +822,7 @@
}
break;
case T_DOUBLE:
- assert(sig_bt[i+1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting half");
if (freg < z_num_farg_registers) {
regs[i].set2(z_farg_reg[freg]);
++freg;
--- a/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -2038,15 +2038,15 @@
generate_push_parmBlk(keylen, fCode, parmBlk, key, cv, true);
// Prepare other registers for instruction.
- // __ z_lgr(src, from); // Not needed, registers are the same.
+ // __ z_lgr(src, from); // Not needed, registers are the same.
__ z_lgr(dst, to);
- __ z_lgr(srclen, msglen);
-
- __ kmc(dst, src); // Decipher the message.
+ __ z_llgfr(srclen, msglen); // We pass the offsets as ints, not as longs as required.
+
+ __ kmc(dst, src); // Decipher the message.
generate_pop_parmBlk(keylen, parmBlk, key, cv);
- __ z_lgr(Z_RET, msglen);
+ __ z_llgfr(Z_RET, msglen); // We pass the offsets as ints, not as longs as required.
__ z_br(Z_R14);
return __ addr_at(start_off);
--- a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -1297,36 +1297,96 @@
// Math function, frame manager must set up an interpreter state, etc.
address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) {
- if (!InlineIntrinsics) { return NULL; } // Generate a vanilla entry.
-
- // Only support absolute value and square root.
- if (kind != Interpreter::java_lang_math_abs && kind != Interpreter::java_lang_math_sqrt) {
- return NULL;
+ // Decide what to do: Use same platform specific instructions and runtime calls as compilers.
+ bool use_instruction = false;
+ address runtime_entry = NULL;
+ int num_args = 1;
+ bool double_precision = true;
+
+ // s390 specific:
+ switch (kind) {
+ case Interpreter::java_lang_math_sqrt:
+ case Interpreter::java_lang_math_abs: use_instruction = true; break;
+ case Interpreter::java_lang_math_fmaF:
+ case Interpreter::java_lang_math_fmaD: use_instruction = UseFMA; break;
+ default: break; // Fall back to runtime call.
+ }
+
+ switch (kind) {
+ case Interpreter::java_lang_math_sin : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dsin); break;
+ case Interpreter::java_lang_math_cos : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dcos); break;
+ case Interpreter::java_lang_math_tan : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dtan); break;
+ case Interpreter::java_lang_math_abs : /* run interpreted */ break;
+ case Interpreter::java_lang_math_sqrt : /* runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dsqrt); not available */ break;
+ case Interpreter::java_lang_math_log : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dlog); break;
+ case Interpreter::java_lang_math_log10: runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dlog10); break;
+ case Interpreter::java_lang_math_pow : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dpow); num_args = 2; break;
+ case Interpreter::java_lang_math_exp : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dexp); break;
+ case Interpreter::java_lang_math_fmaF : /* run interpreted */ num_args = 3; double_precision = false; break;
+ case Interpreter::java_lang_math_fmaD : /* run interpreted */ num_args = 3; break;
+ default: ShouldNotReachHere();
}
- BLOCK_COMMENT("math_entry {");
-
- address math_entry = __ pc();
-
- if (kind == Interpreter::java_lang_math_abs) {
- // Load operand from stack.
- __ mem2freg_opt(Z_FRET, Address(Z_esp, Interpreter::stackElementSize));
- __ z_lpdbr(Z_FRET);
+ // Use normal entry if neither instruction nor runtime call is used.
+ if (!use_instruction && runtime_entry == NULL) return NULL;
+
+ address entry = __ pc();
+
+ if (use_instruction) {
+ switch (kind) {
+ case Interpreter::java_lang_math_sqrt:
+ // Can use memory operand directly.
+ __ z_sqdb(Z_FRET, Interpreter::stackElementSize, Z_esp);
+ break;
+ case Interpreter::java_lang_math_abs:
+ // Load operand from stack.
+ __ mem2freg_opt(Z_FRET, Address(Z_esp, Interpreter::stackElementSize));
+ __ z_lpdbr(Z_FRET);
+ break;
+ case Interpreter::java_lang_math_fmaF:
+ __ mem2freg_opt(Z_FRET, Address(Z_esp, Interpreter::stackElementSize)); // result reg = arg3
+ __ mem2freg_opt(Z_FARG2, Address(Z_esp, 3 * Interpreter::stackElementSize)); // arg1
+ __ z_maeb(Z_FRET, Z_FARG2, Address(Z_esp, 2 * Interpreter::stackElementSize));
+ break;
+ case Interpreter::java_lang_math_fmaD:
+ __ mem2freg_opt(Z_FRET, Address(Z_esp, Interpreter::stackElementSize)); // result reg = arg3
+ __ mem2freg_opt(Z_FARG2, Address(Z_esp, 5 * Interpreter::stackElementSize)); // arg1
+ __ z_madb(Z_FRET, Z_FARG2, Address(Z_esp, 3 * Interpreter::stackElementSize));
+ break;
+ default: ShouldNotReachHere();
+ }
} else {
- // sqrt
- // Can use memory operand directly.
- __ z_sqdb(Z_FRET, Interpreter::stackElementSize, Z_esp);
+ // Load arguments
+ assert(num_args <= 4, "passed in registers");
+ if (double_precision) {
+ int offset = (2 * num_args - 1) * Interpreter::stackElementSize;
+ for (int i = 0; i < num_args; ++i) {
+ __ mem2freg_opt(as_FloatRegister(Z_FARG1->encoding() + 2 * i), Address(Z_esp, offset));
+ offset -= 2 * Interpreter::stackElementSize;
+ }
+ } else {
+ int offset = num_args * Interpreter::stackElementSize;
+ for (int i = 0; i < num_args; ++i) {
+ __ mem2freg_opt(as_FloatRegister(Z_FARG1->encoding() + 2 * i), Address(Z_esp, offset));
+ offset -= Interpreter::stackElementSize;
+ }
+ }
+ // Call runtime
+ __ save_return_pc(); // Save Z_R14.
+ __ push_frame_abi160(0); // Without new frame the RT call could overwrite the saved Z_R14.
+
+ __ call_VM_leaf(runtime_entry);
+
+ __ pop_frame();
+ __ restore_return_pc(); // Restore Z_R14.
}
- // Restore caller sp for c2i case.
+ // Pop c2i arguments (if any) off when we return.
__ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started.
- // We are done, return.
__ z_br(Z_R14);
- BLOCK_COMMENT("} math_entry");
-
- return math_entry;
+ return entry;
}
// Interpreter stub for calling a native method. (asm interpreter).
--- a/hotspot/src/cpu/s390/vm/vm_version_s390.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/s390/vm/vm_version_s390.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -155,9 +155,8 @@
FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
}
- if (UseFMA) {
- warning("FMA instructions are not available on this CPU");
- FLAG_SET_DEFAULT(UseFMA, false);
+ if (FLAG_IS_DEFAULT(UseFMA)) {
+ FLAG_SET_DEFAULT(UseFMA, true);
}
// On z/Architecture, we take UseSHA as the general switch to enable/disable the SHA intrinsics.
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -425,7 +425,7 @@
#ifdef _LP64
case T_LONG:
- assert(sig_bt[i+1] == T_VOID, "expecting VOID in other half");
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting VOID in other half");
// fall-through
case T_OBJECT:
case T_ARRAY:
@@ -441,7 +441,7 @@
break;
#else
case T_LONG:
- assert(sig_bt[i+1] == T_VOID, "expecting VOID in other half");
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting VOID in other half");
// On 32-bit SPARC put longs always on the stack to keep the pressure off
// integer argument registers. They should be used for oops.
slot = round_to(slot, 2); // align
@@ -460,7 +460,7 @@
break;
case T_DOUBLE:
- assert(sig_bt[i+1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting half");
if (round_to(flt_reg, 2) + 1 < flt_reg_max) {
flt_reg = round_to(flt_reg, 2); // align
FloatRegister r = as_FloatRegister(flt_reg);
@@ -1174,7 +1174,7 @@
regs[i].set1(int_stk_helper(j));
break;
case T_LONG:
- assert(sig_bt[i+1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting half");
case T_ADDRESS: // raw pointers, like current thread, for VM calls
case T_ARRAY:
case T_OBJECT:
@@ -1209,7 +1209,7 @@
break;
case T_DOUBLE:
{
- assert(sig_bt[i + 1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half");
// V9ism: doubles go in EVEN/ODD regs and stack slots
int double_index = (j << 1);
param_array_reg.set2(VMRegImpl::stack2reg(double_index));
@@ -1261,7 +1261,7 @@
break;
case T_DOUBLE:
case T_LONG:
- assert(sig_bt[i + 1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half");
regs[i].set_pair(int_stk_helper(i + 1), int_stk_helper(i));
break;
case T_VOID: regs[i].set_bad(); break;
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -63,9 +63,10 @@
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
#define MIN_STACK_RESERVED_PAGES (0)
-#ifdef AMD64
-// Very large C++ stack frames using solaris-amd64 optimized builds
-// due to lack of optimization caused by C++ compiler bugs
+#ifdef _LP64
+// Java_java_net_SocketOutputStream_socketWrite0() uses a 64k buffer on the
+// stack if compiled for unix and LP64. To pass stack overflow tests we need
+// 20 shadow pages.
#define DEFAULT_STACK_SHADOW_PAGES (NOT_WIN64(20) WIN64_ONLY(7) DEBUG_ONLY(+2))
// For those clients that do not use write socket, we allow
// the min range value to be below that of the default
@@ -73,7 +74,7 @@
#else
#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
-#endif // AMD64
+#endif // _LP64
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -478,12 +478,12 @@
}
break;
case T_LONG:
- assert(sig_bt[i+1] == T_VOID, "missing Half" );
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "missing Half" );
regs[i].set2(VMRegImpl::stack2reg(dstack));
dstack += 2;
break;
case T_DOUBLE:
- assert(sig_bt[i+1] == T_VOID, "missing Half" );
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "missing Half" );
if( freg_arg0 == (uint)i ) {
regs[i].set2(xmm0->as_VMReg());
} else if( freg_arg1 == (uint)i ) {
@@ -1001,7 +1001,7 @@
case T_DOUBLE: // The stack numbering is reversed from Java
// Since C arguments do not get reversed, the ordering for
// doubles on the stack must be opposite the Java convention
- assert(sig_bt[i+1] == T_VOID, "missing Half" );
+ assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "missing Half" );
regs[i].set2(VMRegImpl::stack2reg(stack));
stack += 2;
break;
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -474,7 +474,7 @@
regs[i].set_bad();
break;
case T_LONG:
- assert(sig_bt[i + 1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half");
// fall through
case T_OBJECT:
case T_ARRAY:
@@ -495,7 +495,7 @@
}
break;
case T_DOUBLE:
- assert(sig_bt[i + 1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half");
if (fp_args < Argument::n_float_register_parameters_j) {
regs[i].set2(FP_ArgReg[fp_args++]->as_VMReg());
} else {
@@ -1014,7 +1014,7 @@
}
break;
case T_LONG:
- assert(sig_bt[i + 1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half");
// fall through
case T_OBJECT:
case T_ARRAY:
@@ -1045,7 +1045,7 @@
}
break;
case T_DOUBLE:
- assert(sig_bt[i + 1] == T_VOID, "expecting half");
+ assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half");
if (fp_args < Argument::n_float_register_parameters_c) {
regs[i].set2(FP_ArgReg[fp_args++]->as_VMReg());
#ifdef _WIN64
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java Thu Dec 22 22:07:36 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, 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
@@ -44,10 +44,14 @@
Type type = db.lookupType("ClassLoaderData");
classLoaderField = type.getOopField("_class_loader");
nextField = type.getAddressField("_next");
+ klassesField = type.getAddressField("_klasses");
+ isAnonymousField = new CIntField(type.getCIntegerField("_is_anonymous"), 0);
}
private static sun.jvm.hotspot.types.OopField classLoaderField;
private static AddressField nextField;
+ private static AddressField klassesField;
+ private static CIntField isAnonymousField;
public ClassLoaderData(Address addr) {
super(addr);
@@ -63,4 +67,16 @@
public Oop getClassLoader() {
return VM.getVM().getObjectHeap().newOop(classLoaderField.getValue(getAddress()));
}
+
+ public boolean getIsAnonymous() {
+ return isAnonymousField.getValue(this) != 0;
+ }
+
+ public ClassLoaderData next() {
+ return instantiateWrapperFor(nextField.getValue(getAddress()));
+ }
+
+ public Klass getKlasses() {
+ return (InstanceKlass)Metadata.instantiateWrapperFor(klassesField.getValue(getAddress()));
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderDataGraph.java Thu Dec 22 22:07:36 2016 +0100
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016, 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 sun.jvm.hotspot.classfile;
+
+import java.io.PrintStream;
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.oops.*;
+import sun.jvm.hotspot.types.*;
+
+public class ClassLoaderDataGraph {
+ static {
+ VM.registerVMInitializedObserver(new Observer() {
+ public void update(Observable o, Object data) {
+ initialize(VM.getVM().getTypeDataBase());
+ }
+ });
+ }
+
+ private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
+ Type type = db.lookupType("ClassLoaderDataGraph");
+
+ headField = type.getAddressField("_head");
+ }
+
+ private static AddressField headField;
+
+ public ClassLoaderData getClassLoaderGraphHead() {
+ return ClassLoaderData.instantiateWrapperFor(headField.getValue());
+ }
+
+ public static interface KlassVisitor {
+ public void visit(Klass k);
+ }
+
+ /** Iterate over all anonymous class loaders and the klasses in those */
+ public void allAnonymousKlassesDo(final KlassVisitor v) {
+ for (ClassLoaderData cl = getClassLoaderGraphHead();
+ cl != null;
+ cl = cl.next()) {
+ if (cl.getIsAnonymous() == true) {
+ for (Klass k = cl.getKlasses(); k != null; k = k.getNextLinkKlass()) {
+ v.visit(k);
+ }
+ }
+ }
+ }
+
+}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java Thu Dec 22 22:07:36 2016 +0100
@@ -61,6 +61,7 @@
}
subklass = new MetadataField(type.getAddressField("_subklass"), 0);
nextSibling = new MetadataField(type.getAddressField("_next_sibling"), 0);
+ nextLink = new MetadataField(type.getAddressField("_next_link"), 0);
vtableLen = new CIntField(type.getCIntegerField("_vtable_len"), 0);
LH_INSTANCE_SLOW_PATH_BIT = db.lookupIntConstant("Klass::_lh_instance_slow_path_bit").intValue();
@@ -92,6 +93,7 @@
private static CIntField accessFlags;
private static MetadataField subklass;
private static MetadataField nextSibling;
+ private static MetadataField nextLink;
private static sun.jvm.hotspot.types.Field traceIDField;
private static CIntField vtableLen;
@@ -114,6 +116,7 @@
public AccessFlags getAccessFlagsObj(){ return new AccessFlags(getAccessFlags()); }
public Klass getSubklassKlass() { return (Klass) subklass.getValue(this); }
public Klass getNextSiblingKlass() { return (Klass) nextSibling.getValue(this); }
+ public Klass getNextLinkKlass() { return (Klass) nextLink.getValue(this); }
public long getVtableLen() { return vtableLen.getValue(this); }
public long traceID() {
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java Thu Dec 22 22:07:36 2016 +0100
@@ -38,6 +38,7 @@
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;
import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.classfile.*;
/** <P> This class encapsulates the global state of the VM; the
universe, object heap, interpreter, etc. It is a Singleton and
@@ -80,6 +81,7 @@
private SymbolTable symbols;
private StringTable strings;
private SystemDictionary dict;
+ private ClassLoaderDataGraph cldGraph;
private Threads threads;
private ObjectSynchronizer synchronizer;
private JNIHandles handles;
@@ -660,6 +662,13 @@
return dict;
}
+ public ClassLoaderDataGraph getClassLoaderDataGraph() {
+ if (cldGraph == null) {
+ cldGraph = new ClassLoaderDataGraph();
+ }
+ return cldGraph;
+ }
+
public Threads getThreads() {
if (threads == null) {
threads = new Threads();
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java Thu Dec 22 22:07:36 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, 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
@@ -31,6 +31,7 @@
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.classfile.*;
/*
* This class writes Java heap in hprof binary format. This format is
@@ -379,6 +380,8 @@
private static final int JVM_SIGNATURE_ARRAY = '[';
private static final int JVM_SIGNATURE_CLASS = 'L';
+ int serialNum = 1;
+
public synchronized void write(String fileName) throws IOException {
// open file stream and create buffered data output stream
fos = new FileOutputStream(fileName);
@@ -516,6 +519,7 @@
private void writeClassDumpRecords() throws IOException {
SystemDictionary sysDict = VM.getVM().getSystemDictionary();
+ ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
try {
sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
public void visit(Klass k) {
@@ -528,6 +532,19 @@
}
}
});
+ // Add the anonymous classes also which are not present in the
+ // System Dictionary
+ cldGraph.allAnonymousKlassesDo(new ClassLoaderDataGraph.KlassVisitor() {
+ public void visit(Klass k) {
+ try {
+ writeHeapRecordPrologue();
+ writeClassDumpRecord(k);
+ writeHeapRecordEpilogue();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
} catch (RuntimeException re) {
handleRuntimeException(re);
}
@@ -799,17 +816,6 @@
writeObjectID(klass.getJavaMirror());
ClassData cd = (ClassData) classDataCache.get(klass);
- if (cd == null) {
- // The class is not present in the system dictionary, probably Lambda.
- // Add it to cache here
- if (klass instanceof InstanceKlass) {
- InstanceKlass ik = (InstanceKlass) klass;
- List fields = getInstanceFields(ik);
- int instSize = getSizeForFields(fields);
- cd = new ClassData(instSize, fields);
- classDataCache.put(ik, cd);
- }
- }
if (Assert.ASSERTS_ENABLED) {
Assert.that(cd != null, "can not get class data for " + klass.getName().asString() + klass.getAddress());
@@ -950,9 +956,24 @@
private void writeClasses() throws IOException {
// write class list (id, name) association
SystemDictionary sysDict = VM.getVM().getSystemDictionary();
+ ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
try {
sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
- private int serialNum = 1;
+ public void visit(Klass k) {
+ try {
+ Instance clazz = k.getJavaMirror();
+ writeHeader(HPROF_LOAD_CLASS, 2 * (OBJ_ID_SIZE + 4));
+ out.writeInt(serialNum);
+ writeObjectID(clazz);
+ out.writeInt(DUMMY_STACK_TRACE_ID);
+ writeSymbolID(k.getName());
+ serialNum++;
+ } catch (IOException exp) {
+ throw new RuntimeException(exp);
+ }
+ }
+ });
+ cldGraph.allAnonymousKlassesDo(new ClassLoaderDataGraph.KlassVisitor() {
public void visit(Klass k) {
try {
Instance clazz = k.getJavaMirror();
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Thu Dec 22 22:07:36 2016 +0100
@@ -53,6 +53,7 @@
import org.graalvm.compiler.hotspot.stubs.Stub;
import org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub;
import org.graalvm.compiler.hotspot.word.KlassPointer;
+import org.graalvm.compiler.hotspot.word.MethodCountersPointer;
import org.graalvm.compiler.lir.LIR;
import org.graalvm.compiler.lir.LIRFrameState;
import org.graalvm.compiler.lir.LIRInstruction;
@@ -316,8 +317,8 @@
/**
* Tiered support.
*/
- public static final ForeignCallDescriptor INVOCATION_EVENT = new ForeignCallDescriptor("invocation_event", void.class, Word.class);
- public static final ForeignCallDescriptor BACKEDGE_EVENT = new ForeignCallDescriptor("backedge_event", void.class, Word.class, int.class, int.class);
+ public static final ForeignCallDescriptor INVOCATION_EVENT = new ForeignCallDescriptor("invocation_event", void.class, MethodCountersPointer.class);
+ public static final ForeignCallDescriptor BACKEDGE_EVENT = new ForeignCallDescriptor("backedge_event", void.class, MethodCountersPointer.class, int.class, int.class);
/**
* @see UncommonTrapCallNode
--- a/hotspot/src/os/aix/vm/os_aix.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os/aix/vm/os_aix.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -848,13 +848,13 @@
assert(thread->osthread() == NULL, "caller responsible");
- // Allocate the OSThread object
+ // Allocate the OSThread object.
OSThread* osthread = new OSThread(NULL, NULL);
if (osthread == NULL) {
return false;
}
- // set the correct thread state
+ // Set the correct thread state.
osthread->set_thread_type(thr_type);
// Initial state is ALLOCATED but not INITIALIZED
@@ -862,7 +862,7 @@
thread->set_osthread(osthread);
- // init thread attributes
+ // Init thread attributes.
pthread_attr_t attr;
pthread_attr_init(&attr);
guarantee(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0, "???");
@@ -871,15 +871,18 @@
if (os::Aix::on_aix()) {
guarantee(pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) == 0, "???");
guarantee(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) == 0, "???");
- } // end: aix
+ }
// Start in suspended state, and in os::thread_start, wake the thread up.
guarantee(pthread_attr_setsuspendstate_np(&attr, PTHREAD_CREATE_SUSPENDED_NP) == 0, "???");
- // calculate stack size if it's not specified by caller
+ // Calculate stack size if it's not specified by caller.
size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size);
pthread_attr_setstacksize(&attr, stack_size);
+ // Configure libc guard page.
+ pthread_attr_setguardsize(&attr, os::Aix::default_guard_size(thr_type));
+
pthread_t tid;
int ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread);
@@ -895,7 +898,7 @@
pthread_attr_destroy(&attr);
if (ret != 0) {
- // Need to clean up stuff we've allocated so far
+ // Need to clean up stuff we've allocated so far.
thread->set_osthread(NULL);
delete osthread;
return false;
@@ -3032,6 +3035,19 @@
return chained;
}
+size_t os::Aix::default_guard_size(os::ThreadType thr_type) {
+ // Creating guard page is very expensive. Java thread has HotSpot
+ // guard pages, only enable glibc guard page for non-Java threads.
+ // (Remember: compiler thread is a Java thread, too!)
+ //
+ // Aix can have different page sizes for stack (4K) and heap (64K).
+ // As Hotspot knows only one page size, we assume the stack has
+ // the same page size as the heap. Returning page_size() here can
+ // cause 16 guard pages which we want to avoid. Thus we return 4K
+ // which will be rounded to the real page size by the OS.
+ return ((thr_type == java_thread || thr_type == compiler_thread) ? 0 : 4 * K);
+}
+
struct sigaction* os::Aix::get_preinstalled_handler(int sig) {
if (sigismember(&sigs, sig)) {
return &sigact[sig];
--- a/hotspot/src/os/aix/vm/os_aix.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os/aix/vm/os_aix.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -140,6 +140,9 @@
// libpthread version string
static void libpthread_init();
+ // Return default libc guard size for the specified thread type.
+ static size_t default_guard_size(os::ThreadType thr_type);
+
// Function returns true if we run on OS/400 (pase), false if we run
// on AIX.
static bool on_pase() {
--- a/hotspot/src/os/linux/vm/os_linux.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -716,11 +716,18 @@
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- // calculate stack size if it's not specified by caller
+ // Calculate stack size if it's not specified by caller.
size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size);
+ // In the Linux NPTL pthread implementation the guard size mechanism
+ // is not implemented properly. The posix standard requires adding
+ // the size of the guard pages to the stack size, instead Linux
+ // takes the space out of 'stacksize'. Thus we adapt the requested
+ // stack_size by the size of the guard pages to mimick proper
+ // behaviour.
+ stack_size = align_size_up(stack_size + os::Linux::default_guard_size(thr_type), vm_page_size());
pthread_attr_setstacksize(&attr, stack_size);
- // glibc guard page
+ // Configure glibc guard page.
pthread_attr_setguardsize(&attr, os::Linux::default_guard_size(thr_type));
ThreadState state;
@@ -920,9 +927,21 @@
// Locate initial thread stack. This special handling of initial thread stack
// is needed because pthread_getattr_np() on most (all?) Linux distros returns
-// bogus value for initial thread.
+// bogus value for the primordial process thread. While the launcher has created
+// the VM in a new thread since JDK 6, we still have to allow for the use of the
+// JNI invocation API from a primordial thread.
void os::Linux::capture_initial_stack(size_t max_size) {
- // stack size is the easy part, get it from RLIMIT_STACK
+
+ // max_size is either 0 (which means accept OS default for thread stacks) or
+ // a user-specified value known to be at least the minimum needed. If we
+ // are actually on the primordial thread we can make it appear that we have a
+ // smaller max_size stack by inserting the guard pages at that location. But we
+ // cannot do anything to emulate a larger stack than what has been provided by
+ // the OS or threading library. In fact if we try to use a stack greater than
+ // what is set by rlimit then we will crash the hosting process.
+
+ // Maximum stack size is the easy part, get it from RLIMIT_STACK.
+ // If this is "unlimited" then it will be a huge value.
struct rlimit rlim;
getrlimit(RLIMIT_STACK, &rlim);
size_t stack_size = rlim.rlim_cur;
@@ -932,17 +951,6 @@
// so we won't install guard page on ld.so's data section.
stack_size -= 2 * page_size();
- // 4441425: avoid crash with "unlimited" stack size on SuSE 7.1 or Redhat
- // 7.1, in both cases we will get 2G in return value.
- // 4466587: glibc 2.2.x compiled w/o "--enable-kernel=2.4.0" (RH 7.0,
- // SuSE 7.2, Debian) can not handle alternate signal stack correctly
- // for initial thread if its stack size exceeds 6M. Cap it at 2M,
- // in case other parts in glibc still assumes 2M max stack size.
- // FIXME: alt signal stack is gone, maybe we can relax this constraint?
- // Problem still exists RH7.2 (IA64 anyway) but 2MB is a little small
- if (stack_size > 2 * K * K IA64_ONLY(*2)) {
- stack_size = 2 * K * K IA64_ONLY(*2);
- }
// Try to figure out where the stack base (top) is. This is harder.
//
// When an application is started, glibc saves the initial stack pointer in
@@ -1102,14 +1110,29 @@
// stack_top could be partially down the page so align it
stack_top = align_size_up(stack_top, page_size());
- if (max_size && stack_size > max_size) {
- _initial_thread_stack_size = max_size;
+ // Allowed stack value is minimum of max_size and what we derived from rlimit
+ if (max_size > 0) {
+ _initial_thread_stack_size = MIN2(max_size, stack_size);
} else {
- _initial_thread_stack_size = stack_size;
- }
-
+ // Accept the rlimit max, but if stack is unlimited then it will be huge, so
+ // clamp it at 8MB as we do on Solaris
+ _initial_thread_stack_size = MIN2(stack_size, 8*M);
+ }
_initial_thread_stack_size = align_size_down(_initial_thread_stack_size, page_size());
_initial_thread_stack_bottom = (address)stack_top - _initial_thread_stack_size;
+
+ assert(_initial_thread_stack_bottom < (address)stack_top, "overflow!");
+
+ if (log_is_enabled(Info, os, thread)) {
+ // See if we seem to be on primordial process thread
+ bool primordial = uintptr_t(&rlim) > uintptr_t(_initial_thread_stack_bottom) &&
+ uintptr_t(&rlim) < stack_top;
+
+ log_info(os, thread)("Capturing initial stack in %s thread: req. size: " SIZE_FORMAT "K, actual size: "
+ SIZE_FORMAT "K, top=" INTPTR_FORMAT ", bottom=" INTPTR_FORMAT,
+ primordial ? "primordial" : "user", max_size / K, _initial_thread_stack_size / K,
+ stack_top, intptr_t(_initial_thread_stack_bottom));
+ }
}
////////////////////////////////////////////////////////////////////////////////
@@ -2833,6 +2856,13 @@
return false;
}
+size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
+ // Creating guard page is very expensive. Java thread has HotSpot
+ // guard pages, only enable glibc guard page for non-Java threads.
+ // (Remember: compiler thread is a Java thread, too!)
+ return ((thr_type == java_thread || thr_type == compiler_thread) ? 0 : page_size());
+}
+
// rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id.
// The table is later used in get_node_by_cpu().
void os::Linux::rebuild_cpu_to_node_map() {
@@ -6065,6 +6095,101 @@
return yes;
}
+
+// Java/Compiler thread:
+//
+// Low memory addresses
+// P0 +------------------------+
+// | |\ Java thread created by VM does not have glibc
+// | glibc guard page | - guard page, attached Java thread usually has
+// | |/ 1 glibc guard page.
+// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
+// | |\
+// | HotSpot Guard Pages | - red, yellow and reserved pages
+// | |/
+// +------------------------+ JavaThread::stack_reserved_zone_base()
+// | |\
+// | Normal Stack | -
+// | |/
+// P2 +------------------------+ Thread::stack_base()
+//
+// Non-Java thread:
+//
+// Low memory addresses
+// P0 +------------------------+
+// | |\
+// | glibc guard page | - usually 1 page
+// | |/
+// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
+// | |\
+// | Normal Stack | -
+// | |/
+// P2 +------------------------+ Thread::stack_base()
+//
+// ** P1 (aka bottom) and size (P2 = P1 - size) are the address and stack size
+// returned from pthread_attr_getstack().
+// ** Due to NPTL implementation error, linux takes the glibc guard page out
+// of the stack size given in pthread_attr. We work around this for
+// threads created by the VM. (We adapt bottom to be P1 and size accordingly.)
+//
+#ifndef ZERO
+static void current_stack_region(address * bottom, size_t * size) {
+ if (os::Linux::is_initial_thread()) {
+ // initial thread needs special handling because pthread_getattr_np()
+ // may return bogus value.
+ *bottom = os::Linux::initial_thread_stack_bottom();
+ *size = os::Linux::initial_thread_stack_size();
+ } else {
+ pthread_attr_t attr;
+
+ int rslt = pthread_getattr_np(pthread_self(), &attr);
+
+ // JVM needs to know exact stack location, abort if it fails
+ if (rslt != 0) {
+ if (rslt == ENOMEM) {
+ vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
+ } else {
+ fatal("pthread_getattr_np failed with error = %d", rslt);
+ }
+ }
+
+ if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
+ fatal("Cannot locate current stack attributes!");
+ }
+
+ // Work around NPTL stack guard error.
+ size_t guard_size = 0;
+ rslt = pthread_attr_getguardsize(&attr, &guard_size);
+ if (rslt != 0) {
+ fatal("pthread_attr_getguardsize failed with error = %d", rslt);
+ }
+ *bottom += guard_size;
+ *size -= guard_size;
+
+ pthread_attr_destroy(&attr);
+
+ }
+ assert(os::current_stack_pointer() >= *bottom &&
+ os::current_stack_pointer() < *bottom + *size, "just checking");
+}
+
+address os::current_stack_base() {
+ address bottom;
+ size_t size;
+ current_stack_region(&bottom, &size);
+ return (bottom + size);
+}
+
+size_t os::current_stack_size() {
+ // This stack size includes the usable stack and HotSpot guard pages
+ // (for the threads that have Hotspot guard pages).
+ address bottom;
+ size_t size;
+ current_stack_region(&bottom, &size);
+ return size;
+}
+#endif
+
static inline struct timespec get_mtime(const char* filename) {
struct stat st;
int ret = os::stat(filename, &st);
--- a/hotspot/src/os/posix/vm/os_posix.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os/posix/vm/os_posix.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -1096,6 +1096,8 @@
int detachstate = 0;
pthread_attr_getstacksize(attr, &stack_size);
pthread_attr_getguardsize(attr, &guard_size);
+ // Work around linux NPTL implementation error, see also os::create_thread() in os_linux.cpp.
+ LINUX_ONLY(stack_size -= guard_size);
pthread_attr_getdetachstate(attr, &detachstate);
jio_snprintf(buf, buflen, "stacksize: " SIZE_FORMAT "k, guardsize: " SIZE_FORMAT "k, %s",
stack_size / 1024, guard_size / 1024,
@@ -1105,14 +1107,18 @@
// Check minimum allowable stack sizes for thread creation and to initialize
// the java system classes, including StackOverflowError - depends on page
-// size. Add two 4K pages for compiler2 recursion in main thread.
-// Add in 4*BytesPerWord 4K pages to account for VM stack during
-// class initialization depending on 32 or 64 bit VM.
+// size.
+// The space needed for frames during startup is platform dependent. It
+// depends on word size, platform calling conventions, C frame layout and
+// interpreter/C1/C2 design decisions. Therefore this is given in a
+// platform (os/cpu) dependent constant.
+// To this, space for guard mechanisms is added, which depends on the
+// page size which again depends on the concrete system the VM is running
+// on. Space for libc guard pages is not included in this size.
jint os::Posix::set_minimum_stack_sizes() {
- _java_thread_min_stack_allowed = MAX2(_java_thread_min_stack_allowed,
- JavaThread::stack_guard_zone_size() +
- JavaThread::stack_shadow_zone_size() +
- (4 * BytesPerWord COMPILER2_PRESENT(+ 2)) * 4 * K);
+ _java_thread_min_stack_allowed = _java_thread_min_stack_allowed +
+ JavaThread::stack_guard_zone_size() +
+ JavaThread::stack_shadow_zone_size();
_java_thread_min_stack_allowed = align_size_up(_java_thread_min_stack_allowed, vm_page_size());
@@ -1128,28 +1134,14 @@
return JNI_ERR;
}
-#ifdef SOLARIS
- // For 64kbps there will be a 64kb page size, which makes
- // the usable default stack size quite a bit less. Increase the
- // stack for 64kb (or any > than 8kb) pages, this increases
- // virtual memory fragmentation (since we're not creating the
- // stack on a power of 2 boundary. The real fix for this
- // should be to fix the guard page mechanism.
-
- if (vm_page_size() > 8*K) {
- stack_size_in_bytes = (stack_size_in_bytes != 0)
- ? stack_size_in_bytes +
- JavaThread::stack_red_zone_size() +
- JavaThread::stack_yellow_zone_size()
- : 0;
- ThreadStackSize = stack_size_in_bytes/K;
- }
-#endif // SOLARIS
-
// Make the stack size a multiple of the page size so that
// the yellow/red zones can be guarded.
- JavaThread::set_stack_size_at_create(round_to(stack_size_in_bytes,
- vm_page_size()));
+ JavaThread::set_stack_size_at_create(round_to(stack_size_in_bytes, vm_page_size()));
+
+ // Reminder: a compiler thread is a Java thread.
+ _compiler_thread_min_stack_allowed = _compiler_thread_min_stack_allowed +
+ JavaThread::stack_guard_zone_size() +
+ JavaThread::stack_shadow_zone_size();
_compiler_thread_min_stack_allowed = align_size_up(_compiler_thread_min_stack_allowed, vm_page_size());
--- a/hotspot/src/os/posix/vm/os_posix.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os/posix/vm/os_posix.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -43,7 +43,11 @@
static void print_load_average(outputStream* st);
// Minimum stack size a thread can be created with (allowing
- // the VM to completely create the thread and enter user code)
+ // the VM to completely create the thread and enter user code).
+ // The initial values exclude any guard pages (by HotSpot or libc).
+ // set_minimum_stack_sizes() will add the size required for
+ // HotSpot guard pages depending on page size and flag settings.
+ // Libc guard pages are never considered by these values.
static size_t _compiler_thread_min_stack_allowed;
static size_t _java_thread_min_stack_allowed;
static size_t _vm_internal_thread_min_stack_allowed;
--- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -535,13 +535,15 @@
////////////////////////////////////////////////////////////////////////////////
// thread stack
-size_t os::Posix::_compiler_thread_min_stack_allowed = 128 * K;
-size_t os::Posix::_java_thread_min_stack_allowed = 128 * K;
-size_t os::Posix::_vm_internal_thread_min_stack_allowed = 128 * K;
+// Minimum usable stack sizes required to get to user code. Space for
+// HotSpot guard pages is added later.
+size_t os::Posix::_compiler_thread_min_stack_allowed = 192 * K;
+size_t os::Posix::_java_thread_min_stack_allowed = 64 * K;
+size_t os::Posix::_vm_internal_thread_min_stack_allowed = 64 * K;
-// return default stack size for thr_type
+// Return default stack size for thr_type.
size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
- // default stack size (compiler thread needs larger stack)
+ // Default stack size (compiler thread needs larger stack).
size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M);
return s;
}
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -839,19 +839,20 @@
////////////////////////////////////////////////////////////////////////////////
// thread stack
-#ifdef AMD64
-size_t os::Posix::_compiler_thread_min_stack_allowed = 64 * K;
-size_t os::Posix::_java_thread_min_stack_allowed = 64 * K;
+// Minimum usable stack sizes required to get to user code. Space for
+// HotSpot guard pages is added later.
+size_t os::Posix::_compiler_thread_min_stack_allowed = 48 * K;
+size_t os::Posix::_java_thread_min_stack_allowed = 48 * K;
+#ifdef _LP64
size_t os::Posix::_vm_internal_thread_min_stack_allowed = 64 * K;
#else
-size_t os::Posix::_compiler_thread_min_stack_allowed = (48 DEBUG_ONLY(+ 4)) * K;
-size_t os::Posix::_java_thread_min_stack_allowed = (48 DEBUG_ONLY(+ 4)) * K;
size_t os::Posix::_vm_internal_thread_min_stack_allowed = (48 DEBUG_ONLY(+ 4)) * K;
+#endif // _LP64
+#ifndef AMD64
#ifdef __GNUC__
#define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;})
#endif
-
#endif // AMD64
// return default stack size for thr_type
@@ -870,14 +871,14 @@
//
// Low memory addresses
// +------------------------+
-// | |\ JavaThread created by VM does not have glibc
+// | |\ Java thread created by VM does not have glibc
// | glibc guard page | - guard, attached Java thread usually has
-// | |/ 1 page glibc guard.
+// | |/ 1 glibc guard page.
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
// | |\
-// | HotSpot Guard Pages | - red and yellow pages
+// | HotSpot Guard Pages | - red, yellow and reserved pages
// | |/
-// +------------------------+ JavaThread::stack_yellow_zone_base()
+// +------------------------+ JavaThread::stack_reserved_zone_base()
// | |\
// | Normal Stack | -
// | |/
@@ -925,7 +926,7 @@
int rslt = pthread_stackseg_np(pthread_self(), &ss);
if (rslt != 0)
- fatal("pthread_stackseg_np failed with err = %d", rslt);
+ fatal("pthread_stackseg_np failed with error = %d", rslt);
*bottom = (address)((char *)ss.ss_sp - ss.ss_size);
*size = ss.ss_size;
@@ -936,12 +937,12 @@
// JVM needs to know exact stack location, abort if it fails
if (rslt != 0)
- fatal("pthread_attr_init failed with err = %d", rslt);
+ fatal("pthread_attr_init failed with error = %d", rslt);
rslt = pthread_attr_get_np(pthread_self(), &attr);
if (rslt != 0)
- fatal("pthread_attr_get_np failed with err = %d", rslt);
+ fatal("pthread_attr_get_np failed with error = %d", rslt);
if (pthread_attr_getstackaddr(&attr, (void **)bottom) != 0 ||
pthread_attr_getstacksize(&attr, size) != 0) {
--- a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -310,7 +310,7 @@
int rslt = pthread_stackseg_np(pthread_self(), &ss);
if (rslt != 0)
- fatal("pthread_stackseg_np failed with err = " INT32_FORMAT, rslt);
+ fatal("pthread_stackseg_np failed with error = " INT32_FORMAT, rslt);
stack_top = (address) ss.ss_sp;
stack_bytes = ss.ss_size;
@@ -322,12 +322,12 @@
// JVM needs to know exact stack location, abort if it fails
if (rslt != 0)
- fatal("pthread_attr_init failed with err = " INT32_FORMAT, rslt);
+ fatal("pthread_attr_init failed with error = " INT32_FORMAT, rslt);
rslt = pthread_attr_get_np(pthread_self(), &attr);
if (rslt != 0)
- fatal("pthread_attr_get_np failed with err = " INT32_FORMAT, rslt);
+ fatal("pthread_attr_get_np failed with error = " INT32_FORMAT, rslt);
if (pthread_attr_getstackaddr(&attr, (void **) &stack_bottom) != 0 ||
pthread_attr_getstacksize(&attr, &stack_bytes) != 0) {
--- a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -473,8 +473,10 @@
////////////////////////////////////////////////////////////////////////////////
// thread stack
-size_t os::Posix::_compiler_thread_min_stack_allowed = 64 * K;
-size_t os::Posix::_java_thread_min_stack_allowed = 64 * K;
+// Minimum usable stack sizes required to get to user code. Space for
+// HotSpot guard pages is added later.
+size_t os::Posix::_compiler_thread_min_stack_allowed = 32 * K;
+size_t os::Posix::_java_thread_min_stack_allowed = 32 * K;
size_t os::Posix::_vm_internal_thread_min_stack_allowed = 64 * K;
// return default stack size for thr_type
@@ -484,91 +486,6 @@
return s;
}
-size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
- // Creating guard page is very expensive. Java thread has HotSpot
- // guard page, only enable glibc guard page for non-Java threads.
- return (thr_type == java_thread ? 0 : page_size());
-}
-
-// Java thread:
-//
-// Low memory addresses
-// +------------------------+
-// | |\ JavaThread created by VM does not have glibc
-// | glibc guard page | - guard, attached Java thread usually has
-// | |/ 1 page glibc guard.
-// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
-// | |\
-// | HotSpot Guard Pages | - red and yellow pages
-// | |/
-// +------------------------+ JavaThread::stack_yellow_zone_base()
-// | |\
-// | Normal Stack | -
-// | |/
-// P2 +------------------------+ Thread::stack_base()
-//
-// Non-Java thread:
-//
-// Low memory addresses
-// +------------------------+
-// | |\
-// | glibc guard page | - usually 1 page
-// | |/
-// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
-// | |\
-// | Normal Stack | -
-// | |/
-// P2 +------------------------+ Thread::stack_base()
-//
-// ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from
-// pthread_attr_getstack()
-
-static void current_stack_region(address * bottom, size_t * size) {
- if (os::Linux::is_initial_thread()) {
- // initial thread needs special handling because pthread_getattr_np()
- // may return bogus value.
- *bottom = os::Linux::initial_thread_stack_bottom();
- *size = os::Linux::initial_thread_stack_size();
- } else {
- pthread_attr_t attr;
-
- int rslt = pthread_getattr_np(pthread_self(), &attr);
-
- // JVM needs to know exact stack location, abort if it fails
- if (rslt != 0) {
- if (rslt == ENOMEM) {
- vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
- } else {
- fatal("pthread_getattr_np failed with errno = %d", rslt);
- }
- }
-
- if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
- fatal("Can not locate current stack attributes!");
- }
-
- pthread_attr_destroy(&attr);
-
- }
- assert(os::current_stack_pointer() >= *bottom &&
- os::current_stack_pointer() < *bottom + *size, "just checking");
-}
-
-address os::current_stack_base() {
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return (bottom + size);
-}
-
-size_t os::current_stack_size() {
- // stack size includes normal stack and HotSpot guard pages
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return size;
-}
-
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
@@ -606,8 +523,10 @@
st->print(" TRAPNO=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_TRAPNO]);
st->cr();
#else
- for (int r = 0; r < 31; r++)
- st->print_cr( "R%d=" INTPTR_FORMAT, r, (size_t)uc->uc_mcontext.regs[r]);
+ for (int r = 0; r < 31; r++) {
+ st->print("R%-2d=", r);
+ print_location(st, uc->uc_mcontext.regs[r]);
+ }
#endif
st->cr();
--- a/hotspot/src/os_cpu/linux_arm/vm/os_linux_arm.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os_cpu/linux_arm/vm/os_linux_arm.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -526,8 +526,10 @@
////////////////////////////////////////////////////////////////////////////////
// thread stack
-size_t os::Posix::_compiler_thread_min_stack_allowed = (48 DEBUG_ONLY(+ 4)) * K;
-size_t os::Posix::_java_thread_min_stack_allowed = (48 DEBUG_ONLY(+ 4)) * K;
+// Minimum usable stack sizes required to get to user code. Space for
+// HotSpot guard pages is added later.
+size_t os::Posix::_compiler_thread_min_stack_allowed = (32 DEBUG_ONLY(+ 4)) * K;
+size_t os::Posix::_java_thread_min_stack_allowed = (32 DEBUG_ONLY(+ 4)) * K;
size_t os::Posix::_vm_internal_thread_min_stack_allowed = (48 DEBUG_ONLY(+ 4)) * K;
// return default stack size for thr_type
@@ -537,91 +539,6 @@
return s;
}
-size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
- // Creating guard page is very expensive. Java thread has HotSpot
- // guard page, only enable glibc guard page for non-Java threads.
- return (thr_type == java_thread ? 0 : page_size());
-}
-
-// Java thread:
-//
-// Low memory addresses
-// +------------------------+
-// | |\ JavaThread created by VM does not have glibc
-// | glibc guard page | - guard, attached Java thread usually has
-// | |/ 1 page glibc guard.
-// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
-// | |\
-// | HotSpot Guard Pages | - red and yellow pages
-// | |/
-// +------------------------+ JavaThread::stack_yellow_zone_base()
-// | |\
-// | Normal Stack | -
-// | |/
-// P2 +------------------------+ Thread::stack_base()
-//
-// Non-Java thread:
-//
-// Low memory addresses
-// +------------------------+
-// | |\
-// | glibc guard page | - usually 1 page
-// | |/
-// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
-// | |\
-// | Normal Stack | -
-// | |/
-// P2 +------------------------+ Thread::stack_base()
-//
-// ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from
-// pthread_attr_getstack()
-
-static void current_stack_region(address * bottom, size_t * size) {
- if (os::Linux::is_initial_thread()) {
- // initial thread needs special handling because pthread_getattr_np()
- // may return bogus value.
- *bottom = os::Linux::initial_thread_stack_bottom();
- *size = os::Linux::initial_thread_stack_size();
- } else {
- pthread_attr_t attr;
-
- int rslt = pthread_getattr_np(pthread_self(), &attr);
-
- // JVM needs to know exact stack location, abort if it fails
- if (rslt != 0) {
- if (rslt == ENOMEM) {
- vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
- } else {
- fatal("pthread_getattr_np failed");
- }
- }
-
- if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
- fatal("Can not locate current stack attributes!");
- }
-
- pthread_attr_destroy(&attr);
-
- }
- assert(os::current_stack_pointer() >= *bottom &&
- os::current_stack_pointer() < *bottom + *size, "just checking");
-}
-
-address os::current_stack_base() {
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return (bottom + size);
-}
-
-size_t os::current_stack_size() {
- // stack size includes normal stack and HotSpot guard pages
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return size;
-}
-
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
--- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -535,100 +535,19 @@
////////////////////////////////////////////////////////////////////////////////
// thread stack
-size_t os::Posix::_compiler_thread_min_stack_allowed = 128 * K;
-size_t os::Posix::_java_thread_min_stack_allowed = 128 * K;
-size_t os::Posix::_vm_internal_thread_min_stack_allowed = 128 * K;
+// Minimum usable stack sizes required to get to user code. Space for
+// HotSpot guard pages is added later.
+size_t os::Posix::_compiler_thread_min_stack_allowed = 64 * K;
+size_t os::Posix::_java_thread_min_stack_allowed = 64 * K;
+size_t os::Posix::_vm_internal_thread_min_stack_allowed = 64 * K;
-// return default stack size for thr_type
+// Return default stack size for thr_type.
size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
- // default stack size (compiler thread needs larger stack)
+ // Default stack size (compiler thread needs larger stack).
size_t s = (thr_type == os::compiler_thread ? 4 * M : 1024 * K);
return s;
}
-size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
- return 2 * page_size();
-}
-
-// Java thread:
-//
-// Low memory addresses
-// +------------------------+
-// | |\ JavaThread created by VM does not have glibc
-// | glibc guard page | - guard, attached Java thread usually has
-// | |/ 1 page glibc guard.
-// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
-// | |\
-// | HotSpot Guard Pages | - red and yellow pages
-// | |/
-// +------------------------+ JavaThread::stack_yellow_zone_base()
-// | |\
-// | Normal Stack | -
-// | |/
-// P2 +------------------------+ Thread::stack_base()
-//
-// Non-Java thread:
-//
-// Low memory addresses
-// +------------------------+
-// | |\
-// | glibc guard page | - usually 1 page
-// | |/
-// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
-// | |\
-// | Normal Stack | -
-// | |/
-// P2 +------------------------+ Thread::stack_base()
-//
-// ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from
-// pthread_attr_getstack()
-
-static void current_stack_region(address * bottom, size_t * size) {
- if (os::Linux::is_initial_thread()) {
- // initial thread needs special handling because pthread_getattr_np()
- // may return bogus value.
- *bottom = os::Linux::initial_thread_stack_bottom();
- *size = os::Linux::initial_thread_stack_size();
- } else {
- pthread_attr_t attr;
-
- int rslt = pthread_getattr_np(pthread_self(), &attr);
-
- // JVM needs to know exact stack location, abort if it fails
- if (rslt != 0) {
- if (rslt == ENOMEM) {
- vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
- } else {
- fatal("pthread_getattr_np failed with errno = %d", rslt);
- }
- }
-
- if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
- fatal("Can not locate current stack attributes!");
- }
-
- pthread_attr_destroy(&attr);
-
- }
- assert(os::current_stack_pointer() >= *bottom &&
- os::current_stack_pointer() < *bottom + *size, "just checking");
-}
-
-address os::current_stack_base() {
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return (bottom + size);
-}
-
-size_t os::current_stack_size() {
- // stack size includes normal stack and HotSpot guard pages
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return size;
-}
-
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
--- a/hotspot/src/os_cpu/linux_s390/vm/os_linux_s390.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os_cpu/linux_s390/vm/os_linux_s390.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -473,103 +473,19 @@
////////////////////////////////////////////////////////////////////////////////
// thread stack
-size_t os::Posix::_compiler_thread_min_stack_allowed = 128 * K;
-size_t os::Posix::_java_thread_min_stack_allowed = 128 * K;
-size_t os::Posix::_vm_internal_thread_min_stack_allowed = 128 * K;
+// Minimum usable stack sizes required to get to user code. Space for
+// HotSpot guard pages is added later.
+size_t os::Posix::_compiler_thread_min_stack_allowed = (52 DEBUG_ONLY(+ 32)) * K;
+size_t os::Posix::_java_thread_min_stack_allowed = (32 DEBUG_ONLY(+ 8)) * K;
+size_t os::Posix::_vm_internal_thread_min_stack_allowed = 32 * K;
-// return default stack size for thr_type
+// Return default stack size for thr_type.
size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
- // default stack size (compiler thread needs larger stack)
+ // Default stack size (compiler thread needs larger stack).
size_t s = (thr_type == os::compiler_thread ? 4 * M : 1024 * K);
return s;
}
-size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
- // z/Architecture: put 2 guard pages right in the middle of thread stack. This value
- // should be consistent with the value used by register stack handling code.
- return 2 * page_size();
-}
-
-// Java thread:
-//
-// Low memory addresses
-// +------------------------+
-// | |\
-// | glibc guard page | - Right in the middle of stack, 2 pages
-// | |/
-// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
-// | |\
-// | HotSpot Guard Pages | - red and yellow pages
-// | |/
-// +------------------------+ JavaThread::stack_yellow_zone_base()
-// | |\
-// | Normal Stack | -
-// | |/
-// P2 +------------------------+ Thread::stack_base()
-//
-// Non-Java thread:
-//
-// Low memory addresses
-// +------------------------+
-// | |\
-// | glibc guard page | - Right in the middle of stack, 2 pages
-// | |/
-// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
-// | |\
-// | Normal Stack | -
-// | |/
-// P2 +------------------------+ Thread::stack_base()
-//
-// ** P2 is the address returned from pthread_attr_getstackaddr(), P2 - P1
-// is the stack size returned by pthread_attr_getstacksize().
-
-
-static void current_stack_region(address * bottom, size_t * size) {
- if (os::Linux::is_initial_thread()) {
- // Initial thread needs special handling because pthread_getattr_np()
- // may return bogus value.
- *bottom = os::Linux::initial_thread_stack_bottom();
- *size = os::Linux::initial_thread_stack_size();
- } else {
- pthread_attr_t attr;
-
- int rslt = pthread_getattr_np(pthread_self(), &attr);
-
- // JVM needs to know exact stack location, abort if it fails
- if (rslt != 0) {
- if (rslt == ENOMEM) {
- vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
- } else {
- fatal("pthread_getattr_np failed with errno = %d", rslt);
- }
- }
-
- if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
- fatal("Can not locate current stack attributes!");
- }
-
- pthread_attr_destroy(&attr);
-
- }
- assert(os::current_stack_pointer() >= *bottom &&
- os::current_stack_pointer() < *bottom + *size, "just checking");
-}
-
-address os::current_stack_base() {
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return (bottom + size);
-}
-
-size_t os::current_stack_size() {
- // stack size includes normal stack and HotSpot guard pages
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return size;
-}
-
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
--- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -156,51 +156,6 @@
return (address)sp;
}
-static void current_stack_region(address* bottom, size_t* size) {
- if (os::Linux::is_initial_thread()) {
- // initial thread needs special handling because pthread_getattr_np()
- // may return bogus value.
- *bottom = os::Linux::initial_thread_stack_bottom();
- *size = os::Linux::initial_thread_stack_size();
- } else {
- pthread_attr_t attr;
-
- int rslt = pthread_getattr_np(pthread_self(), &attr);
-
- // JVM needs to know exact stack location, abort if it fails
- if (rslt != 0) {
- if (rslt == ENOMEM) {
- vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
- } else {
- fatal("pthread_getattr_np failed with errno = %d", rslt);
- }
- }
-
- if (pthread_attr_getstack(&attr, (void**)bottom, size) != 0) {
- fatal("Can not locate current stack attributes!");
- }
-
- pthread_attr_destroy(&attr);
- }
- assert(os::current_stack_pointer() >= *bottom &&
- os::current_stack_pointer() < *bottom + *size, "just checking");
-}
-
-address os::current_stack_base() {
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return bottom + size;
-}
-
-size_t os::current_stack_size() {
- // stack size includes normal stack and HotSpot guard pages
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return size;
-}
-
char* os::non_memory_address_word() {
// Must never look like an address returned by reserve_memory,
// even in its subfields (as defined by the CPU immediate fields,
@@ -726,8 +681,10 @@
///////////////////////////////////////////////////////////////////////////////
// thread stack
-size_t os::Posix::_compiler_thread_min_stack_allowed = 128 * K;
-size_t os::Posix::_java_thread_min_stack_allowed = 128 * K;
+// Minimum usable stack sizes required to get to user code. Space for
+// HotSpot guard pages is added later.
+size_t os::Posix::_compiler_thread_min_stack_allowed = 64 * K;
+size_t os::Posix::_java_thread_min_stack_allowed = 64 * K;
size_t os::Posix::_vm_internal_thread_min_stack_allowed = 128 * K;
// return default stack size for thr_type
@@ -737,12 +694,6 @@
return s;
}
-size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
- // Creating guard page is very expensive. Java thread has HotSpot
- // guard page, only enable glibc guard page for non-Java threads.
- return (thr_type == java_thread ? 0 : page_size());
-}
-
#ifndef PRODUCT
void os::verify_stack_alignment() {
}
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -677,15 +677,15 @@
////////////////////////////////////////////////////////////////////////////////
// thread stack
-#ifdef AMD64
-size_t os::Posix::_compiler_thread_min_stack_allowed = 64 * K;
-size_t os::Posix::_java_thread_min_stack_allowed = 64 * K;
+// Minimum usable stack sizes required to get to user code. Space for
+// HotSpot guard pages is added later.
+size_t os::Posix::_compiler_thread_min_stack_allowed = 48 * K;
+size_t os::Posix::_java_thread_min_stack_allowed = 40 * K;
+#ifdef _LP64
size_t os::Posix::_vm_internal_thread_min_stack_allowed = 64 * K;
#else
-size_t os::Posix::_compiler_thread_min_stack_allowed = (48 DEBUG_ONLY(+ 4)) * K;
-size_t os::Posix::_java_thread_min_stack_allowed = (48 DEBUG_ONLY(+ 4)) * K;
size_t os::Posix::_vm_internal_thread_min_stack_allowed = (48 DEBUG_ONLY(+ 4)) * K;
-#endif // AMD64
+#endif // _LP64
// return default stack size for thr_type
size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
@@ -698,91 +698,6 @@
return s;
}
-size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
- // Creating guard page is very expensive. Java thread has HotSpot
- // guard page, only enable glibc guard page for non-Java threads.
- return (thr_type == java_thread ? 0 : page_size());
-}
-
-// Java thread:
-//
-// Low memory addresses
-// +------------------------+
-// | |\ JavaThread created by VM does not have glibc
-// | glibc guard page | - guard, attached Java thread usually has
-// | |/ 1 page glibc guard.
-// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
-// | |\
-// | HotSpot Guard Pages | - red and yellow pages
-// | |/
-// +------------------------+ JavaThread::stack_yellow_zone_base()
-// | |\
-// | Normal Stack | -
-// | |/
-// P2 +------------------------+ Thread::stack_base()
-//
-// Non-Java thread:
-//
-// Low memory addresses
-// +------------------------+
-// | |\
-// | glibc guard page | - usually 1 page
-// | |/
-// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
-// | |\
-// | Normal Stack | -
-// | |/
-// P2 +------------------------+ Thread::stack_base()
-//
-// ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from
-// pthread_attr_getstack()
-
-static void current_stack_region(address * bottom, size_t * size) {
- if (os::Linux::is_initial_thread()) {
- // initial thread needs special handling because pthread_getattr_np()
- // may return bogus value.
- *bottom = os::Linux::initial_thread_stack_bottom();
- *size = os::Linux::initial_thread_stack_size();
- } else {
- pthread_attr_t attr;
-
- int rslt = pthread_getattr_np(pthread_self(), &attr);
-
- // JVM needs to know exact stack location, abort if it fails
- if (rslt != 0) {
- if (rslt == ENOMEM) {
- vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
- } else {
- fatal("pthread_getattr_np failed with errno = %d", rslt);
- }
- }
-
- if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
- fatal("Can not locate current stack attributes!");
- }
-
- pthread_attr_destroy(&attr);
-
- }
- assert(os::current_stack_pointer() >= *bottom &&
- os::current_stack_pointer() < *bottom + *size, "just checking");
-}
-
-address os::current_stack_base() {
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return (bottom + size);
-}
-
-size_t os::current_stack_size() {
- // stack size includes normal stack and HotSpot guard pages
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return size;
-}
-
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
--- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -320,12 +320,6 @@
return s;
}
-size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
- // Only enable glibc guard pages for non-Java threads
- // (Java threads have HotSpot guard pages)
- return (thr_type == java_thread ? 0 : page_size());
-}
-
static void current_stack_region(address *bottom, size_t *size) {
pthread_attr_t attr;
int res = pthread_getattr_np(pthread_self(), &attr);
@@ -334,7 +328,7 @@
vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
}
else {
- fatal("pthread_getattr_np failed with errno = %d", res);
+ fatal("pthread_getattr_np failed with error = %d", res);
}
}
@@ -342,7 +336,7 @@
size_t stack_bytes;
res = pthread_attr_getstack(&attr, (void **) &stack_bottom, &stack_bytes);
if (res != 0) {
- fatal("pthread_attr_getstack failed with errno = %d", res);
+ fatal("pthread_attr_getstack failed with error = %d", res);
}
address stack_top = stack_bottom + stack_bytes;
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -81,15 +81,13 @@
#define MAX_PATH (2 * K)
-// Minimum stack size for the VM. It's easier to document a constant
-// but it's different for x86 and sparc because the page sizes are different.
+// Minimum usable stack sizes required to get to user code. Space for
+// HotSpot guard pages is added later.
+size_t os::Posix::_compiler_thread_min_stack_allowed = 104 * K;
+size_t os::Posix::_java_thread_min_stack_allowed = 86 * K;
#ifdef _LP64
-size_t os::Posix::_compiler_thread_min_stack_allowed = 128 * K;
-size_t os::Posix::_java_thread_min_stack_allowed = 128 * K;
size_t os::Posix::_vm_internal_thread_min_stack_allowed = 128 * K;
#else
-size_t os::Posix::_compiler_thread_min_stack_allowed = 96 * K;
-size_t os::Posix::_java_thread_min_stack_allowed = 96 * K;
size_t os::Posix::_vm_internal_thread_min_stack_allowed = 96 * K;
#endif
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -86,19 +86,23 @@
#define MAX_PATH (2 * K)
-// Minimum stack sizes for the VM. It's easier to document a constant value
-// but it's different for x86 and sparc because the page sizes are different.
+// Minimum usable stack sizes required to get to user code. Space for
+// HotSpot guard pages is added later.
+#ifdef _LP64
+size_t os::Posix::_compiler_thread_min_stack_allowed = 202 * K;
+size_t os::Posix::_java_thread_min_stack_allowed = 48 * K;
+size_t os::Posix::_vm_internal_thread_min_stack_allowed = 224 * K;
+#else
+size_t os::Posix::_compiler_thread_min_stack_allowed = 32 * K;
+size_t os::Posix::_java_thread_min_stack_allowed = 32 * K;
+size_t os::Posix::_vm_internal_thread_min_stack_allowed = 64 * K;
+#endif // _LP64
+
#ifdef AMD64
-size_t os::Posix::_compiler_thread_min_stack_allowed = 394 * K;
-size_t os::Posix::_java_thread_min_stack_allowed = 224 * K;
-size_t os::Posix::_vm_internal_thread_min_stack_allowed = 224 * K;
#define REG_SP REG_RSP
#define REG_PC REG_RIP
#define REG_FP REG_RBP
#else
-size_t os::Posix::_compiler_thread_min_stack_allowed = 64 * K;
-size_t os::Posix::_java_thread_min_stack_allowed = 64 * K;
-size_t os::Posix::_vm_internal_thread_min_stack_allowed = 64 * K;
#define REG_SP UESP
#define REG_PC EIP
#define REG_FP EBP
--- a/hotspot/src/share/vm/c1/c1_LIR.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIR.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -677,9 +677,7 @@
// LIR_Op3
case lir_idiv:
- case lir_irem:
- case lir_fmad:
- case lir_fmaf: {
+ case lir_irem: {
assert(op->as_Op3() != NULL, "must be");
LIR_Op3* op3= (LIR_Op3*)op;
@@ -697,6 +695,17 @@
break;
}
+ case lir_fmad:
+ case lir_fmaf: {
+ assert(op->as_Op3() != NULL, "must be");
+ LIR_Op3* op3= (LIR_Op3*)op;
+ assert(op3->_info == NULL, "no info");
+ do_input(op3->_opr1);
+ do_input(op3->_opr2);
+ do_input(op3->_opr3);
+ do_output(op3->_result);
+ break;
+ }
// LIR_OpJavaCall
case lir_static_call:
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -84,7 +84,6 @@
typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n);
typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);
typedef jint (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len);
-typedef void (JNICALL *FreeEntry_t)(jzfile *zip, jzentry *entry);
static ZipOpen_t ZipOpen = NULL;
static ZipClose_t ZipClose = NULL;
@@ -94,7 +93,6 @@
static canonicalize_fn_t CanonicalizeEntry = NULL;
static ZipInflateFully_t ZipInflateFully = NULL;
static Crc32_t Crc32 = NULL;
-static FreeEntry_t FreeEntry = NULL;
// Entry points for jimage.dll for loading jimage file entries
@@ -150,7 +148,6 @@
GrowableArray<char*>* ClassLoader::_boot_modules_array = NULL;
GrowableArray<char*>* ClassLoader::_platform_modules_array = NULL;
SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
-int ClassLoader::_num_patch_mod_prefixes = 0;
#endif
// helper routines
@@ -320,20 +317,6 @@
FREE_C_HEAP_ARRAY(char, _zip_name);
}
-bool ClassPathZipEntry::stream_exists(const char* name) {
- // enable call to C land
- JavaThread* thread = JavaThread::current();
- ThreadToNativeFromVM ttn(thread);
- // check whether zip archive contains name
- jint name_len, filesize;
- jzentry* entry = (*FindEntry)(_zip, name, &filesize, &name_len);
- if (entry != NULL) {
- (*FreeEntry)(_zip, entry);
- return true;
- }
- return false;
-}
-
u1* ClassPathZipEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) {
// enable call to C land
JavaThread* thread = JavaThread::current();
@@ -1090,7 +1073,6 @@
GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry"));
ZipInflateFully = CAST_TO_FN_PTR(ZipInflateFully_t, os::dll_lookup(handle, "ZIP_InflateFully"));
Crc32 = CAST_TO_FN_PTR(Crc32_t, os::dll_lookup(handle, "ZIP_CRC32"));
- FreeEntry = CAST_TO_FN_PTR(FreeEntry_t, os::dll_lookup(handle, "ZIP_FreeEntry"));
// ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL
if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL ||
@@ -1418,57 +1400,6 @@
return NULL;
}
-#if INCLUDE_CDS
-// The following function is only used during CDS dump time.
-// It checks if a class can be found in the jar entries of the _patch_mod_entries.
-// It does not support non-jar entries.
-bool ClassLoader::is_in_patch_module(const char* const file_name) {
- assert(DumpSharedSpaces, "dump time only");
- if (_patch_mod_entries == NULL) {
- return false;
- }
-
- int num_of_entries = _patch_mod_entries->length();
- char* class_module_name = NULL;
- ResourceMark rm;
- const char *pkg_name = package_from_name(file_name);
- // Using the jimage to obtain the class' module name.
- // The ModuleEntryTable cannot be used at this point during dump time
- // because the module system hasn't been initialized yet.
- if (pkg_name != NULL) {
- JImageFile *jimage = _jrt_entry->jimage();
- class_module_name = (char*)(*JImagePackageToModule)(jimage, pkg_name);
- }
-
- if (class_module_name == NULL) {
- return false;
- }
-
- // Loop through all the patch module entries looking for module
- for (int i = 0; i < num_of_entries; i++) {
- ModuleClassPathList* module_cpl = _patch_mod_entries->at(i);
- Symbol* module_cpl_name = module_cpl->module_name();
-
- if (strcmp(module_cpl_name->as_C_string(), class_module_name) == 0) {
- // Class' module has been located, attempt to locate
- // the class from the module's ClassPathEntry list.
- ClassPathEntry* e = module_cpl->module_first_entry();
- while (e != NULL) {
- if (e->is_jar_file()) {
- if (e->stream_exists(file_name)) {
- return true;
- } else {
- e = e->next();
- }
- }
- }
- }
- }
-
- return false;
-}
-#endif // INCLUDE_CDS
-
instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS) {
assert(name != NULL, "invariant");
assert(THREAD->is_Java_thread(), "must be a JavaThread");
@@ -1494,8 +1425,6 @@
// If DumpSharedSpaces is true boot loader visibility boundaries are set to:
// - [jimage] + [_first_append_entry to _last_append_entry] (all path entries).
- // If a class is found in the --patch-module entries, the class will not be included in the
- // CDS archive. Also, CDS is not supported if exploded module builds are used.
//
// If search_append_only is true, boot loader visibility boundaries are
// set to be _first_append_entry to the end. This includes:
@@ -1519,15 +1448,13 @@
// Note: The --patch-module entries are never searched if the boot loader's
// visibility boundary is limited to only searching the append entries.
if (_patch_mod_entries != NULL && !search_append_only) {
+ // At CDS dump time, the --patch-module entries are ignored. That means a
+ // class is still loaded from the runtime image even if it might
+ // appear in the _patch_mod_entries. The runtime shared class visibility
+ // check will determine if a shared class is visible based on the runtime
+ // environemnt, including the runtime --patch-module setting.
if (!DumpSharedSpaces) {
stream = search_module_entries(_patch_mod_entries, class_name, file_name, CHECK_NULL);
- } else {
-#if INCLUDE_CDS
- if (is_in_patch_module(file_name)) {
- tty->print_cr("Preload Warning: Skip archiving class %s found in --patch-module entry", class_name);
- return NULL;
- }
-#endif
}
}
@@ -1679,57 +1606,8 @@
}
#if INCLUDE_CDS
-// Capture all the --patch-module entries specified during CDS dump time.
-// It also captures the non-existing path(s) and the required file(s) during inspecting
-// the entries.
-void ClassLoader::setup_patch_mod_path() {
- assert(DumpSharedSpaces, "only used with -Xshare:dump");
- ResourceMark rm;
- GrowableArray<ModulePatchPath*>* patch_mod_args = Arguments::get_patch_mod_prefix();
- if (patch_mod_args != NULL) {
- int num_of_entries = patch_mod_args->length();
- for (int i = 0; i < num_of_entries; i++) {
- const char* module_name = (patch_mod_args->at(i))->module_name();
- const char* module_path = (patch_mod_args->at(i))->path_string();
- int path_len = (int)strlen(module_path);
- int name_len = (int)strlen(module_name);
- int buf_len = name_len + path_len + 2; // add 2 for the '=' and NULL terminator
- int end = 0;
- char* buf = NEW_C_HEAP_ARRAY(char, buf_len, mtInternal);
- // Iterate over the module's class path entries
- for (int start = 0; start < path_len; start = end) {
- while (module_path[end] && module_path[end] != os::path_separator()[0]) {
- end++;
- }
- strncpy(buf, &module_path[start], end - start);
- buf[end - start] = '\0';
- struct stat st;
- if (os::stat(buf, &st) != 0) {
- // File not found
- _shared_paths_misc_info->add_nonexist_path(buf);
- } else {
- if ((st.st_mode & S_IFMT) != S_IFREG) { // is not a regular file
- vm_exit_during_initialization(
- "--patch-module requires a regular file during dumping", buf);
- } else {
- _shared_paths_misc_info->add_required_file(buf);
- }
- }
- while (module_path[end] == os::path_separator()[0]) {
- end++;
- }
- };
- jio_snprintf(buf, buf_len, "%s=%s", module_name, module_path);
- _shared_paths_misc_info->add_patch_mod_classpath((const char*)buf);
- _num_patch_mod_prefixes++;
- FREE_C_HEAP_ARRAY(char, buf);
- }
- }
-}
-
void ClassLoader::initialize_shared_path() {
if (DumpSharedSpaces) {
- setup_patch_mod_path();
ClassLoaderExt::setup_search_paths();
_shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check()
}
--- a/hotspot/src/share/vm/classfile/classLoader.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/classfile/classLoader.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -69,7 +69,6 @@
// Attempt to locate file_name through this class path entry.
// Returns a class file parsing stream if successfull.
virtual ClassFileStream* open_stream(const char* name, TRAPS) = 0;
- virtual bool stream_exists(const char* name) = 0;
// Debugging
NOT_PRODUCT(virtual void compile_the_world(Handle loader, TRAPS) = 0;)
};
@@ -84,7 +83,6 @@
JImageFile* jimage() const { return NULL; }
ClassPathDirEntry(const char* dir);
ClassFileStream* open_stream(const char* name, TRAPS);
- bool stream_exists(const char* name) { return false; }
// Debugging
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
};
@@ -128,7 +126,6 @@
ClassFileStream* open_stream(const char* name, TRAPS);
void contents_do(void f(const char* name, void* context), void* context);
bool is_multiple_versioned(TRAPS) NOT_CDS_RETURN_(false);
- bool stream_exists(const char* name);
// Debugging
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
};
@@ -148,7 +145,6 @@
ClassPathImageEntry(JImageFile* jimage, const char* name);
~ClassPathImageEntry();
ClassFileStream* open_stream(const char* name, TRAPS);
- bool stream_exists(const char* name) { return false; }
// Debugging
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
@@ -259,7 +255,6 @@
// Info used by CDS
CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;)
- CDS_ONLY(static int _num_patch_mod_prefixes;)
// Initialization:
// - setup the boot loader's system class path
@@ -434,9 +429,6 @@
static void initialize_module_loader_map(JImageFile* jimage);
static s2 classloader_type(Symbol* class_name, ClassPathEntry* e,
int classpath_index, TRAPS);
- static bool is_in_patch_module(const char* const file_name);
- static void setup_patch_mod_path(); // Only when -Xshare:dump
- static int num_patch_mod_prefixes() { return _num_patch_mod_prefixes; }
#endif
static void trace_class_path(const char* msg, const char* name = NULL);
--- a/hotspot/src/share/vm/classfile/moduleEntry.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/classfile/moduleEntry.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -108,6 +108,18 @@
}
MutexLocker m1(Module_lock);
+ // This is a guard against possible race between agent threads that redefine
+ // or retransform classes in this module. Only one of them is adding the
+ // default read edges to the unnamed modules of the boot and app class loaders
+ // with an upcall to jdk.internal.module.Modules.transformedByAgent.
+ // At the same time, another thread can instrument the module classes by
+ // injecting dependencies that require the default read edges for resolution.
+ if (this->has_default_read_edges() && !m->is_named()) {
+ ClassLoaderData* cld = m->loader_data();
+ if (cld->is_the_null_class_loader_data() || cld->is_system_class_loader_data()) {
+ return true; // default read edge
+ }
+ }
if (!has_reads()) {
return false;
} else {
--- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -86,9 +86,6 @@
case REQUIRED:
out->print("Expecting that file %s must exist and is not altered", path);
break;
- case PATCH_MOD:
- out->print("Expecting --patch-module=%s", path);
- break;
default:
ShouldNotReachHere();
}
@@ -167,26 +164,6 @@
}
}
break;
- case PATCH_MOD:
- {
- GrowableArray<ModulePatchPath*>* patch_mod_args = Arguments::get_patch_mod_prefix();
- if (patch_mod_args != NULL) {
- int num_of_entries = patch_mod_args->length();
- for (int i = 0; i < num_of_entries; i++) {
- const char* module_name = (patch_mod_args->at(i))->module_name();
- const char* path_string = (patch_mod_args->at(i))->path_string();
- size_t n = strlen(module_name);
- // path contains the module name, followed by '=', and one or more entries.
- // E.g.: "java.base=foo" or "java.naming=dir1:dir2:dir3"
- if ((strncmp(module_name, path, n) != 0) ||
- (path[n] != '=') ||
- (strcmp(path + n + 1, path_string) != 0)) {
- return fail("--patch-module mismatch, path not found in run time: ", path);
- }
- }
- }
- }
- break;
default:
return fail("Corrupted archive file header");
}
--- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -104,28 +104,10 @@
add_path(path, NON_EXIST);
}
- // The path must exist and have required size and modification time
- void add_required_file(const char* path) {
- add_path(path, REQUIRED);
-
- struct stat st;
- if (os::stat(path, &st) != 0) {
- assert(0, "sanity");
-#if INCLUDE_CDS
- ClassLoader::exit_with_path_failure("failed to os::stat(%s)", path); // should not happen
-#endif
- }
- write_time(st.st_mtime);
- write_long(st.st_size);
- }
-
// The path must exist, and must contain exactly <num_entries> files/dirs
void add_boot_classpath(const char* path) {
add_path(path, BOOT);
}
- void add_patch_mod_classpath(const char* path) {
- add_path(path, PATCH_MOD);
- }
int write_jint(jint num) {
write(&num, sizeof(num));
return 0;
@@ -147,8 +129,7 @@
enum {
BOOT = 1,
NON_EXIST = 2,
- REQUIRED = 3,
- PATCH_MOD = 4
+ REQUIRED = 3
};
virtual const char* type_name(int type) {
@@ -156,7 +137,6 @@
case BOOT: return "BOOT";
case NON_EXIST: return "NON_EXIST";
case REQUIRED: return "REQUIRED";
- case PATCH_MOD: return "PATCH_MOD";
default: ShouldNotReachHere(); return "?";
}
}
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -1231,6 +1231,8 @@
bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
instanceKlassHandle ik,
Handle class_loader, TRAPS) {
+ assert(!ModuleEntryTable::javabase_moduleEntry()->is_patched(),
+ "Cannot use sharing if java.base is patched");
ResourceMark rm;
int path_index = ik->shared_classpath_index();
SharedClassPathEntry* ent =
@@ -1258,6 +1260,12 @@
}
}
+ // If the archived class is from a module that has been patched at runtime,
+ // the class cannot be loaded from the archive.
+ if (mod_entry != NULL && mod_entry->is_patched()) {
+ return false;
+ }
+
if (class_loader.is_null()) {
assert(ent != NULL, "Shared class for NULL classloader must have valid SharedClassPathEntry");
// The NULL classloader can load archived class originated from the
--- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -299,10 +299,6 @@
}
static void initialize_method_handle_entries();
-
- // PPC-only: Support abs and sqrt like in compiler.
- // For others we can use a normal (native) entry.
- static bool math_entry_available(MethodKind kind);
};
//------------------------------------------------------------------------------------------------------------------------
--- a/hotspot/src/share/vm/interpreter/cppInterpreterGenerator.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/interpreter/cppInterpreterGenerator.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -57,6 +57,8 @@
method_entry(java_lang_math_log10 );
method_entry(java_lang_math_pow );
method_entry(java_lang_math_exp );
+ method_entry(java_lang_math_fmaD );
+ method_entry(java_lang_math_fmaF );
method_entry(java_lang_ref_reference_get);
AbstractInterpreter::initialize_method_handle_entries();
@@ -95,7 +97,9 @@
case Interpreter::java_lang_math_log10 : // fall thru
case Interpreter::java_lang_math_sqrt : // fall thru
case Interpreter::java_lang_math_pow : // fall thru
- case Interpreter::java_lang_math_exp : entry_point = generate_math_entry(kind); break;
+ case Interpreter::java_lang_math_exp : // fall thru
+ case Interpreter::java_lang_math_fmaD : // fall thru
+ case Interpreter::java_lang_math_fmaF : entry_point = generate_math_entry(kind); break;
case Interpreter::java_lang_ref_reference_get
: entry_point = generate_Reference_get_entry(); break;
default:
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -426,15 +426,16 @@
Symbol* field_sig = cp->signature_ref_at(bc_index);
fieldDescriptor fd;
- klass->find_field(field_name, field_sig, &fd);
- if (fd.access_flags().is_final()) {
- if (fd.access_flags().is_static()) {
- if (!method->is_static_initializer()) {
- fd.set_has_initialized_final_update(true);
- }
- } else {
- if (!method->is_object_initializer()) {
- fd.set_has_initialized_final_update(true);
+ if (klass->find_field(field_name, field_sig, &fd) != NULL) {
+ if (fd.access_flags().is_final()) {
+ if (fd.access_flags().is_static()) {
+ if (!method->is_static_initializer()) {
+ fd.set_has_initialized_final_update(true);
+ }
+ } else {
+ if (!method->is_object_initializer()) {
+ fd.set_has_initialized_final_update(true);
+ }
}
}
}
--- a/hotspot/src/share/vm/logging/logFileStreamOutput.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/logging/logFileStreamOutput.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -29,11 +29,17 @@
#include "memory/allocation.inline.hpp"
static bool initialized;
-static char stdoutmem[sizeof(LogStdoutOutput)];
-static char stderrmem[sizeof(LogStderrOutput)];
+static union {
+ char stdoutmem[sizeof(LogStdoutOutput)];
+ jlong dummy;
+} aligned_stdoutmem;
+static union {
+ char stderrmem[sizeof(LogStderrOutput)];
+ jlong dummy;
+} aligned_stderrmem;
-LogStdoutOutput &StdoutLog = reinterpret_cast<LogStdoutOutput&>(stdoutmem);
-LogStderrOutput &StderrLog = reinterpret_cast<LogStderrOutput&>(stderrmem);
+LogStdoutOutput &StdoutLog = reinterpret_cast<LogStdoutOutput&>(aligned_stdoutmem.stdoutmem);
+LogStderrOutput &StderrLog = reinterpret_cast<LogStderrOutput&>(aligned_stderrmem.stderrmem);
LogFileStreamInitializer::LogFileStreamInitializer() {
if (!initialized) {
--- a/hotspot/src/share/vm/memory/filemap.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/memory/filemap.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -179,7 +179,6 @@
_classpath_entry_table_size = mapinfo->_classpath_entry_table_size;
_classpath_entry_table = mapinfo->_classpath_entry_table;
_classpath_entry_size = mapinfo->_classpath_entry_size;
- _num_patch_mod_prefixes = ClassLoader::num_patch_mod_prefixes();
// The following fields are for sanity checks for whether this archive
// will function correctly with this JVM and the bootclasspath it's
@@ -948,23 +947,6 @@
return false;
}
- // Check if there is a mismatch in --patch-module entry counts between dump time and run time.
- // More checks will be performed on individual --patch-module entry in the
- // SharedPathsMiscInfo::check() function.
- GrowableArray<ModulePatchPath*>* patch_mod_args = Arguments::get_patch_mod_prefix();
- if (patch_mod_args != NULL) {
- if (_num_patch_mod_prefixes == 0) {
- FileMapInfo::fail_stop("--patch-module found in run time but none was specified in dump time");
- }
- if (patch_mod_args->length() != _num_patch_mod_prefixes) {
- FileMapInfo::fail_stop("mismatched --patch-module entry counts between dump time and run time");
- }
- } else {
- if (_num_patch_mod_prefixes > 0) {
- FileMapInfo::fail_stop("--patch-module specified in dump time but none was specified in run time");
- }
- }
-
return true;
}
--- a/hotspot/src/share/vm/memory/filemap.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/memory/filemap.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -155,7 +155,6 @@
// loading failures during runtime.
int _classpath_entry_table_size;
size_t _classpath_entry_size;
- int _num_patch_mod_prefixes; // number of --patch-module entries
SharedClassPathEntry* _classpath_entry_table;
char* region_addr(int idx);
--- a/hotspot/src/share/vm/opto/runtime.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/opto/runtime.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -59,7 +59,6 @@
#include "opto/mulnode.hpp"
#include "opto/runtime.hpp"
#include "opto/subnode.hpp"
-#include "prims/jvmtiThreadState.hpp"
#include "runtime/atomic.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/handles.inline.hpp"
@@ -1458,11 +1457,6 @@
}
#endif
- JvmtiThreadState *state = thread->jvmti_thread_state();
- if (state != NULL) {
- state->set_exception_detected();
- }
-
thread->set_vm_result(exception);
// Frame not compiled (handles deoptimization blob)
return SharedRuntime::raw_exception_handler_for_return_address(thread, ret_pc);
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -130,15 +130,15 @@
private:
JavaThread *_thread;
JNIEnv* _jni_env;
- bool _exception_detected;
- bool _exception_caught;
+ JvmtiThreadState::ExceptionState _saved_exception_state;
#if 0
JNIHandleBlock* _hblock;
#endif
public:
JvmtiEventMark(JavaThread *thread) : _thread(thread),
- _jni_env(thread->jni_environment()) {
+ _jni_env(thread->jni_environment()),
+ _saved_exception_state(JvmtiThreadState::ES_CLEARED) {
#if 0
_hblock = thread->active_handles();
_hblock->clear_thoroughly(); // so we can be safe
@@ -149,11 +149,7 @@
// we are before an event.
// Save current jvmti thread exception state.
if (state != NULL) {
- _exception_detected = state->is_exception_detected();
- _exception_caught = state->is_exception_caught();
- } else {
- _exception_detected = false;
- _exception_caught = false;
+ _saved_exception_state = state->get_exception_state();
}
JNIHandleBlock* old_handles = thread->active_handles();
@@ -186,12 +182,7 @@
// we are continuing after an event.
if (state != NULL) {
// Restore the jvmti thread exception state.
- if (_exception_detected) {
- state->set_exception_detected();
- }
- if (_exception_caught) {
- state->set_exception_caught();
- }
+ state->restore_exception_state(_saved_exception_state);
}
}
@@ -1552,7 +1543,6 @@
}
}
-
void JvmtiExport::post_exception_throw(JavaThread *thread, Method* method, address location, oop exception) {
HandleMark hm(thread);
methodHandle mh(thread, method);
@@ -2454,7 +2444,7 @@
JvmtiThreadState* state = thread->jvmti_thread_state();
if (state != NULL) {
- state->clear_exception_detected();
+ state->clear_exception_state();
}
}
--- a/hotspot/src/share/vm/prims/jvmtiThreadState.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiThreadState.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -50,8 +50,7 @@
: _thread_event_enable() {
assert(JvmtiThreadState_lock->is_locked(), "sanity check");
_thread = thread;
- _exception_detected = false;
- _exception_caught = false;
+ _exception_state = ES_CLEARED;
_debuggable = true;
_hide_single_stepping = false;
_hide_level = 0;
@@ -310,7 +309,7 @@
// an exception.
//
if (is_exception_detected()) {
- clear_exception_detected();
+ clear_exception_state();
}
// If step is pending for popframe then it may not be
// a repeat step. The new_bci and method_id is same as current_bci
@@ -385,7 +384,7 @@
// an exception.
//
if (is_exception_detected()) {
- clear_exception_detected();
+ clear_exception_state();
}
// If step is pending for earlyret then it may not be a repeat step.
// The new_bci and method_id is same as current_bci and current
--- a/hotspot/src/share/vm/prims/jvmtiThreadState.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiThreadState.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -76,13 +76,21 @@
private:
friend class JvmtiEnv;
JavaThread *_thread;
- bool _exception_detected;
- bool _exception_caught;
bool _hide_single_stepping;
bool _pending_step_for_popframe;
bool _pending_step_for_earlyret;
int _hide_level;
+ public:
+ enum ExceptionState {
+ ES_CLEARED,
+ ES_DETECTED,
+ ES_CAUGHT
+ };
+
+ private:
+ ExceptionState _exception_state;
+
// Used to send class being redefined/retransformed and kind of transform
// info to the class file load hook event handler.
KlassHandle *_class_being_redefined;
@@ -161,16 +169,18 @@
int count_frames();
inline JavaThread *get_thread() { return _thread; }
- inline bool is_exception_detected() { return _exception_detected; }
- inline bool is_exception_caught() { return _exception_caught; }
- inline void set_exception_detected() { _exception_detected = true;
- _exception_caught = false; }
- inline void clear_exception_detected() {
- _exception_detected = false;
- assert(_exception_caught == false, "_exception_caught is out of phase");
- }
- inline void set_exception_caught() { _exception_caught = true;
- _exception_detected = false; }
+
+ inline bool is_exception_detected() { return _exception_state == ES_DETECTED; }
+ inline bool is_exception_caught() { return _exception_state == ES_CAUGHT; }
+
+ inline void set_exception_detected() { _exception_state = ES_DETECTED; }
+ inline void set_exception_caught() { _exception_state = ES_CAUGHT; }
+
+ inline void clear_exception_state() { _exception_state = ES_CLEARED; }
+
+ // We need to save and restore exception state inside JvmtiEventMark
+ inline ExceptionState get_exception_state() { return _exception_state; }
+ inline void restore_exception_state(ExceptionState state) { _exception_state = state; }
inline void clear_hide_single_stepping() {
if (_hide_level > 0) {
--- a/hotspot/src/share/vm/runtime/arguments.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -1323,26 +1323,32 @@
"jdk.module.limitmods",
"jdk.module.path",
"jdk.module.upgrade.path",
- "jdk.module.addmods.0" };
- const char* unsupported_options[] = { "-m",
- "--limit-modules",
- "--module-path",
- "--upgrade-module-path",
- "--add-modules" };
+ "jdk.module.addmods.0",
+ "jdk.module.patch.0" };
+ const char* unsupported_options[] = { "-m", // cannot use at dump time
+ "--limit-modules", // ignored at dump time
+ "--module-path", // ignored at dump time
+ "--upgrade-module-path", // ignored at dump time
+ "--add-modules", // ignored at dump time
+ "--patch-module" // ignored at dump time
+ };
assert(ARRAY_SIZE(unsupported_properties) == ARRAY_SIZE(unsupported_options), "must be");
- // If a vm option is found in the unsupported_options array with index less than the warning_idx,
- // vm will exit with an error message. Otherwise, it will result in a warning message.
- uint warning_idx = 2;
+ // If a vm option is found in the unsupported_options array with index less than the info_idx,
+ // vm will exit with an error message. Otherwise, it will print an informational message if
+ // PrintSharedSpaces is enabled.
+ uint info_idx = 1;
SystemProperty* sp = system_properties();
while (sp != NULL) {
for (uint i = 0; i < ARRAY_SIZE(unsupported_properties); i++) {
if (strcmp(sp->key(), unsupported_properties[i]) == 0) {
- if (i < warning_idx) {
+ if (i < info_idx) {
vm_exit_during_initialization(
"Cannot use the following option when dumping the shared archive", unsupported_options[i]);
} else {
- warning(
- "the %s option is ignored when dumping the shared archive", unsupported_options[i]);
+ if (PrintSharedSpaces) {
+ tty->print_cr(
+ "Info: the %s option is ignored when dumping the shared archive", unsupported_options[i]);
+ }
}
}
}
@@ -1419,10 +1425,8 @@
}
}
-#if defined(COMPILER2) || INCLUDE_JVMCI || defined(_LP64) || !INCLUDE_CDS
// Conflict: required to use shared spaces (-Xshare:on), but
// incompatible command line options were chosen.
-
static void no_shared_spaces(const char* message) {
if (RequireSharedSpaces) {
jio_fprintf(defaultStream::error_stream(),
@@ -1432,7 +1436,6 @@
FLAG_SET_DEFAULT(UseSharedSpaces, false);
}
}
-#endif
// Returns threshold scaled with the value of scale.
// If scale < 0.0, threshold is returned without scaling.
@@ -2680,6 +2683,12 @@
return result;
}
+#if INCLUDE_CDS
+ if (UseSharedSpaces && patch_mod_javabase) {
+ no_shared_spaces("CDS is disabled when " JAVA_BASE_NAME " module is patched.");
+ }
+#endif
+
return JNI_OK;
}
@@ -4408,7 +4417,6 @@
}
jint Arguments::apply_ergo() {
-
// Set flags based on ergonomics.
set_ergonomics_flags();
--- a/hotspot/src/share/vm/runtime/os.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/runtime/os.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -436,7 +436,7 @@
vm_thread,
cgc_thread, // Concurrent GC thread
pgc_thread, // Parallel GC thread
- java_thread,
+ java_thread, // Java, CodeCacheSweeper, JVMTIAgent and Service threads.
compiler_thread,
watcher_thread,
os_thread
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -288,7 +288,8 @@
nonstatic_field(Klass, _access_flags, AccessFlags) \
nonstatic_field(Klass, _prototype_header, markOop) \
nonstatic_field(Klass, _next_sibling, Klass*) \
- nonstatic_field(Klass, _vtable_len, int) \
+ nonstatic_field(Klass, _next_link, Klass*) \
+ nonstatic_field(Klass, _vtable_len, int) \
nonstatic_field(vtableEntry, _method, Method*) \
nonstatic_field(MethodData, _size, int) \
nonstatic_field(MethodData, _method, Method*) \
@@ -712,6 +713,8 @@
\
nonstatic_field(ClassLoaderData, _class_loader, oop) \
nonstatic_field(ClassLoaderData, _next, ClassLoaderData*) \
+ volatile_nonstatic_field(ClassLoaderData, _klasses, Klass*) \
+ nonstatic_field(ClassLoaderData, _is_anonymous, bool) \
\
static_field(ClassLoaderDataGraph, _head, ClassLoaderData*) \
\
--- a/hotspot/test/ProblemList.txt Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/test/ProblemList.txt Thu Dec 22 22:07:36 2016 +0100
@@ -71,7 +71,6 @@
# :hotspot_serviceability
-serviceability/dcmd/jvmti/LoadAgentDcmdTest.java 8150318 generic-all
serviceability/jdwp/AllModulesCommandTest.java 8168478 generic-all
serviceability/sa/sadebugd/SADebugDTest.java 8163805 generic-all
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/c2/Test7005594.java Thu Dec 22 22:07:36 2016 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011, 2016, 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 7005594
+ * @summary Array overflow not handled correctly with loop optimzations
+ *
+ * @run main/othervm -Xcomp
+ -XX:CompileOnly=compiler.c2.Test7005594::test
+ compiler.c2.Test7005594
+ */
+
+package compiler.c2;
+
+public class Test7005594 {
+ static int test(byte a[]){
+ int result = 0;
+ for (int i = 1; i < a.length; i += Integer.MAX_VALUE) {
+ result += a[i];
+ }
+ return result;
+ }
+
+ public static void main(String [] args){
+ try {
+ int result = test(new byte[2]);
+ throw new AssertionError("Expected ArrayIndexOutOfBoundsException was not thrown");
+ } catch (ArrayIndexOutOfBoundsException e) {
+ System.out.println("Expected " + e + " was thrown");
+ }
+ }
+}
--- a/hotspot/test/compiler/c2/cr7005594/Test7005594.java Wed Dec 21 22:41:18 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2011, 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 7005594
- * @summary Array overflow not handled correctly with loop optimzations
- *
- * @run shell Test7005594.sh
- */
-
-package compiler.c2.cr7005594;
-
-public class Test7005594 {
-
- static int test(byte a[]){
- int result=0;
- for( int i=0; i<a.length; i+=((0x7fffffff>>1)+1) ){
- result += a[i];
- }
- return result;
- }
-
- public static void main(String [] args){
- byte a[]=new byte[(0x7fffffff>>1)+2];
- int result = 0;
- try {
- result = test(a);
- } catch (ArrayIndexOutOfBoundsException e) {
- e.printStackTrace(System.out);
- System.out.println("Passed");
- System.exit(95);
- }
- System.out.println(result);
- System.out.println("FAILED");
- System.exit(97);
- }
-
-}
-
--- a/hotspot/test/compiler/c2/cr7005594/Test7005594.sh Wed Dec 21 22:41:18 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2011, 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.
-#
-#
-## some tests require path to find test source dir
-if [ "${TESTSRC}" = "" ]
-then
- TESTSRC=${PWD}
- echo "TESTSRC not set. Using "${TESTSRC}" as default"
-fi
-echo "TESTSRC=${TESTSRC}"
-## Adding common setup Variables for running shell tests.
-. ${TESTSRC}/../../../test_env.sh
-
-# Amount of physical memory in megabytes
-MEM=0
-if [ -f "/proc/meminfo" ]; then
- # Linux, Windows/Cygwin
- MEM=`cat /proc/meminfo |grep ^MemTotal: | awk '{print $2}'`
- MEM="$(($MEM / 1024))"
-elif [ -x "/usr/sbin/prtconf" ]; then
- # Solaris
- MEM=`/usr/sbin/prtconf | grep "^Memory size" | awk '{print $3}'`
-elif [ -x "/usr/sbin/system_profiler" ]; then
- # MacOS
- MEMo=`/usr/sbin/system_profiler SPHardwareDataType | grep Memory:`
- MEM=`echo "$MEMo" | awk '{print $2}'`
- MEMu=`echo "$MEMo" | awk '{print $3}'`
- case $MEMu in
- GB)
- MEM="$(($MEM * 1024))"
- ;;
- MB)
- ;;
- *)
- echo "Unknown memory unit in system_profile output: $MEMu"
- ;;
- esac
-elif [ -n "$ROOTDIR" -a -x "$ROOTDIR/mksnt/sysinf" ]; then
- # Windows/MKS
- MEM=`"$ROOTDIR/mksnt/sysinf" memory -v | grep "Total Physical Memory: " | sed 's/Total Physical Memory: *//g'`
- MEM="$(($machine_memory / 1024))"
-else
- echo "Unable to determine amount of physical memory on the machine"
-fi
-
-if [ $MEM -lt 2000 ]; then
- echo "Test skipped due to low (or unknown) memory on the system: $MEM Mb"
- exit 0
-fi
-
-echo "MEMORY=$MEM Mb"
-
-set -x
-
-cp ${TESTSRC}/Test7005594.java .
-cp ${TESTSRC}/Test7005594.sh .
-
-${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Test7005594.java
-
-${TESTJAVA}/bin/java ${TESTOPTS} -Xmx1600m -Xms1600m -XX:+IgnoreUnrecognizedVMOptions \
- -XX:-ZapUnusedHeapArea -Xcomp -XX:CompileCommand=quiet \
- -XX:CompileOnly=compiler.c2.cr7005594.Test7005594::test \
- compiler.c2.cr7005594.Test7005594 > test.out 2>&1
-
-result=$?
-
-cat test.out
-
-if [ $result -eq 95 ]
-then
- echo "Passed"
- exit 0
-fi
-
-if [ $result -eq 97 ]
-then
- echo "Failed"
- exit 1
-fi
-
-# The test should pass when no enough space for object heap
-grep "Could not reserve enough space for .*object heap" test.out
-if [ $? = 0 ]
-then
- echo "Passed"
- exit 0
-else
- echo "Failed"
- exit 1
-fi
--- a/hotspot/test/compiler/ciReplay/CiReplayBase.java Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/test/compiler/ciReplay/CiReplayBase.java Thu Dec 22 22:07:36 2016 +0100
@@ -215,7 +215,7 @@
try(BufferedReader br = new BufferedReader(new FileReader(REPLAY_FILE_NAME))) {
return br.lines()
.filter(s -> s.startsWith("compile "))
- .map(s -> s.substring(s.lastIndexOf(' ') + 1))
+ .map(s -> s.split("\\s+")[5])
.map(Integer::parseInt)
.findAny()
.get();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/floatingpoint/TestFMABrokenC1RegAlloc.java Thu Dec 22 22:07:36 2016 +0100
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2016, Red Hat, Inc. 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 8171092
+ * @summary C1's Math.fma() intrinsic doesn't correctly marks its inputs
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestFMABrokenC1RegAlloc
+ *
+ */
+
+public class TestFMABrokenC1RegAlloc {
+
+ double dummy0;
+ double dummy1;
+ double dummy2;
+ double dummy3;
+ double dummy4;
+ double dummy5;
+ double dummy6;
+ double dummy7;
+ double dummy8;
+ double dummy9;
+ double dummy10;
+ double dummy11;
+ double dummy12;
+ double dummy13;
+ double dummy14;
+ double dummy15;
+ double dummy16;
+ double dummy17;
+ double dummy18;
+ double dummy19;
+ double dummy20;
+ double dummy21;
+ double dummy22;
+ double dummy23;
+ double dummy24;
+ double dummy25;
+ double dummy26;
+ double dummy27;
+ double dummy28;
+ double dummy29;
+ double dummy30;
+ double dummy31;
+ double dummy32;
+ double dummy33;
+ double dummy34;
+ double dummy35;
+ double dummy36;
+ double dummy37;
+ double dummy38;
+ double dummy39;
+
+ double test(double a, double b, double c) {
+ double dummy0 = this.dummy0;
+ double dummy1 = this.dummy1;
+ double dummy2 = this.dummy2;
+ double dummy3 = this.dummy3;
+ double dummy4 = this.dummy4;
+ double dummy5 = this.dummy5;
+ double dummy6 = this.dummy6;
+ double dummy7 = this.dummy7;
+ double dummy8 = this.dummy8;
+ double dummy9 = this.dummy9;
+ double dummy10 = this.dummy10;
+ double dummy11 = this.dummy11;
+ double dummy12 = this.dummy12;
+ double dummy13 = this.dummy13;
+ double dummy14 = this.dummy14;
+ double dummy15 = this.dummy15;
+ double dummy16 = this.dummy16;
+ double dummy17 = this.dummy17;
+ double dummy18 = this.dummy18;
+ double dummy19 = this.dummy19;
+ double dummy20 = this.dummy20;
+ double dummy21 = this.dummy21;
+ double dummy22 = this.dummy22;
+ double dummy23 = this.dummy23;
+ double dummy24 = this.dummy24;
+ double dummy25 = this.dummy25;
+ double dummy26 = this.dummy26;
+ double dummy27 = this.dummy27;
+ double dummy28 = this.dummy28;
+ double dummy29 = this.dummy29;
+ double dummy30 = this.dummy30;
+ double dummy31 = this.dummy31;
+ double dummy32 = this.dummy32;
+ double dummy33 = this.dummy33;
+ double dummy34 = this.dummy34;
+ double dummy35 = this.dummy35;
+ double dummy36 = this.dummy36;
+ double dummy37 = this.dummy37;
+ double dummy38 = this.dummy38;
+ double dummy39 = this.dummy39;
+ return Math.fma(a, b, c) +
+ dummy0 +
+ dummy1 +
+ dummy2 +
+ dummy3 +
+ dummy4 +
+ dummy5 +
+ dummy6 +
+ dummy7 +
+ dummy8 +
+ dummy9 +
+ dummy10 +
+ dummy11 +
+ dummy12 +
+ dummy13 +
+ dummy14 +
+ dummy15 +
+ dummy16 +
+ dummy17 +
+ dummy18 +
+ dummy19 +
+ dummy20 +
+ dummy21 +
+ dummy22 +
+ dummy23 +
+ dummy24 +
+ dummy25 +
+ dummy26 +
+ dummy27 +
+ dummy28 +
+ dummy29 +
+ dummy30 +
+ dummy31 +
+ dummy32 +
+ dummy33 +
+ dummy34 +
+ dummy35 +
+ dummy36 +
+ dummy37 +
+ dummy38 +
+ dummy39;
+ }
+
+ static public void main(String[] args) {
+ TestFMABrokenC1RegAlloc t = new TestFMABrokenC1RegAlloc();
+ for (int i = 0; i < 5000; i++) {
+ if (t.test(5.0, 10.0, 7.0) != 57.0) {
+ throw new RuntimeException("Failed");
+ }
+ }
+ }
+}
--- a/hotspot/test/compiler/testlibrary/rtm/RTMTestBase.java Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/test/compiler/testlibrary/rtm/RTMTestBase.java Thu Dec 22 22:07:36 2016 +0100
@@ -241,7 +241,7 @@
CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS,
CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
"-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI",
- "-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED");
+ "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED");
if (test != null) {
for (String method : test.getMethodsToCompileNames()) {
--- a/hotspot/test/native/logging/logTestUtils.inline.hpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/test/native/logging/logTestUtils.inline.hpp Thu Dec 22 22:07:36 2016 +0100
@@ -59,6 +59,20 @@
assert(!failed, "failed to create directory %s", name);
}
+static inline void delete_empty_directory(const char* name) {
+#ifdef _WINDOWS
+ if (!file_exists(name)) {
+ return;
+ }
+ bool failed;
+ failed = !RemoveDirectory(name);
+ EXPECT_FALSE(failed) << "failed to remove directory '" << name
+ << "': LastError = " << GetLastError();
+#else
+ delete_file(name);
+#endif
+}
+
static inline void init_log_file(const char* filename, const char* options = "") {
LogStreamHandle(Error, logging) stream;
bool success = LogConfiguration::parse_log_arguments(filename, "logging=trace", "", options, &stream);
--- a/hotspot/test/native/logging/test_logFileOutput.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/test/native/logging/test_logFileOutput.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -103,7 +103,7 @@
EXPECT_FALSE(fo.initialize(buf, &ss)) << "Accepted filesize that overflows";
}
-TEST(LogFileOutput, startup_rotation) {
+TEST_VM(LogFileOutput, startup_rotation) {
const size_t rotations = 5;
const char* filename = "start-rotate-test";
char* rotated_file[rotations];
@@ -140,7 +140,7 @@
}
}
-TEST(LogFileOutput, startup_truncation) {
+TEST_VM(LogFileOutput, startup_truncation) {
const char* filename = "start-truncate-test";
const char* archived_filename = "start-truncate-test.0";
@@ -168,7 +168,7 @@
delete_file(archived_filename);
}
-TEST(LogFileOutput, invalid_file) {
+TEST_VM(LogFileOutput, invalid_file) {
ResourceMark rm;
stringStream ss;
@@ -179,5 +179,5 @@
<< "file was initialized when there was an existing directory with the same name";
EXPECT_TRUE(string_contains_substring(ss.as_string(), "tmplogdir is not a regular file"))
<< "missing expected error message, received msg: %s" << ss.as_string();
- remove("tmplogdir");
+ delete_empty_directory("tmplogdir");
}
--- a/hotspot/test/native/logging/test_logMessageTest.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/test/native/logging/test_logMessageTest.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -10,7 +10,7 @@
* 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
- * ac_heapanied this code).
+ * 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,
@@ -19,8 +19,8 @@
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
- *
*/
+
#include "precompiled.hpp"
#include "logTestFixture.hpp"
#include "logTestUtils.inline.hpp"
--- a/hotspot/test/native/logging/test_logStream.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/test/native/logging/test_logStream.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -41,41 +41,41 @@
EXPECT_TRUE(file_contains_substring(TestLogFileName, "3 workers\n"));
}
-TEST_F(LogStreamTest, from_log) {
+TEST_VM_F(LogStreamTest, from_log) {
Log(gc) log;
LogStream stream(log.debug());
verify_stream(&stream);
}
-TEST_F(LogStreamTest, from_logtarget) {
+TEST_VM_F(LogStreamTest, from_logtarget) {
LogTarget(Debug, gc) log;
LogStream stream(log);
verify_stream(&stream);
}
-TEST_F(LogStreamTest, handle) {
+TEST_VM_F(LogStreamTest, handle) {
LogStreamHandle(Debug, gc) stream;
verify_stream(&stream);
}
-TEST_F(LogStreamTest, no_rm) {
+TEST_VM_F(LogStreamTest, no_rm) {
ResourceMark rm;
outputStream* stream = LogTarget(Debug, gc)::stream();
verify_stream(stream);
}
-TEST_F(LogStreamTest, c_heap_stream) {
+TEST_VM_F(LogStreamTest, c_heap_stream) {
Log(gc) log;
LogStreamCHeap stream(log.debug());
verify_stream(&stream);
}
-TEST_F(LogStreamTest, c_heap_stream_target) {
+TEST_VM_F(LogStreamTest, c_heap_stream_target) {
LogTarget(Debug, gc) log;
LogStreamCHeap stream(log);
--- a/hotspot/test/native/utilities/test_linkedlist.cpp Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/test/native/utilities/test_linkedlist.cpp Thu Dec 22 22:07:36 2016 +0100
@@ -74,7 +74,7 @@
ASSERT_EQ(six.value(), i->value()) << "Should be 6";
i = ll.find(three);
- ASSERT_EQ(NULL, i) << "Not in the list";
+ ASSERT_TRUE(i == NULL) << "Not in the list";
LinkedListNode<Integer>* node = ll.find_node(six);
ASSERT_TRUE(node != NULL) << "6 is in the list";
--- a/hotspot/test/runtime/modules/IgnoreModulePropertiesTest.java Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/test/runtime/modules/IgnoreModulePropertiesTest.java Thu Dec 22 22:07:36 2016 +0100
@@ -72,6 +72,6 @@
testOption("--add-reads", "xyzz=yyzd", "jdk.module.addreads.0", "WARNING: Unknown module: xyzz");
testOption("--add-exports", "java.base/xyzz=yyzd", "jdk.module.addexports.0",
"WARNING: package xyzz not in java.base");
- testOption("--patch-module", "=d", "jdk.module.patch.0", "Missing module name");
+ testOption("--patch-module", "=d", "jdk.module.patch.0", "Unable to parse --patch-module");
}
}
--- a/hotspot/test/runtime/modules/PatchModule/PatchModuleCDS.java Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleCDS.java Thu Dec 22 22:07:36 2016 +0100
@@ -52,7 +52,7 @@
new OutputAnalyzer(pb.start())
.shouldContain("ro space:"); // Make sure archive got created.
- // Case 2: Test that only jar file in --patch-module is supported for CDS dumping
+ // Case 2: Test that directory in --patch-module is supported for CDS dumping
// Create a class file in the module java.base.
String source = "package javax.naming.spi; " +
"public class NamingManager { " +
@@ -73,7 +73,7 @@
"-Xlog:class+path=info",
"-version");
new OutputAnalyzer(pb.start())
- .shouldContain("--patch-module requires a regular file during dumping");
+ .shouldContain("ro space:"); // Make sure archive got created.
// Case 3a: Test CDS dumping with jar file in --patch-module
BasicJarBuilder.build("javanaming", "javax/naming/spi/NamingManager");
--- a/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java Thu Dec 22 22:07:36 2016 +0100
@@ -136,11 +136,7 @@
if (Platform.isWindows()) {
return "bin";
}
- if (Platform.isOSX()) {
- return "lib";
- }
-
- return "lib/" + Platform.getOsArch();
+ return "lib";
}
/**
--- a/hotspot/test/serviceability/jvmti/AddModuleExportsAndOpens/libAddModuleExportsAndOpensTest.c Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/test/serviceability/jvmti/AddModuleExportsAndOpens/libAddModuleExportsAndOpensTest.c Thu Dec 22 22:07:36 2016 +0100
@@ -82,14 +82,18 @@
}
static
-jint throw_exc(JNIEnv *env, char *msg) {
+void throw_exc(JNIEnv *env, char *msg) {
jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
+ jint rt = JNI_OK;
if (exc_class == NULL) {
printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
- return -1;
+ return;
}
- return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
+ rt = JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
+ if (rt == JNI_ERR) {
+ printf("throw_exc: Error in JNI ThrowNew(env, %s)\n", msg);
+ }
}
static
--- a/hotspot/test/serviceability/jvmti/AddModuleReads/libAddModuleReadsTest.c Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/test/serviceability/jvmti/AddModuleReads/libAddModuleReadsTest.c Thu Dec 22 22:07:36 2016 +0100
@@ -81,14 +81,18 @@
}
static
-jint throw_exc(JNIEnv *env, char *msg) {
+void throw_exc(JNIEnv *env, char *msg) {
jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
+ jint rt = JNI_OK;
if (exc_class == NULL) {
printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
- return -1;
+ return;
}
- return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
+ rt = JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
+ if (rt == JNI_ERR) {
+ printf("throw_exc: Error in JNI ThrowNew(env, %s)\n", msg);
+ }
}
static
--- a/hotspot/test/serviceability/jvmti/AddModuleUsesAndProvides/libAddModuleUsesAndProvidesTest.c Wed Dec 21 22:41:18 2016 -0800
+++ b/hotspot/test/serviceability/jvmti/AddModuleUsesAndProvides/libAddModuleUsesAndProvidesTest.c Thu Dec 22 22:07:36 2016 +0100
@@ -82,14 +82,18 @@
}
static
-jint throw_exc(JNIEnv *env, char *msg) {
+void throw_exc(JNIEnv *env, char *msg) {
jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
+ jint rt = JNI_OK;
if (exc_class == NULL) {
printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
- return -1;
+ return;
}
- return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
+ rt = JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
+ if (rt == JNI_ERR) {
+ printf("throw_exc: Error in JNI ThrowNew(env, %s)\n", msg);
+ }
}
static
--- a/hotspot/test/serviceability/jvmti/ExceptionCaughtOutOfPhase/ExceptionCaughtOutOfPhaseTest.java Wed Dec 21 22:41:18 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2016, 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.security.AccessController;
-import java.security.PrivilegedAction;
-
-/*
- * @test
- * @bug 8134434
- * @summary JVM_DoPrivileged() fires assert(_exception_caught == false) failed: _exception_caught is out of phase
- * @run main/othervm -agentlib:jdwp=transport=dt_socket,address=9000,server=y,suspend=n -Xbatch ExceptionCaughtOutOfPhaseTest
- */
-
-public class ExceptionCaughtOutOfPhaseTest {
- public static void main(String[] args) {
- PrivilegedAction action = new HotThrowingAction();
- System.out.println("### Warm-up");
- for(int i=0; i<11000; i++) {
- try {
- action.run(); // call run() to get it compiled
- } catch(Throwable t) {
- // ignored
- }
- }
-
- System.out.println("### Warm-up done");
- System.out.println("### Executing privileged action");
-
- try {
- AccessController.doPrivileged(action);
- } catch (Error e) {
- // ignored
- }
- }
-
- public static class HotThrowingAction implements PrivilegedAction {
- public Object run() {
- throw new Error();
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/sa/TestHeapDumpForInvokeDynamic.java Thu Dec 22 22:07:36 2016 +0100
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2016, 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.util.ArrayList;
+import java.util.List;
+import java.io.File;
+import java.nio.file.Files;
+import java.io.IOException;
+import java.io.BufferedInputStream;
+import java.util.stream.Collectors;
+import java.io.FileInputStream;
+
+import sun.jvm.hotspot.HotSpotAgent;
+import sun.jvm.hotspot.debugger.*;
+
+import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.Utils;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.hprof.HprofParser;
+import jdk.test.lib.hprof.parser.HprofReader;
+import jdk.test.lib.hprof.parser.PositionDataInputStream;
+import jdk.test.lib.hprof.model.Snapshot;
+
+/*
+ * @test
+ * @library /test/lib
+ * @requires os.family != "mac"
+ * @modules java.base/jdk.internal.misc
+ * jdk.hotspot.agent/sun.jvm.hotspot
+ * jdk.hotspot.agent/sun.jvm.hotspot.utilities
+ * jdk.hotspot.agent/sun.jvm.hotspot.oops
+ * jdk.hotspot.agent/sun.jvm.hotspot.debugger
+ * @run main/othervm TestHeapDumpForInvokeDynamic
+ */
+
+public class TestHeapDumpForInvokeDynamic {
+
+ private static LingeredAppWithInvokeDynamic theApp = null;
+
+ private static void verifyHeapDump(String heapFile) {
+
+ File heapDumpFile = new File(heapFile);
+ Asserts.assertTrue(heapDumpFile.exists() && heapDumpFile.isFile(),
+ "Could not create dump file " + heapDumpFile.getAbsolutePath());
+ try (PositionDataInputStream in = new PositionDataInputStream(
+ new BufferedInputStream(new FileInputStream(heapFile)))) {
+ int i = in.readInt();
+ if (HprofReader.verifyMagicNumber(i)) {
+ Snapshot sshot;
+ HprofReader r = new HprofReader(heapFile, in, 0,
+ false, 0);
+ sshot = r.read();
+ } else {
+ throw new IOException("Unrecognized magic number: " + i);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ Asserts.fail("Could not read dump file " + heapFile);
+ } finally {
+ heapDumpFile.delete();
+ }
+ }
+
+ private static void attachDumpAndVerify(String heapDumpFileName,
+ long lingeredAppPid) throws Exception {
+
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
+ launcher.addToolArg("jmap");
+ launcher.addToolArg("--binaryheap");
+ launcher.addToolArg("--dumpfile");
+ launcher.addToolArg(heapDumpFileName);
+ launcher.addToolArg("--pid");
+ launcher.addToolArg(Long.toString(lingeredAppPid));
+
+ ProcessBuilder processBuilder = new ProcessBuilder();
+ processBuilder.command(launcher.getCommand());
+ System.out.println(
+ processBuilder.command().stream().collect(Collectors.joining(" ")));
+
+ OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder);
+ SAOutput.shouldHaveExitValue(0);
+ SAOutput.shouldContain("heap written to");
+ SAOutput.shouldContain(heapDumpFileName);
+ System.out.println(SAOutput.getOutput());
+
+ verifyHeapDump(heapDumpFileName);
+ }
+
+ public static void main (String... args) throws Exception {
+
+ String heapDumpFileName = "lambdaHeapDump.bin";
+
+ if (!Platform.shouldSAAttach()) {
+ System.out.println(
+ "SA attach not expected to work - test skipped.");
+ return;
+ }
+
+ File heapDumpFile = new File(heapDumpFileName);
+ if (heapDumpFile.exists()) {
+ heapDumpFile.delete();
+ }
+
+ try {
+ List<String> vmArgs = new ArrayList<String>();
+ vmArgs.add("-XX:+UsePerfData");
+ vmArgs.addAll(Utils.getVmOptions());
+
+ theApp = new LingeredAppWithInvokeDynamic();
+ LingeredApp.startApp(vmArgs, theApp);
+ attachDumpAndVerify(heapDumpFileName, theApp.getPid());
+ } finally {
+ LingeredApp.stopApp(theApp);
+ }
+ }
+}