# HG changeset patch # User jwilhelm # Date 1482440856 -3600 # Node ID c80e97a973602e0521fed659ba56d3fe605dfb48 # Parent 24ee5092cc0b078c152c4a5f4b073af50ca301fc# Parent 83423be5b4835236f4f249e73f4839969b5b7f30 Merge diff -r 24ee5092cc0b -r c80e97a97360 hotspot/make/lib/CompileDtracePostJvm.gmk --- 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. diff -r 24ee5092cc0b -r c80e97a97360 hotspot/make/lib/CompileGtest.gmk --- 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, \ )) diff -r 24ee5092cc0b -r c80e97a97360 hotspot/make/lib/Lib-jdk.hotspot.agent.gmk --- 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) diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/aarch64/vm/aarch64.ad --- 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); %} diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp --- 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; diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/aarch64/vm/c1_MacroAssembler_aarch64.cpp --- 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); diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/aarch64/vm/c1_MacroAssembler_aarch64.hpp --- 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 diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp --- 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); diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp --- 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, diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp --- 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, diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp --- 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 { diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/arm/vm/sharedRuntime_arm.cpp --- 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 diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/ppc/vm/abstractInterpreter_ppc.cpp --- 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. diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/ppc/vm/assembler_ppc.hpp --- 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); diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp --- 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)); } diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp --- 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"); diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp --- 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) { diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/ppc/vm/globals_ppc.hpp --- 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) diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/ppc/vm/ppc.ad --- 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 diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp --- 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]; diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp --- 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(); diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp --- 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) { diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/s390/vm/assembler_s390.hpp --- 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 diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/s390/vm/assembler_s390.inline.hpp --- 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));} diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp --- 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; } } diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp --- 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) { diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/s390/vm/s390.ad --- 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 diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/s390/vm/sharedRuntime_s390.cpp --- 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; diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp --- 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); diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp --- 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). diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/s390/vm/vm_version_s390.cpp --- 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. diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- 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; diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/x86/vm/globals_x86.hpp --- 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); diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp --- 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; diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- 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 diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java --- 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())); + } } diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderDataGraph.java --- /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); + } + } + } + } + +} diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java --- 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() { diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java --- 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.*; /**
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();
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java
--- 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();
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java
--- 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
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os/aix/vm/os_aix.cpp
--- 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];
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os/aix/vm/os_aix.hpp
--- 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() {
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os/linux/vm/os_linux.cpp
--- 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);
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os/posix/vm/os_posix.cpp
--- 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());
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os/posix/vm/os_posix.hpp
--- 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;
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp
--- 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;
}
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
--- 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) {
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp
--- 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) {
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp
--- 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();
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os_cpu/linux_arm/vm/os_linux_arm.cpp
--- 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
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp
--- 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
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os_cpu/linux_s390/vm/os_linux_s390.cpp
--- 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
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp
--- 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() {
}
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp
--- 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
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
--- 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;
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp
--- 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
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
--- 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
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/share/vm/c1/c1_LIR.cpp
--- 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:
diff -r 24ee5092cc0b -r c80e97a97360 hotspot/src/share/vm/classfile/classLoader.cpp
--- 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