--- a/hotspot/.hgtags Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/.hgtags Thu Apr 06 22:13:13 2017 +0000
@@ -566,3 +566,4 @@
94b4e2e5331d38eab6a3639c3511b2e0715df0e9 jdk-9+160
191ffbdb3d7b734288daa7fb76b37a0a85dfe7eb jdk-9+161
b01c519b715ef6f785d0631adee0a6537cf6c12e jdk-9+162
+983fe207555724d98f4876991e1cbafbcf2733e8 jdk-9+163
--- a/hotspot/make/lib/CompileJvm.gmk Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/make/lib/CompileJvm.gmk Thu Apr 06 22:13:13 2017 +0000
@@ -118,6 +118,12 @@
OPENJDK_TARGET_CPU_VM_VERSION := amd64
else ifeq ($(OPENJDK_TARGET_CPU), sparcv9)
OPENJDK_TARGET_CPU_VM_VERSION := sparc
+else ifeq ($(HOTSPOT_TARGET_CPU_ARCH), arm)
+ ifeq ($(OPENJDK_TARGET_CPU), aarch64)
+ # This sets the Oracle Aarch64 port to use arm64
+ # while the original Aarch64 port uses aarch64
+ OPENJDK_TARGET_CPU_VM_VERSION := arm64
+ endif
else
OPENJDK_TARGET_CPU_VM_VERSION := $(OPENJDK_TARGET_CPU)
endif
--- a/hotspot/make/test/JtregNative.gmk Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/make/test/JtregNative.gmk Thu Apr 06 22:13:13 2017 +0000
@@ -50,6 +50,8 @@
$(HOTSPOT_TOPDIR)/test/runtime/jni/PrivateInterfaceMethods \
$(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \
$(HOTSPOT_TOPDIR)/test/runtime/jni/CalleeSavedRegisters \
+ $(HOTSPOT_TOPDIR)/test/runtime/jni/CallWithJNIWeak \
+ $(HOTSPOT_TOPDIR)/test/runtime/jni/ReturnJNIWeak \
$(HOTSPOT_TOPDIR)/test/runtime/modules/getModuleJNI \
$(HOTSPOT_TOPDIR)/test/runtime/SameObject \
$(HOTSPOT_TOPDIR)/test/runtime/BoolReturn \
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Thu Apr 06 22:13:13 2017 +0000
@@ -15501,7 +15501,7 @@
%}
instruct string_indexofUU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
- iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
@@ -15520,7 +15520,7 @@
%}
instruct string_indexofLL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
- iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
@@ -15539,7 +15539,7 @@
%}
instruct string_indexofUL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
- iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
@@ -15558,7 +15558,7 @@
%}
instruct string_indexofLU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
- iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LU);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
@@ -15577,8 +15577,8 @@
%}
instruct string_indexof_conUU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
- immI_le_4 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
- iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ immI_le_4 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2,
+ iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
@@ -15598,8 +15598,8 @@
%}
instruct string_indexof_conLL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
- immI_le_4 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
- iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ immI_le_4 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2,
+ iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
@@ -15619,8 +15619,8 @@
%}
instruct string_indexof_conUL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
- immI_1 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
- iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ immI_1 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2,
+ iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
@@ -15640,8 +15640,8 @@
%}
instruct string_indexof_conLU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
- immI_1 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
- iRegI tmp3, iRegI tmp4, rFlagsReg cr)
+ immI_1 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2,
+ iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LU);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
@@ -15661,8 +15661,8 @@
%}
instruct string_indexofU_char(iRegP_R1 str1, iRegI_R2 cnt1, iRegI_R3 ch,
- iRegI_R0 result, iRegI tmp1, iRegI tmp2,
- iRegI tmp3, rFlagsReg cr)
+ iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2,
+ iRegINoSp tmp3, rFlagsReg cr)
%{
match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
effect(USE_KILL str1, USE_KILL cnt1, USE_KILL ch,
@@ -16101,7 +16101,7 @@
// ====================REDUCTION ARITHMETIC====================================
-instruct reduce_add2I(iRegINoSp dst, iRegIorL2I src1, vecD src2, iRegI tmp, iRegI tmp2)
+instruct reduce_add2I(iRegINoSp dst, iRegIorL2I src1, vecD src2, iRegINoSp tmp, iRegINoSp tmp2)
%{
match(Set dst (AddReductionVI src1 src2));
ins_cost(INSN_COST);
@@ -16120,7 +16120,7 @@
ins_pipe(pipe_class_default);
%}
-instruct reduce_add4I(iRegINoSp dst, iRegIorL2I src1, vecX src2, vecX tmp, iRegI tmp2)
+instruct reduce_add4I(iRegINoSp dst, iRegIorL2I src1, vecX src2, vecX tmp, iRegINoSp tmp2)
%{
match(Set dst (AddReductionVI src1 src2));
ins_cost(INSN_COST);
@@ -16138,7 +16138,7 @@
ins_pipe(pipe_class_default);
%}
-instruct reduce_mul2I(iRegINoSp dst, iRegIorL2I src1, vecD src2, iRegI tmp)
+instruct reduce_mul2I(iRegINoSp dst, iRegIorL2I src1, vecD src2, iRegINoSp tmp)
%{
match(Set dst (MulReductionVI src1 src2));
ins_cost(INSN_COST);
@@ -16157,7 +16157,7 @@
ins_pipe(pipe_class_default);
%}
-instruct reduce_mul4I(iRegINoSp dst, iRegIorL2I src1, vecX src2, vecX tmp, iRegI tmp2)
+instruct reduce_mul4I(iRegINoSp dst, iRegIorL2I src1, vecX src2, vecX tmp, iRegINoSp tmp2)
%{
match(Set dst (MulReductionVI src1 src2));
ins_cost(INSN_COST);
--- a/hotspot/src/cpu/aarch64/vm/jniFastGetField_aarch64.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/aarch64/vm/jniFastGetField_aarch64.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -82,6 +82,11 @@
__ eor(robj, robj, rcounter); // obj, since
// robj ^ rcounter ^ rcounter == robj
// robj is address dependent on rcounter.
+
+ // If mask changes we need to ensure that the inverse is still encodable as an immediate
+ STATIC_ASSERT(JNIHandles::weak_tag_mask == 1);
+ __ andr(robj, robj, ~JNIHandles::weak_tag_mask);
+
__ ldr(robj, Address(robj, 0)); // *obj
__ lsr(roffset, c_rarg2, 2); // offset
--- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -2052,13 +2052,31 @@
__ reset_last_Java_frame(false);
- // Unpack oop result
+ // Unbox oop result, e.g. JNIHandles::resolve result.
if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
- Label L;
- __ cbz(r0, L);
- __ ldr(r0, Address(r0, 0));
- __ bind(L);
- __ verify_oop(r0);
+ Label done, not_weak;
+ __ cbz(r0, done); // Use NULL as-is.
+ STATIC_ASSERT(JNIHandles::weak_tag_mask == 1u);
+ __ tbz(r0, 0, not_weak); // Test for jweak tag.
+ // Resolve jweak.
+ __ ldr(r0, Address(r0, -JNIHandles::weak_tag_value));
+ __ verify_oop(r0);
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) {
+ __ g1_write_barrier_pre(noreg /* obj */,
+ r0 /* pre_val */,
+ rthread /* thread */,
+ rscratch1 /* tmp */,
+ true /* tosca_live */,
+ true /* expand_call */);
+ }
+#endif // INCLUDE_ALL_GCS
+ __ b(done);
+ __ bind(not_weak);
+ // Resolve (untagged) jobject.
+ __ ldr(r0, Address(r0, 0));
+ __ verify_oop(r0);
+ __ bind(done);
}
if (CheckJNICalls) {
--- a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1395,13 +1395,32 @@
// and result handler will pick it up
{
- Label no_oop, store_result;
+ Label no_oop, not_weak, store_result;
__ adr(t, ExternalAddress(AbstractInterpreter::result_handler(T_OBJECT)));
__ cmp(t, result_handler);
__ br(Assembler::NE, no_oop);
- // retrieve result
+ // Unbox oop result, e.g. JNIHandles::resolve result.
__ pop(ltos);
- __ cbz(r0, store_result);
+ __ cbz(r0, store_result); // Use NULL as-is.
+ STATIC_ASSERT(JNIHandles::weak_tag_mask == 1u);
+ __ tbz(r0, 0, not_weak); // Test for jweak tag.
+ // Resolve jweak.
+ __ ldr(r0, Address(r0, -JNIHandles::weak_tag_value));
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) {
+ __ enter(); // Barrier may call runtime.
+ __ g1_write_barrier_pre(noreg /* obj */,
+ r0 /* pre_val */,
+ rthread /* thread */,
+ t /* tmp */,
+ true /* tosca_live */,
+ true /* expand_call */);
+ __ leave();
+ }
+#endif // INCLUDE_ALL_GCS
+ __ b(store_result);
+ __ bind(not_weak);
+ // Resolve (untagged) jobject.
__ ldr(r0, Address(r0, 0));
__ bind(store_result);
__ str(r0, Address(rfp, frame::interpreter_frame_oop_temp_offset*wordSize));
--- a/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -476,185 +476,6 @@
}
//////////////////////////////////////////////////////////////////////////////////
-#if INCLUDE_ALL_GCS
-
-// G1 pre-barrier.
-// Blows all volatile registers (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR).
-// If store_addr != noreg, then previous value is loaded from [store_addr];
-// in such case store_addr and new_val registers are preserved;
-// otherwise pre_val register is preserved.
-void InterpreterMacroAssembler::g1_write_barrier_pre(Register store_addr,
- Register new_val,
- Register pre_val,
- Register tmp1,
- Register tmp2) {
- Label done;
- Label runtime;
-
- if (store_addr != noreg) {
- assert_different_registers(store_addr, new_val, pre_val, tmp1, tmp2, noreg);
- } else {
- assert (new_val == noreg, "should be");
- assert_different_registers(pre_val, tmp1, tmp2, noreg);
- }
-
- Address in_progress(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
- SATBMarkQueue::byte_offset_of_active()));
- Address index(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
- SATBMarkQueue::byte_offset_of_index()));
- Address buffer(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
- SATBMarkQueue::byte_offset_of_buf()));
-
- // Is marking active?
- assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "adjust this code");
- ldrb(tmp1, in_progress);
- cbz(tmp1, done);
-
- // Do we need to load the previous value?
- if (store_addr != noreg) {
- load_heap_oop(pre_val, Address(store_addr, 0));
- }
-
- // Is the previous value null?
- cbz(pre_val, done);
-
- // Can we store original value in the thread's buffer?
- // Is index == 0?
- // (The index field is typed as size_t.)
-
- ldr(tmp1, index); // tmp1 := *index_adr
- ldr(tmp2, buffer);
-
- subs(tmp1, tmp1, wordSize); // tmp1 := tmp1 - wordSize
- b(runtime, lt); // If negative, goto runtime
-
- str(tmp1, index); // *index_adr := tmp1
-
- // Record the previous value
- str(pre_val, Address(tmp2, tmp1));
- b(done);
-
- bind(runtime);
-
- // save the live input values
-#ifdef AARCH64
- if (store_addr != noreg) {
- raw_push(store_addr, new_val);
- } else {
- raw_push(pre_val, ZR);
- }
-#else
- if (store_addr != noreg) {
- // avoid raw_push to support any ordering of store_addr and new_val
- push(RegisterSet(store_addr) | RegisterSet(new_val));
- } else {
- push(pre_val);
- }
-#endif // AARCH64
-
- if (pre_val != R0) {
- mov(R0, pre_val);
- }
- mov(R1, Rthread);
-
- call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), R0, R1);
-
-#ifdef AARCH64
- if (store_addr != noreg) {
- raw_pop(store_addr, new_val);
- } else {
- raw_pop(pre_val, ZR);
- }
-#else
- if (store_addr != noreg) {
- pop(RegisterSet(store_addr) | RegisterSet(new_val));
- } else {
- pop(pre_val);
- }
-#endif // AARCH64
-
- bind(done);
-}
-
-// G1 post-barrier.
-// Blows all volatile registers (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR).
-void InterpreterMacroAssembler::g1_write_barrier_post(Register store_addr,
- Register new_val,
- Register tmp1,
- Register tmp2,
- Register tmp3) {
-
- Address queue_index(Rthread, in_bytes(JavaThread::dirty_card_queue_offset() +
- DirtyCardQueue::byte_offset_of_index()));
- Address buffer(Rthread, in_bytes(JavaThread::dirty_card_queue_offset() +
- DirtyCardQueue::byte_offset_of_buf()));
-
- BarrierSet* bs = Universe::heap()->barrier_set();
- CardTableModRefBS* ct = (CardTableModRefBS*)bs;
- Label done;
- Label runtime;
-
- // Does store cross heap regions?
-
- eor(tmp1, store_addr, new_val);
-#ifdef AARCH64
- logical_shift_right(tmp1, tmp1, HeapRegion::LogOfHRGrainBytes);
- cbz(tmp1, done);
-#else
- movs(tmp1, AsmOperand(tmp1, lsr, HeapRegion::LogOfHRGrainBytes));
- b(done, eq);
-#endif
-
- // crosses regions, storing NULL?
-
- cbz(new_val, done);
-
- // storing region crossing non-NULL, is card already dirty?
- const Register card_addr = tmp1;
- assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
-
- mov_address(tmp2, (address)ct->byte_map_base, symbolic_Relocation::card_table_reference);
- add(card_addr, tmp2, AsmOperand(store_addr, lsr, CardTableModRefBS::card_shift));
-
- ldrb(tmp2, Address(card_addr));
- cmp(tmp2, (int)G1SATBCardTableModRefBS::g1_young_card_val());
- b(done, eq);
-
- membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreLoad), tmp2);
-
- assert(CardTableModRefBS::dirty_card_val() == 0, "adjust this code");
- ldrb(tmp2, Address(card_addr));
- cbz(tmp2, done);
-
- // storing a region crossing, non-NULL oop, card is clean.
- // dirty card and log.
-
- strb(zero_register(tmp2), Address(card_addr));
-
- ldr(tmp2, queue_index);
- ldr(tmp3, buffer);
-
- subs(tmp2, tmp2, wordSize);
- b(runtime, lt); // go to runtime if now negative
-
- str(tmp2, queue_index);
-
- str(card_addr, Address(tmp3, tmp2));
- b(done);
-
- bind(runtime);
-
- if (card_addr != R0) {
- mov(R0, card_addr);
- }
- mov(R1, Rthread);
- call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), R0, R1);
-
- bind(done);
-}
-
-#endif // INCLUDE_ALL_GCS
-//////////////////////////////////////////////////////////////////////////////////
// Java Expression Stack
--- a/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp Thu Apr 06 22:13:13 2017 +0000
@@ -146,27 +146,6 @@
void set_card(Register card_table_base, Address card_table_addr, Register tmp);
-#if INCLUDE_ALL_GCS
- // G1 pre-barrier.
- // Blows all volatile registers (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR).
- // If store_addr != noreg, then previous value is loaded from [store_addr];
- // in such case store_addr and new_val registers are preserved;
- // otherwise pre_val register is preserved.
- void g1_write_barrier_pre(Register store_addr,
- Register new_val,
- Register pre_val,
- Register tmp1,
- Register tmp2);
-
- // G1 post-barrier.
- // Blows all volatile registers (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR).
- void g1_write_barrier_post(Register store_addr,
- Register new_val,
- Register tmp1,
- Register tmp2,
- Register tmp3);
-#endif // INCLUDE_ALL_GCS
-
void pop_ptr(Register r);
void pop_i(Register r = R0_tos);
#ifdef AARCH64
--- a/hotspot/src/cpu/arm/vm/jniFastGetField_arm.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/jniFastGetField_arm.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, 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
@@ -119,6 +119,14 @@
__ ldr_s32(Rsafept_cnt, Address(Rsafepoint_counter_addr));
__ tbnz(Rsafept_cnt, 0, slow_case);
+#ifdef AARCH64
+ // If mask changes we need to ensure that the inverse is still encodable as an immediate
+ STATIC_ASSERT(JNIHandles::weak_tag_mask == 1);
+ __ andr(R1, R1, ~JNIHandles::weak_tag_mask);
+#else
+ __ bic(R1, R1, JNIHandles::weak_tag_mask);
+#endif
+
if (os::is_MP()) {
// Address dependency restricts memory access ordering. It's cheaper than explicit LoadLoad barrier
__ andr(Rtmp1, Rsafept_cnt, (unsigned)1);
--- a/hotspot/src/cpu/arm/vm/macroAssembler_arm.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/macroAssembler_arm.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, 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
@@ -2211,6 +2211,219 @@
b(done, eq);
}
+
+void MacroAssembler::resolve_jobject(Register value,
+ Register tmp1,
+ Register tmp2) {
+ assert_different_registers(value, tmp1, tmp2);
+ Label done, not_weak;
+ cbz(value, done); // Use NULL as-is.
+ STATIC_ASSERT(JNIHandles::weak_tag_mask == 1u);
+ tbz(value, 0, not_weak); // Test for jweak tag.
+ // Resolve jweak.
+ ldr(value, Address(value, -JNIHandles::weak_tag_value));
+ verify_oop(value);
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) {
+ g1_write_barrier_pre(noreg, // store_addr
+ noreg, // new_val
+ value, // pre_val
+ tmp1, // tmp1
+ tmp2); // tmp2
+ }
+#endif // INCLUDE_ALL_GCS
+ b(done);
+ bind(not_weak);
+ // Resolve (untagged) jobject.
+ ldr(value, Address(value));
+ verify_oop(value);
+ bind(done);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////
+
+#if INCLUDE_ALL_GCS
+
+// G1 pre-barrier.
+// Blows all volatile registers (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR).
+// If store_addr != noreg, then previous value is loaded from [store_addr];
+// in such case store_addr and new_val registers are preserved;
+// otherwise pre_val register is preserved.
+void MacroAssembler::g1_write_barrier_pre(Register store_addr,
+ Register new_val,
+ Register pre_val,
+ Register tmp1,
+ Register tmp2) {
+ Label done;
+ Label runtime;
+
+ if (store_addr != noreg) {
+ assert_different_registers(store_addr, new_val, pre_val, tmp1, tmp2, noreg);
+ } else {
+ assert (new_val == noreg, "should be");
+ assert_different_registers(pre_val, tmp1, tmp2, noreg);
+ }
+
+ Address in_progress(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_active()));
+ Address index(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_index()));
+ Address buffer(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_buf()));
+
+ // Is marking active?
+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "adjust this code");
+ ldrb(tmp1, in_progress);
+ cbz(tmp1, done);
+
+ // Do we need to load the previous value?
+ if (store_addr != noreg) {
+ load_heap_oop(pre_val, Address(store_addr, 0));
+ }
+
+ // Is the previous value null?
+ cbz(pre_val, done);
+
+ // Can we store original value in the thread's buffer?
+ // Is index == 0?
+ // (The index field is typed as size_t.)
+
+ ldr(tmp1, index); // tmp1 := *index_adr
+ ldr(tmp2, buffer);
+
+ subs(tmp1, tmp1, wordSize); // tmp1 := tmp1 - wordSize
+ b(runtime, lt); // If negative, goto runtime
+
+ str(tmp1, index); // *index_adr := tmp1
+
+ // Record the previous value
+ str(pre_val, Address(tmp2, tmp1));
+ b(done);
+
+ bind(runtime);
+
+ // save the live input values
+#ifdef AARCH64
+ if (store_addr != noreg) {
+ raw_push(store_addr, new_val);
+ } else {
+ raw_push(pre_val, ZR);
+ }
+#else
+ if (store_addr != noreg) {
+ // avoid raw_push to support any ordering of store_addr and new_val
+ push(RegisterSet(store_addr) | RegisterSet(new_val));
+ } else {
+ push(pre_val);
+ }
+#endif // AARCH64
+
+ if (pre_val != R0) {
+ mov(R0, pre_val);
+ }
+ mov(R1, Rthread);
+
+ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), R0, R1);
+
+#ifdef AARCH64
+ if (store_addr != noreg) {
+ raw_pop(store_addr, new_val);
+ } else {
+ raw_pop(pre_val, ZR);
+ }
+#else
+ if (store_addr != noreg) {
+ pop(RegisterSet(store_addr) | RegisterSet(new_val));
+ } else {
+ pop(pre_val);
+ }
+#endif // AARCH64
+
+ bind(done);
+}
+
+// G1 post-barrier.
+// Blows all volatile registers (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR).
+void MacroAssembler::g1_write_barrier_post(Register store_addr,
+ Register new_val,
+ Register tmp1,
+ Register tmp2,
+ Register tmp3) {
+
+ Address queue_index(Rthread, in_bytes(JavaThread::dirty_card_queue_offset() +
+ DirtyCardQueue::byte_offset_of_index()));
+ Address buffer(Rthread, in_bytes(JavaThread::dirty_card_queue_offset() +
+ DirtyCardQueue::byte_offset_of_buf()));
+
+ BarrierSet* bs = Universe::heap()->barrier_set();
+ CardTableModRefBS* ct = (CardTableModRefBS*)bs;
+ Label done;
+ Label runtime;
+
+ // Does store cross heap regions?
+
+ eor(tmp1, store_addr, new_val);
+#ifdef AARCH64
+ logical_shift_right(tmp1, tmp1, HeapRegion::LogOfHRGrainBytes);
+ cbz(tmp1, done);
+#else
+ movs(tmp1, AsmOperand(tmp1, lsr, HeapRegion::LogOfHRGrainBytes));
+ b(done, eq);
+#endif
+
+ // crosses regions, storing NULL?
+
+ cbz(new_val, done);
+
+ // storing region crossing non-NULL, is card already dirty?
+ const Register card_addr = tmp1;
+ assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
+
+ mov_address(tmp2, (address)ct->byte_map_base, symbolic_Relocation::card_table_reference);
+ add(card_addr, tmp2, AsmOperand(store_addr, lsr, CardTableModRefBS::card_shift));
+
+ ldrb(tmp2, Address(card_addr));
+ cmp(tmp2, (int)G1SATBCardTableModRefBS::g1_young_card_val());
+ b(done, eq);
+
+ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreLoad), tmp2);
+
+ assert(CardTableModRefBS::dirty_card_val() == 0, "adjust this code");
+ ldrb(tmp2, Address(card_addr));
+ cbz(tmp2, done);
+
+ // storing a region crossing, non-NULL oop, card is clean.
+ // dirty card and log.
+
+ strb(zero_register(tmp2), Address(card_addr));
+
+ ldr(tmp2, queue_index);
+ ldr(tmp3, buffer);
+
+ subs(tmp2, tmp2, wordSize);
+ b(runtime, lt); // go to runtime if now negative
+
+ str(tmp2, queue_index);
+
+ str(card_addr, Address(tmp3, tmp2));
+ b(done);
+
+ bind(runtime);
+
+ if (card_addr != R0) {
+ mov(R0, card_addr);
+ }
+ mov(R1, Rthread);
+ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), R0, R1);
+
+ bind(done);
+}
+
+#endif // INCLUDE_ALL_GCS
+
+//////////////////////////////////////////////////////////////////////////////////
+
#ifdef AARCH64
void MacroAssembler::load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed) {
--- a/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp Thu Apr 06 22:13:13 2017 +0000
@@ -401,6 +401,29 @@
void biased_locking_enter_with_cas(Register obj_reg, Register old_mark_reg, Register new_mark_reg,
Register tmp, Label& slow_case, int* counter_addr);
+ void resolve_jobject(Register value, Register tmp1, Register tmp2);
+
+#if INCLUDE_ALL_GCS
+ // G1 pre-barrier.
+ // Blows all volatile registers (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR).
+ // If store_addr != noreg, then previous value is loaded from [store_addr];
+ // in such case store_addr and new_val registers are preserved;
+ // otherwise pre_val register is preserved.
+ void g1_write_barrier_pre(Register store_addr,
+ Register new_val,
+ Register pre_val,
+ Register tmp1,
+ Register tmp2);
+
+ // G1 post-barrier.
+ // Blows all volatile registers (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR).
+ void g1_write_barrier_post(Register store_addr,
+ Register new_val,
+ Register tmp1,
+ Register tmp2,
+ Register tmp3);
+#endif // INCLUDE_ALL_GCS
+
#ifndef AARCH64
void nop() {
mov(R0, R0);
--- a/hotspot/src/cpu/arm/vm/sharedRuntime_arm.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/sharedRuntime_arm.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, 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
@@ -1732,14 +1732,7 @@
case T_FLOAT : // fall through
case T_DOUBLE : /* nothing to do */ break;
case T_OBJECT : // fall through
- case T_ARRAY : {
- Label L;
- __ cbz(R0, L);
- __ ldr(R0, Address(R0));
- __ verify_oop(R0);
- __ bind(L);
- break;
- }
+ case T_ARRAY : break; // See JNIHandles::resolve below
default:
ShouldNotReachHere();
}
@@ -1748,13 +1741,14 @@
if (CheckJNICalls) {
__ str(__ zero_register(Rtemp), Address(Rthread, JavaThread::pending_jni_exception_check_fn_offset()));
}
+#endif // AARCH64
- // Unhandle the result
+ // Unbox oop result, e.g. JNIHandles::resolve value in R0.
if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
- __ cmp(R0, 0);
- __ ldr(R0, Address(R0), ne);
+ __ resolve_jobject(R0, // value
+ Rtemp, // tmp1
+ R1_tmp); // tmp2
}
-#endif // AARCH64
// Any exception pending?
__ ldr(Rtemp, Address(Rthread, Thread::pending_exception_offset()));
--- a/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1237,28 +1237,25 @@
__ str(__ zero_register(Rtemp), Address(Rthread, JavaThread::pending_jni_exception_check_fn_offset()));
}
- // Unbox if the result is non-zero object
+ // Unbox oop result, e.g. JNIHandles::resolve result if it's an oop.
+ {
+ Label Lnot_oop;
#ifdef AARCH64
- {
- Label L, Lnull;
__ mov_slow(Rtemp, AbstractInterpreter::result_handler(T_OBJECT));
__ cmp(Rresult_handler, Rtemp);
- __ b(L, ne);
- __ cbz(Rsaved_result, Lnull);
- __ ldr(Rsaved_result, Address(Rsaved_result));
- __ bind(Lnull);
- // Store oop on the stack for GC
- __ str(Rsaved_result, Address(FP, frame::interpreter_frame_oop_temp_offset * wordSize));
- __ bind(L);
+ __ b(Lnot_oop, ne);
+#else // !AARCH64
+ // For ARM32, Rresult_handler is -1 for oop result, 0 otherwise.
+ __ cbz(Rresult_handler, Lnot_oop);
+#endif // !AARCH64
+ Register value = AARCH64_ONLY(Rsaved_result) NOT_AARCH64(Rsaved_result_lo);
+ __ resolve_jobject(value, // value
+ Rtemp, // tmp1
+ R1_tmp); // tmp2
+ // Store resolved result in frame for GC visibility.
+ __ str(value, Address(FP, frame::interpreter_frame_oop_temp_offset * wordSize));
+ __ bind(Lnot_oop);
}
-#else
- __ tst(Rsaved_result_lo, Rresult_handler);
- __ ldr(Rsaved_result_lo, Address(Rsaved_result_lo), ne);
-
- // Store oop on the stack for GC
- __ cmp(Rresult_handler, 0);
- __ str(Rsaved_result_lo, Address(FP, frame::interpreter_frame_oop_temp_offset * wordSize), ne);
-#endif // AARCH64
#ifdef AARCH64
// Restore SP (drop native parameters area), to keep SP in sync with extended_sp in frame
--- a/hotspot/src/cpu/ppc/vm/frame_ppc.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/ppc/vm/frame_ppc.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017 SAP SE. 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
@@ -171,10 +171,7 @@
switch (method->result_type()) {
case T_OBJECT:
case T_ARRAY: {
- oop* obj_p = *(oop**)lresult;
- oop obj = (obj_p == NULL) ? (oop)NULL : *obj_p;
- assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check");
- *oop_result = obj;
+ *oop_result = JNIHandles::resolve(*(jobject*)lresult);
break;
}
// We use std/stfd to store the values.
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -3033,6 +3033,34 @@
stbx(R0, Rtmp, Robj);
}
+// Kills R31 if value is a volatile register.
+void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp2, bool needs_frame) {
+ Label done;
+ cmpdi(CCR0, value, 0);
+ beq(CCR0, done); // Use NULL as-is.
+
+ clrrdi(tmp1, value, JNIHandles::weak_tag_size);
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) { andi_(tmp2, value, JNIHandles::weak_tag_mask); }
+#endif
+ ld(value, 0, tmp1); // Resolve (untagged) jobject.
+
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) {
+ Label not_weak;
+ beq(CCR0, not_weak); // Test for jweak tag.
+ verify_oop(value);
+ g1_write_barrier_pre(noreg, // obj
+ noreg, // offset
+ value, // pre_val
+ tmp1, tmp2, needs_frame);
+ bind(not_weak);
+ }
+#endif // INCLUDE_ALL_GCS
+ verify_oop(value);
+ bind(done);
+}
+
#if INCLUDE_ALL_GCS
// General G1 pre-barrier generator.
// Goal: record the previous value if it is not null.
@@ -3094,7 +3122,7 @@
bind(runtime);
- // VM call need frame to access(write) O register.
+ // May need to preserve LR. Also needed if current frame is not compatible with C calling convention.
if (needs_frame) {
save_LR_CR(Rtmp1);
push_frame_reg_args(0, Rtmp2);
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp Thu Apr 06 22:13:13 2017 +0000
@@ -649,6 +649,8 @@
void card_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp);
void card_table_write(jbyte* byte_map_base, Register Rtmp, Register Robj);
+ void resolve_jobject(Register value, Register tmp1, Register tmp2, bool needs_frame);
+
#if INCLUDE_ALL_GCS
// General G1 pre-barrier generator.
void g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val,
--- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017 SAP SE. 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
@@ -2477,16 +2477,11 @@
__ reset_last_Java_frame();
- // Unpack oop result.
+ // Unbox oop result, e.g. JNIHandles::resolve value.
// --------------------------------------------------------------------------
if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
- Label skip_unboxing;
- __ cmpdi(CCR0, R3_RET, 0);
- __ beq(CCR0, skip_unboxing);
- __ ld(R3_RET, 0, R3_RET);
- __ bind(skip_unboxing);
- __ verify_oop(R3_RET);
+ __ resolve_jobject(R3_RET, r_temp_1, r_temp_2, /* needs_frame */ false); // kills R31
}
if (CheckJNICalls) {
--- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -401,11 +401,8 @@
case T_LONG:
break;
case T_OBJECT:
- // unbox result if not null
- __ cmpdi(CCR0, R3_RET, 0);
- __ beq(CCR0, done);
- __ ld(R3_RET, 0, R3_RET);
- __ verify_oop(R3_RET);
+ // JNIHandles::resolve result.
+ __ resolve_jobject(R3_RET, R11_scratch1, R12_scratch2, /* needs_frame */ true); // kills R31
break;
case T_FLOAT:
break;
--- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -3450,6 +3450,34 @@
z_mvi(0, store_addr, 0); // Store byte 0.
}
+void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp2) {
+ NearLabel Ldone;
+ z_ltgr(tmp1, value);
+ z_bre(Ldone); // Use NULL result as-is.
+
+ z_nill(value, ~JNIHandles::weak_tag_mask);
+ z_lg(value, 0, value); // Resolve (untagged) jobject.
+
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) {
+ NearLabel Lnot_weak;
+ z_tmll(tmp1, JNIHandles::weak_tag_mask); // Test for jweak tag.
+ z_braz(Lnot_weak);
+ verify_oop(value);
+ g1_write_barrier_pre(noreg /* obj */,
+ noreg /* offset */,
+ value /* pre_val */,
+ noreg /* val */,
+ tmp1 /* tmp1 */,
+ tmp2 /* tmp2 */,
+ true /* pre_val_needed */);
+ bind(Lnot_weak);
+ }
+#endif // INCLUDE_ALL_GCS
+ verify_oop(value);
+ bind(Ldone);
+}
+
#if INCLUDE_ALL_GCS
//------------------------------------------------------
--- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp Thu Apr 06 22:13:13 2017 +0000
@@ -726,6 +726,8 @@
// Write to card table for modification at store_addr - register is destroyed afterwards.
void card_write_barrier_post(Register store_addr, Register tmp);
+ void resolve_jobject(Register value, Register tmp1, Register tmp2);
+
#if INCLUDE_ALL_GCS
// General G1 pre-barrier generator.
// Purpose: record the previous value if it is not null.
--- a/hotspot/src/cpu/s390/vm/sharedRuntime_s390.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/s390/vm/sharedRuntime_s390.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017 SAP SE. 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
@@ -2272,13 +2272,9 @@
__ reset_last_Java_frame();
- // Unpack oop result
+ // Unpack oop result, e.g. JNIHandles::resolve result.
if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
- NearLabel L;
- __ compare64_and_branch(Z_RET, (RegisterOrConstant)0L, Assembler::bcondEqual, L);
- __ z_lg(Z_RET, 0, Z_RET);
- __ bind(L);
- __ verify_oop(Z_RET);
+ __ resolve_jobject(Z_RET, /* tmp1 */ Z_R13, /* tmp2 */ Z_R7);
}
if (CheckJNICalls) {
--- a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1692,14 +1692,11 @@
// from the jni handle to z_ijava_state.oop_temp. This is
// necessary, because we reset the jni handle block below.
// NOTE: frame::interpreter_frame_result() depends on this, too.
- { NearLabel no_oop_result, store_oop_result;
+ { NearLabel no_oop_result;
__ load_absolute_address(Z_R1, AbstractInterpreter::result_handler(T_OBJECT));
__ compareU64_and_branch(Z_R1, Rresult_handler, Assembler::bcondNotEqual, no_oop_result);
- __ compareU64_and_branch(Rlresult, (intptr_t)0L, Assembler::bcondEqual, store_oop_result);
- __ z_lg(Rlresult, 0, Rlresult); // unbox
- __ bind(store_oop_result);
+ __ resolve_jobject(Rlresult, /* tmp1 */ Rmethod, /* tmp2 */ Z_R1);
__ z_stg(Rlresult, oop_tmp_offset, Z_fp);
- __ verify_oop(Rlresult);
__ bind(no_oop_result);
}
--- a/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -68,6 +68,7 @@
__ andcc (G4, 1, G0);
__ br (Assembler::notZero, false, Assembler::pn, label1);
__ delayed()->srl (O2, 2, O4);
+ __ andn (O1, JNIHandles::weak_tag_mask, O1);
__ ld_ptr (O1, 0, O5);
assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
@@ -147,6 +148,7 @@
__ andcc (G4, 1, G0);
__ br (Assembler::notZero, false, Assembler::pn, label1);
__ delayed()->srl (O2, 2, O4);
+ __ andn (O1, JNIHandles::weak_tag_mask, O1);
__ ld_ptr (O1, 0, O5);
__ add (O5, O4, O5);
@@ -219,6 +221,7 @@
__ andcc (G4, 1, G0);
__ br (Assembler::notZero, false, Assembler::pn, label1);
__ delayed()->srl (O2, 2, O4);
+ __ andn (O1, JNIHandles::weak_tag_mask, O1);
__ ld_ptr (O1, 0, O5);
assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -2754,15 +2754,30 @@
__ verify_thread(); // G2_thread must be correct
__ reset_last_Java_frame();
- // Unpack oop result
+ // Unbox oop result, e.g. JNIHandles::resolve value in I0.
if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
- Label L;
- __ addcc(G0, I0, G0);
- __ brx(Assembler::notZero, true, Assembler::pt, L);
- __ delayed()->ld_ptr(I0, 0, I0);
- __ mov(G0, I0);
- __ bind(L);
- __ verify_oop(I0);
+ Label done, not_weak;
+ __ br_null(I0, false, Assembler::pn, done); // Use NULL as-is.
+ __ delayed()->andcc(I0, JNIHandles::weak_tag_mask, G0); // Test for jweak
+ __ brx(Assembler::zero, true, Assembler::pt, not_weak);
+ __ delayed()->ld_ptr(I0, 0, I0); // Maybe resolve (untagged) jobject.
+ // Resolve jweak.
+ __ ld_ptr(I0, -JNIHandles::weak_tag_value, I0);
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) {
+ // Copy to O0 because macro doesn't allow pre_val in input reg.
+ __ mov(I0, O0);
+ __ g1_write_barrier_pre(noreg /* obj */,
+ noreg /* index */,
+ 0 /* offset */,
+ O0 /* pre_val */,
+ G3_scratch /* tmp */,
+ true /* preserve_o_regs */);
+ }
+#endif // INCLUDE_ALL_GCS
+ __ bind(not_weak);
+ __ verify_oop(I0);
+ __ bind(done);
}
if (CheckJNICalls) {
--- a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1514,11 +1514,23 @@
__ set((intptr_t)AbstractInterpreter::result_handler(T_OBJECT), G3_scratch);
__ cmp_and_brx_short(G3_scratch, Lscratch, Assembler::notEqual, Assembler::pt, no_oop);
- __ addcc(G0, O0, O0);
- __ brx(Assembler::notZero, true, Assembler::pt, store_result); // if result is not NULL:
- __ delayed()->ld_ptr(O0, 0, O0); // unbox it
- __ mov(G0, O0);
-
+ // Unbox oop result, e.g. JNIHandles::resolve value in O0.
+ __ br_null(O0, false, Assembler::pn, store_result); // Use NULL as-is.
+ __ delayed()->andcc(O0, JNIHandles::weak_tag_mask, G0); // Test for jweak
+ __ brx(Assembler::zero, true, Assembler::pt, store_result);
+ __ delayed()->ld_ptr(O0, 0, O0); // Maybe resolve (untagged) jobject.
+ // Resolve jweak.
+ __ ld_ptr(O0, -JNIHandles::weak_tag_value, O0);
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) {
+ __ g1_write_barrier_pre(noreg /* obj */,
+ noreg /* index */,
+ 0 /* offset */,
+ O0 /* pre_val */,
+ G3_scratch /* tmp */,
+ true /* preserve_o_regs */);
+ }
+#endif // INCLUDE_ALL_GCS
__ bind(store_result);
// Store it where gc will look for it and result handler expects it.
__ st_ptr(O0, FP, (frame::interpreter_frame_oop_temp_offset*wordSize) + STACK_BIAS);
--- a/hotspot/src/cpu/x86/vm/jniFastGetField_x86_32.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/x86/vm/jniFastGetField_x86_32.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -85,6 +85,9 @@
__ movptr (rdx, Address(rsp, 2*wordSize)); // obj
}
__ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID
+
+ __ clear_jweak_tag(rdx);
+
__ movptr(rdx, Address(rdx, 0)); // *obj
__ shrptr (rax, 2); // offset
@@ -202,6 +205,9 @@
__ movptr(rdx, Address(rsp, 3*wordSize)); // obj
}
__ movptr(rsi, Address(rsp, 4*wordSize)); // jfieldID
+
+ __ clear_jweak_tag(rdx);
+
__ movptr(rdx, Address(rdx, 0)); // *obj
__ shrptr(rsi, 2); // offset
@@ -291,6 +297,9 @@
__ movptr(rdx, Address(rsp, 2*wordSize)); // obj
}
__ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID
+
+ __ clear_jweak_tag(rdx);
+
__ movptr(rdx, Address(rdx, 0)); // *obj
__ shrptr(rax, 2); // offset
--- a/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -80,6 +80,9 @@
// robj ^ rcounter ^ rcounter == robj
// robj is data dependent on rcounter.
}
+
+ __ clear_jweak_tag(robj);
+
__ movptr(robj, Address(robj, 0)); // *obj
__ mov (roffset, c_rarg2);
__ shrptr(roffset, 2); // offset
@@ -178,6 +181,9 @@
// robj ^ rcounter ^ rcounter == robj
// robj is data dependent on rcounter.
}
+
+ __ clear_jweak_tag(robj);
+
__ movptr(robj, Address(robj, 0)); // *obj
__ mov (roffset, c_rarg2);
__ shrptr(roffset, 2); // offset
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -5129,6 +5129,43 @@
}
+void MacroAssembler::resolve_jobject(Register value,
+ Register thread,
+ Register tmp) {
+ assert_different_registers(value, thread, tmp);
+ Label done, not_weak;
+ testptr(value, value);
+ jcc(Assembler::zero, done); // Use NULL as-is.
+ testptr(value, JNIHandles::weak_tag_mask); // Test for jweak tag.
+ jcc(Assembler::zero, not_weak);
+ // Resolve jweak.
+ movptr(value, Address(value, -JNIHandles::weak_tag_value));
+ verify_oop(value);
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) {
+ g1_write_barrier_pre(noreg /* obj */,
+ value /* pre_val */,
+ thread /* thread */,
+ tmp /* tmp */,
+ true /* tosca_live */,
+ true /* expand_call */);
+ }
+#endif // INCLUDE_ALL_GCS
+ jmp(done);
+ bind(not_weak);
+ // Resolve (untagged) jobject.
+ movptr(value, Address(value, 0));
+ verify_oop(value);
+ bind(done);
+}
+
+void MacroAssembler::clear_jweak_tag(Register possibly_jweak) {
+ const int32_t inverted_jweak_mask = ~static_cast<int32_t>(JNIHandles::weak_tag_mask);
+ STATIC_ASSERT(inverted_jweak_mask == -2); // otherwise check this code
+ // The inverted mask is sign-extended
+ andptr(possibly_jweak, inverted_jweak_mask);
+}
+
//////////////////////////////////////////////////////////////////////////////////
#if INCLUDE_ALL_GCS
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Thu Apr 06 22:13:13 2017 +0000
@@ -297,6 +297,9 @@
void store_check(Register obj); // store check for obj - register is destroyed afterwards
void store_check(Register obj, Address dst); // same as above, dst is exact store location (reg. is destroyed)
+ void resolve_jobject(Register value, Register thread, Register tmp);
+ void clear_jweak_tag(Register possibly_jweak);
+
#if INCLUDE_ALL_GCS
void g1_write_barrier_pre(Register obj,
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -2226,14 +2226,11 @@
__ reset_last_Java_frame(thread, false);
- // Unpack oop result
+ // Unbox oop result, e.g. JNIHandles::resolve value.
if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
- Label L;
- __ cmpptr(rax, (int32_t)NULL_WORD);
- __ jcc(Assembler::equal, L);
- __ movptr(rax, Address(rax, 0));
- __ bind(L);
- __ verify_oop(rax);
+ __ resolve_jobject(rax /* value */,
+ thread /* thread */,
+ rcx /* tmp */);
}
if (CheckJNICalls) {
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -2579,14 +2579,11 @@
__ reset_last_Java_frame(false);
- // Unpack oop result
+ // Unbox oop result, e.g. JNIHandles::resolve value.
if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
- Label L;
- __ testptr(rax, rax);
- __ jcc(Assembler::zero, L);
- __ movptr(rax, Address(rax, 0));
- __ bind(L);
- __ verify_oop(rax);
+ __ resolve_jobject(rax /* value */,
+ r15_thread /* thread */,
+ rcx /* tmp */);
}
if (CheckJNICalls) {
--- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1194,16 +1194,16 @@
// and result handler will pick it up
{
- Label no_oop, store_result;
+ Label no_oop, not_weak, store_result;
__ lea(t, ExternalAddress(AbstractInterpreter::result_handler(T_OBJECT)));
__ cmpptr(t, Address(rbp, frame::interpreter_frame_result_handler_offset*wordSize));
__ jcc(Assembler::notEqual, no_oop);
// retrieve result
__ pop(ltos);
- __ testptr(rax, rax);
- __ jcc(Assembler::zero, store_result);
- __ movptr(rax, Address(rax, 0));
- __ bind(store_result);
+ // Unbox oop result, e.g. JNIHandles::resolve value.
+ __ resolve_jobject(rax /* value */,
+ thread /* thread */,
+ t /* tmp */);
__ movptr(Address(rbp, frame::interpreter_frame_oop_temp_offset*wordSize), rax);
// keep stack depth as expected by pushing oop which will eventually be discarded
__ push(ltos);
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -406,10 +406,12 @@
// oop_temp where the garbage collector can see it before
// we release the handle it might be protected by.
if (handler->result_type() == &ffi_type_pointer) {
- if (result[0])
- istate->set_oop_temp(*(oop *) result[0]);
- else
+ if (result[0] == 0) {
istate->set_oop_temp(NULL);
+ } else {
+ jobject handle = reinterpret_cast<jobject>(result[0]);
+ istate->set_oop_temp(JNIHandles::resolve(handle));
+ }
}
// Reset handle block
--- a/hotspot/src/share/vm/Xusage.txt Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/Xusage.txt Thu Apr 06 22:13:13 2017 +0000
@@ -12,7 +12,7 @@
-Xms<size> set initial Java heap size
-Xmx<size> set maximum Java heap size
-Xss<size> set java thread stack size
- -Xprof output cpu profiling data
+ -Xprof output cpu profiling data (deprecated)
-Xfuture enable strictest checks, anticipating future default
-Xrs reduce use of OS signals by Java/VM (see documentation)
-Xcheck:jni perform additional checks for JNI functions
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1540,7 +1540,7 @@
ciMethod* caller = state()->scope()->method();
ciMethodData* md = caller->method_data_or_null();
ciProfileData* data = md->bci_to_data(invoke_bci);
- if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) {
+ if (data != NULL && (data->is_CallTypeData() || data->is_VirtualCallTypeData())) {
bool has_return = data->is_CallTypeData() ? ((ciCallTypeData*)data)->has_return() : ((ciVirtualCallTypeData*)data)->has_return();
// May not be true in case of an inlined call through a method handle intrinsic.
if (has_return) {
@@ -1758,7 +1758,7 @@
start = has_receiver ? 1 : 0;
if (profile_arguments()) {
ciProfileData* data = method()->method_data()->bci_to_data(bci());
- if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) {
+ if (data != NULL && (data->is_CallTypeData() || data->is_VirtualCallTypeData())) {
n = data->is_CallTypeData() ? data->as_CallTypeData()->number_of_arguments() : data->as_VirtualCallTypeData()->number_of_arguments();
}
}
@@ -4351,7 +4351,7 @@
}
ciMethodData* md = m->method_data_or_null();
ciProfileData* data = md->bci_to_data(invoke_bci);
- if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) {
+ if (data != NULL && (data->is_CallTypeData() || data->is_VirtualCallTypeData())) {
append(new ProfileReturnType(m , invoke_bci, callee, ret));
}
}
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -3262,50 +3262,52 @@
int bci = x->bci_of_invoke();
ciMethodData* md = x->method()->method_data_or_null();
ciProfileData* data = md->bci_to_data(bci);
- if ((data->is_CallTypeData() && data->as_CallTypeData()->has_arguments()) ||
- (data->is_VirtualCallTypeData() && data->as_VirtualCallTypeData()->has_arguments())) {
- ByteSize extra = data->is_CallTypeData() ? CallTypeData::args_data_offset() : VirtualCallTypeData::args_data_offset();
- int base_offset = md->byte_offset_of_slot(data, extra);
- LIR_Opr mdp = LIR_OprFact::illegalOpr;
- ciTypeStackSlotEntries* args = data->is_CallTypeData() ? ((ciCallTypeData*)data)->args() : ((ciVirtualCallTypeData*)data)->args();
-
- Bytecodes::Code bc = x->method()->java_code_at_bci(bci);
- int start = 0;
- int stop = data->is_CallTypeData() ? ((ciCallTypeData*)data)->number_of_arguments() : ((ciVirtualCallTypeData*)data)->number_of_arguments();
- if (x->callee()->is_loaded() && x->callee()->is_static() && Bytecodes::has_receiver(bc)) {
- // first argument is not profiled at call (method handle invoke)
- assert(x->method()->raw_code_at_bci(bci) == Bytecodes::_invokehandle, "invokehandle expected");
- start = 1;
+ if (data != NULL) {
+ if ((data->is_CallTypeData() && data->as_CallTypeData()->has_arguments()) ||
+ (data->is_VirtualCallTypeData() && data->as_VirtualCallTypeData()->has_arguments())) {
+ ByteSize extra = data->is_CallTypeData() ? CallTypeData::args_data_offset() : VirtualCallTypeData::args_data_offset();
+ int base_offset = md->byte_offset_of_slot(data, extra);
+ LIR_Opr mdp = LIR_OprFact::illegalOpr;
+ ciTypeStackSlotEntries* args = data->is_CallTypeData() ? ((ciCallTypeData*)data)->args() : ((ciVirtualCallTypeData*)data)->args();
+
+ Bytecodes::Code bc = x->method()->java_code_at_bci(bci);
+ int start = 0;
+ int stop = data->is_CallTypeData() ? ((ciCallTypeData*)data)->number_of_arguments() : ((ciVirtualCallTypeData*)data)->number_of_arguments();
+ if (x->callee()->is_loaded() && x->callee()->is_static() && Bytecodes::has_receiver(bc)) {
+ // first argument is not profiled at call (method handle invoke)
+ assert(x->method()->raw_code_at_bci(bci) == Bytecodes::_invokehandle, "invokehandle expected");
+ start = 1;
+ }
+ ciSignature* callee_signature = x->callee()->signature();
+ // method handle call to virtual method
+ bool has_receiver = x->callee()->is_loaded() && !x->callee()->is_static() && !Bytecodes::has_receiver(bc);
+ ciSignatureStream callee_signature_stream(callee_signature, has_receiver ? x->callee()->holder() : NULL);
+
+ bool ignored_will_link;
+ ciSignature* signature_at_call = NULL;
+ x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call);
+ ciSignatureStream signature_at_call_stream(signature_at_call);
+
+ // if called through method handle invoke, some arguments may have been popped
+ for (int i = 0; i < stop && i+start < x->nb_profiled_args(); i++) {
+ int off = in_bytes(TypeEntriesAtCall::argument_type_offset(i)) - in_bytes(TypeEntriesAtCall::args_data_offset());
+ ciKlass* exact = profile_type(md, base_offset, off,
+ args->type(i), x->profiled_arg_at(i+start), mdp,
+ !x->arg_needs_null_check(i+start),
+ signature_at_call_stream.next_klass(), callee_signature_stream.next_klass());
+ if (exact != NULL) {
+ md->set_argument_type(bci, i, exact);
+ }
+ }
+ } else {
+#ifdef ASSERT
+ Bytecodes::Code code = x->method()->raw_code_at_bci(x->bci_of_invoke());
+ int n = x->nb_profiled_args();
+ assert(MethodData::profile_parameters() && (MethodData::profile_arguments_jsr292_only() ||
+ (x->inlined() && ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)))),
+ "only at JSR292 bytecodes");
+#endif
}
- ciSignature* callee_signature = x->callee()->signature();
- // method handle call to virtual method
- bool has_receiver = x->callee()->is_loaded() && !x->callee()->is_static() && !Bytecodes::has_receiver(bc);
- ciSignatureStream callee_signature_stream(callee_signature, has_receiver ? x->callee()->holder() : NULL);
-
- bool ignored_will_link;
- ciSignature* signature_at_call = NULL;
- x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call);
- ciSignatureStream signature_at_call_stream(signature_at_call);
-
- // if called through method handle invoke, some arguments may have been popped
- for (int i = 0; i < stop && i+start < x->nb_profiled_args(); i++) {
- int off = in_bytes(TypeEntriesAtCall::argument_type_offset(i)) - in_bytes(TypeEntriesAtCall::args_data_offset());
- ciKlass* exact = profile_type(md, base_offset, off,
- args->type(i), x->profiled_arg_at(i+start), mdp,
- !x->arg_needs_null_check(i+start),
- signature_at_call_stream.next_klass(), callee_signature_stream.next_klass());
- if (exact != NULL) {
- md->set_argument_type(bci, i, exact);
- }
- }
- } else {
-#ifdef ASSERT
- Bytecodes::Code code = x->method()->raw_code_at_bci(x->bci_of_invoke());
- int n = x->nb_profiled_args();
- assert(MethodData::profile_parameters() && (MethodData::profile_arguments_jsr292_only() ||
- (x->inlined() && ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)))),
- "only at JSR292 bytecodes");
-#endif
}
}
}
@@ -3396,24 +3398,26 @@
int bci = x->bci_of_invoke();
ciMethodData* md = x->method()->method_data_or_null();
ciProfileData* data = md->bci_to_data(bci);
- assert(data->is_CallTypeData() || data->is_VirtualCallTypeData(), "wrong profile data type");
- ciReturnTypeEntry* ret = data->is_CallTypeData() ? ((ciCallTypeData*)data)->ret() : ((ciVirtualCallTypeData*)data)->ret();
- LIR_Opr mdp = LIR_OprFact::illegalOpr;
-
- bool ignored_will_link;
- ciSignature* signature_at_call = NULL;
- x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call);
-
- // The offset within the MDO of the entry to update may be too large
- // to be used in load/store instructions on some platforms. So have
- // profile_type() compute the address of the profile in a register.
- ciKlass* exact = profile_type(md, md->byte_offset_of_slot(data, ret->type_offset()), 0,
- ret->type(), x->ret(), mdp,
- !x->needs_null_check(),
- signature_at_call->return_type()->as_klass(),
- x->callee()->signature()->return_type()->as_klass());
- if (exact != NULL) {
- md->set_return_type(bci, exact);
+ if (data != NULL) {
+ assert(data->is_CallTypeData() || data->is_VirtualCallTypeData(), "wrong profile data type");
+ ciReturnTypeEntry* ret = data->is_CallTypeData() ? ((ciCallTypeData*)data)->ret() : ((ciVirtualCallTypeData*)data)->ret();
+ LIR_Opr mdp = LIR_OprFact::illegalOpr;
+
+ bool ignored_will_link;
+ ciSignature* signature_at_call = NULL;
+ x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call);
+
+ // The offset within the MDO of the entry to update may be too large
+ // to be used in load/store instructions on some platforms. So have
+ // profile_type() compute the address of the profile in a register.
+ ciKlass* exact = profile_type(md, md->byte_offset_of_slot(data, ret->type_offset()), 0,
+ ret->type(), x->ret(), mdp,
+ !x->needs_null_check(),
+ signature_at_call->return_type()->as_klass(),
+ x->callee()->signature()->return_type()->as_klass());
+ if (exact != NULL) {
+ md->set_return_type(bci, exact);
+ }
}
}
--- a/hotspot/src/share/vm/ci/ciMethodData.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/ci/ciMethodData.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -408,11 +408,13 @@
MethodData* mdo = get_MethodData();
if (mdo != NULL) {
ProfileData* data = mdo->bci_to_data(bci);
- if (data->is_CallTypeData()) {
- data->as_CallTypeData()->set_argument_type(i, k->get_Klass());
- } else {
- assert(data->is_VirtualCallTypeData(), "no arguments!");
- data->as_VirtualCallTypeData()->set_argument_type(i, k->get_Klass());
+ if (data != NULL) {
+ if (data->is_CallTypeData()) {
+ data->as_CallTypeData()->set_argument_type(i, k->get_Klass());
+ } else {
+ assert(data->is_VirtualCallTypeData(), "no arguments!");
+ data->as_VirtualCallTypeData()->set_argument_type(i, k->get_Klass());
+ }
}
}
}
@@ -430,11 +432,13 @@
MethodData* mdo = get_MethodData();
if (mdo != NULL) {
ProfileData* data = mdo->bci_to_data(bci);
- if (data->is_CallTypeData()) {
- data->as_CallTypeData()->set_return_type(k->get_Klass());
- } else {
- assert(data->is_VirtualCallTypeData(), "no arguments!");
- data->as_VirtualCallTypeData()->set_return_type(k->get_Klass());
+ if (data != NULL) {
+ if (data->is_CallTypeData()) {
+ data->as_CallTypeData()->set_return_type(k->get_Klass());
+ } else {
+ assert(data->is_VirtualCallTypeData(), "no arguments!");
+ data->as_VirtualCallTypeData()->set_return_type(k->get_Klass());
+ }
}
}
}
--- a/hotspot/src/share/vm/classfile/moduleEntry.hpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/classfile/moduleEntry.hpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -36,8 +36,8 @@
#include "utilities/ostream.hpp"
#define UNNAMED_MODULE "Unnamed Module"
-#define JAVAPKG "java/"
-#define JAVAPKG_LEN 5
+#define JAVAPKG "java"
+#define JAVAPKG_LEN 4
#define JAVA_BASE_NAME "java.base"
class ModuleClosure;
--- a/hotspot/src/share/vm/classfile/modules.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/classfile/modules.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -319,7 +319,8 @@
// Only modules defined to either the boot or platform class loader, can define a "java/" package.
if (!h_loader.is_null() &&
!SystemDictionary::is_platform_class_loader(h_loader()) &&
- strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
+ (strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0 &&
+ (package_name[JAVAPKG_LEN] == '/' || package_name[JAVAPKG_LEN] == '\0'))) {
const char* class_loader_name = SystemDictionary::loader_name(h_loader());
size_t pkg_len = strlen(package_name);
char* pkg_name = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, pkg_len);
@@ -704,7 +705,8 @@
// Only modules defined to either the boot or platform class loader, can define a "java/" package.
if (!loader_data->is_the_null_class_loader_data() &&
!loader_data->is_platform_class_loader_data() &&
- strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
+ (strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0 &&
+ (package_name[JAVAPKG_LEN] == '/' || package_name[JAVAPKG_LEN] == '\0'))) {
const char* class_loader_name = SystemDictionary::loader_name(loader_data);
size_t pkg_len = strlen(package_name);
char* pkg_name = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, pkg_len);
--- a/hotspot/src/share/vm/classfile/stringTable.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/classfile/stringTable.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -96,10 +96,14 @@
// Pick hashing algorithm
unsigned int StringTable::hash_string(const jchar* s, int len) {
- return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
+ return use_alternate_hashcode() ? alt_hash_string(s, len) :
java_lang_String::hash_code(s, len);
}
+unsigned int StringTable::alt_hash_string(const jchar* s, int len) {
+ return AltHashing::murmur3_32(seed(), s, len);
+}
+
unsigned int StringTable::hash_string(oop string) {
EXCEPTION_MARK;
if (string == NULL) {
@@ -117,11 +121,10 @@
}
}
-oop StringTable::lookup_shared(jchar* name, int len) {
- // java_lang_String::hash_code() was used to compute hash values in the shared table. Don't
- // use the hash value from StringTable::hash_string() as it might use alternate hashcode.
- return _shared_table.lookup((const char*)name,
- java_lang_String::hash_code(name, len), len);
+oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
+ assert(hash == java_lang_String::hash_code(name, len),
+ "hash must be computed using java_lang_String::hash_code");
+ return _shared_table.lookup((const char*)name, hash, len);
}
oop StringTable::lookup_in_main_table(int index, jchar* name,
@@ -156,7 +159,7 @@
unsigned int hashValue;
int index;
if (use_alternate_hashcode()) {
- hashValue = hash_string(name, len);
+ hashValue = alt_hash_string(name, len);
index = hash_to_index(hashValue);
} else {
hashValue = hashValue_arg;
@@ -199,12 +202,15 @@
}
oop StringTable::lookup(jchar* name, int len) {
- oop string = lookup_shared(name, len);
+ // shared table always uses java_lang_String::hash_code
+ unsigned int hash = java_lang_String::hash_code(name, len);
+ oop string = lookup_shared(name, len, hash);
if (string != NULL) {
return string;
}
-
- unsigned int hash = hash_string(name, len);
+ if (use_alternate_hashcode()) {
+ hash = alt_hash_string(name, len);
+ }
int index = the_table()->hash_to_index(hash);
string = the_table()->lookup_in_main_table(index, name, len, hash);
@@ -215,12 +221,15 @@
oop StringTable::intern(Handle string_or_null, jchar* name,
int len, TRAPS) {
- oop found_string = lookup_shared(name, len);
+ // shared table always uses java_lang_String::hash_code
+ unsigned int hashValue = java_lang_String::hash_code(name, len);
+ oop found_string = lookup_shared(name, len, hashValue);
if (found_string != NULL) {
return found_string;
}
-
- unsigned int hashValue = hash_string(name, len);
+ if (use_alternate_hashcode()) {
+ hashValue = alt_hash_string(name, len);
+ }
int index = the_table()->hash_to_index(hashValue);
found_string = the_table()->lookup_in_main_table(index, name, len, hashValue);
--- a/hotspot/src/share/vm/classfile/stringTable.hpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/classfile/stringTable.hpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -56,7 +56,7 @@
unsigned int hashValue, TRAPS);
oop lookup_in_main_table(int index, jchar* chars, int length, unsigned int hashValue);
- static oop lookup_shared(jchar* name, int len);
+ static oop lookup_shared(jchar* name, int len, unsigned int hash);
// Apply the give oop closure to the entries to the buckets
// in the range [start_idx, end_idx).
@@ -65,6 +65,13 @@
// in the range [start_idx, end_idx).
static void buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, int* processed, int* removed);
+ // Hashing algorithm, used as the hash value used by the
+ // StringTable for bucket selection and comparison (stored in the
+ // HashtableEntry structures). This is used in the String.intern() method.
+ static unsigned int hash_string(const jchar* s, int len);
+ static unsigned int hash_string(oop string);
+ static unsigned int alt_hash_string(const jchar* s, int len);
+
StringTable() : RehashableHashtable<oop, mtSymbol>((int)StringTableSize,
sizeof (HashtableEntry<oop, mtSymbol>)) {}
@@ -109,12 +116,6 @@
}
static void possibly_parallel_oops_do(OopClosure* f);
- // Hashing algorithm, used as the hash value used by the
- // StringTable for bucket selection and comparison (stored in the
- // HashtableEntry structures). This is used in the String.intern() method.
- static unsigned int hash_string(const jchar* s, int len);
- static unsigned int hash_string(oop string);
-
// Internal test.
static void test_alt_hash() PRODUCT_RETURN;
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -561,6 +561,7 @@
template(int_StringBuffer_signature, "(I)Ljava/lang/StringBuffer;") \
template(char_StringBuffer_signature, "(C)Ljava/lang/StringBuffer;") \
template(int_String_signature, "(I)Ljava/lang/String;") \
+ template(boolean_boolean_int_signature, "(ZZ)I") \
template(codesource_permissioncollection_signature, "(Ljava/security/CodeSource;Ljava/security/PermissionCollection;)V") \
/* signature symbols needed by intrinsics */ \
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, template, VM_ALIAS_IGNORE) \
--- a/hotspot/src/share/vm/compiler/compilerDefinitions.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/compiler/compilerDefinitions.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -100,7 +100,9 @@
FLAG_SET_ERGO(size_t, MetaspaceSize, 12*M);
}
if (FLAG_IS_DEFAULT(MaxRAM)) {
- FLAG_SET_ERGO(uint64_t, MaxRAM, 1ULL*G);
+ // Do not use FLAG_SET_ERGO to update MaxRAM, as this will impact
+ // heap setting done based on available phys_mem (see Arguments::set_heap_size).
+ FLAG_SET_DEFAULT(MaxRAM, 1ULL*G);
}
if (FLAG_IS_DEFAULT(CompileThreshold)) {
FLAG_SET_ERGO(intx, CompileThreshold, 1500);
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -2417,22 +2417,24 @@
void InstanceKlass::check_prohibited_package(Symbol* class_name,
Handle class_loader,
TRAPS) {
- ResourceMark rm(THREAD);
if (!class_loader.is_null() &&
!SystemDictionary::is_platform_class_loader(class_loader()) &&
- class_name != NULL &&
- strncmp(class_name->as_C_string(), JAVAPKG, JAVAPKG_LEN) == 0) {
- TempNewSymbol pkg_name = InstanceKlass::package_from_name(class_name, CHECK);
- assert(pkg_name != NULL, "Error in parsing package name starting with 'java/'");
- char* name = pkg_name->as_C_string();
- const char* class_loader_name = SystemDictionary::loader_name(class_loader());
- StringUtils::replace_no_expand(name, "/", ".");
- const char* msg_text1 = "Class loader (instance of): ";
- const char* msg_text2 = " tried to load prohibited package name: ";
- size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(name) + 1;
- char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
- jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, name);
- THROW_MSG(vmSymbols::java_lang_SecurityException(), message);
+ class_name != NULL) {
+ ResourceMark rm(THREAD);
+ char* name = class_name->as_C_string();
+ if (strncmp(name, JAVAPKG, JAVAPKG_LEN) == 0 && name[JAVAPKG_LEN] == '/') {
+ TempNewSymbol pkg_name = InstanceKlass::package_from_name(class_name, CHECK);
+ assert(pkg_name != NULL, "Error in parsing package name starting with 'java/'");
+ name = pkg_name->as_C_string();
+ const char* class_loader_name = SystemDictionary::loader_name(class_loader());
+ StringUtils::replace_no_expand(name, "/", ".");
+ const char* msg_text1 = "Class loader (instance of): ";
+ const char* msg_text2 = " tried to load prohibited package name: ";
+ size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(name) + 1;
+ char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
+ jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, name);
+ THROW_MSG(vmSymbols::java_lang_SecurityException(), message);
+ }
}
return;
}
--- a/hotspot/src/share/vm/opto/arraycopynode.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/opto/arraycopynode.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -225,7 +225,6 @@
Node* dest = in(ArrayCopyNode::Dest);
const Type* src_type = phase->type(src);
const TypeAryPtr* ary_src = src_type->isa_aryptr();
- assert(ary_src != NULL, "should be an array copy/clone");
if (is_arraycopy() || is_copyofrange() || is_copyof()) {
const Type* dest_type = phase->type(dest);
@@ -286,7 +285,8 @@
copy_type = dest_elem;
} else {
- assert (is_clonebasic(), "should be");
+ assert(ary_src != NULL, "should be a clone");
+ assert(is_clonebasic(), "should be");
disjoint_bases = true;
assert(src->is_AddP(), "should be base + off");
--- a/hotspot/src/share/vm/opto/callnode.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/opto/callnode.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -784,8 +784,8 @@
}
// May modify (by reflection) if an boxing object is passed
// as argument or returned.
- if (returns_pointer() && (proj_out(TypeFunc::Parms) != NULL)) {
- Node* proj = proj_out(TypeFunc::Parms);
+ Node* proj = returns_pointer() ? proj_out(TypeFunc::Parms) : NULL;
+ if (proj != NULL) {
const TypeInstPtr* inst_t = phase->type(proj)->isa_instptr();
if ((inst_t != NULL) && (!inst_t->klass_is_exact() ||
(inst_t->klass() == boxing_klass))) {
--- a/hotspot/src/share/vm/opto/castnode.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/opto/castnode.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -225,7 +225,10 @@
}
// Similar to ConvI2LNode::Ideal() for the same reasons
- if (can_reshape && !phase->C->major_progress()) {
+ // Do not narrow the type of range check dependent CastIINodes to
+ // avoid corruption of the graph if a CastII is replaced by TOP but
+ // the corresponding range check is not removed.
+ if (can_reshape && !_range_check_dependency && !phase->C->major_progress()) {
const TypeInt* this_type = this->type()->is_int();
const TypeInt* in_type = phase->type(in(1))->isa_int();
if (in_type != NULL && this_type != NULL &&
--- a/hotspot/src/share/vm/opto/convertnode.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/opto/convertnode.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -294,8 +294,7 @@
}
#ifdef _LP64
- // Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y)) or
- // ConvI2L(CastII(AddI(x, y))) to AddL(ConvI2L(CastII(x)), ConvI2L(CastII(y))),
+ // Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y))
// but only if x and y have subranges that cannot cause 32-bit overflow,
// under the assumption that x+y is in my own subrange this->type().
@@ -319,13 +318,6 @@
Node* z = in(1);
int op = z->Opcode();
- Node* ctrl = NULL;
- if (op == Op_CastII && z->as_CastII()->has_range_check()) {
- // Skip CastII node but save control dependency
- ctrl = z->in(0);
- z = z->in(1);
- op = z->Opcode();
- }
if (op == Op_AddI || op == Op_SubI) {
Node* x = z->in(1);
Node* y = z->in(2);
@@ -385,8 +377,8 @@
}
assert(rxlo == (int)rxlo && rxhi == (int)rxhi, "x should not overflow");
assert(rylo == (int)rylo && ryhi == (int)ryhi, "y should not overflow");
- Node* cx = phase->C->constrained_convI2L(phase, x, TypeInt::make(rxlo, rxhi, widen), ctrl);
- Node* cy = phase->C->constrained_convI2L(phase, y, TypeInt::make(rylo, ryhi, widen), ctrl);
+ Node* cx = phase->C->constrained_convI2L(phase, x, TypeInt::make(rxlo, rxhi, widen), NULL);
+ Node* cy = phase->C->constrained_convI2L(phase, y, TypeInt::make(rylo, ryhi, widen), NULL);
switch (op) {
case Op_AddI: return new AddLNode(cx, cy);
case Op_SubI: return new SubLNode(cx, cy);
--- a/hotspot/src/share/vm/opto/ifnode.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/opto/ifnode.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1465,8 +1465,9 @@
// be skipped. For example, range check predicate has two checks
// for lower and upper bounds.
ProjNode* unc_proj = proj_out(1 - prev_dom->as_Proj()->_con)->as_Proj();
- if (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate) != NULL)
- prev_dom = idom;
+ if ((unc_proj != NULL) && (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate) != NULL)) {
+ prev_dom = idom;
+ }
// Now walk the current IfNode's projections.
// Loop ends when 'this' has no more uses.
--- a/hotspot/src/share/vm/opto/lcm.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/opto/lcm.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -254,10 +254,12 @@
const TypePtr *adr_type = NULL; // Do not need this return value here
const Node* base = mach->get_base_and_disp(offset, adr_type);
if (base == NULL || base == NodeSentinel) {
- // Narrow oop address doesn't have base, only index
- if( val->bottom_type()->isa_narrowoop() &&
- MacroAssembler::needs_explicit_null_check(offset) )
- continue; // Give up if offset is beyond page size
+ // Narrow oop address doesn't have base, only index.
+ // Give up if offset is beyond page size or if heap base is not protected.
+ if (val->bottom_type()->isa_narrowoop() &&
+ (MacroAssembler::needs_explicit_null_check(offset) ||
+ !Universe::narrow_oop_use_implicit_null_checks()))
+ continue;
// cannot reason about it; is probably not implicit null exception
} else {
const TypePtr* tptr;
@@ -269,12 +271,17 @@
// only regular oops are expected here
tptr = base->bottom_type()->is_ptr();
}
- // Give up if offset is not a compile-time constant
- if( offset == Type::OffsetBot || tptr->_offset == Type::OffsetBot )
+ // Give up if offset is not a compile-time constant.
+ if (offset == Type::OffsetBot || tptr->_offset == Type::OffsetBot)
continue;
offset += tptr->_offset; // correct if base is offseted
- if( MacroAssembler::needs_explicit_null_check(offset) )
- continue; // Give up is reference is beyond 4K page size
+ // Give up if reference is beyond page size.
+ if (MacroAssembler::needs_explicit_null_check(offset))
+ continue;
+ // Give up if base is a decode node and the heap base is not protected.
+ if (base->is_Mach() && base->as_Mach()->ideal_Opcode() == Op_DecodeN &&
+ !Universe::narrow_oop_use_implicit_null_checks())
+ continue;
}
}
--- a/hotspot/src/share/vm/opto/library_call.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/opto/library_call.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -2394,10 +2394,10 @@
// the barriers get omitted and the unsafe reference begins to "pollute"
// the alias analysis of the rest of the graph, either Compile::can_alias
// or Compile::must_alias will throw a diagnostic assert.)
- bool need_mem_bar;
+ bool need_mem_bar = false;
switch (kind) {
case Relaxed:
- need_mem_bar = mismatched || can_access_non_heap;
+ need_mem_bar = mismatched && !adr_type->isa_aryptr();
break;
case Opaque:
// Opaque uses CPUOrder membars for protection against code movement.
--- a/hotspot/src/share/vm/opto/loopTransform.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -3174,6 +3174,11 @@
return false;
}
+ Node* exit = head->loopexit()->proj_out(0);
+ if (exit == NULL) {
+ return false;
+ }
+
#ifndef PRODUCT
if (TraceLoopOpts) {
tty->print("ArrayFill ");
@@ -3281,7 +3286,6 @@
*/
// Redirect the old control and memory edges that are outside the loop.
- Node* exit = head->loopexit()->proj_out(0);
// Sometimes the memory phi of the head is used as the outgoing
// state of the loop. It's safe in this case to replace it with the
// result_mem.
--- a/hotspot/src/share/vm/opto/parse2.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/opto/parse2.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -826,6 +826,9 @@
ciMethodData* methodData = method()->method_data();
if (!methodData->is_mature()) return PROB_UNKNOWN;
ciProfileData* data = methodData->bci_to_data(bci());
+ if (data == NULL) {
+ return PROB_UNKNOWN;
+ }
if (!data->is_JumpData()) return PROB_UNKNOWN;
// get taken and not taken values
@@ -917,8 +920,8 @@
// of the OSR-ed method, and we want to deopt to gather more stats.
// If you have ANY counts, then this loop is simply 'cold' relative
// to the OSR loop.
- if (data->as_BranchData()->taken() +
- data->as_BranchData()->not_taken() == 0 ) {
+ if (data == NULL ||
+ (data->as_BranchData()->taken() + data->as_BranchData()->not_taken() == 0)) {
// This is the only way to return PROB_UNKNOWN:
return PROB_UNKNOWN;
}
--- a/hotspot/src/share/vm/opto/stringopts.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/opto/stringopts.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -891,8 +891,9 @@
ctrl_path.push(cn);
ctrl_path.push(cn->proj_out(0));
ctrl_path.push(cn->proj_out(0)->unique_out());
- if (cn->proj_out(0)->unique_out()->as_Catch()->proj_out(0) != NULL) {
- ctrl_path.push(cn->proj_out(0)->unique_out()->as_Catch()->proj_out(0));
+ Node* catchproj = cn->proj_out(0)->unique_out()->as_Catch()->proj_out(0);
+ if (catchproj != NULL) {
+ ctrl_path.push(catchproj);
}
} else {
ShouldNotReachHere();
--- a/hotspot/src/share/vm/prims/jni.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/prims/jni.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -932,8 +932,7 @@
inline void get_long() { _arguments->push_long(va_arg(_ap, jlong)); }
inline void get_float() { _arguments->push_float((jfloat)va_arg(_ap, jdouble)); } // float is coerced to double w/ va_arg
inline void get_double() { _arguments->push_double(va_arg(_ap, jdouble)); }
- inline void get_object() { jobject l = va_arg(_ap, jobject);
- _arguments->push_oop(Handle((oop *)l, false)); }
+ inline void get_object() { _arguments->push_jobject(va_arg(_ap, jobject)); }
inline void set_ap(va_list rap) {
va_copy(_ap, rap);
@@ -1022,7 +1021,7 @@
inline void get_long() { _arguments->push_long((_ap++)->j); }
inline void get_float() { _arguments->push_float((_ap++)->f); }
inline void get_double() { _arguments->push_double((_ap++)->d);}
- inline void get_object() { _arguments->push_oop(Handle((oop *)(_ap++)->l, false)); }
+ inline void get_object() { _arguments->push_jobject((_ap++)->l); }
inline void set_ap(const jvalue *rap) { _ap = rap; }
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1793,6 +1793,13 @@
}
}
+ if (initial_object != NULL) {
+ oop init_obj = JNIHandles::resolve_external_guard(initial_object);
+ if (init_obj == NULL) {
+ return JVMTI_ERROR_INVALID_OBJECT;
+ }
+ }
+
Thread *thread = Thread::current();
HandleMark hm(thread);
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -2863,6 +2863,10 @@
if (res != JNI_OK) {
return res;
}
+ } else if (match_option(option, "--permit-illegal-access")) {
+ if (!create_property("jdk.module.permitIllegalAccess", "true", ExternalProperty)) {
+ return JNI_ENOMEM;
+ }
// -agentlib and -agentpath
} else if (match_option(option, "-agentlib:", &tail) ||
(is_absolute_path = match_option(option, "-agentpath:", &tail))) {
@@ -3105,6 +3109,7 @@
// -Xprof
} else if (match_option(option, "-Xprof")) {
#if INCLUDE_FPROF
+ log_warning(arguments)("Option -Xprof was deprecated in version 9 and will likely be removed in a future release.");
_has_profile = true;
#else // INCLUDE_FPROF
jio_fprintf(defaultStream::error_stream(),
--- a/hotspot/src/share/vm/runtime/java.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/runtime/java.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -618,6 +618,13 @@
}
}
+void vm_exit_during_initialization() {
+ vm_notify_during_shutdown(NULL, NULL);
+
+ // Failure during initialization, we don't want to dump core
+ vm_abort(false);
+}
+
void vm_exit_during_initialization(Handle exception) {
tty->print_cr("Error occurred during initialization of VM");
// If there are exceptions on this thread it must be cleared
--- a/hotspot/src/share/vm/runtime/java.hpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/runtime/java.hpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -45,6 +45,7 @@
extern void notify_vm_shutdown();
// VM exit if error occurs during initialization of VM
+extern void vm_exit_during_initialization();
extern void vm_exit_during_initialization(Handle exception);
extern void vm_exit_during_initialization(Symbol* exception_name, const char* message);
extern void vm_exit_during_initialization(const char* error, const char* message = NULL);
--- a/hotspot/src/share/vm/runtime/javaCalls.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/runtime/javaCalls.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -328,9 +328,9 @@
// Verify the arguments
if (CheckJNICalls) {
- args->verify(method, result->get_type(), thread);
+ args->verify(method, result->get_type());
}
- else debug_only(args->verify(method, result->get_type(), thread));
+ else debug_only(args->verify(method, result->get_type()));
#if INCLUDE_JVMCI
}
#else
@@ -442,12 +442,43 @@
//--------------------------------------------------------------------------------------
// Implementation of JavaCallArguments
+inline bool is_value_state_indirect_oop(uint state) {
+ assert(state != JavaCallArguments::value_state_oop,
+ "Checking for handles after removal");
+ assert(state < JavaCallArguments::value_state_limit,
+ "Invalid value state %u", state);
+ return state != JavaCallArguments::value_state_primitive;
+}
+
+inline oop resolve_indirect_oop(intptr_t value, uint state) {
+ switch (state) {
+ case JavaCallArguments::value_state_handle:
+ {
+ oop* ptr = reinterpret_cast<oop*>(value);
+ return Handle::raw_resolve(ptr);
+ }
+
+ case JavaCallArguments::value_state_jobject:
+ {
+ jobject obj = reinterpret_cast<jobject>(value);
+ return JNIHandles::resolve(obj);
+ }
+
+ default:
+ ShouldNotReachHere();
+ return NULL;
+ }
+}
+
intptr_t* JavaCallArguments::parameters() {
// First convert all handles to oops
for(int i = 0; i < _size; i++) {
- if (_is_oop[i]) {
- // Handle conversion
- _value[i] = cast_from_oop<intptr_t>(Handle::raw_resolve((oop *)_value[i]));
+ uint state = _value_state[i];
+ assert(state != value_state_oop, "Multiple handle conversions");
+ if (is_value_state_indirect_oop(state)) {
+ oop obj = resolve_indirect_oop(_value[i], state);
+ _value[i] = cast_from_oop<intptr_t>(obj);
+ _value_state[i] = value_state_oop;
}
}
// Return argument vector
@@ -457,30 +488,42 @@
class SignatureChekker : public SignatureIterator {
private:
- bool *_is_oop;
- int _pos;
+ int _pos;
BasicType _return_type;
- intptr_t* _value;
- Thread* _thread;
+ u_char* _value_state;
+ intptr_t* _value;
public:
bool _is_return;
- SignatureChekker(Symbol* signature, BasicType return_type, bool is_static, bool* is_oop, intptr_t* value, Thread* thread) : SignatureIterator(signature) {
- _is_oop = is_oop;
- _is_return = false;
- _return_type = return_type;
- _pos = 0;
- _value = value;
- _thread = thread;
-
+ SignatureChekker(Symbol* signature,
+ BasicType return_type,
+ bool is_static,
+ u_char* value_state,
+ intptr_t* value) :
+ SignatureIterator(signature),
+ _pos(0),
+ _return_type(return_type),
+ _value_state(value_state),
+ _value(value),
+ _is_return(false)
+ {
if (!is_static) {
check_value(true); // Receiver must be an oop
}
}
void check_value(bool type) {
- guarantee(_is_oop[_pos++] == type, "signature does not match pushed arguments");
+ uint state = _value_state[_pos++];
+ if (type) {
+ guarantee(is_value_state_indirect_oop(state),
+ "signature does not match pushed arguments: %u at %d",
+ state, _pos - 1);
+ } else {
+ guarantee(state == JavaCallArguments::value_state_primitive,
+ "signature does not match pushed arguments: %u at %d",
+ state, _pos - 1);
+ }
}
void check_doing_return(bool state) { _is_return = state; }
@@ -515,24 +558,20 @@
return;
}
- // verify handle and the oop pointed to by handle
- int p = _pos;
- bool bad = false;
- // If argument is oop
- if (_is_oop[p]) {
- intptr_t v = _value[p];
- if (v != 0 ) {
- size_t t = (size_t)v;
- bad = (t < (size_t)os::vm_page_size() ) || !Handle::raw_resolve((oop *)v)->is_oop_or_null(true);
- if (CheckJNICalls && bad) {
- ReportJNIFatalError((JavaThread*)_thread, "Bad JNI oop argument");
- }
- }
- // for the regular debug case.
- assert(!bad, "Bad JNI oop argument");
+ intptr_t v = _value[_pos];
+ if (v != 0) {
+ // v is a "handle" referring to an oop, cast to integral type.
+ // There shouldn't be any handles in very low memory.
+ guarantee((size_t)v >= (size_t)os::vm_page_size(),
+ "Bad JNI oop argument %d: " PTR_FORMAT, _pos, v);
+ // Verify the pointee.
+ oop vv = resolve_indirect_oop(v, _value_state[_pos]);
+ guarantee(vv->is_oop_or_null(true),
+ "Bad JNI oop argument %d: " PTR_FORMAT " -> " PTR_FORMAT,
+ _pos, v, p2i(vv));
}
- check_value(true);
+ check_value(true); // Verify value state.
}
void do_bool() { check_int(T_BOOLEAN); }
@@ -549,8 +588,7 @@
};
-void JavaCallArguments::verify(const methodHandle& method, BasicType return_type,
- Thread *thread) {
+void JavaCallArguments::verify(const methodHandle& method, BasicType return_type) {
guarantee(method->size_of_parameters() == size_of_parameters(), "wrong no. of arguments pushed");
// Treat T_OBJECT and T_ARRAY as the same
@@ -559,7 +597,11 @@
// Check that oop information is correct
Symbol* signature = method->signature();
- SignatureChekker sc(signature, return_type, method->is_static(),_is_oop, _value, thread);
+ SignatureChekker sc(signature,
+ return_type,
+ method->is_static(),
+ _value_state,
+ _value);
sc.iterate_parameters();
sc.check_doing_return(true);
sc.iterate_returntype();
--- a/hotspot/src/share/vm/runtime/javaCalls.hpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/runtime/javaCalls.hpp Thu Apr 06 22:13:13 2017 +0000
@@ -80,11 +80,11 @@
_default_size = 8 // Must be at least # of arguments in JavaCalls methods
};
- intptr_t _value_buffer [_default_size + 1];
- bool _is_oop_buffer[_default_size + 1];
+ intptr_t _value_buffer [_default_size + 1];
+ u_char _value_state_buffer[_default_size + 1];
intptr_t* _value;
- bool* _is_oop;
+ u_char* _value_state;
int _size;
int _max_size;
bool _start_at_zero; // Support late setting of receiver
@@ -92,8 +92,8 @@
void initialize() {
// Starts at first element to support set_receiver.
- _value = &_value_buffer[1];
- _is_oop = &_is_oop_buffer[1];
+ _value = &_value_buffer[1];
+ _value_state = &_value_state_buffer[1];
_max_size = _default_size;
_size = 0;
@@ -101,6 +101,23 @@
JVMCI_ONLY(_alternative_target = NULL;)
}
+ // Helper for push_oop and the like. The value argument is a
+ // "handle" that refers to an oop. We record the address of the
+ // handle rather than the designated oop. The handle is later
+ // resolved to the oop by parameters(). This delays the exposure of
+ // naked oops until it is GC-safe.
+ template<typename T>
+ inline int push_oop_impl(T handle, int size) {
+ // JNITypes::put_obj expects an oop value, so we play fast and
+ // loose with the type system. The cast from handle type to oop
+ // *must* use a C-style cast. In a product build it performs a
+ // reinterpret_cast. In a debug build (more accurately, in a
+ // CHECK_UNHANDLED_OOPS build) it performs a static_cast, invoking
+ // the debug-only oop class's conversion from void* constructor.
+ JNITypes::put_obj((oop)handle, _value, size); // Updates size.
+ return size; // Return the updated size.
+ }
+
public:
JavaCallArguments() { initialize(); }
@@ -111,11 +128,12 @@
JavaCallArguments(int max_size) {
if (max_size > _default_size) {
- _value = NEW_RESOURCE_ARRAY(intptr_t, max_size + 1);
- _is_oop = NEW_RESOURCE_ARRAY(bool, max_size + 1);
+ _value = NEW_RESOURCE_ARRAY(intptr_t, max_size + 1);
+ _value_state = NEW_RESOURCE_ARRAY(u_char, max_size + 1);
- // Reserve room for potential receiver in value and is_oop
- _value++; _is_oop++;
+ // Reserve room for potential receiver in value and state
+ _value++;
+ _value_state++;
_max_size = max_size;
_size = 0;
@@ -136,25 +154,52 @@
}
#endif
- inline void push_oop(Handle h) { _is_oop[_size] = true;
- JNITypes::put_obj((oop)h.raw_value(), _value, _size); }
+ // The possible values for _value_state elements.
+ enum {
+ value_state_primitive,
+ value_state_oop,
+ value_state_handle,
+ value_state_jobject,
+ value_state_limit
+ };
- inline void push_int(int i) { _is_oop[_size] = false;
- JNITypes::put_int(i, _value, _size); }
+ inline void push_oop(Handle h) {
+ _value_state[_size] = value_state_handle;
+ _size = push_oop_impl(h.raw_value(), _size);
+ }
+
+ inline void push_jobject(jobject h) {
+ _value_state[_size] = value_state_jobject;
+ _size = push_oop_impl(h, _size);
+ }
- inline void push_double(double d) { _is_oop[_size] = false; _is_oop[_size + 1] = false;
- JNITypes::put_double(d, _value, _size); }
+ inline void push_int(int i) {
+ _value_state[_size] = value_state_primitive;
+ JNITypes::put_int(i, _value, _size);
+ }
+
+ inline void push_double(double d) {
+ _value_state[_size] = value_state_primitive;
+ _value_state[_size + 1] = value_state_primitive;
+ JNITypes::put_double(d, _value, _size);
+ }
- inline void push_long(jlong l) { _is_oop[_size] = false; _is_oop[_size + 1] = false;
- JNITypes::put_long(l, _value, _size); }
+ inline void push_long(jlong l) {
+ _value_state[_size] = value_state_primitive;
+ _value_state[_size + 1] = value_state_primitive;
+ JNITypes::put_long(l, _value, _size);
+ }
- inline void push_float(float f) { _is_oop[_size] = false;
- JNITypes::put_float(f, _value, _size); }
+ inline void push_float(float f) {
+ _value_state[_size] = value_state_primitive;
+ JNITypes::put_float(f, _value, _size);
+ }
// receiver
Handle receiver() {
assert(_size > 0, "must at least be one argument");
- assert(_is_oop[0], "first argument must be an oop");
+ assert(_value_state[0] == value_state_handle,
+ "first argument must be an oop");
assert(_value[0] != 0, "receiver must be not-null");
return Handle((oop*)_value[0], false);
}
@@ -162,11 +207,11 @@
void set_receiver(Handle h) {
assert(_start_at_zero == false, "can only be called once");
_start_at_zero = true;
- _is_oop--;
+ _value_state--;
_value--;
_size++;
- _is_oop[0] = true;
- _value[0] = (intptr_t)h.raw_value();
+ _value_state[0] = value_state_handle;
+ push_oop_impl(h.raw_value(), 0);
}
// Converts all Handles to oops, and returns a reference to parameter vector
@@ -174,7 +219,7 @@
int size_of_parameters() const { return _size; }
// Verify that pushed arguments fits a given method
- void verify(const methodHandle& method, BasicType return_type, Thread *thread);
+ void verify(const methodHandle& method, BasicType return_type);
};
// All calls to Java have to go via JavaCalls. Sets up the stack frame
--- a/hotspot/src/share/vm/runtime/jniHandles.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/runtime/jniHandles.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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,9 @@
#include "runtime/jniHandles.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/thread.inline.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1SATBCardTableModRefBS.hpp"
+#endif
JNIHandleBlock* JNIHandles::_global_handles = NULL;
JNIHandleBlock* JNIHandles::_weak_global_handles = NULL;
@@ -92,28 +95,48 @@
jobject res = NULL;
if (!obj.is_null()) {
// ignore null handles
- MutexLocker ml(JNIGlobalHandle_lock);
- assert(Universe::heap()->is_in_reserved(obj()), "sanity check");
- res = _weak_global_handles->allocate_handle(obj());
+ {
+ MutexLocker ml(JNIGlobalHandle_lock);
+ assert(Universe::heap()->is_in_reserved(obj()), "sanity check");
+ res = _weak_global_handles->allocate_handle(obj());
+ }
+ // Add weak tag.
+ assert(is_ptr_aligned(res, weak_tag_alignment), "invariant");
+ char* tptr = reinterpret_cast<char*>(res) + weak_tag_value;
+ res = reinterpret_cast<jobject>(tptr);
} else {
CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
}
return res;
}
+template<bool external_guard>
+oop JNIHandles::resolve_jweak(jweak handle) {
+ assert(is_jweak(handle), "precondition");
+ oop result = jweak_ref(handle);
+ result = guard_value<external_guard>(result);
+#if INCLUDE_ALL_GCS
+ if (result != NULL && UseG1GC) {
+ G1SATBCardTableModRefBS::enqueue(result);
+ }
+#endif // INCLUDE_ALL_GCS
+ return result;
+}
+
+template oop JNIHandles::resolve_jweak<true>(jweak);
+template oop JNIHandles::resolve_jweak<false>(jweak);
void JNIHandles::destroy_global(jobject handle) {
if (handle != NULL) {
assert(is_global_handle(handle), "Invalid delete of global JNI handle");
- *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it
+ jobject_ref(handle) = deleted_handle();
}
}
void JNIHandles::destroy_weak_global(jobject handle) {
if (handle != NULL) {
- assert(!CheckJNICalls || is_weak_global_handle(handle), "Invalid delete of weak global JNI handle");
- *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it
+ jweak_ref(handle) = deleted_handle();
}
}
--- a/hotspot/src/share/vm/runtime/jniHandles.hpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/runtime/jniHandles.hpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -40,7 +40,28 @@
static JNIHandleBlock* _weak_global_handles; // First weak global handle block
static oop _deleted_handle; // Sentinel marking deleted handles
+ inline static bool is_jweak(jobject handle);
+ inline static oop& jobject_ref(jobject handle); // NOT jweak!
+ inline static oop& jweak_ref(jobject handle);
+
+ template<bool external_guard> inline static oop guard_value(oop value);
+ template<bool external_guard> inline static oop resolve_impl(jobject handle);
+ template<bool external_guard> static oop resolve_jweak(jweak handle);
+
public:
+ // Low tag bit in jobject used to distinguish a jweak. jweak is
+ // type equivalent to jobject, but there are places where we need to
+ // be able to distinguish jweak values from other jobjects, and
+ // is_weak_global_handle is unsuitable for performance reasons. To
+ // provide such a test we add weak_tag_value to the (aligned) byte
+ // address designated by the jobject to produce the corresponding
+ // jweak. Accessing the value of a jobject must account for it
+ // being a possibly offset jweak.
+ static const uintptr_t weak_tag_size = 1;
+ static const uintptr_t weak_tag_alignment = (1u << weak_tag_size);
+ static const uintptr_t weak_tag_mask = weak_tag_alignment - 1;
+ static const int weak_tag_value = 1;
+
// Resolve handle into oop
inline static oop resolve(jobject handle);
// Resolve externally provided handle into oop with some guards
@@ -176,36 +197,85 @@
#endif
};
+inline bool JNIHandles::is_jweak(jobject handle) {
+ STATIC_ASSERT(weak_tag_size == 1);
+ STATIC_ASSERT(weak_tag_value == 1);
+ return (reinterpret_cast<uintptr_t>(handle) & weak_tag_mask) != 0;
+}
+
+inline oop& JNIHandles::jobject_ref(jobject handle) {
+ assert(!is_jweak(handle), "precondition");
+ return *reinterpret_cast<oop*>(handle);
+}
+
+inline oop& JNIHandles::jweak_ref(jobject handle) {
+ assert(is_jweak(handle), "precondition");
+ char* ptr = reinterpret_cast<char*>(handle) - weak_tag_value;
+ return *reinterpret_cast<oop*>(ptr);
+}
+
+// external_guard is true if called from resolve_external_guard.
+// Treat deleted (and possibly zapped) as NULL for external_guard,
+// else as (asserted) error.
+template<bool external_guard>
+inline oop JNIHandles::guard_value(oop value) {
+ if (!external_guard) {
+ assert(value != badJNIHandle, "Pointing to zapped jni handle area");
+ assert(value != deleted_handle(), "Used a deleted global handle");
+ } else if ((value == badJNIHandle) || (value == deleted_handle())) {
+ value = NULL;
+ }
+ return value;
+}
+
+// external_guard is true if called from resolve_external_guard.
+template<bool external_guard>
+inline oop JNIHandles::resolve_impl(jobject handle) {
+ assert(handle != NULL, "precondition");
+ oop result;
+ if (is_jweak(handle)) { // Unlikely
+ result = resolve_jweak<external_guard>(handle);
+ } else {
+ result = jobject_ref(handle);
+ // Construction of jobjects canonicalize a null value into a null
+ // jobject, so for non-jweak the pointee should never be null.
+ assert(external_guard || result != NULL,
+ "Invalid value read from jni handle");
+ result = guard_value<external_guard>(result);
+ }
+ return result;
+}
inline oop JNIHandles::resolve(jobject handle) {
- oop result = (handle == NULL ? (oop)NULL : *(oop*)handle);
- assert(result != NULL || (handle == NULL || !CheckJNICalls || is_weak_global_handle(handle)), "Invalid value read from jni handle");
- assert(result != badJNIHandle, "Pointing to zapped jni handle area");
+ oop result = NULL;
+ if (handle != NULL) {
+ result = resolve_impl<false /* external_guard */ >(handle);
+ }
return result;
-};
-
+}
+// Resolve some erroneous cases to NULL, rather than treating them as
+// possibly unchecked errors. In particular, deleted handles are
+// treated as NULL (though a deleted and later reallocated handle
+// isn't detected).
inline oop JNIHandles::resolve_external_guard(jobject handle) {
- if (handle == NULL) return NULL;
- oop result = *(oop*)handle;
- if (result == NULL || result == badJNIHandle) return NULL;
+ oop result = NULL;
+ if (handle != NULL) {
+ result = resolve_impl<true /* external_guard */ >(handle);
+ }
return result;
-};
-
+}
inline oop JNIHandles::resolve_non_null(jobject handle) {
assert(handle != NULL, "JNI handle should not be null");
- oop result = *(oop*)handle;
- assert(result != NULL, "Invalid value read from jni handle");
- assert(result != badJNIHandle, "Pointing to zapped jni handle area");
- // Don't let that private _deleted_handle object escape into the wild.
- assert(result != deleted_handle(), "Used a deleted global handle.");
+ oop result = resolve_impl<false /* external_guard */ >(handle);
+ assert(result != NULL, "NULL read from jni handle");
return result;
-};
+}
inline void JNIHandles::destroy_local(jobject handle) {
if (handle != NULL) {
- *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it
+ jobject_ref(handle) = deleted_handle();
}
}
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -181,13 +181,13 @@
}
if (UseG1GC) {
- def(SATB_Q_FL_lock , PaddedMutex , special, true, Monitor::_safepoint_check_never);
- def(SATB_Q_CBL_mon , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_never);
- def(Shared_SATB_Q_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_never);
+ def(SATB_Q_FL_lock , PaddedMutex , special , true, Monitor::_safepoint_check_never);
+ def(SATB_Q_CBL_mon , PaddedMonitor, leaf - 1 , true, Monitor::_safepoint_check_never);
+ def(Shared_SATB_Q_lock , PaddedMutex , leaf - 1 , true, Monitor::_safepoint_check_never);
- def(DirtyCardQ_FL_lock , PaddedMutex , special, true, Monitor::_safepoint_check_never);
- def(DirtyCardQ_CBL_mon , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_never);
- def(Shared_DirtyCardQ_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_never);
+ def(DirtyCardQ_FL_lock , PaddedMutex , special , true, Monitor::_safepoint_check_never);
+ def(DirtyCardQ_CBL_mon , PaddedMonitor, leaf - 1 , true, Monitor::_safepoint_check_never);
+ def(Shared_DirtyCardQ_lock , PaddedMutex , leaf - 1 , true, Monitor::_safepoint_check_never);
def(FreeList_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_never);
def(SecondaryFreeList_lock , PaddedMonitor, leaf , true, Monitor::_safepoint_check_never);
--- a/hotspot/src/share/vm/runtime/thread.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/runtime/thread.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -3408,9 +3408,16 @@
Klass* klass = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
- JavaValue result(T_VOID);
+ JavaValue result(T_INT);
+ JavaCallArguments args;
+ args.push_int(DisplayVMOutputToStderr);
+ args.push_int(log_is_enabled(Debug, init)); // print stack trace if exception thrown
JavaCalls::call_static(&result, klass, vmSymbols::initPhase2_name(),
- vmSymbols::void_method_signature(), CHECK);
+ vmSymbols::boolean_boolean_int_signature(), &args, CHECK);
+ if (result.get_jint() != JNI_OK) {
+ vm_exit_during_initialization(); // no message or exception
+ }
+
universe_post_module_init();
}
--- a/hotspot/src/share/vm/shark/sharkNativeWrapper.cpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/shark/sharkNativeWrapper.cpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright 2009, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -300,6 +300,7 @@
not_null, merge);
builder()->SetInsertPoint(not_null);
+#error Needs to be updated for tagged jweak; see JNIHandles.
Value *unboxed_result = builder()->CreateLoad(result);
builder()->CreateBr(merge);
--- a/hotspot/src/share/vm/utilities/debug.hpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/utilities/debug.hpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -140,6 +140,9 @@
// For backward compatibility.
#define assert(p, ...) vmassert(p, __VA_ARGS__)
+#ifndef ASSERT
+#define vmassert_status(p, status, msg)
+#else
// This version of vmassert is for use with checking return status from
// library calls that return actual error values eg. EINVAL,
// ENOMEM etc, rather than returning -1 and setting errno.
@@ -155,6 +158,7 @@
BREAKPOINT; \
} \
} while (0)
+#endif
// For backward compatibility.
#define assert_status(p, status, msg) vmassert_status(p, status, msg)
--- a/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp Thu Apr 06 22:13:13 2017 +0000
@@ -1,6 +1,6 @@
/*
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2012, 2017 SAP SE. 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
@@ -153,6 +153,9 @@
// offset_of as it is defined for gcc.
#define offset_of(klass,field) (size_t)((intx)&(((klass*)16)->field) - 16)
+// AIX 5.3 has buggy __thread support. (see JDK-8176442).
+#define USE_LIBRARY_BASED_TLS_ONLY 1
+
#ifndef USE_LIBRARY_BASED_TLS_ONLY
#define THREAD_LOCAL_DECL __thread
#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arraycopy/TestObjectArrayCopy.java Thu Apr 06 22:13:13 2017 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017, SAP SE and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8176505
+ * @summary Wrong assertion 'should be an array copy/clone' in arraycopynode.cpp
+ *
+ * @run main/othervm -Xbatch -XX:-UseOnStackReplacement compiler.arraycopy.TestObjectArrayCopy
+ *
+ * @author Volker Simonis
+ */
+
+package compiler.arraycopy;
+
+public class TestObjectArrayCopy {
+
+ public static boolean crash(Object src) {
+ String[] dst = new String[1];
+ System.arraycopy(src, 0, dst, 0, 1);
+ return dst[0] == null;
+ }
+
+ public static void main(String[] args) {
+ String[] sa = new String[1];
+ for (int i = 0; i < 20_000; i++) {
+ crash(sa);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/c2/TestNPEHeapBased.java Thu Apr 06 22:13:13 2017 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017 SAP SE. 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 8176518
+ * @summary Invalid ImplicitNullChecks when heap base not protected
+ *
+ * @run main/othervm -XX:ObjectAlignmentInBytes=16 -XX:HeapBaseMinAddress=64g
+ * -XX:-TieredCompilation -Xbatch
+ * compiler.c2.TestNPEHeapBased
+ * @requires vm.bits == "64"
+ */
+
+package compiler.c2;
+public class TestNPEHeapBased {
+
+ TestNPEHeapBased instance = null;
+ int i = 0;
+
+ public void set_i(int value) {
+ instance.i = value;
+ }
+
+
+ static final int loop_cnt = 200000;
+
+ public static void main(String args[]){
+ TestNPEHeapBased xyz = new TestNPEHeapBased();
+ xyz.instance = xyz;
+ for (int x = 0; x < loop_cnt; x++) xyz.set_i(x);
+ xyz.instance = null;
+ try {
+ xyz.set_i(0);
+ } catch (NullPointerException npe) {
+ System.out.println("Got expected NullPointerException:");
+ npe.printStackTrace();
+ return;
+ }
+ throw new InternalError("NullPointerException is missing!");
+ }
+
+}
--- a/hotspot/test/compiler/loopopts/TestLoopPeeling.java Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/test/compiler/loopopts/TestLoopPeeling.java Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8078262
+ * @bug 8078262 8177095
* @summary Tests correct dominator information after loop peeling.
*
* @run main/othervm -Xcomp
@@ -40,14 +40,16 @@
public static void main(String args[]) {
TestLoopPeeling test = new TestLoopPeeling();
try {
- test.testArrayAccess(0, 1);
+ test.testArrayAccess1(0, 1);
+ test.testArrayAccess2(0);
+ test.testArrayAccess3(0, false);
test.testArrayAllocation(0, 1);
} catch (Exception e) {
// Ignore exceptions
}
}
- public void testArrayAccess(int index, int inc) {
+ public void testArrayAccess1(int index, int inc) {
int storeIndex = -1;
for (; index < 10; index += inc) {
@@ -63,7 +65,7 @@
if (index == 42) {
// This store and the corresponding range check are moved out of the
- // loop and both used after old loop and the peeled iteration exit.
+ // loop and both used after main loop and the peeled iteration exit.
// For the peeled iteration, storeIndex is always -1 and the ConvI2L
// is replaced by TOP. However, the range check is not folded because
// we don't do the split if optimization in PhaseIdealLoop2.
@@ -77,6 +79,44 @@
}
}
+ public int testArrayAccess2(int index) {
+ // Load1 and the corresponding range check are moved out of the loop
+ // and both are used after the main loop and the peeled iteration exit.
+ // For the peeled iteration, storeIndex is always Integer.MIN_VALUE and
+ // for the main loop it is 0. Hence, the merging phi has type int:<=0.
+ // Load1 reads the array at index ConvI2L(CastII(AddI(storeIndex, -1)))
+ // where the CastII is range check dependent and has type int:>=0.
+ // The CastII gets pushed through the AddI and its type is changed to int:>=1
+ // which does not overlap with the input type of storeIndex (int:<=0).
+ // The CastII is replaced by TOP causing a cascade of other eliminations.
+ // Since the control path through the range check CmpU(AddI(storeIndex, -1))
+ // is not eliminated, the graph is in a corrupted state. We fail once we merge
+ // with the result of Load2 because we get data from a non-dominating region.
+ int storeIndex = Integer.MIN_VALUE;
+ for (; index < 10; ++index) {
+ if (index == 42) {
+ return array[storeIndex-1]; // Load1
+ }
+ storeIndex = 0;
+ }
+ return array[42]; // Load2
+ }
+
+ public int testArrayAccess3(int index, boolean b) {
+ // Same as testArrayAccess2 but manifests as crash in register allocator.
+ int storeIndex = Integer.MIN_VALUE;
+ for (; index < 10; ++index) {
+ if (b) {
+ return 0;
+ }
+ if (index == 42) {
+ return array[storeIndex-1]; // Load1
+ }
+ storeIndex = 0;
+ }
+ return array[42]; // Load2
+ }
+
public byte[] testArrayAllocation(int index, int inc) {
int allocationCount = -1;
byte[] result;
@@ -88,7 +128,7 @@
if (index == 42) {
// This allocation and the corresponding size check are moved out of the
- // loop and both used after old loop and the peeled iteration exit.
+ // loop and both used after main loop and the peeled iteration exit.
// For the peeled iteration, allocationCount is always -1 and the ConvI2L
// is replaced by TOP. However, the size check is not folded because
// we don't do the split if optimization in PhaseIdealLoop2.
--- a/hotspot/test/runtime/MinimalVM/JMX.java Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/test/runtime/MinimalVM/JMX.java Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -47,9 +47,8 @@
.shouldContain("-Dcom.sun.management is not supported in this VM.")
.shouldHaveExitValue(1);
- pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), Long.toString(ProcessTools.getProcessId()), "VM.print_threads"});
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), "-l"});
new OutputAnalyzer(pb.start())
- .shouldContain("Could not find any processes matching ")
- .shouldHaveExitValue(1);
+ .shouldNotMatch("^" + Long.toString(ProcessTools.getProcessId()) + "\\s+.*$");
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/CallWithJNIWeak/CallWithJNIWeak.java Thu Apr 06 22:13:13 2017 +0000
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8166188
+ * @summary Test call of native function with JNI weak global ref.
+ * @modules java.base
+ * @run main/othervm/native CallWithJNIWeak
+ */
+
+public class CallWithJNIWeak {
+ static {
+ System.loadLibrary("CallWithJNIWeak");
+ }
+
+ private static native void testJNIFieldAccessors(CallWithJNIWeak o);
+
+ // The field initializations must be kept in sync with the JNI code
+ // which reads verifies the values of these fields.
+ private int i = 1;
+ private long j = 2;
+ private boolean z = true;
+ private char c = 'a';
+ private short s = 3;
+ private float f = 1.0f;
+ private double d = 2.0;
+ private Object l;
+
+ private CallWithJNIWeak() {
+ this.l = this;
+ }
+
+ private native void weakReceiverTest0();
+ private void weakReceiverTest() {
+ weakReceiverTest0();
+ }
+
+ private synchronized void synchonizedWeakReceiverTest() {
+ this.notifyAll();
+ }
+
+
+ private static native void runTests(CallWithJNIWeak o);
+
+ public static void main(String[] args) {
+ CallWithJNIWeak w = new CallWithJNIWeak();
+ for (int i = 0; i < 20000; i++) {
+ runTests(w);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/CallWithJNIWeak/libCallWithJNIWeak.c Thu Apr 06 22:13:13 2017 +0000
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <jni.h>
+
+/*
+ * Class: CallWithJNIWeak
+ * Method: testJNIFieldAccessors
+ * Signature: (LCallWithJNIWeak;)V
+ */
+JNIEXPORT void JNICALL
+Java_CallWithJNIWeak_testJNIFieldAccessors(JNIEnv *env, jclass clazz, jobject this) {
+ // Make sure that we have a weak reference to the receiver
+
+ jweak self = (*env)->NewWeakGlobalRef(env, this);
+
+ jclass this_class = (*env)->GetObjectClass(env, self);
+
+ jclass exception = (*env)->FindClass(env, "java/lang/RuntimeException");
+
+ jfieldID id_i = (*env)->GetFieldID(env, this_class, "i", "I");
+ jfieldID id_j = (*env)->GetFieldID(env, this_class, "j", "J");
+ jfieldID id_z = (*env)->GetFieldID(env, this_class, "z", "Z");
+ jfieldID id_c = (*env)->GetFieldID(env, this_class, "c", "C");
+ jfieldID id_s = (*env)->GetFieldID(env, this_class, "s", "S");
+ jfieldID id_f = (*env)->GetFieldID(env, this_class, "f", "F");
+ jfieldID id_d = (*env)->GetFieldID(env, this_class, "d", "D");
+ jfieldID id_l = (*env)->GetFieldID(env, this_class, "l", "Ljava/lang/Object;");
+ jvalue v;
+
+#define CHECK(variable, expected) \
+ do { \
+ if ((variable) != (expected)) { \
+ (*env)->ThrowNew(env, exception, #variable" != " #expected); \
+ return; \
+ } \
+ } while(0)
+
+ // The values checked below must be kept in sync with the Java source file.
+
+ v.i = (*env)->GetIntField(env, self, id_i);
+ CHECK(v.i, 1);
+
+ v.j = (*env)->GetLongField(env, self, id_j);
+ CHECK(v.j, 2);
+
+ v.z = (*env)->GetBooleanField(env, self, id_z);
+ CHECK(v.z, JNI_TRUE);
+
+ v.c = (*env)->GetCharField(env, self, id_c);
+ CHECK(v.c, 'a');
+
+ v.s = (*env)->GetShortField(env, self, id_s);
+ CHECK(v.s, 3);
+
+ v.f = (*env)->GetFloatField(env, self, id_f);
+ CHECK(v.f, 1.0f);
+
+ v.d = (*env)->GetDoubleField(env, self, id_d);
+ CHECK(v.d, 2.0);
+
+#undef CHECK
+
+ v.l = (*env)->GetObjectField(env, self, id_l);
+ if (v.l == NULL) {
+ (*env)->ThrowNew(env, exception, "Object field was null");
+ return;
+ }
+ {
+ jclass clz = (*env)->GetObjectClass(env, v.l);
+ if (!(*env)->IsSameObject(env, clazz, clz)) {
+ (*env)->ThrowNew(env, exception, "Bad object class");
+ }
+ }
+
+ (*env)->DeleteWeakGlobalRef(env, self);
+}
+
+/*
+ * Class: CallWithJNIWeak
+ * Method: runTests
+ * Signature: (LCallWithJNIWeak;)V
+ */
+JNIEXPORT void JNICALL
+Java_CallWithJNIWeak_runTests(JNIEnv *env, jclass clazz, jobject this) {
+ jweak that = (*env)->NewWeakGlobalRef(env, this);
+ {
+ jmethodID method = (*env)->GetStaticMethodID(env,
+ clazz, "testJNIFieldAccessors", "(LCallWithJNIWeak;)V");
+ (*env)->CallStaticVoidMethod(env, clazz, method, that);
+ if ((*env)->ExceptionCheck(env)) {
+ return;
+ }
+ }
+
+ {
+ jmethodID method = (*env)->GetMethodID(env, clazz, "weakReceiverTest", "()V");
+ (*env)->CallVoidMethod(env, that, method);
+ if ((*env)->ExceptionCheck(env)) {
+ return;
+ }
+ }
+
+ {
+ jmethodID method = (*env)->GetMethodID(env, clazz, "synchonizedWeakReceiverTest", "()V");
+ (*env)->CallVoidMethod(env, that, method);
+ if ((*env)->ExceptionCheck(env)) {
+ return;
+ }
+ }
+ (*env)->DeleteWeakGlobalRef(env, that);
+}
+
+/*
+ * Class: CallWithJNIWeak
+ * Method: weakReceiverTest0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_CallWithJNIWeak_weakReceiverTest0(JNIEnv *env, jobject obj) {
+ (*env)->GetObjectClass(env, obj);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/ReturnJNIWeak/ReturnJNIWeak.java Thu Apr 06 22:13:13 2017 +0000
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8166188
+ * @requires vm.opt.ExplicitGCInvokesConcurrent != true
+ * @summary Test return of JNI weak global refs from native calls.
+ * @modules java.base
+ * @run main/othervm/native -Xint ReturnJNIWeak
+ * @run main/othervm/native -Xcomp ReturnJNIWeak
+ */
+
+public final class ReturnJNIWeak {
+
+ static {
+ System.loadLibrary("ReturnJNIWeak");
+ }
+
+ private static final class TestObject {
+ public final int value;
+
+ public TestObject(int value) {
+ this.value = value;
+ }
+ }
+
+ private static volatile TestObject testObject = null;
+
+ private static native void registerObject(Object o);
+ private static native void unregisterObject();
+ private static native Object getObject();
+
+ // Create the test object and record it both strongly and weakly.
+ private static void remember(int value) {
+ TestObject o = new TestObject(value);
+ registerObject(o);
+ testObject = o;
+ }
+
+ // Remove both strong and weak references to the current test object.
+ private static void forget() {
+ unregisterObject();
+ testObject = null;
+ }
+
+ // Verify the weakly recorded object
+ private static void checkValue(int value) throws Exception {
+ Object o = getObject();
+ if (o == null) {
+ throw new RuntimeException("Weak reference unexpectedly null");
+ }
+ TestObject t = (TestObject)o;
+ if (t.value != value) {
+ throw new RuntimeException("Incorrect value");
+ }
+ }
+
+ // Verify we can create a weak reference and get it back.
+ private static void testSanity() throws Exception {
+ System.out.println("running testSanity");
+ int value = 5;
+ try {
+ remember(value);
+ checkValue(value);
+ } finally {
+ forget();
+ }
+ }
+
+ // Verify weak ref value survives across collection if strong ref exists.
+ private static void testSurvival() throws Exception {
+ System.out.println("running testSurvival");
+ int value = 10;
+ try {
+ remember(value);
+ checkValue(value);
+ System.gc();
+ // Verify weak ref still has expected value.
+ checkValue(value);
+ } finally {
+ forget();
+ }
+ }
+
+ // Verify weak ref cleared if no strong ref exists.
+ private static void testClear() throws Exception {
+ System.out.println("running testClear");
+ int value = 15;
+ try {
+ remember(value);
+ checkValue(value);
+ // Verify still good.
+ checkValue(value);
+ // Drop reference.
+ testObject = null;
+ System.gc();
+ // Verify weak ref cleared as expected.
+ Object recorded = getObject();
+ if (recorded != null) {
+ throw new RuntimeException("expected clear");
+ }
+ } finally {
+ forget();
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ testSanity();
+ testSurvival();
+ testClear();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/ReturnJNIWeak/libReturnJNIWeak.c Thu Apr 06 22:13:13 2017 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * Native support for ReturnJNIWeak test.
+ */
+
+#include "jni.h"
+
+static jweak registered = NULL;
+
+JNIEXPORT void JNICALL
+Java_ReturnJNIWeak_registerObject(JNIEnv* env,
+ jclass jclazz,
+ jobject value) {
+ // assert registered == NULL
+ registered = (*env)->NewWeakGlobalRef(env, value);
+}
+
+JNIEXPORT void JNICALL
+Java_ReturnJNIWeak_unregisterObject(JNIEnv* env, jclass jclazz) {
+ if (registered != NULL) {
+ (*env)->DeleteWeakGlobalRef(env, registered);
+ registered = NULL;
+ }
+}
+
+JNIEXPORT jobject JNICALL
+Java_ReturnJNIWeak_getObject(JNIEnv* env, jclass jclazz) {
+ // assert registered != NULL
+ return registered;
+}
--- a/hotspot/test/runtime/modules/IgnoreModulePropertiesTest.java Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/test/runtime/modules/IgnoreModulePropertiesTest.java Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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,7 +44,7 @@
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-D" + prop + "=" + value, "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldContain("java version ");
+ output.shouldContain(" version ");
output.shouldHaveExitValue(0);
// Ensure that the property and its value aren't available.
--- a/hotspot/test/serviceability/jvmti/GetNamedModule/libGetNamedModuleTest.c Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/test/serviceability/jvmti/GetNamedModule/libGetNamedModuleTest.c Thu Apr 06 22:13:13 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -183,7 +183,7 @@
err = (*jvmti)->GetNamedModule(jvmti, loader, pkg_name, module_ptr);
if (err != JVMTI_ERROR_NONE) {
printf(" Error in GetNamedModule for package \"%s\": %s (%d)\n",
- pkg_name, TranslateError(err), err);
+ name, TranslateError(err), err);
return err;
}
printf(" returned module: %p\n", *module_ptr);
--- a/hotspot/test/test_env.sh Thu Apr 06 21:14:07 2017 +0000
+++ b/hotspot/test/test_env.sh Thu Apr 06 22:13:13 2017 +0000
@@ -214,6 +214,11 @@
then
VM_CPU="aarch64"
fi
+grep "arm64" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+ VM_CPU="aarch64"
+fi
export VM_TYPE VM_BITS VM_OS VM_CPU
echo "VM_TYPE=${VM_TYPE}"
echo "VM_BITS=${VM_BITS}"