--- old/make/autoconf/hotspot.m4 2020-01-17 17:14:11.751117164 +0100 +++ new/make/autoconf/hotspot.m4 2020-01-17 17:14:11.649117169 +0100 @@ -25,7 +25,7 @@ # All valid JVM features, regardless of platform VALID_JVM_FEATURES="compiler1 compiler2 zero minimal dtrace jvmti jvmci \ - graal vm-structs jni-check services management cmsgc epsilongc g1gc parallelgc serialgc zgc nmt cds \ + graal vm-structs jni-check services management cmsgc epsilongc g1gc parallelgc serialgc shenandoahgc zgc nmt cds \ static-build link-time-opt aot jfr" # Deprecated JVM features (these are ignored, but with a warning) @@ -338,6 +338,15 @@ fi fi + # Only enable Shenandoah on supported arches + AC_MSG_CHECKING([if shenandoah can be built]) + if test "x$OPENJDK_TARGET_CPU_ARCH" = "xx86" || test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then + AC_MSG_RESULT([yes]) + else + DISABLED_JVM_FEATURES="$DISABLED_JVM_FEATURES shenandoahgc" + AC_MSG_RESULT([no, platform not supported]) + fi + # Only enable ZGC on supported platforms AC_MSG_CHECKING([if zgc can be built]) if test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then @@ -349,7 +358,7 @@ # Disable unsupported GCs for Zero if HOTSPOT_CHECK_JVM_VARIANT(zero); then - DISABLED_JVM_FEATURES="$DISABLED_JVM_FEATURES epsilongc g1gc zgc" + DISABLED_JVM_FEATURES="$DISABLED_JVM_FEATURES epsilongc g1gc shenandoahgc zgc" fi # Turn on additional features based on other parts of configure @@ -483,7 +492,7 @@ fi # All variants but minimal (and custom) get these features - NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES cmsgc g1gc parallelgc serialgc epsilongc jni-check jvmti management nmt services vm-structs zgc" + NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES cmsgc g1gc parallelgc serialgc epsilongc shenandoahgc jni-check jvmti management nmt services vm-structs zgc" AC_MSG_CHECKING([if cds should be enabled]) if test "x$ENABLE_CDS" = "xtrue"; then --- old/make/hotspot/gensrc/GensrcAdlc.gmk 2020-01-17 17:14:12.342117131 +0100 +++ new/make/hotspot/gensrc/GensrcAdlc.gmk 2020-01-17 17:14:12.240117137 +0100 @@ -136,6 +136,12 @@ $d/os_cpu/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH)/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH).ad \ ))) + ifeq ($(call check-jvm-feature, shenandoahgc), true) + AD_SRC_FILES += $(call uniq, $(wildcard $(foreach d, $(AD_SRC_ROOTS), \ + $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/gc/shenandoah/shenandoah_$(HOTSPOT_TARGET_CPU).ad \ + ))) + endif + SINGLE_AD_SRCFILE := $(ADLC_SUPPORT_DIR)/all-ad-src.ad INSERT_FILENAME_AWK_SCRIPT := \ --- old/make/hotspot/lib/JvmFeatures.gmk 2020-01-17 17:14:12.933117098 +0100 +++ new/make/hotspot/lib/JvmFeatures.gmk 2020-01-17 17:14:12.830117104 +0100 @@ -166,6 +166,11 @@ JVM_EXCLUDE_PATTERNS += gc/z endif +ifneq ($(call check-jvm-feature, shenandoahgc), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_SHENANDOAHGC=0 + JVM_EXCLUDE_PATTERNS += gc/shenandoah +endif + ifneq ($(call check-jvm-feature, jfr), true) JVM_CFLAGS_FEATURES += -DINCLUDE_JFR=0 JVM_EXCLUDE_PATTERNS += jfr --- old/make/hotspot/lib/JvmOverrideFiles.gmk 2020-01-17 17:14:13.511117067 +0100 +++ new/make/hotspot/lib/JvmOverrideFiles.gmk 2020-01-17 17:14:13.410117072 +0100 @@ -36,6 +36,11 @@ BUILD_LIBJVM_assembler_x86.cpp_CXXFLAGS := -Wno-maybe-uninitialized BUILD_LIBJVM_cardTableBarrierSetAssembler_x86.cpp_CXXFLAGS := -Wno-maybe-uninitialized BUILD_LIBJVM_interp_masm_x86.cpp_CXXFLAGS := -Wno-uninitialized + ifeq ($(DEBUG_LEVEL), release) + # Need extra inlining to collapse all marking code into the hot marking loop + BUILD_LIBJVM_shenandoahConcurrentMark.cpp_CXXFLAGS := --param inline-unit-growth=1000 + BUILD_LIBJVM_shenandoahTraversalGC.cpp_CXXFLAGS := --param inline-unit-growth=1000 + endif endif LIBJVM_FDLIBM_COPY_OPT_FLAG := $(CXX_O_FLAG_NONE) --- old/src/hotspot/cpu/aarch64/aarch64.ad 2020-01-17 17:14:14.086117035 +0100 +++ new/src/hotspot/cpu/aarch64/aarch64.ad 2020-01-17 17:14:13.983117041 +0100 @@ -1280,6 +1280,10 @@ case Op_GetAndSetN: case Op_GetAndAddI: case Op_GetAndAddL: +#if INCLUDE_SHENANDOAHGC + case Op_ShenandoahCompareAndSwapP: + case Op_ShenandoahCompareAndSwapN: +#endif return true; case Op_CompareAndExchangeI: case Op_CompareAndExchangeN: --- old/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp 2020-01-17 17:14:14.814116995 +0100 +++ new/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp 2020-01-17 17:14:14.712117000 +0100 @@ -36,6 +36,7 @@ #include "gc/shared/c1/barrierSetC1.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" +#include "utilities/macros.hpp" #include "vmreg_x86.inline.hpp" #ifdef ASSERT @@ -674,6 +675,11 @@ if (type == T_OBJECT || type == T_ARRAY) { cmp_value.load_item_force(FrameMap::rax_oop_opr); new_value.load_item(); +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC) { + __ cas_obj(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), new_register(T_OBJECT), new_register(T_OBJECT)); + } else +#endif __ cas_obj(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), ill, ill); } else if (type == T_INT) { cmp_value.load_item_force(FrameMap::rax_opr); @@ -699,6 +705,12 @@ // Because we want a 2-arg form of xchg and xadd __ move(value.result(), result); assert(type == T_INT || is_oop LP64_ONLY( || type == T_LONG ), "unexpected type"); +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC) { + LIR_Opr tmp = is_oop ? new_register(type) : LIR_OprFact::illegalOpr; + __ xchg(addr, result, result, tmp); + } else +#endif __ xchg(addr, result, result, LIR_OprFact::illegalOpr); return result; } --- old/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp 2020-01-17 17:14:15.410116962 +0100 +++ new/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp 2020-01-17 17:14:15.308116968 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, 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 @@ -33,6 +33,7 @@ #include "code/nativeInst.hpp" #include "code/vtableStubs.hpp" #include "gc/shared/gcLocker.hpp" +#include "gc/shared/collectedHeap.hpp" #include "interpreter/interpreter.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" @@ -1434,6 +1435,102 @@ } } +// Pin incoming array argument of java critical method +static void pin_critical_native_array(MacroAssembler* masm, + VMRegPair reg, + int& pinned_slot) { + assert(UseShenandoahGC, "only supported in Shenandoah for now"); + __ block_comment("pin_critical_native_array {"); + Register tmp_reg = rax; + + Label is_null; + VMRegPair tmp; + VMRegPair in_reg = reg; + bool on_stack = false; + + tmp.set_ptr(tmp_reg->as_VMReg()); + if (reg.first()->is_stack()) { + // Load the arg up from the stack + move_ptr(masm, reg, tmp); + reg = tmp; + on_stack = true; + } else { + __ movptr(rax, reg.first()->as_Register()); + } + __ testptr(reg.first()->as_Register(), reg.first()->as_Register()); + __ jccb(Assembler::equal, is_null); + + __ push(c_rarg0); + __ push(c_rarg1); + __ push(c_rarg2); + __ push(c_rarg3); +#ifdef _WIN64 + // caller-saved registers on Windows + __ push(r10); + __ push(r11); +#else + __ push(c_rarg4); + __ push(c_rarg5); +#endif + + if (reg.first()->as_Register() != c_rarg1) { + __ movptr(c_rarg1, reg.first()->as_Register()); + } + __ movptr(c_rarg0, r15_thread); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::pin_object))); + +#ifdef _WIN64 + __ pop(r11); + __ pop(r10); +#else + __ pop(c_rarg5); + __ pop(c_rarg4); +#endif + __ pop(c_rarg3); + __ pop(c_rarg2); + __ pop(c_rarg1); + __ pop(c_rarg0); + + if (on_stack) { + __ movptr(Address(rbp, reg2offset_in(in_reg.first())), rax); + __ bind(is_null); + } else { + __ movptr(reg.first()->as_Register(), rax); + + // save on stack for unpinning later + __ bind(is_null); + assert(reg.first()->is_Register(), "Must be a register"); + int offset = pinned_slot * VMRegImpl::stack_slot_size; + pinned_slot += VMRegImpl::slots_per_word; + __ movq(Address(rsp, offset), rax); + } + __ block_comment("} pin_critical_native_array"); +} + +// Unpin array argument of java critical method +static void unpin_critical_native_array(MacroAssembler* masm, + VMRegPair reg, + int& pinned_slot) { + assert(UseShenandoahGC, "only supported in Shenandoah for now"); + __ block_comment("unpin_critical_native_array {"); + Label is_null; + + if (reg.first()->is_stack()) { + __ movptr(c_rarg1, Address(rbp, reg2offset_in(reg.first()))); + } else { + int offset = pinned_slot * VMRegImpl::stack_slot_size; + pinned_slot += VMRegImpl::slots_per_word; + __ movq(c_rarg1, Address(rsp, offset)); + } + __ testptr(c_rarg1, c_rarg1); + __ jccb(Assembler::equal, is_null); + + __ movptr(c_rarg0, r15_thread); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::unpin_object))); + + __ bind(is_null); + __ block_comment("} unpin_critical_native_array"); +} // Check GCLocker::needs_gc and enter the runtime if it's true. This // keeps a new JNI critical region from starting until a GC has been @@ -2130,7 +2227,7 @@ const Register oop_handle_reg = r14; - if (is_critical_native) { + if (is_critical_native && !Universe::heap()->supports_object_pinning()) { check_needs_gc_for_critical_native(masm, stack_slots, total_c_args, total_in_args, oop_handle_offset, oop_maps, in_regs, in_sig_bt); } @@ -2187,6 +2284,11 @@ // the incoming and outgoing registers are offset upwards and for // critical natives they are offset down. GrowableArray arg_order(2 * total_in_args); + // Inbound arguments that need to be pinned for critical natives + GrowableArray pinned_args(total_in_args); + // Current stack slot for storing register based array argument + int pinned_slot = oop_handle_offset; + VMRegPair tmp_vmreg; tmp_vmreg.set2(rbx->as_VMReg()); @@ -2234,6 +2336,12 @@ switch (in_sig_bt[i]) { case T_ARRAY: if (is_critical_native) { + // pin before unpack + if (Universe::heap()->supports_object_pinning()) { + assert(pinned_slot <= stack_slots, "overflow"); + pin_critical_native_array(masm, in_regs[i], pinned_slot); + pinned_args.append(i); + } unpack_array_argument(masm, in_regs[i], in_elem_bt[i], out_regs[c_arg + 1], out_regs[c_arg]); c_arg++; #ifdef ASSERT @@ -2450,6 +2558,19 @@ default : ShouldNotReachHere(); } + // unpin pinned arguments + pinned_slot = oop_handle_offset; + if (pinned_args.length() > 0) { + // save return value that may be overwritten otherwise. + save_native_result(masm, ret_type, stack_slots); + for (int index = 0; index < pinned_args.length(); index ++) { + int i = pinned_args.at(index); + assert(pinned_slot <= stack_slots, "overflow"); + unpin_critical_native_array(masm, in_regs[i], pinned_slot); + } + restore_native_result(masm, ret_type, stack_slots); + } + // Switch thread to "native transition" state before reading the synchronization state. // This additional state is necessary because reading and testing the synchronization // state is not atomic w.r.t. GC, as this scenario demonstrates: --- old/src/hotspot/share/adlc/formssel.cpp 2020-01-17 17:14:16.026116928 +0100 +++ new/src/hotspot/share/adlc/formssel.cpp 2020-01-17 17:14:15.929116933 +0100 @@ -778,6 +778,10 @@ !strcmp(_matrule->_rChild->_opType,"LoadBarrierSlowReg") || !strcmp(_matrule->_rChild->_opType,"LoadBarrierWeakSlowReg") || #endif +#if INCLUDE_SHENANDOAHGC + !strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeP") || + !strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeN") || +#endif !strcmp(_matrule->_rChild->_opType,"CompareAndExchangeP") || !strcmp(_matrule->_rChild->_opType,"CompareAndExchangeN"))) return true; else if ( is_ideal_load() == Form::idealP ) return true; @@ -3502,6 +3506,9 @@ "CompareAndSwapB", "CompareAndSwapS", "CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN", "WeakCompareAndSwapB", "WeakCompareAndSwapS", "WeakCompareAndSwapI", "WeakCompareAndSwapL", "WeakCompareAndSwapP", "WeakCompareAndSwapN", "CompareAndExchangeB", "CompareAndExchangeS", "CompareAndExchangeI", "CompareAndExchangeL", "CompareAndExchangeP", "CompareAndExchangeN", +#if INCLUDE_SHENANDOAHGC + "ShenandoahCompareAndSwapN", "ShenandoahCompareAndSwapP", "ShenandoahWeakCompareAndSwapP", "ShenandoahWeakCompareAndSwapN", "ShenandoahCompareAndExchangeP", "ShenandoahCompareAndExchangeN", +#endif "StoreCM", "ClearArray", "GetAndSetB", "GetAndSetS", "GetAndAddI", "GetAndSetI", "GetAndSetP", --- old/src/hotspot/share/ci/ciInstanceKlass.cpp 2020-01-17 17:14:16.660116893 +0100 +++ new/src/hotspot/share/ci/ciInstanceKlass.cpp 2020-01-17 17:14:16.560116899 +0100 @@ -554,6 +554,12 @@ _has_injected_fields = has_injected_fields; } +bool ciInstanceKlass::has_object_fields() const { + GUARDED_VM_ENTRY( + return get_instanceKlass()->nonstatic_oop_map_size() > 0; + ); +} + // ------------------------------------------------------------------ // ciInstanceKlass::find_method // --- old/src/hotspot/share/ci/ciInstanceKlass.hpp 2020-01-17 17:14:17.247116861 +0100 +++ new/src/hotspot/share/ci/ciInstanceKlass.hpp 2020-01-17 17:14:17.148116866 +0100 @@ -202,6 +202,8 @@ return _has_injected_fields > 0 ? true : false; } + bool has_object_fields() const; + // nth nonstatic field (presented by ascending address) ciField* nonstatic_field_at(int i) { assert(_nonstatic_fields != NULL, ""); --- old/src/hotspot/share/code/codeBlob.cpp 2020-01-17 17:14:17.827116829 +0100 +++ new/src/hotspot/share/code/codeBlob.cpp 2020-01-17 17:14:17.727116834 +0100 @@ -31,6 +31,7 @@ #include "code/vtableStubs.hpp" #include "compiler/disassembler.hpp" #include "interpreter/bytecode.hpp" +#include "interpreter/interpreter.hpp" #include "memory/allocation.inline.hpp" #include "memory/heap.hpp" #include "memory/resourceArea.hpp" --- old/src/hotspot/share/code/codeCache.hpp 2020-01-17 17:14:18.407116797 +0100 +++ new/src/hotspot/share/code/codeCache.hpp 2020-01-17 17:14:18.310116802 +0100 @@ -73,6 +73,7 @@ class OopClosure; class KlassDepChange; +class ShenandoahParallelCodeHeapIterator; class CodeCache : AllStatic { friend class VMStructs; @@ -80,6 +81,7 @@ template friend class CodeBlobIterator; friend class WhiteBox; friend class CodeCacheLoader; + friend class ShenandoahParallelCodeHeapIterator; private: // CodeHeaps of the cache static GrowableArray* _heaps; --- old/src/hotspot/share/gc/shared/barrierSetConfig.hpp 2020-01-17 17:14:18.992116765 +0100 +++ new/src/hotspot/share/gc/shared/barrierSetConfig.hpp 2020-01-17 17:14:18.891116770 +0100 @@ -32,6 +32,7 @@ f(CardTableBarrierSet) \ EPSILONGC_ONLY(f(EpsilonBarrierSet)) \ G1GC_ONLY(f(G1BarrierSet)) \ + SHENANDOAHGC_ONLY(f(ShenandoahBarrierSet)) \ ZGC_ONLY(f(ZBarrierSet)) #define FOR_EACH_ABSTRACT_BARRIER_SET_DO(f) \ --- old/src/hotspot/share/gc/shared/barrierSetConfig.inline.hpp 2020-01-17 17:14:19.569116733 +0100 +++ new/src/hotspot/share/gc/shared/barrierSetConfig.inline.hpp 2020-01-17 17:14:19.471116738 +0100 @@ -36,6 +36,9 @@ #if INCLUDE_G1GC #include "gc/g1/g1BarrierSet.inline.hpp" #endif +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/shenandoahBarrierSet.inline.hpp" +#endif #if INCLUDE_ZGC #include "gc/z/zBarrierSet.inline.hpp" #endif --- old/src/hotspot/share/gc/shared/collectedHeap.hpp 2020-01-17 17:14:20.148116701 +0100 +++ new/src/hotspot/share/gc/shared/collectedHeap.hpp 2020-01-17 17:14:20.049116706 +0100 @@ -89,6 +89,7 @@ // CMSHeap // G1CollectedHeap // ParallelScavengeHeap +// ShenandoahHeap // ZCollectedHeap // class CollectedHeap : public CHeapObj { @@ -178,7 +179,8 @@ CMS, G1, Epsilon, - Z + Z, + Shenandoah }; static inline size_t filler_array_max_size() { --- old/src/hotspot/share/gc/shared/gcCause.cpp 2020-01-17 17:14:20.737116668 +0100 +++ new/src/hotspot/share/gc/shared/gcCause.cpp 2020-01-17 17:14:20.637116674 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, 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 @@ -105,6 +105,21 @@ case _dcmd_gc_run: return "Diagnostic Command"; + case _shenandoah_allocation_failure_evac: + return "Allocation Failure During Evacuation"; + + case _shenandoah_stop_vm: + return "Stopping VM"; + + case _shenandoah_concurrent_gc: + return "Concurrent GC"; + + case _shenandoah_traversal_gc: + return "Traversal GC"; + + case _shenandoah_upgrade_to_full_gc: + return "Upgrade To Full GC"; + case _z_timer: return "Timer"; --- old/src/hotspot/share/gc/shared/gcCause.hpp 2020-01-17 17:14:21.328116636 +0100 +++ new/src/hotspot/share/gc/shared/gcCause.hpp 2020-01-17 17:14:21.223116642 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, 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 @@ -78,6 +78,12 @@ _dcmd_gc_run, + _shenandoah_stop_vm, + _shenandoah_allocation_failure_evac, + _shenandoah_concurrent_gc, + _shenandoah_traversal_gc, + _shenandoah_upgrade_to_full_gc, + _z_timer, _z_warmup, _z_allocation_rate, @@ -121,7 +127,8 @@ // _allocation_failure is the generic cause a collection for allocation failure // _adaptive_size_policy is for a collecton done before a full GC return (cause == GCCause::_allocation_failure || - cause == GCCause::_adaptive_size_policy); + cause == GCCause::_adaptive_size_policy || + cause == GCCause::_shenandoah_allocation_failure_evac); } // Return a string describing the GCCause. --- old/src/hotspot/share/gc/shared/gcConfig.cpp 2020-01-17 17:14:21.910116604 +0100 +++ new/src/hotspot/share/gc/shared/gcConfig.cpp 2020-01-17 17:14:21.810116609 +0100 @@ -43,6 +43,9 @@ #if INCLUDE_SERIALGC #include "gc/serial/serialArguments.hpp" #endif +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/shenandoahArguments.hpp" +#endif #if INCLUDE_ZGC #include "gc/z/zArguments.hpp" #endif @@ -57,23 +60,25 @@ _flag(flag), _name(name), _arguments(arguments), _hs_err_name(hs_err_name) {} }; - CMSGC_ONLY(static CMSArguments cmsArguments;) - EPSILONGC_ONLY(static EpsilonArguments epsilonArguments;) - G1GC_ONLY(static G1Arguments g1Arguments;) -PARALLELGC_ONLY(static ParallelArguments parallelArguments;) - SERIALGC_ONLY(static SerialArguments serialArguments;) - ZGC_ONLY(static ZArguments zArguments;) + CMSGC_ONLY(static CMSArguments cmsArguments;) + EPSILONGC_ONLY(static EpsilonArguments epsilonArguments;) + G1GC_ONLY(static G1Arguments g1Arguments;) + PARALLELGC_ONLY(static ParallelArguments parallelArguments;) + SERIALGC_ONLY(static SerialArguments serialArguments;) +SHENANDOAHGC_ONLY(static ShenandoahArguments shenandoahArguments;) + ZGC_ONLY(static ZArguments zArguments;) // Table of supported GCs, for translating between command // line flag, CollectedHeap::Name and GCArguments instance. static const SupportedGC SupportedGCs[] = { - CMSGC_ONLY_ARG(SupportedGC(UseConcMarkSweepGC, CollectedHeap::CMS, cmsArguments, "concurrent mark sweep gc")) - EPSILONGC_ONLY_ARG(SupportedGC(UseEpsilonGC, CollectedHeap::Epsilon, epsilonArguments, "epsilon gc")) - G1GC_ONLY_ARG(SupportedGC(UseG1GC, CollectedHeap::G1, g1Arguments, "g1 gc")) - PARALLELGC_ONLY_ARG(SupportedGC(UseParallelGC, CollectedHeap::Parallel, parallelArguments, "parallel gc")) - PARALLELGC_ONLY_ARG(SupportedGC(UseParallelOldGC, CollectedHeap::Parallel, parallelArguments, "parallel gc")) - SERIALGC_ONLY_ARG(SupportedGC(UseSerialGC, CollectedHeap::Serial, serialArguments, "serial gc")) - ZGC_ONLY_ARG(SupportedGC(UseZGC, CollectedHeap::Z, zArguments, "z gc")) + CMSGC_ONLY_ARG(SupportedGC(UseConcMarkSweepGC, CollectedHeap::CMS, cmsArguments, "concurrent mark sweep gc")) + EPSILONGC_ONLY_ARG(SupportedGC(UseEpsilonGC, CollectedHeap::Epsilon, epsilonArguments, "epsilon gc")) + G1GC_ONLY_ARG(SupportedGC(UseG1GC, CollectedHeap::G1, g1Arguments, "g1 gc")) + PARALLELGC_ONLY_ARG(SupportedGC(UseParallelGC, CollectedHeap::Parallel, parallelArguments, "parallel gc")) + PARALLELGC_ONLY_ARG(SupportedGC(UseParallelOldGC, CollectedHeap::Parallel, parallelArguments, "parallel gc")) + SERIALGC_ONLY_ARG(SupportedGC(UseSerialGC, CollectedHeap::Serial, serialArguments, "serial gc")) +SHENANDOAHGC_ONLY_ARG(SupportedGC(UseShenandoahGC, CollectedHeap::Shenandoah, shenandoahArguments, "shenandoah gc")) + ZGC_ONLY_ARG(SupportedGC(UseZGC, CollectedHeap::Z, zArguments, "z gc")) }; #define FOR_EACH_SUPPORTED_GC(var) \ @@ -90,14 +95,15 @@ bool GCConfig::_gc_selected_ergonomically = false; void GCConfig::fail_if_unsupported_gc_is_selected() { - NOT_CMSGC( FAIL_IF_SELECTED(UseConcMarkSweepGC, true)); - NOT_EPSILONGC( FAIL_IF_SELECTED(UseEpsilonGC, true)); - NOT_G1GC( FAIL_IF_SELECTED(UseG1GC, true)); - NOT_PARALLELGC(FAIL_IF_SELECTED(UseParallelGC, true)); - NOT_PARALLELGC(FAIL_IF_SELECTED(UseParallelOldGC, true)); - NOT_SERIALGC( FAIL_IF_SELECTED(UseSerialGC, true)); - NOT_SERIALGC( FAIL_IF_SELECTED(UseParallelOldGC, false)); - NOT_ZGC( FAIL_IF_SELECTED(UseZGC, true)); + NOT_CMSGC( FAIL_IF_SELECTED(UseConcMarkSweepGC, true)); + NOT_EPSILONGC( FAIL_IF_SELECTED(UseEpsilonGC, true)); + NOT_G1GC( FAIL_IF_SELECTED(UseG1GC, true)); + NOT_PARALLELGC( FAIL_IF_SELECTED(UseParallelGC, true)); + NOT_PARALLELGC( FAIL_IF_SELECTED(UseParallelOldGC, true)); + NOT_SERIALGC( FAIL_IF_SELECTED(UseSerialGC, true)); + NOT_SERIALGC( FAIL_IF_SELECTED(UseParallelOldGC, false)); + NOT_SHENANDOAHGC(FAIL_IF_SELECTED(UseShenandoahGC, true)); + NOT_ZGC( FAIL_IF_SELECTED(UseZGC, true)); } void GCConfig::select_gc_ergonomically() { --- old/src/hotspot/share/gc/shared/gcConfiguration.cpp 2020-01-17 17:14:22.491116572 +0100 +++ new/src/hotspot/share/gc/shared/gcConfiguration.cpp 2020-01-17 17:14:22.391116577 +0100 @@ -43,7 +43,7 @@ return ParNew; } - if (UseZGC) { + if (UseZGC || UseShenandoahGC) { return NA; } @@ -67,6 +67,10 @@ return Z; } + if (UseShenandoahGC) { + return Shenandoah; + } + return SerialOld; } --- old/src/hotspot/share/gc/shared/gcName.hpp 2020-01-17 17:14:23.072116540 +0100 +++ new/src/hotspot/share/gc/shared/gcName.hpp 2020-01-17 17:14:22.972116545 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, 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 @@ -39,6 +39,7 @@ G1Old, G1Full, Z, + Shenandoah, NA, GCNameEndSentinel }; @@ -58,6 +59,7 @@ case G1Old: return "G1Old"; case G1Full: return "G1Full"; case Z: return "Z"; + case Shenandoah: return "Shenandoah"; case NA: return "N/A"; default: ShouldNotReachHere(); return NULL; } --- old/src/hotspot/share/gc/shared/gc_globals.hpp 2020-01-17 17:14:23.649116508 +0100 +++ new/src/hotspot/share/gc/shared/gc_globals.hpp 2020-01-17 17:14:23.547116514 +0100 @@ -41,6 +41,9 @@ #if INCLUDE_SERIALGC #include "gc/serial/serial_globals.hpp" #endif +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/shenandoah_globals.hpp" +#endif #if INCLUDE_ZGC #include "gc/z/z_globals.hpp" #endif @@ -140,6 +143,22 @@ constraint, \ writeable)) \ \ + SHENANDOAHGC_ONLY(GC_SHENANDOAH_FLAGS( \ + develop, \ + develop_pd, \ + product, \ + product_pd, \ + diagnostic, \ + diagnostic_pd, \ + experimental, \ + notproduct, \ + manageable, \ + product_rw, \ + lp64_product, \ + range, \ + constraint, \ + writeable)) \ + \ ZGC_ONLY(GC_Z_FLAGS( \ develop, \ develop_pd, \ @@ -179,6 +198,9 @@ experimental(bool, UseZGC, false, \ "Use the Z garbage collector") \ \ + experimental(bool, UseShenandoahGC, false, \ + "Use the Shenandoah garbage collector") \ + \ product(uint, ParallelGCThreads, 0, \ "Number of parallel threads parallel gc will use") \ constraint(ParallelGCThreadsConstraintFunc,AfterErgo) \ --- old/src/hotspot/share/gc/shared/referenceProcessor.cpp 2020-01-17 17:14:24.245116475 +0100 +++ new/src/hotspot/share/gc/shared/referenceProcessor.cpp 2020-01-17 17:14:24.141116481 +0100 @@ -1156,7 +1156,7 @@ // Check assumption that an object is not potentially // discovered twice except by concurrent collectors that potentially // trace the same Reference object twice. - assert(UseConcMarkSweepGC || UseG1GC, + assert(UseConcMarkSweepGC || UseG1GC || UseShenandoahGC, "Only possible with a concurrent marking collector"); return true; } --- old/src/hotspot/share/gc/shared/taskqueue.hpp 2020-01-17 17:14:24.834116443 +0100 +++ new/src/hotspot/share/gc/shared/taskqueue.hpp 2020-01-17 17:14:24.734116448 +0100 @@ -357,7 +357,8 @@ static int randomParkAndMiller(int* seed0); public: // Returns "true" if some TaskQueue in the set contains a task. - virtual bool peek() = 0; + virtual bool peek() = 0; + virtual size_t tasks() = 0; }; template class TaskQueueSetSuperImpl: public CHeapObj, public TaskQueueSetSuper { @@ -389,6 +390,7 @@ bool steal(uint queue_num, int* seed, E& t); bool peek(); + size_t tasks(); uint size() const { return _n; } }; @@ -414,6 +416,16 @@ return false; } +template +size_t GenericTaskQueueSet::tasks() { + size_t n = 0; + for (uint j = 0; j < _n; j++) { + n += _queues[j]->size(); + } + return n; +} + + // When to terminate from the termination protocol. class TerminatorTerminator: public CHeapObj { public: @@ -426,7 +438,7 @@ #undef TRACESPINNING class ParallelTaskTerminator: public StackObj { -private: +protected: uint _n_threads; TaskQueueSetSuper* _queue_set; @@ -462,7 +474,7 @@ // As above, but it also terminates if the should_exit_termination() // method of the terminator parameter returns true. If terminator is // NULL, then it is ignored. - bool offer_termination(TerminatorTerminator* terminator); + virtual bool offer_termination(TerminatorTerminator* terminator); // Reset the terminator, so that it may be reused again. // The caller is responsible for ensuring that this is done --- old/src/hotspot/share/gc/shared/vmStructs_gc.hpp 2020-01-17 17:14:25.413116411 +0100 +++ new/src/hotspot/share/gc/shared/vmStructs_gc.hpp 2020-01-17 17:14:25.315116416 +0100 @@ -50,6 +50,9 @@ #include "gc/serial/defNewGeneration.hpp" #include "gc/serial/vmStructs_serial.hpp" #endif +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/vmStructs_shenandoah.hpp" +#endif #if INCLUDE_ZGC #include "gc/z/vmStructs_z.hpp" #endif @@ -73,6 +76,9 @@ SERIALGC_ONLY(VM_STRUCTS_SERIALGC(nonstatic_field, \ volatile_nonstatic_field, \ static_field)) \ + SHENANDOAHGC_ONLY(VM_STRUCTS_SHENANDOAH(nonstatic_field, \ + volatile_nonstatic_field, \ + static_field)) \ ZGC_ONLY(VM_STRUCTS_ZGC(nonstatic_field, \ volatile_nonstatic_field, \ static_field)) \ @@ -178,6 +184,9 @@ SERIALGC_ONLY(VM_TYPES_SERIALGC(declare_type, \ declare_toplevel_type, \ declare_integer_type)) \ + SHENANDOAHGC_ONLY(VM_TYPES_SHENANDOAH(declare_type, \ + declare_toplevel_type, \ + declare_integer_type)) \ ZGC_ONLY(VM_TYPES_ZGC(declare_type, \ declare_toplevel_type, \ declare_integer_type)) \ @@ -253,6 +262,8 @@ declare_constant_with_value)) \ SERIALGC_ONLY(VM_INT_CONSTANTS_SERIALGC(declare_constant, \ declare_constant_with_value)) \ + SHENANDOAHGC_ONLY(VM_INT_CONSTANTS_SHENANDOAH(declare_constant, \ + declare_constant_with_value)) \ ZGC_ONLY(VM_INT_CONSTANTS_ZGC(declare_constant, \ declare_constant_with_value)) \ \ --- old/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp 2020-01-17 17:14:25.993116379 +0100 +++ new/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp 2020-01-17 17:14:25.892116384 +0100 @@ -129,7 +129,7 @@ ZBarrierSetC2State* s = bs->state(); if (s->load_barrier_count() >= 2) { Compile::TracePhase tp("idealLoop", &C->timers[Phase::_t_idealLoop]); - PhaseIdealLoop ideal_loop(igvn, true, false, true); + PhaseIdealLoop ideal_loop(igvn, LoopOptsZgcLastRound); if (C->major_progress()) C->print_method(PHASE_PHASEIDEALLOOP_ITERATIONS, 2); } } --- old/src/hotspot/share/jfr/leakprofiler/leakProfiler.cpp 2020-01-17 17:14:26.590116346 +0100 +++ new/src/hotspot/share/jfr/leakprofiler/leakProfiler.cpp 2020-01-17 17:14:26.488116352 +0100 @@ -53,6 +53,11 @@ return false; } + if (UseShenandoahGC) { + log_warning(jfr)("LeakProfiler is currently not supported in combination with Shenandoah GC"); + return false; + } + assert(!is_running(), "invariant"); assert(sample_count > 0, "invariant"); --- old/src/hotspot/share/jfr/metadata/metadata.xml 2020-01-17 17:14:27.167116314 +0100 +++ new/src/hotspot/share/jfr/metadata/metadata.xml 2020-01-17 17:14:27.069116320 +0100 @@ -922,6 +922,27 @@ + + + + + + + + + + + + + + + + + + + --- old/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp 2020-01-17 17:14:27.786116280 +0100 +++ new/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp 2020-01-17 17:14:27.684116286 +0100 @@ -63,6 +63,9 @@ #if INCLUDE_G1GC #include "gc/g1/g1HeapRegionEventSender.hpp" #endif +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/shenandoahJfrSupport.hpp" +#endif /** * JfrPeriodic class @@ -574,3 +577,14 @@ event.set_flushingEnabled(UseCodeCacheFlushing); event.commit(); } + + +TRACE_REQUEST_FUNC(ShenandoahHeapRegionInformation) { +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC) { + VM_ShenandoahSendHeapRegionInfoEvents op; + VMThread::execute(&op); + } +#endif +} + --- old/src/hotspot/share/memory/metaspace.hpp 2020-01-17 17:14:28.369116248 +0100 +++ new/src/hotspot/share/memory/metaspace.hpp 2020-01-17 17:14:28.270116253 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, 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 @@ -235,6 +235,7 @@ class ClassLoaderMetaspace : public CHeapObj { friend class CollectedHeap; // For expand_and_allocate() friend class ZCollectedHeap; // For expand_and_allocate() + friend class ShenandoahHeap; // For expand_and_allocate() friend class Metaspace; friend class MetaspaceUtils; friend class metaspace::PrintCLDMetaspaceInfoClosure; --- old/src/hotspot/share/opto/arraycopynode.cpp 2020-01-17 17:14:28.955116216 +0100 +++ new/src/hotspot/share/opto/arraycopynode.cpp 2020-01-17 17:14:28.857116221 +0100 @@ -30,6 +30,9 @@ #include "opto/graphKit.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/macros.hpp" +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" +#endif ArrayCopyNode::ArrayCopyNode(Compile* C, bool alloc_tightly_coupled, bool has_negative_length_guard) : CallNode(arraycopy_type(), NULL, TypeRawPtr::BOTTOM), @@ -205,6 +208,11 @@ Node* v = LoadNode::make(*phase, ctl, mem->memory_at(fieldidx), next_src, adr_type, type, bt, MemNode::unordered); v = phase->transform(v); +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC && bt == T_OBJECT) { + v = ShenandoahBarrierSetC2::bsc2()->arraycopy_load_reference_barrier(phase, v); + } +#endif Node* s = StoreNode::make(*phase, ctl, mem->memory_at(fieldidx), next_dest, adr_type, v, bt, MemNode::unordered); s = phase->transform(s); mem->set_memory_at(fieldidx, s); @@ -373,6 +381,11 @@ if (count > 0) { Node* v = LoadNode::make(*phase, forward_ctl, start_mem_src, adr_src, atp_src, value_type, copy_type, MemNode::unordered); v = phase->transform(v); +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC && copy_type == T_OBJECT) { + v = ShenandoahBarrierSetC2::bsc2()->arraycopy_load_reference_barrier(phase, v); + } +#endif mem = StoreNode::make(*phase, forward_ctl, mem, adr_dest, atp_dest, v, copy_type, MemNode::unordered); mem = phase->transform(mem); for (int i = 1; i < count; i++) { @@ -381,6 +394,11 @@ Node* next_dest = phase->transform(new AddPNode(base_dest,adr_dest,off)); v = LoadNode::make(*phase, forward_ctl, same_alias ? mem : start_mem_src, next_src, atp_src, value_type, copy_type, MemNode::unordered); v = phase->transform(v); +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC && copy_type == T_OBJECT) { + v = ShenandoahBarrierSetC2::bsc2()->arraycopy_load_reference_barrier(phase, v); + } +#endif mem = StoreNode::make(*phase, forward_ctl,mem,next_dest,atp_dest,v, copy_type, MemNode::unordered); mem = phase->transform(mem); } @@ -422,11 +440,21 @@ Node* next_dest = phase->transform(new AddPNode(base_dest,adr_dest,off)); Node* v = LoadNode::make(*phase, backward_ctl, same_alias ? mem : start_mem_src, next_src, atp_src, value_type, copy_type, MemNode::unordered); v = phase->transform(v); +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC && copy_type == T_OBJECT) { + v = ShenandoahBarrierSetC2::bsc2()->arraycopy_load_reference_barrier(phase, v); + } +#endif mem = StoreNode::make(*phase, backward_ctl,mem,next_dest,atp_dest,v, copy_type, MemNode::unordered); mem = phase->transform(mem); } Node* v = LoadNode::make(*phase, backward_ctl, same_alias ? mem : start_mem_src, adr_src, atp_src, value_type, copy_type, MemNode::unordered); v = phase->transform(v); +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC && copy_type == T_OBJECT) { + v = ShenandoahBarrierSetC2::bsc2()->arraycopy_load_reference_barrier(phase, v); + } +#endif mem = StoreNode::make(*phase, backward_ctl, mem, adr_dest, atp_dest, v, copy_type, MemNode::unordered); mem = phase->transform(mem); } else if(can_reshape) { @@ -485,7 +513,8 @@ } else { if (in(TypeFunc::Control) != ctl) { // we can't return new memory and control from Ideal at parse time - assert(!is_clonebasic(), "added control for clone?"); + assert(!is_clonebasic() || UseShenandoahGC, "added control for clone?"); + phase->record_for_igvn(this); return false; } } --- old/src/hotspot/share/opto/cfgnode.hpp 2020-01-17 17:14:29.535116184 +0100 +++ new/src/hotspot/share/opto/cfgnode.hpp 2020-01-17 17:14:29.439116189 +0100 @@ -303,7 +303,6 @@ protected: ProjNode* range_check_trap_proj(int& flip, Node*& l, Node*& r); Node* Ideal_common(PhaseGVN *phase, bool can_reshape); - Node* dominated_by(Node* prev_dom, PhaseIterGVN* igvn); Node* search_identical(int dist); public: @@ -391,6 +390,7 @@ virtual const RegMask &out_RegMask() const; Node* fold_compares(PhaseIterGVN* phase); static Node* up_one_dom(Node* curr, bool linear_only = false); + Node* dominated_by(Node* prev_dom, PhaseIterGVN* igvn); // Takes the type of val and filters it through the test represented // by if_proj and returns a more refined type if one is produced. --- old/src/hotspot/share/opto/classes.cpp 2020-01-17 17:14:30.125116151 +0100 +++ new/src/hotspot/share/opto/classes.cpp 2020-01-17 17:14:30.024116157 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -51,6 +51,9 @@ #if INCLUDE_ZGC #include "gc/z/c2/zBarrierSetC2.hpp" #endif +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" +#endif // ---------------------------------------------------------------------------- // Build a table of virtual functions to map from Nodes to dense integer --- old/src/hotspot/share/opto/classes.hpp 2020-01-17 17:14:30.698116120 +0100 +++ new/src/hotspot/share/opto/classes.hpp 2020-01-17 17:14:30.602116125 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -265,6 +265,19 @@ macro(RoundFloat) macro(SafePoint) macro(SafePointScalarObject) +#if INCLUDE_SHENANDOAHGC +#define shmacro(x) macro(x) +#else +#define shmacro(x) optionalmacro(x) +#endif +shmacro(ShenandoahCompareAndExchangeP) +shmacro(ShenandoahCompareAndExchangeN) +shmacro(ShenandoahCompareAndSwapN) +shmacro(ShenandoahCompareAndSwapP) +shmacro(ShenandoahWeakCompareAndSwapN) +shmacro(ShenandoahWeakCompareAndSwapP) +shmacro(ShenandoahEnqueueBarrier) +shmacro(ShenandoahLoadReferenceBarrier) macro(SCMemProj) macro(SqrtD) macro(SqrtF) --- old/src/hotspot/share/opto/compile.cpp 2020-01-17 17:14:31.275116088 +0100 +++ new/src/hotspot/share/opto/compile.cpp 2020-01-17 17:14:31.176116093 +0100 @@ -82,6 +82,9 @@ #if INCLUDE_ZGC #include "gc/z/c2/zBarrierSetC2.hpp" #endif +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" +#endif // -------------------- Compile::mach_constant_base_node ----------------------- @@ -2104,7 +2107,7 @@ // PhaseIdealLoop is expensive so we only try it once we are // out of live nodes and we only try it again if the previous // helped got the number of nodes down significantly - PhaseIdealLoop ideal_loop( igvn, false, true ); + PhaseIdealLoop ideal_loop(igvn, LoopOptsNone); if (failing()) return; low_live_nodes = live_nodes(); _major_progress = true; @@ -2155,6 +2158,21 @@ } +bool Compile::optimize_loops(int& loop_opts_cnt, PhaseIterGVN& igvn, LoopOptsMode mode) { + if(loop_opts_cnt > 0) { + debug_only( int cnt = 0; ); + while(major_progress() && (loop_opts_cnt > 0)) { + TracePhase tp("idealLoop", &timers[_t_idealLoop]); + assert( cnt++ < 40, "infinite cycle in loop optimization" ); + PhaseIdealLoop ideal_loop(igvn, mode); + loop_opts_cnt--; + if (failing()) return false; + if (major_progress()) print_method(PHASE_PHASEIDEALLOOP_ITERATIONS, 2); + } + } + return true; +} + //------------------------------Optimize--------------------------------------- // Given a graph, optimize it. void Compile::Optimize() { @@ -2193,10 +2211,10 @@ igvn.optimize(); } - print_method(PHASE_ITER_GVN1, 2); - if (failing()) return; + print_method(PHASE_ITER_GVN1, 2); + inline_incrementally(igvn); print_method(PHASE_INCREMENTAL_INLINE, 2); @@ -2245,7 +2263,7 @@ if (has_loops()) { // Cleanup graph (remove dead nodes). TracePhase tp("idealLoop", &timers[_t_idealLoop]); - PhaseIdealLoop ideal_loop( igvn, false, true ); + PhaseIdealLoop ideal_loop(igvn, LoopOptsNone); if (major_progress()) print_method(PHASE_PHASEIDEAL_BEFORE_EA, 2); if (failing()) return; } @@ -2280,7 +2298,7 @@ if((loop_opts_cnt > 0) && (has_loops() || has_split_ifs())) { { TracePhase tp("idealLoop", &timers[_t_idealLoop]); - PhaseIdealLoop ideal_loop( igvn, true ); + PhaseIdealLoop ideal_loop(igvn, LoopOptsDefault); loop_opts_cnt--; if (major_progress()) print_method(PHASE_PHASEIDEALLOOP1, 2); if (failing()) return; @@ -2288,7 +2306,7 @@ // Loop opts pass if partial peeling occurred in previous pass if(PartialPeelLoop && major_progress() && (loop_opts_cnt > 0)) { TracePhase tp("idealLoop", &timers[_t_idealLoop]); - PhaseIdealLoop ideal_loop( igvn, false ); + PhaseIdealLoop ideal_loop(igvn, LoopOptsSkipSplitIf); loop_opts_cnt--; if (major_progress()) print_method(PHASE_PHASEIDEALLOOP2, 2); if (failing()) return; @@ -2296,7 +2314,7 @@ // Loop opts pass for loop-unrolling before CCP if(major_progress() && (loop_opts_cnt > 0)) { TracePhase tp("idealLoop", &timers[_t_idealLoop]); - PhaseIdealLoop ideal_loop( igvn, false ); + PhaseIdealLoop ideal_loop(igvn, LoopOptsSkipSplitIf); loop_opts_cnt--; if (major_progress()) print_method(PHASE_PHASEIDEALLOOP3, 2); } @@ -2332,16 +2350,8 @@ // Loop transforms on the ideal graph. Range Check Elimination, // peeling, unrolling, etc. - if(loop_opts_cnt > 0) { - debug_only( int cnt = 0; ); - while(major_progress() && (loop_opts_cnt > 0)) { - TracePhase tp("idealLoop", &timers[_t_idealLoop]); - assert( cnt++ < 40, "infinite cycle in loop optimization" ); - PhaseIdealLoop ideal_loop( igvn, true); - loop_opts_cnt--; - if (major_progress()) print_method(PHASE_PHASEIDEALLOOP_ITERATIONS, 2); - if (failing()) return; - } + if (!optimize_loops(loop_opts_cnt, igvn, LoopOptsDefault)) { + return; } #if INCLUDE_ZGC @@ -2383,6 +2393,15 @@ } } + print_method(PHASE_BEFORE_BARRIER_EXPAND, 2); + +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC && ((ShenandoahBarrierSetC2*)BarrierSet::barrier_set()->barrier_set_c2())->expand_barriers(this, igvn)) { + assert(failing(), "must bail out w/ explicit message"); + return; + } +#endif + if (opaque4_count() > 0) { C->remove_opaque4_nodes(igvn); igvn.optimize(); @@ -2823,6 +2842,17 @@ case Op_CallLeafNoFP: { assert (n->is_Call(), ""); CallNode *call = n->as_Call(); +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC && ShenandoahBarrierSetC2::is_shenandoah_wb_pre_call(call)) { + uint cnt = ShenandoahBarrierSetC2::write_ref_field_pre_entry_Type()->domain()->cnt(); + if (call->req() > cnt) { + assert(call->req() == cnt+1, "only one extra input"); + Node* addp = call->in(cnt); + assert(!ShenandoahBarrierSetC2::has_only_shenandoah_wb_pre_uses(addp), "useless address computation?"); + call->del_req(cnt); + } + } +#endif // Count call sites where the FP mode bit would have to be flipped. // Do not count uncommon runtime calls: // uncommon_trap, _complete_monitor_locking, _complete_monitor_unlocking, @@ -3387,6 +3417,28 @@ } break; } +#if INCLUDE_SHENANDOAHGC + case Op_ShenandoahCompareAndSwapP: + case Op_ShenandoahCompareAndSwapN: + case Op_ShenandoahWeakCompareAndSwapN: + case Op_ShenandoahWeakCompareAndSwapP: + case Op_ShenandoahCompareAndExchangeP: + case Op_ShenandoahCompareAndExchangeN: +#ifdef ASSERT + if( VerifyOptoOopOffsets ) { + MemNode* mem = n->as_Mem(); + // Check to see if address types have grounded out somehow. + const TypeInstPtr *tp = mem->in(MemNode::Address)->bottom_type()->isa_instptr(); + ciInstanceKlass *k = tp->klass()->as_instance_klass(); + bool oop_offset_is_sane = k->contains_field_offset(tp->offset()); + assert( !tp || oop_offset_is_sane, "" ); + } +#endif + break; + case Op_ShenandoahLoadReferenceBarrier: + assert(false, "should have been expanded already"); + break; +#endif case Op_RangeCheck: { RangeCheckNode* rc = n->as_RangeCheck(); Node* iff = new IfNode(rc->in(0), rc->in(1), rc->_prob, rc->_fcnt); @@ -3823,10 +3875,18 @@ // Currently supported: // - G1 pre-barriers (see GraphKit::g1_write_barrier_pre()) void Compile::verify_barriers() { -#if INCLUDE_G1GC - if (UseG1GC) { +#if INCLUDE_G1GC || INCLUDE_SHENANDOAHGC + if (UseG1GC || UseShenandoahGC) { // Verify G1 pre-barriers + +#if INCLUDE_G1GC && INCLUDE_SHENANDOAHGC + const int marking_offset = in_bytes(UseG1GC ? G1ThreadLocalData::satb_mark_queue_active_offset() + : ShenandoahThreadLocalData::satb_mark_queue_active_offset()); +#elif INCLUDE_G1GC const int marking_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()); +#else + const int marking_offset = in_bytes(ShenandoahThreadLocalData::satb_mark_queue_active_offset()); +#endif ResourceArea *area = Thread::current()->resource_area(); Unique_Node_List visited(area); --- old/src/hotspot/share/opto/compile.hpp 2020-01-17 17:14:31.909116053 +0100 +++ new/src/hotspot/share/opto/compile.hpp 2020-01-17 17:14:31.810116058 +0100 @@ -90,6 +90,16 @@ class Node_Stack; struct Final_Reshape_Counts; +enum LoopOptsMode { + LoopOptsDefault = 0, + LoopOptsNone = 1, + LoopOptsSkipSplitIf = 2, + LoopOptsShenandoahExpand = 3, + LoopOptsShenandoahPostExpand = 4, + LoopOptsVerify = 5, + LoopOptsZgcLastRound = 6 +}; + typedef unsigned int node_idx_t; class NodeCloneInfo { private: @@ -1084,6 +1094,7 @@ void inline_incrementally(PhaseIterGVN& igvn); void inline_string_calls(bool parse_time); void inline_boxing_calls(PhaseIterGVN& igvn); + bool optimize_loops(int& loop_opts_cnt, PhaseIterGVN& igvn, LoopOptsMode mode); // Matching, CFG layout, allocation, code generation PhaseCFG* cfg() { return _cfg; } --- old/src/hotspot/share/opto/escape.cpp 2020-01-17 17:14:32.509116020 +0100 +++ new/src/hotspot/share/opto/escape.cpp 2020-01-17 17:14:32.409116025 +0100 @@ -45,6 +45,9 @@ #if INCLUDE_ZGC #include "gc/z/c2/zBarrierSetC2.hpp" #endif +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" +#endif ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) : _nodes(C->comp_arena(), C->unique(), C->unique(), NULL), @@ -512,6 +515,10 @@ } case Op_CompareAndExchangeP: case Op_CompareAndExchangeN: +#if INCLUDE_SHENANDOAHGC + case Op_ShenandoahCompareAndExchangeP: + case Op_ShenandoahCompareAndExchangeN: +#endif case Op_GetAndSetP: case Op_GetAndSetN: { add_objload_to_connection_graph(n, delayed_worklist); @@ -521,6 +528,12 @@ case Op_StoreN: case Op_StoreNKlass: case Op_StorePConditional: +#if INCLUDE_SHENANDOAHGC + case Op_ShenandoahWeakCompareAndSwapP: + case Op_ShenandoahWeakCompareAndSwapN: + case Op_ShenandoahCompareAndSwapP: + case Op_ShenandoahCompareAndSwapN: +#endif case Op_WeakCompareAndSwapP: case Op_WeakCompareAndSwapN: case Op_CompareAndSwapP: @@ -554,8 +567,8 @@ // Pointer stores in G1 barriers looks like unsafe access. // Ignore such stores to be able scalar replace non-escaping // allocations. -#if INCLUDE_G1GC - if (UseG1GC && adr->is_AddP()) { +#if INCLUDE_G1GC || INCLUDE_SHENANDOAHGC + if ((UseG1GC || UseShenandoahGC) && adr->is_AddP()) { Node* base = get_addp_base(adr); if (base->Opcode() == Op_LoadP && base->in(MemNode::Address)->is_AddP()) { @@ -563,7 +576,15 @@ Node* tls = get_addp_base(adr); if (tls->Opcode() == Op_ThreadLocal) { int offs = (int)igvn->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot); - if (offs == in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset())) { +#if INCLUDE_G1GC && INCLUDE_SHENANDOAHGC + const int buf_offset = in_bytes(UseG1GC ? G1ThreadLocalData::satb_mark_queue_buffer_offset() + : ShenandoahThreadLocalData::satb_mark_queue_buffer_offset()); +#elif INCLUDE_G1GC + const int buf_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()); +#else + const int buf_offset = in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset()); +#endif + if (offs == buf_offset) { break; // G1 pre barrier previous oop value store. } if (offs == in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset())) { @@ -600,6 +621,13 @@ add_java_object(n, PointsToNode::ArgEscape); break; } +#if INCLUDE_SHENANDOAHGC + case Op_ShenandoahEnqueueBarrier: + add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(1), delayed_worklist); + break; + case Op_ShenandoahLoadReferenceBarrier: + add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(ShenandoahLoadReferenceBarrierNode::ValueIn), delayed_worklist); +#endif default: ; // Do nothing for nodes not related to EA. } @@ -740,6 +768,14 @@ case Op_CompareAndSwapN: case Op_WeakCompareAndSwapP: case Op_WeakCompareAndSwapN: +#if INCLUDE_SHENANDOAHGC + case Op_ShenandoahCompareAndExchangeP: + case Op_ShenandoahCompareAndExchangeN: + case Op_ShenandoahCompareAndSwapP: + case Op_ShenandoahCompareAndSwapN: + case Op_ShenandoahWeakCompareAndSwapP: + case Op_ShenandoahWeakCompareAndSwapN: +#endif case Op_GetAndSetP: case Op_GetAndSetN: { Node* adr = n->in(MemNode::Address); @@ -753,6 +789,9 @@ } #endif if (opcode == Op_GetAndSetP || opcode == Op_GetAndSetN || +#if INCLUDE_SHENANDOAHGC + opcode == Op_ShenandoahCompareAndExchangeN || opcode == Op_ShenandoahCompareAndExchangeP || +#endif opcode == Op_CompareAndExchangeN || opcode == Op_CompareAndExchangeP) { add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL); } @@ -815,6 +854,14 @@ } break; } +#if INCLUDE_SHENANDOAHGC + case Op_ShenandoahEnqueueBarrier: + add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(1), NULL); + break; + case Op_ShenandoahLoadReferenceBarrier: + add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(ShenandoahLoadReferenceBarrierNode::ValueIn), NULL); + break; +#endif default: { // This method should be called only for EA specific nodes which may // miss some edges when they were created. @@ -2113,6 +2160,10 @@ // Check for unsafe oop field access if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN) || n->has_out_with(Op_GetAndSetP, Op_GetAndSetN, Op_CompareAndExchangeP, Op_CompareAndExchangeN) || +#if INCLUDE_SHENANDOAHGC + n->has_out_with(Op_ShenandoahCompareAndExchangeP) || n->has_out_with(Op_ShenandoahCompareAndExchangeN) || + n->has_out_with(Op_ShenandoahCompareAndSwapP, Op_ShenandoahCompareAndSwapN, Op_ShenandoahWeakCompareAndSwapP, Op_ShenandoahWeakCompareAndSwapN) || +#endif n->has_out_with(Op_CompareAndSwapP, Op_CompareAndSwapN, Op_WeakCompareAndSwapP, Op_WeakCompareAndSwapN)) { bt = T_OBJECT; (*unsafe) = true; @@ -2378,7 +2429,8 @@ assert(opcode == Op_ConP || opcode == Op_ThreadLocal || opcode == Op_CastX2P || uncast_base->is_DecodeNarrowPtr() || (uncast_base->is_Mem() && (uncast_base->bottom_type()->isa_rawptr() != NULL)) || - (uncast_base->is_Proj() && uncast_base->in(0)->is_Allocate()), "sanity"); + (uncast_base->is_Proj() && uncast_base->in(0)->is_Allocate()) || + uncast_base->Opcode() == Op_ShenandoahLoadReferenceBarrier, "sanity"); } } return base; --- old/src/hotspot/share/opto/graphKit.cpp 2020-01-17 17:14:33.129115986 +0100 +++ new/src/hotspot/share/opto/graphKit.cpp 2020-01-17 17:14:33.029115991 +0100 @@ -43,6 +43,10 @@ #include "opto/runtime.hpp" #include "runtime/deoptimization.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/macros.hpp" +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" +#endif //----------------------------GraphKit----------------------------------------- // Main utility constructor. @@ -3738,6 +3742,14 @@ if (ptr == NULL) { // reduce dumb test in callers return NULL; } + +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC) { + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + ptr = bs->step_over_gc_barrier(ptr); + } +#endif + if (ptr->is_CheckCastPP()) { // strip only one raw-to-oop cast ptr = ptr->in(1); if (ptr == NULL) return NULL; --- old/src/hotspot/share/opto/loopTransform.cpp 2020-01-17 17:14:33.758115951 +0100 +++ new/src/hotspot/share/opto/loopTransform.cpp 2020-01-17 17:14:33.658115956 +0100 @@ -2852,6 +2852,14 @@ ((bol->in(1)->Opcode() == Op_StorePConditional ) || (bol->in(1)->Opcode() == Op_StoreIConditional ) || (bol->in(1)->Opcode() == Op_StoreLConditional ) || +#if INCLUDE_SHENANDOAHGC + (bol->in(1)->Opcode() == Op_ShenandoahCompareAndExchangeP ) || + (bol->in(1)->Opcode() == Op_ShenandoahCompareAndExchangeN ) || + (bol->in(1)->Opcode() == Op_ShenandoahWeakCompareAndSwapP ) || + (bol->in(1)->Opcode() == Op_ShenandoahWeakCompareAndSwapN ) || + (bol->in(1)->Opcode() == Op_ShenandoahCompareAndSwapP ) || + (bol->in(1)->Opcode() == Op_ShenandoahCompareAndSwapN ) || +#endif (bol->in(1)->Opcode() == Op_CompareAndExchangeB ) || (bol->in(1)->Opcode() == Op_CompareAndExchangeS ) || (bol->in(1)->Opcode() == Op_CompareAndExchangeI ) || --- old/src/hotspot/share/opto/loopnode.cpp 2020-01-17 17:14:34.375115917 +0100 +++ new/src/hotspot/share/opto/loopnode.cpp 2020-01-17 17:14:34.280115922 +0100 @@ -40,6 +40,10 @@ #include "opto/mulnode.hpp" #include "opto/rootnode.hpp" #include "opto/superword.hpp" +#include "utilities/macros.hpp" +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" +#endif //============================================================================= //------------------------------is_loop_iv------------------------------------- @@ -2713,7 +2717,12 @@ //----------------------------build_and_optimize------------------------------- // Create a PhaseLoop. Build the ideal Loop tree. Map each Ideal Node to // its corresponding LoopNode. If 'optimize' is true, do some loop cleanups. -void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts, bool last_round) { +void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { + bool do_split_ifs = (mode == LoopOptsDefault || mode == LoopOptsZgcLastRound); + bool skip_loop_opts = (mode == LoopOptsNone) ; + bool shenandoah_opts = (mode == LoopOptsShenandoahExpand || + mode == LoopOptsShenandoahPostExpand); + ResourceMark rm; int old_progress = C->major_progress(); @@ -2777,7 +2786,7 @@ } // Nothing to do, so get out - bool stop_early = !C->has_loops() && !skip_loop_opts && !do_split_ifs && !_verify_me && !_verify_only; + bool stop_early = !C->has_loops() && !skip_loop_opts && !do_split_ifs && !_verify_me && !_verify_only && !shenandoah_opts; bool do_expensive_nodes = C->should_optimize_expensive_nodes(_igvn); if (stop_early && !do_expensive_nodes) { _igvn.optimize(); // Cleanup NeverBranches @@ -2856,8 +2865,9 @@ // Given early legal placement, try finding counted loops. This placement // is good enough to discover most loop invariants. - if( !_verify_me && !_verify_only ) - _ltree_root->counted_loop( this ); + if (!_verify_me && !_verify_only && !shenandoah_opts) { + _ltree_root->counted_loop(this); + } // Find latest loop placement. Find ideal loop placement. visited.Clear(); @@ -2928,6 +2938,16 @@ return; } +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC && ((ShenandoahBarrierSetC2*) BarrierSet::barrier_set()->barrier_set_c2())->optimize_loops(this, mode, visited, nstack, worklist)) { + _igvn.optimize(); + if (C->log() != NULL) { + log_loop_tree(_ltree_root, _ltree_root, C->log()); + } + return; + } +#endif + if (ReassociateInvariants) { // Reassociate invariants and prep for split_thru_phi for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) { @@ -2955,9 +2975,9 @@ // that require basic-block info (like cloning through Phi's) if( SplitIfBlocks && do_split_ifs ) { visited.Clear(); - split_if_with_blocks( visited, nstack, last_round ); + split_if_with_blocks( visited, nstack, mode == LoopOptsZgcLastRound ); NOT_PRODUCT( if( VerifyLoopOptimizations ) verify(); ); - if (last_round) { + if (mode == LoopOptsZgcLastRound) { C->set_major_progress(); } } @@ -3958,7 +3978,8 @@ } while(worklist.size() != 0 && LCA != early) { Node* s = worklist.pop(); - if (s->is_Load() || s->Opcode() == Op_SafePoint) { + if (s->is_Load() || s->is_ShenandoahBarrier() || s->Opcode() == Op_SafePoint || + (UseShenandoahGC && s->is_CallStaticJava() && s->as_CallStaticJava()->uncommon_trap_request() != 0)) { continue; } else if (s->is_MergeMem()) { for (DUIterator_Fast imax, i = s->fast_outs(imax); i < imax; i++) { @@ -4146,7 +4167,9 @@ } IdealLoopTree* loop = get_loop(least); Node* head = loop->_head; - if (head->is_OuterStripMinedLoop()) { + if (head->is_OuterStripMinedLoop() && + // Verification can't be applied to fully built strip mined loops + head->as_Loop()->outer_loop_end()->in(1)->find_int_con(-1) == 0) { Node* sfpt = head->as_Loop()->outer_safepoint(); ResourceMark rm; Unique_Node_List wq; @@ -4226,6 +4249,9 @@ case Op_HasNegatives: pinned = false; } + if (UseShenandoahGC && n->is_CMove()) { + pinned = false; + } if( pinned ) { IdealLoopTree *chosen_loop = get_loop(n->is_CFG() ? n : get_ctrl(n)); if( !chosen_loop->_child ) // Inner loop? @@ -4490,6 +4516,7 @@ } } } +#endif // Collect a R-P-O for the whole CFG. // Result list is in post-order (scan backwards for RPO) @@ -4512,7 +4539,6 @@ } } } -#endif //============================================================================= --- old/src/hotspot/share/opto/loopnode.hpp 2020-01-17 17:14:35.013115882 +0100 +++ new/src/hotspot/share/opto/loopnode.hpp 2020-01-17 17:14:34.913115887 +0100 @@ -925,11 +925,11 @@ _dom_lca_tags(arena()), // Thread::resource_area _verify_me(NULL), _verify_only(true) { - build_and_optimize(false, false); + build_and_optimize(LoopOptsVerify); } // build the loop tree and perform any requested optimizations - void build_and_optimize(bool do_split_if, bool skip_loop_opts, bool last_round = false); + void build_and_optimize(LoopOptsMode mode); // Dominators for the sea of nodes void Dominators(); @@ -939,13 +939,13 @@ Node *dom_lca_internal( Node *n1, Node *n2 ) const; // Compute the Ideal Node to Loop mapping - PhaseIdealLoop( PhaseIterGVN &igvn, bool do_split_ifs, bool skip_loop_opts = false, bool last_round = false) : + PhaseIdealLoop( PhaseIterGVN &igvn, LoopOptsMode mode) : PhaseTransform(Ideal_Loop), _igvn(igvn), _dom_lca_tags(arena()), // Thread::resource_area _verify_me(NULL), _verify_only(false) { - build_and_optimize(do_split_ifs, skip_loop_opts, last_round); + build_and_optimize(mode); } // Verify that verify_me made the same decisions as a fresh run. @@ -955,7 +955,7 @@ _dom_lca_tags(arena()), // Thread::resource_area _verify_me(verify_me), _verify_only(false) { - build_and_optimize(false, false); + build_and_optimize(LoopOptsVerify); } // Build and verify the loop tree without modifying the graph. This @@ -1291,8 +1291,10 @@ Node *place_near_use( Node *useblock ) const; Node* try_move_store_before_loop(Node* n, Node *n_ctrl); void try_move_store_after_loop(Node* n); +public: bool identical_backtoback_ifs(Node *n); bool can_split_if(Node *n_ctrl); +private: bool _created_loop_node; public: @@ -1307,7 +1309,6 @@ #ifndef PRODUCT void dump( ) const; void dump( IdealLoopTree *loop, uint rpo_idx, Node_List &rpo_list ) const; - void rpo( Node *start, Node_Stack &stk, VectorSet &visited, Node_List &rpo_list ) const; void verify() const; // Major slow :-) void verify_compare( Node *n, const PhaseIdealLoop *loop_verify, VectorSet &visited ) const; IdealLoopTree *get_loop_idx(Node* n) const { @@ -1319,6 +1320,9 @@ static int _loop_invokes; // Count of PhaseIdealLoop invokes static int _loop_work; // Sum of PhaseIdealLoop x _unique #endif + void rpo( Node *start, Node_Stack &stk, VectorSet &visited, Node_List &rpo_list ) const; + + PhaseIterGVN& igvn() { return _igvn; } }; // This kit may be used for making of a reserved copy of a loop before this loop --- old/src/hotspot/share/opto/macro.cpp 2020-01-17 17:14:35.607115849 +0100 +++ new/src/hotspot/share/opto/macro.cpp 2020-01-17 17:14:35.508115854 +0100 @@ -47,9 +47,13 @@ #include "opto/subnode.hpp" #include "opto/type.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/macros.hpp" #if INCLUDE_G1GC #include "gc/g1/g1ThreadLocalData.hpp" #endif // INCLUDE_G1GC +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" +#endif // @@ -458,7 +462,14 @@ if (val == mem) { values.at_put(j, mem); } else if (val->is_Store()) { - values.at_put(j, val->in(MemNode::ValueIn)); + Node* n = val->in(MemNode::ValueIn); +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC) { + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + n = bs->step_over_gc_barrier(n); + } +#endif + values.at_put(j, n); } else if(val->is_Proj() && val->in(0) == alloc) { values.at_put(j, _igvn.zerocon(ft)); } else if (val->is_Phi()) { @@ -569,7 +580,14 @@ // hit a sentinel, return appropriate 0 value return _igvn.zerocon(ft); } else if (mem->is_Store()) { - return mem->in(MemNode::ValueIn); + Node* n = mem->in(MemNode::ValueIn); +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC) { + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + n = bs->step_over_gc_barrier(n); + } +#endif + return n; } else if (mem->is_Phi()) { // attempt to produce a Phi reflecting the values on the input paths of the Phi Node_Stack value_phis(a, 8); @@ -646,6 +664,7 @@ k < kmax && can_eliminate; k++) { Node* n = use->fast_out(k); if (!n->is_Store() && n->Opcode() != Op_CastP2X && + SHENANDOAHGC_ONLY((!UseShenandoahGC || !ShenandoahBarrierSetC2::is_shenandoah_wb_pre_call(n)) &&) !(n->is_ArrayCopy() && n->as_ArrayCopy()->is_clonebasic() && n->in(ArrayCopyNode::Dest) == use)) { --- old/src/hotspot/share/opto/macroArrayCopy.cpp 2020-01-17 17:14:36.217115815 +0100 +++ new/src/hotspot/share/opto/macroArrayCopy.cpp 2020-01-17 17:14:36.117115821 +0100 @@ -31,6 +31,10 @@ #include "opto/macro.hpp" #include "opto/runtime.hpp" #include "utilities/align.hpp" +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" +#include "gc/shenandoah/shenandoahRuntime.hpp" +#endif void PhaseMacroExpand::insert_mem_bar(Node** ctrl, Node** mem, int opcode, Node* precedent) { @@ -552,7 +556,7 @@ // At this point we know we do not need type checks on oop stores. BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - if (alloc != NULL && !bs->array_copy_requires_gc_barriers(copy_type)) { + if (alloc != NULL && !bs->array_copy_requires_gc_barriers(copy_type) && !UseShenandoahGC) { // If we do not need gc barriers, copy using the jint or jlong stub. copy_type = LP64_ONLY(UseCompressedOops ? T_INT : T_LONG) NOT_LP64(T_INT); assert(type2aelembytes(basic_elem_type) == type2aelembytes(copy_type), --- old/src/hotspot/share/opto/matcher.cpp 2020-01-17 17:14:36.808115783 +0100 +++ new/src/hotspot/share/opto/matcher.cpp 2020-01-17 17:14:36.706115788 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -2254,6 +2254,14 @@ case Op_StorePConditional: case Op_StoreIConditional: case Op_StoreLConditional: +#if INCLUDE_SHENANDOAHGC + case Op_ShenandoahCompareAndExchangeP: + case Op_ShenandoahCompareAndExchangeN: + case Op_ShenandoahWeakCompareAndSwapP: + case Op_ShenandoahWeakCompareAndSwapN: + case Op_ShenandoahCompareAndSwapP: + case Op_ShenandoahCompareAndSwapN: +#endif case Op_CompareAndExchangeB: case Op_CompareAndExchangeS: case Op_CompareAndExchangeI: @@ -2497,6 +2505,14 @@ // that a monitor exit operation contains a serializing instruction. if (xop == Op_MemBarVolatile || +#if INCLUDE_SHENANDOAHGC + xop == Op_ShenandoahCompareAndExchangeP || + xop == Op_ShenandoahCompareAndExchangeN || + xop == Op_ShenandoahWeakCompareAndSwapP || + xop == Op_ShenandoahWeakCompareAndSwapN || + xop == Op_ShenandoahCompareAndSwapN || + xop == Op_ShenandoahCompareAndSwapP || +#endif xop == Op_CompareAndExchangeB || xop == Op_CompareAndExchangeS || xop == Op_CompareAndExchangeI || --- old/src/hotspot/share/opto/memnode.cpp 2020-01-17 17:14:37.423115749 +0100 +++ new/src/hotspot/share/opto/memnode.cpp 2020-01-17 17:14:37.322115755 +0100 @@ -52,6 +52,9 @@ #if INCLUDE_ZGC #include "gc/z/c2/zBarrierSetC2.hpp" #endif +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" +#endif // Portions of code courtesy of Clifford Click @@ -1112,6 +1115,11 @@ (tp != NULL) && tp->is_ptr_to_boxed_value()) { intptr_t ignore = 0; Node* base = AddPNode::Ideal_base_and_offset(ld_adr, phase, ignore); +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC) { + base = ((ShenandoahBarrierSetC2*) BarrierSet::barrier_set()->barrier_set_c2())->step_over_gc_barrier(base); + } +#endif if (base != NULL && base->is_Proj() && base->as_Proj()->_con == TypeFunc::Parms && base->in(0)->is_CallStaticJava() && --- old/src/hotspot/share/opto/mulnode.cpp 2020-01-17 17:14:38.056115714 +0100 +++ new/src/hotspot/share/opto/mulnode.cpp 2020-01-17 17:14:37.957115720 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,10 @@ #include "opto/mulnode.hpp" #include "opto/phaseX.hpp" #include "opto/subnode.hpp" +#include "utilities/macros.hpp" +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" +#endif // Portions of code courtesy of Clifford Click @@ -474,6 +478,15 @@ Node *load = in(1); uint lop = load->Opcode(); +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC && ShenandoahBarrierC2Support::is_gc_state_load(load)) { + // Do not touch the load+mask, we would match the whole sequence exactly. + // Converting the load to LoadUB/LoadUS would mismatch and waste a register + // on the barrier fastpath. + return NULL; + } +#endif + // Masking bits off of a Character? Hi bits are already zero. if( lop == Op_LoadUS && (mask & 0xFFFF0000) ) // Can we make a smaller mask? --- old/src/hotspot/share/opto/node.hpp 2020-01-17 17:14:38.650115681 +0100 +++ new/src/hotspot/share/opto/node.hpp 2020-01-17 17:14:38.552115687 +0100 @@ -143,6 +143,7 @@ class RootNode; class SafePointNode; class SafePointScalarObjectNode; +class ShenandoahBarrierNode; class StartNode; class State; class StoreNode; @@ -678,6 +679,7 @@ DEFINE_CLASS_ID(EncodeNarrowPtr, Type, 6) DEFINE_CLASS_ID(EncodeP, EncodeNarrowPtr, 0) DEFINE_CLASS_ID(EncodePKlass, EncodeNarrowPtr, 1) + DEFINE_CLASS_ID(ShenandoahBarrier, Type, 7) DEFINE_CLASS_ID(Proj, Node, 3) DEFINE_CLASS_ID(CatchProj, Proj, 0) @@ -877,6 +879,7 @@ DEFINE_CLASS_QUERY(Root) DEFINE_CLASS_QUERY(SafePoint) DEFINE_CLASS_QUERY(SafePointScalarObject) + DEFINE_CLASS_QUERY(ShenandoahBarrier) DEFINE_CLASS_QUERY(Start) DEFINE_CLASS_QUERY(Store) DEFINE_CLASS_QUERY(Sub) --- old/src/hotspot/share/opto/phaseX.cpp 2020-01-17 17:14:39.249115648 +0100 +++ new/src/hotspot/share/opto/phaseX.cpp 2020-01-17 17:14:39.145115654 +0100 @@ -2106,6 +2106,10 @@ default: break; } + if (UseShenandoahGC) { + // TODO: Should we call this for ZGC as well? + BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(igvn->_worklist, old); + } } } --- old/src/hotspot/share/opto/phasetype.hpp 2020-01-17 17:14:39.861115615 +0100 +++ new/src/hotspot/share/opto/phasetype.hpp 2020-01-17 17:14:39.762115620 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018, 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 @@ -52,6 +52,7 @@ PHASE_MATCHING, PHASE_INCREMENTAL_INLINE, PHASE_INCREMENTAL_BOXING_INLINE, + PHASE_BEFORE_BARRIER_EXPAND, PHASE_BEFORE_MACRO_EXPANSION, PHASE_END, PHASE_FAILURE, @@ -89,6 +90,7 @@ case PHASE_MATCHING: return "After matching"; case PHASE_INCREMENTAL_INLINE: return "Incremental Inline"; case PHASE_INCREMENTAL_BOXING_INLINE: return "Incremental Boxing Inline"; + case PHASE_BEFORE_BARRIER_EXPAND: return "Before Barrier Expand"; case PHASE_BEFORE_MACRO_EXPANSION: return "Before macro expansion"; case PHASE_END: return "End"; case PHASE_FAILURE: return "Failure"; --- old/src/hotspot/share/opto/type.hpp 2020-01-17 17:14:40.437115583 +0100 +++ new/src/hotspot/share/opto/type.hpp 2020-01-17 17:14:40.338115588 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -1770,6 +1770,8 @@ // UseOptoBiasInlining #define XorXNode XorLNode #define StoreXConditionalNode StoreLConditionalNode +#define LoadXNode LoadLNode +#define StoreXNode StoreLNode // Opcodes #define Op_LShiftX Op_LShiftL #define Op_AndX Op_AndL @@ -1815,6 +1817,8 @@ // UseOptoBiasInlining #define XorXNode XorINode #define StoreXConditionalNode StoreIConditionalNode +#define LoadXNode LoadINode +#define StoreXNode StoreINode // Opcodes #define Op_LShiftX Op_LShiftI #define Op_AndX Op_AndI --- old/src/hotspot/share/runtime/mutexLocker.cpp 2020-01-17 17:14:41.038115550 +0100 +++ new/src/hotspot/share/runtime/mutexLocker.cpp 2020-01-17 17:14:40.938115555 +0100 @@ -216,6 +216,14 @@ def(MarkStackFreeList_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_never); def(MarkStackChunkList_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_never); } + if (UseShenandoahGC) { + def(SATB_Q_FL_lock , PaddedMutex , access, true, Monitor::_safepoint_check_never); + def(SATB_Q_CBL_mon , PaddedMonitor, access, true, Monitor::_safepoint_check_never); + def(Shared_SATB_Q_lock , PaddedMutex , access + 1, true, Monitor::_safepoint_check_never); + + def(StringDedupQueue_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never); + def(StringDedupTable_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never); + } def(ParGCRareEvent_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_sometimes); def(DerivedPointerTableGC_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never); def(CGCPhaseManager_lock , PaddedMonitor, leaf, false, Monitor::_safepoint_check_sometimes); --- old/src/hotspot/share/runtime/sharedRuntime.cpp 2020-01-17 17:14:41.623115518 +0100 +++ new/src/hotspot/share/runtime/sharedRuntime.cpp 2020-01-17 17:14:41.522115523 +0100 @@ -2880,6 +2880,24 @@ GCLocker::unlock_critical(thread); JRT_END +JRT_LEAF(oopDesc*, SharedRuntime::pin_object(JavaThread* thread, oopDesc* obj)) + assert(Universe::heap()->supports_object_pinning(), "Why we here?"); + assert(UseShenandoahGC, "only supported in Shenandoah for now"); + assert(obj != NULL, "Should not be null"); + oop o(obj); + o = Universe::heap()->pin_object(thread, o); + assert(o != NULL, "Should not be null"); + return o; +JRT_END + +JRT_LEAF(void, SharedRuntime::unpin_object(JavaThread* thread, oopDesc* obj)) + assert(Universe::heap()->supports_object_pinning(), "Why we here?"); + assert(UseShenandoahGC, "only supported in Shenandoah for now"); + assert(obj != NULL, "Should not be null"); + oop o(obj); + Universe::heap()->unpin_object(thread, o); +JRT_END + // ------------------------------------------------------------------------- // Java-Java calling convention // (what you use when Java calls Java) --- old/src/hotspot/share/runtime/sharedRuntime.hpp 2020-01-17 17:14:42.235115484 +0100 +++ new/src/hotspot/share/runtime/sharedRuntime.hpp 2020-01-17 17:14:42.137115489 +0100 @@ -487,6 +487,10 @@ // Block before entering a JNI critical method static void block_for_jni_critical(JavaThread* thread); + // Pin/Unpin object + static oopDesc* pin_object(JavaThread* thread, oopDesc* obj); + static void unpin_object(JavaThread* thread, oopDesc* obj); + // A compiled caller has just called the interpreter, but compiled code // exists. Patch the caller so he no longer calls into the interpreter. static void fixup_callers_callsite(Method* moop, address ret_pc); --- old/src/hotspot/share/runtime/stackValue.cpp 2020-01-17 17:14:42.822115451 +0100 +++ new/src/hotspot/share/runtime/stackValue.cpp 2020-01-17 17:14:42.722115457 +0100 @@ -32,6 +32,9 @@ #if INCLUDE_ZGC #include "gc/z/zBarrier.inline.hpp" #endif +#if INCLUDE_SHENANDOAHGC +#include "gc/shenandoah/shenandoahBarrierSet.hpp" +#endif StackValue* StackValue::create_stack_value(const frame* fr, const RegisterMap* reg_map, ScopeValue* sv) { if (sv->is_location()) { @@ -106,8 +109,15 @@ } else { value.noop = *(narrowOop*) value_addr; } - // Decode narrowoop and wrap a handle around the oop - Handle h(Thread::current(), CompressedOops::decode(value.noop)); + // Decode narrowoop + oop val = CompressedOops::decode(value.noop); + // Deoptimization must make sure all oops have passed load barriers +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC) { + val = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(val); + } +#endif + Handle h(Thread::current(), val); // Wrap a handle around the oop return new StackValue(h); } #endif @@ -122,13 +132,17 @@ val = (oop)NULL; } #endif + // Deoptimization must make sure all oops have passed load barriers #if INCLUDE_ZGC - // Deoptimization must make sure all oop have passed load barrier if (UseZGC) { val = ZBarrier::load_barrier_on_oop_field_preloaded((oop*)value_addr, val); } #endif - +#if INCLUDE_SHENANDOAHGC + if (UseShenandoahGC) { + val = ShenandoahBarrierSet::barrier_set()->load_reference_barrier(val); + } +#endif Handle h(Thread::current(), val); // Wrap a handle around the oop return new StackValue(h); } --- old/src/hotspot/share/runtime/vmOperations.hpp 2020-01-17 17:14:43.398115420 +0100 +++ new/src/hotspot/share/runtime/vmOperations.hpp 2020-01-17 17:14:43.299115425 +0100 @@ -99,6 +99,15 @@ template(HeapIterateOperation) \ template(ReportJavaOutOfMemory) \ template(JFRCheckpoint) \ + template(ShenandoahFullGC) \ + template(ShenandoahInitMark) \ + template(ShenandoahFinalMarkStartEvac) \ + template(ShenandoahFinalEvac) \ + template(ShenandoahInitTraversalGC) \ + template(ShenandoahFinalTraversalGC) \ + template(ShenandoahInitUpdateRefs) \ + template(ShenandoahFinalUpdateRefs) \ + template(ShenandoahDegeneratedGC) \ template(Exit) \ template(LinuxDllLoad) \ template(RotateGCLog) \ --- old/src/hotspot/share/utilities/globalDefinitions.hpp 2020-01-17 17:14:43.982115388 +0100 +++ new/src/hotspot/share/utilities/globalDefinitions.hpp 2020-01-17 17:14:43.882115393 +0100 @@ -69,6 +69,7 @@ #define UINT64_FORMAT_X "%" PRIx64 #define INT64_FORMAT_W(width) "%" #width PRId64 #define UINT64_FORMAT_W(width) "%" #width PRIu64 +#define UINT64_FORMAT_X_W(width) "%" #width PRIx64 #define PTR64_FORMAT "0x%016" PRIx64 --- old/src/hotspot/share/utilities/macros.hpp 2020-01-17 17:14:44.575115355 +0100 +++ new/src/hotspot/share/utilities/macros.hpp 2020-01-17 17:14:44.475115360 +0100 @@ -221,6 +221,24 @@ #define NOT_SERIALGC_RETURN_(code) { return code; } #endif // INCLUDE_SERIALGC +#ifndef INCLUDE_SHENANDOAHGC +#define INCLUDE_SHENANDOAHGC 1 +#endif // INCLUDE_SHENANDOAHGC + +#if INCLUDE_SHENANDOAHGC +#define SHENANDOAHGC_ONLY(x) x +#define SHENANDOAHGC_ONLY_ARG(arg) arg, +#define NOT_SHENANDOAHGC(x) +#define NOT_SHENANDOAHGC_RETURN /* next token must be ; */ +#define NOT_SHENANDOAHGC_RETURN_(code) /* next token must be ; */ +#else +#define SHENANDOAHGC_ONLY(x) +#define SHENANDOAHGC_ONLY_ARG(arg) +#define NOT_SHENANDOAHGC(x) x +#define NOT_SHENANDOAHGC_RETURN {} +#define NOT_SHENANDOAHGC_RETURN_(code) { return code; } +#endif // INCLUDE_SHENANDOAHGC + #ifndef INCLUDE_ZGC #define INCLUDE_ZGC 1 #endif // INCLUDE_ZGC --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HSDB.java 2020-01-17 17:14:45.149115323 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HSDB.java 2020-01-17 17:14:45.048115329 +0100 @@ -36,6 +36,7 @@ import sun.jvm.hotspot.gc.epsilon.*; import sun.jvm.hotspot.gc.parallel.*; import sun.jvm.hotspot.gc.shared.*; +import sun.jvm.hotspot.gc.shenandoah.*; import sun.jvm.hotspot.gc.g1.*; import sun.jvm.hotspot.gc.z.*; import sun.jvm.hotspot.interpreter.*; @@ -1113,6 +1114,10 @@ } else if (collHeap instanceof EpsilonHeap) { anno = "Epsilon "; bad = false; + } else if (collHeap instanceof ShenandoahHeap) { + ShenandoahHeap heap = (ShenandoahHeap) collHeap; + anno = "ShenandoahHeap "; + bad = false; } else if (collHeap instanceof ZCollectedHeap) { ZCollectedHeap heap = (ZCollectedHeap) collHeap; anno = "ZHeap "; --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CollectedHeapName.java 2020-01-17 17:14:45.746115290 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CollectedHeapName.java 2020-01-17 17:14:45.648115296 +0100 @@ -37,6 +37,7 @@ public static final CollectedHeapName G1 = new CollectedHeapName("G1"); public static final CollectedHeapName EPSILON = new CollectedHeapName("Epsilon"); public static final CollectedHeapName Z = new CollectedHeapName("Z"); + public static final CollectedHeapName SHENANDOAH = new CollectedHeapName("Shenandoah"); public String toString() { return name; --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GCCause.java 2020-01-17 17:14:46.322115259 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GCCause.java 2020-01-17 17:14:46.222115264 +0100 @@ -67,6 +67,12 @@ _z_allocation_stall ("Allocation Stall"), _z_proactive ("Proactive"), + _shenandoah_allocation_failure_evac ("Allocation Failure During Evacuation"), + _shenandoah_stop_vm ("Stopping VM"), + _shenandoah_concurrent_gc ("Concurrent GC"), + _shenandoah_traversal_gc ("Traversal GC"), + _shenandoah_upgrade_to_full_gc ("Upgrade To Full GC"), + _last_gc_cause ("ILLEGAL VALUE - last gc cause - ILLEGAL VALUE"); private final String value; --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GCName.java 2020-01-17 17:14:46.904115227 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GCName.java 2020-01-17 17:14:46.801115232 +0100 @@ -38,6 +38,7 @@ G1Old ("G1Old"), G1Full ("G1Full"), Z ("Z"), + Shenandoah ("Shenandoah"), NA ("N/A"), GCNameEndSentinel ("GCNameEndSentinel"); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java 2020-01-17 17:14:47.483115195 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java 2020-01-17 17:14:47.383115200 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import sun.jvm.hotspot.gc.parallel.ParallelScavengeHeap; import sun.jvm.hotspot.gc.serial.SerialHeap; import sun.jvm.hotspot.gc.shared.CollectedHeap; +import sun.jvm.hotspot.gc.shenandoah.ShenandoahHeap; import sun.jvm.hotspot.gc.z.ZCollectedHeap; import sun.jvm.hotspot.oops.Oop; import sun.jvm.hotspot.runtime.BasicType; @@ -110,6 +111,7 @@ addHeapTypeIfInDB(db, G1CollectedHeap.class); addHeapTypeIfInDB(db, EpsilonHeap.class); addHeapTypeIfInDB(db, ZCollectedHeap.class); + addHeapTypeIfInDB(db, ShenandoahHeap.class); mainThreadGroupField = type.getOopField("_main_thread_group"); systemThreadGroupField = type.getOopField("_system_thread_group"); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java 2020-01-17 17:14:48.070115162 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java 2020-01-17 17:14:47.968115168 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import sun.jvm.hotspot.gc.shared.*; import sun.jvm.hotspot.gc.epsilon.*; import sun.jvm.hotspot.gc.g1.*; +import sun.jvm.hotspot.gc.shenandoah.*; import sun.jvm.hotspot.gc.parallel.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.runtime.*; @@ -439,6 +440,10 @@ } else if (heap instanceof G1CollectedHeap) { G1CollectedHeap g1h = (G1CollectedHeap) heap; g1h.heapRegionIterate(lrc); + } else if (heap instanceof ShenandoahHeap) { + // Operation (currently) not supported with Shenandoah GC. Print + // a warning and leave the list of live regions empty. + System.err.println("Warning: Operation not supported with Shenandoah GC"); } else if (heap instanceof EpsilonHeap) { EpsilonHeap eh = (EpsilonHeap) heap; liveRegions.add(eh.space().top()); --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VMOps.java 2020-01-17 17:14:48.650115130 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VMOps.java 2020-01-17 17:14:48.553115136 +0100 @@ -55,6 +55,7 @@ CMS_Final_Remark, G1CollectFull, ZOperation, + ShenandoahOperation, G1CollectForAllocation, G1IncCollectionPause, EnableBiasedLocking, --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java 2020-01-17 17:14:49.230115098 +0100 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java 2020-01-17 17:14:49.130115104 +0100 @@ -29,6 +29,7 @@ import sun.jvm.hotspot.gc.g1.*; import sun.jvm.hotspot.gc.parallel.*; import sun.jvm.hotspot.gc.serial.*; +import sun.jvm.hotspot.gc.shenandoah.*; import sun.jvm.hotspot.gc.shared.*; import sun.jvm.hotspot.gc.z.*; import sun.jvm.hotspot.debugger.JVMDebugger; @@ -83,7 +84,11 @@ printValMB("MetaspaceSize = ", getFlagValue("MetaspaceSize", flagMap)); printValMB("CompressedClassSpaceSize = ", getFlagValue("CompressedClassSpaceSize", flagMap)); printValMB("MaxMetaspaceSize = ", getFlagValue("MaxMetaspaceSize", flagMap)); - printValMB("G1HeapRegionSize = ", HeapRegion.grainBytes()); + if (heap instanceof ShenandoahHeap) { + printValMB("ShenandoahRegionSize = ", ShenandoahHeapRegion.regionSizeBytes()); + } else { + printValMB("G1HeapRegionSize = ", HeapRegion.grainBytes()); + } System.out.println(); System.out.println("Heap Usage:"); @@ -126,6 +131,14 @@ printValMB("used = ", oldGen.used()); printValMB("free = ", oldFree); System.out.println(alignment + (double)oldGen.used() * 100.0 / oldGen.capacity() + "% used"); + } else if (heap instanceof ShenandoahHeap) { + ShenandoahHeap sh = (ShenandoahHeap) heap; + long num_regions = sh.numOfRegions(); + System.out.println("Shenandoah Heap:"); + System.out.println(" regions = " + num_regions); + printValMB("capacity = ", num_regions * ShenandoahHeapRegion.regionSizeBytes()); + printValMB("used = ", sh.used()); + printValMB("committed = ", sh.committed()); } else if (heap instanceof EpsilonHeap) { EpsilonHeap eh = (EpsilonHeap) heap; printSpace(eh.space()); @@ -181,6 +194,14 @@ l = getFlagValue("ParallelGCThreads", flagMap); System.out.println("with " + l + " thread(s)"); return; + } + + l = getFlagValue("UseShenandoahGC", flagMap); + if (l == 1L) { + System.out.print("Shenandoah GC "); + l = getFlagValue("ParallelGCThreads", flagMap); + System.out.println("with " + l + " thread(s)"); + return; } System.out.println("Mark Sweep Compact GC"); --- old/src/jdk.jfr/share/conf/jfr/default.jfc 2020-01-17 17:14:49.811115066 +0100 +++ new/src/jdk.jfr/share/conf/jfr/default.jfc 2020-01-17 17:14:49.709115072 +0100 @@ -420,6 +420,15 @@ false + + false + everyChunk + + + + false + + true false --- old/src/jdk.jfr/share/conf/jfr/profile.jfc 2020-01-17 17:14:50.404115034 +0100 +++ new/src/jdk.jfr/share/conf/jfr/profile.jfc 2020-01-17 17:14:50.305115039 +0100 @@ -420,6 +420,15 @@ false + + false + everyChunk + + + + false + + true true --- old/test/hotspot/jtreg/TEST.ROOT 2020-01-17 17:14:50.987115002 +0100 +++ new/test/hotspot/jtreg/TEST.ROOT 2020-01-17 17:14:50.889115007 +0100 @@ -48,6 +48,7 @@ vm.gc.Serial \ vm.gc.Parallel \ vm.gc.ConcMarkSweep \ + vm.gc.Shenandoah \ vm.gc.Epsilon \ vm.gc.Z \ vm.jvmci \ --- old/test/hotspot/jtreg/TEST.groups 2020-01-17 17:14:51.564114970 +0100 +++ new/test/hotspot/jtreg/TEST.groups 2020-01-17 17:14:51.464114975 +0100 @@ -175,7 +175,8 @@ :tier1_gc_1 \ :tier1_gc_2 \ :tier1_gc_gcold \ - :tier1_gc_gcbasher + :tier1_gc_gcbasher \ + :tier1_gc_shenandoah hotspot_not_fast_gc = \ :hotspot_gc \ @@ -195,7 +196,8 @@ -gc/stress \ -gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java \ -gc/cms/TestMBeanCMS.java \ - -gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java + -gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java \ + -gc/shenandoah tier1_gc_gcold = \ gc/stress/gcold/TestGCOldWithG1.java \ @@ -208,6 +210,51 @@ gc/stress/gcbasher/TestGCBasherWithCMS.java \ gc/stress/gcbasher/TestGCBasherWithSerial.java \ gc/stress/gcbasher/TestGCBasherWithParallel.java + +tier1_gc_shenandoah = \ + gc/shenandoah/options/ \ + gc/shenandoah/compiler/ \ + gc/shenandoah/mxbeans/ \ + gc/shenandoah/TestSmallHeap.java \ + gc/shenandoah/oom/ + +tier2_gc_shenandoah = \ + runtime/MemberName/MemberNameLeak.java \ + runtime/CompressedOops/UseCompressedOops.java \ + gc/TestHumongousReferenceObject.java \ + gc/TestSystemGC.java \ + gc/arguments/TestDisableDefaultGC.java \ + gc/arguments/TestUseCompressedOopsErgo.java \ + gc/arguments/TestAlignmentToUseLargePages.java \ + gc/class_unloading/TestClassUnloadingDisabled.java \ + gc/ergonomics/TestInitialGCThreadLogging.java \ + gc/ergonomics/TestDynamicNumberOfGCThreads.java \ + gc/logging/TestGCId.java \ + gc/metaspace/TestMetaspacePerfCounters.java \ + gc/metaspace/TestMetaspacePerfCounters.java \ + gc/startup_warnings/TestShenandoah.java \ + gc/TestFullGCALot.java \ + gc/logging/TestUnifiedLoggingSwitchStress.java \ + runtime/Metaspace/DefineClass.java \ + gc/shenandoah/ \ + serviceability/sa/TestHeapDumpForInvokeDynamic.java \ + -gc/shenandoah/TestStringDedupStress.java \ + -gc/shenandoah/jni/CriticalNativeStress.java \ + -:tier1_gc_shenandoah + +tier3_gc_shenandoah = \ + gc/stress/gcold/TestGCOldWithShenandoah.java \ + gc/stress/gcbasher/TestGCBasherWithShenandoah.java \ + gc/stress/gclocker/TestGCLockerWithShenandoah.java \ + gc/stress/systemgc/TestSystemGCWithShenandoah.java \ + gc/shenandoah/TestStringDedupStress.java \ + gc/shenandoah/jni/CriticalNativeStress.java \ + -:tier2_gc_shenandoah + +hotspot_gc_shenandoah = \ + :tier1_gc_shenandoah \ + :tier2_gc_shenandoah \ + :tier3_gc_shenandoah tier1_runtime = \ runtime/ \ --- old/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatiles.java 2020-01-17 17:14:52.149114938 +0100 +++ new/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatiles.java 2020-01-17 17:14:52.048114943 +0100 @@ -39,7 +39,9 @@ * CMS, * CMSCondMark, * Serial, - * Parallel} + * Parallel, + * Shenandoah, + * ShenandoahTraversal} */ @@ -100,6 +102,18 @@ procArgs[argcount - 3] = "-XX:+UseConcMarkSweepGC"; procArgs[argcount - 2] = "-XX:+UseCondCardMark"; break; + case "Shenandoah": + argcount = 8; + procArgs = new String[argcount]; + procArgs[argcount - 2] = "-XX:+UseShenandoahGC"; + break; + case "ShenandoahTraversal": + argcount = 10; + procArgs = new String[argcount]; + procArgs[argcount - 4] = "-XX:+UseShenandoahGC"; + procArgs[argcount - 3] = "-XX:+UnlockExperimentalVMOptions"; + procArgs[argcount - 2] = "-XX:ShenandoahGCMode=traversal"; + break; default: throw new RuntimeException("unexpected test type " + testType); } @@ -355,6 +369,17 @@ "ret" }; break; + case "Shenandoah": + case "ShenandoahTraversal": + // Shenandoah generates normal object graphs for + // volatile stores + matches = new String[] { + "membar_release (elided)", + "stlrw", + "membar_volatile (elided)", + "ret" + }; + break; } } else { switch (testType) { @@ -418,6 +443,20 @@ "ret" }; break; + + case "Shenandoah": + case "ShenandoahTraversal": + // Shenandoah generates normal object graphs for + // volatile stores + matches = new String[] { + "membar_release", + "dmb ish", + "strw", + "membar_volatile", + "dmb ish", + "ret" + }; + break; } } @@ -520,6 +559,17 @@ "ret" }; break; + case "Shenandoah": + case "ShenandoahTraversal": + // For volatile CAS, Shenanodoah generates normal + // graphs with a shenandoah-specific cmpxchg + matches = new String[] { + "membar_release (elided)", + "cmpxchgw_acq_shenandoah", + "membar_acquire (elided)", + "ret" + }; + break; } } else { switch (testType) { @@ -762,6 +812,19 @@ "membar_acquire", "dmb ish", "ret" + }; + break; + case "Shenandoah": + case "ShenandoahTraversal": + // For volatile CAS, Shenanodoah generates normal + // graphs with a shenandoah-specific cmpxchg + matches = new String[] { + "membar_release", + "dmb ish", + "cmpxchgw_shenandoah", + "membar_acquire", + "dmb ish", + "ret" }; break; } --- old/test/hotspot/jtreg/gc/TestFullGCCount.java 2020-01-17 17:14:52.742114905 +0100 +++ new/test/hotspot/jtreg/gc/TestFullGCCount.java 2020-01-17 17:14:52.643114910 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, 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 @@ -25,7 +25,9 @@ * @test TestFullGCCount.java * @bug 7072527 * @summary CMS: JMM GC counters overcount in some cases - * @requires !(vm.gc.ConcMarkSweep & vm.opt.ExplicitGCInvokesConcurrent == true) + * @requires !(vm.gc == "ConcMarkSweep" & vm.opt.ExplicitGCInvokesConcurrent == true) + * @comment Shenandoah has "ExplicitGCInvokesConcurrent" on by default + * @requires !(vm.gc == "Shenandoah" & vm.opt.ExplicitGCInvokesConcurrent != false) * @modules java.management * @run main/othervm -Xlog:gc TestFullGCCount */ --- old/test/hotspot/jtreg/gc/TestHumongousReferenceObject.java 2020-01-17 17:14:53.323114873 +0100 +++ new/test/hotspot/jtreg/gc/TestHumongousReferenceObject.java 2020-01-17 17:14:53.221114878 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -35,6 +35,16 @@ * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=8M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject */ + +/* + * @test TestHumongousReferenceObjectShenandoah + * @summary Test that verifies that iteration over large, plain Java objects, that potentially cross region boundaries, with references in them works. + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @bug 8151499 8153734 + * @modules java.base/jdk.internal.vm.annotation + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xms128m -Xmx128m -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahHeapRegionSize=8M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xms128m -Xmx128m -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahHeapRegionSize=8M -XX:ContendedPaddingWidth=8192 -XX:+UnlockDiagnosticVMOptions -XX:+ShenandoahVerify TestHumongousReferenceObject + */ public class TestHumongousReferenceObject { /* --- old/test/hotspot/jtreg/gc/TestSystemGC.java 2020-01-17 17:14:53.904114841 +0100 +++ new/test/hotspot/jtreg/gc/TestSystemGC.java 2020-01-17 17:14:53.805114846 +0100 @@ -45,6 +45,14 @@ * @run main/othervm -XX:+UseConcMarkSweepGC -XX:+ExplicitGCInvokesConcurrent TestSystemGC */ +/* + * @test TestSystemGCShenandoah + * @key gc + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @summary Runs System.gc() with different flags. + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC TestSystemGC + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+ExplicitGCInvokesConcurrent TestSystemGC + */ public class TestSystemGC { public static void main(String args[]) throws Exception { System.gc(); --- old/test/hotspot/jtreg/gc/arguments/TestAlignmentToUseLargePages.java 2020-01-17 17:14:54.478114809 +0100 +++ new/test/hotspot/jtreg/gc/arguments/TestAlignmentToUseLargePages.java 2020-01-17 17:14:54.380114815 +0100 @@ -48,6 +48,16 @@ * @run main/othervm -Xms71M -Xmx91M -XX:+UseConcMarkSweepGC -XX:-UseLargePages TestAlignmentToUseLargePages */ +/** + * @test TestAlignmentToUseLargePagesShenandoah + * @key gc + * @bug 8024396 + * @comment Graal does not support Shenandoah + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @run main/othervm -Xms71M -Xmx91M -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms71M -Xmx91M -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:-UseLargePages TestAlignmentToUseLargePages + */ + public class TestAlignmentToUseLargePages { public static void main(String args[]) throws Exception { // nothing to do --- old/test/hotspot/jtreg/gc/arguments/TestDisableDefaultGC.java 2020-01-17 17:14:55.062114777 +0100 +++ new/test/hotspot/jtreg/gc/arguments/TestDisableDefaultGC.java 2020-01-17 17:14:54.960114783 +0100 @@ -44,6 +44,7 @@ "-XX:-UseG1GC", "-XX:-UseConcMarkSweepGC", "-XX:+UnlockExperimentalVMOptions", + "-XX:-UseShenandoahGC", "-XX:-UseZGC", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); --- old/test/hotspot/jtreg/gc/arguments/TestMaxMinHeapFreeRatioFlags.java 2020-01-17 17:14:55.640114745 +0100 +++ new/test/hotspot/jtreg/gc/arguments/TestMaxMinHeapFreeRatioFlags.java 2020-01-17 17:14:55.540114751 +0100 @@ -25,7 +25,7 @@ * @test TestMaxMinHeapFreeRatioFlags * @key gc * @summary Verify that heap size changes according to max and min heap free ratios. - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management --- old/test/hotspot/jtreg/gc/arguments/TestNewRatioFlag.java 2020-01-17 17:14:56.216114713 +0100 +++ new/test/hotspot/jtreg/gc/arguments/TestNewRatioFlag.java 2020-01-17 17:14:56.117114719 +0100 @@ -26,7 +26,7 @@ * @key gc * @bug 8025166 * @summary Verify that heap devided among generations according to NewRatio - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management --- old/test/hotspot/jtreg/gc/arguments/TestNewSizeFlags.java 2020-01-17 17:14:56.788114682 +0100 +++ new/test/hotspot/jtreg/gc/arguments/TestNewSizeFlags.java 2020-01-17 17:14:56.695114687 +0100 @@ -26,7 +26,7 @@ * @key gc * @bug 8025166 * @summary Verify that young gen size conforms values specified by NewSize, MaxNewSize and Xmn options - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management --- old/test/hotspot/jtreg/gc/arguments/TestShrinkHeapInSteps.java 2020-01-17 17:14:57.367114650 +0100 +++ new/test/hotspot/jtreg/gc/arguments/TestShrinkHeapInSteps.java 2020-01-17 17:14:57.267114655 +0100 @@ -25,7 +25,7 @@ * @test TestShrinkHeapInSteps * @key gc * @summary Verify that -XX:-ShrinkHeapInSteps works properly. - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management --- old/test/hotspot/jtreg/gc/arguments/TestSurvivorRatioFlag.java 2020-01-17 17:14:57.942114618 +0100 +++ new/test/hotspot/jtreg/gc/arguments/TestSurvivorRatioFlag.java 2020-01-17 17:14:57.842114624 +0100 @@ -25,7 +25,7 @@ * @test TestSurvivorRatioFlag * @key gc * @summary Verify that actual survivor ratio is equal to specified SurvivorRatio value - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management --- old/test/hotspot/jtreg/gc/arguments/TestTargetSurvivorRatioFlag.java 2020-01-17 17:14:58.523114586 +0100 +++ new/test/hotspot/jtreg/gc/arguments/TestTargetSurvivorRatioFlag.java 2020-01-17 17:14:58.423114592 +0100 @@ -27,7 +27,7 @@ * @summary Verify that option TargetSurvivorRatio affects survivor space occupancy after minor GC. * @requires (vm.opt.ExplicitGCInvokesConcurrent == null) | (vm.opt.ExplicitGCInvokesConcurrent == false) * @requires (vm.opt.UseJVMCICompiler == null) | (vm.opt.UseJVMCICompiler == false) - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management --- old/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsErgo.java 2020-01-17 17:14:59.104114554 +0100 +++ new/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsErgo.java 2020-01-17 17:14:59.003114560 +0100 @@ -54,6 +54,21 @@ * @run main/othervm TestUseCompressedOopsErgo -XX:+UseConcMarkSweepGC */ +/* + * @test TestUseCompressedOopsErgoShenandoah + * @key gc + * @bug 8010722 + * @comment Graal does not support Shenandoah + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management/sun.management + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm TestUseCompressedOopsErgo -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC + */ + public class TestUseCompressedOopsErgo { public static void main(String args[]) throws Exception { --- old/test/hotspot/jtreg/gc/arguments/TestVerifyBeforeAndAfterGCFlags.java 2020-01-17 17:14:59.678114523 +0100 +++ new/test/hotspot/jtreg/gc/arguments/TestVerifyBeforeAndAfterGCFlags.java 2020-01-17 17:14:59.581114528 +0100 @@ -28,7 +28,7 @@ * @summary Runs an simple application (GarbageProducer) with various combinations of -XX:{+|-}Verify{After|Before}GC flags and checks that output contain or doesn't contain expected patterns - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @modules java.base/jdk.internal.misc * @modules java.management * @library /test/lib --- old/test/hotspot/jtreg/gc/class_unloading/TestClassUnloadingDisabled.java 2020-01-17 17:15:00.255114491 +0100 +++ new/test/hotspot/jtreg/gc/class_unloading/TestClassUnloadingDisabled.java 2020-01-17 17:15:00.155114496 +0100 @@ -64,6 +64,24 @@ * -XX:-ClassUnloading -XX:+UseConcMarkSweepGC TestClassUnloadingDisabled */ +/* + * @test TestClassUnloadingDisabledShenandoah + * @key gc + * @bug 8114823 + * @comment Graal does not support Shenandoah + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @requires vm.opt.ExplicitGCInvokesConcurrent != true + * @requires vm.opt.ClassUnloading != true + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-ClassUnloading -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC TestClassUnloadingDisabled + */ + import java.io.File; import java.io.IOException; import java.nio.file.Files; --- old/test/hotspot/jtreg/gc/ergonomics/TestDynamicNumberOfGCThreads.java 2020-01-17 17:15:00.837114459 +0100 +++ new/test/hotspot/jtreg/gc/ergonomics/TestDynamicNumberOfGCThreads.java 2020-01-17 17:15:00.737114464 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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 @@ -29,10 +29,14 @@ * @key gc * @modules java.base/jdk.internal.misc * @library /test/lib + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestDynamicNumberOfGCThreads */ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import sun.hotspot.gc.GC; public class TestDynamicNumberOfGCThreads { public static void main(String[] args) throws Exception { @@ -42,6 +46,10 @@ testDynamicNumberOfGCThreads("UseG1GC"); testDynamicNumberOfGCThreads("UseParallelGC"); + + if (GC.Shenandoah.isSupported()) { + testDynamicNumberOfGCThreads("UseShenandoahGC"); + } } private static void verifyDynamicNumberOfGCThreads(OutputAnalyzer output) { @@ -51,7 +59,7 @@ private static void testDynamicNumberOfGCThreads(String gcFlag) throws Exception { // UseDynamicNumberOfGCThreads and TraceDynamicGCThreads enabled - String[] baseArgs = {"-XX:+" + gcFlag, "-Xmx10M", "-XX:+UseDynamicNumberOfGCThreads", "-Xlog:gc+task=trace", GCTest.class.getName()}; + String[] baseArgs = {"-XX:+UnlockExperimentalVMOptions", "-XX:+" + gcFlag, "-Xmx10M", "-XX:+UseDynamicNumberOfGCThreads", "-Xlog:gc+task=trace", GCTest.class.getName()}; // Base test with gc and +UseDynamicNumberOfGCThreads: ProcessBuilder pb_enabled = ProcessTools.createJavaProcessBuilder(baseArgs); --- old/test/hotspot/jtreg/gc/ergonomics/TestInitialGCThreadLogging.java 2020-01-17 17:15:01.418114427 +0100 +++ new/test/hotspot/jtreg/gc/ergonomics/TestInitialGCThreadLogging.java 2020-01-17 17:15:01.317114432 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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 @@ -29,10 +29,14 @@ * @key gc * @modules java.base/jdk.internal.misc * @library /test/lib + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestInitialGCThreadLogging */ import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.gc.GC; public class TestInitialGCThreadLogging { public static void main(String[] args) throws Exception { @@ -42,6 +46,10 @@ testInitialGCThreadLogging("UseG1GC", "GC Thread"); testInitialGCThreadLogging("UseParallelGC", "ParGC Thread"); + + if (GC.Shenandoah.isSupported()) { + testInitialGCThreadLogging("UseShenandoahGC", "Shenandoah GC Thread"); + } } private static void verifyDynamicNumberOfGCThreads(OutputAnalyzer output, String threadName) { @@ -51,7 +59,7 @@ private static void testInitialGCThreadLogging(String gcFlag, String threadName) throws Exception { // UseDynamicNumberOfGCThreads and TraceDynamicGCThreads enabled - String[] baseArgs = {"-XX:+" + gcFlag, "-Xmx10M", "-XX:+UseDynamicNumberOfGCThreads", "-Xlog:gc+task=trace", "-version"}; + String[] baseArgs = {"-XX:+UnlockExperimentalVMOptions", "-XX:+" + gcFlag, "-Xmx10M", "-XX:+UseDynamicNumberOfGCThreads", "-Xlog:gc+task=trace", "-version"}; // Base test with gc and +UseDynamicNumberOfGCThreads: ProcessBuilder pb_enabled = ProcessTools.createJavaProcessBuilder(baseArgs); --- old/test/hotspot/jtreg/gc/logging/TestGCId.java 2020-01-17 17:15:01.997114395 +0100 +++ new/test/hotspot/jtreg/gc/logging/TestGCId.java 2020-01-17 17:15:01.896114400 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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 @@ -30,10 +30,14 @@ * @library /test/lib * @modules java.base/jdk.internal.misc * java.management + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestGCId */ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import sun.hotspot.gc.GC; public class TestGCId { public static void main(String[] args) throws Exception { @@ -41,6 +45,9 @@ testGCId("UseG1GC"); testGCId("UseConcMarkSweepGC"); testGCId("UseSerialGC"); + if (GC.Shenandoah.isSupported()) { + testGCId("UseShenandoahGC"); + } } private static void verifyContainsGCIDs(OutputAnalyzer output) { @@ -51,7 +58,7 @@ private static void testGCId(String gcFlag) throws Exception { ProcessBuilder pb_default = - ProcessTools.createJavaProcessBuilder("-XX:+" + gcFlag, "-Xlog:gc", "-Xmx10M", GCTest.class.getName()); + ProcessTools.createJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", "-XX:+" + gcFlag, "-Xlog:gc", "-Xmx10M", GCTest.class.getName()); verifyContainsGCIDs(new OutputAnalyzer(pb_default.start())); } --- old/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java 2020-01-17 17:15:02.567114363 +0100 +++ new/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java 2020-01-17 17:15:02.469114369 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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 @@ -53,6 +53,20 @@ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseParallelGC -XX:+UseParallelOldGC TestMetaspacePerfCounters * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseG1GC TestMetaspacePerfCounters */ + +/* @test TestMetaspacePerfCountersShenandoah + * @bug 8014659 + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @library /test/lib / + * @summary Tests that performance counters for metaspace and compressed class + * space exists and works. + * @modules java.base/jdk.internal.misc + * java.compiler + * java.management/sun.management + * jdk.internal.jvmstat/sun.jvmstat.monitor + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC TestMetaspacePerfCounters + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC TestMetaspacePerfCounters + */ public class TestMetaspacePerfCounters { public static Class fooClass = null; private static final String[] counterNames = {"minCapacity", "maxCapacity", "capacity", "used"}; --- old/test/hotspot/jtreg/gc/survivorAlignment/TestAllocationInEden.java 2020-01-17 17:15:03.149114331 +0100 +++ new/test/hotspot/jtreg/gc/survivorAlignment/TestAllocationInEden.java 2020-01-17 17:15:03.048114337 +0100 @@ -26,7 +26,7 @@ * @bug 8031323 * @summary Verify that object's alignment in eden space is not affected by * SurvivorAlignmentInBytes option. - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management --- old/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromEdenToTenured.java 2020-01-17 17:15:03.724114300 +0100 +++ new/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromEdenToTenured.java 2020-01-17 17:15:03.623114305 +0100 @@ -26,7 +26,7 @@ * @bug 8031323 * @summary Verify that objects promoted from eden space to tenured space during * full GC are not aligned to SurvivorAlignmentInBytes value. - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management --- old/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java 2020-01-17 17:15:04.296114268 +0100 +++ new/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java 2020-01-17 17:15:04.199114273 +0100 @@ -26,7 +26,7 @@ * @bug 8031323 * @summary Verify that objects promoted from survivor space to tenured space * during full GC are not aligned to SurvivorAlignmentInBytes value. - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management --- old/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java 2020-01-17 17:15:04.877114236 +0100 +++ new/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java 2020-01-17 17:15:04.776114242 +0100 @@ -27,7 +27,7 @@ * @summary Verify that objects promoted from survivor space to tenured space * when their age exceeded tenuring threshold are not aligned to * SurvivorAlignmentInBytes value. - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management --- old/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionToSurvivor.java 2020-01-17 17:15:05.446114205 +0100 +++ new/test/hotspot/jtreg/gc/survivorAlignment/TestPromotionToSurvivor.java 2020-01-17 17:15:05.345114210 +0100 @@ -26,7 +26,7 @@ * @bug 8031323 * @summary Verify that objects promoted from eden space to survivor space after * minor GC are aligned to SurvivorAlignmentInBytes. - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management --- old/test/hotspot/jtreg/gc/whitebox/TestWBGC.java 2020-01-17 17:15:06.015114173 +0100 +++ new/test/hotspot/jtreg/gc/whitebox/TestWBGC.java 2020-01-17 17:15:05.916114179 +0100 @@ -25,7 +25,7 @@ * @test TestWBGC * @bug 8055098 * @summary Test verify that WB methods isObjectInOldGen and youngGC works correctly. - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management --- old/test/hotspot/jtreg/resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java 2020-01-17 17:15:06.596114141 +0100 +++ new/test/hotspot/jtreg/resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java 2020-01-17 17:15:06.498114147 +0100 @@ -47,6 +47,7 @@ * @library /test/lib * @bug 8171084 * @requires vm.hasSAandCanAttach & (vm.bits == "64" & os.maxMemory > 8g) + * @requires vm.gc != "Shenandoah" * @modules java.base/jdk.internal.misc * jdk.hotspot.agent/sun.jvm.hotspot * jdk.hotspot.agent/sun.jvm.hotspot.utilities --- old/test/hotspot/jtreg/runtime/CompressedOops/UseCompressedOops.java 2020-01-17 17:15:07.174114110 +0100 +++ new/test/hotspot/jtreg/runtime/CompressedOops/UseCompressedOops.java 2020-01-17 17:15:07.073114115 +0100 @@ -37,6 +37,7 @@ import jdk.test.lib.Platform; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.gc.GC; import sun.hotspot.code.Compiler; @@ -61,6 +62,9 @@ testCompressedOopsModes(args, "-XX:+UseSerialGC"); testCompressedOopsModes(args, "-XX:+UseParallelGC"); testCompressedOopsModes(args, "-XX:+UseParallelOldGC"); + if (GC.Shenandoah.isSupported()) { + testCompressedOopsModes(args, "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC"); + } } public static void testCompressedOopsModes(ArrayList flags1, String... flags2) throws Exception { --- old/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java 2020-01-17 17:15:07.752114078 +0100 +++ new/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java 2020-01-17 17:15:07.655114083 +0100 @@ -36,6 +36,7 @@ import jdk.test.lib.process.ProcessTools; import sun.hotspot.code.Compiler; +import sun.hotspot.gc.GC; public class MemberNameLeak { static class Leak { @@ -61,6 +62,7 @@ // Run this Leak class with logging ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-Xlog:membername+table=trace", + "-XX:+UnlockExperimentalVMOptions", gc, Leak.class.getName()); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("ResolvedMethod entry added for MemberNameLeak$Leak.callMe()V"); @@ -73,8 +75,11 @@ test("-XX:+UseG1GC"); test("-XX:+UseParallelGC"); test("-XX:+UseSerialGC"); - if (!Compiler.isGraalEnabled()) { // Graal does not support CMS + if (!Compiler.isGraalEnabled()) { // Graal does not support CMS and Shenandoah test("-XX:+UseConcMarkSweepGC"); + if (GC.Shenandoah.isSupported()) { + test("-XX:+UseShenandoahGC"); + } } } } --- old/test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java 2020-01-17 17:15:08.312114047 +0100 +++ new/test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java 2020-01-17 17:15:08.218114052 +0100 @@ -34,6 +34,7 @@ * @bug 8191658 * @summary Test clhsdb jhisto command * @requires vm.hasSA + * @requires vm.gc != "Shenandoah" * @library /test/lib * @run main/othervm ClhsdbJhisto */ --- old/test/hotspot/jtreg/serviceability/tmtools/jstat/GcCapacityTest.java 2020-01-17 17:15:08.888114015 +0100 +++ new/test/hotspot/jtreg/serviceability/tmtools/jstat/GcCapacityTest.java 2020-01-17 17:15:08.787114021 +0100 @@ -27,7 +27,7 @@ * @test * @summary Test checks the consistency of the output * displayed with jstat -gccapacity. - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @modules java.base/jdk.internal.misc * @library /test/lib * @library ../share --- old/test/hotspot/jtreg/serviceability/tmtools/jstat/GcCauseTest01.java 2020-01-17 17:15:09.464113983 +0100 +++ new/test/hotspot/jtreg/serviceability/tmtools/jstat/GcCauseTest01.java 2020-01-17 17:15:09.362113989 +0100 @@ -32,7 +32,7 @@ * @library /test/lib * @library ../share * @requires vm.opt.ExplicitGCInvokesConcurrent != true - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @run main/othervm -XX:+UsePerfData -Xmx128M GcCauseTest01 */ import utils.*; --- old/test/hotspot/jtreg/serviceability/tmtools/jstat/GcCauseTest02.java 2020-01-17 17:15:10.036113952 +0100 +++ new/test/hotspot/jtreg/serviceability/tmtools/jstat/GcCauseTest02.java 2020-01-17 17:15:09.938113957 +0100 @@ -28,7 +28,7 @@ * test forces debuggee application eat ~70% of heap and runs jstat. * jstat should show actual usage of old gen (OC/OU ~= old gen usage). * @requires vm.opt.ExplicitGCInvokesConcurrent != true - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @modules java.base/jdk.internal.misc * @library /test/lib * @library ../share --- old/test/hotspot/jtreg/serviceability/tmtools/jstat/GcCauseTest03.java 2020-01-17 17:15:10.610113920 +0100 +++ new/test/hotspot/jtreg/serviceability/tmtools/jstat/GcCauseTest03.java 2020-01-17 17:15:10.513113926 +0100 @@ -27,7 +27,7 @@ * Test scenario: * test forces debuggee application call System.gc(), runs jstat and checks that * cause of last garbage collection displayed by jstat (LGCC) is 'System.gc()'. - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @modules java.base/jdk.internal.misc * @library /test/lib * @library ../share --- old/test/hotspot/jtreg/serviceability/tmtools/jstat/GcNewTest.java 2020-01-17 17:15:11.175113889 +0100 +++ new/test/hotspot/jtreg/serviceability/tmtools/jstat/GcNewTest.java 2020-01-17 17:15:11.079113894 +0100 @@ -29,7 +29,7 @@ * test several times provokes garbage collection in the debuggee application and after each garbage * collection runs jstat. jstat should show that after garbage collection number of GC events and garbage * collection time increase. - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @modules java.base/jdk.internal.misc * @library /test/lib * @library ../share --- old/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest01.java 2020-01-17 17:15:11.746113858 +0100 +++ new/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest01.java 2020-01-17 17:15:11.646113863 +0100 @@ -35,7 +35,7 @@ * @library /test/lib * @library ../share * @requires vm.opt.ExplicitGCInvokesConcurrent != true - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @run main/othervm -XX:+UsePerfData -Xmx128M GcTest01 */ import utils.*; --- old/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest02.java 2020-01-17 17:15:12.321113826 +0100 +++ new/test/hotspot/jtreg/serviceability/tmtools/jstat/GcTest02.java 2020-01-17 17:15:12.221113831 +0100 @@ -28,7 +28,7 @@ * test forces debuggee application eat ~70% of heap and runs jstat. * jstat should show actual usage of old gen (OC/OU ~= old gen usage). * @requires vm.opt.ExplicitGCInvokesConcurrent != true - * @requires vm.gc != "Z" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" * @modules java.base/jdk.internal.misc * @library /test/lib * @library ../share --- old/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/general_functions/GF08/gf08t001/TestDriver.java 2020-01-17 17:15:12.886113795 +0100 +++ new/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/general_functions/GF08/gf08t001/TestDriver.java 2020-01-17 17:15:12.789113800 +0100 @@ -72,15 +72,16 @@ Boolean isUseG1GCon = wb.getBooleanVMFlag("UseG1GC"); Boolean isUseConcMarkSweepGCon = wb.getBooleanVMFlag("UseConcMarkSweepGC"); Boolean isUseZGCon = wb.getBooleanVMFlag("UseZGC"); + Boolean isShenandoahGCon = wb.getBooleanVMFlag("UseShenandoahGC"); Boolean isUseEpsilonGCon = wb.getBooleanVMFlag("UseEpsilonGC"); if (Compiler.isGraalEnabled() && - (isUseConcMarkSweepGCon || isUseZGCon || isUseEpsilonGCon)) { + (isUseConcMarkSweepGCon || isUseZGCon || isUseEpsilonGCon || isShenandoahGCon)) { return; // Graal does not support these GCs } String keyPhrase; - if ((isExplicitGCInvokesConcurrentOn && (isUseG1GCon || isUseConcMarkSweepGCon)) || isUseZGCon) { + if ((isExplicitGCInvokesConcurrentOn && (isUseG1GCon || isUseConcMarkSweepGCon)) || isUseZGCon || isShenandoahGCon) { keyPhrase = "GC"; } else { keyPhrase = "Pause Full"; --- old/test/lib/jdk/test/lib/jfr/EventNames.java 2020-01-17 17:15:13.458113763 +0100 +++ new/test/lib/jdk/test/lib/jfr/EventNames.java 2020-01-17 17:15:13.361113769 +0100 @@ -98,6 +98,8 @@ public final static String G1HeapSummary = PREFIX + "G1HeapSummary"; public final static String G1HeapRegionInformation = PREFIX + "G1HeapRegionInformation"; public final static String G1HeapRegionTypeChange = PREFIX + "G1HeapRegionTypeChange"; + public final static String ShenandoahHeapRegionInformation = PREFIX + "ShenandoahHeapRegionInformation"; + public final static String ShenandoahHeapRegionStateChange = PREFIX + "ShenandoahHeapRegionStateChange"; public final static String TenuringDistribution = PREFIX + "TenuringDistribution"; public final static String GarbageCollection = PREFIX + "GarbageCollection"; public final static String ParallelOldCollection = PREFIX + "ParallelOldGarbageCollection"; --- old/test/lib/jdk/test/lib/jfr/GCHelper.java 2020-01-17 17:15:14.031113732 +0100 +++ new/test/lib/jdk/test/lib/jfr/GCHelper.java 2020-01-17 17:15:13.931113737 +0100 @@ -80,6 +80,7 @@ public static final String pauseLevelEvent = "GCPhasePauseLevel"; private static final List g1HeapRegionTypes; + private static final List shenandoahHeapRegionStates; private static PrintStream defaultErrorLog = null; public static int getGcId(RecordedEvent event) { @@ -207,6 +208,21 @@ }; g1HeapRegionTypes = Collections.unmodifiableList(Arrays.asList(g1HeapRegionTypeLiterals)); + + String[] shenandoahHeapRegionStateLiterals = new String[] { + "Empty Uncommitted", + "Empty Committed", + "Regular", + "Humongous Start", + "Humongous Continuation", + "Humongous Start, Pinned", + "Collection Set", + "Pinned", + "Collection Set, Pinned", + "Trash" + }; + + shenandoahHeapRegionStates = Collections.unmodifiableList(Arrays.asList(shenandoahHeapRegionStateLiterals)); } /** @@ -443,6 +459,13 @@ return g1HeapRegionTypes.contains(type); } + public static boolean assertIsValidShenandoahHeapRegionState(final String state) { + if (!shenandoahHeapRegionStates.contains(state)) { + throw new AssertionError("Unknown state '" + state + "', valid heap region states are " + shenandoahHeapRegionStates); + } + return true; + } + /** * Helper function to align heap size up. * --- old/test/lib/sun/hotspot/gc/GC.java 2020-01-17 17:15:14.610113700 +0100 +++ new/test/lib/sun/hotspot/gc/GC.java 2020-01-17 17:15:14.510113705 +0100 @@ -38,7 +38,8 @@ ConcMarkSweep(3), G1(4), Epsilon(5), - Z(6); + Z(6), + Shenandoah(7); private static final WhiteBox WB = WhiteBox.getWhiteBox(); --- /dev/null 2020-01-17 11:46:19.065201212 +0100 +++ new/src/hotspot/share/gc/shared/markBitMap.cpp 2020-01-17 17:15:15.078113674 +0100 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015, 2018, 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. + * + */ + +// Concurrent marking bit map wrapper + +#include "precompiled.hpp" +#include "gc/shared/markBitMap.inline.hpp" +#include "utilities/bitMap.inline.hpp" + +MarkBitMapRO::MarkBitMapRO(int shifter) : + _bm(), + _shifter(shifter) { + _bmStartWord = 0; + _bmWordSize = 0; +} + +#ifndef PRODUCT +bool MarkBitMapRO::covers(MemRegion heap_rs) const { + // assert(_bm.map() == _virtual_space.low(), "map inconsistency"); + assert(((size_t)_bm.size() * ((size_t)1 << _shifter)) == _bmWordSize, + "size inconsistency"); + return _bmStartWord == (HeapWord*)(heap_rs.start()) && + _bmWordSize == heap_rs.word_size(); +} +#endif + +void MarkBitMapRO::print_on_error(outputStream* st, const char* prefix) const { + _bm.print_on_error(st, prefix); +} + +size_t MarkBitMap::compute_size(size_t heap_size) { + return ReservedSpace::allocation_align_size_up(heap_size / mark_distance()); +} + +size_t MarkBitMap::mark_distance() { + return MinObjAlignmentInBytes * BitsPerByte; +} + +void MarkBitMap::initialize(MemRegion heap, MemRegion bitmap) { + _bmStartWord = heap.start(); + _bmWordSize = heap.word_size(); + + _bm = BitMapView((BitMap::bm_word_t*) bitmap.start(), _bmWordSize >> _shifter); + _covered = heap; +} + +void MarkBitMap::do_clear(MemRegion mr, bool large) { + MemRegion intersection = mr.intersection(_covered); + assert(!intersection.is_empty(), + "Given range from " PTR_FORMAT " to " PTR_FORMAT " is completely outside the heap", + p2i(mr.start()), p2i(mr.end())); + // convert address range into offset range + size_t beg = heapWordToOffset(intersection.start()); + size_t end = heapWordToOffset(intersection.end()); + if (large) { + _bm.clear_large_range(beg, end); + } else { + _bm.clear_range(beg, end); + } +} + --- /dev/null 2020-01-17 11:46:19.065201212 +0100 +++ new/src/hotspot/share/gc/shared/markBitMap.hpp 2020-01-17 17:15:15.675113641 +0100 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015, 2018, 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. + * + */ + +#ifndef SHARE_VM_GC_SHARED_CMBITMAP_HPP +#define SHARE_VM_GC_SHARED_CMBITMAP_HPP + +#include "memory/memRegion.hpp" +#include "utilities/bitMap.hpp" +#include "utilities/globalDefinitions.hpp" + +// A generic CM bit map. This is essentially a wrapper around the BitMap +// class, with one bit per (1<<_shifter) HeapWords. + +class MarkBitMapRO { + protected: + MemRegion _covered; // The heap area covered by this bitmap. + HeapWord* _bmStartWord; // base address of range covered by map + size_t _bmWordSize; // map size (in #HeapWords covered) + const int _shifter; // map to char or bit + BitMapView _bm; // the bit map itself + + public: + // constructor + MarkBitMapRO(int shifter); + + // inquiries + HeapWord* startWord() const { return _bmStartWord; } + // the following is one past the last word in space + HeapWord* endWord() const { return _bmStartWord + _bmWordSize; } + + // read marks + + bool isMarked(HeapWord* addr) const { + assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize), + "outside underlying space?"); + return _bm.at(heapWordToOffset(addr)); + } + + // iteration + inline bool iterate(BitMapClosure* cl, MemRegion mr); + + // Return the address corresponding to the next marked bit at or after + // "addr", and before "limit", if "limit" is non-NULL. If there is no + // such bit, returns "limit" if that is non-NULL, or else "endWord()". + inline HeapWord* getNextMarkedWordAddress(const HeapWord* addr, + const HeapWord* limit = NULL) const; + + // conversion utilities + HeapWord* offsetToHeapWord(size_t offset) const { + return _bmStartWord + (offset << _shifter); + } + size_t heapWordToOffset(const HeapWord* addr) const { + return pointer_delta(addr, _bmStartWord) >> _shifter; + } + + // The argument addr should be the start address of a valid object + inline HeapWord* nextObject(HeapWord* addr); + + void print_on_error(outputStream* st, const char* prefix) const; + + // debugging + NOT_PRODUCT(bool covers(MemRegion rs) const;) +}; + +class MarkBitMap : public MarkBitMapRO { + private: + // Clear bitmap range + void do_clear(MemRegion mr, bool large); + + public: + static size_t compute_size(size_t heap_size); + // Returns the amount of bytes on the heap between two marks in the bitmap. + static size_t mark_distance(); + // Returns how many bytes (or bits) of the heap a single byte (or bit) of the + // mark bitmap corresponds to. This is the same as the mark distance above. static size_t heap_map_factor() { + static size_t heap_map_factor() { + return mark_distance(); + } + + MarkBitMap() : MarkBitMapRO(LogMinObjAlignment) {} + + // Initializes the underlying BitMap to cover the given area. + void initialize(MemRegion heap, MemRegion bitmap); + + // Write marks. + inline void mark(HeapWord* addr); + inline void clear(HeapWord* addr); + inline bool parMark(HeapWord* addr); + + // Clear range. For larger regions, use *_large. + void clear() { do_clear(_covered, true); } + void clear_range(MemRegion mr) { do_clear(mr, false); } + void clear_range_large(MemRegion mr) { do_clear(mr, true); } +}; + +#endif // SHARE_VM_GC_SHARED_CMBITMAP_HPP --- /dev/null 2020-01-17 11:46:19.065201212 +0100 +++ new/src/hotspot/share/gc/shared/markBitMap.inline.hpp 2020-01-17 17:15:16.266113609 +0100 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015, 2018, 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. + * + */ + +#ifndef SHARE_VM_GC_SHARED_CMBITMAP_INLINE_HPP +#define SHARE_VM_GC_SHARED_CMBITMAP_INLINE_HPP + +#include "gc/shared/markBitMap.hpp" +#include "oops/oop.inline.hpp" +#include "utilities/bitMap.inline.hpp" +#include "utilities/align.hpp" + +inline HeapWord* MarkBitMapRO::getNextMarkedWordAddress(const HeapWord* addr, + const HeapWord* limit) const { + // First we must round addr *up* to a possible object boundary. + addr = (HeapWord*)align_up((intptr_t)addr, + HeapWordSize << _shifter); + size_t addrOffset = heapWordToOffset(addr); + assert(limit != NULL, "limit must not be NULL"); + size_t limitOffset = heapWordToOffset(limit); + size_t nextOffset = _bm.get_next_one_offset(addrOffset, limitOffset); + HeapWord* nextAddr = offsetToHeapWord(nextOffset); + assert(nextAddr >= addr, "get_next_one postcondition"); + assert(nextAddr == limit || isMarked(nextAddr), + "get_next_one postcondition"); + return nextAddr; +} + +inline bool MarkBitMapRO::iterate(BitMapClosure* cl, MemRegion mr) { + HeapWord* start_addr = MAX2(startWord(), mr.start()); + HeapWord* end_addr = MIN2(endWord(), mr.end()); + + if (end_addr > start_addr) { + // Right-open interval [start-offset, end-offset). + BitMap::idx_t start_offset = heapWordToOffset(start_addr); + BitMap::idx_t end_offset = heapWordToOffset(end_addr); + + start_offset = _bm.get_next_one_offset(start_offset, end_offset); + while (start_offset < end_offset) { + if (!cl->do_bit(start_offset)) { + return false; + } + HeapWord* next_addr = MIN2(nextObject(offsetToHeapWord(start_offset)), end_addr); + BitMap::idx_t next_offset = heapWordToOffset(next_addr); + start_offset = _bm.get_next_one_offset(next_offset, end_offset); + } + } + return true; +} + +// The argument addr should be the start address of a valid object +HeapWord* MarkBitMapRO::nextObject(HeapWord* addr) { + oop obj = (oop) addr; + HeapWord* res = addr + obj->size(); + assert(offsetToHeapWord(heapWordToOffset(res)) == res, "sanity"); + return res; +} + +#define check_mark(addr) \ + assert(_bmStartWord <= (addr) && (addr) < (_bmStartWord + _bmWordSize), \ + "outside underlying space?"); \ + /* assert(G1CollectedHeap::heap()->is_in_exact(addr), \ + err_msg("Trying to access not available bitmap "PTR_FORMAT \ + " corresponding to "PTR_FORMAT" (%u)", \ + p2i(this), p2i(addr), G1CollectedHeap::heap()->addr_to_region(addr))); */ + +inline void MarkBitMap::mark(HeapWord* addr) { + check_mark(addr); + _bm.set_bit(heapWordToOffset(addr)); +} + +inline void MarkBitMap::clear(HeapWord* addr) { + check_mark(addr); + _bm.clear_bit(heapWordToOffset(addr)); +} + +inline bool MarkBitMap::parMark(HeapWord* addr) { + check_mark(addr); + return _bm.par_set_bit(heapWordToOffset(addr)); +} + +#undef check_mark + +#endif // SHARE_VM_GC_SHARED_CMBITMAP_INLINE_HPP --- /dev/null 2020-01-17 11:46:19.065201212 +0100 +++ new/src/hotspot/share/gc/shared/parallelCleaning.cpp 2020-01-17 17:15:16.871113575 +0100 @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2015, 2018, 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 "precompiled.hpp" +#include "classfile/symbolTable.hpp" +#include "classfile/stringTable.hpp" +#include "code/codeCache.hpp" +#include "gc/shared/parallelCleaning.hpp" +#include "memory/resourceArea.hpp" +#include "prims/resolvedMethodTable.hpp" +#include "logging/log.hpp" +#include "gc/shared/gcCause.hpp" +#include "gc/shared/gcTraceTime.hpp" +#include "gc/shared/gcTraceTime.inline.hpp" + +StringSymbolTableUnlinkTask::StringSymbolTableUnlinkTask(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols) : + AbstractGangTask("String/Symbol Unlinking"), + _is_alive(is_alive), + _par_state_string(StringTable::weak_storage()), + _process_strings(process_strings), _strings_processed(0), _strings_removed(0), + _process_symbols(process_symbols), _symbols_processed(0), _symbols_removed(0) { + + _initial_string_table_size = (int) StringTable::the_table()->table_size(); + _initial_symbol_table_size = SymbolTable::the_table()->table_size(); + if (process_symbols) { + SymbolTable::clear_parallel_claimed_index(); + } +} + +StringSymbolTableUnlinkTask::~StringSymbolTableUnlinkTask() { + guarantee(!_process_symbols || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size, + "claim value %d after unlink less than initial symbol table size %d", + SymbolTable::parallel_claimed_index(), _initial_symbol_table_size); + + log_info(gc, stringtable)( + "Cleaned string and symbol table, " + "strings: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed, " + "symbols: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed", + strings_processed(), strings_removed(), + symbols_processed(), symbols_removed()); +} + +void StringSymbolTableUnlinkTask::work(uint worker_id) { + int strings_processed = 0; + int strings_removed = 0; + int symbols_processed = 0; + int symbols_removed = 0; + if (_process_strings) { + StringTable::possibly_parallel_unlink(&_par_state_string, _is_alive, &strings_processed, &strings_removed); + Atomic::add(strings_processed, &_strings_processed); + Atomic::add(strings_removed, &_strings_removed); + } + if (_process_symbols) { + SymbolTable::possibly_parallel_unlink(&symbols_processed, &symbols_removed); + Atomic::add(symbols_processed, &_symbols_processed); + Atomic::add(symbols_removed, &_symbols_removed); + } +} + +size_t StringSymbolTableUnlinkTask::strings_processed() const { return (size_t)_strings_processed; } +size_t StringSymbolTableUnlinkTask::strings_removed() const { return (size_t)_strings_removed; } + +size_t StringSymbolTableUnlinkTask::symbols_processed() const { return (size_t)_symbols_processed; } +size_t StringSymbolTableUnlinkTask::symbols_removed() const { return (size_t)_symbols_removed; } + + +Monitor* CodeCacheUnloadingTask::_lock = new Monitor(Mutex::leaf, "Code Cache Unload lock", false, Monitor::_safepoint_check_never); + +CodeCacheUnloadingTask::CodeCacheUnloadingTask(uint num_workers, BoolObjectClosure* is_alive, bool unloading_occurred) : + _is_alive(is_alive), + _unloading_occurred(unloading_occurred), + _num_workers(num_workers), + _first_nmethod(NULL), + _claimed_nmethod(NULL), + _postponed_list(NULL), + _num_entered_barrier(0) +{ + CompiledMethod::increase_unloading_clock(); + // Get first alive nmethod + CompiledMethodIterator iter = CompiledMethodIterator(); + if(iter.next_alive()) { + _first_nmethod = iter.method(); + } + _claimed_nmethod = (volatile CompiledMethod*)_first_nmethod; +} + +CodeCacheUnloadingTask::~CodeCacheUnloadingTask() { + CodeCache::verify_clean_inline_caches(); + + CodeCache::set_needs_cache_clean(false); + guarantee(CodeCache::scavenge_root_nmethods() == NULL, "Must be"); + + CodeCache::verify_icholder_relocations(); +} + +void CodeCacheUnloadingTask::add_to_postponed_list(CompiledMethod* nm) { + CompiledMethod* old; + do { + old = (CompiledMethod*)_postponed_list; + nm->set_unloading_next(old); + } while ((CompiledMethod*)Atomic::cmpxchg(nm, &_postponed_list, old) != old); +} + +void CodeCacheUnloadingTask::clean_nmethod(CompiledMethod* nm) { + bool postponed = nm->do_unloading_parallel(_is_alive, _unloading_occurred); + + if (postponed) { + // This nmethod referred to an nmethod that has not been cleaned/unloaded yet. + add_to_postponed_list(nm); + } + + // Mark that this thread has been cleaned/unloaded. + // After this call, it will be safe to ask if this nmethod was unloaded or not. + nm->set_unloading_clock(CompiledMethod::global_unloading_clock()); +} + +void CodeCacheUnloadingTask::clean_nmethod_postponed(CompiledMethod* nm) { + nm->do_unloading_parallel_postponed(); +} + +void CodeCacheUnloadingTask::claim_nmethods(CompiledMethod** claimed_nmethods, int *num_claimed_nmethods) { + CompiledMethod* first; + CompiledMethodIterator last; + + do { + *num_claimed_nmethods = 0; + + first = (CompiledMethod*)_claimed_nmethod; + last = CompiledMethodIterator(first); + + if (first != NULL) { + + for (int i = 0; i < MaxClaimNmethods; i++) { + if (!last.next_alive()) { + break; + } + claimed_nmethods[i] = last.method(); + (*num_claimed_nmethods)++; + } + } + + } while ((CompiledMethod*)Atomic::cmpxchg(last.method(), &_claimed_nmethod, first) != first); +} + +CompiledMethod* CodeCacheUnloadingTask::claim_postponed_nmethod() { + CompiledMethod* claim; + CompiledMethod* next; + + do { + claim = (CompiledMethod*)_postponed_list; + if (claim == NULL) { + return NULL; + } + + next = claim->unloading_next(); + + } while ((CompiledMethod*)Atomic::cmpxchg(next, &_postponed_list, claim) != claim); + + return claim; +} + +// Mark that we're done with the first pass of nmethod cleaning. +void CodeCacheUnloadingTask::barrier_mark(uint worker_id) { + MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag); + _num_entered_barrier++; + if (_num_entered_barrier == _num_workers) { + ml.notify_all(); + } +} + +// See if we have to wait for the other workers to +// finish their first-pass nmethod cleaning work. +void CodeCacheUnloadingTask::barrier_wait(uint worker_id) { + if (_num_entered_barrier < _num_workers) { + MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag); + while (_num_entered_barrier < _num_workers) { + ml.wait(Mutex::_no_safepoint_check_flag, 0, false); + } + } +} + +// Cleaning and unloading of nmethods. Some work has to be postponed +// to the second pass, when we know which nmethods survive. +void CodeCacheUnloadingTask::work_first_pass(uint worker_id) { + // The first nmethods is claimed by the first worker. + if (worker_id == 0 && _first_nmethod != NULL) { + clean_nmethod(_first_nmethod); + _first_nmethod = NULL; + } + + int num_claimed_nmethods; + CompiledMethod* claimed_nmethods[MaxClaimNmethods]; + + while (true) { + claim_nmethods(claimed_nmethods, &num_claimed_nmethods); + + if (num_claimed_nmethods == 0) { + break; + } + + for (int i = 0; i < num_claimed_nmethods; i++) { + clean_nmethod(claimed_nmethods[i]); + } + } +} + +void CodeCacheUnloadingTask::work_second_pass(uint worker_id) { + CompiledMethod* nm; + // Take care of postponed nmethods. + while ((nm = claim_postponed_nmethod()) != NULL) { + clean_nmethod_postponed(nm); + } +} + +KlassCleaningTask::KlassCleaningTask(BoolObjectClosure* is_alive) : + _is_alive(is_alive), + _clean_klass_tree_claimed(0), + _klass_iterator() { +} + +bool KlassCleaningTask::claim_clean_klass_tree_task() { + if (_clean_klass_tree_claimed) { + return false; + } + + return Atomic::cmpxchg(1, &_clean_klass_tree_claimed, 0) == 0; +} + +InstanceKlass* KlassCleaningTask::claim_next_klass() { + Klass* klass; + do { + klass =_klass_iterator.next_klass(); + } while (klass != NULL && !klass->is_instance_klass()); + + // this can be null so don't call InstanceKlass::cast + return static_cast(klass); +} + +void KlassCleaningTask::clean_klass(InstanceKlass* ik) { + ik->clean_weak_instanceklass_links(); +} + +void KlassCleaningTask::work() { + ResourceMark rm; + + // One worker will clean the subklass/sibling klass tree. + if (claim_clean_klass_tree_task()) { + Klass::clean_subklass_tree(); + } + + // All workers will help cleaning the classes, + InstanceKlass* klass; + while ((klass = claim_next_klass()) != NULL) { + clean_klass(klass); + } +} + +bool ResolvedMethodCleaningTask::claim_resolved_method_task() { + if (_resolved_method_task_claimed) { + return false; + } + return Atomic::cmpxchg(1, &_resolved_method_task_claimed, 0) == 0; +} + +// These aren't big, one thread can do it all. +void ResolvedMethodCleaningTask::work() { + if (claim_resolved_method_task()) { + ResolvedMethodTable::unlink(); + } +} + +ParallelCleaningTask::ParallelCleaningTask(BoolObjectClosure* is_alive, + bool process_strings, + bool process_symbols, + uint num_workers, + bool unloading_occurred) : + AbstractGangTask("Parallel Cleaning"), + _string_symbol_task(is_alive, process_strings, process_symbols), + _code_cache_task(num_workers, is_alive, unloading_occurred), + _klass_cleaning_task(is_alive), + _resolved_method_cleaning_task(is_alive) +{ + + +} + +// The parallel work done by all worker threads. +void ParallelCleaningTask::work(uint worker_id) { + // Do first pass of code cache cleaning. + _code_cache_task.work_first_pass(worker_id); + + // Let the threads mark that the first pass is done. + _code_cache_task.barrier_mark(worker_id); + + // Clean the Strings and Symbols. + _string_symbol_task.work(worker_id); + + // Clean unreferenced things in the ResolvedMethodTable + _resolved_method_cleaning_task.work(); + + // Wait for all workers to finish the first code cache cleaning pass. + _code_cache_task.barrier_wait(worker_id); + + // Do the second code cache cleaning work, which realize on + // the liveness information gathered during the first pass. + _code_cache_task.work_second_pass(worker_id); + + // Clean all klasses that were not unloaded. + _klass_cleaning_task.work(); +} --- /dev/null 2020-01-17 11:46:19.065201212 +0100 +++ new/src/hotspot/share/gc/shared/parallelCleaning.hpp 2020-01-17 17:15:17.470113542 +0100 @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2015, 2018, 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. + * + */ + +#ifndef SHARE_VM_GC_SHARED_PARALLELCLEANING_HPP +#define SHARE_VM_GC_SHARED_PARALLELCLEANING_HPP + +#include "gc/shared/oopStorageParState.hpp" +#include "gc/shared/workgroup.hpp" + +class StringSymbolTableUnlinkTask : public AbstractGangTask { +private: + BoolObjectClosure* _is_alive; + OopStorage::ParState _par_state_string; + int _initial_string_table_size; + int _initial_symbol_table_size; + + bool _process_strings; + volatile int _strings_processed; + volatile int _strings_removed; + + bool _process_symbols; + volatile int _symbols_processed; + volatile int _symbols_removed; + +public: + StringSymbolTableUnlinkTask(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols); + ~StringSymbolTableUnlinkTask(); + + void work(uint worker_id); + + size_t strings_processed() const; + size_t strings_removed() const; + + size_t symbols_processed() const; + size_t symbols_removed() const; +}; + +class CodeCacheUnloadingTask { +private: + static Monitor* _lock; + + BoolObjectClosure* const _is_alive; + const bool _unloading_occurred; + const uint _num_workers; + + // Variables used to claim nmethods. + CompiledMethod* _first_nmethod; + volatile CompiledMethod* _claimed_nmethod; + + // The list of nmethods that need to be processed by the second pass. + volatile CompiledMethod* _postponed_list; + volatile uint _num_entered_barrier; + + public: + CodeCacheUnloadingTask(uint num_workers, BoolObjectClosure* is_alive, bool unloading_occurred); + ~CodeCacheUnloadingTask(); + + private: + void add_to_postponed_list(CompiledMethod* nm); + + void clean_nmethod(CompiledMethod* nm); + + void clean_nmethod_postponed(CompiledMethod* nm); + + static const int MaxClaimNmethods = 16; + + void claim_nmethods(CompiledMethod** claimed_nmethods, int *num_claimed_nmethods); + + CompiledMethod* claim_postponed_nmethod(); + + public: + // Mark that we're done with the first pass of nmethod cleaning. + void barrier_mark(uint worker_id); + + // See if we have to wait for the other workers to + // finish their first-pass nmethod cleaning work. + void barrier_wait(uint worker_id); + + // Cleaning and unloading of nmethods. Some work has to be postponed + // to the second pass, when we know which nmethods survive. + void work_first_pass(uint worker_id); + + void work_second_pass(uint worker_id); +}; + +class KlassCleaningTask : public StackObj { + BoolObjectClosure* _is_alive; + volatile int _clean_klass_tree_claimed; + ClassLoaderDataGraphKlassIteratorAtomic _klass_iterator; + + public: + KlassCleaningTask(BoolObjectClosure* is_alive); + + private: + bool claim_clean_klass_tree_task(); + + InstanceKlass* claim_next_klass(); + +public: + + void clean_klass(InstanceKlass* ik); + + void work(); +}; + +class ResolvedMethodCleaningTask : public StackObj { + BoolObjectClosure* _is_alive; + volatile int _resolved_method_task_claimed; +public: + ResolvedMethodCleaningTask(BoolObjectClosure* is_alive) : + _is_alive(is_alive), _resolved_method_task_claimed(0) {} + + bool claim_resolved_method_task(); + void work(); +}; + +// To minimize the remark pause times, the tasks below are done in parallel. +class ParallelCleaningTask : public AbstractGangTask { +private: + StringSymbolTableUnlinkTask _string_symbol_task; + CodeCacheUnloadingTask _code_cache_task; + KlassCleaningTask _klass_cleaning_task; + ResolvedMethodCleaningTask _resolved_method_cleaning_task; + +public: + // The constructor is run in the VMThread. + ParallelCleaningTask(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols, uint num_workers, bool unloading_occurred); + + // The parallel work done by all worker threads. + void work(uint worker_id); +}; + +#endif // SHARE_VM_GC_SHARED_PARALLELCLEANING_HPP --- /dev/null 2020-01-17 11:46:19.065201212 +0100 +++ new/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesShenandoah.java 2020-01-17 17:15:18.074113509 +0100 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary C2 should use ldar, stlr and ldaxr+stlxr insns for volatile operations + * @library /test/lib / + * + * @modules java.base/jdk.internal.misc + * + * @requires os.arch=="aarch64" & vm.debug == true & + * vm.flavor == "server" & !vm.graal.enabled & + * vm.gc.Shenandoah + * + * @build compiler.c2.aarch64.TestVolatiles + * compiler.c2.aarch64.TestVolatileLoad + * compiler.c2.aarch64.TestUnsafeVolatileLoad + * compiler.c2.aarch64.TestVolatileStore + * compiler.c2.aarch64.TestUnsafeVolatileStore + * compiler.c2.aarch64.TestUnsafeVolatileCAS + * + * @run driver compiler.c2.aarch64.TestVolatilesSerial + * TestVolatileLoad Shenandoah + * + * @run driver compiler.c2.aarch64.TestVolatilesSerial + * TestVolatileStore Shenandoah + * + * @run driver compiler.c2.aarch64.TestVolatilesSerial + * TestUnsafeVolatileLoad Shenandoah + * + * @run driver compiler.c2.aarch64.TestVolatilesSerial + * TestUnsafeVolatileStore Shenandoah + * + * @run driver compiler.c2.aarch64.TestVolatilesSerial + * TestUnsafeVolatileCAS Shenandoah + * + * @run driver compiler.c2.aarch64.TestVolatilesSerial + * TestVolatileLoad ShenandoahTraversal + * + * @run driver compiler.c2.aarch64.TestVolatilesSerial + * TestVolatileStore ShenandoahTraversal + * + * @run driver compiler.c2.aarch64.TestVolatilesSerial + * TestUnsafeVolatileLoad ShenandoahTraversal + * + * @run driver compiler.c2.aarch64.TestVolatilesSerial + * TestUnsafeVolatileStore ShenandoahTraversal + * + * @run driver compiler.c2.aarch64.TestVolatilesSerial + * TestUnsafeVolatileCAS ShenandoahTraversal + */ + +package compiler.c2.aarch64; + +public class TestVolatilesShenandoah { + public static void main(String args[]) throws Throwable + { + // delegate work to shared code + new TestVolatiles().runtest(args[0], args[1]); + } +} --- /dev/null 2020-01-17 11:46:19.065201212 +0100 +++ new/test/hotspot/jtreg/gc/startup_warnings/TestShenandoah.java 2020-01-17 17:15:18.680113476 +0100 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* +* @test TestShenandoah +* @key gc +* @requires vm.gc.Shenandoah & !vm.graal.enabled +* @bug 8006398 +* @summary Test that the Shenandoah collector does not print a warning message +* @library /test/lib +* @modules java.base/jdk.internal.misc +* java.management +*/ + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class TestShenandoah { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("deprecated"); + output.shouldNotContain("error"); + output.shouldHaveExitValue(0); + } + +} --- /dev/null 2020-01-17 11:46:19.065201212 +0100 +++ new/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithShenandoah.java 2020-01-17 17:15:19.277113443 +0100 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2016, 2018, Red Hat, Inc. All rights reserved. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.io.IOException; + +/* + * @test TestGCBasherWithShenandoah + * @key gc + * @key stress + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @requires vm.flavor == "server" & !vm.emulatedClient & !vm.graal.enabled + * @summary Stress the Shenandoah GC by trying to make old objects more likely to be garbage than young objects. + * + * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive + * -XX:+ShenandoahVerify -XX:+ShenandoahDegeneratedGC + * TestGCBasherWithShenandoah 120000 + * + * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive + * -XX:+ShenandoahVerify -XX:-ShenandoahDegeneratedGC + * TestGCBasherWithShenandoah 120000 + */ + +/* + * @test TestGCBasherWithShenandoah + * @key gc + * @key stress + * @library / + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @requires vm.flavor == "server" & !vm.emulatedClient & !vm.graal.enabled + * @summary Stress the Shenandoah GC by trying to make old objects more likely to be garbage than young objects. + * + * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive + * -XX:+ShenandoahOOMDuringEvacALot + * TestGCBasherWithShenandoah 120000 + * + * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive + * -XX:+ShenandoahAllocFailureALot + * TestGCBasherWithShenandoah 120000 + * + * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive + * TestGCBasherWithShenandoah 120000 + */ + +/* + * @test TestGCBasherWithShenandoah + * @key gc + * @key stress + * @library / + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @requires vm.flavor == "server" & !vm.emulatedClient & !vm.graal.enabled + * @summary Stress the Shenandoah GC by trying to make old objects more likely to be garbage than young objects. + * + * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive + * -XX:+ShenandoahVerify + * TestGCBasherWithShenandoah 120000 + * + * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive + * TestGCBasherWithShenandoah 120000 + * + * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact + * TestGCBasherWithShenandoah 120000 + */ + +/* + * @test TestGCBasherWithShenandoah + * @key gc + * @key stress + * @library / + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @requires vm.flavor == "server" & !vm.emulatedClient & !vm.graal.enabled + * @summary Stress the Shenandoah GC by trying to make old objects more likely to be garbage than young objects. + * + * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive + * -XX:+ShenandoahOOMDuringEvacALot + * TestGCBasherWithShenandoah 120000 + * + * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive + * -XX:+ShenandoahAllocFailureALot + * TestGCBasherWithShenandoah 120000 + * + * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive + * TestGCBasherWithShenandoah 120000 + */ + +/* + * @test TestGCBasherWithShenandoah + * @key gc + * @key stress + * @library / + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @requires vm.flavor == "server" & !vm.emulatedClient & !vm.graal.enabled + * @summary Stress the Shenandoah GC by trying to make old objects more likely to be garbage than young objects. + * + * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal + * -XX:+ShenandoahVerify + * TestGCBasherWithShenandoah 120000 + * + * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal + * TestGCBasherWithShenandoah 120000 + */ +public class TestGCBasherWithShenandoah { + public static void main(String[] args) throws IOException { + TestGCBasher.main(args); + } +} --- /dev/null 2020-01-17 11:46:19.065201212 +0100 +++ new/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithShenandoah.java 2020-01-17 17:15:19.874113410 +0100 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test TestGCLockerWithShenandoah + * @key gc + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @summary Stress Shenandoah's JNI handling by calling GetPrimitiveArrayCritical while concurrently filling up old gen. + * + * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:+UseShenandoahGC + * -XX:+ShenandoahVerify + * TestGCLockerWithShenandoah + * + * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:+UseShenandoahGC + * TestGCLockerWithShenandoah + * + * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive + * -XX:+ShenandoahOOMDuringEvacALot + * TestGCLockerWithShenandoah + * + * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive + * -XX:+ShenandoahAllocFailureALot + * TestGCLockerWithShenandoah + */ +public class TestGCLockerWithShenandoah { + public static void main(String[] args) { + String[] testArgs = {"2", "Shenandoah heap"}; + TestGCLocker.main(testArgs); + } +} --- /dev/null 2020-01-17 11:46:19.065201212 +0100 +++ new/test/hotspot/jtreg/gc/stress/gcold/TestGCOldWithShenandoah.java 2020-01-17 17:15:20.469113377 +0100 @@ -0,0 +1,125 @@ +/* +* Copyright (c) 2016, 2018, 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 TestGCOldWithShenandoah + * @key gc + * @key stress + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @summary Stress the GC by trying to make old objects more likely to be garbage than young objects. + * + * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive + * -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify + * TestGCOld 50 1 20 10 10000 + * + * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive + * -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify + * TestGCOld 50 1 20 10 10000 + * + * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive + * -XX:+ShenandoahDegeneratedGC + * TestGCOld 50 1 20 10 10000 + * + * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive + * -XX:-ShenandoahDegeneratedGC + * TestGCOld 50 1 20 10 10000 + */ + +/* + * @test TestGCOldWithShenandoah + * @key gc + * @key stress + * @library / + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @summary Stress the GC by trying to make old objects more likely to be garbage than young objects. + * + * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive + * -XX:+ShenandoahOOMDuringEvacALot + * TestGCOld 50 1 20 10 10000 + * + * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive + * -XX:+ShenandoahAllocFailureALot + * TestGCOld 50 1 20 10 10000 + * + * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive + * TestGCOld 50 1 20 10 10000 + * + * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive + * -XX:+ShenandoahVerify + * TestGCOld 50 1 20 10 10000 + * + * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive + * TestGCOld 50 1 20 10 10000 + * + * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact + * TestGCOld 50 1 20 10 10000 + */ + +/* + * @test TestGCOldWithShenandoah + * @key gc + * @key stress + * @library / + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @summary Stress the GC by trying to make old objects more likely to be garbage than young objects. + * + * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive + * -XX:+ShenandoahOOMDuringEvacALot + * TestGCOld 50 1 20 10 10000 + * + * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive + * -XX:+ShenandoahAllocFailureALot + * TestGCOld 50 1 20 10 10000 + * + * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive + * TestGCOld 50 1 20 10 10000 + * + * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal + * -XX:+ShenandoahVerify + * TestGCOld 50 1 20 10 10000 + * + * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal + * TestGCOld 50 1 20 10 10000 + */ + +public class TestGCOldWithShenandoah { + + public static void main(String[] args) { + TestGCOld.main(args); + } +} --- /dev/null 2020-01-17 11:46:19.065201212 +0100 +++ new/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithShenandoah.java 2020-01-17 17:15:21.060113344 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test TestSystemGCWithShenandoah + * @key gc + * @key stress + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @summary Stress the Shenandoah GC full GC by allocating objects of different lifetimes concurrently with System.gc(). + * + * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:+UseShenandoahGC + * -XX:+ShenandoahVerify + * TestSystemGCWithShenandoah 270 + * + * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:+UseShenandoahGC + * TestSystemGCWithShenandoah 270 + */ + +/* + * @test TestSystemGCWithShenandoah + * @key gc + * @key stress + * @library / + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @summary Stress the Shenandoah GC full GC by allocating objects of different lifetimes concurrently with System.gc(). + * + * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal + * -XX:+ShenandoahVerify + * TestSystemGCWithShenandoah 270 + * + */ +public class TestSystemGCWithShenandoah { + public static void main(String[] args) throws Exception { + TestSystemGC.main(args); + } +} --- /dev/null 2020-01-17 11:46:19.065201212 +0100 +++ new/test/jdk/jdk/jfr/event/gc/detailed/TestShenandoahHeapRegionInformationEvent.java 2020-01-17 17:15:21.653113312 +0100 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019, Red Hat, Inc. All rights reserved. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package jdk.jfr.event.gc.detailed; + +import java.nio.file.Paths; +import java.util.List; + +import jdk.jfr.EventType; +import jdk.jfr.FlightRecorder; +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.test.lib.Asserts; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; +import jdk.test.lib.jfr.GCHelper; + +/** + * @test + * @bug 8221507 + * @requires vm.hasJFR + * @requires vm.gc == "Shenandoah" | vm.gc == null + * @key jfr + * @library /test/lib /test/jdk + * @run main/othervm -Xmx32m -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGarbageThreshold=1 jdk.jfr.event.gc.detailed.TestShenandoahHeapRegionInformationEvent + */ + + +public class TestShenandoahHeapRegionInformationEvent { + private final static String EVENT_NAME = EventNames.ShenandoahHeapRegionInformation; + public static void main(String[] args) throws Exception { + try (Recording recording = new Recording()) { + // activate the event we are interested in and start recording + for (EventType t : FlightRecorder.getFlightRecorder().getEventTypes()) { + System.out.println(t.getName()); + } + recording.enable(EVENT_NAME); + recording.start(); + recording.stop(); + + // Verify recording + List events = Events.fromRecording(recording); + Events.hasEvents(events); + for (RecordedEvent event : events) { + Events.assertField(event, "index").notEqual(-1); + GCHelper.assertIsValidShenandoahHeapRegionState(Events.assertField(event, "state").getValue()); + Events.assertField(event, "used").atMost(1L*1024*1024); + } + } + } +} --- /dev/null 2020-01-17 11:46:19.065201212 +0100 +++ new/test/jdk/jdk/jfr/event/gc/detailed/TestShenandoahHeapRegionStateChangeEvent.java 2020-01-17 17:15:22.248113279 +0100 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2019, Red Hat, Inc. All rights reserved. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package jdk.jfr.event.gc.detailed; + +import java.nio.file.Paths; +import java.time.Duration; +import java.util.List; + +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.test.lib.Asserts; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; +import jdk.test.lib.jfr.GCHelper; + +/** + * @test + * @bug 8221507 + * @requires vm.hasJFR + * @requires vm.gc == "Shenandoah" | vm.gc == null + * @key jfr + * @library /test/lib /test/jdk + * @run main/othervm -Xmx32m -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGarbageThreshold=1 jdk.jfr.event.gc.detailed.TestShenandoahHeapRegionStateChangeEvent + */ + +public class TestShenandoahHeapRegionStateChangeEvent { + private final static String EVENT_NAME = EventNames.ShenandoahHeapRegionStateChange; + + public static void main(String[] args) throws Exception { + try (Recording recording = new Recording()) { + // activate the event we are interested in and start recording + recording.enable(EVENT_NAME).withThreshold(Duration.ofMillis(0)); + recording.start(); + + byte[][] array = new byte[1024][]; + for (int i = 0; i < array.length; i++) { + array[i] = new byte[20 * 1024]; + } + recording.stop(); + + // Verify recording + List events = Events.fromRecording(recording); + Asserts.assertFalse(events.isEmpty(), "No events found"); + + for (RecordedEvent event : events) { + Events.assertField(event, "index").notEqual(-1); + GCHelper.assertIsValidShenandoahHeapRegionState(Events.assertField(event, "from").getValue()); + GCHelper.assertIsValidShenandoahHeapRegionState(Events.assertField(event, "to").getValue()); + Events.assertField(event, "used").atMost(1L*1024*1024); + } + } + } +}