Mercurial > hg > jdk9-shenandoah > hotspot
changeset 9454:1538d2529fb8
Simplify interpreter write barrier.
author | rkennke |
---|---|
date | Thu, 20 Aug 2015 17:52:14 +0200 |
parents | 1650eab95d25 |
children | 2cb85c37fb07 |
files | src/cpu/x86/vm/interp_masm_x86.cpp src/cpu/x86/vm/shenandoahBarrierSet_x86.cpp src/cpu/x86/vm/templateTable_x86.cpp src/share/vm/gc/shared/barrierSet.hpp src/share/vm/gc/shenandoah/shenandoahBarrierSet.hpp |
diffstat | 5 files changed, 80 insertions(+), 190 deletions(-) [+] |
line wrap: on
line diff
--- a/src/cpu/x86/vm/interp_masm_x86.cpp Thu Aug 20 17:52:12 2015 +0200 +++ b/src/cpu/x86/vm/interp_masm_x86.cpp Thu Aug 20 17:52:14 2015 +0200 @@ -1063,7 +1063,7 @@ movptr(obj_reg, Address(lock_reg, obj_offset)); // Need to preemptively evacuate obj because we CAS the mark word later. - oopDesc::bs()->interpreter_write_barrier(this, obj_reg, false, 0, 1, BarrierSet::ss_c_rarg1); + oopDesc::bs()->interpreter_write_barrier(this, obj_reg); if (UseBiasedLocking) { biased_locking_enter(lock_reg, obj_reg, swap_reg, tmp_reg, false, done, &slow_case); @@ -1161,7 +1161,7 @@ movptr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes())); // Need to preemptively evacuate obj because we CAS the mark word later. - oopDesc::bs()->interpreter_write_barrier(this, obj_reg, false, 0, 1, BarrierSet::ss_c_rarg1); + oopDesc::bs()->interpreter_write_barrier(this, obj_reg); // Free entry movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD);
--- a/src/cpu/x86/vm/shenandoahBarrierSet_x86.cpp Thu Aug 20 17:52:12 2015 +0200 +++ b/src/cpu/x86/vm/shenandoahBarrierSet_x86.cpp Thu Aug 20 17:52:14 2015 +0200 @@ -167,7 +167,7 @@ } } -void ShenandoahBarrierSet::interpreter_write_barrier(MacroAssembler* masm, Register dst, bool explicit_null_check, int stack_adjust, int num_state_save, ...) { +void ShenandoahBarrierSet::interpreter_write_barrier(MacroAssembler* masm, Register dst) { if (! ShenandoahWriteBarrier) { assert(! ShenandoahConcurrentEvacuation, "Can only do this without concurrent evacuation"); @@ -179,15 +179,6 @@ Label done; - // Resolve oop first. - // TODO: Make this not-null-checking as soon as we have implicit null checks in c1! - - - if (explicit_null_check) { - __ testptr(dst, dst); - __ jcc(Assembler::zero, done); - } - Address evacuation_in_progress = Address(r15_thread, in_bytes(JavaThread::evacuation_in_progress_offset())); __ cmpb(evacuation_in_progress, 0); @@ -210,128 +201,55 @@ __ jcc(Assembler::zero, done); - intArray save_states = intArray(num_state_save); - va_list vl; - va_start(vl, num_state_save); - for (int i = 0; i < num_state_save; i++) { - save_states.at_put(i, va_arg(vl, int)); - } - va_end(vl); + __ push(rscratch1); - __ push(rscratch1); - for (int i = 0; i < num_state_save; i++) { - switch (save_states[i]) { - case noreg: - __ subptr(rsp, Interpreter::stackElementSize); - break; - case ss_rax: - __ push(rax); - break; - case ss_rbx: - __ push(rbx); - break; - case ss_rcx: - __ push(rcx); - break; - case ss_rdx: - __ push(rdx); - break; - case ss_rsi: - __ push(rsi); - break; - case ss_rdi: - __ push(rdi); - break; - case ss_r13: - __ push(r13); - break; - case ss_ftos: - __ subptr(rsp, wordSize); - __ movflt(Address(rsp, 0), xmm0); - break; - case ss_dtos: - __ subptr(rsp, 2 * wordSize); - __ movdbl(Address(rsp, 0), xmm0); - break; - case ss_c_rarg0: - __ push(c_rarg0); - break; - case ss_c_rarg1: - __ push(c_rarg1); - break; - case ss_c_rarg2: - __ push(c_rarg2); - break; - case ss_c_rarg3: - __ push(c_rarg3); - break; - case ss_c_rarg4: - __ push(c_rarg4); - break; - - default: - ShouldNotReachHere(); - } + // Save possibly live regs. + if (dst != rax) { + __ push(rax); + } + if (dst != rbx) { + __ push(rbx); + } + if (dst != rcx) { + __ push(rcx); + } + if (dst != rdx) { + __ push(rdx); + } + if (dst != c_rarg1) { + __ push(c_rarg1); } + __ subptr(rsp, 2 * wordSize); + __ movdbl(Address(rsp, 0), xmm0); + + // Call into runtime __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahBarrierSet::resolve_and_maybe_copy_oop_interp), dst); __ mov(rscratch1, rax); - for (int i = num_state_save - 1; i >= 0; i--) { - switch (save_states[i]) { - case noreg: - __ addptr(rsp, Interpreter::stackElementSize); - break; - case ss_rax: - __ pop(rax); - break; - case ss_rbx: - __ pop(rbx); - break; - case ss_rcx: - __ pop(rcx); - break; - case ss_rdx: - __ pop(rdx); - break; - case ss_rsi: - __ pop(rsi); - break; - case ss_rdi: - __ pop(rdi); - break; - case ss_r13: - __ pop(r13); - break; - case ss_ftos: - __ movflt(xmm0, Address(rsp, 0)); - __ addptr(rsp, wordSize); - break; - case ss_dtos: - __ movdbl(xmm0, Address(rsp, 0)); - __ addptr(rsp, 2 * Interpreter::stackElementSize); - break; - case ss_c_rarg0: - __ pop(c_rarg0); - break; - case ss_c_rarg1: - __ pop(c_rarg1); - break; - case ss_c_rarg2: - __ pop(c_rarg2); - break; - case ss_c_rarg3: - __ pop(c_rarg3); - break; - case ss_c_rarg4: - __ pop(c_rarg4); - break; - default: - ShouldNotReachHere(); - } + // Restore possibly live regs. + __ movdbl(xmm0, Address(rsp, 0)); + __ addptr(rsp, 2 * Interpreter::stackElementSize); + + if (dst != c_rarg1) { + __ pop(c_rarg1); + } + if (dst != rdx) { + __ pop(rdx); + } + if (dst != rcx) { + __ pop(rcx); + } + if (dst != rbx) { + __ pop(rbx); + } + if (dst != rax) { + __ pop(rax); } + // Move result into dst reg. __ mov(dst, rscratch1); + __ pop(rscratch1); __ bind(done);
--- a/src/cpu/x86/vm/templateTable_x86.cpp Thu Aug 20 17:52:12 2015 +0200 +++ b/src/cpu/x86/vm/templateTable_x86.cpp Thu Aug 20 17:52:14 2015 +0200 @@ -1007,7 +1007,7 @@ // rbx: index // rdx: array index_check(rdx, rbx); // prefer index in rbx - oopDesc::bs()->interpreter_write_barrier(_masm, rdx, false, 0, 3, BarrierSet::noreg, BarrierSet::ss_rbx, BarrierSet::ss_rax); + oopDesc::bs()->interpreter_write_barrier(_masm, rdx); __ movl(Address(rdx, rbx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_INT)), @@ -1022,7 +1022,7 @@ // rdx: high(value) index_check(rcx, rbx); // prefer index in rbx, // rbx,: index - oopDesc::bs()->interpreter_write_barrier(_masm, rcx, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_rbx, BarrierSet::ss_rax, BarrierSet::ss_rdx); + oopDesc::bs()->interpreter_write_barrier(_masm, rcx); __ movptr(Address(rcx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize), rax); NOT_LP64(__ movl(Address(rcx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG) + 1 * wordSize), rdx)); } @@ -1035,7 +1035,7 @@ // rbx: index // rdx: array index_check(rdx, rbx); // prefer index in rbx - oopDesc::bs()->interpreter_write_barrier(_masm, rdx, false, 0, 3, BarrierSet::noreg, BarrierSet::ss_rbx, BarrierSet::ss_ftos); + oopDesc::bs()->interpreter_write_barrier(_masm, rdx); LP64_ONLY(__ movflt(Address(rdx, rbx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_FLOAT)), @@ -1050,7 +1050,7 @@ // rbx: index // rdx: array index_check(rdx, rbx); // prefer index in rbx - oopDesc::bs()->interpreter_write_barrier(_masm, rdx, false, 0, 3, BarrierSet::noreg, BarrierSet::ss_rbx, BarrierSet::ss_dtos); + oopDesc::bs()->interpreter_write_barrier(_masm, rdx); LP64_ONLY(__ movdbl(Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_DOUBLE)), @@ -1071,7 +1071,7 @@ arrayOopDesc::base_offset_in_bytes(T_OBJECT)); index_check_without_pop(rdx, rcx); // kills rbx - oopDesc::bs()->interpreter_write_barrier(_masm, rdx, false, 3, 3, BarrierSet::noreg, BarrierSet::ss_rcx, BarrierSet::ss_rax); + oopDesc::bs()->interpreter_write_barrier(_masm, rdx); __ testptr(rax, rax); __ jcc(Assembler::zero, is_null); @@ -1120,7 +1120,7 @@ // rbx: index // rdx: array index_check(rdx, rbx); // prefer index in rbx - oopDesc::bs()->interpreter_write_barrier(_masm, rdx, false, 0, 3, BarrierSet::noreg, BarrierSet::ss_rbx, BarrierSet::ss_rax); + oopDesc::bs()->interpreter_write_barrier(_masm, rdx); __ movb(Address(rdx, rbx, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)), @@ -1134,7 +1134,7 @@ // rbx: index // rdx: array index_check(rdx, rbx); // prefer index in rbx - oopDesc::bs()->interpreter_write_barrier(_masm, rdx, false, 0, 3, BarrierSet::noreg, BarrierSet::ss_rbx, BarrierSet::ss_rax); + oopDesc::bs()->interpreter_write_barrier(_masm, rdx); __ movw(Address(rdx, rbx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)), @@ -2235,12 +2235,18 @@ transition(atos, vtos); // assume branch is more often taken than not (loops use backward branches) Label not_taken; - // NOTE: We need to preemptively evacuate the oops here (for Shenandoah GC), because - // we might get false negatives if both operands are the same, but another - // thread evacuates between the load of the 1st and 2nd operand. - oopDesc::bs()->interpreter_write_barrier(_masm, rax, true, 0, 0); __ pop_ptr(rdx); - oopDesc::bs()->interpreter_read_barrier(_masm, rdx); + if (UseShenandoahGC) { + // For Shenandoah, if the objects are not equal, we try again after + // resolving both objects through a read barrier, to make sure we're + // not comparing from-space and to-space copies of the same object. + Label eq; + __ cmpptr(rdx, rax); + __ jcc(Assembler::equal, eq); + oopDesc::bs()->interpreter_read_barrier(_masm, rax); + oopDesc::bs()->interpreter_read_barrier(_masm, rdx); + __ bind(eq); + } __ cmpptr(rdx, rax); __ jcc(j_not(cc), not_taken); branch(false, false); @@ -2954,10 +2960,8 @@ __ pop(btos); if (!is_static) { pop_and_check_object(obj); - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); - } else { - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 3, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); } + oopDesc::bs()->interpreter_write_barrier(_masm, obj); __ movb(field, rax); if (!is_static && rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_bputfield, bc, rbx, true, byte_no); @@ -2974,10 +2978,8 @@ __ pop(atos); if (!is_static) { pop_and_check_object(obj); - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); - } else { - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 3, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); } + oopDesc::bs()->interpreter_write_barrier(_masm, obj); // Store into the field do_oop_store(_masm, field, rax, _bs->kind(), false); if (!is_static && rc == may_rewrite) { @@ -2995,10 +2997,8 @@ __ pop(itos); if (!is_static) { pop_and_check_object(obj); - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); - } else { - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 3, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); } + oopDesc::bs()->interpreter_write_barrier(_masm, obj); __ movl(field, rax); if (!is_static && rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_iputfield, bc, rbx, true, byte_no); @@ -3015,10 +3015,8 @@ __ pop(ctos); if (!is_static) { pop_and_check_object(obj); - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); - } else { - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 3, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); } + oopDesc::bs()->interpreter_write_barrier(_masm, obj); __ movw(field, rax); if (!is_static && rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_cputfield, bc, rbx, true, byte_no); @@ -3035,10 +3033,8 @@ __ pop(stos); if (!is_static) { pop_and_check_object(obj); - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); - } else { - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 3, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); } + oopDesc::bs()->interpreter_write_barrier(_masm, obj); __ movw(field, rax); if (!is_static && rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_sputfield, bc, rbx, true, byte_no); @@ -3056,10 +3052,8 @@ __ pop(ltos); if (!is_static) { pop_and_check_object(obj); - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); - } else { - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 3, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); } + oopDesc::bs()->interpreter_write_barrier(_masm, obj); __ movq(field, rax); if (!is_static && rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_lputfield, bc, rbx, true, byte_no); @@ -3107,10 +3101,8 @@ __ pop(ftos); if (!is_static) { pop_and_check_object(obj); - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_ftos, BarrierSet::ss_rbx, BarrierSet::ss_rdx); - } else { - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 3, BarrierSet::ss_ftos, BarrierSet::ss_rbx, BarrierSet::ss_rdx); } + oopDesc::bs()->interpreter_write_barrier(_masm, obj); NOT_LP64( __ fstp_s(field);) LP64_ONLY( __ movflt(field, xmm0);) if (!is_static && rc == may_rewrite) { @@ -3130,10 +3122,8 @@ __ pop(dtos); if (!is_static) { pop_and_check_object(obj); - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_dtos, BarrierSet::ss_rbx, BarrierSet::ss_rdx); - } else { - oopDesc::bs()->interpreter_write_barrier(_masm, obj, false, 0, 3, BarrierSet::ss_dtos, BarrierSet::ss_rbx, BarrierSet::ss_rdx); } + oopDesc::bs()->interpreter_write_barrier(_masm, obj); NOT_LP64( __ fstp_d(field);) LP64_ONLY( __ movdbl(field, xmm0);) if (!is_static && rc == may_rewrite) { @@ -3261,11 +3251,11 @@ // access field switch (bytecode()) { case Bytecodes::_fast_aputfield: - oopDesc::bs()->interpreter_write_barrier(_masm, rcx, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); + oopDesc::bs()->interpreter_write_barrier(_masm, rcx); do_oop_store(_masm, field, rax, _bs->kind(), false); break; case Bytecodes::_fast_lputfield: - oopDesc::bs()->interpreter_write_barrier(_masm, rcx, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); + oopDesc::bs()->interpreter_write_barrier(_masm, rcx); #ifdef _LP64 __ movq(field, rax); #else @@ -3273,26 +3263,26 @@ #endif break; case Bytecodes::_fast_iputfield: - oopDesc::bs()->interpreter_write_barrier(_masm, rcx, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); + oopDesc::bs()->interpreter_write_barrier(_masm, rcx); __ movl(field, rax); break; case Bytecodes::_fast_bputfield: - oopDesc::bs()->interpreter_write_barrier(_masm, rcx, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); + oopDesc::bs()->interpreter_write_barrier(_masm, rcx); __ movb(field, rax); break; case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: - oopDesc::bs()->interpreter_write_barrier(_masm, rcx, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_rax, BarrierSet::ss_rbx, BarrierSet::ss_rdx); + oopDesc::bs()->interpreter_write_barrier(_masm, rcx); __ movw(field, rax); break; case Bytecodes::_fast_fputfield: - oopDesc::bs()->interpreter_write_barrier(_masm, rcx, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_ftos, BarrierSet::ss_rbx, BarrierSet::ss_rdx); + oopDesc::bs()->interpreter_write_barrier(_masm, rcx); NOT_LP64( __ fstp_s(field); ) LP64_ONLY( __ movflt(field, xmm0);) break; case Bytecodes::_fast_dputfield: - oopDesc::bs()->interpreter_write_barrier(_masm, rcx, false, 0, 4, BarrierSet::noreg, BarrierSet::ss_dtos, BarrierSet::ss_rbx, BarrierSet::ss_rdx); + oopDesc::bs()->interpreter_write_barrier(_masm, rcx); NOT_LP64( __ fstp_d(field); ) LP64_ONLY( __ movdbl(field, xmm0);) break; @@ -4176,7 +4166,7 @@ // We need to preemptively evacuate the object, because we later compare // it to objects in the BasicObjectLock list, and we might get false negatives // if another thread evacuates the object in the meantime. See acmp. - oopDesc::bs()->interpreter_write_barrier(_masm, rax, false, 0, 0); + oopDesc::bs()->interpreter_write_barrier(_masm, rax); const Address monitor_block_top( rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); @@ -4284,7 +4274,7 @@ // We need to preemptively evacuate the object, because we later compare // it to objects in the BasicObjectLock list, and we might get false negatives // if another thread evacuates the object in the meantime. See acmp. - oopDesc::bs()->interpreter_write_barrier(_masm, rax, false, 0, 0); + oopDesc::bs()->interpreter_write_barrier(_masm, rax); const Address monitor_block_top( rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize);
--- a/src/share/vm/gc/shared/barrierSet.hpp Thu Aug 20 17:52:12 2015 +0200 +++ b/src/share/vm/gc/shared/barrierSet.hpp Thu Aug 20 17:52:14 2015 +0200 @@ -90,24 +90,6 @@ TargetUninitialized = 1 }; - enum SaveState { - noreg, - ss_rax, - ss_rbx, - ss_rcx, - ss_rdx, - ss_rsi, - ss_rdi, - ss_ftos, - ss_dtos, - ss_r13, - ss_c_rarg0, - ss_c_rarg1, - ss_c_rarg2, - ss_c_rarg3, - ss_c_rarg4 - }; - protected: // Some barrier sets create tables whose elements correspond to parts of // the heap; the CardTableModRefBS is an example. Such barrier sets will @@ -252,7 +234,7 @@ // Default implementation does nothing. } - virtual void interpreter_write_barrier(MacroAssembler* masm, Register dst, bool explicit_null_check, int stack_adjust, int num_save_state, ...) { + virtual void interpreter_write_barrier(MacroAssembler* masm, Register dst) { // Default implementation does nothing. } #endif
--- a/src/share/vm/gc/shenandoah/shenandoahBarrierSet.hpp Thu Aug 20 17:52:12 2015 +0200 +++ b/src/share/vm/gc/shenandoah/shenandoahBarrierSet.hpp Thu Aug 20 17:52:14 2015 +0200 @@ -166,7 +166,7 @@ public: virtual void interpreter_read_barrier(MacroAssembler* masm, Register dst); virtual void interpreter_read_barrier_not_null(MacroAssembler* masm, Register dst); - void interpreter_write_barrier(MacroAssembler* masm, Register dst, bool explicit_null_check, int stack_adjust, int num_save_state, ...); + void interpreter_write_barrier(MacroAssembler* masm, Register dst); private: void compile_resolve_oop_runtime(MacroAssembler* masm, Register dst);