# HG changeset patch # User jwilhelm # Date 1488473219 -3600 # Thu Mar 02 17:46:59 2017 +0100 # Node ID 3f9d664def00e3fbd64a11a0d3b0eda391c414d4 # Parent 2ff05d967fb2848e9f904c4f2b19edc7c90972ba 8176054: [BACKOUT][REDO] G1 Needs pre barrier on dereference of weak JNI handles Reviewed-by: diff --git a/make/test/JtregNative.gmk b/make/test/JtregNative.gmk --- a/make/test/JtregNative.gmk +++ b/make/test/JtregNative.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -48,8 +48,6 @@ $(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 \ diff --git a/src/cpu/aarch64/vm/jniFastGetField_aarch64.cpp b/src/cpu/aarch64/vm/jniFastGetField_aarch64.cpp --- a/src/cpu/aarch64/vm/jniFastGetField_aarch64.cpp +++ b/src/cpu/aarch64/vm/jniFastGetField_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2010, 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,11 +82,6 @@ __ 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 diff --git a/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp b/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp --- a/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp +++ b/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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,31 +2052,13 @@ __ reset_last_Java_frame(false); - // Unbox oop result, e.g. JNIHandles::resolve result. + // Unpack oop result if (ret_type == T_OBJECT || ret_type == T_ARRAY) { - 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); + Label L; + __ cbz(r0, L); + __ ldr(r0, Address(r0, 0)); + __ bind(L); + __ verify_oop(r0); } if (CheckJNICalls) { diff --git a/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp b/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp --- a/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp +++ b/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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. * @@ -1399,32 +1399,13 @@ // and result handler will pick it up { - Label no_oop, not_weak, store_result; + Label no_oop, store_result; __ adr(t, ExternalAddress(AbstractInterpreter::result_handler(T_OBJECT))); __ cmp(t, result_handler); __ br(Assembler::NE, no_oop); - // Unbox oop result, e.g. JNIHandles::resolve result. + // retrieve result __ pop(ltos); - __ 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. + __ cbz(r0, store_result); __ ldr(r0, Address(r0, 0)); __ bind(store_result); __ str(r0, Address(rfp, frame::interpreter_frame_oop_temp_offset*wordSize)); diff --git a/src/cpu/arm/vm/interp_masm_arm.cpp b/src/cpu/arm/vm/interp_masm_arm.cpp --- a/src/cpu/arm/vm/interp_masm_arm.cpp +++ b/src/cpu/arm/vm/interp_masm_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -476,6 +476,185 @@ } ////////////////////////////////////////////////////////////////////////////////// +#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 diff --git a/src/cpu/arm/vm/interp_masm_arm.hpp b/src/cpu/arm/vm/interp_masm_arm.hpp --- a/src/cpu/arm/vm/interp_masm_arm.hpp +++ b/src/cpu/arm/vm/interp_masm_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -146,6 +146,27 @@ 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 diff --git a/src/cpu/arm/vm/jniFastGetField_arm.cpp b/src/cpu/arm/vm/jniFastGetField_arm.cpp --- a/src/cpu/arm/vm/jniFastGetField_arm.cpp +++ b/src/cpu/arm/vm/jniFastGetField_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,14 +119,6 @@ __ 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); diff --git a/src/cpu/arm/vm/macroAssembler_arm.cpp b/src/cpu/arm/vm/macroAssembler_arm.cpp --- a/src/cpu/arm/vm/macroAssembler_arm.cpp +++ b/src/cpu/arm/vm/macroAssembler_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2211,219 +2211,6 @@ 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) { diff --git a/src/cpu/arm/vm/macroAssembler_arm.hpp b/src/cpu/arm/vm/macroAssembler_arm.hpp --- a/src/cpu/arm/vm/macroAssembler_arm.hpp +++ b/src/cpu/arm/vm/macroAssembler_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -402,29 +402,6 @@ 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); diff --git a/src/cpu/arm/vm/sharedRuntime_arm.cpp b/src/cpu/arm/vm/sharedRuntime_arm.cpp --- a/src/cpu/arm/vm/sharedRuntime_arm.cpp +++ b/src/cpu/arm/vm/sharedRuntime_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1732,7 +1732,14 @@ case T_FLOAT : // fall through case T_DOUBLE : /* nothing to do */ break; case T_OBJECT : // fall through - case T_ARRAY : break; // See JNIHandles::resolve below + case T_ARRAY : { + Label L; + __ cbz(R0, L); + __ ldr(R0, Address(R0)); + __ verify_oop(R0); + __ bind(L); + break; + } default: ShouldNotReachHere(); } @@ -1741,15 +1748,14 @@ if (CheckJNICalls) { __ str(__ zero_register(Rtemp), Address(Rthread, JavaThread::pending_jni_exception_check_fn_offset())); } + + // Unhandle the result + if (ret_type == T_OBJECT || ret_type == T_ARRAY) { + __ cmp(R0, 0); + __ ldr(R0, Address(R0), ne); + } #endif // AARCH64 - // Unbox oop result, e.g. JNIHandles::resolve value in R0. - if (ret_type == T_OBJECT || ret_type == T_ARRAY) { - __ resolve_jobject(R0, // value - Rtemp, // tmp1 - R1_tmp); // tmp2 - } - // Any exception pending? __ ldr(Rtemp, Address(Rthread, Thread::pending_exception_offset())); __ mov(SP, FP); diff --git a/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp b/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp --- a/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp +++ b/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1240,25 +1240,28 @@ __ str(__ zero_register(Rtemp), Address(Rthread, JavaThread::pending_jni_exception_check_fn_offset())); } - // Unbox oop result, e.g. JNIHandles::resolve result if it's an oop. + // Unbox if the result is non-zero object +#ifdef AARCH64 { - Label Lnot_oop; -#ifdef AARCH64 + Label L, Lnull; __ mov_slow(Rtemp, AbstractInterpreter::result_handler(T_OBJECT)); __ cmp(Rresult_handler, Rtemp); - __ 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); + __ 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); } +#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 diff --git a/src/cpu/ppc/vm/frame_ppc.cpp b/src/cpu/ppc/vm/frame_ppc.cpp --- a/src/cpu/ppc/vm/frame_ppc.cpp +++ b/src/cpu/ppc/vm/frame_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 SAP SE. All rights reserved. + * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015 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,7 +171,10 @@ switch (method->result_type()) { case T_OBJECT: case T_ARRAY: { - *oop_result = JNIHandles::resolve(*(jobject*)lresult); + 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; break; } // We use std/stfd to store the values. diff --git a/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/src/cpu/ppc/vm/macroAssembler_ppc.cpp --- a/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 SAP SE. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 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 @@ -3033,34 +3033,6 @@ 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. @@ -3122,7 +3094,7 @@ bind(runtime); - // May need to preserve LR. Also needed if current frame is not compatible with C calling convention. + // VM call need frame to access(write) O register. if (needs_frame) { save_LR_CR(Rtmp1); push_frame_reg_args(0, Rtmp2); diff --git a/src/cpu/ppc/vm/macroAssembler_ppc.hpp b/src/cpu/ppc/vm/macroAssembler_ppc.hpp --- a/src/cpu/ppc/vm/macroAssembler_ppc.hpp +++ b/src/cpu/ppc/vm/macroAssembler_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 SAP SE. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 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 @@ -649,8 +649,6 @@ 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, diff --git a/src/cpu/ppc/vm/sharedRuntime_ppc.cpp b/src/cpu/ppc/vm/sharedRuntime_ppc.cpp --- a/src/cpu/ppc/vm/sharedRuntime_ppc.cpp +++ b/src/cpu/ppc/vm/sharedRuntime_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 SAP SE. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 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,11 +2477,16 @@ __ reset_last_Java_frame(); - // Unbox oop result, e.g. JNIHandles::resolve value. + // Unpack oop result. // -------------------------------------------------------------------------- if (ret_type == T_OBJECT || ret_type == T_ARRAY) { - __ resolve_jobject(R3_RET, r_temp_1, r_temp_2, /* needs_frame */ false); // kills R31 + 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); } if (CheckJNICalls) { diff --git a/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp b/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp --- a/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp +++ b/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015, 2017 SAP SE. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016 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 @@ -401,8 +401,11 @@ case T_LONG: break; case T_OBJECT: - // JNIHandles::resolve result. - __ resolve_jobject(R3_RET, R11_scratch1, R12_scratch2, /* needs_frame */ true); // kills R31 + // unbox result if not null + __ cmpdi(CCR0, R3_RET, 0); + __ beq(CCR0, done); + __ ld(R3_RET, 0, R3_RET); + __ verify_oop(R3_RET); break; case T_FLOAT: break; diff --git a/src/cpu/s390/vm/macroAssembler_s390.cpp b/src/cpu/s390/vm/macroAssembler_s390.cpp --- a/src/cpu/s390/vm/macroAssembler_s390.cpp +++ b/src/cpu/s390/vm/macroAssembler_s390.cpp @@ -3439,34 +3439,6 @@ 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 //------------------------------------------------------ diff --git a/src/cpu/s390/vm/macroAssembler_s390.hpp b/src/cpu/s390/vm/macroAssembler_s390.hpp --- a/src/cpu/s390/vm/macroAssembler_s390.hpp +++ b/src/cpu/s390/vm/macroAssembler_s390.hpp @@ -726,8 +726,6 @@ // 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. diff --git a/src/cpu/s390/vm/sharedRuntime_s390.cpp b/src/cpu/s390/vm/sharedRuntime_s390.cpp --- a/src/cpu/s390/vm/sharedRuntime_s390.cpp +++ b/src/cpu/s390/vm/sharedRuntime_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2017 SAP SE. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016 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,9 +2272,13 @@ __ reset_last_Java_frame(); - // Unpack oop result, e.g. JNIHandles::resolve result. + // Unpack oop result if (ret_type == T_OBJECT || ret_type == T_ARRAY) { - __ resolve_jobject(Z_RET, /* tmp1 */ Z_R13, /* tmp2 */ Z_R7); + 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); } if (CheckJNICalls) { diff --git a/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp b/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp --- a/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp +++ b/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2017 SAP SE. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016 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 @@ -1695,11 +1695,14 @@ // 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; + { NearLabel no_oop_result, store_oop_result; __ load_absolute_address(Z_R1, AbstractInterpreter::result_handler(T_OBJECT)); __ compareU64_and_branch(Z_R1, Rresult_handler, Assembler::bcondNotEqual, no_oop_result); - __ resolve_jobject(Rlresult, /* tmp1 */ Rmethod, /* tmp2 */ Z_R1); + __ compareU64_and_branch(Rlresult, (intptr_t)0L, Assembler::bcondEqual, store_oop_result); + __ z_lg(Rlresult, 0, Rlresult); // unbox + __ bind(store_oop_result); __ z_stg(Rlresult, oop_tmp_offset, Z_fp); + __ verify_oop(Rlresult); __ bind(no_oop_result); } diff --git a/src/cpu/sparc/vm/jniFastGetField_sparc.cpp b/src/cpu/sparc/vm/jniFastGetField_sparc.cpp --- a/src/cpu/sparc/vm/jniFastGetField_sparc.cpp +++ b/src/cpu/sparc/vm/jniFastGetField_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2010, 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,7 +68,6 @@ __ 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"); @@ -148,7 +147,6 @@ __ 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); @@ -221,7 +219,6 @@ __ 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"); diff --git a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2754,30 +2754,15 @@ __ verify_thread(); // G2_thread must be correct __ reset_last_Java_frame(); - // Unbox oop result, e.g. JNIHandles::resolve value in I0. + // Unpack oop result if (ret_type == T_OBJECT || ret_type == T_ARRAY) { - 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); + 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); } if (CheckJNICalls) { diff --git a/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp b/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp --- a/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp +++ b/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1516,23 +1516,11 @@ __ set((intptr_t)AbstractInterpreter::result_handler(T_OBJECT), G3_scratch); __ cmp_and_brx_short(G3_scratch, Lscratch, Assembler::notEqual, Assembler::pt, no_oop); - // 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 + __ 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); + __ 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); diff --git a/src/cpu/x86/vm/jniFastGetField_x86_32.cpp b/src/cpu/x86/vm/jniFastGetField_x86_32.cpp --- a/src/cpu/x86/vm/jniFastGetField_x86_32.cpp +++ b/src/cpu/x86/vm/jniFastGetField_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2010, 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,9 +85,6 @@ __ 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 @@ -205,9 +202,6 @@ __ 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 @@ -297,9 +291,6 @@ __ 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 diff --git a/src/cpu/x86/vm/jniFastGetField_x86_64.cpp b/src/cpu/x86/vm/jniFastGetField_x86_64.cpp --- a/src/cpu/x86/vm/jniFastGetField_x86_64.cpp +++ b/src/cpu/x86/vm/jniFastGetField_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2010, 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,9 +80,6 @@ // 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 @@ -181,9 +178,6 @@ // 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 diff --git a/src/cpu/x86/vm/macroAssembler_x86.cpp b/src/cpu/x86/vm/macroAssembler_x86.cpp --- a/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -5129,43 +5129,6 @@ } -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(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 diff --git a/src/cpu/x86/vm/macroAssembler_x86.hpp b/src/cpu/x86/vm/macroAssembler_x86.hpp --- a/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -297,9 +297,6 @@ 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, diff --git a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2226,11 +2226,14 @@ __ reset_last_Java_frame(thread, false); - // Unbox oop result, e.g. JNIHandles::resolve value. + // Unpack oop result if (ret_type == T_OBJECT || ret_type == T_ARRAY) { - __ resolve_jobject(rax /* value */, - thread /* thread */, - rcx /* tmp */); + Label L; + __ cmpptr(rax, (int32_t)NULL_WORD); + __ jcc(Assembler::equal, L); + __ movptr(rax, Address(rax, 0)); + __ bind(L); + __ verify_oop(rax); } if (CheckJNICalls) { diff --git a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2579,11 +2579,14 @@ __ reset_last_Java_frame(false); - // Unbox oop result, e.g. JNIHandles::resolve value. + // Unpack oop result if (ret_type == T_OBJECT || ret_type == T_ARRAY) { - __ resolve_jobject(rax /* value */, - r15_thread /* thread */, - rcx /* tmp */); + Label L; + __ testptr(rax, rax); + __ jcc(Assembler::zero, L); + __ movptr(rax, Address(rax, 0)); + __ bind(L); + __ verify_oop(rax); } if (CheckJNICalls) { diff --git a/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp b/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp --- a/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp +++ b/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1193,16 +1193,16 @@ // and result handler will pick it up { - Label no_oop, not_weak, store_result; + Label no_oop, 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); - // Unbox oop result, e.g. JNIHandles::resolve value. - __ resolve_jobject(rax /* value */, - thread /* thread */, - t /* tmp */); + __ testptr(rax, rax); + __ jcc(Assembler::zero, store_result); + __ movptr(rax, Address(rax, 0)); + __ bind(store_result); __ 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); diff --git a/src/cpu/zero/vm/cppInterpreter_zero.cpp b/src/cpu/zero/vm/cppInterpreter_zero.cpp --- a/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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,12 +406,10 @@ // 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] == 0) { + if (result[0]) + istate->set_oop_temp(*(oop *) result[0]); + else istate->set_oop_temp(NULL); - } else { - jobject handle = reinterpret_cast(result[0]); - istate->set_oop_temp(JNIHandles::resolve(handle)); - } } // Reset handle block diff --git a/src/share/vm/prims/jni.cpp b/src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp +++ b/src/share/vm/prims/jni.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -935,7 +935,8 @@ 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() { _arguments->push_jobject(va_arg(_ap, jobject)); } + inline void get_object() { jobject l = va_arg(_ap, jobject); + _arguments->push_oop(Handle((oop *)l, false)); } inline void set_ap(va_list rap) { va_copy(_ap, rap); @@ -1024,7 +1025,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_jobject((_ap++)->l); } + inline void get_object() { _arguments->push_oop(Handle((oop *)(_ap++)->l, false)); } inline void set_ap(const jvalue *rap) { _ap = rap; } diff --git a/src/share/vm/prims/jvmtiEnv.cpp b/src/share/vm/prims/jvmtiEnv.cpp --- a/src/share/vm/prims/jvmtiEnv.cpp +++ b/src/share/vm/prims/jvmtiEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1796,13 +1796,6 @@ } } - 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); KlassHandle kh (thread, k_oop); diff --git a/src/share/vm/runtime/javaCalls.cpp b/src/share/vm/runtime/javaCalls.cpp --- a/src/share/vm/runtime/javaCalls.cpp +++ b/src/share/vm/runtime/javaCalls.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -328,9 +328,9 @@ // Verify the arguments if (CheckJNICalls) { - args->verify(method, result->get_type()); + args->verify(method, result->get_type(), thread); } - else debug_only(args->verify(method, result->get_type())); + else debug_only(args->verify(method, result->get_type(), thread)); #if INCLUDE_JVMCI } #else @@ -442,43 +442,12 @@ //-------------------------------------------------------------------------------------- // 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(value); - return Handle::raw_resolve(ptr); - } - - case JavaCallArguments::value_state_jobject: - { - jobject obj = reinterpret_cast(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++) { - 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(obj); - _value_state[i] = value_state_oop; + if (_is_oop[i]) { + // Handle conversion + _value[i] = cast_from_oop(Handle::raw_resolve((oop *)_value[i])); } } // Return argument vector @@ -488,42 +457,30 @@ class SignatureChekker : public SignatureIterator { private: - int _pos; + bool *_is_oop; + int _pos; BasicType _return_type; - u_char* _value_state; - intptr_t* _value; + intptr_t* _value; + Thread* _thread; public: bool _is_return; - 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) - { + 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; + if (!is_static) { check_value(true); // Receiver must be an oop } } void check_value(bool type) { - 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); - } + guarantee(_is_oop[_pos++] == type, "signature does not match pushed arguments"); } void check_doing_return(bool state) { _is_return = state; } @@ -558,20 +515,24 @@ return; } - 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)); + // 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"); } - check_value(true); // Verify value state. + check_value(true); } void do_bool() { check_int(T_BOOLEAN); } @@ -588,7 +549,8 @@ }; -void JavaCallArguments::verify(const methodHandle& method, BasicType return_type) { +void JavaCallArguments::verify(const methodHandle& method, BasicType return_type, + Thread *thread) { guarantee(method->size_of_parameters() == size_of_parameters(), "wrong no. of arguments pushed"); // Treat T_OBJECT and T_ARRAY as the same @@ -597,11 +559,7 @@ // Check that oop information is correct Symbol* signature = method->signature(); - SignatureChekker sc(signature, - return_type, - method->is_static(), - _value_state, - _value); + SignatureChekker sc(signature, return_type, method->is_static(),_is_oop, _value, thread); sc.iterate_parameters(); sc.check_doing_return(true); sc.iterate_returntype(); diff --git a/src/share/vm/runtime/javaCalls.hpp b/src/share/vm/runtime/javaCalls.hpp --- a/src/share/vm/runtime/javaCalls.hpp +++ b/src/share/vm/runtime/javaCalls.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,11 +80,11 @@ _default_size = 8 // Must be at least # of arguments in JavaCalls methods }; - intptr_t _value_buffer [_default_size + 1]; - u_char _value_state_buffer[_default_size + 1]; + intptr_t _value_buffer [_default_size + 1]; + bool _is_oop_buffer[_default_size + 1]; intptr_t* _value; - u_char* _value_state; + bool* _is_oop; 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]; - _value_state = &_value_state_buffer[1]; + _value = &_value_buffer[1]; + _is_oop = &_is_oop_buffer[1]; _max_size = _default_size; _size = 0; @@ -101,23 +101,6 @@ 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 - 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(); } @@ -128,12 +111,11 @@ JavaCallArguments(int max_size) { if (max_size > _default_size) { - _value = NEW_RESOURCE_ARRAY(intptr_t, max_size + 1); - _value_state = NEW_RESOURCE_ARRAY(u_char, max_size + 1); + _value = NEW_RESOURCE_ARRAY(intptr_t, max_size + 1); + _is_oop = NEW_RESOURCE_ARRAY(bool, max_size + 1); - // Reserve room for potential receiver in value and state - _value++; - _value_state++; + // Reserve room for potential receiver in value and is_oop + _value++; _is_oop++; _max_size = max_size; _size = 0; @@ -154,52 +136,25 @@ } #endif - // 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_oop(Handle h) { _is_oop[_size] = true; + JNITypes::put_obj((oop)h.raw_value(), _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_int(int i) { _is_oop[_size] = false; + JNITypes::put_int(i, _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_long(jlong l) { _is_oop[_size] = false; _is_oop[_size + 1] = false; + JNITypes::put_long(l, _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) { - _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) { - _value_state[_size] = value_state_primitive; - JNITypes::put_float(f, _value, _size); - } + inline void push_float(float f) { _is_oop[_size] = false; + JNITypes::put_float(f, _value, _size); } // receiver Handle receiver() { assert(_size > 0, "must at least be one argument"); - assert(_value_state[0] == value_state_handle, - "first argument must be an oop"); + assert(_is_oop[0], "first argument must be an oop"); assert(_value[0] != 0, "receiver must be not-null"); return Handle((oop*)_value[0], false); } @@ -207,11 +162,11 @@ void set_receiver(Handle h) { assert(_start_at_zero == false, "can only be called once"); _start_at_zero = true; - _value_state--; + _is_oop--; _value--; _size++; - _value_state[0] = value_state_handle; - push_oop_impl(h.raw_value(), 0); + _is_oop[0] = true; + _value[0] = (intptr_t)h.raw_value(); } // Converts all Handles to oops, and returns a reference to parameter vector @@ -219,7 +174,7 @@ int size_of_parameters() const { return _size; } // Verify that pushed arguments fits a given method - void verify(const methodHandle& method, BasicType return_type); + void verify(const methodHandle& method, BasicType return_type, Thread *thread); }; // All calls to Java have to go via JavaCalls. Sets up the stack frame diff --git a/src/share/vm/runtime/jniHandles.cpp b/src/share/vm/runtime/jniHandles.cpp --- a/src/share/vm/runtime/jniHandles.cpp +++ b/src/share/vm/runtime/jniHandles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,9 +31,6 @@ #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; @@ -95,48 +92,28 @@ 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()); - } - // Add weak tag. - assert(is_ptr_aligned(res, weak_tag_alignment), "invariant"); - char* tptr = reinterpret_cast(res) + weak_tag_value; - res = reinterpret_cast(tptr); + MutexLocker ml(JNIGlobalHandle_lock); + assert(Universe::heap()->is_in_reserved(obj()), "sanity check"); + res = _weak_global_handles->allocate_handle(obj()); } else { CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); } return res; } -template -oop JNIHandles::resolve_jweak(jweak handle) { - assert(is_jweak(handle), "precondition"); - oop result = jweak_ref(handle); - result = guard_value(result); -#if INCLUDE_ALL_GCS - if (result != NULL && UseG1GC) { - G1SATBCardTableModRefBS::enqueue(result); - } -#endif // INCLUDE_ALL_GCS - return result; -} - -template oop JNIHandles::resolve_jweak(jweak); -template oop JNIHandles::resolve_jweak(jweak); void JNIHandles::destroy_global(jobject handle) { if (handle != NULL) { assert(is_global_handle(handle), "Invalid delete of global JNI handle"); - jobject_ref(handle) = deleted_handle(); + *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it } } void JNIHandles::destroy_weak_global(jobject handle) { if (handle != NULL) { - jweak_ref(handle) = deleted_handle(); + 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 } } diff --git a/src/share/vm/runtime/jniHandles.hpp b/src/share/vm/runtime/jniHandles.hpp --- a/src/share/vm/runtime/jniHandles.hpp +++ b/src/share/vm/runtime/jniHandles.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,28 +40,7 @@ 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 inline static oop guard_value(oop value); - template inline static oop resolve_impl(jobject handle); - template 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 @@ -197,85 +176,36 @@ #endif }; -inline bool JNIHandles::is_jweak(jobject handle) { - STATIC_ASSERT(weak_tag_size == 1); - STATIC_ASSERT(weak_tag_value == 1); - return (reinterpret_cast(handle) & weak_tag_mask) != 0; -} - -inline oop& JNIHandles::jobject_ref(jobject handle) { - assert(!is_jweak(handle), "precondition"); - return *reinterpret_cast(handle); -} - -inline oop& JNIHandles::jweak_ref(jobject handle) { - assert(is_jweak(handle), "precondition"); - char* ptr = reinterpret_cast(handle) - weak_tag_value; - return *reinterpret_cast(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 -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 -inline oop JNIHandles::resolve_impl(jobject handle) { - assert(handle != NULL, "precondition"); - oop result; - if (is_jweak(handle)) { // Unlikely - result = resolve_jweak(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(result); - } - return result; -} inline oop JNIHandles::resolve(jobject handle) { - oop result = NULL; - if (handle != NULL) { - result = resolve_impl(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"); 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) { - oop result = NULL; - if (handle != NULL) { - result = resolve_impl(handle); - } + if (handle == NULL) return NULL; + oop result = *(oop*)handle; + if (result == NULL || result == badJNIHandle) return NULL; return result; -} +}; + inline oop JNIHandles::resolve_non_null(jobject handle) { assert(handle != NULL, "JNI handle should not be null"); - oop result = resolve_impl(handle); - assert(result != NULL, "NULL read from jni handle"); + 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."); return result; -} +}; inline void JNIHandles::destroy_local(jobject handle) { if (handle != NULL) { - jobject_ref(handle) = deleted_handle(); + *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it } } diff --git a/src/share/vm/shark/sharkNativeWrapper.cpp b/src/share/vm/shark/sharkNativeWrapper.cpp --- a/src/share/vm/shark/sharkNativeWrapper.cpp +++ b/src/share/vm/shark/sharkNativeWrapper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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,7 +300,6 @@ 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); diff --git a/test/runtime/jni/CallWithJNIWeak/CallWithJNIWeak.java b/test/runtime/jni/CallWithJNIWeak/CallWithJNIWeak.java deleted file mode 100644 --- a/test/runtime/jni/CallWithJNIWeak/CallWithJNIWeak.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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); - } - } -} diff --git a/test/runtime/jni/CallWithJNIWeak/libCallWithJNIWeak.c b/test/runtime/jni/CallWithJNIWeak/libCallWithJNIWeak.c deleted file mode 100644 --- a/test/runtime/jni/CallWithJNIWeak/libCallWithJNIWeak.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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 - -/* - * 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); -} diff --git a/test/runtime/jni/ReturnJNIWeak/ReturnJNIWeak.java b/test/runtime/jni/ReturnJNIWeak/ReturnJNIWeak.java deleted file mode 100644 --- a/test/runtime/jni/ReturnJNIWeak/ReturnJNIWeak.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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(); - } -} diff --git a/test/runtime/jni/ReturnJNIWeak/libReturnJNIWeak.c b/test/runtime/jni/ReturnJNIWeak/libReturnJNIWeak.c deleted file mode 100644 --- a/test/runtime/jni/ReturnJNIWeak/libReturnJNIWeak.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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; -}