mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 19:44:41 +02:00
Merge
This commit is contained in:
commit
4ce0eb8df9
97 changed files with 1715 additions and 1352 deletions
|
@ -188,7 +188,6 @@ ifeq ($(call check-jvm-feature, dtrace), true)
|
|||
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 @@ ifeq ($(call check-jvm-feature, dtrace), true)
|
|||
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.
|
||||
|
|
|
@ -54,6 +54,13 @@ endif
|
|||
|
||||
# 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 @@ $(eval $(call SetupNativeCompilation, BUILD_GTEST_LIBJVM, \
|
|||
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 @@ $(eval $(call SetupNativeCompilation, BUILD_GTEST_LIBJVM, \
|
|||
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, \
|
||||
))
|
||||
|
|
|
@ -113,7 +113,6 @@ $(eval $(call SetupNativeCompilation, BUILD_LIBSA, \
|
|||
LIBS := $(SA_LIBS), \
|
||||
MAPFILE := $(SA_MAPFILE), \
|
||||
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libsa, \
|
||||
STRIP_SYMBOLS := true, \
|
||||
))
|
||||
|
||||
TARGETS += $(BUILD_LIBSA)
|
||||
|
|
|
@ -14086,7 +14086,7 @@ instruct overflowMulL_reg(rFlagsReg cr, iRegL op1, iRegL op2)
|
|||
|
||||
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 @@ instruct overflowMulL_reg(rFlagsReg cr, iRegL op1, iRegL op2)
|
|||
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 @@ instruct overflowMulL_reg_branch(cmpOp cmp, iRegL op1, iRegL op2, label labl, rF
|
|||
|
||||
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 @@ instruct overflowMulL_reg_branch(cmpOp cmp, iRegL op1, iRegL op2, label labl, rF
|
|||
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);
|
||||
%}
|
||||
|
||||
|
|
|
@ -3111,7 +3111,7 @@ void LIR_Assembler::peephole(LIR_List *lir) {
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -195,95 +195,22 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
|
|||
}
|
||||
}
|
||||
|
||||
// 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 @@ void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2,
|
|||
|
||||
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);
|
||||
|
|
|
@ -36,7 +36,6 @@ using MacroAssembler::null_check;
|
|||
// initialization
|
||||
void pd_init() { _rsp_offset = 0; }
|
||||
|
||||
void zero_memory(Register addr, Register len, Register t1);
|
||||
|
||||
public:
|
||||
void try_allocate(
|
||||
|
@ -75,7 +74,8 @@ void zero_memory(Register addr, Register len, Register t1);
|
|||
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
|
||||
|
|
|
@ -728,7 +728,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
|
|||
|
||||
__ 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 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
|
|||
__ 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 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
|
|||
__ 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);
|
||||
|
|
|
@ -3944,12 +3944,82 @@ Register MacroAssembler::tlab_refill(Label& retry,
|
|||
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,
|
||||
|
|
|
@ -857,6 +857,7 @@ public:
|
|||
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,
|
||||
|
|
|
@ -282,7 +282,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
|||
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 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
|||
}
|
||||
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 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
|||
}
|
||||
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 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
|||
}
|
||||
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 {
|
||||
|
|
|
@ -453,7 +453,7 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
|||
}
|
||||
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 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
|||
}
|
||||
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 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
|||
#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
|
||||
|
|
|
@ -51,19 +51,25 @@ int AbstractInterpreter::BasicType_as_index(BasicType type) {
|
|||
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.
|
||||
|
|
|
@ -460,16 +460,15 @@ class Assembler : public AbstractAssembler {
|
|||
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 @@ class Assembler : public AbstractAssembler {
|
|||
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);
|
||||
|
|
|
@ -700,6 +700,26 @@ inline void Assembler::fdiv_( FloatRegister d, FloatRegister a, FloatRegister b)
|
|||
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)); }
|
||||
|
|
|
@ -292,28 +292,28 @@ void LIR_Assembler::klass2reg_with_patching(Register reg, CodeEmitInfo *info) {
|
|||
}
|
||||
|
||||
|
||||
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 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
|
|||
}
|
||||
__ 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 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
|
|||
}
|
||||
|
||||
} else if (divisor == -1) {
|
||||
if (op->code() == lir_idiv) {
|
||||
if (code == lir_idiv) {
|
||||
__ neg(Rresult, Rdividend);
|
||||
} else {
|
||||
__ li(Rresult, 0);
|
||||
|
@ -360,7 +360,7 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
|
|||
|
||||
} 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 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
|
|||
__ 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) {
|
|||
}
|
||||
|
||||
|
||||
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");
|
||||
|
|
|
@ -1435,7 +1435,26 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -42,6 +42,9 @@ define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs pas
|
|||
|
||||
#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)
|
||||
|
||||
|
|
|
@ -9569,6 +9569,117 @@ instruct roundFloat_nop(regF dst) %{
|
|||
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
|
||||
|
|
|
@ -594,7 +594,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
|||
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 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
|||
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 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
|||
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];
|
||||
|
|
|
@ -1134,14 +1134,57 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call, Regist
|
|||
// 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 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
|
|||
#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();
|
||||
|
|
|
@ -230,9 +230,8 @@ void VM_Version::initialize() {
|
|||
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) {
|
||||
|
|
|
@ -790,6 +790,16 @@ class Assembler : public AbstractAssembler {
|
|||
#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 @@ class Assembler : public AbstractAssembler {
|
|||
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
|
||||
|
|
|
@ -777,6 +777,23 @@ inline void Assembler::z_meeb( FloatRegister r1, const Address& a)
|
|||
inline void Assembler::z_mdb( FloatRegister r1, const Address& a) { z_mdb( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); }
|
||||
|
||||
|
||||
//---------------
|
||||
// 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
|
||||
//---------------
|
||||
|
|
|
@ -324,6 +324,22 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1237,7 +1237,28 @@ void LIRGenerator::do_update_CRC32C(Intrinsic* x) {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -7249,6 +7249,171 @@ instruct mulD_reg_mem(regD dst, memoryRX src)%{
|
|||
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
|
||||
|
|
|
@ -683,7 +683,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
|||
}
|
||||
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 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
|||
}
|
||||
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 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
|||
}
|
||||
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;
|
||||
|
|
|
@ -2038,15 +2038,15 @@ class StubGenerator: public StubCodeGenerator {
|
|||
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);
|
||||
__ z_llgfr(srclen, msglen); // We pass the offsets as ints, not as longs as required.
|
||||
|
||||
__ kmc(dst, src); // Decipher the message.
|
||||
__ 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);
|
||||
|
|
|
@ -1297,36 +1297,96 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
|||
// 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.
|
||||
// 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;
|
||||
|
||||
// Only support absolute value and square root.
|
||||
if (kind != Interpreter::java_lang_math_abs && kind != Interpreter::java_lang_math_sqrt) {
|
||||
return NULL;
|
||||
// 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.
|
||||
}
|
||||
|
||||
BLOCK_COMMENT("math_entry {");
|
||||
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();
|
||||
}
|
||||
|
||||
address math_entry = __ pc();
|
||||
// Use normal entry if neither instruction nor runtime call is used.
|
||||
if (!use_instruction && runtime_entry == NULL) return NULL;
|
||||
|
||||
if (kind == Interpreter::java_lang_math_abs) {
|
||||
// Load operand from stack.
|
||||
__ mem2freg_opt(Z_FRET, Address(Z_esp, Interpreter::stackElementSize));
|
||||
__ z_lpdbr(Z_FRET);
|
||||
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).
|
||||
|
|
|
@ -155,9 +155,8 @@ void VM_Version::initialize() {
|
|||
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.
|
||||
|
|
|
@ -425,7 +425,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
|||
|
||||
#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 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
|||
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 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
|||
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 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
|||
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 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
|||
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 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
|||
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;
|
||||
|
|
|
@ -63,9 +63,10 @@ define_pd_global(intx, InlineSmallCode, 1000);
|
|||
#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 @@ define_pd_global(intx, InlineSmallCode, 1000);
|
|||
#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);
|
||||
|
|
|
@ -478,12 +478,12 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
|||
}
|
||||
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 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
|||
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;
|
||||
|
|
|
@ -474,7 +474,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
|||
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 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
|||
}
|
||||
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 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
|||
}
|
||||
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 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
|||
}
|
||||
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
|
||||
|
|
|
@ -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 @@ public class ClassLoaderData extends VMObject {
|
|||
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 class ClassLoaderData extends VMObject {
|
|||
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()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -61,6 +61,7 @@ public class Klass extends Metadata implements ClassConstants {
|
|||
}
|
||||
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 @@ public class Klass extends Metadata implements ClassConstants {
|
|||
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 class Klass extends Metadata implements ClassConstants {
|
|||
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() {
|
||||
|
|
|
@ -38,6 +38,7 @@ import sun.jvm.hotspot.oops.*;
|
|||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.classfile.*;
|
||||
|
||||
/** <P> This class encapsulates the global state of the VM; the
|
||||
universe, object heap, interpreter, etc. It is a Singleton and
|
||||
|
@ -80,6 +81,7 @@ public class VM {
|
|||
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 @@ public class VM {
|
|||
return dict;
|
||||
}
|
||||
|
||||
public ClassLoaderDataGraph getClassLoaderDataGraph() {
|
||||
if (cldGraph == null) {
|
||||
cldGraph = new ClassLoaderDataGraph();
|
||||
}
|
||||
return cldGraph;
|
||||
}
|
||||
|
||||
public Threads getThreads() {
|
||||
if (threads == null) {
|
||||
threads = new Threads();
|
||||
|
|
|
@ -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.debugger.*;
|
|||
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 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
|||
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 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
|||
|
||||
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 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
|||
}
|
||||
}
|
||||
});
|
||||
// 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 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
|||
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 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
|||
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();
|
||||
|
|
|
@ -53,6 +53,7 @@ import org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub;
|
|||
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 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen
|
|||
/**
|
||||
* 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
|
||||
|
|
|
@ -848,13 +848,13 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
|
|||
|
||||
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 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
|
|||
|
||||
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 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
|
|||
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 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
|
|||
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 @@ bool os::Aix::chained_handler(int sig, siginfo_t* siginfo, void* context) {
|
|||
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];
|
||||
|
|
|
@ -140,6 +140,9 @@ class Aix {
|
|||
// 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() {
|
||||
|
|
|
@ -716,11 +716,18 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
|
|||
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 @@ static bool find_vma(address addr, address* vma_low, address* vma_high) {
|
|||
|
||||
// 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 @@ void os::Linux::capture_initial_stack(size_t max_size) {
|
|||
// 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 @@ void os::Linux::capture_initial_stack(size_t max_size) {
|
|||
// 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 @@ bool os::Linux::libnuma_init() {
|
|||
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 @@ bool os::start_debugging(char *buf, int buflen) {
|
|||
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);
|
||||
|
|
|
@ -1096,6 +1096,8 @@ char* os::Posix::describe_pthread_attr(char* buf, size_t buflen, const pthread_a
|
|||
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 @@ char* os::Posix::describe_pthread_attr(char* buf, size_t buflen, const pthread_a
|
|||
|
||||
// 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 @@ jint os::Posix::set_minimum_stack_sizes() {
|
|||
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());
|
||||
|
||||
|
|
|
@ -43,7 +43,11 @@ protected:
|
|||
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;
|
||||
|
|
|
@ -535,13 +535,15 @@ void os::Aix::init_thread_fpu_state(void) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
||||
|
|
|
@ -839,19 +839,20 @@ bool os::is_allocatable(size_t bytes) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
|
|||
//
|
||||
// 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 @@ static void current_stack_region(address * bottom, size_t * size) {
|
|||
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 @@ static void current_stack_region(address * bottom, size_t * size) {
|
|||
|
||||
// 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) {
|
||||
|
|
|
@ -310,7 +310,7 @@ static void current_stack_region(address *bottom, size_t *size) {
|
|||
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 @@ static void current_stack_region(address *bottom, size_t *size) {
|
|||
|
||||
// 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) {
|
||||
|
|
|
@ -473,8 +473,10 @@ bool os::is_allocatable(size_t bytes) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
|
|||
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 @@ void os::print_context(outputStream *st, const void *context) {
|
|||
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();
|
||||
|
||||
|
|
|
@ -526,8 +526,10 @@ bool os::is_allocatable(size_t bytes) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
|
|||
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
|
||||
|
||||
|
|
|
@ -535,100 +535,19 @@ void os::Linux::set_fpu_control_word(int fpu_control) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
|
||||
|
|
|
@ -473,103 +473,19 @@ void os::Linux::set_fpu_control_word(int fpu_control) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
|
||||
|
|
|
@ -156,51 +156,6 @@ address os::current_stack_pointer() {
|
|||
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 @@ bool os::is_allocatable(size_t bytes) {
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
|
|||
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() {
|
||||
}
|
||||
|
|
|
@ -677,15 +677,15 @@ bool os::is_allocatable(size_t bytes) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
|
|||
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
|
||||
|
||||
|
|
|
@ -320,12 +320,6 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
|
|||
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 @@ static void current_stack_region(address *bottom, size_t *size) {
|
|||
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 @@ static void current_stack_region(address *bottom, size_t *size) {
|
|||
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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
#ifdef AMD64
|
||||
size_t os::Posix::_compiler_thread_min_stack_allowed = 394 * K;
|
||||
size_t os::Posix::_java_thread_min_stack_allowed = 224 * K;
|
||||
// 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
|
||||
#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
|
||||
|
|
|
@ -677,9 +677,7 @@ void LIR_OpVisitState::visit(LIR_Op* op) {
|
|||
|
||||
// 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 @@ void LIR_OpVisitState::visit(LIR_Op* op) {
|
|||
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:
|
||||
|
|
|
@ -84,7 +84,6 @@ typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned ch
|
|||
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 GetNextEntry_t GetNextEntry = NULL;
|
|||
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 @@ int ClassLoader::_num_entries = 0;
|
|||
GrowableArray<char*>* ClassLoader::_boot_modules_array = NULL;
|
||||
GrowableArray<char*>* ClassLoader::_platform_modules_array = NULL;
|
||||
SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
|
||||
int ClassLoader::_num_patch_mod_prefixes = 0;
|
||||
#endif
|
||||
|
||||
// helper routines
|
||||
|
@ -320,20 +317,6 @@ ClassPathZipEntry::~ClassPathZipEntry() {
|
|||
FREE_C_HEAP_ARRAY(char, _zip_name);
|
||||
}
|
||||
|
||||
bool ClassPathZipEntry::stream_exists(const char* name) {
|
||||
// enable call to C land
|
||||
JavaThread* thread = JavaThread::current();
|
||||
ThreadToNativeFromVM ttn(thread);
|
||||
// check whether zip archive contains name
|
||||
jint name_len, filesize;
|
||||
jzentry* entry = (*FindEntry)(_zip, name, &filesize, &name_len);
|
||||
if (entry != NULL) {
|
||||
(*FreeEntry)(_zip, entry);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
u1* ClassPathZipEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) {
|
||||
// enable call to C land
|
||||
JavaThread* thread = JavaThread::current();
|
||||
|
@ -1090,7 +1073,6 @@ void ClassLoader::load_zip_library() {
|
|||
GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry"));
|
||||
ZipInflateFully = CAST_TO_FN_PTR(ZipInflateFully_t, os::dll_lookup(handle, "ZIP_InflateFully"));
|
||||
Crc32 = CAST_TO_FN_PTR(Crc32_t, os::dll_lookup(handle, "ZIP_CRC32"));
|
||||
FreeEntry = CAST_TO_FN_PTR(FreeEntry_t, os::dll_lookup(handle, "ZIP_FreeEntry"));
|
||||
|
||||
// ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL
|
||||
if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL ||
|
||||
|
@ -1418,57 +1400,6 @@ ClassFileStream* ClassLoader::search_module_entries(const GrowableArray<ModuleCl
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS
|
||||
// The following function is only used during CDS dump time.
|
||||
// It checks if a class can be found in the jar entries of the _patch_mod_entries.
|
||||
// It does not support non-jar entries.
|
||||
bool ClassLoader::is_in_patch_module(const char* const file_name) {
|
||||
assert(DumpSharedSpaces, "dump time only");
|
||||
if (_patch_mod_entries == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int num_of_entries = _patch_mod_entries->length();
|
||||
char* class_module_name = NULL;
|
||||
ResourceMark rm;
|
||||
const char *pkg_name = package_from_name(file_name);
|
||||
// Using the jimage to obtain the class' module name.
|
||||
// The ModuleEntryTable cannot be used at this point during dump time
|
||||
// because the module system hasn't been initialized yet.
|
||||
if (pkg_name != NULL) {
|
||||
JImageFile *jimage = _jrt_entry->jimage();
|
||||
class_module_name = (char*)(*JImagePackageToModule)(jimage, pkg_name);
|
||||
}
|
||||
|
||||
if (class_module_name == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Loop through all the patch module entries looking for module
|
||||
for (int i = 0; i < num_of_entries; i++) {
|
||||
ModuleClassPathList* module_cpl = _patch_mod_entries->at(i);
|
||||
Symbol* module_cpl_name = module_cpl->module_name();
|
||||
|
||||
if (strcmp(module_cpl_name->as_C_string(), class_module_name) == 0) {
|
||||
// Class' module has been located, attempt to locate
|
||||
// the class from the module's ClassPathEntry list.
|
||||
ClassPathEntry* e = module_cpl->module_first_entry();
|
||||
while (e != NULL) {
|
||||
if (e->is_jar_file()) {
|
||||
if (e->stream_exists(file_name)) {
|
||||
return true;
|
||||
} else {
|
||||
e = e->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif // INCLUDE_CDS
|
||||
|
||||
instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS) {
|
||||
assert(name != NULL, "invariant");
|
||||
assert(THREAD->is_Java_thread(), "must be a JavaThread");
|
||||
|
@ -1494,8 +1425,6 @@ instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_onl
|
|||
|
||||
// If DumpSharedSpaces is true boot loader visibility boundaries are set to:
|
||||
// - [jimage] + [_first_append_entry to _last_append_entry] (all path entries).
|
||||
// If a class is found in the --patch-module entries, the class will not be included in the
|
||||
// CDS archive. Also, CDS is not supported if exploded module builds are used.
|
||||
//
|
||||
// If search_append_only is true, boot loader visibility boundaries are
|
||||
// set to be _first_append_entry to the end. This includes:
|
||||
|
@ -1519,15 +1448,13 @@ instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_onl
|
|||
// Note: The --patch-module entries are never searched if the boot loader's
|
||||
// visibility boundary is limited to only searching the append entries.
|
||||
if (_patch_mod_entries != NULL && !search_append_only) {
|
||||
// At CDS dump time, the --patch-module entries are ignored. That means a
|
||||
// class is still loaded from the runtime image even if it might
|
||||
// appear in the _patch_mod_entries. The runtime shared class visibility
|
||||
// check will determine if a shared class is visible based on the runtime
|
||||
// environemnt, including the runtime --patch-module setting.
|
||||
if (!DumpSharedSpaces) {
|
||||
stream = search_module_entries(_patch_mod_entries, class_name, file_name, CHECK_NULL);
|
||||
} else {
|
||||
#if INCLUDE_CDS
|
||||
if (is_in_patch_module(file_name)) {
|
||||
tty->print_cr("Preload Warning: Skip archiving class %s found in --patch-module entry", class_name);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1679,57 +1606,8 @@ void ClassLoader::initialize() {
|
|||
}
|
||||
|
||||
#if INCLUDE_CDS
|
||||
// Capture all the --patch-module entries specified during CDS dump time.
|
||||
// It also captures the non-existing path(s) and the required file(s) during inspecting
|
||||
// the entries.
|
||||
void ClassLoader::setup_patch_mod_path() {
|
||||
assert(DumpSharedSpaces, "only used with -Xshare:dump");
|
||||
ResourceMark rm;
|
||||
GrowableArray<ModulePatchPath*>* patch_mod_args = Arguments::get_patch_mod_prefix();
|
||||
if (patch_mod_args != NULL) {
|
||||
int num_of_entries = patch_mod_args->length();
|
||||
for (int i = 0; i < num_of_entries; i++) {
|
||||
const char* module_name = (patch_mod_args->at(i))->module_name();
|
||||
const char* module_path = (patch_mod_args->at(i))->path_string();
|
||||
int path_len = (int)strlen(module_path);
|
||||
int name_len = (int)strlen(module_name);
|
||||
int buf_len = name_len + path_len + 2; // add 2 for the '=' and NULL terminator
|
||||
int end = 0;
|
||||
char* buf = NEW_C_HEAP_ARRAY(char, buf_len, mtInternal);
|
||||
// Iterate over the module's class path entries
|
||||
for (int start = 0; start < path_len; start = end) {
|
||||
while (module_path[end] && module_path[end] != os::path_separator()[0]) {
|
||||
end++;
|
||||
}
|
||||
strncpy(buf, &module_path[start], end - start);
|
||||
buf[end - start] = '\0';
|
||||
struct stat st;
|
||||
if (os::stat(buf, &st) != 0) {
|
||||
// File not found
|
||||
_shared_paths_misc_info->add_nonexist_path(buf);
|
||||
} else {
|
||||
if ((st.st_mode & S_IFMT) != S_IFREG) { // is not a regular file
|
||||
vm_exit_during_initialization(
|
||||
"--patch-module requires a regular file during dumping", buf);
|
||||
} else {
|
||||
_shared_paths_misc_info->add_required_file(buf);
|
||||
}
|
||||
}
|
||||
while (module_path[end] == os::path_separator()[0]) {
|
||||
end++;
|
||||
}
|
||||
};
|
||||
jio_snprintf(buf, buf_len, "%s=%s", module_name, module_path);
|
||||
_shared_paths_misc_info->add_patch_mod_classpath((const char*)buf);
|
||||
_num_patch_mod_prefixes++;
|
||||
FREE_C_HEAP_ARRAY(char, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLoader::initialize_shared_path() {
|
||||
if (DumpSharedSpaces) {
|
||||
setup_patch_mod_path();
|
||||
ClassLoaderExt::setup_search_paths();
|
||||
_shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check()
|
||||
}
|
||||
|
|
|
@ -69,7 +69,6 @@ public:
|
|||
// Attempt to locate file_name through this class path entry.
|
||||
// Returns a class file parsing stream if successfull.
|
||||
virtual ClassFileStream* open_stream(const char* name, TRAPS) = 0;
|
||||
virtual bool stream_exists(const char* name) = 0;
|
||||
// Debugging
|
||||
NOT_PRODUCT(virtual void compile_the_world(Handle loader, TRAPS) = 0;)
|
||||
};
|
||||
|
@ -84,7 +83,6 @@ class ClassPathDirEntry: public ClassPathEntry {
|
|||
JImageFile* jimage() const { return NULL; }
|
||||
ClassPathDirEntry(const char* dir);
|
||||
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||
bool stream_exists(const char* name) { return false; }
|
||||
// Debugging
|
||||
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
|
||||
};
|
||||
|
@ -128,7 +126,6 @@ class ClassPathZipEntry: public ClassPathEntry {
|
|||
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||
void contents_do(void f(const char* name, void* context), void* context);
|
||||
bool is_multiple_versioned(TRAPS) NOT_CDS_RETURN_(false);
|
||||
bool stream_exists(const char* name);
|
||||
// Debugging
|
||||
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
|
||||
};
|
||||
|
@ -148,7 +145,6 @@ public:
|
|||
ClassPathImageEntry(JImageFile* jimage, const char* name);
|
||||
~ClassPathImageEntry();
|
||||
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||
bool stream_exists(const char* name) { return false; }
|
||||
|
||||
// Debugging
|
||||
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
|
||||
|
@ -259,7 +255,6 @@ class ClassLoader: AllStatic {
|
|||
|
||||
// Info used by CDS
|
||||
CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;)
|
||||
CDS_ONLY(static int _num_patch_mod_prefixes;)
|
||||
|
||||
// Initialization:
|
||||
// - setup the boot loader's system class path
|
||||
|
@ -434,9 +429,6 @@ class ClassLoader: AllStatic {
|
|||
static void initialize_module_loader_map(JImageFile* jimage);
|
||||
static s2 classloader_type(Symbol* class_name, ClassPathEntry* e,
|
||||
int classpath_index, TRAPS);
|
||||
static bool is_in_patch_module(const char* const file_name);
|
||||
static void setup_patch_mod_path(); // Only when -Xshare:dump
|
||||
static int num_patch_mod_prefixes() { return _num_patch_mod_prefixes; }
|
||||
#endif
|
||||
|
||||
static void trace_class_path(const char* msg, const char* name = NULL);
|
||||
|
|
|
@ -108,6 +108,18 @@ bool ModuleEntry::can_read(ModuleEntry* m) const {
|
|||
}
|
||||
|
||||
MutexLocker m1(Module_lock);
|
||||
// This is a guard against possible race between agent threads that redefine
|
||||
// or retransform classes in this module. Only one of them is adding the
|
||||
// default read edges to the unnamed modules of the boot and app class loaders
|
||||
// with an upcall to jdk.internal.module.Modules.transformedByAgent.
|
||||
// At the same time, another thread can instrument the module classes by
|
||||
// injecting dependencies that require the default read edges for resolution.
|
||||
if (this->has_default_read_edges() && !m->is_named()) {
|
||||
ClassLoaderData* cld = m->loader_data();
|
||||
if (cld->is_the_null_class_loader_data() || cld->is_system_class_loader_data()) {
|
||||
return true; // default read edge
|
||||
}
|
||||
}
|
||||
if (!has_reads()) {
|
||||
return false;
|
||||
} else {
|
||||
|
|
|
@ -86,9 +86,6 @@ void SharedPathsMiscInfo::print_path(int type, const char* path) {
|
|||
case REQUIRED:
|
||||
out->print("Expecting that file %s must exist and is not altered", path);
|
||||
break;
|
||||
case PATCH_MOD:
|
||||
out->print("Expecting --patch-module=%s", path);
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
@ -167,26 +164,6 @@ bool SharedPathsMiscInfo::check(jint type, const char* path) {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case PATCH_MOD:
|
||||
{
|
||||
GrowableArray<ModulePatchPath*>* patch_mod_args = Arguments::get_patch_mod_prefix();
|
||||
if (patch_mod_args != NULL) {
|
||||
int num_of_entries = patch_mod_args->length();
|
||||
for (int i = 0; i < num_of_entries; i++) {
|
||||
const char* module_name = (patch_mod_args->at(i))->module_name();
|
||||
const char* path_string = (patch_mod_args->at(i))->path_string();
|
||||
size_t n = strlen(module_name);
|
||||
// path contains the module name, followed by '=', and one or more entries.
|
||||
// E.g.: "java.base=foo" or "java.naming=dir1:dir2:dir3"
|
||||
if ((strncmp(module_name, path, n) != 0) ||
|
||||
(path[n] != '=') ||
|
||||
(strcmp(path + n + 1, path_string) != 0)) {
|
||||
return fail("--patch-module mismatch, path not found in run time: ", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return fail("Corrupted archive file header");
|
||||
}
|
||||
|
|
|
@ -104,28 +104,10 @@ public:
|
|||
add_path(path, NON_EXIST);
|
||||
}
|
||||
|
||||
// The path must exist and have required size and modification time
|
||||
void add_required_file(const char* path) {
|
||||
add_path(path, REQUIRED);
|
||||
|
||||
struct stat st;
|
||||
if (os::stat(path, &st) != 0) {
|
||||
assert(0, "sanity");
|
||||
#if INCLUDE_CDS
|
||||
ClassLoader::exit_with_path_failure("failed to os::stat(%s)", path); // should not happen
|
||||
#endif
|
||||
}
|
||||
write_time(st.st_mtime);
|
||||
write_long(st.st_size);
|
||||
}
|
||||
|
||||
// The path must exist, and must contain exactly <num_entries> files/dirs
|
||||
void add_boot_classpath(const char* path) {
|
||||
add_path(path, BOOT);
|
||||
}
|
||||
void add_patch_mod_classpath(const char* path) {
|
||||
add_path(path, PATCH_MOD);
|
||||
}
|
||||
int write_jint(jint num) {
|
||||
write(&num, sizeof(num));
|
||||
return 0;
|
||||
|
@ -147,8 +129,7 @@ public:
|
|||
enum {
|
||||
BOOT = 1,
|
||||
NON_EXIST = 2,
|
||||
REQUIRED = 3,
|
||||
PATCH_MOD = 4
|
||||
REQUIRED = 3
|
||||
};
|
||||
|
||||
virtual const char* type_name(int type) {
|
||||
|
@ -156,7 +137,6 @@ public:
|
|||
case BOOT: return "BOOT";
|
||||
case NON_EXIST: return "NON_EXIST";
|
||||
case REQUIRED: return "REQUIRED";
|
||||
case PATCH_MOD: return "PATCH_MOD";
|
||||
default: ShouldNotReachHere(); return "?";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1231,6 +1231,8 @@ instanceKlassHandle SystemDictionary::load_shared_class(
|
|||
bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
|
||||
instanceKlassHandle ik,
|
||||
Handle class_loader, TRAPS) {
|
||||
assert(!ModuleEntryTable::javabase_moduleEntry()->is_patched(),
|
||||
"Cannot use sharing if java.base is patched");
|
||||
ResourceMark rm;
|
||||
int path_index = ik->shared_classpath_index();
|
||||
SharedClassPathEntry* ent =
|
||||
|
@ -1258,6 +1260,12 @@ bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
|
|||
}
|
||||
}
|
||||
|
||||
// If the archived class is from a module that has been patched at runtime,
|
||||
// the class cannot be loaded from the archive.
|
||||
if (mod_entry != NULL && mod_entry->is_patched()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (class_loader.is_null()) {
|
||||
assert(ent != NULL, "Shared class for NULL classloader must have valid SharedClassPathEntry");
|
||||
// The NULL classloader can load archived class originated from the
|
||||
|
|
|
@ -299,10 +299,6 @@ class AbstractInterpreter: AllStatic {
|
|||
}
|
||||
|
||||
static void initialize_method_handle_entries();
|
||||
|
||||
// PPC-only: Support abs and sqrt like in compiler.
|
||||
// For others we can use a normal (native) entry.
|
||||
static bool math_entry_available(MethodKind kind);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -57,6 +57,8 @@ void CppInterpreterGenerator::generate_all() {
|
|||
method_entry(java_lang_math_log10 );
|
||||
method_entry(java_lang_math_pow );
|
||||
method_entry(java_lang_math_exp );
|
||||
method_entry(java_lang_math_fmaD );
|
||||
method_entry(java_lang_math_fmaF );
|
||||
method_entry(java_lang_ref_reference_get);
|
||||
|
||||
AbstractInterpreter::initialize_method_handle_entries();
|
||||
|
@ -95,7 +97,9 @@ address CppInterpreterGenerator::generate_method_entry(
|
|||
case Interpreter::java_lang_math_log10 : // fall thru
|
||||
case Interpreter::java_lang_math_sqrt : // fall thru
|
||||
case Interpreter::java_lang_math_pow : // fall thru
|
||||
case Interpreter::java_lang_math_exp : entry_point = generate_math_entry(kind); break;
|
||||
case Interpreter::java_lang_math_exp : // fall thru
|
||||
case Interpreter::java_lang_math_fmaD : // fall thru
|
||||
case Interpreter::java_lang_math_fmaF : entry_point = generate_math_entry(kind); break;
|
||||
case Interpreter::java_lang_ref_reference_get
|
||||
: entry_point = generate_Reference_get_entry(); break;
|
||||
default:
|
||||
|
|
|
@ -426,15 +426,16 @@ void Rewriter::scan_method(Method* method, bool reverse, bool* invokespecial_err
|
|||
Symbol* field_sig = cp->signature_ref_at(bc_index);
|
||||
|
||||
fieldDescriptor fd;
|
||||
klass->find_field(field_name, field_sig, &fd);
|
||||
if (fd.access_flags().is_final()) {
|
||||
if (fd.access_flags().is_static()) {
|
||||
if (!method->is_static_initializer()) {
|
||||
fd.set_has_initialized_final_update(true);
|
||||
}
|
||||
} else {
|
||||
if (!method->is_object_initializer()) {
|
||||
fd.set_has_initialized_final_update(true);
|
||||
if (klass->find_field(field_name, field_sig, &fd) != NULL) {
|
||||
if (fd.access_flags().is_final()) {
|
||||
if (fd.access_flags().is_static()) {
|
||||
if (!method->is_static_initializer()) {
|
||||
fd.set_has_initialized_final_update(true);
|
||||
}
|
||||
} else {
|
||||
if (!method->is_object_initializer()) {
|
||||
fd.set_has_initialized_final_update(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,17 @@
|
|||
#include "memory/allocation.inline.hpp"
|
||||
|
||||
static bool initialized;
|
||||
static char stdoutmem[sizeof(LogStdoutOutput)];
|
||||
static char stderrmem[sizeof(LogStderrOutput)];
|
||||
static union {
|
||||
char stdoutmem[sizeof(LogStdoutOutput)];
|
||||
jlong dummy;
|
||||
} aligned_stdoutmem;
|
||||
static union {
|
||||
char stderrmem[sizeof(LogStderrOutput)];
|
||||
jlong dummy;
|
||||
} aligned_stderrmem;
|
||||
|
||||
LogStdoutOutput &StdoutLog = reinterpret_cast<LogStdoutOutput&>(stdoutmem);
|
||||
LogStderrOutput &StderrLog = reinterpret_cast<LogStderrOutput&>(stderrmem);
|
||||
LogStdoutOutput &StdoutLog = reinterpret_cast<LogStdoutOutput&>(aligned_stdoutmem.stdoutmem);
|
||||
LogStderrOutput &StderrLog = reinterpret_cast<LogStderrOutput&>(aligned_stderrmem.stderrmem);
|
||||
|
||||
LogFileStreamInitializer::LogFileStreamInitializer() {
|
||||
if (!initialized) {
|
||||
|
|
|
@ -179,7 +179,6 @@ void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment
|
|||
_classpath_entry_table_size = mapinfo->_classpath_entry_table_size;
|
||||
_classpath_entry_table = mapinfo->_classpath_entry_table;
|
||||
_classpath_entry_size = mapinfo->_classpath_entry_size;
|
||||
_num_patch_mod_prefixes = ClassLoader::num_patch_mod_prefixes();
|
||||
|
||||
// The following fields are for sanity checks for whether this archive
|
||||
// will function correctly with this JVM and the bootclasspath it's
|
||||
|
@ -948,23 +947,6 @@ bool FileMapInfo::FileMapHeader::validate() {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Check if there is a mismatch in --patch-module entry counts between dump time and run time.
|
||||
// More checks will be performed on individual --patch-module entry in the
|
||||
// SharedPathsMiscInfo::check() function.
|
||||
GrowableArray<ModulePatchPath*>* patch_mod_args = Arguments::get_patch_mod_prefix();
|
||||
if (patch_mod_args != NULL) {
|
||||
if (_num_patch_mod_prefixes == 0) {
|
||||
FileMapInfo::fail_stop("--patch-module found in run time but none was specified in dump time");
|
||||
}
|
||||
if (patch_mod_args->length() != _num_patch_mod_prefixes) {
|
||||
FileMapInfo::fail_stop("mismatched --patch-module entry counts between dump time and run time");
|
||||
}
|
||||
} else {
|
||||
if (_num_patch_mod_prefixes > 0) {
|
||||
FileMapInfo::fail_stop("--patch-module specified in dump time but none was specified in run time");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -155,7 +155,6 @@ public:
|
|||
// loading failures during runtime.
|
||||
int _classpath_entry_table_size;
|
||||
size_t _classpath_entry_size;
|
||||
int _num_patch_mod_prefixes; // number of --patch-module entries
|
||||
SharedClassPathEntry* _classpath_entry_table;
|
||||
|
||||
char* region_addr(int idx);
|
||||
|
|
|
@ -59,7 +59,6 @@
|
|||
#include "opto/mulnode.hpp"
|
||||
#include "opto/runtime.hpp"
|
||||
#include "opto/subnode.hpp"
|
||||
#include "prims/jvmtiThreadState.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/fprofiler.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
|
@ -1458,11 +1457,6 @@ address OptoRuntime::rethrow_C(oopDesc* exception, JavaThread* thread, address r
|
|||
}
|
||||
#endif
|
||||
|
||||
JvmtiThreadState *state = thread->jvmti_thread_state();
|
||||
if (state != NULL) {
|
||||
state->set_exception_detected();
|
||||
}
|
||||
|
||||
thread->set_vm_result(exception);
|
||||
// Frame not compiled (handles deoptimization blob)
|
||||
return SharedRuntime::raw_exception_handler_for_return_address(thread, ret_pc);
|
||||
|
|
|
@ -130,15 +130,15 @@ class JvmtiEventMark : public StackObj {
|
|||
private:
|
||||
JavaThread *_thread;
|
||||
JNIEnv* _jni_env;
|
||||
bool _exception_detected;
|
||||
bool _exception_caught;
|
||||
JvmtiThreadState::ExceptionState _saved_exception_state;
|
||||
#if 0
|
||||
JNIHandleBlock* _hblock;
|
||||
#endif
|
||||
|
||||
public:
|
||||
JvmtiEventMark(JavaThread *thread) : _thread(thread),
|
||||
_jni_env(thread->jni_environment()) {
|
||||
_jni_env(thread->jni_environment()),
|
||||
_saved_exception_state(JvmtiThreadState::ES_CLEARED) {
|
||||
#if 0
|
||||
_hblock = thread->active_handles();
|
||||
_hblock->clear_thoroughly(); // so we can be safe
|
||||
|
@ -149,11 +149,7 @@ public:
|
|||
// we are before an event.
|
||||
// Save current jvmti thread exception state.
|
||||
if (state != NULL) {
|
||||
_exception_detected = state->is_exception_detected();
|
||||
_exception_caught = state->is_exception_caught();
|
||||
} else {
|
||||
_exception_detected = false;
|
||||
_exception_caught = false;
|
||||
_saved_exception_state = state->get_exception_state();
|
||||
}
|
||||
|
||||
JNIHandleBlock* old_handles = thread->active_handles();
|
||||
|
@ -186,12 +182,7 @@ public:
|
|||
// we are continuing after an event.
|
||||
if (state != NULL) {
|
||||
// Restore the jvmti thread exception state.
|
||||
if (_exception_detected) {
|
||||
state->set_exception_detected();
|
||||
}
|
||||
if (_exception_caught) {
|
||||
state->set_exception_caught();
|
||||
}
|
||||
state->restore_exception_state(_saved_exception_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1552,7 +1543,6 @@ void JvmtiExport::post_single_step(JavaThread *thread, Method* method, address l
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void JvmtiExport::post_exception_throw(JavaThread *thread, Method* method, address location, oop exception) {
|
||||
HandleMark hm(thread);
|
||||
methodHandle mh(thread, method);
|
||||
|
@ -2454,7 +2444,7 @@ void JvmtiExport::clear_detected_exception(JavaThread* thread) {
|
|||
|
||||
JvmtiThreadState* state = thread->jvmti_thread_state();
|
||||
if (state != NULL) {
|
||||
state->clear_exception_detected();
|
||||
state->clear_exception_state();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,7 @@ JvmtiThreadState::JvmtiThreadState(JavaThread* thread)
|
|||
: _thread_event_enable() {
|
||||
assert(JvmtiThreadState_lock->is_locked(), "sanity check");
|
||||
_thread = thread;
|
||||
_exception_detected = false;
|
||||
_exception_caught = false;
|
||||
_exception_state = ES_CLEARED;
|
||||
_debuggable = true;
|
||||
_hide_single_stepping = false;
|
||||
_hide_level = 0;
|
||||
|
@ -310,7 +309,7 @@ void JvmtiThreadState::process_pending_step_for_popframe() {
|
|||
// an exception.
|
||||
//
|
||||
if (is_exception_detected()) {
|
||||
clear_exception_detected();
|
||||
clear_exception_state();
|
||||
}
|
||||
// If step is pending for popframe then it may not be
|
||||
// a repeat step. The new_bci and method_id is same as current_bci
|
||||
|
@ -385,7 +384,7 @@ void JvmtiThreadState::process_pending_step_for_earlyret() {
|
|||
// an exception.
|
||||
//
|
||||
if (is_exception_detected()) {
|
||||
clear_exception_detected();
|
||||
clear_exception_state();
|
||||
}
|
||||
// If step is pending for earlyret then it may not be a repeat step.
|
||||
// The new_bci and method_id is same as current_bci and current
|
||||
|
|
|
@ -76,13 +76,21 @@ class JvmtiThreadState : public CHeapObj<mtInternal> {
|
|||
private:
|
||||
friend class JvmtiEnv;
|
||||
JavaThread *_thread;
|
||||
bool _exception_detected;
|
||||
bool _exception_caught;
|
||||
bool _hide_single_stepping;
|
||||
bool _pending_step_for_popframe;
|
||||
bool _pending_step_for_earlyret;
|
||||
int _hide_level;
|
||||
|
||||
public:
|
||||
enum ExceptionState {
|
||||
ES_CLEARED,
|
||||
ES_DETECTED,
|
||||
ES_CAUGHT
|
||||
};
|
||||
|
||||
private:
|
||||
ExceptionState _exception_state;
|
||||
|
||||
// Used to send class being redefined/retransformed and kind of transform
|
||||
// info to the class file load hook event handler.
|
||||
KlassHandle *_class_being_redefined;
|
||||
|
@ -161,16 +169,18 @@ class JvmtiThreadState : public CHeapObj<mtInternal> {
|
|||
int count_frames();
|
||||
|
||||
inline JavaThread *get_thread() { return _thread; }
|
||||
inline bool is_exception_detected() { return _exception_detected; }
|
||||
inline bool is_exception_caught() { return _exception_caught; }
|
||||
inline void set_exception_detected() { _exception_detected = true;
|
||||
_exception_caught = false; }
|
||||
inline void clear_exception_detected() {
|
||||
_exception_detected = false;
|
||||
assert(_exception_caught == false, "_exception_caught is out of phase");
|
||||
}
|
||||
inline void set_exception_caught() { _exception_caught = true;
|
||||
_exception_detected = false; }
|
||||
|
||||
inline bool is_exception_detected() { return _exception_state == ES_DETECTED; }
|
||||
inline bool is_exception_caught() { return _exception_state == ES_CAUGHT; }
|
||||
|
||||
inline void set_exception_detected() { _exception_state = ES_DETECTED; }
|
||||
inline void set_exception_caught() { _exception_state = ES_CAUGHT; }
|
||||
|
||||
inline void clear_exception_state() { _exception_state = ES_CLEARED; }
|
||||
|
||||
// We need to save and restore exception state inside JvmtiEventMark
|
||||
inline ExceptionState get_exception_state() { return _exception_state; }
|
||||
inline void restore_exception_state(ExceptionState state) { _exception_state = state; }
|
||||
|
||||
inline void clear_hide_single_stepping() {
|
||||
if (_hide_level > 0) {
|
||||
|
|
|
@ -1323,26 +1323,32 @@ void Arguments::check_unsupported_dumping_properties() {
|
|||
"jdk.module.limitmods",
|
||||
"jdk.module.path",
|
||||
"jdk.module.upgrade.path",
|
||||
"jdk.module.addmods.0" };
|
||||
const char* unsupported_options[] = { "-m",
|
||||
"--limit-modules",
|
||||
"--module-path",
|
||||
"--upgrade-module-path",
|
||||
"--add-modules" };
|
||||
"jdk.module.addmods.0",
|
||||
"jdk.module.patch.0" };
|
||||
const char* unsupported_options[] = { "-m", // cannot use at dump time
|
||||
"--limit-modules", // ignored at dump time
|
||||
"--module-path", // ignored at dump time
|
||||
"--upgrade-module-path", // ignored at dump time
|
||||
"--add-modules", // ignored at dump time
|
||||
"--patch-module" // ignored at dump time
|
||||
};
|
||||
assert(ARRAY_SIZE(unsupported_properties) == ARRAY_SIZE(unsupported_options), "must be");
|
||||
// If a vm option is found in the unsupported_options array with index less than the warning_idx,
|
||||
// vm will exit with an error message. Otherwise, it will result in a warning message.
|
||||
uint warning_idx = 2;
|
||||
// If a vm option is found in the unsupported_options array with index less than the info_idx,
|
||||
// vm will exit with an error message. Otherwise, it will print an informational message if
|
||||
// PrintSharedSpaces is enabled.
|
||||
uint info_idx = 1;
|
||||
SystemProperty* sp = system_properties();
|
||||
while (sp != NULL) {
|
||||
for (uint i = 0; i < ARRAY_SIZE(unsupported_properties); i++) {
|
||||
if (strcmp(sp->key(), unsupported_properties[i]) == 0) {
|
||||
if (i < warning_idx) {
|
||||
if (i < info_idx) {
|
||||
vm_exit_during_initialization(
|
||||
"Cannot use the following option when dumping the shared archive", unsupported_options[i]);
|
||||
} else {
|
||||
warning(
|
||||
"the %s option is ignored when dumping the shared archive", unsupported_options[i]);
|
||||
if (PrintSharedSpaces) {
|
||||
tty->print_cr(
|
||||
"Info: the %s option is ignored when dumping the shared archive", unsupported_options[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1419,10 +1425,8 @@ void Arguments::set_mode_flags(Mode mode) {
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(COMPILER2) || INCLUDE_JVMCI || defined(_LP64) || !INCLUDE_CDS
|
||||
// Conflict: required to use shared spaces (-Xshare:on), but
|
||||
// incompatible command line options were chosen.
|
||||
|
||||
static void no_shared_spaces(const char* message) {
|
||||
if (RequireSharedSpaces) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
|
@ -1432,7 +1436,6 @@ static void no_shared_spaces(const char* message) {
|
|||
FLAG_SET_DEFAULT(UseSharedSpaces, false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Returns threshold scaled with the value of scale.
|
||||
// If scale < 0.0, threshold is returned without scaling.
|
||||
|
@ -2680,6 +2683,12 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
|||
return result;
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS
|
||||
if (UseSharedSpaces && patch_mod_javabase) {
|
||||
no_shared_spaces("CDS is disabled when " JAVA_BASE_NAME " module is patched.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return JNI_OK;
|
||||
}
|
||||
|
||||
|
@ -4408,7 +4417,6 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) {
|
|||
}
|
||||
|
||||
jint Arguments::apply_ergo() {
|
||||
|
||||
// Set flags based on ergonomics.
|
||||
set_ergonomics_flags();
|
||||
|
||||
|
|
|
@ -436,7 +436,7 @@ class os: AllStatic {
|
|||
vm_thread,
|
||||
cgc_thread, // Concurrent GC thread
|
||||
pgc_thread, // Parallel GC thread
|
||||
java_thread,
|
||||
java_thread, // Java, CodeCacheSweeper, JVMTIAgent and Service threads.
|
||||
compiler_thread,
|
||||
watcher_thread,
|
||||
os_thread
|
||||
|
|
|
@ -288,7 +288,8 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
|
|||
nonstatic_field(Klass, _access_flags, AccessFlags) \
|
||||
nonstatic_field(Klass, _prototype_header, markOop) \
|
||||
nonstatic_field(Klass, _next_sibling, Klass*) \
|
||||
nonstatic_field(Klass, _vtable_len, int) \
|
||||
nonstatic_field(Klass, _next_link, Klass*) \
|
||||
nonstatic_field(Klass, _vtable_len, int) \
|
||||
nonstatic_field(vtableEntry, _method, Method*) \
|
||||
nonstatic_field(MethodData, _size, int) \
|
||||
nonstatic_field(MethodData, _method, Method*) \
|
||||
|
@ -712,6 +713,8 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
|
|||
\
|
||||
nonstatic_field(ClassLoaderData, _class_loader, oop) \
|
||||
nonstatic_field(ClassLoaderData, _next, ClassLoaderData*) \
|
||||
volatile_nonstatic_field(ClassLoaderData, _klasses, Klass*) \
|
||||
nonstatic_field(ClassLoaderData, _is_anonymous, bool) \
|
||||
\
|
||||
static_field(ClassLoaderDataGraph, _head, ClassLoaderData*) \
|
||||
\
|
||||
|
|
|
@ -71,7 +71,6 @@ runtime/SharedArchiveFile/DefaultUseWithClient.java 8154204 generic-all
|
|||
|
||||
# :hotspot_serviceability
|
||||
|
||||
serviceability/dcmd/jvmti/LoadAgentDcmdTest.java 8150318 generic-all
|
||||
serviceability/jdwp/AllModulesCommandTest.java 8168478 generic-all
|
||||
serviceability/sa/sadebugd/SADebugDTest.java 8163805 generic-all
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -26,35 +26,28 @@
|
|||
* @bug 7005594
|
||||
* @summary Array overflow not handled correctly with loop optimzations
|
||||
*
|
||||
* @run shell Test7005594.sh
|
||||
* @run main/othervm -Xcomp
|
||||
-XX:CompileOnly=compiler.c2.Test7005594::test
|
||||
compiler.c2.Test7005594
|
||||
*/
|
||||
|
||||
package compiler.c2.cr7005594;
|
||||
package compiler.c2;
|
||||
|
||||
public class Test7005594 {
|
||||
static int test(byte a[]){
|
||||
int result = 0;
|
||||
for (int i = 1; i < a.length; i += Integer.MAX_VALUE) {
|
||||
result += a[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int test(byte a[]){
|
||||
int result=0;
|
||||
for( int i=0; i<a.length; i+=((0x7fffffff>>1)+1) ){
|
||||
result += a[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void main(String [] args){
|
||||
byte a[]=new byte[(0x7fffffff>>1)+2];
|
||||
int result = 0;
|
||||
try {
|
||||
result = test(a);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
e.printStackTrace(System.out);
|
||||
System.out.println("Passed");
|
||||
System.exit(95);
|
||||
}
|
||||
System.out.println(result);
|
||||
System.out.println("FAILED");
|
||||
System.exit(97);
|
||||
}
|
||||
|
||||
public static void main(String [] args){
|
||||
try {
|
||||
int result = test(new byte[2]);
|
||||
throw new AssertionError("Expected ArrayIndexOutOfBoundsException was not thrown");
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
System.out.println("Expected " + e + " was thrown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
#
|
||||
## some tests require path to find test source dir
|
||||
if [ "${TESTSRC}" = "" ]
|
||||
then
|
||||
TESTSRC=${PWD}
|
||||
echo "TESTSRC not set. Using "${TESTSRC}" as default"
|
||||
fi
|
||||
echo "TESTSRC=${TESTSRC}"
|
||||
## Adding common setup Variables for running shell tests.
|
||||
. ${TESTSRC}/../../../test_env.sh
|
||||
|
||||
# Amount of physical memory in megabytes
|
||||
MEM=0
|
||||
if [ -f "/proc/meminfo" ]; then
|
||||
# Linux, Windows/Cygwin
|
||||
MEM=`cat /proc/meminfo |grep ^MemTotal: | awk '{print $2}'`
|
||||
MEM="$(($MEM / 1024))"
|
||||
elif [ -x "/usr/sbin/prtconf" ]; then
|
||||
# Solaris
|
||||
MEM=`/usr/sbin/prtconf | grep "^Memory size" | awk '{print $3}'`
|
||||
elif [ -x "/usr/sbin/system_profiler" ]; then
|
||||
# MacOS
|
||||
MEMo=`/usr/sbin/system_profiler SPHardwareDataType | grep Memory:`
|
||||
MEM=`echo "$MEMo" | awk '{print $2}'`
|
||||
MEMu=`echo "$MEMo" | awk '{print $3}'`
|
||||
case $MEMu in
|
||||
GB)
|
||||
MEM="$(($MEM * 1024))"
|
||||
;;
|
||||
MB)
|
||||
;;
|
||||
*)
|
||||
echo "Unknown memory unit in system_profile output: $MEMu"
|
||||
;;
|
||||
esac
|
||||
elif [ -n "$ROOTDIR" -a -x "$ROOTDIR/mksnt/sysinf" ]; then
|
||||
# Windows/MKS
|
||||
MEM=`"$ROOTDIR/mksnt/sysinf" memory -v | grep "Total Physical Memory: " | sed 's/Total Physical Memory: *//g'`
|
||||
MEM="$(($machine_memory / 1024))"
|
||||
else
|
||||
echo "Unable to determine amount of physical memory on the machine"
|
||||
fi
|
||||
|
||||
if [ $MEM -lt 2000 ]; then
|
||||
echo "Test skipped due to low (or unknown) memory on the system: $MEM Mb"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "MEMORY=$MEM Mb"
|
||||
|
||||
set -x
|
||||
|
||||
cp ${TESTSRC}/Test7005594.java .
|
||||
cp ${TESTSRC}/Test7005594.sh .
|
||||
|
||||
${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Test7005594.java
|
||||
|
||||
${TESTJAVA}/bin/java ${TESTOPTS} -Xmx1600m -Xms1600m -XX:+IgnoreUnrecognizedVMOptions \
|
||||
-XX:-ZapUnusedHeapArea -Xcomp -XX:CompileCommand=quiet \
|
||||
-XX:CompileOnly=compiler.c2.cr7005594.Test7005594::test \
|
||||
compiler.c2.cr7005594.Test7005594 > test.out 2>&1
|
||||
|
||||
result=$?
|
||||
|
||||
cat test.out
|
||||
|
||||
if [ $result -eq 95 ]
|
||||
then
|
||||
echo "Passed"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ $result -eq 97 ]
|
||||
then
|
||||
echo "Failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The test should pass when no enough space for object heap
|
||||
grep "Could not reserve enough space for .*object heap" test.out
|
||||
if [ $? = 0 ]
|
||||
then
|
||||
echo "Passed"
|
||||
exit 0
|
||||
else
|
||||
echo "Failed"
|
||||
exit 1
|
||||
fi
|
|
@ -215,7 +215,7 @@ public abstract class CiReplayBase {
|
|||
try(BufferedReader br = new BufferedReader(new FileReader(REPLAY_FILE_NAME))) {
|
||||
return br.lines()
|
||||
.filter(s -> s.startsWith("compile "))
|
||||
.map(s -> s.substring(s.lastIndexOf(' ') + 1))
|
||||
.map(s -> s.split("\\s+")[5])
|
||||
.map(Integer::parseInt)
|
||||
.findAny()
|
||||
.get();
|
||||
|
|
167
hotspot/test/compiler/floatingpoint/TestFMABrokenC1RegAlloc.java
Normal file
167
hotspot/test/compiler/floatingpoint/TestFMABrokenC1RegAlloc.java
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Red Hat, Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8171092
|
||||
* @summary C1's Math.fma() intrinsic doesn't correctly marks its inputs
|
||||
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestFMABrokenC1RegAlloc
|
||||
*
|
||||
*/
|
||||
|
||||
public class TestFMABrokenC1RegAlloc {
|
||||
|
||||
double dummy0;
|
||||
double dummy1;
|
||||
double dummy2;
|
||||
double dummy3;
|
||||
double dummy4;
|
||||
double dummy5;
|
||||
double dummy6;
|
||||
double dummy7;
|
||||
double dummy8;
|
||||
double dummy9;
|
||||
double dummy10;
|
||||
double dummy11;
|
||||
double dummy12;
|
||||
double dummy13;
|
||||
double dummy14;
|
||||
double dummy15;
|
||||
double dummy16;
|
||||
double dummy17;
|
||||
double dummy18;
|
||||
double dummy19;
|
||||
double dummy20;
|
||||
double dummy21;
|
||||
double dummy22;
|
||||
double dummy23;
|
||||
double dummy24;
|
||||
double dummy25;
|
||||
double dummy26;
|
||||
double dummy27;
|
||||
double dummy28;
|
||||
double dummy29;
|
||||
double dummy30;
|
||||
double dummy31;
|
||||
double dummy32;
|
||||
double dummy33;
|
||||
double dummy34;
|
||||
double dummy35;
|
||||
double dummy36;
|
||||
double dummy37;
|
||||
double dummy38;
|
||||
double dummy39;
|
||||
|
||||
double test(double a, double b, double c) {
|
||||
double dummy0 = this.dummy0;
|
||||
double dummy1 = this.dummy1;
|
||||
double dummy2 = this.dummy2;
|
||||
double dummy3 = this.dummy3;
|
||||
double dummy4 = this.dummy4;
|
||||
double dummy5 = this.dummy5;
|
||||
double dummy6 = this.dummy6;
|
||||
double dummy7 = this.dummy7;
|
||||
double dummy8 = this.dummy8;
|
||||
double dummy9 = this.dummy9;
|
||||
double dummy10 = this.dummy10;
|
||||
double dummy11 = this.dummy11;
|
||||
double dummy12 = this.dummy12;
|
||||
double dummy13 = this.dummy13;
|
||||
double dummy14 = this.dummy14;
|
||||
double dummy15 = this.dummy15;
|
||||
double dummy16 = this.dummy16;
|
||||
double dummy17 = this.dummy17;
|
||||
double dummy18 = this.dummy18;
|
||||
double dummy19 = this.dummy19;
|
||||
double dummy20 = this.dummy20;
|
||||
double dummy21 = this.dummy21;
|
||||
double dummy22 = this.dummy22;
|
||||
double dummy23 = this.dummy23;
|
||||
double dummy24 = this.dummy24;
|
||||
double dummy25 = this.dummy25;
|
||||
double dummy26 = this.dummy26;
|
||||
double dummy27 = this.dummy27;
|
||||
double dummy28 = this.dummy28;
|
||||
double dummy29 = this.dummy29;
|
||||
double dummy30 = this.dummy30;
|
||||
double dummy31 = this.dummy31;
|
||||
double dummy32 = this.dummy32;
|
||||
double dummy33 = this.dummy33;
|
||||
double dummy34 = this.dummy34;
|
||||
double dummy35 = this.dummy35;
|
||||
double dummy36 = this.dummy36;
|
||||
double dummy37 = this.dummy37;
|
||||
double dummy38 = this.dummy38;
|
||||
double dummy39 = this.dummy39;
|
||||
return Math.fma(a, b, c) +
|
||||
dummy0 +
|
||||
dummy1 +
|
||||
dummy2 +
|
||||
dummy3 +
|
||||
dummy4 +
|
||||
dummy5 +
|
||||
dummy6 +
|
||||
dummy7 +
|
||||
dummy8 +
|
||||
dummy9 +
|
||||
dummy10 +
|
||||
dummy11 +
|
||||
dummy12 +
|
||||
dummy13 +
|
||||
dummy14 +
|
||||
dummy15 +
|
||||
dummy16 +
|
||||
dummy17 +
|
||||
dummy18 +
|
||||
dummy19 +
|
||||
dummy20 +
|
||||
dummy21 +
|
||||
dummy22 +
|
||||
dummy23 +
|
||||
dummy24 +
|
||||
dummy25 +
|
||||
dummy26 +
|
||||
dummy27 +
|
||||
dummy28 +
|
||||
dummy29 +
|
||||
dummy30 +
|
||||
dummy31 +
|
||||
dummy32 +
|
||||
dummy33 +
|
||||
dummy34 +
|
||||
dummy35 +
|
||||
dummy36 +
|
||||
dummy37 +
|
||||
dummy38 +
|
||||
dummy39;
|
||||
}
|
||||
|
||||
static public void main(String[] args) {
|
||||
TestFMABrokenC1RegAlloc t = new TestFMABrokenC1RegAlloc();
|
||||
for (int i = 0; i < 5000; i++) {
|
||||
if (t.test(5.0, 10.0, 7.0) != 57.0) {
|
||||
throw new RuntimeException("Failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -241,7 +241,7 @@ public class RTMTestBase {
|
|||
CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS,
|
||||
CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
|
||||
"-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI",
|
||||
"-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED");
|
||||
"--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED");
|
||||
|
||||
if (test != null) {
|
||||
for (String method : test.getMethodsToCompileNames()) {
|
||||
|
|
|
@ -59,6 +59,20 @@ static inline void create_directory(const char* name) {
|
|||
assert(!failed, "failed to create directory %s", name);
|
||||
}
|
||||
|
||||
static inline void delete_empty_directory(const char* name) {
|
||||
#ifdef _WINDOWS
|
||||
if (!file_exists(name)) {
|
||||
return;
|
||||
}
|
||||
bool failed;
|
||||
failed = !RemoveDirectory(name);
|
||||
EXPECT_FALSE(failed) << "failed to remove directory '" << name
|
||||
<< "': LastError = " << GetLastError();
|
||||
#else
|
||||
delete_file(name);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void init_log_file(const char* filename, const char* options = "") {
|
||||
LogStreamHandle(Error, logging) stream;
|
||||
bool success = LogConfiguration::parse_log_arguments(filename, "logging=trace", "", options, &stream);
|
||||
|
|
|
@ -103,7 +103,7 @@ TEST_VM(LogFileOutput, filesize_overflow) {
|
|||
EXPECT_FALSE(fo.initialize(buf, &ss)) << "Accepted filesize that overflows";
|
||||
}
|
||||
|
||||
TEST(LogFileOutput, startup_rotation) {
|
||||
TEST_VM(LogFileOutput, startup_rotation) {
|
||||
const size_t rotations = 5;
|
||||
const char* filename = "start-rotate-test";
|
||||
char* rotated_file[rotations];
|
||||
|
@ -140,7 +140,7 @@ TEST(LogFileOutput, startup_rotation) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(LogFileOutput, startup_truncation) {
|
||||
TEST_VM(LogFileOutput, startup_truncation) {
|
||||
const char* filename = "start-truncate-test";
|
||||
const char* archived_filename = "start-truncate-test.0";
|
||||
|
||||
|
@ -168,7 +168,7 @@ TEST(LogFileOutput, startup_truncation) {
|
|||
delete_file(archived_filename);
|
||||
}
|
||||
|
||||
TEST(LogFileOutput, invalid_file) {
|
||||
TEST_VM(LogFileOutput, invalid_file) {
|
||||
ResourceMark rm;
|
||||
stringStream ss;
|
||||
|
||||
|
@ -179,5 +179,5 @@ TEST(LogFileOutput, invalid_file) {
|
|||
<< "file was initialized when there was an existing directory with the same name";
|
||||
EXPECT_TRUE(string_contains_substring(ss.as_string(), "tmplogdir is not a regular file"))
|
||||
<< "missing expected error message, received msg: %s" << ss.as_string();
|
||||
remove("tmplogdir");
|
||||
delete_empty_directory("tmplogdir");
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* ac_heapanied this code).
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
|
@ -19,8 +19,8 @@
|
|||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "logTestFixture.hpp"
|
||||
#include "logTestUtils.inline.hpp"
|
||||
|
|
|
@ -41,41 +41,41 @@ void LogStreamTest::verify_stream(outputStream* stream) {
|
|||
EXPECT_TRUE(file_contains_substring(TestLogFileName, "3 workers\n"));
|
||||
}
|
||||
|
||||
TEST_F(LogStreamTest, from_log) {
|
||||
TEST_VM_F(LogStreamTest, from_log) {
|
||||
Log(gc) log;
|
||||
LogStream stream(log.debug());
|
||||
|
||||
verify_stream(&stream);
|
||||
}
|
||||
|
||||
TEST_F(LogStreamTest, from_logtarget) {
|
||||
TEST_VM_F(LogStreamTest, from_logtarget) {
|
||||
LogTarget(Debug, gc) log;
|
||||
LogStream stream(log);
|
||||
|
||||
verify_stream(&stream);
|
||||
}
|
||||
|
||||
TEST_F(LogStreamTest, handle) {
|
||||
TEST_VM_F(LogStreamTest, handle) {
|
||||
LogStreamHandle(Debug, gc) stream;
|
||||
|
||||
verify_stream(&stream);
|
||||
}
|
||||
|
||||
TEST_F(LogStreamTest, no_rm) {
|
||||
TEST_VM_F(LogStreamTest, no_rm) {
|
||||
ResourceMark rm;
|
||||
outputStream* stream = LogTarget(Debug, gc)::stream();
|
||||
|
||||
verify_stream(stream);
|
||||
}
|
||||
|
||||
TEST_F(LogStreamTest, c_heap_stream) {
|
||||
TEST_VM_F(LogStreamTest, c_heap_stream) {
|
||||
Log(gc) log;
|
||||
LogStreamCHeap stream(log.debug());
|
||||
|
||||
verify_stream(&stream);
|
||||
}
|
||||
|
||||
TEST_F(LogStreamTest, c_heap_stream_target) {
|
||||
TEST_VM_F(LogStreamTest, c_heap_stream_target) {
|
||||
LogTarget(Debug, gc) log;
|
||||
LogStreamCHeap stream(log);
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ TEST(LinkedList, simple) {
|
|||
ASSERT_EQ(six.value(), i->value()) << "Should be 6";
|
||||
|
||||
i = ll.find(three);
|
||||
ASSERT_EQ(NULL, i) << "Not in the list";
|
||||
ASSERT_TRUE(i == NULL) << "Not in the list";
|
||||
|
||||
LinkedListNode<Integer>* node = ll.find_node(six);
|
||||
ASSERT_TRUE(node != NULL) << "6 is in the list";
|
||||
|
|
|
@ -72,6 +72,6 @@ public class IgnoreModulePropertiesTest {
|
|||
testOption("--add-reads", "xyzz=yyzd", "jdk.module.addreads.0", "WARNING: Unknown module: xyzz");
|
||||
testOption("--add-exports", "java.base/xyzz=yyzd", "jdk.module.addexports.0",
|
||||
"WARNING: package xyzz not in java.base");
|
||||
testOption("--patch-module", "=d", "jdk.module.patch.0", "Missing module name");
|
||||
testOption("--patch-module", "=d", "jdk.module.patch.0", "Unable to parse --patch-module");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ public class PatchModuleCDS {
|
|||
new OutputAnalyzer(pb.start())
|
||||
.shouldContain("ro space:"); // Make sure archive got created.
|
||||
|
||||
// Case 2: Test that only jar file in --patch-module is supported for CDS dumping
|
||||
// Case 2: Test that directory in --patch-module is supported for CDS dumping
|
||||
// Create a class file in the module java.base.
|
||||
String source = "package javax.naming.spi; " +
|
||||
"public class NamingManager { " +
|
||||
|
@ -73,7 +73,7 @@ public class PatchModuleCDS {
|
|||
"-Xlog:class+path=info",
|
||||
"-version");
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldContain("--patch-module requires a regular file during dumping");
|
||||
.shouldContain("ro space:"); // Make sure archive got created.
|
||||
|
||||
// Case 3a: Test CDS dumping with jar file in --patch-module
|
||||
BasicJarBuilder.build("javanaming", "javax/naming/spi/NamingManager");
|
||||
|
|
|
@ -136,11 +136,7 @@ public class LoadAgentDcmdTest {
|
|||
if (Platform.isWindows()) {
|
||||
return "bin";
|
||||
}
|
||||
if (Platform.isOSX()) {
|
||||
return "lib";
|
||||
}
|
||||
|
||||
return "lib/" + Platform.getOsArch();
|
||||
return "lib";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -82,14 +82,18 @@ jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
|
|||
}
|
||||
|
||||
static
|
||||
jint throw_exc(JNIEnv *env, char *msg) {
|
||||
void throw_exc(JNIEnv *env, char *msg) {
|
||||
jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
|
||||
jint rt = JNI_OK;
|
||||
|
||||
if (exc_class == NULL) {
|
||||
printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
rt = JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
|
||||
if (rt == JNI_ERR) {
|
||||
printf("throw_exc: Error in JNI ThrowNew(env, %s)\n", msg);
|
||||
}
|
||||
return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
|
@ -81,14 +81,18 @@ jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
|
|||
}
|
||||
|
||||
static
|
||||
jint throw_exc(JNIEnv *env, char *msg) {
|
||||
void throw_exc(JNIEnv *env, char *msg) {
|
||||
jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
|
||||
jint rt = JNI_OK;
|
||||
|
||||
if (exc_class == NULL) {
|
||||
printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
rt = JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
|
||||
if (rt == JNI_ERR) {
|
||||
printf("throw_exc: Error in JNI ThrowNew(env, %s)\n", msg);
|
||||
}
|
||||
return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
|
@ -82,14 +82,18 @@ jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
|
|||
}
|
||||
|
||||
static
|
||||
jint throw_exc(JNIEnv *env, char *msg) {
|
||||
void throw_exc(JNIEnv *env, char *msg) {
|
||||
jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
|
||||
jint rt = JNI_OK;
|
||||
|
||||
if (exc_class == NULL) {
|
||||
printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
rt = JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
|
||||
if (rt == JNI_ERR) {
|
||||
printf("throw_exc: Error in JNI ThrowNew(env, %s)\n", msg);
|
||||
}
|
||||
return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8134434
|
||||
* @summary JVM_DoPrivileged() fires assert(_exception_caught == false) failed: _exception_caught is out of phase
|
||||
* @run main/othervm -agentlib:jdwp=transport=dt_socket,address=9000,server=y,suspend=n -Xbatch ExceptionCaughtOutOfPhaseTest
|
||||
*/
|
||||
|
||||
public class ExceptionCaughtOutOfPhaseTest {
|
||||
public static void main(String[] args) {
|
||||
PrivilegedAction action = new HotThrowingAction();
|
||||
System.out.println("### Warm-up");
|
||||
for(int i=0; i<11000; i++) {
|
||||
try {
|
||||
action.run(); // call run() to get it compiled
|
||||
} catch(Throwable t) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("### Warm-up done");
|
||||
System.out.println("### Executing privileged action");
|
||||
|
||||
try {
|
||||
AccessController.doPrivileged(action);
|
||||
} catch (Error e) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
public static class HotThrowingAction implements PrivilegedAction {
|
||||
public Object run() {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
}
|
141
hotspot/test/serviceability/sa/TestHeapDumpForInvokeDynamic.java
Normal file
141
hotspot/test/serviceability/sa/TestHeapDumpForInvokeDynamic.java
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.io.IOException;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.util.stream.Collectors;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
import sun.jvm.hotspot.HotSpotAgent;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
|
||||
import jdk.test.lib.apps.LingeredApp;
|
||||
import jdk.test.lib.JDKToolLauncher;
|
||||
import jdk.test.lib.JDKToolFinder;
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.Utils;
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.hprof.HprofParser;
|
||||
import jdk.test.lib.hprof.parser.HprofReader;
|
||||
import jdk.test.lib.hprof.parser.PositionDataInputStream;
|
||||
import jdk.test.lib.hprof.model.Snapshot;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @library /test/lib
|
||||
* @requires os.family != "mac"
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* jdk.hotspot.agent/sun.jvm.hotspot
|
||||
* jdk.hotspot.agent/sun.jvm.hotspot.utilities
|
||||
* jdk.hotspot.agent/sun.jvm.hotspot.oops
|
||||
* jdk.hotspot.agent/sun.jvm.hotspot.debugger
|
||||
* @run main/othervm TestHeapDumpForInvokeDynamic
|
||||
*/
|
||||
|
||||
public class TestHeapDumpForInvokeDynamic {
|
||||
|
||||
private static LingeredAppWithInvokeDynamic theApp = null;
|
||||
|
||||
private static void verifyHeapDump(String heapFile) {
|
||||
|
||||
File heapDumpFile = new File(heapFile);
|
||||
Asserts.assertTrue(heapDumpFile.exists() && heapDumpFile.isFile(),
|
||||
"Could not create dump file " + heapDumpFile.getAbsolutePath());
|
||||
try (PositionDataInputStream in = new PositionDataInputStream(
|
||||
new BufferedInputStream(new FileInputStream(heapFile)))) {
|
||||
int i = in.readInt();
|
||||
if (HprofReader.verifyMagicNumber(i)) {
|
||||
Snapshot sshot;
|
||||
HprofReader r = new HprofReader(heapFile, in, 0,
|
||||
false, 0);
|
||||
sshot = r.read();
|
||||
} else {
|
||||
throw new IOException("Unrecognized magic number: " + i);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Asserts.fail("Could not read dump file " + heapFile);
|
||||
} finally {
|
||||
heapDumpFile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private static void attachDumpAndVerify(String heapDumpFileName,
|
||||
long lingeredAppPid) throws Exception {
|
||||
|
||||
JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
|
||||
launcher.addToolArg("jmap");
|
||||
launcher.addToolArg("--binaryheap");
|
||||
launcher.addToolArg("--dumpfile");
|
||||
launcher.addToolArg(heapDumpFileName);
|
||||
launcher.addToolArg("--pid");
|
||||
launcher.addToolArg(Long.toString(lingeredAppPid));
|
||||
|
||||
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||
processBuilder.command(launcher.getCommand());
|
||||
System.out.println(
|
||||
processBuilder.command().stream().collect(Collectors.joining(" ")));
|
||||
|
||||
OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder);
|
||||
SAOutput.shouldHaveExitValue(0);
|
||||
SAOutput.shouldContain("heap written to");
|
||||
SAOutput.shouldContain(heapDumpFileName);
|
||||
System.out.println(SAOutput.getOutput());
|
||||
|
||||
verifyHeapDump(heapDumpFileName);
|
||||
}
|
||||
|
||||
public static void main (String... args) throws Exception {
|
||||
|
||||
String heapDumpFileName = "lambdaHeapDump.bin";
|
||||
|
||||
if (!Platform.shouldSAAttach()) {
|
||||
System.out.println(
|
||||
"SA attach not expected to work - test skipped.");
|
||||
return;
|
||||
}
|
||||
|
||||
File heapDumpFile = new File(heapDumpFileName);
|
||||
if (heapDumpFile.exists()) {
|
||||
heapDumpFile.delete();
|
||||
}
|
||||
|
||||
try {
|
||||
List<String> vmArgs = new ArrayList<String>();
|
||||
vmArgs.add("-XX:+UsePerfData");
|
||||
vmArgs.addAll(Utils.getVmOptions());
|
||||
|
||||
theApp = new LingeredAppWithInvokeDynamic();
|
||||
LingeredApp.startApp(vmArgs, theApp);
|
||||
attachDumpAndVerify(heapDumpFileName, theApp.getPid());
|
||||
} finally {
|
||||
LingeredApp.stopApp(theApp);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue