diff --git a/.github/workflows/submit.yml b/.github/workflows/submit.yml index d0817aa7241..5333ec0f1c9 100644 --- a/.github/workflows/submit.yml +++ b/.github/workflows/submit.yml @@ -14,7 +14,7 @@ on: jobs: prerequisites: name: Prerequisites - runs-on: "ubuntu-latest" + runs-on: "ubuntu-20.04" outputs: should_run: ${{ steps.check_submit.outputs.should_run }} bundle_id: ${{ steps.check_bundle_id.outputs.bundle_id }} @@ -88,7 +88,7 @@ jobs: if: steps.check_submit.outputs.should_run != 'false' && steps.jtreg.outputs.cache-hit != 'true' - name: Build jtreg - run: sh make/build-all.sh ${JAVA_HOME} + run: sh make/build-all.sh ${JAVA_HOME_8_X64} working-directory: jtreg if: steps.check_submit.outputs.should_run != 'false' && steps.jtreg.outputs.cache-hit != 'true' @@ -106,7 +106,7 @@ jobs: linux_x64_build: name: Linux x64 - runs-on: "ubuntu-latest" + runs-on: "ubuntu-20.04" needs: prerequisites if: needs.prerequisites.outputs.should_run != 'false' && needs.prerequisites.outputs.platform_linux_x64 != 'false' @@ -189,7 +189,9 @@ jobs: path: gtest - name: Install dependencies - run: sudo apt-get install libxrandr-dev libxtst-dev libcups2-dev libasound2-dev + run: | + sudo apt-get install gcc-10=10.2.0-5ubuntu1~20.04 g++-10=10.2.0-5ubuntu1~20.04 libxrandr-dev libxtst-dev libcups2-dev libasound2-dev + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 - name: Configure run: > @@ -221,7 +223,7 @@ jobs: linux_x64_test: name: Linux x64 - runs-on: "ubuntu-latest" + runs-on: "ubuntu-20.04" needs: - prerequisites - linux_x64_build @@ -400,7 +402,7 @@ jobs: linux_aarch64_build: name: Linux aarch64 - runs-on: "ubuntu-latest" + runs-on: "ubuntu-20.04" needs: - prerequisites - linux_x64_build @@ -536,7 +538,7 @@ jobs: linux_arm_build: name: Linux arm - runs-on: "ubuntu-latest" + runs-on: "ubuntu-20.04" needs: - prerequisites - linux_x64_build @@ -672,7 +674,7 @@ jobs: linux_s390x_build: name: Linux s390x - runs-on: "ubuntu-latest" + runs-on: "ubuntu-20.04" needs: - prerequisites - linux_x64_build @@ -808,7 +810,7 @@ jobs: linux_ppc64le_build: name: Linux ppc64le - runs-on: "ubuntu-latest" + runs-on: "ubuntu-20.04" needs: - prerequisites - linux_x64_build @@ -944,7 +946,7 @@ jobs: linux_x86_build: name: Linux x86 - runs-on: "ubuntu-latest" + runs-on: "ubuntu-20.04" needs: prerequisites if: needs.prerequisites.outputs.should_run != 'false' && needs.prerequisites.outputs.platform_linux_x86 != 'false' @@ -1018,7 +1020,8 @@ jobs: run: | sudo dpkg --add-architecture i386 sudo apt-get update - sudo apt-get install gcc-multilib g++-multilib libfreetype6-dev:i386 libxrandr-dev:i386 libxtst-dev:i386 libtiff-dev:i386 libcupsimage2-dev:i386 libcups2-dev:i386 libasound2-dev:i386 + sudo apt-get install gcc-10-multilib g++-10-multilib libfreetype6-dev:i386 libxrandr-dev:i386 libxtst-dev:i386 libtiff-dev:i386 libcupsimage2-dev:i386 libcups2-dev:i386 libasound2-dev:i386 + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 - name: Configure run: > @@ -1051,7 +1054,7 @@ jobs: linux_x86_test: name: Linux x86 - runs-on: "ubuntu-latest" + runs-on: "ubuntu-20.04" needs: - prerequisites - linux_x86_build @@ -1842,7 +1845,7 @@ jobs: artifacts: name: Post-process artifacts - runs-on: "ubuntu-latest" + runs-on: "ubuntu-20.04" if: always() continue-on-error: true needs: diff --git a/.jcheck/conf b/.jcheck/conf index 38ebf1da655..902f2ba592a 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -33,4 +33,5 @@ version=0 domain=openjdk.org [checks "whitespace"] -files=.*\.cpp|.*\.hpp|.*\.c|.*\.h|.*\.java|.*\.cc|.*\.hh|.*\.m|.*\.mm +files=.*\.cpp|.*\.hpp|.*\.c|.*\.h|.*\.java|.*\.cc|.*\.hh|.*\.m|.*\.mm|.*\.gmk|.*\.m4|.*\.ac|Makefile +ignore-tabs=.*\.gmk|Makefile diff --git a/make/autoconf/jvm-features.m4 b/make/autoconf/jvm-features.m4 index b45271641fb..b4e633401d9 100644 --- a/make/autoconf/jvm-features.m4 +++ b/make/autoconf/jvm-features.m4 @@ -159,7 +159,7 @@ AC_DEFUN_ONCE([JVM_FEATURES_PARSE_OPTIONS], # Likewise, check for deprecated arguments. m4_foreach(FEATURE, m4_split(jvm_features_deprecated), [ AC_ARG_ENABLE(jvm-feature-FEATURE, AS_HELP_STRING( - [--enable-jvm-feature-FEATURE], + [--enable-jvm-feature-FEATURE], [Deprecated. Option is kept for backwards compatibility and is ignored])) m4_define(FEATURE_SHELL, [enable_jvm_feature_]m4_translit(FEATURE, -, _)) diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index ded7fdf8c59..d4c202146e0 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -805,13 +805,15 @@ define SetupNativeCompilationBody -include $$($1_PCH_DEPS_TARGETS_FILE) $1_PCH_COMMAND := $$($1_CC) $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \ - $$($1_OPT_CFLAGS) -x c++-header -c $(C_FLAG_DEPS) $$($1_PCH_DEPS_FILE) + $$($1_OPT_CFLAGS) -x c++-header -c $(C_FLAG_DEPS) \ + $$(addsuffix .tmp, $$($1_PCH_DEPS_FILE)) $$($1_PCH_FILE): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE) $$(call LogInfo, Generating precompiled header) $$(call MakeDir, $$(@D)) $$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \ $$($1_PCH_COMMAND) $$< -o $$@)) + $$(call fix-deps-file, $$($1_PCH_DEPS_FILE)) $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_PCH_DEPS_FILE) \ > $$($1_PCH_DEPS_TARGETS_FILE) diff --git a/make/modules/java.base/gendata/GendataCryptoPolicy.gmk b/make/modules/java.base/gendata/GendataCryptoPolicy.gmk index e36a1b9fcb7..c63b36fe058 100644 --- a/make/modules/java.base/gendata/GendataCryptoPolicy.gmk +++ b/make/modules/java.base/gendata/GendataCryptoPolicy.gmk @@ -27,7 +27,7 @@ # In pre-JDK9 releases, Oracle JDK has had a separately downloadable set # of policy files which has been a nightmare for deployment. # -# We now create 2 complete initial sets of policy files and package into +# We now create 2 complete initial sets of policy files and package into # 2 different directories. The crypto.policy Security property will select # the active policy. # diff --git a/src/demo/share/java2d/RenderPerfTest/Makefile b/src/demo/share/java2d/RenderPerfTest/Makefile index 9ceb7a9d64a..ece64399bd5 100644 --- a/src/demo/share/java2d/RenderPerfTest/Makefile +++ b/src/demo/share/java2d/RenderPerfTest/Makefile @@ -39,7 +39,7 @@ RENDERPERFLCD_CLASSES = $(CLASSES)/renderperf/RenderPerfLCDTest.class RENDERPERF_SOURCES = $(SOURCEPATH)/renderperf/RenderPerfTest.java RENDERPERFLCD_SOURCES = $(SOURCEPATH)/renderperf/RenderPerfLCDTest.java -RENDERPERF_RESOURCES = $(CLASSES)/renderperf/images/duke.png +RENDERPERF_RESOURCES = $(CLASSES)/renderperf/images/duke.png all: mkdirs $(DIST)/RenderPerfTest.jar $(DIST)/RenderPerfLCDTest.jar diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index d24e8d21c5a..b9d262c3c96 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -504,8 +504,7 @@ class Address { if (size == 0) // It's a byte i->f(_ext.shift() >= 0, 12); else { - if (_ext.shift() > 0) - assert(_ext.shift() == (int)size, "bad shift"); + assert(_ext.shift() <= 0 || _ext.shift() == (int)size, "bad shift"); i->f(_ext.shift() > 0, 12); } i->f(0b10, 11, 10); diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp index f471209a4c0..1cbc3ed21d1 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp @@ -33,7 +33,6 @@ // Implementation of the platform-specific part of StubRoutines - for // a description of how to extend it, see the stubRoutines.hpp file. -address StubRoutines::aarch64::_get_previous_fp_entry = NULL; address StubRoutines::aarch64::_get_previous_sp_entry = NULL; address StubRoutines::aarch64::_f2i_fixup = NULL; diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp index 6960a19b3f5..7578791b540 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp @@ -43,7 +43,6 @@ class aarch64 { friend class StubGenerator; private: - static address _get_previous_fp_entry; static address _get_previous_sp_entry; static address _f2i_fixup; @@ -77,11 +76,6 @@ class aarch64 { public: - static address get_previous_fp_entry() - { - return _get_previous_fp_entry; - } - static address get_previous_sp_entry() { return _get_previous_sp_entry; diff --git a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp index 8ea0a4239af..195c76bd2db 100644 --- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp @@ -32,6 +32,7 @@ #include "gc/g1/heapRegion.hpp" #include "interpreter/interp_masm.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/debug.hpp" #include "utilities/macros.hpp" #ifdef COMPILER1 #include "c1/c1_LIRAssembler.hpp" @@ -264,6 +265,8 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Register thread, Register tmp, Register tmp2) { + // Generated code assumes that buffer index is pointer sized. + STATIC_ASSERT(in_bytes(SATBMarkQueue::byte_width_of_index()) == sizeof(intptr_t)); #ifdef _LP64 assert(thread == r15_thread, "must be"); #endif // _LP64 @@ -314,18 +317,13 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, __ movb(Address(card_addr, 0), (int)G1CardTable::dirty_card_val()); - __ cmpl(queue_index, 0); - __ jcc(Assembler::equal, runtime); - __ subl(queue_index, wordSize); - __ movptr(tmp2, buffer); -#ifdef _LP64 - __ movslq(rscratch1, queue_index); - __ addq(tmp2, rscratch1); - __ movq(Address(tmp2, 0), card_addr); -#else - __ addl(tmp2, queue_index); - __ movl(Address(tmp2, 0), card_addr); -#endif + __ movptr(tmp2, queue_index); + __ testptr(tmp2, tmp2); + __ jcc(Assembler::zero, runtime); + __ subptr(tmp2, wordSize); + __ movptr(queue_index, tmp2); + __ addptr(tmp2, buffer); + __ movptr(Address(tmp2, 0), card_addr); __ jmp(done); __ bind(runtime); @@ -453,6 +451,9 @@ void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarri #define __ sasm-> void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) { + // Generated code assumes that buffer index is pointer sized. + STATIC_ASSERT(in_bytes(SATBMarkQueue::byte_width_of_index()) == sizeof(intptr_t)); + __ prologue("g1_pre_barrier", false); // arg0 : previous value of memory diff --git a/src/hotspot/cpu/x86/methodHandles_x86.cpp b/src/hotspot/cpu/x86/methodHandles_x86.cpp index 0209120b80c..687b040d0aa 100644 --- a/src/hotspot/cpu/x86/methodHandles_x86.cpp +++ b/src/hotspot/cpu/x86/methodHandles_x86.cpp @@ -528,6 +528,12 @@ void trace_method_handle_stub(const char* adaptername, } tty->cr(); + // Note: We want to allow trace_method_handle from any call site. + // While trace_method_handle creates a frame, it may be entered + // without a PC on the stack top (e.g. not just after a call). + // Walking that frame could lead to failures due to that invalid PC. + // => carefully detect that frame when doing the stack walking + { // dumping last frame with frame::describe @@ -536,43 +542,38 @@ void trace_method_handle_stub(const char* adaptername, PRESERVE_EXCEPTION_MARK; // may not be needed but safer and inexpensive here FrameValues values; - // Note: We want to allow trace_method_handle from any call site. - // While trace_method_handle creates a frame, it may be entered - // without a PC on the stack top (e.g. not just after a call). - // Walking that frame could lead to failures due to that invalid PC. - // => carefully detect that frame when doing the stack walking - // Current C frame frame cur_frame = os::current_frame(); - // Robust search of trace_calling_frame (independant of inlining). - // Assumes saved_regs comes from a pusha in the trace_calling_frame. - assert(cur_frame.sp() < saved_regs, "registers not saved on stack ?"); - frame trace_calling_frame = os::get_sender_for_C_frame(&cur_frame); - while (trace_calling_frame.fp() < saved_regs) { - trace_calling_frame = os::get_sender_for_C_frame(&trace_calling_frame); - } - - // safely create a frame and call frame::describe - intptr_t *dump_sp = trace_calling_frame.sender_sp(); - intptr_t *dump_fp = trace_calling_frame.link(); - - bool walkable = has_mh; // whether the traced frame shoud be walkable - - if (walkable) { - // The previous definition of walkable may have to be refined - // if new call sites cause the next frame constructor to start - // failing. Alternatively, frame constructors could be - // modified to support the current or future non walkable - // frames (but this is more intrusive and is not considered as - // part of this RFE, which will instead use a simpler output). - frame dump_frame = frame(dump_sp, dump_fp); - dump_frame.describe(values, 1); - } else { - // Stack may not be walkable (invalid PC above FP): - // Add descriptions without building a Java frame to avoid issues - values.describe(-1, dump_fp, "fp for #1 "); - values.describe(-1, dump_sp, "sp for #1"); + if (cur_frame.fp() != 0) { // not walkable + + // Robust search of trace_calling_frame (independent of inlining). + // Assumes saved_regs comes from a pusha in the trace_calling_frame. + assert(cur_frame.sp() < saved_regs, "registers not saved on stack ?"); + frame trace_calling_frame = os::get_sender_for_C_frame(&cur_frame); + while (trace_calling_frame.fp() < saved_regs) { + trace_calling_frame = os::get_sender_for_C_frame(&trace_calling_frame); + } + + // safely create a frame and call frame::describe + intptr_t *dump_sp = trace_calling_frame.sender_sp(); + intptr_t *dump_fp = trace_calling_frame.link(); + + if (has_mh) { + // The previous definition of walkable may have to be refined + // if new call sites cause the next frame constructor to start + // failing. Alternatively, frame constructors could be + // modified to support the current or future non walkable + // frames (but this is more intrusive and is not considered as + // part of this RFE, which will instead use a simpler output). + frame dump_frame = frame(dump_sp, dump_fp); + dump_frame.describe(values, 1); + } else { + // Stack may not be walkable (invalid PC above FP): + // Add descriptions without building a Java frame to avoid issues + values.describe(-1, dump_fp, "fp for #1 "); + values.describe(-1, dump_sp, "sp for #1"); + } } values.describe(-1, entry_sp, "raw top of stack"); diff --git a/src/hotspot/cpu/x86/registerMap_x86.cpp b/src/hotspot/cpu/x86/registerMap_x86.cpp index 32e71c7e263..fd091262c29 100644 --- a/src/hotspot/cpu/x86/registerMap_x86.cpp +++ b/src/hotspot/cpu/x86/registerMap_x86.cpp @@ -28,23 +28,35 @@ address RegisterMap::pd_location(VMReg reg) const { if (reg->is_XMMRegister()) { - int regBase = reg->value() - ConcreteRegisterImpl::max_fpr; - if (regBase % 4 == 0) { - // Reads of the low and high 16 byte parts should be handled by location itself - // because they have separate callee saved entries. - // See RegisterSaver::save_live_registers(). - return NULL; + int reg_base = reg->value() - ConcreteRegisterImpl::max_fpr; + int base_reg_enc = (reg_base / XMMRegisterImpl::max_slots_per_register); + assert(base_reg_enc >= 0 && base_reg_enc < XMMRegisterImpl::number_of_registers, "invalid XMMRegister: %d", base_reg_enc); + VMReg base_reg = as_XMMRegister(base_reg_enc)->as_VMReg(); + intptr_t offset_in_bytes = (reg->value() - base_reg->value()) * VMRegImpl::stack_slot_size; + if (base_reg_enc > 15) { + if (offset_in_bytes == 0) { + return NULL; // ZMM16-31 are stored in full. + } + } else { + if (offset_in_bytes == 0 || offset_in_bytes == 16 || offset_in_bytes == 32) { + // Reads of the low and high 16 byte parts should be handled by location itself because + // they have separate callee saved entries (see RegisterSaver::save_live_registers()). + return NULL; + } + // The upper part of YMM0-15 and ZMM0-15 registers are saved separately in the frame. + if (offset_in_bytes > 32) { + base_reg = base_reg->next(8); + offset_in_bytes -= 32; + } else if (offset_in_bytes > 16) { + base_reg = base_reg->next(4); + offset_in_bytes -= 16; + } else { + // XMM0-15 case (0 < offset_in_bytes < 16). No need to adjust base register (or offset). + } } - VMReg baseReg = as_XMMRegister(regBase / XMMRegisterImpl::max_slots_per_register)->as_VMReg(); - intptr_t offset = (reg->value() - baseReg->value()) * VMRegImpl::stack_slot_size; // offset in bytes - if (offset >= 16) { - // The high part of YMM registers are saved in a their own area in the frame - baseReg = baseReg->next()->next()->next()->next(); - offset -= 16; - } - address baseLocation = location(baseReg); - if (baseLocation != NULL) { - return baseLocation + offset; + address base_location = location(base_reg); + if (base_location != NULL) { + return base_location + offset_in_bytes; } } return NULL; diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index 635ea4288c9..b73100f34c7 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -89,9 +89,10 @@ class RegisterSaver { #define XSAVE_AREA_YMM_BEGIN 576 #define XSAVE_AREA_ZMM_BEGIN 1152 #define XSAVE_AREA_UPPERBANK 1664 -#define DEF_XMM_OFFS(regnum) xmm ## regnum ## _off = xmm_off + (regnum)*16/BytesPerInt, xmm ## regnum ## H_off -#define DEF_YMM_OFFS(regnum) ymm ## regnum ## _off = ymm_off + (regnum)*16/BytesPerInt, ymm ## regnum ## H_off -#define DEF_ZMM_OFFS(regnum) zmm ## regnum ## _off = zmm_off + (regnum-16)*64/BytesPerInt, zmm ## regnum ## H_off +#define DEF_XMM_OFFS(regnum) xmm ## regnum ## _off = xmm_off + (regnum)*16/BytesPerInt, xmm ## regnum ## H_off +#define DEF_YMM_OFFS(regnum) ymm ## regnum ## _off = ymm_off + (regnum)*16/BytesPerInt, ymm ## regnum ## H_off +#define DEF_ZMM_OFFS(regnum) zmm ## regnum ## _off = zmm_off + (regnum)*32/BytesPerInt, zmm ## regnum ## H_off +#define DEF_ZMM_UPPER_OFFS(regnum) zmm ## regnum ## _off = zmm_upper_off + (regnum-16)*64/BytesPerInt, zmm ## regnum ## H_off enum layout { fpu_state_off = frame::arg_reg_save_area_bytes/BytesPerInt, // fxsave save area xmm_off = fpu_state_off + XSAVE_AREA_BEGIN/BytesPerInt, // offset in fxsave save area @@ -102,10 +103,12 @@ class RegisterSaver { DEF_YMM_OFFS(0), DEF_YMM_OFFS(1), // 2..15 are implied in range usage - zmm_high = xmm_off + (XSAVE_AREA_ZMM_BEGIN - XSAVE_AREA_BEGIN)/BytesPerInt, - zmm_off = xmm_off + (XSAVE_AREA_UPPERBANK - XSAVE_AREA_BEGIN)/BytesPerInt, - DEF_ZMM_OFFS(16), - DEF_ZMM_OFFS(17), + zmm_off = xmm_off + (XSAVE_AREA_ZMM_BEGIN - XSAVE_AREA_BEGIN)/BytesPerInt, + DEF_ZMM_OFFS(0), + DEF_ZMM_OFFS(1), + zmm_upper_off = xmm_off + (XSAVE_AREA_UPPERBANK - XSAVE_AREA_BEGIN)/BytesPerInt, + DEF_ZMM_UPPER_OFFS(16), + DEF_ZMM_UPPER_OFFS(17), // 18..31 are implied in range usage fpu_state_end = fpu_state_off + ((FPUStateSizeInWords-1)*wordSize / BytesPerInt), fpu_stateH_end, @@ -137,7 +140,7 @@ class RegisterSaver { }; public: - static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors = false); + static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors); static void restore_live_registers(MacroAssembler* masm, bool restore_vectors = false); // Offsets into the register save area @@ -162,12 +165,12 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ num_xmm_regs = num_xmm_regs/2; } #if COMPILER2_OR_JVMCI - if (save_vectors) { - assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX"); - assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); + if (save_vectors && UseAVX == 0) { + save_vectors = false; // vectors larger than 16 byte long are supported only with AVX } + assert(!save_vectors || MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); #else - assert(!save_vectors, "vectors are generated only by C2 and JVMCI"); + save_vectors = false; // vectors are generated only by C2 and JVMCI #endif // Always make the frame size 16-byte aligned, both vector and non vector stacks are always allocated @@ -259,7 +262,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg()); off += delta; } - if(UseAVX > 2) { + if (UseAVX > 2) { // Obtain xmm16..xmm31 from the XSAVE area on EVEX enabled targets off = zmm16_off; delta = zmm17_off - off; @@ -272,13 +275,24 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ #if COMPILER2_OR_JVMCI if (save_vectors) { + // Save upper half of YMM registers(0..15) off = ymm0_off; - int delta = ymm1_off - off; + delta = ymm1_off - ymm0_off; for (int n = 0; n < 16; n++) { XMMRegister ymm_name = as_XMMRegister(n); map->set_callee_saved(STACK_OFFSET(off), ymm_name->as_VMReg()->next(4)); off += delta; } + if (VM_Version::supports_evex()) { + // Save upper half of ZMM registers(0..15) + off = zmm0_off; + delta = zmm1_off - zmm0_off; + for (int n = 0; n < 16; n++) { + XMMRegister zmm_name = as_XMMRegister(n); + map->set_callee_saved(STACK_OFFSET(off), zmm_name->as_VMReg()->next(8)); + off += delta; + } + } } #endif // COMPILER2_OR_JVMCI @@ -2606,12 +2620,15 @@ void SharedRuntime::generate_deopt_blob() { ResourceMark rm; // Setup code generation tools int pad = 0; + if (UseAVX > 2) { + pad += 1024; + } #if INCLUDE_JVMCI if (EnableJVMCI || UseAOT) { pad += 512; // Increase the buffer size when compiling for JVMCI } #endif - CodeBuffer buffer("deopt_blob", 2048+pad, 1024); + CodeBuffer buffer("deopt_blob", 2560+pad, 1024); MacroAssembler* masm = new MacroAssembler(&buffer); int frame_size_in_words; OopMap* map = NULL; @@ -2653,7 +2670,7 @@ void SharedRuntime::generate_deopt_blob() { // Prolog for non exception case! // Save everything in sight. - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_vectors*/ true); // Normal deoptimization. Save exec mode for unpack_frames. __ movl(r14, Deoptimization::Unpack_deopt); // callee-saved @@ -2671,7 +2688,7 @@ void SharedRuntime::generate_deopt_blob() { // return address is the pc describes what bci to do re-execute at // No need to update map as each call to save_live_registers will produce identical oopmap - (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_vectors*/ true); __ movl(r14, Deoptimization::Unpack_reexecute); // callee-saved __ jmp(cont); @@ -2690,7 +2707,7 @@ void SharedRuntime::generate_deopt_blob() { uncommon_trap_offset = __ pc() - start; // Save everything in sight. - RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_vectors*/ true); // fetch_unroll_info needs to call last_java_frame() __ set_last_Java_frame(noreg, noreg, NULL); @@ -2737,7 +2754,7 @@ void SharedRuntime::generate_deopt_blob() { __ push(0); // Save everything in sight. - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_vectors*/ true); // Now it is safe to overwrite any register @@ -3339,7 +3356,8 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha int start = __ offset(); - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + // No need to save vector registers since they are caller-saved anyway. + map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_vectors*/ false); int frame_complete = __ offset(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index b028e6a9c9b..fd3b67de383 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -566,26 +566,6 @@ class StubGenerator: public StubCodeGenerator { return start; } - // Support for intptr_t get_previous_fp() - // - // This routine is used to find the previous frame pointer for the - // caller (current_frame_guess). This is used as part of debugging - // ps() is seemingly lost trying to find frames. - // This code assumes that caller current_frame_guess) has a frame. - address generate_get_previous_fp() { - StubCodeMark mark(this, "StubRoutines", "get_previous_fp"); - const Address old_fp(rbp, 0); - const Address older_fp(rax, 0); - address start = __ pc(); - - __ enter(); - __ movptr(rax, old_fp); // callers fp - __ movptr(rax, older_fp); // the frame for ps() - __ pop(rbp); - __ ret(0); - - return start; - } // Support for intptr_t get_previous_sp() // @@ -6717,7 +6697,6 @@ address generate_avx_ghash_processBlocks() { StubRoutines::_fence_entry = generate_orderaccess_fence(); // platform dependent - StubRoutines::x86::_get_previous_fp_entry = generate_get_previous_fp(); StubRoutines::x86::_get_previous_sp_entry = generate_get_previous_sp(); StubRoutines::x86::_verify_mxcsr_entry = generate_verify_mxcsr(); diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.hpp b/src/hotspot/cpu/x86/stubRoutines_x86.hpp index fa4c34016a5..84ae8a75b5a 100644 --- a/src/hotspot/cpu/x86/stubRoutines_x86.hpp +++ b/src/hotspot/cpu/x86/stubRoutines_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, 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 @@ -42,7 +42,6 @@ class x86 { #ifdef _LP64 private: - static address _get_previous_fp_entry; static address _get_previous_sp_entry; static address _f2i_fixup; @@ -57,10 +56,6 @@ class x86 { public: - static address get_previous_fp_entry() { - return _get_previous_fp_entry; - } - static address get_previous_sp_entry() { return _get_previous_sp_entry; } diff --git a/src/hotspot/cpu/x86/stubRoutines_x86_64.cpp b/src/hotspot/cpu/x86/stubRoutines_x86_64.cpp index b2821321630..03cd8838266 100644 --- a/src/hotspot/cpu/x86/stubRoutines_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubRoutines_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, 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,7 +31,6 @@ // Implementation of the platform-specific part of StubRoutines - for // a description of how to extend it, see the stubRoutines.hpp file. -address StubRoutines::x86::_get_previous_fp_entry = NULL; address StubRoutines::x86::_get_previous_sp_entry = NULL; address StubRoutines::x86::_f2i_fixup = NULL; diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp index 6394aa850cb..b7a9cb55156 100644 --- a/src/hotspot/os/posix/signals_posix.cpp +++ b/src/hotspot/os/posix/signals_posix.cpp @@ -47,6 +47,14 @@ // signal handling (except suspend/resume) // suspend/resume +// Glibc on Linux uses the SA_RESTORER flag to indicate +// the use of a "signal trampoline". We have no interest +// in this flag and need to ignore it when checking our +// own flag settings. +// Note: SA_RESTORER is not exposed through signal.h so we +// have to hardwire its 0x04000000 value in the mask. +LINUX_ONLY(const int SA_RESTORER_FLAG_MASK = ~0x04000000;) + // Todo: provide a os::get_max_process_id() or similar. Number of processes // may have been configured, can be read more accurately from proc fs etc. #ifndef MAX_PID @@ -657,9 +665,19 @@ static const char* describe_sa_flags(int flags, char* buffer, size_t size) { strncpy(buffer, "none", size); + const unsigned int unknown_flag = ~(SA_NOCLDSTOP | + SA_ONSTACK | + SA_NOCLDSTOP | + SA_RESTART | + SA_SIGINFO | + SA_NOCLDWAIT | + SA_NODEFER + AIX_ONLY(| SA_OLDSTYLE) + ); + const struct { // NB: i is an unsigned int here because SA_RESETHAND is on some - // systems 0x80000000, which is implicitly unsigned. Assignining + // systems 0x80000000, which is implicitly unsigned. Assigning // it to an int field would be an overflow in unsigned-to-signed // conversion. unsigned int i; @@ -675,10 +693,10 @@ static const char* describe_sa_flags(int flags, char* buffer, size_t size) { #if defined(AIX) { SA_OLDSTYLE, "SA_OLDSTYLE" }, #endif - { 0, NULL } + { unknown_flag, "NOT USED" } }; - for (idx = 0; flaginfo[idx].s && remaining > 1; idx++) { + for (idx = 0; flaginfo[idx].i != unknown_flag && remaining > 1; idx++) { if (flags & flaginfo[idx].i) { if (first) { jio_snprintf(p, remaining, "%s", flaginfo[idx].s); @@ -691,6 +709,10 @@ static const char* describe_sa_flags(int flags, char* buffer, size_t size) { remaining -= len; } } + unsigned int unknowns = flags & unknown_flag; + if (unknowns != 0) { + jio_snprintf(p, remaining, "|Unknown_flags:%x", unknowns); + } buffer[size - 1] = '\0'; @@ -734,6 +756,9 @@ static void check_signal_handler(int sig) { os_sigaction(sig, (struct sigaction*)NULL, &act); + // See comment for SA_RESTORER_FLAG_MASK + LINUX_ONLY(act.sa_flags &= SA_RESTORER_FLAG_MASK;) + address thisHandler = (act.sa_flags & SA_SIGINFO) ? CAST_FROM_FN_PTR(address, act.sa_sigaction) : CAST_FROM_FN_PTR(address, act.sa_handler); @@ -1310,6 +1335,9 @@ void PosixSignals::print_signal_handler(outputStream* st, int sig, struct sigaction sa; sigaction(sig, NULL, &sa); + // See comment for SA_RESTORER_FLAG_MASK + LINUX_ONLY(sa.sa_flags &= SA_RESTORER_FLAG_MASK;) + st->print("%s: ", os::exception_name(sig, buf, buflen)); address handler = (sa.sa_flags & SA_SIGINFO) @@ -1331,7 +1359,8 @@ void PosixSignals::print_signal_handler(outputStream* st, int sig, // May be, handler was resetted by VMError? if (rh != NULL) { handler = rh; - sa.sa_flags = VMError::get_resetted_sigflags(sig); + // See comment for SA_RESTORER_FLAG_MASK + sa.sa_flags = VMError::get_resetted_sigflags(sig) LINUX_ONLY(& SA_RESTORER_FLAG_MASK); } // Print textual representation of sa_flags. diff --git a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp index 0a61ef0e95f..d94ca5d4707 100644 --- a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp +++ b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp @@ -142,32 +142,14 @@ bool os::win32::get_frame_at_stack_banging_point(JavaThread* thread, return true; } -// By default, gcc always saves frame pointer rfp on this stack. This -// may get turned off by -fomit-frame-pointer. frame os::get_sender_for_C_frame(frame* fr) { - return frame(fr->link(), fr->link(), fr->sender_pc()); + ShouldNotReachHere(); + return frame(); } frame os::current_frame() { - typedef intptr_t* get_fp_func (); - get_fp_func* func = CAST_TO_FN_PTR(get_fp_func*, - StubRoutines::aarch64::get_previous_fp_entry()); - if (func == NULL) return frame(); - intptr_t* fp = (*func)(); - if (fp == NULL) { - return frame(); - } - - frame myframe((intptr_t*)os::current_stack_pointer(), - (intptr_t*)fp, - CAST_FROM_FN_PTR(address, os::current_frame)); - if (os::is_first_C_frame(&myframe)) { - - // stack is not walkable - return frame(); - } else { - return os::get_sender_for_C_frame(&myframe); - } + return frame(); // cannot walk Windows frames this way. See os::get_native_stack + // and os::platform_print_native_stack } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp index 0543463b68d..8afd5aeeb04 100644 --- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp @@ -323,13 +323,6 @@ frame os::fetch_frame_from_context(const void* ucVoid) { return frame(sp, fp, epc); } -// VC++ does not save frame pointer on stack in optimized build. It -// can be turned off by /Oy-. If we really want to walk C frames, -// we can use the StackWalk() API. -frame os::get_sender_for_C_frame(frame* fr) { - return frame(fr->sender_sp(), fr->link(), fr->sender_pc()); -} - #ifndef AMD64 // Ignore "C4172: returning address of local variable or temporary" on 32bit PRAGMA_DIAG_PUSH @@ -390,49 +383,18 @@ bool os::win32::get_frame_at_stack_banging_point(JavaThread* thread, return true; } -#ifndef AMD64 -intptr_t* _get_previous_fp() { - intptr_t **frameptr; - __asm { - mov frameptr, ebp - }; - // ebp (frameptr) is for this frame (_get_previous_fp). We want the ebp for the - // caller of os::current_frame*(), so go up two frames. However, for - // optimized builds, _get_previous_fp() will be inlined, so only go - // up 1 frame in that case. -#ifdef _NMT_NOINLINE_ - return **(intptr_t***)frameptr; -#else - return *frameptr; -#endif + +// VC++ does not save frame pointer on stack in optimized build. It +// can be turned off by /Oy-. If we really want to walk C frames, +// we can use the StackWalk() API. +frame os::get_sender_for_C_frame(frame* fr) { + ShouldNotReachHere(); + return frame(); } -#endif // !AMD64 frame os::current_frame() { - -#ifdef AMD64 - // apparently _asm not supported on windows amd64 - typedef intptr_t* get_fp_func (); - get_fp_func* func = CAST_TO_FN_PTR(get_fp_func*, - StubRoutines::x86::get_previous_fp_entry()); - if (func == NULL) return frame(); - intptr_t* fp = (*func)(); - if (fp == NULL) { - return frame(); - } -#else - intptr_t* fp = _get_previous_fp(); -#endif // AMD64 - - frame myframe((intptr_t*)os::current_stack_pointer(), - (intptr_t*)fp, - CAST_FROM_FN_PTR(address, os::current_frame)); - if (os::is_first_C_frame(&myframe)) { - // stack is not walkable - return frame(); - } else { - return os::get_sender_for_C_frame(&myframe); - } + return frame(); // cannot walk Windows frames this way. See os::get_native_stack + // and os::platform_print_native_stack } void os::print_context(outputStream *st, const void *context) { diff --git a/src/hotspot/share/gc/shared/ptrQueue.hpp b/src/hotspot/share/gc/shared/ptrQueue.hpp index 261c702e10c..472608d1045 100644 --- a/src/hotspot/share/gc/shared/ptrQueue.hpp +++ b/src/hotspot/share/gc/shared/ptrQueue.hpp @@ -178,7 +178,7 @@ class PtrQueue { return byte_offset_of(Derived, _index); } - static ByteSize byte_width_of_index() { return in_ByteSize(sizeof(size_t)); } + static constexpr ByteSize byte_width_of_index() { return in_ByteSize(sizeof(size_t)); } template static ByteSize byte_offset_of_buf() { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index a0c99af2d37..edba82e3886 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -1690,7 +1690,9 @@ void ShenandoahHeap::op_final_mark() { // Notify JVMTI that the tagmap table will need cleaning. JvmtiTagMap::set_needs_cleaning(); - parallel_cleaning(false /* full gc*/); + if (is_degenerated_gc_in_progress()) { + parallel_cleaning(false /* full gc*/); + } if (ShenandoahVerify) { verifier()->verify_roots_no_forwarded(); @@ -1761,10 +1763,8 @@ void ShenandoahHeap::op_final_mark() { if (ShenandoahVerify) { // If OOM while evacuating/updating of roots, there is no guarantee of their consistencies if (!cancelled_gc()) { - // We only evacuate/update thread and serial weak roots at this pause - ShenandoahRootVerifier::RootTypes types = ShenandoahRootVerifier::combine(ShenandoahRootVerifier::ThreadRoots, - ShenandoahRootVerifier::SerialWeakRoots); - verifier()->verify_roots_no_forwarded(types); + // We only evacuate/update thread roots at this pause + verifier()->verify_roots_no_forwarded(ShenandoahRootVerifier::ThreadRoots); } verifier()->verify_during_evacuation(); } @@ -1851,6 +1851,9 @@ class ShenandoahEvacUpdateCodeCacheClosure : public NMethodClosure { void do_nmethod(nmethod* n) { ShenandoahNMethod* data = ShenandoahNMethod::gc_data(n); ShenandoahReentrantLocker locker(data->lock()); + // Setup EvacOOM scope below reentrant lock to avoid deadlock with + // nmethod_entry_barrier + ShenandoahEvacOOMScope oom; data->oops_do(&_cl, true/*fix relocation*/); _bs->disarm(n); } @@ -1887,20 +1890,23 @@ class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask { void work(uint worker_id) { ShenandoahConcurrentWorkerSession worker_session(worker_id); - ShenandoahEvacOOMScope oom; { - // vm_roots and weak_roots are OopStorage backed roots, concurrent iteration - // may race against OopStorage::release() calls. - ShenandoahEvacUpdateOopStorageRootsClosure cl; - _vm_roots.oops_do(&cl, worker_id); - } + ShenandoahEvacOOMScope oom; + { + // vm_roots and weak_roots are OopStorage backed roots, concurrent iteration + // may race against OopStorage::release() calls. + ShenandoahEvacUpdateOopStorageRootsClosure cl; + _vm_roots.oops_do(&cl, worker_id); + } - { - ShenandoahEvacuateUpdateRootsClosure<> cl; - CLDToOopClosure clds(&cl, ClassLoaderData::_claim_strong); - _cld_roots.cld_do(&clds, worker_id); + { + ShenandoahEvacuateUpdateRootsClosure<> cl; + CLDToOopClosure clds(&cl, ClassLoaderData::_claim_strong); + _cld_roots.cld_do(&clds, worker_id); + } } + // Cannot setup ShenandoahEvacOOMScope here, due to potential deadlock with nmethod_entry_barrier. if (_process_codecache) { ShenandoahWorkerTimingsTracker timer(_phase, ShenandoahPhaseTimings::CodeCacheRoots, worker_id); ShenandoahEvacUpdateCodeCacheClosure cl; @@ -1991,9 +1997,13 @@ class ShenandoahConcurrentWeakRootsEvacUpdateTask : public AbstractGangTask { MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); _nmethod_itr.nmethods_do_begin(); } + + _dedup_roots.prologue(); } ~ShenandoahConcurrentWeakRootsEvacUpdateTask() { + _dedup_roots.epilogue(); + if (_concurrent_class_unloading) { MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); _nmethod_itr.nmethods_do_end(); @@ -2411,12 +2421,11 @@ void ShenandoahHeap::stop() { void ShenandoahHeap::stw_unload_classes(bool full_gc) { if (!unload_classes()) return; - // Unload classes and purge SystemDictionary. { ShenandoahGCPhase phase(full_gc ? ShenandoahPhaseTimings::full_gc_purge_class_unload : - ShenandoahPhaseTimings::purge_class_unload); + ShenandoahPhaseTimings::degen_gc_purge_class_unload); bool purged_class = SystemDictionary::do_unloading(gc_timer()); ShenandoahIsAliveSelector is_alive; @@ -2428,7 +2437,7 @@ void ShenandoahHeap::stw_unload_classes(bool full_gc) { { ShenandoahGCPhase phase(full_gc ? ShenandoahPhaseTimings::full_gc_purge_cldg : - ShenandoahPhaseTimings::purge_cldg); + ShenandoahPhaseTimings::degen_gc_purge_cldg); ClassLoaderDataGraph::purge(/*at_safepoint*/true); } // Resize and verify metaspace @@ -2443,11 +2452,11 @@ void ShenandoahHeap::stw_unload_classes(bool full_gc) { void ShenandoahHeap::stw_process_weak_roots(bool full_gc) { ShenandoahGCPhase root_phase(full_gc ? ShenandoahPhaseTimings::full_gc_purge : - ShenandoahPhaseTimings::purge); + ShenandoahPhaseTimings::degen_gc_purge); uint num_workers = _workers->active_workers(); ShenandoahPhaseTimings::Phase timing_phase = full_gc ? ShenandoahPhaseTimings::full_gc_purge_weak_par : - ShenandoahPhaseTimings::purge_weak_par; + ShenandoahPhaseTimings::degen_gc_purge_weak_par; ShenandoahGCPhase phase(timing_phase); ShenandoahGCWorkerPhase worker_phase(timing_phase); @@ -2456,17 +2465,17 @@ void ShenandoahHeap::stw_process_weak_roots(bool full_gc) { ShenandoahForwardedIsAliveClosure is_alive; ShenandoahUpdateRefsClosure keep_alive; ShenandoahParallelWeakRootsCleaningTask - cleaning_task(timing_phase, &is_alive, &keep_alive, num_workers, is_stw_gc_in_progress()); + cleaning_task(timing_phase, &is_alive, &keep_alive, num_workers); _workers->run_task(&cleaning_task); } else { ShenandoahIsAliveClosure is_alive; #ifdef ASSERT ShenandoahAssertNotForwardedClosure verify_cl; ShenandoahParallelWeakRootsCleaningTask - cleaning_task(timing_phase, &is_alive, &verify_cl, num_workers, is_stw_gc_in_progress()); + cleaning_task(timing_phase, &is_alive, &verify_cl, num_workers); #else ShenandoahParallelWeakRootsCleaningTask - cleaning_task(timing_phase, &is_alive, &do_nothing_cl, num_workers, is_stw_gc_in_progress()); + cleaning_task(timing_phase, &is_alive, &do_nothing_cl, num_workers); #endif _workers->run_task(&cleaning_task); } @@ -2474,10 +2483,9 @@ void ShenandoahHeap::stw_process_weak_roots(bool full_gc) { void ShenandoahHeap::parallel_cleaning(bool full_gc) { assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); + assert(is_stw_gc_in_progress(), "Only for Degenerated and Full GC"); stw_process_weak_roots(full_gc); - if (!ShenandoahConcurrentRoots::should_do_concurrent_class_unloading()) { - stw_unload_classes(full_gc); - } + stw_unload_classes(full_gc); } void ShenandoahHeap::set_has_forwarded_objects(bool cond) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahParallelCleaning.hpp b/src/hotspot/share/gc/shenandoah/shenandoahParallelCleaning.hpp index 2e7309a1301..bb85fd73bc5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahParallelCleaning.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahParallelCleaning.hpp @@ -40,14 +40,12 @@ class ShenandoahParallelWeakRootsCleaningTask : public AbstractGangTask { WeakProcessor::Task _weak_processing_task; IsAlive* _is_alive; KeepAlive* _keep_alive; - bool _include_concurrent_roots; public: ShenandoahParallelWeakRootsCleaningTask(ShenandoahPhaseTimings::Phase phase, IsAlive* is_alive, KeepAlive* keep_alive, - uint num_workers, - bool include_concurrent_roots); + uint num_workers); ~ShenandoahParallelWeakRootsCleaningTask(); void work(uint worker_id); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahParallelCleaning.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahParallelCleaning.inline.hpp index 1b0859d4392..27e916b4f71 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahParallelCleaning.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahParallelCleaning.inline.hpp @@ -36,11 +36,10 @@ template ShenandoahParallelWeakRootsCleaningTask::ShenandoahParallelWeakRootsCleaningTask(ShenandoahPhaseTimings::Phase phase, IsAlive* is_alive, KeepAlive* keep_alive, - uint num_workers, - bool include_concurrent_roots) : + uint num_workers) : AbstractGangTask("Shenandoah Weak Root Cleaning"), _phase(phase), _weak_processing_task(num_workers), - _is_alive(is_alive), _keep_alive(keep_alive), _include_concurrent_roots(include_concurrent_roots) { + _is_alive(is_alive), _keep_alive(keep_alive) { assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); if (ShenandoahStringDedup::is_enabled()) { @@ -53,16 +52,12 @@ ShenandoahParallelWeakRootsCleaningTask::~ShenandoahParallel if (StringDedup::is_enabled()) { StringDedup::gc_epilogue(); } - if (_include_concurrent_roots) { - _weak_processing_task.report_num_dead(); - } + _weak_processing_task.report_num_dead(); } template void ShenandoahParallelWeakRootsCleaningTask::work(uint worker_id) { - if (_include_concurrent_roots) { - _weak_processing_task.work(worker_id, _is_alive, _keep_alive); - } + _weak_processing_task.work(worker_id, _is_alive, _keep_alive); if (ShenandoahStringDedup::is_enabled()) { ShenandoahStringDedup::parallel_oops_do(_phase, _is_alive, _keep_alive, worker_id); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp index b65746c3791..08c1672c908 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp @@ -108,8 +108,8 @@ bool ShenandoahPhaseTimings::is_worker_phase(Phase phase) { case full_gc_scan_conc_roots: case full_gc_purge_class_unload: case full_gc_purge_weak_par: - case purge_class_unload: - case purge_weak_par: + case degen_gc_purge_class_unload: + case degen_gc_purge_weak_par: case heap_iteration_roots: case conc_mark_roots: case conc_weak_roots_work: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp index 200429898d7..07c3393f38f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp @@ -66,12 +66,6 @@ class outputStream; f(finish_queues, " Finish Queues") \ f(weakrefs, " Weak References") \ f(weakrefs_process, " Process") \ - f(purge, " System Purge") \ - f(purge_class_unload, " Unload Classes") \ - SHENANDOAH_PAR_PHASE_DO(purge_cu_par_, " CU: ", f) \ - f(purge_weak_par, " Weak Roots") \ - SHENANDOAH_PAR_PHASE_DO(purge_weak_par_, " WR: ", f) \ - f(purge_cldg, " CLDG") \ f(final_update_region_states, " Update Region States") \ f(final_manage_labs, " Manage GC/TLABs") \ f(choose_cset, " Choose Collection Set") \ @@ -124,6 +118,12 @@ class outputStream; f(degen_gc, "Pause Degenerated GC (N)") \ f(degen_gc_scan_conc_roots, " Degen Mark Roots") \ SHENANDOAH_PAR_PHASE_DO(degen_gc_conc_mark_, " DM: ", f) \ + f(degen_gc_purge, " System Purge") \ + f(degen_gc_purge_class_unload, " Unload Classes") \ + SHENANDOAH_PAR_PHASE_DO(degen_gc_purge_cu_par_, " DCU: ", f) \ + f(degen_gc_purge_weak_par, " Weak Roots") \ + SHENANDOAH_PAR_PHASE_DO(degen_gc_purge_weak_p_, " DWR: ", f) \ + f(degen_gc_purge_cldg, " CLDG") \ f(degen_gc_update_roots, " Degen Update Roots") \ SHENANDOAH_PAR_PHASE_DO(degen_gc_update_, " DU: ", f) \ \ diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp index 6653279a6ad..3962c2f19ee 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp @@ -78,6 +78,9 @@ void ShenandoahStringDedupRoots::oops_do(BoolObjectClosure* is_alive, OopClosure ShenandoahConcurrentStringDedupRoots::ShenandoahConcurrentStringDedupRoots(ShenandoahPhaseTimings::Phase phase) : _phase(phase) { +} + +void ShenandoahConcurrentStringDedupRoots::prologue() { if (ShenandoahStringDedup::is_enabled()) { StringDedupTable_lock->lock_without_safepoint_check(); StringDedupQueue_lock->lock_without_safepoint_check(); @@ -85,7 +88,7 @@ ShenandoahConcurrentStringDedupRoots::ShenandoahConcurrentStringDedupRoots(Shena } } -ShenandoahConcurrentStringDedupRoots::~ShenandoahConcurrentStringDedupRoots() { +void ShenandoahConcurrentStringDedupRoots::epilogue() { if (ShenandoahStringDedup::is_enabled()) { StringDedup::gc_epilogue(); StringDedupQueue_lock->unlock(); @@ -169,8 +172,6 @@ void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) { // Always disarm on-stack nmethods, because we are evacuating/updating them // here ShenandoahCodeBlobAndDisarmClosure codeblob_cl(oops); - - // Process light-weight/limited parallel roots then _thread_roots.oops_do(oops, &codeblob_cl, worker_id); } @@ -223,8 +224,13 @@ ShenandoahHeapIterationRootScanner::ShenandoahHeapIterationRootScanner() : _weak_roots(ShenandoahPhaseTimings::heap_iteration_roots), _dedup_roots(ShenandoahPhaseTimings::heap_iteration_roots), _code_roots(ShenandoahPhaseTimings::heap_iteration_roots) { + _dedup_roots.prologue(); } +ShenandoahHeapIterationRootScanner::~ShenandoahHeapIterationRootScanner() { + _dedup_roots.epilogue(); +} + void ShenandoahHeapIterationRootScanner::roots_do(OopClosure* oops) { assert(Thread::current()->is_VM_thread(), "Only by VM thread"); // Must use _claim_none to avoid interfering with concurrent CLDG iteration diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp index 3b0a998a987..fad0c8d42d5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp @@ -93,7 +93,9 @@ class ShenandoahConcurrentStringDedupRoots { public: ShenandoahConcurrentStringDedupRoots(ShenandoahPhaseTimings::Phase phase); - ~ShenandoahConcurrentStringDedupRoots(); + + void prologue(); + void epilogue(); void oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id); }; @@ -191,6 +193,7 @@ class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor { public: ShenandoahHeapIterationRootScanner(); + ~ShenandoahHeapIterationRootScanner(); void roots_do(OopClosure* cl); }; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp index f274612b4f8..2aa72365de9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp @@ -99,9 +99,7 @@ void ShenandoahRootVerifier::oops_do(OopClosure* oops) { if (verify(WeakRoots)) { shenandoah_assert_safepoint(); - concurrent_weak_roots_do(oops); - } else if (verify(ConcurrentWeakRoots)) { - concurrent_weak_roots_do(oops); + weak_roots_do(oops); } if (ShenandoahStringDedup::is_enabled() && verify(StringDedupRoots)) { @@ -155,7 +153,7 @@ void ShenandoahRootVerifier::strong_roots_do(OopClosure* oops) { Threads::possibly_parallel_oops_do(true, oops, &blobs); } -void ShenandoahRootVerifier::concurrent_weak_roots_do(OopClosure* cl) { +void ShenandoahRootVerifier::weak_roots_do(OopClosure* cl) { for (OopStorageSet::Iterator it = OopStorageSet::weak_iterator(); !it.is_end(); ++it) { OopStorage* storage = *it; storage->oops_do(cl); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp index 23d0545471b..d79624f6f37 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp @@ -47,11 +47,9 @@ class ShenandoahRootVerifier : public StackObj { ThreadRoots = 1 << 1, CodeRoots = 1 << 2, CLDGRoots = 1 << 3, - SerialWeakRoots = 1 << 4, - ConcurrentWeakRoots = 1 << 5, - WeakRoots = (SerialWeakRoots | ConcurrentWeakRoots), - StringDedupRoots = 1 << 6, - JNIHandleRoots = 1 << 7, + WeakRoots = 1 << 4, + StringDedupRoots = 1 << 5, + JNIHandleRoots = 1 << 6, AllRoots = (SerialRoots | ThreadRoots | CodeRoots | CLDGRoots | WeakRoots | StringDedupRoots | JNIHandleRoots) }; @@ -72,7 +70,7 @@ class ShenandoahRootVerifier : public StackObj { private: bool verify(RootTypes type) const; - void concurrent_weak_roots_do(OopClosure* cl); + void weak_roots_do(OopClosure* cl); }; #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTVERIFIER_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp index a499a9556b0..4e4ba4c696d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp @@ -715,19 +715,6 @@ void ShenandoahVerifier::verify_at_safepoint(const char *label, size_t count_reachable = 0; if (ShenandoahVerifyLevel >= 2) { ShenandoahRootVerifier verifier; - switch (weak_roots) { - case _verify_serial_weak_roots: - verifier.excludes(ShenandoahRootVerifier::ConcurrentWeakRoots); - break; - case _verify_concurrent_weak_roots: - verifier.excludes(ShenandoahRootVerifier::SerialWeakRoots); - break; - case _verify_all_weak_roots: - break; - default: - ShouldNotReachHere(); - } - ShenandoahVerifierReachableTask task(_verification_bit_map, ld, &verifier, label, options); _heap->workers()->run_task(&task); count_reachable = task.processed(); diff --git a/src/hotspot/share/gc/z/zBarrier.cpp b/src/hotspot/share/gc/z/zBarrier.cpp index 3200b2ab0c3..970a3979a27 100644 --- a/src/hotspot/share/gc/z/zBarrier.cpp +++ b/src/hotspot/share/gc/z/zBarrier.cpp @@ -198,25 +198,6 @@ uintptr_t ZBarrier::mark_barrier_on_finalizable_oop_slow_path(uintptr_t addr) { return mark(addr); } -uintptr_t ZBarrier::mark_barrier_on_root_oop_slow_path(uintptr_t addr) { - assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); - assert(during_mark(), "Invalid phase"); - - // Mark - return mark(addr); -} - -// -// Relocate barrier -// -uintptr_t ZBarrier::relocate_barrier_on_root_oop_slow_path(uintptr_t addr) { - assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); - assert(during_relocate(), "Invalid phase"); - - // Relocate - return relocate(addr); -} - // // Narrow oop variants, never used. // diff --git a/src/hotspot/share/gc/z/zBarrier.hpp b/src/hotspot/share/gc/z/zBarrier.hpp index c3ab96dc5d9..0043f87988e 100644 --- a/src/hotspot/share/gc/z/zBarrier.hpp +++ b/src/hotspot/share/gc/z/zBarrier.hpp @@ -73,9 +73,6 @@ class ZBarrier : public AllStatic { static uintptr_t mark_barrier_on_oop_slow_path(uintptr_t addr); static uintptr_t mark_barrier_on_finalizable_oop_slow_path(uintptr_t addr); - static uintptr_t mark_barrier_on_root_oop_slow_path(uintptr_t addr); - - static uintptr_t relocate_barrier_on_root_oop_slow_path(uintptr_t addr); public: // Load barrier @@ -112,12 +109,8 @@ class ZBarrier : public AllStatic { // Mark barrier static void mark_barrier_on_oop_field(volatile oop* p, bool finalizable); static void mark_barrier_on_oop_array(volatile oop* p, size_t length, bool finalizable); - static void mark_barrier_on_root_oop_field(oop* p); static void mark_barrier_on_invisible_root_oop_field(oop* p); - // Relocate barrier - static void relocate_barrier_on_root_oop_field(oop* p); - // Narrow oop variants, never used. static oop load_barrier_on_oop_field(volatile narrowOop* p); static oop load_barrier_on_oop_field_preloaded(volatile narrowOop* p, oop o); diff --git a/src/hotspot/share/gc/z/zBarrier.inline.hpp b/src/hotspot/share/gc/z/zBarrier.inline.hpp index ed12ed44c0e..47210c92cdb 100644 --- a/src/hotspot/share/gc/z/zBarrier.inline.hpp +++ b/src/hotspot/share/gc/z/zBarrier.inline.hpp @@ -407,17 +407,4 @@ inline void ZBarrier::mark_barrier_on_oop_array(volatile oop* p, size_t length, } } -inline void ZBarrier::mark_barrier_on_root_oop_field(oop* p) { - const oop o = *p; - root_barrier(p, o); -} - -// -// Relocate barrier -// -inline void ZBarrier::relocate_barrier_on_root_oop_field(oop* p) { - const oop o = *p; - root_barrier(p, o); -} - #endif // SHARE_GC_Z_ZBARRIER_INLINE_HPP diff --git a/src/hotspot/share/gc/z/zGlobals.hpp b/src/hotspot/share/gc/z/zGlobals.hpp index 2721e4ec3e8..300f6489af5 100644 --- a/src/hotspot/share/gc/z/zGlobals.hpp +++ b/src/hotspot/share/gc/z/zGlobals.hpp @@ -153,6 +153,6 @@ const size_t ZMarkProactiveFlushMax = 10; const size_t ZMarkTerminateFlushMax = 3; // Try complete mark timeout -const uint64_t ZMarkCompleteTimeout = 1000; // us +const uint64_t ZMarkCompleteTimeout = 200; // us #endif // SHARE_GC_Z_ZGLOBALS_HPP diff --git a/src/hotspot/share/gc/z/zOopClosures.hpp b/src/hotspot/share/gc/z/zOopClosures.hpp index 48dab73aa53..32aa98a8a95 100644 --- a/src/hotspot/share/gc/z/zOopClosures.hpp +++ b/src/hotspot/share/gc/z/zOopClosures.hpp @@ -25,7 +25,6 @@ #define SHARE_GC_Z_ZOOPCLOSURES_HPP #include "memory/iterator.hpp" -#include "gc/z/zRootsIterator.hpp" class ZLoadBarrierOopClosure : public BasicOopIterateClosure { public: @@ -53,11 +52,6 @@ class ZPhantomIsAliveObjectClosure : public BoolObjectClosure { virtual bool do_object_b(oop o); }; -class ZPhantomKeepAliveOopClosure : public OopClosure { -public: - virtual void do_oop(oop* p); - virtual void do_oop(narrowOop* p); -}; class ZPhantomCleanOopClosure : public OopClosure { public: virtual void do_oop(oop* p); diff --git a/src/hotspot/share/gc/z/zOopClosures.inline.hpp b/src/hotspot/share/gc/z/zOopClosures.inline.hpp index da8f22ff9d8..693e3da5e1b 100644 --- a/src/hotspot/share/gc/z/zOopClosures.inline.hpp +++ b/src/hotspot/share/gc/z/zOopClosures.inline.hpp @@ -76,14 +76,6 @@ inline bool ZPhantomIsAliveObjectClosure::do_object_b(oop o) { return ZBarrier::is_alive_barrier_on_phantom_oop(o); } -inline void ZPhantomKeepAliveOopClosure::do_oop(oop* p) { - ZBarrier::keep_alive_barrier_on_phantom_oop_field(p); -} - -inline void ZPhantomKeepAliveOopClosure::do_oop(narrowOop* p) { - ShouldNotReachHere(); -} - inline void ZPhantomCleanOopClosure::do_oop(oop* p) { // Read the oop once, to make sure the liveness check // and the later clearing uses the same value. diff --git a/src/hotspot/share/gc/z/zRelocate.cpp b/src/hotspot/share/gc/z/zRelocate.cpp index b5be3053944..08414627b2b 100644 --- a/src/hotspot/share/gc/z/zRelocate.cpp +++ b/src/hotspot/share/gc/z/zRelocate.cpp @@ -25,8 +25,7 @@ #include "gc/z/zAddress.inline.hpp" #include "gc/z/zBarrier.inline.hpp" #include "gc/z/zForwarding.inline.hpp" -#include "gc/z/zHeap.hpp" -#include "gc/z/zOopClosures.inline.hpp" +#include "gc/z/zHeap.inline.hpp" #include "gc/z/zPage.inline.hpp" #include "gc/z/zRelocate.hpp" #include "gc/z/zRelocationSet.inline.hpp" @@ -39,22 +38,10 @@ #include "prims/jvmtiTagMap.hpp" static const ZStatCounter ZCounterRelocationContention("Contention", "Relocation Contention", ZStatUnitOpsPerSecond); -static const ZStatSubPhase ZSubPhasePauseRootsJVMTITagMap("Pause Roots JVMTITagMap"); ZRelocate::ZRelocate(ZWorkers* workers) : _workers(workers) {} -class ZRelocateRootsIteratorClosure : public OopClosure { -public: - virtual void do_oop(oop* p) { - ZBarrier::relocate_barrier_on_root_oop_field(p); - } - - virtual void do_oop(narrowOop* p) { - ShouldNotReachHere(); - } -}; - uintptr_t ZRelocate::relocate_object_inner(ZForwarding* forwarding, uintptr_t from_index, uintptr_t from_offset) const { ZForwardingCursor cursor; diff --git a/src/hotspot/share/gc/z/zStackWatermark.hpp b/src/hotspot/share/gc/z/zStackWatermark.hpp index dc657aaa7cf..43d1cf57d2a 100644 --- a/src/hotspot/share/gc/z/zStackWatermark.hpp +++ b/src/hotspot/share/gc/z/zStackWatermark.hpp @@ -26,6 +26,7 @@ #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetNMethod.hpp" +#include "gc/shared/threadLocalAllocBuffer.hpp" #include "gc/z/zOopClosures.hpp" #include "memory/allocation.hpp" #include "memory/iterator.hpp" diff --git a/src/hotspot/share/gc/z/zWeakRootsProcessor.cpp b/src/hotspot/share/gc/z/zWeakRootsProcessor.cpp index b492cdf9078..f0a47cf8bef 100644 --- a/src/hotspot/share/gc/z/zWeakRootsProcessor.cpp +++ b/src/hotspot/share/gc/z/zWeakRootsProcessor.cpp @@ -23,6 +23,7 @@ #include "precompiled.hpp" #include "gc/z/zOopClosures.inline.hpp" +#include "gc/z/zRootsIterator.hpp" #include "gc/z/zTask.hpp" #include "gc/z/zWorkers.hpp" diff --git a/src/hotspot/share/gc/z/zWeakRootsProcessor.hpp b/src/hotspot/share/gc/z/zWeakRootsProcessor.hpp index 1f295a47b20..5233042e7fa 100644 --- a/src/hotspot/share/gc/z/zWeakRootsProcessor.hpp +++ b/src/hotspot/share/gc/z/zWeakRootsProcessor.hpp @@ -33,7 +33,6 @@ class ZWeakRootsProcessor { public: ZWeakRootsProcessor(ZWorkers* workers); - void process_weak_roots(); void process_concurrent_weak_roots(); }; diff --git a/src/hotspot/share/memory/metaspace/chunkManager.cpp b/src/hotspot/share/memory/metaspace/chunkManager.cpp index 7be0a2e2626..130c7c22deb 100644 --- a/src/hotspot/share/memory/metaspace/chunkManager.cpp +++ b/src/hotspot/share/memory/metaspace/chunkManager.cpp @@ -382,12 +382,23 @@ ChunkManager* ChunkManager::chunkmanager_nonclass() { return MetaspaceContext::context_nonclass() == NULL ? NULL : MetaspaceContext::context_nonclass()->cm(); } +// Calculates the total number of committed words over all chunks. Walks chunks. +size_t ChunkManager::calc_committed_word_size() const { + MutexLocker fcl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag); + return calc_committed_word_size_locked(); +} + +size_t ChunkManager::calc_committed_word_size_locked() const { + assert_lock_strong(MetaspaceExpand_lock); + return _chunks.calc_committed_word_size(); +} + // Update statistics. void ChunkManager::add_to_statistics(ChunkManagerStats* out) const { MutexLocker fcl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag); for (chunklevel_t l = chunklevel::ROOT_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l++) { out->_num_chunks[l] += _chunks.num_chunks_at_level(l); - out->_committed_word_size[l] += _chunks.committed_word_size_at_level(l); + out->_committed_word_size[l] += _chunks.calc_committed_word_size_at_level(l); } DEBUG_ONLY(out->verify();) } @@ -418,8 +429,8 @@ void ChunkManager::print_on(outputStream* st) const { void ChunkManager::print_on_locked(outputStream* st) const { assert_lock_strong(MetaspaceExpand_lock); - st->print_cr("cm %s: %d chunks, total word size: " SIZE_FORMAT ", committed word size: " SIZE_FORMAT, _name, - total_num_chunks(), total_word_size(), _chunks.committed_word_size()); + st->print_cr("cm %s: %d chunks, total word size: " SIZE_FORMAT ".", _name, + total_num_chunks(), total_word_size()); _chunks.print_on(st); } diff --git a/src/hotspot/share/memory/metaspace/chunkManager.hpp b/src/hotspot/share/memory/metaspace/chunkManager.hpp index ffc5113fd23..93fe40c818a 100644 --- a/src/hotspot/share/memory/metaspace/chunkManager.hpp +++ b/src/hotspot/share/memory/metaspace/chunkManager.hpp @@ -107,6 +107,9 @@ class ChunkManager : public CHeapObj { // See return_chunk(). void return_chunk_locked(Metachunk* c); + // Calculates the total number of committed words over all chunks. Walks chunks. + size_t calc_committed_word_size_locked() const; + public: // Creates a chunk manager with a given name (which is for debug purposes only) @@ -167,8 +170,8 @@ class ChunkManager : public CHeapObj { // Returns number of words in all free chunks (regardless of commit state). size_t total_word_size() const { return _chunks.word_size(); } - // Returns number of committed words in all free chunks. - size_t total_committed_word_size() const { return _chunks.committed_word_size(); } + // Calculates the total number of committed words over all chunks. Walks chunks. + size_t calc_committed_word_size() const; // Update statistics. void add_to_statistics(ChunkManagerStats* out) const; diff --git a/src/hotspot/share/memory/metaspace/freeChunkList.cpp b/src/hotspot/share/memory/metaspace/freeChunkList.cpp index 90dec13c16f..7c06c003e3a 100644 --- a/src/hotspot/share/memory/metaspace/freeChunkList.cpp +++ b/src/hotspot/share/memory/metaspace/freeChunkList.cpp @@ -31,6 +31,15 @@ namespace metaspace { +// Calculates total number of committed words over all chunks (walks chunks). +size_t FreeChunkList::calc_committed_word_size() const { + size_t s = 0; + for (const Metachunk* c = _first; c != NULL; c = c->next()) { + s += c->committed_words(); + } + return s; +} + void FreeChunkList::print_on(outputStream* st) const { if (_num_chunks.get() > 0) { for (const Metachunk* c = _first; c != NULL; c = c->next()) { @@ -60,7 +69,6 @@ void FreeChunkList::verify() const { assert(_last == NULL, "Sanity"); } else { assert(_last != NULL, "Sanity"); - size_t committed = 0; int num = 0; bool uncommitted = (_first->committed_words() == 0); for (Metachunk* c = _first; c != NULL; c = c->next()) { @@ -71,11 +79,9 @@ void FreeChunkList::verify() const { assert(c->prev() == NULL || c->prev()->next() == c, "back link broken"); assert(c != c->prev() && c != c->next(), "circle"); c->verify(); - committed += c->committed_words(); num++; } _num_chunks.check(num); - _committed_word_size.check(committed); } } @@ -90,15 +96,19 @@ size_t FreeChunkListVector::word_size() const { return sum; } -// Returns total committed size in all lists -size_t FreeChunkListVector::committed_word_size() const { +// Calculates total number of committed words over all chunks (walks chunks). +size_t FreeChunkListVector::calc_committed_word_size() const { size_t sum = 0; for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l++) { - sum += list_for_level(l)->committed_word_size(); + sum += calc_committed_word_size_at_level(l); } return sum; } +size_t FreeChunkListVector::calc_committed_word_size_at_level(chunklevel_t lvl) const { + return list_for_level(lvl)->calc_committed_word_size(); +} + // Returns total committed size in all lists int FreeChunkListVector::num_chunks() const { int n = 0; @@ -146,8 +156,8 @@ void FreeChunkListVector::print_on(outputStream* st) const { list_for_level(l)->print_on(st); st->cr(); } - st->print_cr("total chunks: %d, total word size: " SIZE_FORMAT ", committed word size: " SIZE_FORMAT ".", - num_chunks(), word_size(), committed_word_size()); + st->print_cr("total chunks: %d, total word size: " SIZE_FORMAT ".", + num_chunks(), word_size()); } #ifdef ASSERT diff --git a/src/hotspot/share/memory/metaspace/freeChunkList.hpp b/src/hotspot/share/memory/metaspace/freeChunkList.hpp index ed27a1414c0..be82b24f125 100644 --- a/src/hotspot/share/memory/metaspace/freeChunkList.hpp +++ b/src/hotspot/share/memory/metaspace/freeChunkList.hpp @@ -70,7 +70,6 @@ class FreeChunkList { Metachunk* _last; IntCounter _num_chunks; - SizeCounter _committed_word_size; void add_front(Metachunk* c) { if (_first == NULL) { @@ -129,7 +128,6 @@ class FreeChunkList { } c->set_next(NULL); c->set_prev(NULL); - _committed_word_size.decrement_by(c->committed_words()); _num_chunks.decrement(); return c; } @@ -144,7 +142,6 @@ class FreeChunkList { } else { add_front(c); } - _committed_word_size.increment_by(c->committed_words()); _num_chunks.increment(); } @@ -186,8 +183,8 @@ class FreeChunkList { // Returns number of chunks int num_chunks() const { return _num_chunks.get(); } - // Returns total committed word size - size_t committed_word_size() const { return _committed_word_size.get(); } + // Calculates total number of committed words over all chunks (walks chunks). + size_t calc_committed_word_size() const; void print_on(outputStream* st) const; @@ -226,11 +223,6 @@ class FreeChunkListVector { return list_for_level(lvl)->num_chunks(); } - // Returns number of chunks for a given level. - size_t committed_word_size_at_level(chunklevel_t lvl) const { - return list_for_level(lvl)->committed_word_size(); - } - // Returns reference to first chunk at this level, or NULL if sublist is empty. Metachunk* first_at_level(chunklevel_t lvl) const { return list_for_level(lvl)->first(); @@ -247,11 +239,14 @@ class FreeChunkListVector { // Return NULL if no such chunk was found. Metachunk* search_chunk_descending(chunklevel_t level, size_t min_committed_words); - // Returns total size in all lists (regardless of commit state of underlying memory) + // Returns total size in all lists (including uncommitted areas) size_t word_size() const; - // Returns total committed size in all lists - size_t committed_word_size() const; + // Calculates total number of committed words over all chunks (walks chunks). + size_t calc_committed_word_size_at_level(chunklevel_t lvl) const; + + // Calculates total number of committed words over all chunks (walks chunks). + size_t calc_committed_word_size() const; // Returns number of chunks in all lists int num_chunks() const; diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index 1e1692dc6f1..d3af76b8263 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -406,12 +406,23 @@ static void format_helper( PhaseRegAlloc *regalloc, outputStream* st, Node *n, c } } +//---------------------print_method_with_lineno-------------------------------- +void JVMState::print_method_with_lineno(outputStream* st, bool show_name) const { + if (show_name) _method->print_short_name(st); + + int lineno = _method->line_number_from_bci(_bci); + if (lineno != -1) { + st->print(" @ bci:%d (line %d)", _bci, lineno); + } else { + st->print(" @ bci:%d", _bci); + } +} + //------------------------------format----------------------------------------- void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) const { st->print(" #"); if (_method) { - _method->print_short_name(st); - st->print(" @ bci:%d ",_bci); + print_method_with_lineno(st, true); } else { st->print_cr(" runtime stub "); return; @@ -537,9 +548,7 @@ void JVMState::dump_spec(outputStream *st) const { printed = true; } } - if (!printed) - _method->print_short_name(st); - st->print(" @ bci:%d",_bci); + print_method_with_lineno(st, !printed); if(_reexecute == Reexecute_True) st->print(" reexecute"); } else { diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index 4688b01d534..e5b21fa79f0 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -306,6 +306,7 @@ class JVMState : public ResourceObj { int interpreter_frame_size() const; #ifndef PRODUCT + void print_method_with_lineno(outputStream* st, bool show_name) const; void format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) const; void dump_spec(outputStream *st) const; void dump_on(outputStream* st) const; diff --git a/src/hotspot/share/opto/graphKit.hpp b/src/hotspot/share/opto/graphKit.hpp index 5f9074c8e24..e6d84424c6b 100644 --- a/src/hotspot/share/opto/graphKit.hpp +++ b/src/hotspot/share/opto/graphKit.hpp @@ -889,6 +889,11 @@ class GraphKit : public Phase { void add_empty_predicate_impl(Deoptimization::DeoptReason reason, int nargs); Node* make_constant_from_field(ciField* field, Node* obj); + + // Vector API support (implemented in vectorIntrinsics.cpp) + Node* box_vector(Node* in, const TypeInstPtr* vbox_type, BasicType elem_bt, int num_elem, bool deoptimize_on_exception = false); + Node* unbox_vector(Node* in, const TypeInstPtr* vbox_type, BasicType elem_bt, int num_elem, bool shuffle_to_vector = false); + Node* vector_shift_count(Node* cnt, int shift_op, BasicType bt, int num_elem); }; // Helper class to support building of control flow branches. Upon diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index c51ce5b9078..82a78553605 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -324,9 +324,6 @@ class LibraryCallKit : public GraphKit { bool inline_vector_convert(); bool inline_vector_extract(); bool inline_vector_insert(); - Node* box_vector(Node* in, const TypeInstPtr* vbox_type, BasicType bt, int num_elem); - Node* unbox_vector(Node* in, const TypeInstPtr* vbox_type, BasicType bt, int num_elem, bool shuffle_to_vector = false); - Node* shift_count(Node* cnt, int shift_op, BasicType bt, int num_elem); enum VectorMaskUseType { VecMaskUseLoad, diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 1d144b1fbcd..dbb1e35fe2e 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -960,7 +960,9 @@ PhaseIterGVN::PhaseIterGVN( PhaseGVN *gvn ) : PhaseGVN(gvn), Node *n = _table.at(i); if(n != NULL && n != _table.sentinel() && n->outcnt() == 0) { if( n->is_top() ) continue; - assert( false, "Parse::remove_useless_nodes missed this node"); + // If remove_useless_nodes() has run, we expect no such nodes left. + assert(!UseLoopSafepoints || !OptoRemoveUseless, + "remove_useless_nodes missed this node"); hash_delete(n); } } diff --git a/src/hotspot/share/opto/vector.cpp b/src/hotspot/share/opto/vector.cpp index 8b4a1f3caa4..943b15515e1 100644 --- a/src/hotspot/share/opto/vector.cpp +++ b/src/hotspot/share/opto/vector.cpp @@ -192,22 +192,13 @@ void PhaseVector::scalarize_vbox_node(VectorBoxNode* vec_box) { Node* new_vbox = NULL; { - PreserveReexecuteState prs(&kit); - - kit.jvms()->set_should_reexecute(true); - - const TypeInstPtr* vbox_type = vec_box->box_type(); - const TypeVect* vect_type = vec_box->vec_type(); Node* vect = vec_box->in(VectorBoxNode::Value); + const TypeInstPtr* vbox_type = vec_box->box_type(); + const TypeVect* vt = vec_box->vec_type(); + BasicType elem_bt = vt->element_basic_type(); + int num_elem = vt->length(); - VectorBoxAllocateNode* alloc = new VectorBoxAllocateNode(C, vbox_type); - kit.set_edges_for_java_call(alloc, /*must_throw=*/false, /*separate_io_proj=*/true); - kit.make_slow_call_ex(alloc, C->env()->Throwable_klass(), /*separate_io_proj=*/true, /*deoptimize=*/true); - kit.set_i_o(gvn.transform( new ProjNode(alloc, TypeFunc::I_O) )); - kit.set_all_memory(gvn.transform( new ProjNode(alloc, TypeFunc::Memory) )); - Node* ret = gvn.transform(new ProjNode(alloc, TypeFunc::Parms)); - - new_vbox = gvn.transform(new VectorBoxNode(C, ret, vect, vbox_type, vect_type)); + new_vbox = kit.box_vector(vect, vbox_type, elem_bt, num_elem, /*deoptimize=*/true); kit.replace_in_map(vec_box, new_vbox); } @@ -367,12 +358,12 @@ Node* PhaseVector::expand_vbox_alloc_node(VectorBoxAllocateNode* vbox_alloc, // The store should be captured by InitializeNode and turned into initialized store later. Node* field_store = gvn.transform(kit.access_store_at(vec_obj, - vec_field, - vec_adr_type, - arr, - TypeOopPtr::make_from_klass(field->type()->as_klass()), - T_OBJECT, - IN_HEAP)); + vec_field, + vec_adr_type, + arr, + TypeOopPtr::make_from_klass(field->type()->as_klass()), + T_OBJECT, + IN_HEAP)); kit.set_memory(field_store, vec_adr_type); kit.replace_call(vbox_alloc, vec_obj, true); diff --git a/src/hotspot/share/opto/vectorIntrinsics.cpp b/src/hotspot/share/opto/vectorIntrinsics.cpp index d06c8348907..6f6932af0ec 100644 --- a/src/hotspot/share/opto/vectorIntrinsics.cpp +++ b/src/hotspot/share/opto/vectorIntrinsics.cpp @@ -29,6 +29,76 @@ #include "opto/vectornode.hpp" #include "prims/vectorSupport.hpp" +#ifdef ASSERT +static bool is_vector(ciKlass* klass) { + return klass->is_subclass_of(ciEnv::current()->vector_VectorPayload_klass()); +} + +static bool check_vbox(const TypeInstPtr* vbox_type) { + assert(vbox_type->klass_is_exact(), ""); + + ciInstanceKlass* ik = vbox_type->klass()->as_instance_klass(); + assert(is_vector(ik), "not a vector"); + + ciField* fd1 = ik->get_field_by_name(ciSymbol::ETYPE_name(), ciSymbol::class_signature(), /* is_static */ true); + assert(fd1 != NULL, "element type info is missing"); + + ciConstant val1 = fd1->constant_value(); + BasicType elem_bt = val1.as_object()->as_instance()->java_mirror_type()->basic_type(); + assert(is_java_primitive(elem_bt), "element type info is missing"); + + ciField* fd2 = ik->get_field_by_name(ciSymbol::VLENGTH_name(), ciSymbol::int_signature(), /* is_static */ true); + assert(fd2 != NULL, "vector length info is missing"); + + ciConstant val2 = fd2->constant_value(); + assert(val2.as_int() > 0, "vector length info is missing"); + + return true; +} +#endif + +Node* GraphKit::box_vector(Node* vector, const TypeInstPtr* vbox_type, BasicType elem_bt, int num_elem, bool deoptimize_on_exception) { + assert(EnableVectorSupport, ""); + + PreserveReexecuteState preexecs(this); + jvms()->set_should_reexecute(true); + + VectorBoxAllocateNode* alloc = new VectorBoxAllocateNode(C, vbox_type); + set_edges_for_java_call(alloc, /*must_throw=*/false, /*separate_io_proj=*/true); + make_slow_call_ex(alloc, env()->Throwable_klass(), /*separate_io_proj=*/true, deoptimize_on_exception); + set_i_o(gvn().transform( new ProjNode(alloc, TypeFunc::I_O) )); + set_all_memory(gvn().transform( new ProjNode(alloc, TypeFunc::Memory) )); + Node* ret = gvn().transform(new ProjNode(alloc, TypeFunc::Parms)); + + assert(check_vbox(vbox_type), ""); + const TypeVect* vt = TypeVect::make(elem_bt, num_elem); + VectorBoxNode* vbox = new VectorBoxNode(C, ret, vector, vbox_type, vt); + return gvn().transform(vbox); +} + +Node* GraphKit::unbox_vector(Node* v, const TypeInstPtr* vbox_type, BasicType elem_bt, int num_elem, bool shuffle_to_vector) { + assert(EnableVectorSupport, ""); + const TypeInstPtr* vbox_type_v = gvn().type(v)->is_instptr(); + if (vbox_type->klass() != vbox_type_v->klass()) { + return NULL; // arguments don't agree on vector shapes + } + if (vbox_type_v->maybe_null()) { + return NULL; // no nulls are allowed + } + assert(check_vbox(vbox_type), ""); + const TypeVect* vt = TypeVect::make(elem_bt, num_elem); + Node* unbox = gvn().transform(new VectorUnboxNode(C, vt, v, merged_memory(), shuffle_to_vector)); + return unbox; +} + +Node* GraphKit::vector_shift_count(Node* cnt, int shift_op, BasicType bt, int num_elem) { + assert(bt == T_INT || bt == T_LONG || bt == T_SHORT || bt == T_BYTE, "byte, short, long and int are supported"); + juint mask = (type2aelembytes(bt) * BitsPerByte - 1); + Node* nmask = gvn().transform(ConNode::make(TypeInt::make(mask))); + Node* mcnt = gvn().transform(new AndINode(cnt, nmask)); + return gvn().transform(VectorNode::shift_count(shift_op, mcnt, num_elem, bt)); +} + bool LibraryCallKit::arch_supports_vector(int sopc, int num_elem, BasicType type, VectorMaskUseType mask_use_type, bool has_scalar_args) { // Check that the operation is valid. if (sopc <= 0) { @@ -108,66 +178,6 @@ static bool is_klass_initialized(const TypeInstPtr* vec_klass) { return klass->is_initialized(); } -#ifdef ASSERT -static bool is_vector(ciKlass* klass) { - return klass->is_subclass_of(ciEnv::current()->vector_VectorPayload_klass()); -} - -static bool check_vbox(const TypeInstPtr* vbox_type) { - assert(vbox_type->klass_is_exact(), ""); - - ciInstanceKlass* ik = vbox_type->klass()->as_instance_klass(); - assert(is_vector(ik), "not a vector"); - - ciField* fd1 = ik->get_field_by_name(ciSymbol::ETYPE_name(), ciSymbol::class_signature(), /* is_static */ true); - assert(fd1 != NULL, "element type info is missing"); - - ciConstant val1 = fd1->constant_value(); - BasicType elem_bt = val1.as_object()->as_instance()->java_mirror_type()->basic_type(); - assert(is_java_primitive(elem_bt), "element type info is missing"); - - ciField* fd2 = ik->get_field_by_name(ciSymbol::VLENGTH_name(), ciSymbol::int_signature(), /* is_static */ true); - assert(fd2 != NULL, "vector length info is missing"); - - ciConstant val2 = fd2->constant_value(); - assert(val2.as_int() > 0, "vector length info is missing"); - - return true; -} -#endif - -Node* LibraryCallKit::box_vector(Node* vector, const TypeInstPtr* vbox_type, - BasicType elem_bt, int num_elem) { - assert(EnableVectorSupport, ""); - const TypeVect* vec_type = TypeVect::make(elem_bt, num_elem); - - VectorBoxAllocateNode* alloc = new VectorBoxAllocateNode(C, vbox_type); - set_edges_for_java_call(alloc, /*must_throw=*/false, /*separate_io_proj=*/true); - make_slow_call_ex(alloc, env()->Throwable_klass(), /*separate_io_proj=*/true); - set_i_o(gvn().transform( new ProjNode(alloc, TypeFunc::I_O) )); - set_all_memory(gvn().transform( new ProjNode(alloc, TypeFunc::Memory) )); - Node* ret = gvn().transform(new ProjNode(alloc, TypeFunc::Parms)); - - assert(check_vbox(vbox_type), ""); - VectorBoxNode* vbox = new VectorBoxNode(C, ret, vector, vbox_type, vec_type); - return gvn().transform(vbox); -} - -Node* LibraryCallKit::unbox_vector(Node* v, const TypeInstPtr* vbox_type, BasicType elem_bt, int num_elem, bool shuffle_to_vector) { - assert(EnableVectorSupport, ""); - const TypeInstPtr* vbox_type_v = gvn().type(v)->is_instptr(); - if (vbox_type->klass() != vbox_type_v->klass()) { - return NULL; // arguments don't agree on vector shapes - } - if (vbox_type_v->maybe_null()) { - return NULL; // no nulls are allowed - } - assert(check_vbox(vbox_type), ""); - const TypeVect* vec_type = TypeVect::make(elem_bt, num_elem); - Node* unbox = gvn().transform(new VectorUnboxNode(C, vec_type, v, merged_memory(), shuffle_to_vector)); - return unbox; -} - // public static // // VM unaryOp(int oprId, Class vmClass, Class elementType, int length, @@ -1165,14 +1175,6 @@ bool LibraryCallKit::inline_vector_rearrange() { return true; } -Node* LibraryCallKit::shift_count(Node* cnt, int shift_op, BasicType bt, int num_elem) { - assert(bt == T_INT || bt == T_LONG || bt == T_SHORT || bt == T_BYTE, "byte, short, long and int are supported"); - juint mask = (type2aelembytes(bt) * BitsPerByte - 1); - Node* nmask = gvn().transform(ConNode::make(TypeInt::make(mask))); - Node* mcnt = gvn().transform(new AndINode(cnt, nmask)); - return gvn().transform(VectorNode::shift_count(shift_op, mcnt, num_elem, bt)); -} - // public static // > // V broadcastInt(int opr, Class vectorClass, Class elementType, int vlen, @@ -1223,7 +1225,7 @@ bool LibraryCallKit::inline_vector_broadcast_int() { return false; // not supported } Node* opd1 = unbox_vector(argument(4), vbox_type, elem_bt, num_elem); - Node* opd2 = shift_count(argument(5), opc, elem_bt, num_elem); + Node* opd2 = vector_shift_count(argument(5), opc, elem_bt, num_elem); if (opd1 == NULL || opd2 == NULL) { return false; } diff --git a/src/hotspot/share/prims/vectorSupport.cpp b/src/hotspot/share/prims/vectorSupport.cpp index 3d2c1fff59e..1011dd9b982 100644 --- a/src/hotspot/share/prims/vectorSupport.cpp +++ b/src/hotspot/share/prims/vectorSupport.cpp @@ -83,126 +83,94 @@ jint VectorSupport::klass2length(InstanceKlass* ik) { return vlen; } -void VectorSupport::init_vector_array(typeArrayOop arr, BasicType elem_bt, int num_elem, address value_addr) { - int elem_size = type2aelembytes(elem_bt); - for (int i = 0; i < num_elem; i++) { +void VectorSupport::init_payload_element(typeArrayOop arr, bool is_mask, BasicType elem_bt, int index, address addr) { + if (is_mask) { + // Masks require special handling: when boxed they are packed and stored in boolean + // arrays, but in scalarized form they have the same size as corresponding vectors. + // For example, Int512Mask is represented in memory as boolean[16], but + // occupies the whole 512-bit vector register when scalarized. + // (In generated code, the conversion is performed by VectorStoreMask.) + // + // TODO: revisit when predicate registers are fully supported. switch (elem_bt) { - case T_BYTE: { - jbyte elem_value = *(jbyte*) (value_addr + i * elem_size); - arr->byte_at_put(i, elem_value); - break; - } - case T_SHORT: { - jshort elem_value = *(jshort*) (value_addr + i * elem_size); - arr->short_at_put(i, elem_value); - break; - } - case T_INT: { - jint elem_value = *(jint*) (value_addr + i * elem_size); - arr->int_at_put(i, elem_value); - break; - } - case T_LONG: { - jlong elem_value = *(jlong*) (value_addr + i * elem_size); - arr->long_at_put(i, elem_value); - break; - } - case T_FLOAT: { - jfloat elem_value = *(jfloat*) (value_addr + i * elem_size); - arr->float_at_put(i, elem_value); - break; - } - case T_DOUBLE: { - jdouble elem_value = *(jdouble*) (value_addr + i * elem_size); - arr->double_at_put(i, elem_value); - break; - } - default: - fatal("unsupported: %s", type2name(elem_bt)); + case T_BYTE: arr->bool_at_put(index, (*(jbyte*)addr) != 0); break; + case T_SHORT: arr->bool_at_put(index, (*(jshort*)addr) != 0); break; + case T_INT: // fall-through + case T_FLOAT: arr->bool_at_put(index, (*(jint*)addr) != 0); break; + case T_LONG: // fall-through + case T_DOUBLE: arr->bool_at_put(index, (*(jlong*)addr) != 0); break; + + default: fatal("unsupported: %s", type2name(elem_bt)); } - } -} - -void VectorSupport::init_mask_array(typeArrayOop arr, BasicType elem_bt, int num_elem, address value_addr) { - int elem_size = type2aelembytes(elem_bt); - - for (int i = 0; i < num_elem; i++) { + } else { switch (elem_bt) { - case T_BYTE: { - jbyte elem_value = *(jbyte*) (value_addr + i * elem_size); - arr->bool_at_put(i, elem_value != 0); - break; - } - case T_SHORT: { - jshort elem_value = *(jshort*) (value_addr + i * elem_size); - arr->bool_at_put(i, elem_value != 0); - break; - } - case T_INT: // fall-through - case T_FLOAT: { - jint elem_value = *(jint*) (value_addr + i * elem_size); - arr->bool_at_put(i, elem_value != 0); - break; - } - case T_LONG: // fall-through - case T_DOUBLE: { - jlong elem_value = *(jlong*) (value_addr + i * elem_size); - arr->bool_at_put(i, elem_value != 0); - break; - } - default: - fatal("unsupported: %s", type2name(elem_bt)); + case T_BYTE: arr-> byte_at_put(index, *(jbyte*)addr); break; + case T_SHORT: arr-> short_at_put(index, *(jshort*)addr); break; + case T_INT: arr-> int_at_put(index, *(jint*)addr); break; + case T_FLOAT: arr-> float_at_put(index, *(jfloat*)addr); break; + case T_LONG: arr-> long_at_put(index, *(jlong*)addr); break; + case T_DOUBLE: arr->double_at_put(index, *(jdouble*)addr); break; + + default: fatal("unsupported: %s", type2name(elem_bt)); } } } -oop VectorSupport::allocate_vector_payload_helper(InstanceKlass* ik, BasicType elem_bt, int num_elem, address value_addr, TRAPS) { - +Handle VectorSupport::allocate_vector_payload_helper(InstanceKlass* ik, frame* fr, RegisterMap* reg_map, Location location, TRAPS) { bool is_mask = is_vector_mask(ik); + int num_elem = klass2length(ik); + BasicType elem_bt = klass2bt(ik); + int elem_size = type2aelembytes(elem_bt); + // On-heap vector values are represented as primitive arrays. TypeArrayKlass* tak = TypeArrayKlass::cast(Universe::typeArrayKlassObj(is_mask ? T_BOOLEAN : elem_bt)); - typeArrayOop arr = tak->allocate(num_elem, CHECK_NULL); // safepoint + typeArrayOop arr = tak->allocate(num_elem, CHECK_NH); // safepoint - if (is_mask) { - init_mask_array(arr, elem_bt, num_elem, value_addr); + if (location.is_register()) { + // Value was in a callee-saved register. + VMReg vreg = VMRegImpl::as_VMReg(location.register_number()); + + for (int i = 0; i < num_elem; i++) { + int vslot = (i * elem_size) / VMRegImpl::stack_slot_size; + int off = (i * elem_size) % VMRegImpl::stack_slot_size; + + address elem_addr = reg_map->location(vreg->next(vslot)) + off; + init_payload_element(arr, is_mask, elem_bt, i, elem_addr); + } + } else { + // Value was directly saved on the stack. + address base_addr = ((address)fr->unextended_sp()) + location.stack_offset(); + for (int i = 0; i < num_elem; i++) { + init_payload_element(arr, is_mask, elem_bt, i, base_addr + i * elem_size); + } + } + return Handle(THREAD, arr); +} + +Handle VectorSupport::allocate_vector_payload(InstanceKlass* ik, frame* fr, RegisterMap* reg_map, ScopeValue* payload, TRAPS) { + if (payload->is_location() && + payload->as_LocationValue()->location().type() == Location::vector) { + // Vector value in an aligned adjacent tuple (1, 2, 4, 8, or 16 slots). + Location location = payload->as_LocationValue()->location(); + return allocate_vector_payload_helper(ik, fr, reg_map, location, THREAD); // safepoint } else { - init_vector_array(arr, elem_bt, num_elem, value_addr); + // Scalar-replaced boxed vector representation. + StackValue* value = StackValue::create_stack_value(fr, reg_map, payload); + return value->get_obj(); } - return arr; } -oop VectorSupport::allocate_vector(InstanceKlass* ik, frame* fr, RegisterMap* reg_map, ObjectValue* ov, TRAPS) { +instanceOop VectorSupport::allocate_vector(InstanceKlass* ik, frame* fr, RegisterMap* reg_map, ObjectValue* ov, TRAPS) { assert(is_vector(ik), "%s not a vector", ik->name()->as_C_string()); assert(ov->field_size() == 1, "%s not a vector", ik->name()->as_C_string()); - // Vector value in an aligned adjacent tuple (1, 2, 4, 8, or 16 slots). - LocationValue* loc_value = ov->field_at(0)->as_LocationValue(); - - BasicType elem_bt = klass2bt(ik); - int num_elem = klass2length(ik); - - Handle vbox = ik->allocate_instance_handle(CHECK_NULL); - - Location loc = loc_value->location(); - - oop payload = NULL; - if (loc.type() == Location::vector) { - address value_addr = loc.is_register() - // Value was in a callee-save register - ? reg_map->location(VMRegImpl::as_VMReg(loc.register_number())) - // Else value was directly saved on the stack. The frame's original stack pointer, - // before any extension by its callee (due to Compiler1 linkage on SPARC), must be used. - : ((address)fr->unextended_sp()) + loc.stack_offset(); - payload = allocate_vector_payload_helper(ik, elem_bt, num_elem, value_addr, CHECK_NULL); // safepoint - } else { - // assert(false, "interesting"); - StackValue* value = StackValue::create_stack_value(fr, reg_map, loc_value); - payload = value->get_obj()(); - } - vector_VectorPayload::set_payload(vbox(), payload); - return vbox(); + ScopeValue* payload_value = ov->field_at(0); + Handle payload_instance = VectorSupport::allocate_vector_payload(ik, fr, reg_map, payload_value, CHECK_NULL); + instanceOop vbox = ik->allocate_instance(CHECK_NULL); + vector_VectorPayload::set_payload(vbox, payload_instance()); + return vbox; } #ifdef COMPILER2 diff --git a/src/hotspot/share/prims/vectorSupport.hpp b/src/hotspot/share/prims/vectorSupport.hpp index 31be129d07b..19e885f9dcf 100644 --- a/src/hotspot/share/prims/vectorSupport.hpp +++ b/src/hotspot/share/prims/vectorSupport.hpp @@ -39,9 +39,10 @@ extern "C" { class VectorSupport : AllStatic { private: - static void init_mask_array(typeArrayOop arr, BasicType elem_bt, int num_elem, address value_addr); - static void init_vector_array(typeArrayOop arr, BasicType elem_bt, int num_elem, address value_addr); - static oop allocate_vector_payload_helper(InstanceKlass* ik, BasicType elem_bt, int num_elem, address value_addr, TRAPS); + static Handle allocate_vector_payload(InstanceKlass* ik, frame* fr, RegisterMap* reg_map, ScopeValue* payload, TRAPS); + static Handle allocate_vector_payload_helper(InstanceKlass* ik, frame* fr, RegisterMap* reg_map, Location location, TRAPS); + + static void init_payload_element(typeArrayOop arr, bool is_mask, BasicType elem_bt, int index, address addr); static BasicType klass2bt(InstanceKlass* ik); static jint klass2length(InstanceKlass* ik); @@ -81,7 +82,7 @@ class VectorSupport : AllStatic { static int vop2ideal(jint vop, BasicType bt); - static oop allocate_vector(InstanceKlass* holder, frame* fr, RegisterMap* reg_map, ObjectValue* sv, TRAPS); + static instanceOop allocate_vector(InstanceKlass* holder, frame* fr, RegisterMap* reg_map, ObjectValue* sv, TRAPS); static bool is_vector(Klass* klass); static bool is_vector_mask(Klass* klass); diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 7d807b20257..3dbc225624a 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1170,9 +1170,13 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) { } // Looks like all platforms can use the same function to check if C -// stack is walkable beyond current frame. The check for fp() is not -// necessary on Sparc, but it's harmless. +// stack is walkable beyond current frame. bool os::is_first_C_frame(frame* fr) { + +#ifdef _WINDOWS + return true; // native stack isn't walkable on windows this way. +#endif + // Load up sp, fp, sender sp and sender fp, check for reasonable values. // Check usp first, because if that's bad the other accessors may fault // on some architectures. Ditto ufp second, etc. diff --git a/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemController.java b/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemController.java index 0c2e54a2634..5045a07cd88 100644 --- a/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemController.java +++ b/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemController.java @@ -26,6 +26,7 @@ package jdk.internal.platform; import java.io.IOException; +import java.io.UncheckedIOException; import java.math.BigInteger; import java.nio.file.Path; import java.nio.file.Paths; @@ -169,8 +170,9 @@ public static long getLongEntry(CgroupSubsystemController controller, String par .findFirst(); return result.isPresent() ? Long.parseLong(result.get()) : defaultRetval; - } - catch (IOException e) { + } catch (UncheckedIOException e) { + return defaultRetval; + } catch (IOException e) { return defaultRetval; } } diff --git a/src/java.base/linux/classes/jdk/internal/platform/CgroupUtil.java b/src/java.base/linux/classes/jdk/internal/platform/CgroupUtil.java index 1e942c599c3..d50aa6bbb6d 100644 --- a/src/java.base/linux/classes/jdk/internal/platform/CgroupUtil.java +++ b/src/java.base/linux/classes/jdk/internal/platform/CgroupUtil.java @@ -27,6 +27,7 @@ import java.io.BufferedReader; import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -45,6 +46,8 @@ public static Stream readFilePrivileged(Path path) throws IOException { } catch (PrivilegedActionException e) { unwrapIOExceptionAndRethrow(e); throw new InternalError(e.getCause()); + } catch (UncheckedIOException e) { + throw e.getCause(); } } @@ -68,6 +71,8 @@ static String readStringValue(CgroupSubsystemController controller, String param } catch (PrivilegedActionException e) { unwrapIOExceptionAndRethrow(e); throw new InternalError(e.getCause()); + } catch (UncheckedIOException e) { + throw e.getCause(); } } @@ -78,6 +83,8 @@ public static List readAllLinesPrivileged(Path path) throws IOException } catch (PrivilegedActionException e) { unwrapIOExceptionAndRethrow(e); throw new InternalError(e.getCause()); + } catch (UncheckedIOException e) { + throw e.getCause(); } } } diff --git a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java index 62a21e50d85..1ee087a5181 100644 --- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java +++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java @@ -26,6 +26,7 @@ package jdk.internal.platform.cgroupv1; import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Stream; @@ -75,6 +76,8 @@ private static CgroupV1Subsystem initSubSystem() { .map(line -> line.split(" ")) .forEach(entry -> createSubSystemController(subsystem, entry)); + } catch (UncheckedIOException e) { + return null; } catch (IOException e) { return null; } @@ -109,6 +112,8 @@ private static CgroupV1Subsystem initSubSystem() { .filter(line -> (line.length >= 3)) .forEach(line -> setSubSystemControllerPath(subsystem, line)); + } catch (UncheckedIOException e) { + return null; } catch (IOException e) { return null; } diff --git a/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2Subsystem.java b/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2Subsystem.java index be97f7cdf44..573a425bd98 100644 --- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2Subsystem.java +++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2Subsystem.java @@ -26,6 +26,7 @@ package jdk.internal.platform.cgroupv2; import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.file.Paths; import java.util.List; import java.util.concurrent.TimeUnit; @@ -69,6 +70,8 @@ private static CgroupV2Subsystem initSubsystem() { .collect(Collectors.joining()); String[] tokens = l.split(" "); mountPath = tokens[4]; + } catch (UncheckedIOException e) { + return null; } catch (IOException e) { return null; } @@ -87,6 +90,8 @@ private static CgroupV2Subsystem initSubsystem() { cgroupPath = tokens[2]; break; } + } catch (UncheckedIOException e) { + return null; } catch (IOException e) { return null; } @@ -329,6 +334,8 @@ private long sumTokensIOStat(Function mapFunc) { return CgroupUtil.readFilePrivileged(Paths.get(unified.path(), "io.stat")) .map(mapFunc) .collect(Collectors.summingLong(e -> e)); + } catch (UncheckedIOException e) { + return CgroupSubsystem.LONG_RETVAL_UNLIMITED; } catch (IOException e) { return CgroupSubsystem.LONG_RETVAL_UNLIMITED; } diff --git a/src/java.base/share/classes/java/io/InputStream.java b/src/java.base/share/classes/java/io/InputStream.java index df398373b50..9b5b0b09c51 100644 --- a/src/java.base/share/classes/java/io/InputStream.java +++ b/src/java.base/share/classes/java/io/InputStream.java @@ -592,6 +592,8 @@ public long skip(long n) throws IOException { * @throws IOException if the stream cannot be positioned properly or * if an I/O error occurs. * @see java.io.InputStream#skip(long) + * + * @since 12 */ public void skipNBytes(long n) throws IOException { if (n > 0) { diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index 354d8f8d2f1..f0b0db20f8c 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -242,7 +242,8 @@ * The record components are deserialized prior to the invocation of the record * constructor, hence this limitation (see * - * [Section 1.14, "Circular References" for additional information). + * Java Object Serialization Specification, + * Section 1.14, "Circular References" for additional information). * The process by which record objects are serialized or externalized cannot be * customized; any class-specific writeObject, readObject, readObjectNoData, * writeExternal, and readExternal methods defined by record classes are @@ -262,7 +263,7 @@ * @see java.io.ObjectOutputStream * @see java.io.Serializable * @see - * Object Serialization Specification, Section 3, Object Input Classes + * Java Object Serialization Specification, Section 3, "Object Input Classes" * @since 1.1 */ public class ObjectInputStream diff --git a/src/java.base/share/classes/java/io/ObjectOutputStream.java b/src/java.base/share/classes/java/io/ObjectOutputStream.java index 2ad8e698ab2..2bc0fc31f36 100644 --- a/src/java.base/share/classes/java/io/ObjectOutputStream.java +++ b/src/java.base/share/classes/java/io/ObjectOutputStream.java @@ -161,7 +161,7 @@ * @see java.io.Serializable * @see java.io.Externalizable * @see - * Object Serialization Specification, Section 2, Object Output Classes + * Java Object Serialization Specification, Section 2, "Object Output Classes" * @since 1.1 */ public class ObjectOutputStream diff --git a/src/java.base/share/classes/java/io/ObjectStreamClass.java b/src/java.base/share/classes/java/io/ObjectStreamClass.java index 259a058842f..89d9c739aa7 100644 --- a/src/java.base/share/classes/java/io/ObjectStreamClass.java +++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java @@ -76,13 +76,13 @@ * *

The algorithm to compute the SerialVersionUID is described in * - * Object Serialization Specification, Section 4.6, Stream Unique Identifiers. + * Java Object Serialization Specification, Section 4.6, "Stream Unique Identifiers". * * @author Mike Warres * @author Roger Riggs * @see ObjectStreamField * @see - * Object Serialization Specification, Section 4, Class Descriptors + * Java Object Serialization Specification, Section 4, "Class Descriptors" * @since 1.1 */ public class ObjectStreamClass implements Serializable { diff --git a/src/java.base/share/classes/java/io/Serializable.java b/src/java.base/share/classes/java/io/Serializable.java index 4686d062108..deab67a710e 100644 --- a/src/java.base/share/classes/java/io/Serializable.java +++ b/src/java.base/share/classes/java/io/Serializable.java @@ -43,20 +43,19 @@ * serializable. The serialization interface has no methods or fields * and serves only to identify the semantics of being serializable.

* - * To allow subtypes of non-serializable classes to be serialized, the - * subtype may assume responsibility for saving and restoring the - * state of the supertype's public, protected, and (if accessible) - * package fields. The subtype may assume this responsibility only if - * the class it extends has an accessible no-arg constructor to - * initialize the class's state. It is an error to declare a class - * Serializable if this is not the case. The error will be detected at - * runtime.

- * - * During deserialization, the fields of non-serializable classes will - * be initialized using the public or protected no-arg constructor of - * the class. A no-arg constructor must be accessible to the subclass - * that is serializable. The fields of serializable subclasses will - * be restored from the stream.

+ * It is possible for subtypes of non-serializable classes to be serialized + * and deserialized. During serialization, no data will be written for the + * fields of non-serializable superclasses. During deserialization, the fields of non-serializable + * superclasses will be initialized using the no-arg constructor of the first (bottommost) + * non-serializable superclass. This constructor must be accessible to the subclass that is being + * deserialized. It is an error to declare a class Serializable if this is not + * the case; the error will be detected at runtime. A serializable subtype may + * assume responsibility for saving and restoring the state of a non-serializable + * supertype's public, protected, and (if accessible) package-access fields. See + * the + * Java Object Serialization Specification, section 3.1, for + * a detailed specification of the deserialization process, including handling of + * serializable and non-serializable classes.

* * When traversing a graph, an object may be encountered that does not * support the Serializable interface. In this case the @@ -135,7 +134,8 @@ * accessibility rules as writeReplace.

* * Enum types are all serializable and receive treatment defined by - * the Java Object Serialization Specification during + * the + * Java Object Serialization Specification during * serialization and deserialization. Any declarations of the special * handling methods discussed above are ignored for enum types.

* @@ -157,7 +157,8 @@ * If a serializable class does not explicitly declare a serialVersionUID, then * the serialization runtime will calculate a default serialVersionUID value * for that class based on various aspects of the class, as described in the - * Java Object Serialization Specification. This specification defines the + * Java Object Serialization + * Specification. This specification defines the * serialVersionUID of an enum type to be 0L. However, it is strongly * recommended that all serializable classes other than enum types explicitly declare * serialVersionUID values, since the default serialVersionUID computation is @@ -179,6 +180,8 @@ * @see java.io.ObjectOutput * @see java.io.ObjectInput * @see java.io.Externalizable + * @see + * Java Object Serialization Specification * @since 1.1 */ public interface Serializable { diff --git a/src/java.base/share/classes/java/io/package-info.java b/src/java.base/share/classes/java/io/package-info.java index 61c5babf016..1c41f9835e6 100644 --- a/src/java.base/share/classes/java/io/package-info.java +++ b/src/java.base/share/classes/java/io/package-info.java @@ -39,7 +39,7 @@ *

* diff --git a/src/java.base/share/classes/java/math/BigInteger.java b/src/java.base/share/classes/java/math/BigInteger.java index 766e65a31bd..354a06dacb1 100644 --- a/src/java.base/share/classes/java/math/BigInteger.java +++ b/src/java.base/share/classes/java/math/BigInteger.java @@ -3950,35 +3950,66 @@ public String toString(int radix) { if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) radix = 10; - // If it's small enough, use smallToString. - if (mag.length <= SCHOENHAGE_BASE_CONVERSION_THRESHOLD) - return smallToString(radix); + BigInteger abs = this.abs(); + + // Ensure buffer capacity sufficient to contain string representation + // floor(bitLength*log(2)/log(radix)) + 1 + // plus an additional character for the sign if negative. + int b = abs.bitLength(); + int numChars = (int)(Math.floor(b*LOG_TWO/logCache[radix]) + 1) + + (signum < 0 ? 1 : 0); + StringBuilder sb = new StringBuilder(numChars); - // Otherwise use recursive toString, which requires positive arguments. - // The results will be concatenated into this StringBuilder - StringBuilder sb = new StringBuilder(); if (signum < 0) { - toString(this.negate(), sb, radix, 0); - sb.insert(0, '-'); + sb.append('-'); } - else - toString(this, sb, radix, 0); + + // Use recursive toString. + toString(abs, sb, radix, 0); return sb.toString(); } - /** This method is used to perform toString when arguments are small. */ - private String smallToString(int radix) { + /** + * If {@code numZeros > 0}, appends that many zeros to the + * specified StringBuilder; otherwise, does nothing. + * + * @param sb The StringBuilder that will be appended to. + * @param numZeros The number of zeros to append. + */ + private static void padWithZeros(StringBuilder buf, int numZeros) { + while (numZeros >= NUM_ZEROS) { + buf.append(ZEROS); + numZeros -= NUM_ZEROS; + } + if (numZeros > 0) { + buf.append(ZEROS, 0, numZeros); + } + } + + /** + * This method is used to perform toString when arguments are small. + * The value must be non-negative. If {@code digits <= 0} no padding + * (pre-pending with zeros) will be effected. + * + * @param radix The base to convert to. + * @param sb The StringBuilder that will be appended to in place. + * @param digits The minimum number of digits to pad to. + */ + private void smallToString(int radix, StringBuilder buf, int digits) { + assert signum >= 0; + if (signum == 0) { - return "0"; + padWithZeros(buf, digits); + return; } // Compute upper bound on number of digit groups and allocate space int maxNumDigitGroups = (4*mag.length + 6)/7; - String digitGroup[] = new String[maxNumDigitGroups]; + long[] digitGroups = new long[maxNumDigitGroups]; // Translate number to string, a digit group at a time - BigInteger tmp = this.abs(); + BigInteger tmp = this; int numGroups = 0; while (tmp.signum != 0) { BigInteger d = longRadix[radix]; @@ -3990,33 +4021,37 @@ private String smallToString(int radix) { BigInteger q2 = q.toBigInteger(tmp.signum * d.signum); BigInteger r2 = r.toBigInteger(tmp.signum * d.signum); - digitGroup[numGroups++] = Long.toString(r2.longValue(), radix); + digitGroups[numGroups++] = r2.longValue(); tmp = q2; } - // Put sign (if any) and first digit group into result buffer - StringBuilder buf = new StringBuilder(numGroups*digitsPerLong[radix]+1); - if (signum < 0) { - buf.append('-'); - } - buf.append(digitGroup[numGroups-1]); + // Get string version of first digit group + String s = Long.toString(digitGroups[numGroups-1], radix); + + // Pad with internal zeros if necessary. + padWithZeros(buf, digits - (s.length() + + (numGroups - 1)*digitsPerLong[radix])); - // Append remaining digit groups padded with leading zeros + // Put first digit group into result buffer + buf.append(s); + + // Append remaining digit groups each padded with leading zeros for (int i=numGroups-2; i >= 0; i--) { // Prepend (any) leading zeros for this digit group - int numLeadingZeros = digitsPerLong[radix]-digitGroup[i].length(); + s = Long.toString(digitGroups[i], radix); + int numLeadingZeros = digitsPerLong[radix] - s.length(); if (numLeadingZeros != 0) { - buf.append(zeros[numLeadingZeros]); + buf.append(ZEROS, 0, numLeadingZeros); } - buf.append(digitGroup[i]); + buf.append(s); } - return buf.toString(); } /** * Converts the specified BigInteger to a string and appends to * {@code sb}. This implements the recursive Schoenhage algorithm - * for base conversions. + * for base conversions. This method can only be called for non-negative + * numbers. *

* See Knuth, Donald, _The Art of Computer Programming_, Vol. 2, * Answers to Exercises (4.4) Question 14. @@ -4026,32 +4061,26 @@ private String smallToString(int radix) { * @param radix The base to convert to. * @param digits The minimum number of digits to pad to. */ - private static void toString(BigInteger u, StringBuilder sb, int radix, - int digits) { + private static void toString(BigInteger u, StringBuilder sb, + int radix, int digits) { + assert u.signum() >= 0; + // If we're smaller than a certain threshold, use the smallToString - // method, padding with leading zeroes when necessary. + // method, padding with leading zeroes when necessary unless we're + // at the beginning of the string or digits <= 0. As u.signum() >= 0, + // smallToString() will not prepend a negative sign. if (u.mag.length <= SCHOENHAGE_BASE_CONVERSION_THRESHOLD) { - String s = u.smallToString(radix); - - // Pad with internal zeros if necessary. - // Don't pad if we're at the beginning of the string. - if ((s.length() < digits) && (sb.length() > 0)) { - for (int i=s.length(); i < digits; i++) { - sb.append('0'); - } - } - - sb.append(s); + u.smallToString(radix, sb, digits); return; } - int b, n; - b = u.bitLength(); - // Calculate a value for n in the equation radix^(2^n) = u // and subtract 1 from that value. This is used to find the // cache index that contains the best value to divide u. - n = (int) Math.round(Math.log(b * LOG_TWO / logCache[radix]) / LOG_TWO - 1.0); + int b = u.bitLength(); + int n = (int) Math.round(Math.log(b * LOG_TWO / logCache[radix]) / + LOG_TWO - 1.0); + BigInteger v = getRadixConversionCache(radix, n); BigInteger[] results; results = u.divideAndRemainder(v); @@ -4059,7 +4088,7 @@ private static void toString(BigInteger u, StringBuilder sb, int radix, int expectedDigits = 1 << n; // Now recursively build the two halves of each number. - toString(results[0], sb, radix, digits-expectedDigits); + toString(results[0], sb, radix, digits - expectedDigits); toString(results[1], sb, radix, expectedDigits); } @@ -4091,14 +4120,11 @@ private static BigInteger getRadixConversionCache(int radix, int exponent) { return cacheLine[exponent]; } - /* zero[i] is a string of i consecutive zeros. */ - private static String zeros[] = new String[64]; - static { - zeros[63] = - "000000000000000000000000000000000000000000000000000000000000000"; - for (int i=0; i < 63; i++) - zeros[i] = zeros[63].substring(0, i); - } + /* Size of ZEROS string. */ + private static int NUM_ZEROS = 63; + + /* ZEROS is a string of NUM_ZEROS consecutive zeros. */ + private static final String ZEROS = "0".repeat(NUM_ZEROS); /** * Returns the decimal String representation of this BigInteger. diff --git a/src/java.base/share/classes/java/text/DecimalFormat.java b/src/java.base/share/classes/java/text/DecimalFormat.java index 4fd1e1ef324..bbb2b8fe085 100644 --- a/src/java.base/share/classes/java/text/DecimalFormat.java +++ b/src/java.base/share/classes/java/text/DecimalFormat.java @@ -127,7 +127,7 @@ * subpattern, for example, {@code "#,##0.00;(#,##0.00)"}. Each * subpattern has a prefix, numeric part, and suffix. The negative subpattern * is optional; if absent, then the positive subpattern prefixed with the - * localized minus sign ({@code '-'} in most locales) is used as the + * minus sign ({@code '-' U+002D HYPHEN-MINUS}) is used as the * negative subpattern. That is, {@code "0.00"} alone is equivalent to * {@code "0.00;-0.00"}. If there is an explicit negative subpattern, it * serves only to specify the negative prefix and suffix; the number of digits, diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m index 3f89524ec5e..a80d43d032d 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2020, 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 @@ -127,6 +127,23 @@ - (NSArray *)accessibilityColumnsAttribute; @end +// In order to use a new NSAccessibility API and since our components +// are represented as a custom UI elements we need to implement a set +// of custom protocols. Definitions of these protocols will start here. + +// This is a root interface in the NSAccessibility* protocols hierarchy +// and all the component-specific protocols should be derived from it. +// It is also a place for the functions that might be exposed by all the +// component accessibility peers. +// Please see https://developer.apple.com/documentation/appkit/nsaccessibilityprotocol +// for more details. +@interface CommonComponentAccessibility : JavaComponentAccessibility { + +} +- (NSRect)accessibilityFrame; +- (nullable id)accessibilityParent; +@end + @implementation JavaComponentAccessibility - (NSString *)description @@ -1917,6 +1934,32 @@ - (id)accessibilityColumnCountAttribute { } @end +@implementation CommonComponentAccessibility +// NSAccessibilityElement protocol implementation +- (NSRect)accessibilityFrame +{ + JNIEnv* env = [ThreadUtilities getJNIEnv]; + jobject axComponent = JNFCallStaticObjectMethod(env, sjm_getAccessibleComponent, + fAccessible, fComponent); + + NSSize size = getAxComponentSize(env, axComponent, fComponent); + NSPoint point = getAxComponentLocationOnScreen(env, axComponent, fComponent); + (*env)->DeleteLocalRef(env, axComponent); + point.y += size.height; + + point.y = [[[[self view] window] screen] frame].size.height - point.y; + + NSRect retval = NSMakeRect(point.x, point.y, size.width, size.height); + return retval; +} + +- (nullable id)accessibilityParent +{ + return [self accessibilityParentAttribute]; +} + +@end + /* * Returns Object.equals for the two items * This may use LWCToolkit.invokeAndWait(); don't call while holding fLock diff --git a/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java b/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java index ba8b5aba27e..f70f1b1f358 100644 --- a/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java +++ b/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java @@ -32,6 +32,7 @@ import java.text.*; import java.util.*; import java.util.concurrent.*; +import java.util.function.LongSupplier; import javax.swing.*; @@ -257,9 +258,14 @@ synchronized Result formatSummary() { String[] kbStrings1 = formatKByteStrings(sunOSMBean.getCommittedVirtualMemorySize()); + // getTotalPhysicalMemorySize and getFreePhysicalMemorySize are deprecated, + // but we want be able to get the data for old target VMs (see JDK-8255934). + @SuppressWarnings("deprecation") String[] kbStrings2 = - formatKByteStrings(sunOSMBean.getTotalMemorySize(), - sunOSMBean.getFreeMemorySize(), + formatKByteStrings(tryToGet(sunOSMBean::getTotalMemorySize, + sunOSMBean::getTotalPhysicalMemorySize), + tryToGet(sunOSMBean::getFreeMemorySize, + sunOSMBean::getFreePhysicalMemorySize), sunOSMBean.getTotalSwapSpaceSize(), sunOSMBean.getFreeSwapSpaceSize()); @@ -317,6 +323,20 @@ synchronized Result formatSummary() { return result; } + /** + * Tries to get the specified value from the list of suppliers. + * Returns -1 if all suppliers fail. + */ + private long tryToGet(LongSupplier ... getters) { + for (LongSupplier getter : getters) { + try { + return getter.getAsLong(); + } catch (UndeclaredThrowableException e) { + } + } + return -1; + } + private synchronized void append(String str) { buf.append(str); } diff --git a/test/hotspot/gtest/metaspace/test_metachunklist.cpp b/test/hotspot/gtest/metaspace/test_metachunklist.cpp index 2d4d2c62dc8..14cf04675f3 100644 --- a/test/hotspot/gtest/metaspace/test_metachunklist.cpp +++ b/test/hotspot/gtest/metaspace/test_metachunklist.cpp @@ -112,7 +112,7 @@ TEST_VM(metaspace, freechunklist) { EXPECT_EQ(lst.num_chunks(), (int)cnt.count()); EXPECT_EQ(lst.word_size(), cnt.total_size()); - EXPECT_EQ(lst.committed_word_size(), committed_cnt.total_size()); + EXPECT_EQ(lst.calc_committed_word_size(), committed_cnt.total_size()); } // Drain each list separately, front to back. While draining observe the order @@ -137,7 +137,7 @@ TEST_VM(metaspace, freechunklist) { EXPECT_EQ(lst.num_chunks(), (int)cnt.count()); EXPECT_EQ(lst.word_size(), cnt.total_size()); - EXPECT_EQ(lst.committed_word_size(), committed_cnt.total_size()); + EXPECT_EQ(lst.calc_committed_word_size(), committed_cnt.total_size()); context.return_chunk(c); diff --git a/test/hotspot/gtest/metaspace/test_metaspacearena.cpp b/test/hotspot/gtest/metaspace/test_metaspacearena.cpp index 89ac6969a5b..96f6b70bbf0 100644 --- a/test/hotspot/gtest/metaspace/test_metaspacearena.cpp +++ b/test/hotspot/gtest/metaspace/test_metaspacearena.cpp @@ -504,7 +504,7 @@ static void test_recover_from_commit_limit_hit() { EXPECT_LE(allocated_from_3, Settings::commit_granule_words() * 2); // We expect the freelist to be empty of committed space... - EXPECT_0(context.cm().total_committed_word_size()); + EXPECT_0(context.cm().calc_committed_word_size()); //msthelper.cm().print_on(tty); @@ -515,7 +515,7 @@ static void test_recover_from_commit_limit_hit() { // Should have populated the freelist with committed space // We expect the freelist to be empty of committed space... - EXPECT_GT(context.cm().total_committed_word_size(), (size_t)0); + EXPECT_GT(context.cm().calc_committed_word_size(), (size_t)0); // Repeat allocation from helper3, should now work. helper3.allocate_from_arena_with_tests_expect_success(1); diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 75fbead6ab9..0e43740556c 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -87,6 +87,7 @@ gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293 macosx-x64 runtime/cds/DeterministicDump.java 8253495 generic-all runtime/jni/terminatedThread/TestTerminatedThread.java 8219652 aix-ppc64 runtime/ReservedStack/ReservedStackTest.java 8231031 generic-all +runtime/ReservedStack/ReservedStackTestCompiler.java 8256359 linux-aarch64 ############################################################################# diff --git a/test/hotspot/jtreg/compiler/arguments/TestDisableUseLoopSafepoints.java b/test/hotspot/jtreg/compiler/arguments/TestDisableUseLoopSafepoints.java new file mode 100644 index 00000000000..a799a919cb5 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arguments/TestDisableUseLoopSafepoints.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6232281 + * @requires vm.debug == true & vm.compiler2.enabled + * @summary Tests that C2 does not crash trivially with a "remove_useless_nodes + * missed this node" message when UseLoopSafepoints is disabled. + * @run main/othervm -Xcomp -XX:-TieredCompilation + -XX:CompileOnly=TestDisableUseLoopSafepoints -XX:-UseLoopSafepoints + * compiler.arguments.TestDisableUseLoopSafepoints + */ + +package compiler.arguments; + +public class TestDisableUseLoopSafepoints { + public static void main(String[] args) { + System.out.println("Passed"); + } +} diff --git a/test/hotspot/jtreg/compiler/arguments/TestPrintOptoAssemblyLineNumbers.java b/test/hotspot/jtreg/compiler/arguments/TestPrintOptoAssemblyLineNumbers.java new file mode 100644 index 00000000000..18e797fb4c1 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arguments/TestPrintOptoAssemblyLineNumbers.java @@ -0,0 +1,75 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8033441 + * @summary Test to ensure that line numbers are now present with the -XX:+PrintOptoAssembly command line option + * + * @requires vm.compiler2.enabled & vm.debug == true + * + * @library /compiler/patches /test/lib + * @run main/othervm compiler.arguments.TestPrintOptoAssemblyLineNumbers +*/ + +package compiler.arguments; + +import jdk.test.lib.Asserts; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class TestPrintOptoAssemblyLineNumbers { + public static void main(String[] args) throws Throwable { + // create subprocess to run some code with -XX:+PrintOptoAssembly enabled + String[] procArgs = new String[]{ + "-XX:+UnlockDiagnosticVMOptions", + "-XX:-TieredCompilation", + "-XX:+PrintOptoAssembly", + "compiler.arguments.TestPrintOptoAssemblyLineNumbers$CheckC2OptoAssembly" + }; + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(procArgs); + String output = new OutputAnalyzer(pb.start()).getOutput(); + + if(output.contains("TestPrintOptoAssemblyLineNumbers$CheckC2OptoAssembly::main @ bci:11")){ + // if C2 optimizer invoked ensure output includes line numbers: + Asserts.assertTrue(output.contains("TestPrintOptoAssemblyLineNumbers$CheckC2OptoAssembly::main @ bci:11 (line 68)")); + } + } + + public static class CheckC2OptoAssembly{ // contents of this class serves to just invoke C2 + public static boolean foo(String arg){ + return arg.contains("45"); + } + + public static void main(String[] args){ + int count = 0; + for(int x = 0; x < 200_000; x++){ + if(foo("something" + x)){ // <- test expects this line of code to be on line 68 + count += 1; + } + } + System.out.println("count: " + count); + } + } +} diff --git a/test/hotspot/jtreg/gc/shenandoah/jni/TestPinnedGarbage.java b/test/hotspot/jtreg/gc/shenandoah/jni/TestPinnedGarbage.java index 68167c87d89..96f00e516d6 100644 --- a/test/hotspot/jtreg/gc/shenandoah/jni/TestPinnedGarbage.java +++ b/test/hotspot/jtreg/gc/shenandoah/jni/TestPinnedGarbage.java @@ -28,12 +28,12 @@ * @requires vm.gc.Shenandoah * @library /test/lib * - * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx512m + * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx128m * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive * -XX:+ShenandoahVerify -XX:+ShenandoahDegeneratedGC * TestPinnedGarbage * - * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx512m + * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx128m * -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive * -XX:+ShenandoahVerify -XX:-ShenandoahDegeneratedGC * TestPinnedGarbage @@ -45,11 +45,11 @@ * @requires vm.gc.Shenandoah * @library /test/lib * - * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx512m + * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx128m * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive * TestPinnedGarbage * - * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx512m + * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx128m * -XX:+UseShenandoahGC * -XX:+ShenandoahVerify * TestPinnedGarbage @@ -65,26 +65,26 @@ public class TestPinnedGarbage { } private static final int NUM_RUNS = 1_000; - private static final int OBJS_COUNT = 1_000; - private static final int GARBAGE_COUNT = 1_000_000; + private static final int OBJS_COUNT = 1 << 10; + private static final int GARBAGE_COUNT = 1 << 18; private static native void pin(int[] a); private static native void unpin(int[] a); public static void main(String[] args) { + Random rng = Utils.getRandomInstance(); for (int i = 0; i < NUM_RUNS; i++) { - test(); + test(rng); } } - private static void test() { + private static void test(Random rng) { Object[] objs = new Object[OBJS_COUNT]; for (int i = 0; i < OBJS_COUNT; i++) { objs[i] = new MyClass(); } int[] cog = new int[10]; - Random rng = Utils.getRandomInstance(); int cogIdx = rng.nextInt(OBJS_COUNT); objs[cogIdx] = cog; pin(cog); diff --git a/test/hotspot/jtreg/runtime/logging/RedefineClasses.java b/test/hotspot/jtreg/runtime/logging/RedefineClasses.java index 1cabba35738..f1e577c9b10 100644 --- a/test/hotspot/jtreg/runtime/logging/RedefineClasses.java +++ b/test/hotspot/jtreg/runtime/logging/RedefineClasses.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, 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,7 +31,7 @@ * java.instrument * @requires vm.jvmti * @run main RedefineClassHelper - * @run main/othervm -Xmx256m -XX:MaxMetaspaceSize=64m -javaagent:redefineagent.jar -Xlog:all=trace:file=all.log RedefineClasses + * @run main/othervm -Xmx256m -XX:MaxMetaspaceSize=64m -javaagent:redefineagent.jar -XX:+Verbose -Xlog:all=trace:file=all.log RedefineClasses */ // package access top-level class to avoid problem with RedefineClassHelper diff --git a/test/hotspot/jtreg/runtime/logging/TestMethodHandlesVerbose.java b/test/hotspot/jtreg/runtime/logging/TestMethodHandlesVerbose.java index e3fa92fa68d..74a370464aa 100644 --- a/test/hotspot/jtreg/runtime/logging/TestMethodHandlesVerbose.java +++ b/test/hotspot/jtreg/runtime/logging/TestMethodHandlesVerbose.java @@ -26,10 +26,11 @@ * @bug 8244946 * @summary Run simple test with -XX:+Verbose and -Xlog:methodhandles. * - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+Verbose -Xlog:methodhandles TestMethodHandlesVerbose + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+Verbose -Xlog:methodhandles TestMethodHandlesVerbose a b */ public class TestMethodHandlesVerbose { public static void main(String[] args) { + System.out.println(args[0] + args[1]); } } diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java index da9d623f6d8..6101b00a24c 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, 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 @@ -257,6 +257,7 @@ private Pair getLastClass(Path errFile) { private String[] cmd(long classStart, long classStop) { String phase = phaseName(classStart); Path file = Paths.get(phase + ".cmd"); + var rng = Utils.getRandomInstance(); try { Files.write(file, List.of( "-Xbatch", @@ -283,6 +284,13 @@ private String[] cmd(long classStart, long classStop) { String.format("-XX:ReplayDataFile=replay_%s_%%p.log", phase), // MethodHandle MUST NOT be compiled "-XX:CompileCommand=exclude,java/lang/invoke/MethodHandle.*", + // Stress* are c2-specific stress flags, so IgnoreUnrecognizedVMOptions is needed + "-XX:+IgnoreUnrecognizedVMOptions", + "-XX:+StressLCM", + "-XX:+StressGCM", + "-XX:+StressIGVN", + // StressSeed is uint + "-XX:StressSeed=" + Math.abs(rng.nextLong()), // CTW entry point CompileTheWorld.class.getName(), target)); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/general_functions/GF08/gf08t001/TestDriver.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/general_functions/GF08/gf08t001/TestDriver.java index 4b3dac65d46..73bfef58eb9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/general_functions/GF08/gf08t001/TestDriver.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/general_functions/GF08/gf08t001/TestDriver.java @@ -62,15 +62,17 @@ */ import sun.hotspot.code.Compiler; +import sun.hotspot.WhiteBox; +import sun.hotspot.gc.GC; public class TestDriver { public static void main(String[] args) throws Exception { - sun.hotspot.WhiteBox wb = sun.hotspot.WhiteBox.getWhiteBox(); + WhiteBox wb = WhiteBox.getWhiteBox(); Boolean isExplicitGCInvokesConcurrentOn = wb.getBooleanVMFlag("ExplicitGCInvokesConcurrent"); - Boolean isUseG1GCon = wb.getBooleanVMFlag("UseG1GC"); - Boolean isUseZGCon = wb.getBooleanVMFlag("UseZGC"); - Boolean isShenandoahGCon = wb.getBooleanVMFlag("UseShenandoahGC"); - Boolean isUseEpsilonGCon = wb.getBooleanVMFlag("UseEpsilonGC"); + boolean isUseG1GCon = GC.G1.isSelected(); + boolean isUseZGCon = GC.Z.isSelected(); + boolean isShenandoahGCon = GC.Shenandoah.isSelected(); + boolean isUseEpsilonGCon = GC.Epsilon.isSelected(); if (Compiler.isGraalEnabled() && (isUseZGCon || isUseEpsilonGCon || isShenandoahGCon)) { diff --git a/test/jdk/java/math/BigInteger/BigIntegerTest.java b/test/jdk/java/math/BigInteger/BigIntegerTest.java index 8d043c57649..9e19f2039b0 100644 --- a/test/jdk/java/math/BigInteger/BigIntegerTest.java +++ b/test/jdk/java/math/BigInteger/BigIntegerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, 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 @@ -26,7 +26,7 @@ * @library /test/lib * @build jdk.test.lib.RandomFactory * @run main BigIntegerTest - * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946 4026465 8074460 8078672 8032027 + * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946 4026465 8074460 8078672 8032027 8229845 * @summary tests methods in BigInteger (use -Dseed=X to set PRNG seed) * @run main/timeout=400 BigIntegerTest * @author madbot @@ -795,7 +795,7 @@ public static void stringConv() { // Generic string conversion. for (int i=0; i<100; i++) { - byte xBytes[] = new byte[Math.abs(random.nextInt())%100+1]; + byte xBytes[] = new byte[Math.abs(random.nextInt())%200+1]; random.nextBytes(xBytes); BigInteger x = new BigInteger(xBytes); @@ -836,6 +836,16 @@ public static void stringConv() { } } + // Check value with many trailing zeros. + String val = "123456789" + "0".repeat(200); + BigInteger b = new BigInteger(val); + String s = b.toString(); + if (!val.equals(s)) { + System.err.format("Expected length %d but got %d%n", + val.length(), s.length()); + failCount++; + } + report("String Conversion", failCount); } diff --git a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/VendorTest.java b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/VendorTest.java new file mode 100644 index 00000000000..eb469ea130a --- /dev/null +++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/VendorTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2020, 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. + */ + +package jdk.jpackage.tests; + +import jdk.jpackage.test.PackageTest; +import jdk.jpackage.test.PackageType; +import jdk.jpackage.test.Annotations.Test; + +/** + * Test --vendor parameter. Output of the test should be + * vendortest*.* package bundle. The output package should provide the + * same functionality as the default package with the default value of vendor + * property overridden. + * + * Linux DEB: + * + * Value of "Maintainer" property of .deb package should start with "Test Vendor" string. + * + * Linux RPM: + * + * Value of "Vendor" property of .rpm package should be set to "Test Vendor" string. + * + * Mac: + * + * --vendor parameter is ignored. + * + * Windows: + * + * Publisher value displayed in the Add/Remove Programs should be set + * to "Test Vendor" string. + */ + +/* + * @test + * @summary Test --vendor jpackage command option + * @library ../../../../helpers + * @key jpackagePlatformPackage + * @requires (os.family == "windows") + * @requires jpackage.test.SQETest != null + * @build jdk.jpackage.test.* + * @modules jdk.jpackage/jdk.jpackage.internal + * @compile VendorTest.java + * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * --jpt-run=jdk.jpackage.tests.VendorTest + */ + +/* + * @test + * @summary Test --vendor jpackage command option + * @library ../../../../helpers + * @key jpackagePlatformPackage + * @requires (os.family != "mac") + * @requires jpackage.test.SQETest == null + * @build jdk.jpackage.test.* + * @modules jdk.jpackage/jdk.jpackage.internal + * @compile VendorTest.java + * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * --jpt-run=jdk.jpackage.tests.VendorTest + */ +public class VendorTest { + + @Test + public static void test() { + final String vendorValue = "Test Vendor"; + + new PackageTest() + .configureHelloApp() + .addBundleDesktopIntegrationVerifier(false) + .addInitializer(cmd -> { + cmd.addArguments("--vendor", vendorValue); + }) + .forTypes(PackageType.LINUX_DEB) + .addBundlePropertyVerifier("Maintainer", value -> { + return value.startsWith(vendorValue + " "); + }, "starts with") + .forTypes(PackageType.LINUX_RPM) + .addBundlePropertyVerifier("Vendor", value -> { + return value.equals(vendorValue); + }, "equals to") + .forTypes(PackageType.WIN_MSI) + .addBundlePropertyVerifier("Manufacturer", value -> { + return value.equals(vendorValue); + }, "equals to") + .run(); + } +} diff --git a/test/micro/org/openjdk/bench/java/security/PKCS12KeyStores.java b/test/micro/org/openjdk/bench/java/security/PKCS12KeyStores.java new file mode 100644 index 00000000000..9c8f378fb9b --- /dev/null +++ b/test/micro/org/openjdk/bench/java/security/PKCS12KeyStores.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2020, 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. + */ +package org.openjdk.bench.java.security; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.math.BigInteger; +import java.security.*; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.*; + +/** + * Tests various algorithm settings for PKCS12 keystores. + */ +@State(Scope.Benchmark) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Warmup(iterations = 2) +@Measurement(iterations = 10) +@BenchmarkMode(Mode.AverageTime) +@Fork(jvmArgsAppend = {"-Xms1024m", "-Xmx1024m", "-Xmn768m", "-XX:+UseParallelGC"}, value = 5) +public class PKCS12KeyStores { + + private static final char[] PASS = "changeit".toCharArray(); + + private Key pk; + private Certificate[] certs; + + // Several pkcs12 keystores in byte arrays + private byte[] bw2048; + private byte[] bw50000; // Default old + private byte[] bs50000; + private byte[] bs10000; // Default new + private byte[] bs2048; + + // Decodes HEX string to byte array + private static byte[] xeh(String in) { + return new BigInteger(in, 16).toByteArray(); + } + + @Setup + public void setup() throws Exception { + // Just generate a keypair and dump getEncoded() of key and cert. + byte[] x1 = xeh("3041020100301306072A8648CE3D020106082A8648CE3D03" + + "0107042730250201010420B561D1FBE150488508BBE8FF4540F09057" + + "58712F5D2D3CC80F9A15BA5D481117"); + byte[] x2 = xeh("3082012D3081D5A00302010202084EE6ECC5585640A7300A" + + "06082A8648CE3D040302300C310A30080603550403130161301E170D" + + "3230313131373230343730355A170D3233303831343230343730355A" + + "300C310A300806035504031301613059301306072A8648CE3D020106" + + "082A8648CE3D030107034200041E761F511841602E272B40A021995D" + + "1BD828DDC7F71412D6A66CC0CB858C856D32C58273E494676D1D2B05" + + "B8E9B08207A122265C2AA5FCBDCE19E5E88CA7A1B6A321301F301D06" + + "03551D0E04160414173F278D77096E5C8EA182D12F147694587B5D9A" + + "300A06082A8648CE3D04030203470030440220760CEAF1FA7041CB8C" + + "1CA80AF60E4F9C9D5136D96B2AF0AAA9440F79561C44E502205D5C72" + + "886C92B95A681C4393C67AAEC8DA9FD7910FF9BF2BCB721AE71D1B6F88"); + KeyFactory kf = KeyFactory.getInstance("EC"); + pk = kf.generatePrivate(new PKCS8EncodedKeySpec(x1)); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + certs = new Certificate[]{cf.generateCertificate(new ByteArrayInputStream(x2))}; + + bw2048 = outweak2048(); + bw50000 = outweak50000_Old(); + bs50000 = outstrong50000(); + bs10000 = outstrong10000_New(); + bs2048 = outstrong2048(); + } + + // Reads in a pkcs12 keystore + private KeyStore in(byte[] b) throws Exception { + KeyStore ks = KeyStore.getInstance("pkcs12"); + ks.load(new ByteArrayInputStream(b), PASS); + if (!ks.getCertificate("a").getPublicKey().getAlgorithm().equals( + ks.getKey("a", PASS).getAlgorithm())) { + throw new RuntimeException("Not same alg"); + } + return ks; + } + + // Generates a pkcs12 keystore with the specified algorithm/ic + private byte[] out(String cAlg, String cIc, String kAlg, String kIc, + String mAlg, String mIc) throws Exception { + System.setProperty("keystore.pkcs12.certProtectionAlgorithm", cAlg); + System.setProperty("keystore.pkcs12.certPbeIterationCount", cIc); + System.setProperty("keystore.pkcs12.keyProtectionAlgorithm", kAlg); + System.setProperty("keystore.pkcs12.keyPbeIterationCount", kIc); + System.setProperty("keystore.pkcs12.macAlgorithm", mAlg); + System.setProperty("keystore.pkcs12.macIterationCount", mIc); + KeyStore ks = KeyStore.getInstance("pkcs12"); + ks.load(null, null); + ks.setKeyEntry("a", pk, PASS, certs); + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + ks.store(bout, PASS); + return bout.toByteArray(); + } + + // Benchmark methods start here: + + // Reading a keystore + @Benchmark + public KeyStore inweak2048() throws Exception { + return in(bw2048); + } + + @Benchmark + public KeyStore inweak50000_Old() throws Exception { + return in(bw50000); + } + + @Benchmark + public KeyStore instrong50000() throws Exception { + return in(bs50000); + } + + @Benchmark + public KeyStore instrong10000_New() throws Exception { + return in(bs10000); + } + + @Benchmark + public KeyStore instrong2048() throws Exception { + return in(bs2048); + } + + // Writing a keystore + @Benchmark + public byte[] outweak2048() throws Exception { + return out("PBEWithSHA1AndRC2_40", "2048", + "PBEWithSHA1AndDESede", "2048", + "HmacPBESHA1", "2048"); + } + + @Benchmark + public byte[] outweak50000_Old() throws Exception { + return out("PBEWithSHA1AndRC2_40", "50000", + "PBEWithSHA1AndDESede", "50000", + "HmacPBESHA1", "100000"); + // Attention: 100000 is old default Mac ic + } + + @Benchmark + public byte[] outstrong50000() throws Exception { + return out("PBEWithHmacSHA256AndAES_256", "50000", + "PBEWithHmacSHA256AndAES_256", "50000", + "HmacPBESHA256", "100000"); + // Attention: 100000 is old default Mac ic + } + + @Benchmark + public byte[] outstrong10000_New() throws Exception { + return out("PBEWithHmacSHA256AndAES_256", "10000", + "PBEWithHmacSHA256AndAES_256", "10000", + "HmacPBESHA256", "10000"); + } + + @Benchmark + public byte[] outstrong2048() throws Exception { + return out("PBEWithHmacSHA256AndAES_256", "2048", + "PBEWithHmacSHA256AndAES_256", "2048", + "HmacPBESHA256", "2048"); + } +}