diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp @@ -22,8 +22,14 @@ */ #include "precompiled.hpp" +#include "gc/shenandoah/brooksPointer.hpp" #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" +#include "gc/shenandoah/shenandoahConnectionMatrix.hpp" +#include "gc/shenandoah/shenandoahHeapRegion.hpp" +#include "gc/shenandoah/shenandoahThreadLocalData.hpp" +#include "interpreter/interpreter.hpp" +#include "runtime/sharedRuntime.hpp" #include "runtime/thread.hpp" #define __ masm-> @@ -59,8 +65,7 @@ #endif Label filtered; - Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() + - SATBMarkQueue::byte_offset_of_active())); + Address in_progress(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_active_offset())); // Is marking active? if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { __ cmpl(in_progress, 0); @@ -146,3 +151,483 @@ __ popa(); } } + +void ShenandoahBarrierSetAssembler::shenandoah_write_barrier_pre(MacroAssembler* masm, + Register obj, + Register pre_val, + Register thread, + Register tmp, + bool tosca_live, + bool expand_call) { + + if (ShenandoahConditionalSATBBarrier) { + Label done; + Address gc_state(thread, in_bytes(ShenandoahThreadLocalData::gc_state_offset())); + __ testb(gc_state, ShenandoahHeap::MARKING); + __ jcc(Assembler::zero, done); // Skip SATB barrier when conc-mark is not active + satb_write_barrier_pre(masm, obj, pre_val, thread, tmp, tosca_live, expand_call); + __ bind(done); + } + if (ShenandoahSATBBarrier) { + satb_write_barrier_pre(masm, obj, pre_val, thread, tmp, tosca_live, expand_call); + } +} + +void ShenandoahBarrierSetAssembler::satb_write_barrier_pre(MacroAssembler* masm, + Register obj, + Register pre_val, + Register thread, + Register tmp, + bool tosca_live, + bool expand_call) { + // If expand_call is true then we expand the call_VM_leaf macro + // directly to skip generating the check by + // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp. + +#ifdef _LP64 + assert(thread == r15_thread, "must be"); +#endif // _LP64 + + Label done; + Label runtime; + + assert(pre_val != noreg, "check this code"); + + if (obj != noreg) { + assert_different_registers(obj, pre_val, tmp); + assert(pre_val != rax, "check this code"); + } + + Address in_progress(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_active_offset())); + Address index(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset())); + Address buffer(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset())); + + Address gc_state(thread, in_bytes(ShenandoahThreadLocalData::gc_state_offset())); + __ testb(gc_state, ShenandoahHeap::MARKING | ShenandoahHeap::TRAVERSAL); + __ jcc(Assembler::zero, done); + + // Do we need to load the previous value? + if (obj != noreg) { + __ load_heap_oop(pre_val, Address(obj, 0), noreg, noreg, AS_RAW); + } + + // Is the previous value null? + __ cmpptr(pre_val, (int32_t) NULL_WORD); + __ jcc(Assembler::equal, done); + + // Can we store original value in the thread's buffer? + // Is index == 0? + // (The index field is typed as size_t.) + + __ movptr(tmp, index); // tmp := *index_adr + __ cmpptr(tmp, 0); // tmp == 0? + __ jcc(Assembler::equal, runtime); // If yes, goto runtime + + __ subptr(tmp, wordSize); // tmp := tmp - wordSize + __ movptr(index, tmp); // *index_adr := tmp + __ addptr(tmp, buffer); // tmp := tmp + *buffer_adr + + // Record the previous value + __ movptr(Address(tmp, 0), pre_val); + __ jmp(done); + + __ bind(runtime); + // save the live input values + if(tosca_live) __ push(rax); + + if (obj != noreg && obj != rax) + __ push(obj); + + if (pre_val != rax) + __ push(pre_val); + + // Calling the runtime using the regular call_VM_leaf mechanism generates + // code (generated by InterpreterMacroAssember::call_VM_leaf_base) + // that checks that the *(ebp+frame::interpreter_frame_last_sp) == NULL. + // + // If we care generating the pre-barrier without a frame (e.g. in the + // intrinsified Reference.get() routine) then ebp might be pointing to + // the caller frame and so this check will most likely fail at runtime. + // + // Expanding the call directly bypasses the generation of the check. + // So when we do not have have a full interpreter frame on the stack + // expand_call should be passed true. + + NOT_LP64( __ push(thread); ) + + if (expand_call) { + LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); ) +#ifdef _LP64 + if (c_rarg1 != thread) { + __ mov(c_rarg1, thread); + } + if (c_rarg0 != pre_val) { + __ mov(c_rarg0, pre_val); + } +#else + __ push(thread); + __ push(pre_val); +#endif + __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), 2); + } else { + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread); + } + + NOT_LP64( __ pop(thread); ) + + // save the live input values + if (pre_val != rax) + __ pop(pre_val); + + if (obj != noreg && obj != rax) + __ pop(obj); + + if(tosca_live) __ pop(rax); + + __ bind(done); +} + +void ShenandoahBarrierSetAssembler::shenandoah_write_barrier_post(MacroAssembler* masm, + Register store_addr, + Register new_val, + Register thread, + Register tmp, + Register tmp2) { + assert(UseShenandoahGC, "why else should we be here?"); + + if (! UseShenandoahMatrix) { + // No need for that barrier if not using matrix. + return; + } + + Label done; + __ testptr(new_val, new_val); + __ jcc(Assembler::zero, done); + ShenandoahConnectionMatrix* matrix = ShenandoahHeap::heap()->connection_matrix(); + address matrix_addr = matrix->matrix_addr(); + __ movptr(rscratch1, (intptr_t) ShenandoahHeap::heap()->base()); + // Compute to-region index + __ movptr(tmp, new_val); + __ subptr(tmp, rscratch1); + __ shrptr(tmp, ShenandoahHeapRegion::region_size_bytes_shift_jint()); + // Compute from-region index + __ movptr(tmp2, store_addr); + __ subptr(tmp2, rscratch1); + __ shrptr(tmp2, ShenandoahHeapRegion::region_size_bytes_shift_jint()); + // Compute matrix index + __ imulptr(tmp, tmp, matrix->stride_jint()); + __ addptr(tmp, tmp2); + // Address is _matrix[to * stride + from] + __ movptr(rscratch1, (intptr_t) matrix_addr); + // Test if the element is already set. + __ cmpb(Address(rscratch1, tmp, Address::times_1), 0); + __ jcc(Assembler::notEqual, done); + // Store true, if not yet set. + __ movb(Address(rscratch1, tmp, Address::times_1), 1); + __ bind(done); +} + +void ShenandoahBarrierSetAssembler::read_barrier(MacroAssembler* masm, Register dst) { + if (ShenandoahReadBarrier) { + read_barrier_impl(masm, dst); + } +} + +void ShenandoahBarrierSetAssembler::read_barrier_impl(MacroAssembler* masm, Register dst) { + assert(UseShenandoahGC && (ShenandoahReadBarrier || ShenandoahStoreValReadBarrier), "should be enabled"); + Label is_null; + __ testptr(dst, dst); + __ jcc(Assembler::zero, is_null); + read_barrier_not_null_impl(masm, dst); + __ bind(is_null); +} + +void ShenandoahBarrierSetAssembler::read_barrier_not_null(MacroAssembler* masm, Register dst) { + if (ShenandoahReadBarrier) { + read_barrier_not_null_impl(masm, dst); + } +} + +void ShenandoahBarrierSetAssembler::read_barrier_not_null_impl(MacroAssembler* masm, Register dst) { + assert(UseShenandoahGC && (ShenandoahReadBarrier || ShenandoahStoreValReadBarrier), "should be enabled"); + __ movptr(dst, Address(dst, BrooksPointer::byte_offset())); +} + + +void ShenandoahBarrierSetAssembler::write_barrier(MacroAssembler* masm, Register dst) { + if (ShenandoahWriteBarrier) { + write_barrier_impl(masm, dst); + } +} + +void ShenandoahBarrierSetAssembler::write_barrier_impl(MacroAssembler* masm, Register dst) { + assert(UseShenandoahGC && (ShenandoahWriteBarrier || ShenandoahStoreValWriteBarrier || ShenandoahStoreValEnqueueBarrier), "should be enabled"); +#ifdef _LP64 + assert(dst != rscratch1, "different regs"); + + Label done; + + Address gc_state(r15_thread, in_bytes(ShenandoahThreadLocalData::gc_state_offset())); + __ testb(gc_state, ShenandoahHeap::EVACUATION | ShenandoahHeap::PARTIAL | ShenandoahHeap::TRAVERSAL); + + // Now check if evacuation is in progress. + read_barrier_not_null(masm, dst); + + __ jcc(Assembler::zero, done); + __ push(rscratch1); + __ push(rscratch2); + + __ movptr(rscratch1, dst); + __ shrptr(rscratch1, ShenandoahHeapRegion::region_size_bytes_shift_jint()); + __ movptr(rscratch2, (intptr_t) ShenandoahHeap::in_cset_fast_test_addr()); + __ movbool(rscratch2, Address(rscratch2, rscratch1, Address::times_1)); + __ testb(rscratch2, 0x1); + + __ pop(rscratch2); + __ pop(rscratch1); + + __ jcc(Assembler::zero, done); + + __ push(rscratch1); + + // 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 * Interpreter::stackElementSize); + __ movdbl(Address(rsp, 0), xmm0); + + // Call into runtime + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahBarrierSet::write_barrier_IRT), dst); + __ mov(rscratch1, rax); + + // 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); +#else + Unimplemented(); +#endif +} + +void ShenandoahBarrierSetAssembler::storeval_barrier(MacroAssembler* masm, Register dst, Register tmp) { + if (ShenandoahStoreValReadBarrier || ShenandoahStoreValWriteBarrier || ShenandoahStoreValEnqueueBarrier) { + storeval_barrier_impl(masm, dst, tmp); + } +} + +void ShenandoahBarrierSetAssembler::storeval_barrier_impl(MacroAssembler* masm, Register dst, Register tmp) { + assert(UseShenandoahGC && (ShenandoahStoreValReadBarrier || ShenandoahStoreValWriteBarrier || ShenandoahStoreValEnqueueBarrier), "should be enabled"); + + if (dst == noreg) return; + +#ifdef _LP64 + if (ShenandoahStoreValWriteBarrier || ShenandoahStoreValEnqueueBarrier) { + Label is_null; + __ testptr(dst, dst); + __ jcc(Assembler::zero, is_null); + write_barrier_impl(masm, dst); + __ bind(is_null); + } + + if (ShenandoahStoreValEnqueueBarrier) { + // The set of registers to be saved+restored is the same as in the write-barrier above. + // Those are the commonly used registers in the interpreter. + __ push(rbx); + __ push(rcx); + __ push(rdx); + __ push(c_rarg1); + __ subptr(rsp, 2 * Interpreter::stackElementSize); + __ movdbl(Address(rsp, 0), xmm0); + + satb_write_barrier_pre(masm, noreg, dst, r15_thread, tmp, true, false); + __ movdbl(xmm0, Address(rsp, 0)); + __ addptr(rsp, 2 * Interpreter::stackElementSize); + __ pop(c_rarg1); + __ pop(rdx); + __ pop(rcx); + __ pop(rbx); + } + if (ShenandoahStoreValReadBarrier) { + read_barrier_impl(masm, dst); + } +#else + Unimplemented(); +#endif +} + +void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Register dst, Address src, Register tmp1, Register tmp_thread) { + bool on_oop = type == T_OBJECT || type == T_ARRAY; + bool in_heap = (decorators & IN_HEAP) != 0; + bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; + bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; + bool on_reference = on_weak || on_phantom; + // tty->print_cr("RB src.base: %s", src.base()->name()); + // __ verify_oop(src.base(), "broken oop before RB"); + /* + if (in_heap) { + read_barrier_not_null(masm, src.base()); + } + */ + // __ verify_oop(src.base(), "broken oop before RB"); + BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); + if (ShenandoahKeepAliveBarrier && on_oop && on_reference) { + const Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread); + NOT_LP64(__ get_thread(thread)); + + // Generate the SATB pre-barrier code to log the value of + // the referent field in an SATB buffer. + shenandoah_write_barrier_pre(masm /* masm */, + noreg /* obj */, + dst /* pre_val */, + thread /* thread */, + tmp1 /* tmp */, + true /* tosca_live */, + true /* expand_call */); + } +} + +void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2) { + + bool in_heap = (decorators & IN_HEAP) != 0; + bool in_concurrent_root = (decorators & IN_CONCURRENT_ROOT) != 0; + /* + if (in_heap) { + write_barrier(masm, dst.base()); + } + */ + if (type == T_OBJECT || type == T_ARRAY) { + bool needs_pre_barrier = in_heap || in_concurrent_root; + bool needs_post_barrier = val != noreg && in_heap && UseShenandoahMatrix; + + Register tmp3 = LP64_ONLY(r8) NOT_LP64(rsi); + Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx); + // flatten object address if needed + // We do it regardless of precise because we need the registers + if (dst.index() == noreg && dst.disp() == 0) { + if (dst.base() != tmp1) { + __ movptr(tmp1, dst.base()); + } + } else { + __ lea(tmp1, dst); + } + +#ifndef _LP64 + InterpreterMacroAssembler *imasm = static_cast(masm); +#endif + + NOT_LP64(__ get_thread(rcx)); + NOT_LP64(imasm->save_bcp()); + + if (needs_pre_barrier) { + shenandoah_write_barrier_pre(masm /*masm*/, + tmp1 /* obj */, + tmp2 /* pre_val */, + rthread /* thread */, + tmp3 /* tmp */, + val != noreg /* tosca_live */, + false /* expand_call */); + } + if (val == noreg) { + BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg); + } else { + storeval_barrier(masm, val, tmp3); + Register new_val = val; + if (needs_post_barrier) { + if (UseCompressedOops) { + new_val = tmp2; + __ movptr(new_val, val); + } + } + BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg); + + if (needs_post_barrier) { + shenandoah_write_barrier_post(masm /*masm*/, + tmp1 /* store_adr */, + new_val /* new_val */, + rthread /* thread */, + tmp3 /* tmp */, + tmp2 /* tmp2 */); + } + } + NOT_LP64(imasm->restore_bcp()); + + } else { + BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2); + } +} + +void ShenandoahBarrierSetAssembler::obj_equals(MacroAssembler* masm, DecoratorSet decorators, Register op1, Register op2) { + __ cmpptr(op1, op2); + if (ShenandoahAcmpBarrier) { + Label done; + __ jccb(Assembler::equal, done); + read_barrier(masm, op1); + read_barrier(masm, op2); + __ cmpptr(op1, op2); + __ bind(done); + } +} + +void ShenandoahBarrierSetAssembler::obj_equals_addr(MacroAssembler* masm, DecoratorSet decorators, Register src1, Address src2) { + __ cmpptr(src1, src2); + if (ShenandoahAcmpBarrier) { + Label done; + __ jccb(Assembler::equal, done); + __ movptr(rscratch2, src2); + read_barrier(masm, src1); + read_barrier(masm, rscratch2); + __ cmpptr(src1, rscratch2); + __ bind(done); + } +} + +void ShenandoahBarrierSetAssembler::resolve_for_read(MacroAssembler* masm, DecoratorSet decorators, Register obj) { + bool oop_not_null = (decorators & OOP_NOT_NULL) != 0; + if (oop_not_null) { + read_barrier_not_null(masm, obj); + } else { + read_barrier(masm, obj); + } +} + +void ShenandoahBarrierSetAssembler::resolve_for_write(MacroAssembler* masm, DecoratorSet decorators, Register obj) { + write_barrier(masm, obj); +} diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp @@ -28,11 +28,57 @@ #include "gc/shared/barrierSetAssembler.hpp" class ShenandoahBarrierSetAssembler: public BarrierSetAssembler { +private: + void satb_write_barrier_pre(MacroAssembler* masm, + Register obj, + Register pre_val, + Register thread, + Register tmp, + bool tosca_live, + bool expand_call); + + void shenandoah_write_barrier_pre(MacroAssembler* masm, + Register obj, + Register pre_val, + Register thread, + Register tmp, + bool tosca_live, + bool expand_call); + void shenandoah_write_barrier_post(MacroAssembler* masm, + Register store_addr, + Register new_val, + Register thread, + Register tmp, + Register tmp2); + + void read_barrier(MacroAssembler* masm, Register dst); + void read_barrier_impl(MacroAssembler* masm, Register dst); + + void read_barrier_not_null(MacroAssembler* masm, Register dst); + void read_barrier_not_null_impl(MacroAssembler* masm, Register dst); + + void write_barrier(MacroAssembler* masm, Register dst); + void write_barrier_impl(MacroAssembler* masm, Register dst); + + void storeval_barrier(MacroAssembler* masm, Register dst, Register tmp); + void storeval_barrier_impl(MacroAssembler* masm, Register dst, Register tmp); + public: virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register src, Register dst, Register count); virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register src, Register dst, Register count); + virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Register dst, Address src, Register tmp1, Register tmp_thread); + virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2); + + virtual void obj_equals(MacroAssembler* masm, DecoratorSet decorators, Register src1, Register src2); + virtual void obj_equals_addr(MacroAssembler* masm, DecoratorSet decorators, Register src1, Address src2); + + virtual void resolve_for_read(MacroAssembler* masm, DecoratorSet decorators, Register obj); + virtual void resolve_for_write(MacroAssembler* masm, DecoratorSet decorators, Register obj); + }; #endif // CPU_X86_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_X86_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp @@ -30,7 +30,7 @@ #include "gc/shenandoah/shenandoahHeap.hpp" #include "utilities/defaultStream.hpp" -void ShenandoahArguments::initialize_flags() { +void ShenandoahArguments::initialize() { #if !(defined AARCH64 || defined AMD64 || defined IA32) vm_exit_during_initialization("Shenandoah GC is not supported on this platform."); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahArguments.hpp b/src/hotspot/share/gc/shenandoah/shenandoahArguments.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.hpp @@ -31,7 +31,7 @@ class ShenandoahArguments : public GCArguments { public: - virtual void initialize_flags(); + virtual void initialize(); virtual size_t conservative_max_heap_alignment(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp @@ -31,6 +31,8 @@ #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" +ShenandoahSATBMarkQueueSet ShenandoahBarrierSet::_satb_mark_queue_set; + template class ShenandoahUpdateRefsForOopClosure: public ExtendedOopClosure { private: @@ -41,13 +43,13 @@ if (STOREVAL_WRITE_BARRIER) { bool evac; o = _heap->evac_update_with_forwarded(p, evac); - if ((ALWAYS_ENQUEUE || evac) && !oopDesc::is_null(o)) { + if ((ALWAYS_ENQUEUE || evac) && !CompressedOops::is_null(o)) { ShenandoahBarrierSet::enqueue(o); } } else { o = _heap->maybe_update_with_forwarded(p); } - if (UPDATE_MATRIX && !oopDesc::is_null(o)) { + if (UPDATE_MATRIX && !CompressedOops::is_null(o)) { _heap->connection_matrix()->set_connected(p, o); } } @@ -166,9 +168,9 @@ (ShenandoahConditionalSATBBarrier && _heap->is_concurrent_mark_in_progress())) { T* elem_ptr = dst; for (int i = 0; i < count; i++, elem_ptr++) { - T heap_oop = oopDesc::load_heap_oop(elem_ptr); - if (!oopDesc::is_null(heap_oop)) { - enqueue(oopDesc::decode_heap_oop_not_null(heap_oop)); + T heap_oop = RawAccess<>::oop_load(elem_ptr); + if (!CompressedOops::is_null(heap_oop)) { + enqueue(CompressedOops::decode_not_null(heap_oop)); } } } @@ -190,12 +192,12 @@ inline void ShenandoahBarrierSet::inline_write_ref_field_pre(T* field, oop new_val) { shenandoah_assert_not_in_cset_loc_except(field, _heap->cancelled_concgc()); if (_heap->is_concurrent_mark_in_progress()) { - T heap_oop = oopDesc::load_heap_oop(field); - if (!oopDesc::is_null(heap_oop)) { - enqueue(oopDesc::decode_heap_oop(heap_oop)); + T heap_oop = RawAccess<>::oop_load(field); + if (!CompressedOops::is_null(heap_oop)) { + enqueue(CompressedOops::decode(heap_oop)); } } - if (UseShenandoahMatrix && ! oopDesc::is_null(new_val)) { + if (UseShenandoahMatrix && ! CompressedOops::is_null(new_val)) { ShenandoahConnectionMatrix* matrix = _heap->connection_matrix(); matrix->set_connected(field, new_val); } @@ -255,7 +257,7 @@ } oop ShenandoahBarrierSet::read_barrier(oop src) { - if (ShenandoahReadBarrier) { + if (ShenandoahReadBarrier && _heap->has_forwarded_objects()) { return ShenandoahBarrierSet::resolve_forwarded(src); } else { return src; @@ -285,7 +287,7 @@ oop ShenandoahBarrierSet::write_barrier_impl(oop obj) { assert(UseShenandoahGC && (ShenandoahWriteBarrier || ShenandoahStoreValWriteBarrier), "should be enabled"); - if (!oopDesc::is_null(obj)) { + if (!CompressedOops::is_null(obj)) { bool evac_in_progress = _heap->is_gc_in_progress_mask(ShenandoahHeap::EVACUATION | ShenandoahHeap::PARTIAL | ShenandoahHeap::TRAVERSAL); oop fwd = resolve_forwarded_not_null(obj); if (evac_in_progress && @@ -318,7 +320,7 @@ if (ShenandoahStoreValWriteBarrier || ShenandoahStoreValEnqueueBarrier) { obj = write_barrier(obj); } - if (ShenandoahStoreValEnqueueBarrier && !oopDesc::is_null(obj)) { + if (ShenandoahStoreValEnqueueBarrier && !CompressedOops::is_null(obj)) { enqueue(obj); } if (ShenandoahStoreValReadBarrier) { @@ -339,7 +341,17 @@ void ShenandoahBarrierSet::enqueue(oop obj) { shenandoah_assert_not_forwarded_if(NULL, obj, ShenandoahHeap::heap()->is_concurrent_traversal_in_progress()); - G1BarrierSet::enqueue(obj); + // Nulls should have been already filtered. + assert(oopDesc::is_oop(obj, true), "Error"); + + if (!_satb_mark_queue_set.is_active()) return; + Thread* thr = Thread::current(); + if (thr->is_Java_thread()) { + ShenandoahThreadLocalData::satb_mark_queue(thr).enqueue(obj); + } else { + MutexLockerEx x(Shared_SATB_Q_lock, Mutex::_no_safepoint_check_flag); + _satb_mark_queue_set.shared_satb_queue()->enqueue(obj); + } } #ifdef ASSERT @@ -348,18 +360,29 @@ } #endif +void ShenandoahBarrierSet::on_thread_create(Thread* thread) { + // Create thread local data + ShenandoahThreadLocalData::create(thread); +} + +void ShenandoahBarrierSet::on_thread_destroy(Thread* thread) { + // Destroy thread local data + ShenandoahThreadLocalData::destroy(thread); +} + + void ShenandoahBarrierSet::on_thread_attach(JavaThread* thread) { assert(!SafepointSynchronize::is_at_safepoint(), "We should not be at a safepoint"); - assert(!thread->satb_mark_queue().is_active(), "SATB queue should not be active"); - assert(thread->satb_mark_queue().is_empty(), "SATB queue should be empty"); - if (thread->satb_mark_queue_set().is_active()) { - thread->satb_mark_queue().set_active(true); + assert(!ShenandoahThreadLocalData::satb_mark_queue(thread).is_active(), "SATB queue should not be active"); + assert(ShenandoahThreadLocalData::satb_mark_queue(thread).is_empty(), "SATB queue should be empty"); + if (ShenandoahBarrierSet::satb_mark_queue_set().is_active()) { + ShenandoahThreadLocalData::satb_mark_queue(thread).set_active(true); } - thread->set_gc_state(JavaThread::gc_state_global()); + ShenandoahThreadLocalData::set_gc_state(thread, ShenandoahHeap::heap()->gc_state()); } void ShenandoahBarrierSet::on_thread_detach(JavaThread* thread) { - thread->satb_mark_queue().flush(); + ShenandoahThreadLocalData::satb_mark_queue(thread).flush(); if (UseTLAB && thread->gclab().is_initialized()) { thread->gclab().make_parsable(true); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp @@ -27,6 +27,7 @@ #include "gc/shared/accessBarrierSupport.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" +#include "gc/shenandoah/shenandoahSATBMarkQueueSet.hpp" class ShenandoahBarrierSet: public BarrierSet { private: @@ -38,12 +39,18 @@ WRITE_BARRIER_ALWAYS_ENQUEUE }; + static ShenandoahSATBMarkQueueSet _satb_mark_queue_set; + ShenandoahHeap* _heap; public: ShenandoahBarrierSet(ShenandoahHeap* heap); + static SATBMarkQueueSet& satb_mark_queue_set() { + return _satb_mark_queue_set; + } + void print_on(outputStream* st) const; bool is_a(BarrierSet::Name bsn); @@ -78,6 +85,8 @@ void write_ref_field_work(void* v, oop o, bool release = false); void write_region(MemRegion mr); + virtual void on_thread_create(Thread* thread); + virtual void on_thread_destroy(Thread* thread); virtual void on_thread_attach(JavaThread* thread); virtual void on_thread_detach(JavaThread* thread); @@ -110,22 +119,6 @@ oop write_barrier_impl(oop obj); -#ifndef CC_INTERP -public: - void interpreter_read_barrier(MacroAssembler* masm, Register dst); - void interpreter_read_barrier_not_null(MacroAssembler* masm, Register dst); - void interpreter_write_barrier(MacroAssembler* masm, Register dst); - void interpreter_storeval_barrier(MacroAssembler* masm, Register dst, Register tmp); - void asm_acmp_barrier(MacroAssembler* masm, Register op1, Register op2); - -private: - void interpreter_read_barrier_impl(MacroAssembler* masm, Register dst); - void interpreter_read_barrier_not_null_impl(MacroAssembler* masm, Register dst); - void interpreter_write_barrier_impl(MacroAssembler* masm, Register dst); - void interpreter_storeval_barrier_impl(MacroAssembler* masm, Register dst, Register tmp); - -#endif - static void keep_alive_if_weak(DecoratorSet decorators, oop value) { assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Reference strength must be known"); const bool on_strong_oop_ref = (decorators & ON_STRONG_OOP_REF) != 0; @@ -285,6 +278,10 @@ return barrier_set_cast(BarrierSet::barrier_set())->write_barrier(obj); } + static bool equals(oop o1, oop o2) { + return barrier_set_cast(BarrierSet::barrier_set())->obj_equals(o1, o2); + } + }; }; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp @@ -53,10 +53,10 @@ expected = res; } while ((! oopDesc::unsafe_equals(compare_value, expected)) && oopDesc::unsafe_equals(BarrierSet::barrier_set()->read_barrier(compare_value), BarrierSet::barrier_set()->read_barrier(expected))); if (oopDesc::unsafe_equals(expected, compare_value)) { - if (ShenandoahSATBBarrier && !oopDesc::is_null(compare_value)) { + if (ShenandoahSATBBarrier && !CompressedOops::is_null(compare_value)) { ShenandoahBarrierSet::enqueue(compare_value); } - if (UseShenandoahMatrix && ! oopDesc::is_null(new_value)) { + if (UseShenandoahMatrix && !CompressedOops::is_null(new_value)) { ShenandoahConnectionMatrix* matrix = ShenandoahHeap::heap()->connection_matrix(); matrix->set_connected(addr, new_value); } @@ -69,11 +69,11 @@ inline oop ShenandoahBarrierSet::AccessBarrier::oop_atomic_xchg_in_heap(oop new_value, T* addr) { oop previous = Raw::oop_atomic_xchg(new_value, addr); if (ShenandoahSATBBarrier) { - if (!oopDesc::is_null(previous)) { + if (!CompressedOops::is_null(previous)) { ShenandoahBarrierSet::enqueue(previous); } } - if (UseShenandoahMatrix && ! oopDesc::is_null(new_value)) { + if (UseShenandoahMatrix && !CompressedOops::is_null(new_value)) { ShenandoahConnectionMatrix* matrix = ShenandoahHeap::heap()->connection_matrix(); matrix->set_connected(addr, new_value); } @@ -85,12 +85,12 @@ bool ShenandoahBarrierSet::AccessBarrier::arraycopy_in_heap(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { assert(((T*)(void*) src_obj) <= src && ((HeapWord*) src) < (((HeapWord*)(void*) src_obj) + src_obj->size()), "pointer out of object bounds src_obj: %p, src: %p, end: %p, size: %u", (void*) src_obj, src, (((HeapWord*)(void*) src_obj) + src_obj->size()), src_obj->size()); assert(((T*)(void*) dst_obj) <= dst && ((HeapWord*) dst) < ((HeapWord*)(void*) dst_obj) + dst_obj->size(), "pointer out of object bounds dst_obj: %p, dst: %p, end: %p, size: %u", (void*) dst_obj, dst, (((HeapWord*)(void*) dst_obj) + dst_obj->size()), dst_obj->size()); - if (!oopDesc::is_null(src_obj)) { + if (!CompressedOops::is_null(src_obj)) { size_t src_offset = pointer_delta((void*) src, (void*) src_obj, sizeof(char)); src_obj = arrayOop(((ShenandoahBarrierSet*) BarrierSet::barrier_set())->read_barrier(src_obj)); src = (T*) (((char*)(void*) src_obj) + src_offset); } - if (!oopDesc::is_null(dst_obj)) { + if (!CompressedOops::is_null(dst_obj)) { size_t dst_offset = pointer_delta((void*) dst, (void*) dst_obj, sizeof(char)); dst_obj = arrayOop(((ShenandoahBarrierSet*) BarrierSet::barrier_set())->write_barrier(dst_obj)); dst = (T*) (((char*)(void*) dst_obj) + dst_offset); @@ -195,22 +195,22 @@ template bool ShenandoahBarrierSet::arraycopy_element(T* cur_src, T* cur_dst, Klass* bound, Thread* thread) { - T o = oopDesc::load_heap_oop(cur_src); + T o = RawAccess<>::oop_load(cur_src); if (SATB) { - T prev = oopDesc::load_heap_oop(cur_dst); - if (!oopDesc::is_null(prev)) { - oop prev_obj = oopDesc::decode_heap_oop_not_null(prev); + T prev = RawAccess<>::oop_load(cur_dst); + if (!CompressedOops::is_null(prev)) { + oop prev_obj = CompressedOops::decode_not_null(prev); enqueue(prev_obj); } } - if (!oopDesc::is_null(o)) { - oop obj = oopDesc::decode_heap_oop_not_null(o); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); if (CHECKCAST) { assert(bound != NULL, "need element klass for checkcast"); - if (!bound->is_instanceof_or_null(obj)) { + if (!oopDesc::is_instanceof_or_null(obj, bound)) { return false; } } @@ -253,10 +253,10 @@ _heap->connection_matrix()->set_connected(cur_dst, obj); } - oopDesc::encode_store_heap_oop_not_null(cur_dst, obj); + RawAccess::oop_store(cur_dst, obj); } else { // Store null. - oopDesc::store_heap_oop(cur_dst, o); + RawAccess<>::oop_store(cur_dst, o); } return true; } @@ -279,12 +279,12 @@ ShenandoahHeap* heap = ShenandoahHeap::heap(); - if (!oopDesc::is_null(src_obj)) { + if (!CompressedOops::is_null(src_obj)) { size_t src_offset = pointer_delta((void*) src, (void*) src_obj, sizeof(T)); src_obj = arrayOop(((ShenandoahBarrierSet*) BarrierSet::barrier_set())->read_barrier(src_obj)); src = ((T*)(void*) src_obj) + src_offset; } - if (!oopDesc::is_null(dst_obj)) { + if (!CompressedOops::is_null(dst_obj)) { size_t dst_offset = pointer_delta((void*) dst, (void*) dst_obj, sizeof(T)); dst_obj = arrayOop(((ShenandoahBarrierSet*) BarrierSet::barrier_set())->write_barrier(dst_obj)); dst = ((T*)(void*) dst_obj) + dst_offset; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp @@ -37,8 +37,8 @@ private: template inline void do_oop_work(T* p) { - T o = oopDesc::load_heap_oop(p); - if (! oopDesc::is_null(o)) { + T o = RawAccess<>::oop_load(p); + if (! CompressedOops::is_null(o)) { _non_null_oops++; } } @@ -65,9 +65,9 @@ template inline void do_oop_work(T* p) { if (_has_cset_oops) return; - T o = oopDesc::load_heap_oop(p); - if (! oopDesc::is_null(o)) { - oop obj1 = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (! CompressedOops::is_null(o)) { + oop obj1 = CompressedOops::decode_not_null(o); if (_heap->in_collection_set(obj1)) { _has_cset_oops = true; } @@ -93,13 +93,13 @@ private: template inline void do_oop_work(T* p) { - T o = oopDesc::load_heap_oop(p); - if (! oopDesc::is_null(o)) { - oop obj1 = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (! CompressedOops::is_null(o)) { + oop obj1 = CompressedOops::decode_not_null(o); oop obj2 = BarrierSet::barrier_set()->write_barrier(obj1); if (! oopDesc::unsafe_equals(obj1, obj2)) { assert (!ShenandoahHeap::heap()->in_collection_set(obj2), "sanity"); - oopDesc::encode_store_heap_oop(p, obj2); + RawAccess::oop_store(p, obj2); } } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp @@ -349,7 +349,7 @@ _task_queues->register_queue(i, task_queue); } - JavaThread::satb_mark_queue_set().set_buffer_size(ShenandoahSATBBufferSize); + ShenandoahBarrierSet::satb_mark_queue_set().set_buffer_size(ShenandoahSATBBufferSize); size_t num_regions = ShenandoahHeap::heap()->num_regions(); _liveness_local = NEW_C_HEAP_ARRAY(jushort*, workers, mtGC); @@ -500,11 +500,11 @@ if (thread->is_Java_thread()) { if (thread->claim_oops_do(true, _thread_parity)) { JavaThread* jt = (JavaThread*)thread; - jt->satb_mark_queue().apply_closure_and_empty(_satb_cl); + ShenandoahThreadLocalData::satb_mark_queue(jt).apply_closure_and_empty(_satb_cl); } } else if (thread->is_VM_thread()) { if (thread->claim_oops_do(true, _thread_parity)) { - JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(_satb_cl); + ShenandoahBarrierSet::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(_satb_cl); } } } @@ -514,7 +514,7 @@ ShenandoahObjToScanQueue* q = get_queue(worker_id); ShenandoahSATBBufferClosure cl(q); - SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); + SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set(); while (satb_mq_set.apply_closure_to_completed_buffer(&cl)); if (remark) { @@ -924,7 +924,7 @@ queues->clear(); // Cancel SATB buffers. - JavaThread::satb_mark_queue_set().abandon_partial_marking(); + ShenandoahBarrierSet::satb_mark_queue_set().abandon_partial_marking(); } ShenandoahObjToScanQueue* ShenandoahConcurrentMark::get_queue(uint worker_id) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.inline.hpp @@ -220,7 +220,7 @@ inline bool ShenandoahConcurrentMark::try_draining_satb_buffer(ShenandoahObjToScanQueue *q, ShenandoahMarkTask &task) { ShenandoahSATBBufferClosure cl(q); - SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); + SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set(); bool had_refs = satb_mq_set.apply_closure_to_completed_buffer(&cl); return had_refs && try_queue(q, task); } @@ -232,9 +232,9 @@ template inline void ShenandoahConcurrentMark::mark_through_ref(T *p, ShenandoahHeap* heap, ShenandoahObjToScanQueue* q, ShenandoahStrDedupQueue* dq) { - T o = oopDesc::load_heap_oop(p); - if (! oopDesc::is_null(o)) { - oop obj = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); switch (UPDATE_REFS) { case NONE: break; @@ -255,7 +255,7 @@ // Note: Only when concurrently updating references can obj become NULL here. // It happens when a mutator thread beats us by writing another value. In that // case we don't need to do anything else. - if (UPDATE_REFS != CONCURRENT || !oopDesc::is_null(obj)) { + if (UPDATE_REFS != CONCURRENT || !CompressedOops::is_null(obj)) { shenandoah_assert_not_forwarded(p, obj); shenandoah_assert_not_in_cset_except(p, obj, heap->cancelled_concgc()); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahEvacOOMHandler.cpp b/src/hotspot/share/gc/shenandoah/shenandoahEvacOOMHandler.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahEvacOOMHandler.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahEvacOOMHandler.cpp @@ -26,6 +26,7 @@ #include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahEvacOOMHandler.hpp" +#include "gc/shenandoah/shenandoahThreadLocalData.hpp" #include "runtime/orderAccess.inline.hpp" #include "runtime/os.hpp" #include "runtime/thread.hpp" @@ -43,14 +44,14 @@ // At this point we are sure that no threads can evacuate anything. Raise // the thread-local oom_during_evac flag to indicate that any attempt // to evacuate should simply return the forwarding pointer instead (which is safe now). - Thread::current()->set_oom_during_evac(true); + ShenandoahThreadLocalData::set_oom_during_evac(Thread::current(), true); } void ShenandoahEvacOOMHandler::enter_evacuation() { jint threads_in_evac = OrderAccess::load_acquire(&_threads_in_evac); - assert(!Thread::current()->is_evac_allowed(), "sanity"); - assert(!Thread::current()->is_oom_during_evac(), "TL oom-during-evac must not be set"); + assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "sanity"); + assert(!ShenandoahThreadLocalData::is_oom_during_evac(Thread::current()), "TL oom-during-evac must not be set"); if ((threads_in_evac & OOM_MARKER_MASK) != 0) { wait_for_no_evac_threads(); @@ -61,7 +62,7 @@ jint other = Atomic::cmpxchg(threads_in_evac + 1, &_threads_in_evac, threads_in_evac); if (other == threads_in_evac) { // Success: caller may safely enter evacuation - DEBUG_ONLY(Thread::current()->set_evac_allowed(true)); + DEBUG_ONLY(ShenandoahThreadLocalData::set_evac_allowed(Thread::current(), true)); return; } else { // Failure: @@ -77,7 +78,7 @@ } void ShenandoahEvacOOMHandler::leave_evacuation() { - if (!Thread::current()->is_oom_during_evac()) { + if (!ShenandoahThreadLocalData::is_oom_during_evac(Thread::current())) { assert((OrderAccess::load_acquire(&_threads_in_evac) & ~OOM_MARKER_MASK) > 0, "sanity"); // NOTE: It's ok to simply decrement, even with mask set, because unmasked value is positive. Atomic::dec(&_threads_in_evac); @@ -85,15 +86,15 @@ // If we get here, the current thread has already gone through the // OOM-during-evac protocol and has thus either never entered or successfully left // the evacuation region. Simply flip its TL oom-during-evac flag back off. - Thread::current()->set_oom_during_evac(false); + ShenandoahThreadLocalData::set_oom_during_evac(Thread::current(), false); } - DEBUG_ONLY(Thread::current()->set_evac_allowed(false)); - assert(!Thread::current()->is_oom_during_evac(), "TL oom-during-evac must be turned off"); + DEBUG_ONLY(ShenandoahThreadLocalData::set_evac_allowed(Thread::current(), false)); + assert(!ShenandoahThreadLocalData::is_oom_during_evac(Thread::current()), "TL oom-during-evac must be turned off"); } void ShenandoahEvacOOMHandler::handle_out_of_memory_during_evacuation() { - assert(Thread::current()->is_evac_allowed(), "sanity"); - assert(!Thread::current()->is_oom_during_evac(), "TL oom-during-evac must not be set"); + assert(ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "sanity"); + assert(!ShenandoahThreadLocalData::is_oom_during_evac(Thread::current()), "TL oom-during-evac must not be set"); jint threads_in_evac = OrderAccess::load_acquire(&_threads_in_evac); while (true) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -64,9 +64,9 @@ #ifdef ASSERT template void ShenandoahAssertToSpaceClosure::do_oop_nv(T* p) { - T o = oopDesc::load_heap_oop(p); - if (! oopDesc::is_null(o)) { - oop obj = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (! CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); shenandoah_assert_not_forwarded(p, obj); } } @@ -145,7 +145,7 @@ heap_alignment); initialize_reserved_region((HeapWord*)heap_rs.base(), (HeapWord*) (heap_rs.base() + heap_rs.size())); - set_barrier_set(new ShenandoahBarrierSet(this)); + BarrierSet::set_barrier_set(new ShenandoahBarrierSet(this)); ReservedSpace pgc_rs = heap_rs.first_part(max_byte_size); _num_regions = max_byte_size / ShenandoahHeapRegion::region_size_bytes(); @@ -214,7 +214,7 @@ // The call below uses stuff (the SATB* things) that are in G1, but probably // belong into a shared location. - JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon, + ShenandoahBarrierSet::satb_mark_queue_set().initialize(SATB_Q_CBL_mon, SATB_Q_FL_lock, 20 /*G1SATBProcessCompletedThreshold */, Shared_SATB_Q_lock); @@ -500,7 +500,10 @@ class ShenandoahInitGCLABClosure : public ThreadClosure { public: void do_thread(Thread* thread) { - thread->gclab().initialize(true); + if (thread != NULL && (thread->is_Java_thread() || thread->is_Worker_thread() || + thread->is_ConcurrentGC_thread())) { + thread->gclab().initialize(true); + } } }; @@ -510,7 +513,7 @@ MutexLocker ml(Threads_lock); ShenandoahInitGCLABClosure init_gclabs; - Threads::java_threads_do(&init_gclabs); + Threads::threads_do(&init_gclabs); gc_threads_do(&init_gclabs); // gclab can not be initialized early during VM startup, as it can not determinate its max_size. @@ -696,7 +699,7 @@ ShenandoahHeap* ShenandoahHeap::heap() { CollectedHeap* heap = Universe::heap(); assert(heap != NULL, "Unitialized access to ShenandoahHeap::heap()"); - assert(heap->kind() == CollectedHeap::ShenandoahHeap, "not a shenandoah heap"); + assert(heap->kind() == CollectedHeap::Shenandoah, "not a shenandoah heap"); return (ShenandoahHeap*) heap; } @@ -791,9 +794,9 @@ void do_oop_work(T* p) { assert(_heap->is_evacuation_in_progress(), "Only do this when evacuation is in progress"); - T o = oopDesc::load_heap_oop(p); - if (! oopDesc::is_null(o)) { - oop obj = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (! CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); if (_heap->in_collection_set(obj)) { shenandoah_assert_marked_complete(p, obj); oop resolved = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); @@ -801,7 +804,7 @@ bool evac; resolved = _heap->evacuate_object(obj, _thread, evac); } - oopDesc::encode_store_heap_oop(p, resolved); + RawAccess::oop_store(p, resolved); } } } @@ -827,9 +830,9 @@ private: template void do_oop_work(T* p) { - T o = oopDesc::load_heap_oop(p); - if (! oopDesc::is_null(o)) { - oop obj = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (! CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); if (_heap->in_collection_set(obj)) { oop resolved = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); if (oopDesc::unsafe_equals(resolved, obj)) { @@ -1045,7 +1048,9 @@ if (UseTLAB) { CollectedHeap::ensure_parsability(retire_tlabs); ShenandoahRetireTLABClosure cl(retire_tlabs); - Threads::java_threads_do(&cl); + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { + cl.do_thread(t); + } gc_threads_do(&cl); } } @@ -1171,7 +1176,9 @@ CollectedHeap::resize_all_tlabs(); ShenandoahResizeGCLABClosure cl; - Threads::java_threads_do(&cl); + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { + cl.do_thread(t); + } gc_threads_do(&cl); } @@ -1186,7 +1193,9 @@ void ShenandoahHeap::accumulate_statistics_all_gclabs() { ShenandoahAccumulateStatisticsGCLABClosure cl; - Threads::java_threads_do(&cl); + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { + cl.do_thread(t); + } gc_threads_do(&cl); } @@ -1322,9 +1331,9 @@ template void do_oop_work(T* p) { - T o = oopDesc::load_heap_oop(p); - if (!oopDesc::is_null(o)) { - oop obj = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); assert(oopDesc::is_oop(obj), "must be a valid oop"); if (!_bitmap->isMarked((HeapWord*) obj)) { @@ -1795,25 +1804,32 @@ } } +void ShenandoahHeap::set_gc_state_all_threads(char state) { + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { + ShenandoahThreadLocalData::set_gc_state(t, state); + } +} + void ShenandoahHeap::set_gc_state_mask(uint mask, bool value) { assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Should really be Shenandoah safepoint"); _gc_state.set_cond(mask, value); - JavaThread::set_gc_state_all_threads(_gc_state.raw_value()); + set_gc_state_all_threads(_gc_state.raw_value()); } void ShenandoahHeap::set_concurrent_mark_in_progress(bool in_progress) { set_gc_state_mask(MARKING, in_progress); - JavaThread::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress); + ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress); } void ShenandoahHeap::set_concurrent_partial_in_progress(bool in_progress) { + set_gc_state_mask(PARTIAL | HAS_FORWARDED, in_progress); - JavaThread::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress); + ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress); } void ShenandoahHeap::set_concurrent_traversal_in_progress(bool in_progress) { set_gc_state_mask(TRAVERSAL | HAS_FORWARDED, in_progress); - JavaThread::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress); + ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress); } void ShenandoahHeap::set_evacuation_in_progress(bool in_progress) { @@ -1841,7 +1857,7 @@ } bool ShenandoahForwardedIsAliveClosure::do_object_b(oop obj) { - if (oopDesc::is_null(obj)) { + if (CompressedOops::is_null(obj)) { return false; } obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); @@ -1850,7 +1866,7 @@ } bool ShenandoahIsAliveClosure::do_object_b(oop obj) { - if (oopDesc::is_null(obj)) { + if (CompressedOops::is_null(obj)) { return false; } shenandoah_assert_not_forwarded(NULL, obj); @@ -2890,3 +2906,7 @@ r = regions.next(); } } + +char ShenandoahHeap::gc_state() const { + return _gc_state.raw_value(); +} diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -328,7 +328,7 @@ void print_extended_on(outputStream *st) const /* override */; ShenandoahHeap::Name kind() const /* override */{ - return CollectedHeap::ShenandoahHeap; + return CollectedHeap::Shenandoah; } jint initialize() /* override */; @@ -430,6 +430,7 @@ void roots_iterate(OopClosure* cl); private: + void set_gc_state_all_threads(char state); void set_gc_state_mask(uint mask, bool value); public: @@ -459,6 +460,8 @@ inline bool has_forwarded_objects() const; inline bool is_gc_in_progress_mask(uint mask) const; + char gc_state() const; + bool process_references() const; bool unload_classes() const; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp @@ -38,6 +38,7 @@ #include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahHeapRegionSet.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" +#include "gc/shenandoah/shenandoahThreadLocalData.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" @@ -49,9 +50,9 @@ template void ShenandoahUpdateRefsClosure::do_oop_work(T* p) { - T o = oopDesc::load_heap_oop(p); - if (! oopDesc::is_null(o)) { - oop obj = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); _heap->update_with_forwarded_not_null(p, obj); } } @@ -109,7 +110,7 @@ if (in_collection_set(obj)) { shenandoah_assert_forwarded_except(p, obj, is_full_gc_in_progress() || cancelled_concgc()); obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); - oopDesc::encode_store_heap_oop(p, obj); + RawAccess::oop_store(p, obj); } #ifdef ASSERT else { @@ -121,9 +122,9 @@ template inline oop ShenandoahHeap::maybe_update_with_forwarded(T* p) { - T o = oopDesc::load_heap_oop(p); - if (! oopDesc::is_null(o)) { - oop obj = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); return maybe_update_with_forwarded_not_null(p, obj); } else { return NULL; @@ -133,9 +134,9 @@ template inline oop ShenandoahHeap::evac_update_with_forwarded(T* p, bool &evac) { evac = false; - T o = oopDesc::load_heap_oop(p); - if (! oopDesc::is_null(o)) { - oop heap_oop = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(o)) { + oop heap_oop = CompressedOops::decode_not_null(o); if (in_collection_set(heap_oop)) { oop forwarded_oop = ShenandoahBarrierSet::resolve_forwarded_not_null(heap_oop); if (oopDesc::unsafe_equals(forwarded_oop, heap_oop)) { @@ -159,9 +160,9 @@ } inline oop ShenandoahHeap::atomic_compare_exchange_oop(oop n, narrowOop* addr, oop c) { - narrowOop cmp = oopDesc::encode_heap_oop(c); - narrowOop val = oopDesc::encode_heap_oop(n); - return oopDesc::decode_heap_oop((narrowOop) Atomic::cmpxchg(val, addr, cmp)); + narrowOop cmp = CompressedOops::encode(c); + narrowOop val = CompressedOops::encode(n); + return CompressedOops::decode((narrowOop) Atomic::cmpxchg(val, addr, cmp)); } template @@ -194,7 +195,7 @@ // which first copies the array, which potentially contains from-space refs, and only afterwards // updates all from-space refs to to-space refs, which leaves a short window where the new array // elements can be from-space. - // assert(oopDesc::is_null(result) || + // assert(CompressedOops::is_null(result) || // oopDesc::unsafe_equals(result, ShenandoahBarrierSet::resolve_oop_static_not_null(result)), // "expect not forwarded"); return NULL; @@ -275,7 +276,7 @@ inline oop ShenandoahHeap::evacuate_object(oop p, Thread* thread, bool& evacuated) { evacuated = false; - if (Thread::current()->is_oom_during_evac()) { + if (ShenandoahThreadLocalData::is_oom_during_evac(Thread::current())) { // This thread went through the OOM during evac protocol and it is safe to return // the forward pointer. It must not attempt to evacuate any more. return ShenandoahBarrierSet::resolve_forwarded(p); @@ -290,7 +291,7 @@ HeapWord* filler; #ifdef ASSERT - assert(thread->is_evac_allowed(), "must be enclosed in ShenandoahOOMDuringEvacHandler"); + assert(ShenandoahThreadLocalData::is_evac_allowed(thread), "must be enclosed in ShenandoahOOMDuringEvacHandler"); if (ShenandoahOOMDuringEvacALot && (os::random() & 1) == 0) { // Simulate OOM every ~2nd slow-path call diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp @@ -51,20 +51,6 @@ #include "gc/shared/taskqueue.inline.hpp" #include "gc/shared/workgroup.hpp" -class ShenandoahMarkCompactBarrierSet : public ShenandoahBarrierSet { -public: - ShenandoahMarkCompactBarrierSet(ShenandoahHeap* heap) : ShenandoahBarrierSet(heap) {} - - oop read_barrier(oop src) { - return src; - } - -#ifdef ASSERT - void verify_safe_oop(oop o) {} - void verify_safe_oop(narrowOop o) {} -#endif -}; - class ShenandoahClearRegionStatusClosure: public ShenandoahHeapRegionClosure { private: ShenandoahHeap* const _heap; @@ -186,10 +172,6 @@ } } - BarrierSet* old_bs = BarrierSet::barrier_set(); - ShenandoahMarkCompactBarrierSet bs(heap); - BarrierSet::set_bs(&bs); - { if (UseTLAB) { heap->make_tlabs_parsable(true); @@ -197,16 +179,17 @@ CodeCache::gc_prologue(); - // We should save the marks of the currently locked biased monitors. - // The marking doesn't preserve the marks of biased objects. - //BiasedLocking::preserve_marks(); - + // TODO: We don't strictly always need to update refs. We might want to clean + // up managing has_forwarded_objects when diving into degen/full-gc. heap->set_has_forwarded_objects(true); OrderAccess::fence(); phase1_mark_heap(); + // Prevent read-barrier from kicking in while adjusting pointers in phase3. + heap->set_has_forwarded_objects(false); + heap->set_full_gc_move_in_progress(true); // Setup workers for the rest @@ -237,7 +220,6 @@ JvmtiExport::gc_epilogue(); } - heap->set_has_forwarded_objects(false); heap->set_full_gc_move_in_progress(false); heap->set_full_gc_in_progress(false); @@ -255,8 +237,6 @@ ShenandoahGCPhase phase(ShenandoahPhaseTimings::full_gc_resize_tlabs); heap->resize_all_tlabs(); } - - BarrierSet::set_bs(old_bs); } @@ -534,12 +514,12 @@ template inline void do_oop_work(T* p) { - T o = oopDesc::load_heap_oop(p); - if (! oopDesc::is_null(o)) { - oop obj = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); assert(_heap->is_marked_complete(obj), "must be marked"); oop forw = oop(BrooksPointer::get_raw(obj)); - oopDesc::encode_store_heap_oop(p, forw); + RawAccess::oop_store(p, forw); if (UseShenandoahMatrix) { if (_heap->is_in_reserved(p)) { assert(_heap->is_in_reserved(forw), "must be in heap"); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOopClosures.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahOopClosures.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahOopClosures.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOopClosures.inline.hpp @@ -38,7 +38,7 @@ inline void ShenandoahUpdateHeapRefsSuperClosure::work(T* p) { oop obj = _heap->maybe_update_with_forwarded(p); if (UPDATE_MATRIX) { - if (!oopDesc::is_null(obj)) { + if (!CompressedOops::is_null(obj)) { _heap->connection_matrix()->set_connected(p, obj); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPartialGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahPartialGC.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahPartialGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPartialGC.cpp @@ -77,7 +77,7 @@ void do_buffer(void** buffer, size_t size) { for (size_t i = 0; i < size; ++i) { oop* p = (oop*) &buffer[i]; - oop obj = oopDesc::load_heap_oop(p); + oop obj = RawAccess<>::oop_load(p); _queue->push(obj); } } @@ -96,11 +96,11 @@ if (thread->is_Java_thread()) { if (thread->claim_oops_do(true, _thread_parity)) { JavaThread* jt = (JavaThread*)thread; - jt->satb_mark_queue().apply_closure_and_empty(_satb_cl); + ShenandoahThreadLocalData::satb_mark_queue(jt).apply_closure_and_empty(_satb_cl); } } else if (thread->is_VM_thread()) { if (thread->claim_oops_do(true, _thread_parity)) { - JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(_satb_cl); + ShenandoahBarrierSet::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(_satb_cl); } } } @@ -197,7 +197,7 @@ { ShenandoahPartialSATBBufferClosure satb_cl(q); // Process remaining finished SATB buffers. - SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); + SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set(); while (satb_mq_set.apply_closure_to_completed_buffer(&satb_cl)); // Process remaining threads SATB buffers. ShenandoahPartialSATBThreadsClosure tc(&satb_cl); @@ -417,7 +417,7 @@ q->pop_local(task) || q->pop_overflow(task)) { oop obj = task.obj(); - assert(!oopDesc::is_null(obj), "must not be null"); + assert(!CompressedOops::is_null(obj), "must not be null"); obj->oop_iterate(&cl); } else { assert(q->is_empty(), "Must be empty"); @@ -430,7 +430,7 @@ // Normal loop. q = queues->queue(worker_id); ShenandoahPartialSATBBufferClosure satb_cl(q); - SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); + SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set(); int seed = 17; @@ -444,7 +444,7 @@ (DO_SATB && satb_mq_set.apply_closure_to_completed_buffer(&satb_cl) && q->pop_buffer(task)) || queues->steal(worker_id, &seed, task))) { oop obj = task.obj(); - assert(!oopDesc::is_null(obj), "must not be null"); + assert(!CompressedOops::is_null(obj), "must not be null"); obj->oop_iterate(&cl); } else { ShenandoahEvacOOMScopeLeaver oom_scope_leaver; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPartialGC.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahPartialGC.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahPartialGC.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPartialGC.inline.hpp @@ -29,9 +29,9 @@ template void ShenandoahPartialGC::process_oop(T* p, Thread* thread, ShenandoahObjToScanQueue* queue) { - T o = oopDesc::load_heap_oop(p); - if (! oopDesc::is_null(o)) { - oop obj = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); if (_heap->in_collection_set(obj)) { oop forw = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); if (oopDesc::unsafe_equals(obj, forw)) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPrinter.cpp b/src/hotspot/share/gc/shenandoah/shenandoahPrinter.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahPrinter.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPrinter.cpp @@ -40,7 +40,7 @@ private: template inline void do_oop_work(T* p) { - oop o = oopDesc::load_decode_heap_oop(p); + oop o = RawAccess<>::oop_load(p); if (o != NULL) { if (ShenandoahHeap::heap()->is_in(o) && oopDesc::is_oop(o)) { tty->print_cr("%s "INT32_FORMAT" ("PTR_FORMAT")-> "PTR_FORMAT" (marked: %s) (%s "PTR_FORMAT")", diff --git a/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.cpp new file mode 100644 --- /dev/null +++ b/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, Red Hat, Inc. and/or its affiliates. + * + * 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 "gc/shenandoah/shenandoahSATBMarkQueueSet.hpp" +#include "gc/shenandoah/shenandoahThreadLocalData.hpp" + +SATBMarkQueue& ShenandoahSATBMarkQueueSet::satb_queue_for_thread(Thread* t) { + return ShenandoahThreadLocalData::satb_mark_queue(t); +} diff --git a/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.hpp new file mode 100644 --- /dev/null +++ b/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, Red Hat, Inc. and/or its affiliates. + * + * 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. + * + */ + +#ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHSATBMARKQUEUESET_HPP +#define SHARE_VM_GC_SHENANDOAH_SHENANDOAHSATBMARKQUEUESET_HPP + +#include "gc/g1/satbMarkQueue.hpp" + +class ShenandoahSATBMarkQueueSet : public SATBMarkQueueSet { +public: + virtual SATBMarkQueue& satb_queue_for_thread(Thread* t); +}; + +#endif diff --git a/src/hotspot/share/gc/shenandoah/shenandoahSharedVariables.hpp b/src/hotspot/share/gc/shenandoah/shenandoahSharedVariables.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahSharedVariables.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahSharedVariables.hpp @@ -178,7 +178,7 @@ return &value; } - ShenandoahSharedValue raw_value() { + ShenandoahSharedValue raw_value() const { return value; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahStrDedupQueue.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahStrDedupQueue.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahStrDedupQueue.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahStrDedupQueue.inline.hpp @@ -41,12 +41,12 @@ template void ShenandoahStrDedupQueueCleanupClosure::do_oop_work(T* p) { - T o = oopDesc::load_heap_oop(p); - if (! oopDesc::is_null(o)) { - oop obj = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); assert(_heap->is_in(obj), "Must be in the heap"); if (!_heap->is_marked_next(obj)) { - oopDesc::encode_store_heap_oop(p, oop()); + RawAccess::oop_store(p, oop()); } } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahStrDedupThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahStrDedupThread.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahStrDedupThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahStrDedupThread.cpp @@ -71,7 +71,7 @@ stats.inc_inspected(); assert(!ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must not at Shenandoah safepoint"); - if (oopDesc::is_null(java_string) || + if (CompressedOops::is_null(java_string) || !ShenandoahStringDedup::is_candidate(java_string)) { stats.inc_skipped(); } else { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp @@ -105,7 +105,7 @@ void do_buffer(void** buffer, size_t size) { for (size_t i = 0; i < size; ++i) { oop* p = (oop*) &buffer[i]; - oop obj = oopDesc::load_heap_oop(p); + oop obj = RawAccess<>::oop_load(p); shenandoah_assert_not_forwarded(p, obj); if (!_heap->is_marked_next(obj) && _heap->mark_next(obj)) { _queue->push(ShenandoahMarkTask(obj)); @@ -124,9 +124,9 @@ void do_thread(Thread* thread) { if (thread->is_Java_thread()) { JavaThread* jt = (JavaThread*)thread; - jt->satb_mark_queue().apply_closure_and_empty(_satb_cl); + ShenandoahThreadLocalData::satb_mark_queue(jt).apply_closure_and_empty(_satb_cl); } else if (thread->is_VM_thread()) { - JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(_satb_cl); + ShenandoahBarrierSet::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(_satb_cl); } } }; @@ -244,7 +244,7 @@ ShenandoahTraversalSATBBufferClosure satb_cl(q); { // Process remaining finished SATB buffers. - SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); + SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set(); while (satb_mq_set.apply_closure_to_completed_buffer(&satb_cl)); // Process remaining threads SATB buffers below. } @@ -495,7 +495,7 @@ // Normal loop. q = queues->queue(worker_id); ShenandoahTraversalSATBBufferClosure satb_cl(q); - SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); + SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set(); int seed = 17; @@ -641,12 +641,12 @@ template inline void do_oop_work(T* p) { - T o = oopDesc::load_heap_oop(p); - if (!oopDesc::is_null(o)) { - oop obj = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); oop forw = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); if (!oopDesc::unsafe_equals(obj, forw)) { - oopDesc::encode_store_heap_oop(p, forw); + RawAccess::oop_store(p, forw); } } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.inline.hpp @@ -36,14 +36,14 @@ template void ShenandoahTraversalGC::process_oop(T* p, Thread* thread, ShenandoahObjToScanQueue* queue, ShenandoahStrDedupQueue* dq) { - T o = oopDesc::load_heap_oop(p); - if (! oopDesc::is_null(o)) { - oop obj = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); if (DEGEN) { oop forw = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); if (!oopDesc::unsafe_equals(obj, forw)) { // Update reference. - oopDesc::encode_store_heap_oop(p, forw); + RawAccess::oop_store(p, forw); } obj = forw; } else if (_heap->in_collection_set(obj)) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp @@ -59,9 +59,9 @@ template void do_oop_work(T* p) { - T o = oopDesc::load_heap_oop(p); - if (!oopDesc::is_null(o)) { - oop obj = oopDesc::decode_heap_oop_not_null(o); + T o = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(o)) { + oop obj = CompressedOops::decode_not_null(o); // Single threaded verification can use faster non-atomic stack and bitmap // methods. @@ -146,7 +146,7 @@ if (!oopDesc::unsafe_equals(obj, fwd)) { verify(ShenandoahAsserts::_safe_oop, obj, _heap->is_in(fwd), "Forwardee must be in heap"); - verify(ShenandoahAsserts::_safe_oop, obj, !oopDesc::is_null(fwd), + verify(ShenandoahAsserts::_safe_oop, obj, !CompressedOops::is_null(fwd), "Forwardee is set"); verify(ShenandoahAsserts::_safe_oop, obj, check_obj_alignment(fwd), "Forwardee must be aligned"); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp b/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahWorkGroup.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" +#include "gc/shenandoah/shenandoahThreadLocalData.hpp" #include "gc/shenandoah/shenandoahWorkGroup.hpp" ShenandoahWorkerScope::ShenandoahWorkerScope(WorkGang* workers, uint nworkers) : @@ -59,6 +60,6 @@ if (_initialize_gclab) { worker->gclab().initialize(true); } - + ShenandoahThreadLocalData::create(worker); return worker; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.cpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.cpp deleted file mode 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2016, Red Hat, Inc. and/or its affiliates. - * - * 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 "precompiled.hpp" -#include "gc/shenandoah/shenandoah_globals.hpp" - -SHENANDOAH_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \ - MATERIALIZE_PD_DEVELOPER_FLAG, \ - MATERIALIZE_PRODUCT_FLAG, \ - MATERIALIZE_PD_PRODUCT_FLAG, \ - MATERIALIZE_DIAGNOSTIC_FLAG, \ - MATERIALIZE_EXPERIMENTAL_FLAG, \ - MATERIALIZE_NOTPRODUCT_FLAG, \ - MATERIALIZE_MANAGEABLE_FLAG, \ - MATERIALIZE_PRODUCT_RW_FLAG, \ - IGNORE_RANGE, \ - IGNORE_CONSTRAINT, \ - IGNORE_WRITEABLE) diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp @@ -24,23 +24,20 @@ #ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAH_GLOBALS_HPP #define SHARE_VM_GC_SHENANDOAH_SHENANDOAH_GLOBALS_HPP -#include "runtime/globals.hpp" - -#define SHENANDOAH_FLAGS(develop, \ - develop_pd, \ - product, \ - product_pd, \ - diagnostic, \ - experimental, \ - notproduct, \ - manageable, \ - product_rw, \ - range, \ - constraint, \ - writeable) \ - \ - product(bool, UseShenandoahGC, false, \ - "Use the Shenandoah garbage collector") \ +#define GC_SHENANDOAH_FLAGS(develop, \ + develop_pd, \ + product, \ + product_pd, \ + diagnostic, \ + diagnostic_pd, \ + experimental, \ + notproduct, \ + manageable, \ + product_rw, \ + lp64_product, \ + range, \ + constraint, \ + writeable) \ \ product(bool, ShenandoahOptimizeStaticFinals, true, \ "Optimize barriers on static final fields. " \ @@ -441,20 +438,6 @@ diagnostic(bool, ShenandoahAllowMixedAllocs, true, \ "Allow mixing mutator and collector allocations in a single " \ "region") \ - \ -SHENANDOAH_FLAGS(DECLARE_DEVELOPER_FLAG, \ - DECLARE_PD_DEVELOPER_FLAG, \ - DECLARE_PRODUCT_FLAG, \ - DECLARE_PD_PRODUCT_FLAG, \ - DECLARE_DIAGNOSTIC_FLAG, \ - DECLARE_EXPERIMENTAL_FLAG, \ - DECLARE_NOTPRODUCT_FLAG, \ - DECLARE_MANAGEABLE_FLAG, \ - DECLARE_PRODUCT_RW_FLAG, \ - IGNORE_RANGE, \ - IGNORE_CONSTRAINT, \ - IGNORE_WRITEABLE) - #endif // SHARE_VM_GC_SHENANDOAH_SHENANDOAH_GLOBALS_HPP