diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml new file mode 100644 index 00000000000..91a69d10292 --- /dev/null +++ b/.github/workflows/android.yml @@ -0,0 +1,26 @@ +name: Android CI + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: set up JDK 11 + uses: actions/setup-java@v4 + with: + java-version: '11' + distribution: 'temurin' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Build with Gradle + run: ./gradlew build diff --git a/.github/workflows/build-cross-compile.yml b/.github/workflows/build-cross-compile.yml index 99b6c40606c..c80f676864e 100644 --- a/.github/workflows/build-cross-compile.yml +++ b/.github/workflows/build-cross-compile.yml @@ -54,18 +54,11 @@ jobs: fail-fast: false matrix: target-cpu: - - aarch64 - arm - s390x - ppc64le - riscv64 include: - - target-cpu: aarch64 - gnu-arch: aarch64 - debian-arch: arm64 - debian-repository: https://httpredir.debian.org/debian/ - debian-version: trixie - tolerate-sysroot-errors: false - target-cpu: arm gnu-arch: arm debian-arch: armhf diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index c501670439e..a77ebece7e2 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -31,6 +31,14 @@ on: platform: required: true type: string + runs-on: + required: false + type: string + default: 'ubuntu-24.04' + bootjdk-platform: + required: false + type: string + default: 'linux-x64' extra-conf-options: required: false type: string @@ -75,7 +83,7 @@ on: jobs: build-linux: name: build - runs-on: ubuntu-24.04 + runs-on: ${{ inputs.runs-on }} strategy: fail-fast: false @@ -90,7 +98,7 @@ jobs: id: bootjdk uses: ./.github/actions/get-bootjdk with: - platform: linux-x64 + platform: ${{ inputs.bootjdk-platform }} - name: 'Get JTReg' id: jtreg diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 94f011ff76c..f3cd8904868 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -34,7 +34,7 @@ on: platforms: description: 'Platform(s) to execute on (comma separated, e.g. "linux-x64, macos, aarch64")' required: true - default: 'linux-x64, linux-x64-variants, linux-cross-compile, alpine-linux-x64, macos-x64, macos-aarch64, windows-x64, windows-aarch64, docs' + default: 'linux-x64, linux-x64-variants, linux-aarch64, linux-cross-compile, alpine-linux-x64, macos-x64, macos-aarch64, windows-x64, windows-aarch64, docs' configure-arguments: description: 'Additional configure arguments' required: false @@ -64,6 +64,7 @@ jobs: outputs: linux-x64: ${{ steps.include.outputs.linux-x64 }} linux-x64-variants: ${{ steps.include.outputs.linux-x64-variants }} + linux-aarch64: ${{ steps.include.outputs.linux-aarch64 }} linux-cross-compile: ${{ steps.include.outputs.linux-cross-compile }} alpine-linux-x64: ${{ steps.include.outputs.alpine-linux-x64 }} macos-x64: ${{ steps.include.outputs.macos-x64 }} @@ -176,6 +177,7 @@ jobs: echo "linux-x64=$(check_platform linux-x64 linux x64)" >> $GITHUB_OUTPUT echo "linux-x64-variants=$(check_platform linux-x64-variants variants)" >> $GITHUB_OUTPUT + echo "linux-aarch64=$(check_platform linux-aarch64 linux aarch64)" >> $GITHUB_OUTPUT echo "linux-cross-compile=$(check_platform linux-cross-compile cross-compile)" >> $GITHUB_OUTPUT echo "alpine-linux-x64=$(check_platform alpine-linux-x64 alpine-linux x64)" >> $GITHUB_OUTPUT echo "macos-x64=$(check_platform macos-x64 macos x64)" >> $GITHUB_OUTPUT @@ -201,6 +203,20 @@ jobs: dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} if: needs.prepare.outputs.linux-x64 == 'true' + build-linux-aarch64: + name: linux-aarch64 + needs: prepare + uses: ./.github/workflows/build-linux.yml + with: + platform: linux-aarch64 + runs-on: 'ubuntu-24.04-arm' + bootjdk-platform: linux-aarch64 + gcc-major-version: '14' + configure-arguments: ${{ github.event.inputs.configure-arguments }} + make-arguments: ${{ github.event.inputs.make-arguments }} + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} + if: needs.prepare.outputs.linux-aarch64 == 'true' + build-linux-x64-hs-nopch: name: linux-x64-hs-nopch needs: prepare @@ -425,6 +441,19 @@ jobs: dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} static-suffix: "-static" + test-linux-aarch64: + name: linux-aarch64 + needs: + - prepare + - build-linux-aarch64 + uses: ./.github/workflows/test.yml + with: + platform: linux-aarch64 + bootjdk-platform: linux-aarch64 + runs-on: ubuntu-24.04-arm + dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} + debug-suffix: -debug + test-macos-aarch64: name: macos-aarch64 needs: diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 00000000000..c6bb03654fa --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,35 @@ +# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Java CI with Maven + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + cache: maven + - name: Build with Maven + run: mvn -B package --file pom.xml + + # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive + - name: Update dependency graph + uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 diff --git a/make/Images.gmk b/make/Images.gmk index 89c0a834477..8008cfa6779 100644 --- a/make/Images.gmk +++ b/make/Images.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2026, 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 @@ -137,16 +137,16 @@ CDS_DUMP_FLAGS = -Xmx128M -Xms128M # Helper function for creating the CDS archives for the JDK and JRE # # Param1 - VM variant (e.g., server, client, zero, ...) -# Param2 - _nocoops, _coh, _nocoops_coh, or empty +# Param2 - _nocoops, _nocoh, _nocoops_nocoh, or empty define CreateCDSArchive $1_$2_COOPS_OPTION := $(if $(findstring _nocoops, $2),-XX:-UseCompressedOops) # enable and also explicitly disable coh as needed. ifeq ($(call isTargetCpuBits, 64), true) - $1_$2_COH_OPTION := -XX:+UnlockExperimentalVMOptions \ - $(if $(findstring _coh, $2),-XX:+UseCompactObjectHeaders,-XX:-UseCompactObjectHeaders) + $1_$2_NOCOH_OPTION := -XX:+UnlockExperimentalVMOptions \ + $(if $(findstring _nocoh, $2),-XX:-UseCompactObjectHeaders,-XX:+UseCompactObjectHeaders) endif - $1_$2_DUMP_EXTRA_ARG := $$($1_$2_COOPS_OPTION) $$($1_$2_COH_OPTION) - $1_$2_DUMP_TYPE := $(if $(findstring _nocoops, $2),-NOCOOPS,)$(if $(findstring _coh, $2),-COH,) + $1_$2_DUMP_EXTRA_ARG := $$($1_$2_COOPS_OPTION) $$($1_$2_NOCOH_OPTION) + $1_$2_DUMP_TYPE := $(if $(findstring _nocoops, $2),-NOCOOPS,)$(if $(findstring _nocoh, $2),-NOCOH,) $1_$2_CDS_DUMP_FLAGS := $(CDS_DUMP_FLAGS) $(if $(filter g1gc, $(JVM_FEATURES_$1)), -XX:+UseG1GC) @@ -200,12 +200,12 @@ ifeq ($(BUILD_CDS_ARCHIVE), true) $(foreach v, $(JVM_VARIANTS), \ $(eval $(call CreateCDSArchive,$v,_nocoops)) \ ) - ifeq ($(BUILD_CDS_ARCHIVE_COH), true) + ifeq ($(BUILD_CDS_ARCHIVE_NOCOH), true) $(foreach v, $(JVM_VARIANTS), \ - $(eval $(call CreateCDSArchive,$v,_coh)) \ + $(eval $(call CreateCDSArchive,$v,_nocoh)) \ ) $(foreach v, $(JVM_VARIANTS), \ - $(eval $(call CreateCDSArchive,$v,_nocoops_coh)) \ + $(eval $(call CreateCDSArchive,$v,_nocoops_nocoh)) \ ) endif endif diff --git a/make/RunTests.gmk b/make/RunTests.gmk index d4be5936c41..1eb81499505 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -972,11 +972,6 @@ define SetupRunJtregTestBody JTREG_AUTO_PROBLEM_LISTS += ProblemList-enable-preview.txt endif - ifneq ($$(findstring -XX:+UseCompactObjectHeaders, $$(JTREG_ALL_OPTIONS)), ) - JTREG_AUTO_PROBLEM_LISTS += ProblemList-coh.txt - endif - - ifneq ($$(JTREG_EXTRA_PROBLEM_LISTS), ) # Accept both absolute paths as well as relative to the current test root. $1_JTREG_BASIC_OPTIONS += $$(addprefix $$(JTREG_PROBLEM_LIST_PREFIX), $$(wildcard \ diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac index 2e608f893d6..6d65ad93c40 100644 --- a/make/autoconf/configure.ac +++ b/make/autoconf/configure.ac @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2026, 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 @@ -260,7 +260,7 @@ LIB_TESTS_ENABLE_DISABLE_JTREG_TEST_THREAD_FACTORY JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST JDKOPT_EXCLUDE_TRANSLATIONS JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE -JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE_COH +JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE_NOCOH JDKOPT_ENABLE_DISABLE_COMPATIBLE_CDS_ALIGNMENT JDKOPT_SETUP_MACOSX_SIGNING JDKOPT_SETUP_SIGNING_HOOK diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 5b1e4c3d7f7..465e06ab39d 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -786,14 +786,14 @@ AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE], # # Enable or disable the default CDS archive generation for Compact Object Headers # -AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE_COH], +AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE_NOCOH], [ - UTIL_ARG_ENABLE(NAME: cds-archive-coh, DEFAULT: auto, RESULT: BUILD_CDS_ARCHIVE_COH, - DESC: [enable generation of default CDS archives for compact object headers (requires --enable-cds-archive)], + UTIL_ARG_ENABLE(NAME: cds-archive-nocoh, DEFAULT: auto, RESULT: BUILD_CDS_ARCHIVE_NOCOH, + DESC: [enable generation of default CDS archives for no compact object headers (requires --enable-cds-archive)], DEFAULT_DESC: [auto], - CHECKING_MSG: [if default CDS archives for compact object headers should be generated], + CHECKING_MSG: [if default CDS archives for no compact object headers should be generated], CHECK_AVAILABLE: [ - AC_MSG_CHECKING([if CDS archive with compact object headers is available]) + AC_MSG_CHECKING([if CDS archive with no compact object headers is available]) if test "x$BUILD_CDS_ARCHIVE" = "xfalse"; then AC_MSG_RESULT([no (CDS default archive generation is disabled)]) AVAILABLE=false @@ -810,7 +810,7 @@ AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE_COH], AVAILABLE=true fi ]) - AC_SUBST(BUILD_CDS_ARCHIVE_COH) + AC_SUBST(BUILD_CDS_ARCHIVE_NOCOH) ]) ################################################################################ diff --git a/make/autoconf/spec.gmk.template b/make/autoconf/spec.gmk.template index 7de5056cb83..15cd5c22d6d 100644 --- a/make/autoconf/spec.gmk.template +++ b/make/autoconf/spec.gmk.template @@ -369,7 +369,7 @@ ENABLE_GENERATE_CLASSLIST := @ENABLE_GENERATE_CLASSLIST@ EXCLUDE_TRANSLATIONS := @EXCLUDE_TRANSLATIONS@ BUILD_CDS_ARCHIVE := @BUILD_CDS_ARCHIVE@ -BUILD_CDS_ARCHIVE_COH := @BUILD_CDS_ARCHIVE_COH@ +BUILD_CDS_ARCHIVE_NOCOH := @BUILD_CDS_ARCHIVE_NOCOH@ ENABLE_COMPATIBLE_CDS_ALIGNMENT := @ENABLE_COMPATIBLE_CDS_ALIGNMENT@ diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf index 6771e8923dc..320ec49a850 100644 --- a/make/conf/github-actions.conf +++ b/make/conf/github-actions.conf @@ -32,6 +32,10 @@ LINUX_X64_BOOT_JDK_EXT=tar.gz LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk26/c3cc523845074aa0af4f5e1e1ed4151d/35/GPL/openjdk-26_linux-x64_bin.tar.gz LINUX_X64_BOOT_JDK_SHA256=83c78367f8c81257beef72aca4bbbf8e6dac8ca2b3a4546a85879a09e6e4e128 +LINUX_AARCH64_BOOT_JDK_EXT=tar.gz +LINUX_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk26/c3cc523845074aa0af4f5e1e1ed4151d/35/GPL/openjdk-26_linux-aarch64_bin.tar.gz +LINUX_AARCH64_BOOT_JDK_SHA256=403ccf451e88d0be9e1dec129fcb9318de9752121e0eb92dfa9a8cf06f249007 + ALPINE_LINUX_X64_BOOT_JDK_EXT=tar.gz ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin26-binaries/releases/download/jdk-26%2B35/OpenJDK26U-jdk_x64_alpine-linux_hotspot_26_35.tar.gz ALPINE_LINUX_X64_BOOT_JDK_SHA256=c105e581fdccb4e7120d889235d1ad8d5b2bed0af4972bc881e0a8ba687c94a4 diff --git a/make/modules/jdk.jcmd/Copy.gmk b/make/modules/jdk.jcmd/Copy.gmk new file mode 100644 index 00000000000..f3240f9f61d --- /dev/null +++ b/make/modules/jdk.jcmd/Copy.gmk @@ -0,0 +1,42 @@ +# +# Copyright (c) 2026, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +################################################################################ + +include CopyCommon.gmk + +# the autocompletion script is Bash-only +ifneq ($(call isTargetOsType, windows), true) + JCMD_CONF_DIR := $(TOPDIR)/src/jdk.jcmd/share/conf + $(eval $(call SetupCopyFiles, COPY_JCMD_BASH_COMPLETION, \ + DEST := $(CONF_DST_DIR)/bash-completion, \ + SRC := $(JCMD_CONF_DIR)/bash-completion, \ + FILES := jcmd, \ + )) +endif + +TARGETS += $(COPY_JCMD_BASH_COMPLETION) + +################################################################################ diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 7487de2d577..c6dc1bdfed2 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -2647,19 +2647,45 @@ static bool is_valid_sve_arith_imm_pattern(Node* n, Node* m) { } // (XorV src (Replicate m1)) -// (XorVMask src (MaskAll m1)) static bool is_vector_bitwise_not_pattern(Node* n, Node* m) { if (n != nullptr && m != nullptr) { - return (n->Opcode() == Op_XorV || n->Opcode() == Op_XorVMask) && + return n->Opcode() == Op_XorV && VectorNode::is_all_ones_vector(m); } return false; } +// Returns true if (n, m) matches "(XorVMask vm2 (MaskAll m1))" and that XorVMask +// is used only by an AndVMask. In that case, cloning m (the MaskAll) lets the +// matcher avoid sharing the MaskAll node and subsume the pattern into rule: +// "(AndVMask vm1 (XorVMask vm2 (MaskAll m1)))". +// +// Limitation: the "andNot" rule still cannot be matched if "m" has other +// uses outside this pattern. +static bool is_vector_mask_not_operand_in_andnot_pattern(Node* n, Node* m) { + if (n == nullptr || m == nullptr) { + return false; + } + + if (VectorNode::is_all_ones_vector(m) && + n->Opcode() == Op_XorVMask && + n->outcnt() == 1 && + n->unique_out()->Opcode() == Op_AndVMask) { + // If another input of the AndVMask is also a mask-not pattern that would + // qualify for the `maskAll` cloning, do not clone the "maskAll" here, + // because the match rule can only consume one such pattern. + Node* use = n->unique_out(); + Node* other_input = use->in(1) == n ? use->in(2) : use->in(1); + return !VectorNode::is_vectormask_bitwise_not_pattern(other_input); + } + return false; +} + // Should the matcher clone input 'm' of node 'n'? bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) { if (is_vshift_con_pattern(n, m) || is_vector_bitwise_not_pattern(n, m) || + is_vector_mask_not_operand_in_andnot_pattern(n, m) || is_valid_sve_arith_imm_pattern(n, m) || is_encode_and_store_pattern(n, m)) { mstack.push(m, Visit); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index f385a3d2eff..7d920704131 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -2667,7 +2667,7 @@ int MacroAssembler::corrected_idivq(Register result, Register ra, Register rb, void MacroAssembler::membar(Membar_mask_bits order_constraint) { address prev = pc() - NativeMembar::instruction_size; - address last = code()->last_insn(); + address last = code()->last_merge_candidate(); if (last != nullptr && nativeInstruction_at(last)->is_Membar() && prev == last) { NativeMembar *bar = NativeMembar_at(prev); if (AlwaysMergeDMB) { @@ -2699,21 +2699,21 @@ void MacroAssembler::membar(Membar_mask_bits order_constraint) { } } } - code()->set_last_insn(pc()); + code()->set_last_merge_candidate(pc()); dmb(Assembler::barrier(order_constraint)); } bool MacroAssembler::try_merge_ldst(Register rt, const Address &adr, size_t size_in_bytes, bool is_store) { if (ldst_can_merge(rt, adr, size_in_bytes, is_store)) { merge_ldst(rt, adr, size_in_bytes, is_store); - code()->clear_last_insn(); + code()->clear_last_merge_candidate(); return true; } else { assert(size_in_bytes == 8 || size_in_bytes == 4, "only 8 bytes or 4 bytes load/store is supported."); const uint64_t mask = size_in_bytes - 1; if (adr.getMode() == Address::base_plus_offset && (adr.offset() & mask) == 0) { // only supports base_plus_offset. - code()->set_last_insn(pc()); + code()->set_last_merge_candidate(pc()); } return false; } @@ -3876,7 +3876,7 @@ bool MacroAssembler::ldst_can_merge(Register rt, size_t cur_size_in_bytes, bool is_store) const { address prev = pc() - NativeInstruction::instruction_size; - address last = code()->last_insn(); + address last = code()->last_merge_candidate(); if (last == nullptr || !nativeInstruction_at(last)->is_Imm_LdSt()) { return false; diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index c02df666a87..a338098cb53 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -168,7 +168,7 @@ class MacroAssembler: public Assembler { void bind(Label& L) { Assembler::bind(L); - code()->clear_last_insn(); + code()->clear_last_merge_candidate(); code()->set_last_label(pc()); } diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 0e32c602d95..02798d5204a 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -4117,7 +4117,7 @@ void MacroAssembler::membar(uint32_t order_constraint) { } address prev = pc() - MacroAssembler::instruction_size; - address last = code()->last_insn(); + address last = code()->last_merge_candidate(); if (last != nullptr && is_membar(last) && prev == last) { // We are merging two memory barrier instructions. On RISCV we @@ -4127,7 +4127,7 @@ void MacroAssembler::membar(uint32_t order_constraint) { return; } - code()->set_last_insn(pc()); + code()->set_last_merge_candidate(pc()); uint32_t predecessor = 0; uint32_t successor = 0; membar_mask_to_pred_succ(order_constraint, predecessor, successor); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index 4cc55e7ae23..6e592b5c852 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -876,7 +876,7 @@ class MacroAssembler: public Assembler { void bind(Label& L) { Assembler::bind(L); // fences across basic blocks should not be merged - code()->clear_last_insn(); + code()->clear_last_merge_candidate(); } typedef void (MacroAssembler::* compare_and_branch_insn)(Register Rs1, Register Rs2, const address dest); diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index 5802217c1c1..392ef78a71d 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -3967,7 +3967,7 @@ void MatchNode::count_commutative_op(int& count) { static const char *commut_vector_op_list[] = { "AddVB", "AddVS", "AddVI", "AddVL", "AddVHF", "AddVF", "AddVD", "MulVB", "MulVS", "MulVI", "MulVL", "MulVHF", "MulVF", "MulVD", - "AndV", "OrV", "XorV", + "AndV", "OrV", "XorV", "AndVMask", "OrVMask", "XorVMask", "MaxVHF", "MinVHF", "MaxV", "MinV", "UMax","UMin" }; diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp index c6475050592..55ba27fcbe1 100644 --- a/src/hotspot/share/asm/codeBuffer.cpp +++ b/src/hotspot/share/asm/codeBuffer.cpp @@ -937,8 +937,8 @@ void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) { // Move all the code and relocations to the new blob: relocate_code_to(&cb); - // some internal addresses, _last_insn _last_label, are used during code emission, - // adjust them in expansion + // some internal addresses, _last_merge_candidate and _last_label, are used during + // code emission, adjust them in expansion adjust_internal_address(insts_begin(), cb.insts_begin()); // Copy the temporary code buffer into the current code buffer. @@ -966,8 +966,8 @@ void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) { } void CodeBuffer::adjust_internal_address(address from, address to) { - if (_last_insn != nullptr) { - _last_insn += to - from; + if (_last_merge_candidate != nullptr) { + _last_merge_candidate += to - from; } if (_last_label != nullptr) { _last_label += to - from; diff --git a/src/hotspot/share/asm/codeBuffer.hpp b/src/hotspot/share/asm/codeBuffer.hpp index 38e151273da..ea0237f1401 100644 --- a/src/hotspot/share/asm/codeBuffer.hpp +++ b/src/hotspot/share/asm/codeBuffer.hpp @@ -561,11 +561,11 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) { OopRecorder* _oop_recorder; - OopRecorder _default_oop_recorder; // override with initialize_oop_recorder + OopRecorder _default_oop_recorder; // override with initialize_oop_recorder Arena* _overflow_arena; - address _last_insn; // used to merge consecutive memory barriers, loads or stores. - address _last_label; // record last bind label address, it's also the start of current bb. + address _last_label; // record last bind label address, it's also the start of current bb. + address _last_merge_candidate; // used to merge consecutive memory barriers, loads or stores. SharedStubToInterpRequests* _shared_stub_to_interp_requests; // used to collect requests for shared iterpreter stubs SharedTrampolineRequests* _shared_trampoline_requests; // used to collect requests for shared trampolines @@ -591,11 +591,11 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) { _total_size = 0; _oop_recorder = nullptr; _overflow_arena = nullptr; - _last_insn = nullptr; _last_label = nullptr; - _finalize_stubs = false; + _last_merge_candidate = nullptr; _shared_stub_to_interp_requests = nullptr; _shared_trampoline_requests = nullptr; + _finalize_stubs = false; _consts.initialize_outer(this, SECT_CONSTS); _insts.initialize_outer(this, SECT_INSTS); @@ -812,9 +812,9 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) { OopRecorder* oop_recorder() const { return _oop_recorder; } - address last_insn() const { return _last_insn; } - void set_last_insn(address a) { _last_insn = a; } - void clear_last_insn() { set_last_insn(nullptr); } + address last_merge_candidate() const { return _last_merge_candidate; } + void set_last_merge_candidate(address a) { _last_merge_candidate = a; } + void clear_last_merge_candidate() { set_last_merge_candidate(nullptr); } address last_label() const { return _last_label; } void set_last_label(address a) { _last_label = a; } diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index e1f66759197..72ba586be98 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -139,10 +139,10 @@ const char* CDSConfig::default_archive_path() { if (!UseCompressedOops) { tmp.print_raw("_nocoops"); } - if (UseCompactObjectHeaders) { - // Note that generation of xxx_coh.jsa variants require - // --enable-cds-archive-coh at build time - tmp.print_raw("_coh"); + if (!UseCompactObjectHeaders) { + // Note that generation of xxx_nocoh.jsa variants require + // --enable-cds-archive-nocoh at build time + tmp.print_raw("_nocoh"); } #endif tmp.print_raw(".jsa"); diff --git a/src/hotspot/share/code/aotCodeCache.cpp b/src/hotspot/share/code/aotCodeCache.cpp index 0e4aea0806b..aec23ded100 100644 --- a/src/hotspot/share/code/aotCodeCache.cpp +++ b/src/hotspot/share/code/aotCodeCache.cpp @@ -1017,11 +1017,6 @@ bool AOTCodeCache::store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind if (AOTCodeEntry::is_blob(entry_kind) && !is_dumping_stub()) { return false; } - // we do not currently store C2 stubs because we are seeing weird - // memory errors when loading them -- see JDK-8357593 - if (entry_kind == AOTCodeEntry::C2Blob) { - return false; - } log_debug(aot, codecache, stubs)("Writing blob '%s' (id=%u, kind=%s) to AOT Code Cache", name, id, aot_code_entry_kind_name[entry_kind]); #ifdef ASSERT @@ -1292,11 +1287,6 @@ CodeBlob* AOTCodeCache::load_code_blob(AOTCodeEntry::Kind entry_kind, uint id, c if (AOTCodeEntry::is_blob(entry_kind) && !is_using_stub()) { return nullptr; } - // we do not currently load C2 stubs because we are seeing weird - // memory errors when loading them -- see JDK-8357593 - if (entry_kind == AOTCodeEntry::C2Blob) { - return nullptr; - } log_debug(aot, codecache, stubs)("Reading blob '%s' (id=%u, kind=%s) from AOT Code Cache", name, id, aot_code_entry_kind_name[entry_kind]); AOTCodeEntry* entry = cache->find_entry(entry_kind, encode_id(entry_kind, id)); diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 3bb4030afde..540b24f5c78 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -268,26 +268,36 @@ class nmethod : public CodeBlob { volatile signed char _state; // {not_installed, in_use, not_entrant} public: - union Flags { - uint8_t _raw; - struct { - bool _has_unsafe_access:1; // May fault due to unsafe access. - bool _has_wide_vectors:1; // Preserve wide vectors at safepoints - bool _has_monitors:1; // Fastpath monitor detection for continuations - bool _has_scoped_access:1; // Used by shared scope closure (scopedMemoryAccess.cpp) + struct Flags { + uint8_t const _bits; + + enum : uint8_t { + UNSAFE_ACCESS = 1 << 0, + WIDE_VECTORS = 1 << 1, + MONITORS = 1 << 2, + SCOPED_ACCESS = 1 << 3 }; - Flags() { - _raw = 0; - } - Flags(bool has_unsafe_access, bool has_wide_vectors, bool has_monitors, bool has_scoped_access) : Flags() { - _has_unsafe_access = has_unsafe_access; - _has_wide_vectors = has_wide_vectors; - _has_monitors = has_monitors; - _has_scoped_access = has_scoped_access; - } - }; - static_assert(sizeof(Flags) == sizeof(uint8_t), "Must fit exactly"); + Flags() : _bits(0) {} + Flags(bool has_unsafe_access, bool has_wide_vectors, bool has_monitors, bool has_scoped_access) : + _bits((has_unsafe_access ? UNSAFE_ACCESS : 0) | + (has_wide_vectors ? WIDE_VECTORS : 0) | + (has_monitors ? MONITORS : 0) | + (has_scoped_access ? SCOPED_ACCESS : 0)) + {} + + // May fault due to unsafe access + bool has_unsafe_access() const { return (_bits & UNSAFE_ACCESS) != 0; } + + // Preserve wide vectors at safepoints + bool has_wide_vectors() const { return (_bits & WIDE_VECTORS) != 0; } + + // Fastpath monitor detection for continuations + bool has_monitors() const { return (_bits & MONITORS) != 0; } + + // Used by shared scope closure (scopedMemoryAccess.cpp) + bool has_scoped_access() const { return (_bits & SCOPED_ACCESS) != 0; } + }; private: // Persistent bits, set once during construction. @@ -779,10 +789,10 @@ class nmethod : public CodeBlob { template void set_gc_data(T* gc_data) { _gc_data = reinterpret_cast(gc_data); } - bool has_unsafe_access() const { return _flags._has_unsafe_access; } - bool has_monitors() const { return _flags._has_monitors; } - bool has_scoped_access() const { return _flags._has_scoped_access; } - bool has_wide_vectors() const { return _flags._has_wide_vectors; } + bool has_unsafe_access() const { return _flags.has_unsafe_access(); } + bool has_monitors() const { return _flags.has_monitors(); } + bool has_scoped_access() const { return _flags.has_scoped_access(); } + bool has_wide_vectors() const { return _flags.has_wide_vectors(); } bool has_flushed_dependencies() const { return _has_flushed_dependencies; } void set_has_flushed_dependencies(bool z) { diff --git a/src/hotspot/share/gc/shared/gcConfig.cpp b/src/hotspot/share/gc/shared/gcConfig.cpp index 402bd0caacd..c31bce35354 100644 --- a/src/hotspot/share/gc/shared/gcConfig.cpp +++ b/src/hotspot/share/gc/shared/gcConfig.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, 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 @@ -95,10 +95,11 @@ void GCConfig::fail_if_non_included_gc_is_selected() { } void GCConfig::select_gc_ergonomically() { - if (os::is_server_class_machine()) { #if INCLUDE_G1GC - FLAG_SET_ERGO_IF_DEFAULT(UseG1GC, true); -#elif INCLUDE_PARALLELGC + FLAG_SET_ERGO_IF_DEFAULT(UseG1GC, true); +#else + if (os::is_server_class_machine()) { +#if INCLUDE_PARALLELGC FLAG_SET_ERGO_IF_DEFAULT(UseParallelGC, true); #elif INCLUDE_SERIALGC FLAG_SET_ERGO_IF_DEFAULT(UseSerialGC, true); @@ -108,6 +109,7 @@ void GCConfig::select_gc_ergonomically() { FLAG_SET_ERGO_IF_DEFAULT(UseSerialGC, true); #endif } +#endif } bool GCConfig::is_no_gc_selected() { diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 25975334dcb..c835d627d62 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -902,6 +902,13 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci, Code_Gen(); } +// C2 uses runtime stubs serialized generation to initialize its static tables +// shared by all compilations, like Type::_shared_type_dict. +// At least one stub have to be completely generated to execute intialization +// before we can skip the rest stubs generation by loading AOT cached stubs. + +static bool c2_do_stub_init_complete = false; + //------------------------------Compile---------------------------------------- // Compile a runtime stub Compile::Compile(ciEnv* ci_env, @@ -976,7 +983,7 @@ Compile::Compile(ciEnv* ci_env, C = this; // try to reuse an existing stub - { + if (c2_do_stub_init_complete) { BlobId blob_id = StubInfo::blob(_stub_id); CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, blob_id); if (blob != nullptr) { @@ -1021,6 +1028,10 @@ Compile::Compile(ciEnv* ci_env, NOT_PRODUCT( verify_graph_edges(); ) Code_Gen(); + + // First successful stub generation will set it to `true` + // and it will stay `true` after that. + c2_do_stub_init_complete = c2_do_stub_init_complete || (_stub_entry_point != nullptr); } Compile::~Compile() { diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index a54fe6e3a73..1059bfe20e5 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -1017,6 +1017,13 @@ bool VectorNode::is_vector_bitwise_not_pattern(Node* n) { return false; } +bool VectorNode::is_vectormask_bitwise_not_pattern(Node* n) { + if (n->Opcode() == Op_XorVMask) { + return is_all_ones_vector(n->in(1)) || + is_all_ones_vector(n->in(2)); + } + return false; +} bool VectorNode::is_reinterpret_opcode(int opc) { switch (opc) { diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index 6bcb7702d13..de077015bca 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -182,6 +182,7 @@ class VectorNode : public TypeNode { // Return true if every bit in this vector is 0. static bool is_all_zeros_vector(Node* n); static bool is_vector_bitwise_not_pattern(Node* n); + static bool is_vectormask_bitwise_not_pattern(Node* n); static Node* degenerate_vector_rotate(Node* n1, Node* n2, bool is_rotate_left, int vlen, BasicType bt, PhaseGVN* phase); diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 6411af1fb75..eaf0cb7559e 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -3522,17 +3522,10 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) { void Arguments::set_compact_headers_flags() { #ifdef _LP64 if (UseCompactObjectHeaders && !UseObjectMonitorTable) { - // If UseCompactObjectHeaders is on the command line, turn on UseObjectMonitorTable. - if (FLAG_IS_CMDLINE(UseCompactObjectHeaders)) { - FLAG_SET_DEFAULT(UseObjectMonitorTable, true); - - // If UseObjectMonitorTable is on the command line, turn off UseCompactObjectHeaders. - } else if (FLAG_IS_CMDLINE(UseObjectMonitorTable)) { - FLAG_SET_DEFAULT(UseCompactObjectHeaders, false); - // If neither on the command line, the defaults are incompatible, but turn on UseObjectMonitorTable. - } else { - FLAG_SET_DEFAULT(UseObjectMonitorTable, true); + if (FLAG_IS_CMDLINE(UseObjectMonitorTable)) { + warning("-UseObjectMonitorTable is incompatible with +UseCompactObjectHeaders; ignoring -UseObjectMonitorTable"); } + FLAG_SET_DEFAULT(UseObjectMonitorTable, true); } #endif } diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index d04b847d713..f90a644eaa4 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -128,7 +128,7 @@ const size_t minimumSymbolTableSize = 1024; "Always use HeapBasedNarrowOop mode, so that AOT code will " \ "always work regardless of runtime heap range") \ \ - product(bool, UseCompactObjectHeaders, false, \ + product(bool, UseCompactObjectHeaders, true, \ "Use compact 64-bit object headers in 64-bit VM") \ \ product(int, ObjectAlignmentInBytes, 8, \ diff --git a/src/hotspot/share/runtime/sharedRuntimeTrans.cpp b/src/hotspot/share/runtime/sharedRuntimeTrans.cpp index 416c8584751..2de3439e0a0 100644 --- a/src/hotspot/share/runtime/sharedRuntimeTrans.cpp +++ b/src/hotspot/share/runtime/sharedRuntimeTrans.cpp @@ -442,8 +442,8 @@ bp[] = {1.0, 1.5,}, cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ - ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ - ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ + ivln2_h = 1.4426946640014648438, /* 0x3FF71547, 0x00000000 =21b 1/ln2*/ + ivln2_l = 3.7688749856360991145e-07; /* 0x3E994AE0, 0xBF85DDF4 =1/ln2 tail*/ ATTRIBUTE_NO_UBSAN static double __ieee754_pow(double x, double y) { diff --git a/src/java.base/share/classes/java/lang/FdLibm.java b/src/java.base/share/classes/java/lang/FdLibm.java index 5a6bdc9b94e..42850269467 100644 --- a/src/java.base/share/classes/java/lang/FdLibm.java +++ b/src/java.base/share/classes/java/lang/FdLibm.java @@ -29,7 +29,8 @@ /** * Port of the "Freely Distributable Math Library", version 5.3, from - * C to Java. + * C to Java, with a fix to pow so that its error bounds conform to + * the quality of implementation criteria for the method. * *

The C version of fdlibm relied on the idiom of pointer aliasing * a 64-bit double floating-point value as a two-element array of @@ -2207,8 +2208,8 @@ else if (y_abs >= 1.0) { // |y| >= 1.0 // |y| is huge if (y_abs > 0x1.00000_ffff_ffffp31) { // if |y| > ~2**31 final double INV_LN2 = 0x1.7154_7652_b82fep0; // 1.44269504088896338700e+00 = 1/ln2 - final double INV_LN2_H = 0x1.715476p0; // 1.44269502162933349609e+00 = 24 bits of 1/ln2 - final double INV_LN2_L = 0x1.4ae0_bf85_ddf44p-26; // 1.92596299112661746887e-08 = 1/ln2 tail + final double INV_LN2_H = 0x1.7154_7p+0; // 1.4426946640014648438 = 21 bits of 1/ln2 + final double INV_LN2_L = 0x1.94ae_0bf8_5ddf4p-22; // 3.7688749856360991145e-07 = 1/ln2 tail // Over/underflow if x is not close to one if (x_abs < 0x1.fffff_0000_0000p-1) // |x| < ~0.9999995231628418 diff --git a/src/java.base/share/classes/java/lang/StrictMath.java b/src/java.base/share/classes/java/lang/StrictMath.java index a8f67ef58ba..6aab491182a 100644 --- a/src/java.base/share/classes/java/lang/StrictMath.java +++ b/src/java.base/share/classes/java/lang/StrictMath.java @@ -66,8 +66,9 @@ * * *

The Java math library is defined with respect to - * {@code fdlibm} version 5.3. Where {@code fdlibm} provides - * more than one definition for a function (such as + * {@code fdlibm} version 5.3 with a fix to {@code pow} so that its error bounds + * conform to the quality of implementation criteria for {@code pow}. + * Where {@code fdlibm} provides more than one definition for a function (such as * {@code acos}), use the "IEEE 754 core function" version * (residing in a file whose name begins with the letter * {@code e}). The methods which require {@code fdlibm} diff --git a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java index 1ccffaa61bb..d15e701b94d 100644 --- a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java +++ b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java @@ -180,7 +180,7 @@ private static class StaticHolders { * * @throws NullPointerException if any argument is {@code null}, unless noted otherwise * @throws IllegalArgumentException if any element in the labels array is null - * @throws IllegalArgumentException if the invocation type is not a method type of first parameter of a reference type, + * @throws IllegalArgumentException if the invocation type is not a method type of first parameter of a target type, * second parameter of type {@code int} and with {@code int} as its return type * @throws IllegalArgumentException if {@code labels} contains an element that is not of type {@code String}, * {@code Integer}, {@code Long}, {@code Float}, {@code Double}, {@code Boolean}, diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsConstants.java b/src/java.base/windows/classes/sun/nio/fs/WindowsConstants.java index 0c09a80e99e..8e713464f19 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsConstants.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, 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 @@ -115,6 +115,12 @@ private WindowsConstants() { } public static final int ERROR_NOT_A_REPARSE_POINT = 4390; public static final int ERROR_INVALID_REPARSE_DATA = 4392; + // FILE_INFO_BY_NAME_CLASS enum values for GetFileInformationByName() + public static final int FileStatByNameInfo = 0; + public static final int FileStatLxByNameInfo = 1; + public static final int FileCaseSensitiveByNameInfo = 2; + public static final int FileStatBasicByNameInfo = 3; + // notify filters public static final int FILE_NOTIFY_CHANGE_FILE_NAME = 0x00000001; public static final int FILE_NOTIFY_CHANGE_DIR_NAME = 0x00000002; diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java b/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java index 3c94e8bc4a2..76422c9ecc9 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, 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 @@ -107,6 +107,35 @@ class WindowsFileAttributes private static final short OFFSETOF_FIND_DATA_SIZELOW = 32; private static final short OFFSETOF_FIND_DATA_RESERVED0 = 36; + /* + * typedef struct _FILE_STAT_BASIC_INFORMATION { + * LARGE_INTEGER FileId; // offset = 0 + * LARGE_INTEGER CreationTime; // offset = 8 + * LARGE_INTEGER LastAccessTime; // offset = 16 + * LARGE_INTEGER LastWriteTime; // offset = 24 + * LARGE_INTEGER ChangeTime; // offset = 32 + * LARGE_INTEGER AllocationSize; // offset = 40 + * LARGE_INTEGER EndOfFile; // offset = 48 + * ULONG FileAttributes; // offset = 56 + * ULONG ReparseTag; // offset = 60 + * ULONG NumberOfLinks; // offset = 64 + * ULONG DeviceType; // offset = 68 + * ULONG DeviceCharacteristics; // offset = 72 + * ULONG Reserved; // offset = 76 + * LARGE_INTEGER VolumeSerialNumber; // offset = 80 + * FILE_ID_128 FileId128; // offset = 88 + * } FILE_STAT_BASIC_INFORMATION; + */ + private static final short SIZEOF_STAT_BASIC_INFO = 104; + private static final short OFFSETOF_STAT_BASIC_INFO_FILEID = 0; + private static final short OFFSETOF_STAT_BASIC_INFO_CREATETIME = 8; + private static final short OFFSETOF_STAT_BASIC_INFO_LASTACCESSTIME = 16; + private static final short OFFSETOF_STAT_BASIC_INFO_LASTWRITETIME = 24; + private static final short OFFSETOF_STAT_BASIC_INFO_ENDOFFILE = 48; + private static final short OFFSETOF_STAT_BASIC_INFO_ATTRIBUTES = 56; + private static final short OFFSETOF_STAT_BASIC_INFO_REPARSETAG = 60; + private static final short OFFSETOF_STAT_BASIC_INFO_VOLSERIAL = 80; + // used to adjust values between Windows and java epochs private static final long WINDOWS_EPOCH_IN_MICROS = -11644473600000000L; private static final long WINDOWS_EPOCH_IN_100NS = -116444736000000000L; @@ -226,6 +255,32 @@ private static WindowsFileAttributes fromFileAttributeData(long address, int rep } + /** + * Create a WindowsFileAttributes from a FILE_STAT_BASIC_INFORMATION structure + */ + static WindowsFileAttributes fromStatBasicInfo(long address) { + int fileAttrs = unsafe.getInt(address + OFFSETOF_STAT_BASIC_INFO_ATTRIBUTES); + long creationTime = unsafe.getLong(address + OFFSETOF_STAT_BASIC_INFO_CREATETIME); + long lastAccessTime = unsafe.getLong(address + OFFSETOF_STAT_BASIC_INFO_LASTACCESSTIME); + long lastWriteTime = unsafe.getLong(address + OFFSETOF_STAT_BASIC_INFO_LASTWRITETIME); + long size = unsafe.getLong(address + OFFSETOF_STAT_BASIC_INFO_ENDOFFILE); + int reparseTag = isReparsePoint(fileAttrs) ? + unsafe.getInt(address + OFFSETOF_STAT_BASIC_INFO_REPARSETAG) : 0; + int volSerialNumber = unsafe.getInt(address + OFFSETOF_STAT_BASIC_INFO_VOLSERIAL); + int fileIndexLow = unsafe.getInt(address + OFFSETOF_STAT_BASIC_INFO_FILEID); + int fileIndexHigh = unsafe.getInt(address + OFFSETOF_STAT_BASIC_INFO_FILEID + 4); + + return new WindowsFileAttributes(fileAttrs, + creationTime, + lastAccessTime, + lastWriteTime, + size, + reparseTag, + volSerialNumber, + fileIndexHigh, + fileIndexLow); + } + /** * Allocates a native buffer for a WIN32_FIND_DATA structure */ @@ -332,6 +387,23 @@ static WindowsFileAttributes get(WindowsPath path, boolean followLinks) } } + if (supportsGetFileInformationByName()) { + try (NativeBuffer buffer = NativeBuffers.getNativeBuffer(SIZEOF_STAT_BASIC_INFO)) { + long addr = buffer.address(); + GetFileInformationByName(path.getPathForWin32Calls(), + FileStatBasicByNameInfo, addr, + SIZEOF_STAT_BASIC_INFO); + + // GetFileInformationByName() doesn't follow reparse points so if + // we discover that this is a reparse point and if we're being asked + // to follow links, then drop to the slow path. + int fileAttrs = unsafe.getInt(addr + OFFSETOF_STAT_BASIC_INFO_ATTRIBUTES); + if (!isReparsePoint(fileAttrs) || !followLinks) { + return fromStatBasicInfo(addr); + } + } + } + // file is reparse point so need to open file to get attributes long handle = path.openForReadAttributeAccess(followLinks); try { diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java b/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java index ba1b7b1aa9f..d6f68b72ed3 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java @@ -367,6 +367,24 @@ static void GetFileAttributesEx(String path, long address) throws WindowsExcepti private static native void GetFileAttributesEx0(long lpFileName, long address) throws WindowsException; + /** + * GetFileInformationByName( + * PCWSTR FileName, + * FILE_INFO_BY_NAME_CLASS FileInformationClass, + * PVOID FileInfoBuffer, + * ULONG FileInfoBufferSize + * ) + */ + static void GetFileInformationByName(String path, int infoClass, long address, int size) + throws WindowsException + { + try (NativeBuffer buffer = asNativeBuffer(path)) { + GetFileInformationByName0(buffer.address(), infoClass, address, size); + } + } + private static native void GetFileInformationByName0(long pathAddress, + int infoClass, long infoAddress, int infoSize) throws WindowsException; + /** * SetFileTime( * HANDLE hFile, @@ -1090,15 +1108,23 @@ static NativeBuffer asNativeBuffer(String s) throws WindowsException { return buffer; } + // -- capabilities -- + private static final int SUPPORTS_GETFILEINFORMATIONBYNAME = 1 << 1; + private static final int capabilities; + + static boolean supportsGetFileInformationByName() { + return (capabilities & SUPPORTS_GETFILEINFORMATIONBYNAME) != 0; + } + // -- native library initialization -- - private static native void initIDs(); + private static native int init(); static { // nio.dll has dependency on net.dll jdk.internal.loader.BootLoader.loadLibrary("net"); jdk.internal.loader.BootLoader.loadLibrary("nio"); - initIDs(); + capabilities = init(); } } diff --git a/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c b/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c index b6e6a9751c0..07452cbef0a 100644 --- a/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c +++ b/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, 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 @@ -79,75 +79,122 @@ static void throwWindowsException(JNIEnv* env, DWORD lastError) { } } +#if !defined(NTDDI_WIN10_NI) || !(NTDDI_VERSION >= NTDDI_WIN10_NI) + +typedef struct _FILE_STAT_BASIC_INFORMATION { + LARGE_INTEGER FileId; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG FileAttributes; + ULONG ReparseTag; + ULONG NumberOfLinks; + ULONG DeviceType; + ULONG DeviceCharacteristics; + ULONG Reserved; + LARGE_INTEGER VolumeSerialNumber; + FILE_ID_128 FileId128; +} FILE_STAT_BASIC_INFORMATION; + +typedef enum _FILE_INFO_BY_NAME_CLASS { + FileStatByNameInfo, + FileStatLxByNameInfo, + FileCaseSensitiveByNameInfo, + FileStatBasicByNameInfo, + MaximumFileInfoByNameClass +} FILE_INFO_BY_NAME_CLASS; + +#endif /* !defined(NTDDI_WIN10_NI) || !(NTDDI_VERSION >= NTDDI_WIN10_NI) */ + +typedef BOOL (WINAPI *PGetFileInformationByName)( + PCWSTR, FILE_INFO_BY_NAME_CLASS, PVOID, ULONG); + +static PGetFileInformationByName pGetFileInformationByName = NULL; + /** * Initializes jfieldIDs and get address of Win32 calls that are located * at runtime. */ -JNIEXPORT void JNICALL -Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this) +JNIEXPORT jint JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_init(JNIEnv* env, jclass this) { jclass clazz; + jint capabilities = 0; clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstFile"); - CHECK_NULL(clazz); + CHECK_NULL_RETURN(clazz, 0); findFirst_handle = (*env)->GetFieldID(env, clazz, "handle", "J"); - CHECK_NULL(findFirst_handle); + CHECK_NULL_RETURN(findFirst_handle, 0); findFirst_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;"); - CHECK_NULL(findFirst_name); + CHECK_NULL_RETURN(findFirst_name, 0); findFirst_attributes = (*env)->GetFieldID(env, clazz, "attributes", "I"); - CHECK_NULL(findFirst_attributes); + CHECK_NULL_RETURN(findFirst_attributes, 0); clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstStream"); - CHECK_NULL(clazz); + CHECK_NULL_RETURN(clazz, 0); findStream_handle = (*env)->GetFieldID(env, clazz, "handle", "J"); - CHECK_NULL(findStream_handle); + CHECK_NULL_RETURN(findStream_handle, 0); findStream_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;"); - CHECK_NULL(findStream_name); + CHECK_NULL_RETURN(findStream_name, 0); clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$VolumeInformation"); - CHECK_NULL(clazz); + CHECK_NULL_RETURN(clazz, 0); volumeInfo_fsName = (*env)->GetFieldID(env, clazz, "fileSystemName", "Ljava/lang/String;"); - CHECK_NULL(volumeInfo_fsName); + CHECK_NULL_RETURN(volumeInfo_fsName, 0); volumeInfo_volName = (*env)->GetFieldID(env, clazz, "volumeName", "Ljava/lang/String;"); - CHECK_NULL(volumeInfo_volName); + CHECK_NULL_RETURN(volumeInfo_volName, 0); volumeInfo_volSN = (*env)->GetFieldID(env, clazz, "volumeSerialNumber", "I"); - CHECK_NULL(volumeInfo_volSN); + CHECK_NULL_RETURN(volumeInfo_volSN, 0); volumeInfo_flags = (*env)->GetFieldID(env, clazz, "flags", "I"); - CHECK_NULL(volumeInfo_flags); + CHECK_NULL_RETURN(volumeInfo_flags, 0); clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$DiskFreeSpace"); - CHECK_NULL(clazz); + CHECK_NULL_RETURN(clazz, 0); diskSpace_bytesAvailable = (*env)->GetFieldID(env, clazz, "freeBytesAvailable", "J"); - CHECK_NULL(diskSpace_bytesAvailable); + CHECK_NULL_RETURN(diskSpace_bytesAvailable, 0); diskSpace_totalBytes = (*env)->GetFieldID(env, clazz, "totalNumberOfBytes", "J"); - CHECK_NULL(diskSpace_totalBytes); + CHECK_NULL_RETURN(diskSpace_totalBytes, 0); diskSpace_totalFree = (*env)->GetFieldID(env, clazz, "totalNumberOfFreeBytes", "J"); - CHECK_NULL(diskSpace_totalFree); + CHECK_NULL_RETURN(diskSpace_totalFree, 0); diskSpace_bytesPerSector = (*env)->GetFieldID(env, clazz, "bytesPerSector", "J"); - CHECK_NULL(diskSpace_bytesPerSector); + CHECK_NULL_RETURN(diskSpace_bytesPerSector, 0); clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$Account"); - CHECK_NULL(clazz); + CHECK_NULL_RETURN(clazz, 0); account_domain = (*env)->GetFieldID(env, clazz, "domain", "Ljava/lang/String;"); - CHECK_NULL(account_domain); + CHECK_NULL_RETURN(account_domain, 0); account_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;"); - CHECK_NULL(account_name); + CHECK_NULL_RETURN(account_name, 0); account_use = (*env)->GetFieldID(env, clazz, "use", "I"); - CHECK_NULL(account_use); + CHECK_NULL_RETURN(account_use, 0); clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$AclInformation"); - CHECK_NULL(clazz); + CHECK_NULL_RETURN(clazz, 0); aclInfo_aceCount = (*env)->GetFieldID(env, clazz, "aceCount", "I"); - CHECK_NULL(aclInfo_aceCount); + CHECK_NULL_RETURN(aclInfo_aceCount, 0); clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$CompletionStatus"); - CHECK_NULL(clazz); + CHECK_NULL_RETURN(clazz, 0); completionStatus_error = (*env)->GetFieldID(env, clazz, "error", "I"); - CHECK_NULL(completionStatus_error); + CHECK_NULL_RETURN(completionStatus_error, 0); completionStatus_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I"); - CHECK_NULL(completionStatus_bytesTransferred); + CHECK_NULL_RETURN(completionStatus_bytesTransferred, 0); completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "J"); - CHECK_NULL(completionStatus_completionKey); + CHECK_NULL_RETURN(completionStatus_completionKey, 0); + + HMODULE hMod = GetModuleHandleW(L"kernel32.dll"); + if (hMod != NULL) { + pGetFileInformationByName = + (PGetFileInformationByName)GetProcAddress(hMod, "GetFileInformationByName"); + if (pGetFileInformationByName != NULL) { + capabilities |= sun_nio_fs_WindowsNativeDispatcher_SUPPORTS_GETFILEINFORMATIONBYNAME; + } + } + + return capabilities; } JNIEXPORT jlong JNICALL @@ -510,6 +557,23 @@ Java_sun_nio_fs_WindowsNativeDispatcher_GetFileAttributesEx0(JNIEnv* env, jclass throwWindowsException(env, GetLastError()); } +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetFileInformationByName0(JNIEnv* env, + jclass this, jlong pathAddress, jint infoClass, jlong infoAddress, jint infoSize) +{ + LPCWSTR lpFileName = jlong_to_ptr(pathAddress); + PVOID pInfo = jlong_to_ptr(infoAddress); + + if (pGetFileInformationByName == NULL) { + JNU_ThrowInternalError(env, "should not reach here"); + return; + } + + if (!pGetFileInformationByName(lpFileName, (FILE_INFO_BY_NAME_CLASS)infoClass, + pInfo, (ULONG)infoSize)) { + throwWindowsException(env, GetLastError()); + } +} JNIEXPORT void JNICALL Java_sun_nio_fs_WindowsNativeDispatcher_SetFileTime0(JNIEnv* env, jclass this, diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index 692ccefa69e..27d6e73fa45 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -2358,8 +2358,9 @@ Symbol findGlobalType(Env env, Scope scope, Name name, RecoveryLoad bestSoFar != sym) { return new AmbiguityError(bestSoFar, sym); } else if (env.toplevel.namedImportScope == scope && - (sym == typeNotFound || (sym.kind == ERR && s.kind == ERR))) { - bestSoFar = bestOf(bestSoFar, new UnresolvableGobalSymbolError(s)); + ((sym == typeNotFound && s.kind.matches(KindSelector.TYP)) || + (sym.kind == ERR && s.kind == ERR))) { + bestSoFar = bestOf(bestSoFar, new UnresolvableGlobalSymbolError(s)); } else bestSoFar = bestOf(bestSoFar, sym); } @@ -4157,9 +4158,9 @@ abstract JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind, List typeargtypes); } - class UnresolvableGobalSymbolError extends InvalidSymbolError { + class UnresolvableGlobalSymbolError extends InvalidSymbolError { - UnresolvableGobalSymbolError(Symbol sym) { + UnresolvableGlobalSymbolError(Symbol sym) { super(HIDDEN, sym, "unresolvable class error"); this.name = sym.name; } diff --git a/src/jdk.jcmd/share/conf/bash-completion/jcmd b/src/jdk.jcmd/share/conf/bash-completion/jcmd new file mode 100644 index 00000000000..c1aca269e72 --- /dev/null +++ b/src/jdk.jcmd/share/conf/bash-completion/jcmd @@ -0,0 +1,157 @@ +# +# Copyright (c) 2026, 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. +# + +# Bash completion for jcmd tool. +# +# Source this file from an interactive shell: +# source /path/to/bash-completion/jcmd +# + +# 'complete' is a Bash builtin from Programmable Completion framework +if ! builtin complete &>/dev/null; then + return 0 2>/dev/null || exit 0 +fi + +function _jcmd__dedupe_words() { + awk '!seen[$0]++' +} + +# list JVM processes on the local machine, except `jcmd` itself. +# Output format: " \n" +function _jcmd__list_processes() { + jcmd -l 2>/dev/null | awk ' + $1 ~ /^[0-9]+$/ && $2 != "jdk.jcmd/sun.tools.jcmd.JCmd" { + print $1, $2 + } + ' +} + +# query the list of commands known by the target JVM +function _jcmd__list_commands_for_jvm() { + local -r jvm_identifier=$1 # can also be a main class name + + jcmd "${jvm_identifier}" help 2>/dev/null | awk ' + /^The following commands are available:/ { in_block=1; next } + /^For more information/ { in_block=0 } + in_block && $1 != "" { print $1 } + ' +} + + +function _jcmd__complete_first_arg() { + local -r cur=$1 + + # include generic options as well + local -a candidates=("-l" "--help") + + local pid main_class _rest + while read -r pid main_class _rest; do + candidates+=("${pid}" "${main_class}") + done < <(_jcmd__list_processes) + + local -r wordlist=$(printf '%s\n' "${candidates[@]}" | _jcmd__dedupe_words | tr '\n' ' ') + COMPREPLY=( $(compgen -W "${wordlist}" -- "${cur}") ) +} + + +function _jcmd__complete_command() { + local -r jvm_identifier=$1 + local -r cur=$2 + + # include "read commands from file" -f flag + local -a commands=("-f") + + local cmd + while read -r cmd; do + [[ -z $cmd ]] && continue + commands+=("$cmd") + done < <(_jcmd__list_commands_for_jvm "${jvm_identifier}") + + printf -v wordlist '%s ' "${commands[@]}" + COMPREPLY=( $(compgen -W "${wordlist}" -- "${cur}") ) +} + + +function _jcmd__complete_help_command() { + local -r jvm_identifier=$1 + local -r cur=$2 + + local -a commands=() + + local cmd + while read -r cmd; do + [[ -z ${cmd} || ${cmd} == help ]] && continue + commands+=("${cmd}") + done < <(_jcmd__list_commands_for_jvm "${jvm_identifier}") + + printf -v wordlist '%s ' "${commands[@]}" + COMPREPLY=( $(compgen -W "${wordlist}" -- "${cur}") ) +} + + +function _jcmd_completion() { + COMPREPLY=() + + # current word, possibly incomplete + local -r cur=${COMP_WORDS[COMP_CWORD]} + + # COMP_WORDS + # An array variable consisting of the individual words in the current command line. + # The line is split into words as `readline` would split it, using COMP_WORDBREAKS. + # A word is considered complete once it is followed by a space. + # COMP_CWORD + # An index into ${COMP_WORDS} of the word containing the current cursor position. + # Examples: + # "jcmd " -> COMP_CWORD = 1, cur = "" + # "jcmd MyA" -> COMP_CWORD = 1, cur = "MyA" + # "jcmd MyApp" -> COMP_CWORD = 1, cur = "MyApp" + # "jcmd MyApp " -> COMP_CWORD = 2, cur = "" + + if [[ ${COMP_CWORD} -eq 1 ]]; then + _jcmd__complete_first_arg "$cur" + return 0 + fi + + local -r jvm_identifier=${COMP_WORDS[1]} + + # 2nd argument: diagnostic command. + if [[ ${COMP_CWORD} -eq 2 ]]; then + _jcmd__complete_command "${jvm_identifier}" "${cur}" + return 0 + fi + + if [[ ${COMP_CWORD} -eq 3 ]]; then + if [[ ${COMP_WORDS[2]} == help ]]; then + _jcmd__complete_help_command "${jvm_identifier}" "${cur}" + elif [[ ${COMP_WORDS[2]} == "-f" ]]; then + # autocomplete filename + compopt -o filenames 2>/dev/null + COMPREPLY=( $(compgen -f -- "${cur}") ) + fi + return 0 + fi +} + +# Avoid alphabetical sorting of completion candidates on double-TAB. This +# keeps each JVM identifier (main class or JAR path) next to its PID. +complete -o nosort -F _jcmd_completion jcmd diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Recording.java b/src/jdk.jfr/share/classes/jdk/jfr/Recording.java index 466654180eb..f4b20aeec03 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Recording.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Recording.java @@ -222,7 +222,7 @@ public boolean stop() { * @return recording settings, not {@code null} */ public Map getSettings() { - return new HashMap<>(internal.getSettings()); + return internal.getSettingsCopy(); } /** diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/OldObjectSample.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/OldObjectSample.java index 21079fab3a9..d3765af8e6c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/OldObjectSample.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/OldObjectSample.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package jdk.jfr.internal; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -92,7 +91,7 @@ public static void updateSettingPathToGcRoots(Map s, Boolean pat } public static Map createSettingsForSnapshot(PlatformRecording recording, Boolean pathToGcRoots) { - Map settings = new HashMap<>(recording.getSettings()); + Map settings = recording.getSettingsCopy(); updateSettingPathToGcRoots(settings, pathToGcRoots); return settings; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java index a82eff239e6..4779b8e0125 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java @@ -585,7 +585,7 @@ synchronized Recording newCopy(PlatformRecording r, boolean stop) { boolean register = !isDestroyed() && r.getState() != RecordingState.CLOSED; Recording newRec = access.newRecording(register); PlatformRecording copy = access.getPlatformRecording(newRec); - copy.setSettings(r.getSettings()); + copy.setSettings(r.getSettingsCopy()); copy.setMaxAge(r.getMaxAge()); copy.setMaxSize(r.getMaxSize()); copy.setDumpOnExit(r.getDumpOnExit()); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java index 92d60f5bdec..407e353b051 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java @@ -253,9 +253,14 @@ void scheduleStart(Instant startTime) { } } - public Map getSettings() { + Map getSettings() { + assert Thread.holdsLock(recorder) : "Must have recorder lock when accessing recorder.settings"; + return settings; + } + + public Map getSettingsCopy() { synchronized (recorder) { - return settings; + return new LinkedHashMap<>(settings); } } @@ -371,7 +376,7 @@ public PlatformRecording newSnapshotClone(String reason, Boolean pathToGcRoots) clone.setStartTime(getStartTime()); } if (pathToGcRoots == null) { - clone.setSettings(getSettings()); // needed for old object sample + clone.setSettings(getSettingsCopy()); // needed for old object sample clone.stop(reason); // dumps to destination path here } else { // Risk of violating lock order here, since diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/CDSPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/CDSPlugin.java index c131c34b952..568f0a27417 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/CDSPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/CDSPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, 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 @@ -60,7 +60,7 @@ private String javaExecutableName() { } } - private void generateCDSArchive(ExecutableImage image, boolean noCoops) { + private void generateCDSArchive(ExecutableImage image, boolean noCoops, boolean noCoh) { List javaCmd = new ArrayList(); Path javaPath = image.getHome().resolve("bin").resolve(javaExecutableName()); if (!Files.exists(javaPath)) { @@ -73,6 +73,10 @@ private void generateCDSArchive(ExecutableImage image, boolean noCoops) { javaCmd.add("-XX:-UseCompressedOops"); archiveMsg += "-NOCOOPS"; } + if (noCoh) { + javaCmd.add("-XX:-UseCompactObjectHeaders"); + archiveMsg += "-NOCOH"; + } ProcessBuilder builder = new ProcessBuilder(javaCmd); int status = -1; try { @@ -100,12 +104,13 @@ public List process(ExecutableImage image) { Path classListPath = image.getHome().resolve("lib").resolve("classlist"); if (Files.exists(classListPath)) { - generateCDSArchive(image,false); + generateCDSArchive(image, false, false); - // The targetPlatform is the same as the runtimePlatform. - // For a 64-bit platform, generate the non-compressed oop CDS archive + // Generate all of the CDS archive combinations: nocoops, nocoh, nocoops_nocoh. if (Architecture.is64bit()) { - generateCDSArchive(image,true); + generateCDSArchive(image, true, false); + generateCDSArchive(image, false, true); + generateCDSArchive(image, true, true); } System.out.println("Created CDS archive successfully"); } else { diff --git a/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c b/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c index 83f3519fbe2..e25da7993ec 100644 --- a/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c +++ b/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2026, 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 @@ -389,7 +389,7 @@ void handleMessage (JNIEnv* env, jobject resultContainerObj, struct msghdr* msg,int read, jboolean isEOR, struct sockaddr* sap) { jobject isa, resultObj; - struct controlData cdata[1]; + struct controlData cdata[1] = {0}; if (read == 0) { /* we reached EOF */ diff --git a/test/hotspot/jtreg/compiler/arguments/TestCompilerCounts.java b/test/hotspot/jtreg/compiler/arguments/TestCompilerCounts.java index 870daa7f0a5..e3f1d59d67c 100644 --- a/test/hotspot/jtreg/compiler/arguments/TestCompilerCounts.java +++ b/test/hotspot/jtreg/compiler/arguments/TestCompilerCounts.java @@ -1,6 +1,6 @@ /* * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, 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 @@ -23,8 +23,8 @@ */ /* - * @test - * @library /test/lib / + * @test id=debug + * @library /test/lib * @bug 8356000 * @requires vm.flagless * @requires vm.bits == "64" @@ -33,8 +33,8 @@ */ /* - * @test - * @library /test/lib / + * @test id=product + * @library /test/lib * @bug 8356000 * @requires vm.flagless * @requires vm.bits == "64" @@ -44,15 +44,10 @@ package compiler.arguments; -import java.io.IOException; -import java.util.List; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.function.Function; import jdk.test.lib.Asserts; -import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.cli.CommandLineOptionTest; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; public class TestCompilerCounts { diff --git a/test/hotspot/jtreg/compiler/intrinsics/math/PowDNodeTests.java b/test/hotspot/jtreg/compiler/intrinsics/math/PowDNodeTests.java index e28cc5ab346..a78a38fc807 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/math/PowDNodeTests.java +++ b/test/hotspot/jtreg/compiler/intrinsics/math/PowDNodeTests.java @@ -45,6 +45,14 @@ public class PowDNodeTests { public static final double B = UNIFORMS.next() * 1000.0d; public static final double E = UNIFORMS.next() * 1000.0d + 3.0d; // e >= 3 to avoid strength reduction code + private static final double REG1_B = 0x1.000002c5e2e99p+0; + private static final double REG1_E = 0x1.c9eee35374af6p+31; + private static final double REG1_R = 0x1.ffffe0bc9e399p+915; + + private static final double REG2_B = 0x1.fffff4e900013p-1; + private static final double REG2_E = 0x1.0000100000001p+31; + private static final double REG2_R = 0x0.421378008b246p-1022; + public static void main(String[] args) { TestFramework.run(); @@ -164,6 +172,20 @@ public static double lateBothConstant() { return Math.pow(base, exp); } + // Test 12: pow(REG1_B, REG1_E) -> REG1_R + @Test + @IR(failOn = {IRNode.POW_D}) + public static double regressionHugeExpAboveOne() { + return Math.pow(REG1_B, REG1_E); + } + + // Test 13: pow(REG2_B, REG2_E) -> REG2_R + @Test + @IR(failOn = {IRNode.POW_D}) + public static double regressionHugeExpBelowOne() { + return Math.pow(REG2_B, REG2_E); + } + private static void assertEQWithinOneUlp(double expected, double observed) { if (Double.isNaN(expected) && Double.isNaN(observed)) return; @@ -214,5 +236,8 @@ private static void testCorrectness() { assertEQWithinOneUlp(StrictMath.pow(b, e), nonConstant(b, e)); } } + + assertEQWithinOneUlp(REG1_R, regressionHugeExpAboveOne()); + assertEQWithinOneUlp(REG2_R, regressionHugeExpBelowOne()); } } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 4f7869f444a..cd4f62825e8 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -1489,6 +1489,16 @@ public class IRNode { beforeMatchingNameRegex(MASK_ALL, "MaskAll"); } + public static final String AARCH64_VMASK_ALL_IMM_I = PREFIX + "AARCH64_VMASK_ALL_IMM_I" + POSTFIX; + static { + machOnlyNameRegex(AARCH64_VMASK_ALL_IMM_I, "vmaskAll_immI"); + } + + public static final String AARCH64_VMASK_ALL_IMM_L = PREFIX + "AARCH64_VMASK_ALL_IMM_L" + POSTFIX; + static { + machOnlyNameRegex(AARCH64_VMASK_ALL_IMM_L, "vmaskAll_immL"); + } + public static final String VECTOR_LONG_TO_MASK = PREFIX + "VECTOR_LONG_TO_MASK" + POSTFIX; static { beforeMatchingNameRegex(VECTOR_LONG_TO_MASK, "VectorLongToMask"); @@ -2718,6 +2728,11 @@ public class IRNode { machOnlyNameRegex(RISCV_VFMADD_MASKED, "vfmadd_masked"); } + public static final String VMASK_AND_NOT_I = PREFIX + "VMASK_AND_NOT_I" + POSTFIX; + static { + machOnlyNameRegex(VMASK_AND_NOT_I, "vmask_and_notI"); + } + public static final String VMASK_AND_NOT_L = PREFIX + "VMASK_AND_NOT_L" + POSTFIX; static { machOnlyNameRegex(VMASK_AND_NOT_L, "vmask_and_notL"); diff --git a/test/hotspot/jtreg/compiler/vectorapi/AllBitsSetVectorMatchRuleTest.java b/test/hotspot/jtreg/compiler/vectorapi/AllBitsSetVectorMatchRuleTest.java index bb88f60dd21..2c5b74a078e 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/AllBitsSetVectorMatchRuleTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/AllBitsSetVectorMatchRuleTest.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, Arm Limited. All rights reserved. + * Copyright (c) 2026, NVIDIA CORPORATION & 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 @@ -38,7 +39,7 @@ /** * @test - * @bug 8287984 + * @bug 8287984 8378737 * @key randomness * @library /test/lib / * @requires vm.compiler2.enabled @@ -90,8 +91,9 @@ public class AllBitsSetVectorMatchRuleTest { } } + // Tests of C2 match rules for vector ops containing an all-bits-set vector operand. + @Test - @Warmup(10000) @IR(counts = { IRNode.VAND_NOT_I, " >= 1" }) public static void testAllBitsSetVector() { IntVector av = IntVector.fromArray(I_SPECIES, ia, 0); @@ -105,7 +107,6 @@ public static void testAllBitsSetVector() { } @Test - @Warmup(10000) @IR(counts = { IRNode.VAND_NOT_L, " >= 1" }) public static void testVectorVAndNotL() { LongVector av = LongVector.fromArray(L_SPECIES, la, 0); @@ -119,8 +120,7 @@ public static void testVectorVAndNotL() { } @Test - @Warmup(10000) - @IR(counts = { IRNode.VAND_NOT_I_MASKED, " >= 1" }, applyIfPlatform = {"aarch64", "true"}, applyIf = {"UseSVE", "> 0"}) + @IR(counts = { IRNode.VAND_NOT_I_MASKED, " >= 1" }, applyIfCPUFeature = {"sve", "true"}) @IR(counts = { IRNode.VAND_NOT_I_MASKED, " >= 1" }, applyIfPlatform = {"riscv64", "true"}) public static void testVectorVAndNotIMasked() { VectorMask avm = VectorMask.fromArray(I_SPECIES, ma, 0); @@ -137,8 +137,7 @@ public static void testVectorVAndNotIMasked() { } @Test - @Warmup(10000) - @IR(counts = { IRNode.VAND_NOT_L_MASKED, " >= 1" }, applyIfPlatform = {"aarch64", "true"}, applyIf = {"UseSVE", "> 0"}) + @IR(counts = { IRNode.VAND_NOT_L_MASKED, " >= 1" }, applyIfCPUFeature = {"sve", "true"}) @IR(counts = { IRNode.VAND_NOT_L_MASKED, " >= 1" }, applyIfPlatform = {"riscv64", "true"}) public static void testVectorVAndNotLMasked() { VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); @@ -155,7 +154,6 @@ public static void testVectorVAndNotLMasked() { } @Test - @Warmup(10000) @IR(counts = { IRNode.RISCV_VAND_NOTI_VX, " >= 1" }, applyIfPlatform = {"riscv64", "true"}) public static void testAllBitsSetVectorRegI() { IntVector av = IntVector.fromArray(I_SPECIES, ia, 0); @@ -169,7 +167,6 @@ public static void testAllBitsSetVectorRegI() { } @Test - @Warmup(10000) @IR(counts = { IRNode.RISCV_VAND_NOTL_VX, " >= 1" }, applyIfPlatform = {"riscv64", "true"}) public static void testAllBitsSetVectorRegL() { LongVector av = LongVector.fromArray(L_SPECIES, la, 0); @@ -183,7 +180,6 @@ public static void testAllBitsSetVectorRegL() { } @Test - @Warmup(10000) @IR(counts = { IRNode.RISCV_VAND_NOTI_VX_MASKED, " >= 1" }, applyIfPlatform = {"riscv64", "true"}) public static void testAllBitsSetVectorRegIMask() { VectorMask avm = VectorMask.fromArray(I_SPECIES, ma, 0); @@ -200,7 +196,6 @@ public static void testAllBitsSetVectorRegIMask() { } @Test - @Warmup(10000) @IR(counts = { IRNode.RISCV_VAND_NOTL_VX_MASKED, " >= 1" }, applyIfPlatform = {"riscv64", "true"}) public static void testAllBitsSetVectorRegLMask() { VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); @@ -216,11 +211,26 @@ public static void testAllBitsSetVectorRegLMask() { } } + // Tests that VectorMask.andNot() chains match to VMASK_AND_NOT / VAND_NOT (two andNot ops). + @Test + @IR(counts = { IRNode.VAND_NOT_I, "2" }, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + @IR(counts = { IRNode.VMASK_AND_NOT_I, "2" }, applyIfCPUFeature = {"sve", "true"}) + public static void testMaskAndNotI() { + VectorMask avm = VectorMask.fromArray(I_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(I_SPECIES, mb, 0); + VectorMask cvm = VectorMask.fromArray(I_SPECIES, mc, 0); + avm.andNot(bvm).andNot(cvm).intoArray(mr, 0); + + // Verify results + for (int i = 0; i < I_SPECIES.length(); i++) { + Asserts.assertEquals((ma[i] & (!mb[i])) & (!mc[i]), mr[i]); + } + } + @Test - @Warmup(10000) - @IR(counts = { IRNode.VAND_NOT_L, " >= 1" }, applyIfPlatform = {"aarch64", "true"}, applyIf = {"UseSVE", "0"}) - @IR(counts = { IRNode.VMASK_AND_NOT_L, " >= 1" }, applyIfPlatform = {"aarch64", "true"}, applyIf = {"UseSVE", "> 0"}) - public static void testAllBitsSetMask() { + @IR(counts = { IRNode.VAND_NOT_L, "2" }, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + @IR(counts = { IRNode.VMASK_AND_NOT_L, "2" }, applyIfCPUFeature = {"sve", "true"}) + public static void testMaskAndNotL() { VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); VectorMask bvm = VectorMask.fromArray(L_SPECIES, mb, 0); VectorMask cvm = VectorMask.fromArray(L_SPECIES, mc, 0); @@ -232,7 +242,123 @@ public static void testAllBitsSetMask() { } } + // Tests that mask.not().and(other) matches to VMASK_AND_NOT (AndVMask commutative rule). + @Test + @IR(counts = { IRNode.VMASK_AND_NOT_I, "1" }, applyIfCPUFeature = {"sve", "true"}) + public static void testCommutativeAndVMaskI() { + VectorMask avm = VectorMask.fromArray(I_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(I_SPECIES, mb, 0); + avm.not().and(bvm).intoArray(mr, 0); + + // Verify results + for (int i = 0; i < I_SPECIES.length(); i++) { + Asserts.assertEquals((!ma[i]) & (mb[i]), mr[i]); + } + } + + @Test + @IR(counts = { IRNode.VMASK_AND_NOT_L, "1" }, applyIfCPUFeature = {"sve", "true"}) + public static void testCommutativeAndVMaskL() { + VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(L_SPECIES, mb, 0); + avm.not().and(bvm).intoArray(mr, 0); + + // Verify results + for (int i = 0; i < L_SPECIES.length(); i++) { + Asserts.assertEquals((!ma[i]) & (mb[i]), mr[i]); + } + } + + // Tests that mask.and(allTrue.xor(other)) matches to VMASK_AND_NOT (XorVMask commutative rule). + @Test + @IR(counts = { IRNode.VMASK_AND_NOT_I, "1" }, applyIfCPUFeature = {"sve", "true"}) + public static void testCommutativeXorVMaskI() { + VectorMask avm = VectorMask.fromArray(I_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(I_SPECIES, mb, 0); + VectorMask alltrue = I_SPECIES.maskAll(true); + bvm.and(alltrue.xor(avm)).intoArray(mr, 0); + + // Verify results + for (int i = 0; i < I_SPECIES.length(); i++) { + Asserts.assertEquals((mb[i]) & (!ma[i]), mr[i]); + } + } + + @Test + @IR(counts = { IRNode.VMASK_AND_NOT_L, "1" }, applyIfCPUFeature = {"sve", "true"}) + public static void testCommutativeXorVMaskL() { + VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(L_SPECIES, mb, 0); + VectorMask alltrue = L_SPECIES.maskAll(true); + bvm.and(alltrue.xor(avm)).intoArray(mr, 0); + + // Verify results + for (int i = 0; i < L_SPECIES.length(); i++) { + Asserts.assertEquals((mb[i]) & (!ma[i]), mr[i]); + } + } + + // Tests that only one MaskAll machine node is generated (no duplicate "maskall" nodes). + @Test + @IR(counts = { IRNode.AARCH64_VMASK_ALL_IMM_I, "1" }, applyIfCPUFeature = {"sve", "true"}) + public static void testSingleMaskAllI() { + VectorMask avm = VectorMask.fromArray(I_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(I_SPECIES, mb, 0); + avm.not().or(bvm.not()).intoArray(mr, 0); + + // Verify results + for (int i = 0; i < I_SPECIES.length(); i++) { + Asserts.assertEquals(!ma[i] | !mb[i], mr[i]); + } + } + + @Test + @IR(counts = { IRNode.AARCH64_VMASK_ALL_IMM_L, "1" }, applyIfCPUFeature = {"sve", "true"}) + public static void testSingleMaskAllL() { + VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(L_SPECIES, mb, 0); + avm.not().or(bvm.not()).intoArray(mr, 0); + + // Verify results + for (int i = 0; i < L_SPECIES.length(); i++) { + Asserts.assertEquals(!ma[i] | !mb[i], mr[i]); + } + } + + // Tests that mask.not().andNot(other) doesn't match to VMASK_AND_NOT rule on SVE, + // and only one MaskAll machine node is generated. + @Test + @IR(counts = { IRNode.AARCH64_VMASK_ALL_IMM_I, "1", IRNode.VMASK_AND_NOT_I, "0" }, + applyIfCPUFeature = {"sve", "true"}) + public static void testSingleMaskAllWithAndNotI() { + VectorMask avm = VectorMask.fromArray(I_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(I_SPECIES, mb, 0); + avm.not().andNot(bvm).intoArray(mr, 0); + + // Verify results + for (int i = 0; i < I_SPECIES.length(); i++) { + Asserts.assertEquals((!ma[i]) & (!mb[i]), mr[i]); + } + } + + @Test + @IR(counts = { IRNode.AARCH64_VMASK_ALL_IMM_L, "1", IRNode.VMASK_AND_NOT_L, "0" }, + applyIfCPUFeature = {"sve", "true"}) + public static void testSingleMaskAllWithAndNotL() { + VectorMask avm = VectorMask.fromArray(L_SPECIES, ma, 0); + VectorMask bvm = VectorMask.fromArray(L_SPECIES, mb, 0); + avm.not().andNot(bvm).intoArray(mr, 0); + + // Verify results + for (int i = 0; i < L_SPECIES.length(); i++) { + Asserts.assertEquals((!ma[i]) & (!mb[i]), mr[i]); + } + } + public static void main(String[] args) { - TestFramework.runWithFlags("--add-modules=jdk.incubator.vector"); + TestFramework testFramework = new TestFramework(); + testFramework.setDefaultWarmup(10000) + .addFlags("--add-modules=jdk.incubator.vector") + .start(); } } diff --git a/test/hotspot/jtreg/runtime/CommandLine/VMOptionWarning.java b/test/hotspot/jtreg/runtime/CommandLine/VMOptionWarning.java index 6c8522c1881..58a90f8ba54 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/VMOptionWarning.java +++ b/test/hotspot/jtreg/runtime/CommandLine/VMOptionWarning.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, 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 @@ -66,6 +66,26 @@ * @run driver VMOptionWarning Develop */ +/* @test VMOptionWarningCompactObjectHeaders + * @bug 8360700 + * @summary Warn if -XX:+UseCompactObjectHeaders is used with -XX:-UseObjectMonitorTable + * @requires vm.flagless + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @run driver VMOptionWarning CompactObjectHeaders + */ + +/* @test VMOptionWarningUseObjectMonitorTable + * @bug 8360700 + * @summary Warn if -XX:-UseObjectMonitorTable is used without -XX:-UseCompactObjectHeaders + * @requires vm.flagless + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @run driver VMOptionWarning UseObjectMonitorTable + */ + import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.Platform; @@ -107,6 +127,20 @@ public static void main(String[] args) throws Exception { output.shouldContain("Error: VM option 'VerifyStack' is develop and is available only in debug version of VM."); break; } + case "CompactObjectHeaders": { + pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseCompactObjectHeaders", "-XX:+UnlockDiagnosticVMOptions", "-XX:-UseObjectMonitorTable", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + output.shouldContain("warning: -UseObjectMonitorTable is incompatible with +UseCompactObjectHeaders; ignoring -UseObjectMonitorTable"); + break; + } + case "UseObjectMonitorTable": { + pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockDiagnosticVMOptions", "-XX:-UseObjectMonitorTable", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + output.shouldContain("warning: -UseObjectMonitorTable is incompatible with +UseCompactObjectHeaders; ignoring -UseObjectMonitorTable"); + break; + } default: { throw new RuntimeException("Invalid argument: " + args[0]); } diff --git a/test/hotspot/jtreg/runtime/cds/MetaspaceAllocGaps.java b/test/hotspot/jtreg/runtime/cds/MetaspaceAllocGaps.java index 65459263e36..df297ddbaa3 100644 --- a/test/hotspot/jtreg/runtime/cds/MetaspaceAllocGaps.java +++ b/test/hotspot/jtreg/runtime/cds/MetaspaceAllocGaps.java @@ -49,14 +49,8 @@ public static void main(String[] args) throws Exception { .classpath(appJar) .appCommandLine("Hello") .setTrainingChecker((OutputAnalyzer out) -> { - // Typically all gaps should be filled. If not, we probably have a regression in C++ class ArchiveUtils. - // - // [0.422s][debug][aot ] Detailed metadata info (excluding heap region): - // [...] - // [0.422s][debug][aot ] Gap : 0 0 0.0 | 0 0 0.0 | 0 0 0.0 <<< look for this pattern - out.shouldMatch("Allocated [1-9][0-9]+ objects of [1-9][0-9]+ bytes in gaps .remain = 0 bytes") - .shouldMatch("debug.* Gap .*0[.]0.*0[.]0.*0[.]0") - .shouldNotMatch("Unexpected .* gaps .* for Klass alignment"); + // We should have only very minimal amount of gaps left unfilled. See JDK-8383503 + out.shouldNotMatch("Unexpected .* gaps .* for Klass alignment"); }) .setProductionChecker((OutputAnalyzer out) -> { out.shouldContain("HelloWorld"); diff --git a/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java b/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java index 8b07cd86a72..4cef6471d2f 100644 --- a/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java +++ b/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java @@ -24,7 +24,7 @@ /** * @test id=nocoops_nocoh - * @summary Test Loading of default archives in all configurations + * @summary Test Loading of default archives in all configurations (requires --enable-cds-archive-nocoh) * @requires vm.cds * @requires vm.cds.default.archive.available * @requires vm.cds.write.archived.java.heap @@ -37,7 +37,7 @@ /** * @test id=nocoops_coh - * @summary Test Loading of default archives in all configurations (requires --enable-cds-archive-coh) + * @summary Test Loading of default archives in all configurations * @requires vm.cds * @requires vm.cds.default.archive.available * @requires vm.cds.write.archived.java.heap @@ -50,7 +50,7 @@ /** * @test id=coops_nocoh - * @summary Test Loading of default archives in all configurations + * @summary Test Loading of default archives in all configurations (requires --enable-cds-archive-nocoh) * @requires vm.cds * @requires vm.cds.default.archive.available * @requires vm.cds.write.archived.java.heap @@ -64,7 +64,7 @@ /** * @test id=coops_coh - * @summary Test Loading of default archives in all configurations (requires --enable-cds-archive-coh) + * @summary Test Loading of default archives in all configurations * @requires vm.cds * @requires vm.cds.default.archive.available * @requires vm.cds.write.archived.java.heap @@ -114,7 +114,7 @@ public static void main(String[] args) throws Exception { switch (args[0]) { case "nocoops_nocoh": coh = coops = '-'; - archiveSuffix = "_nocoops"; + archiveSuffix = "_nocoops_nocoh"; if (!isArchiveAvailable(coops, coh, archiveSuffix)) { throw new SkippedException("Skipping test due to " + archivePath(archiveSuffix).toString() + " not available"); @@ -123,7 +123,7 @@ public static void main(String[] args) throws Exception { case "nocoops_coh": coops = '-'; coh = '+'; - archiveSuffix = "_nocoops_coh"; + archiveSuffix = "_nocoops"; if (!isArchiveAvailable(coops, coh, archiveSuffix)) { throw new SkippedException("Skipping test due to " + archivePath(archiveSuffix).toString() + " not available"); @@ -132,7 +132,7 @@ public static void main(String[] args) throws Exception { case "coops_nocoh": coops = '+'; coh = '-'; - archiveSuffix = ""; + archiveSuffix = "_nocoh"; if (!isArchiveAvailable(coops, coh, archiveSuffix)) { throw new SkippedException("Skipping test due to " + archivePath(archiveSuffix).toString() + " not available"); @@ -140,7 +140,7 @@ public static void main(String[] args) throws Exception { break; case "coops_coh": coh = coops = '+'; - archiveSuffix = "_coh"; + archiveSuffix = ""; if (!isArchiveAvailable(coops, coh, archiveSuffix)) { throw new SkippedException("Skipping test due to " + archivePath(archiveSuffix).toString() + " not available"); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeFlags.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeFlags.java index 01b64a7fff0..027dd4fbed6 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeFlags.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeFlags.java @@ -217,10 +217,7 @@ public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception // AOTStubCaching is on, non-zero stubs should be stored out.shouldMatch("Shared Blobs:\\s+total=[1-9][0-9]+"); out.shouldMatch("C1 Blobs:\\s+total=[1-9][0-9]+"); - // we do not currently load or store C2 stubs - // because we are seeing weird memory errors - // when loading them -- see JDK-8357593 - out.shouldMatch("C2 Blobs:\\s+total=0"); + out.shouldMatch("C2 Blobs:\\s+total=[1-9][0-9]+"); } else { // AOTStubCaching is off, no stubs should be stored out.shouldMatch("Shared Blobs:\\s+total=0"); diff --git a/test/jdk/ProblemList-coh.txt b/test/jdk/ProblemList-coh.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test/jdk/java/lang/StrictMath/PowTests.java b/test/jdk/java/lang/StrictMath/PowTests.java index 90482b264fe..d38041cdce9 100644 --- a/test/jdk/java/lang/StrictMath/PowTests.java +++ b/test/jdk/java/lang/StrictMath/PowTests.java @@ -301,6 +301,18 @@ private static int testPow() { 5.0, 55.901699437494756 }, + + { + 0x1.000002c5e2e99p+0, // |x| > 1 + 0x1.c9eee35374af6p+31, // |y| huge + 0x1.ffffe0bc9e399p+915 + }, + + { + 0x1.fffff4e900013p-1, // |x| < 1 + 0x1.0000100000001p+31, // |y| huge + 0x0.421378008b246p-1022 + }, }; for (double[] testCase: testCases) diff --git a/test/jdk/sun/net/www/protocol/http/NTLMHeadTest.java b/test/jdk/sun/net/www/protocol/http/NTLMHeadTest.java index 52174ab2f55..2cbbf5f6534 100644 --- a/test/jdk/sun/net/www/protocol/http/NTLMHeadTest.java +++ b/test/jdk/sun/net/www/protocol/http/NTLMHeadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, 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 @@ -22,8 +22,9 @@ */ /* - * @test + * @test id=default * @bug 8270290 + * @requires os.family != "windows" * @library /test/lib * @run main/othervm NTLMHeadTest SERVER * @run main/othervm NTLMHeadTest PROXY @@ -48,6 +49,17 @@ * include the body. */ +/* + * @test id=windows + * @bug 8270290 + * @comment Only run on specific Windows OS versions because NTLMv1 is no longer supported starting Windows 11 and Windows Server 2025 + * @requires os.family == "windows" & (os.name == "Windows 10" | os.name == "Windows Server 2016" | os.name == "Windows Server 2019" | os.name == "Windows Server 2022") + * @library /test/lib + * @run main/othervm NTLMHeadTest SERVER + * @run main/othervm NTLMHeadTest PROXY + * @run main/othervm NTLMHeadTest TUNNEL + */ + import java.net.*; import java.io.*; import java.util.*; diff --git a/test/jdk/sun/net/www/protocol/http/TestTransparentNTLM.java b/test/jdk/sun/net/www/protocol/http/TestTransparentNTLM.java index 1c2262ba8e2..7a8082a4012 100644 --- a/test/jdk/sun/net/www/protocol/http/TestTransparentNTLM.java +++ b/test/jdk/sun/net/www/protocol/http/TestTransparentNTLM.java @@ -26,7 +26,8 @@ * @bug 8225425 * @summary Verifies that transparent NTLM (on Windows) is not used by default, * and is used only when the relevant property is set. - * @requires os.family == "windows" + * @comment Only run on specific Windows OS versions because NTLMv1 is no longer supported starting Windows 11 and Windows Server 2025 + * @requires os.family == "windows" & (os.name == "Windows 10" | os.name == "Windows Server 2016" | os.name == "Windows Server 2019" | os.name == "Windows Server 2022") * @library /test/lib * @run junit/othervm * -Dtest.auth.succeed=false diff --git a/test/jdk/tools/jlink/plugins/CDSPluginTest.java b/test/jdk/tools/jlink/plugins/CDSPluginTest.java index 4193c0a0244..5d2c1be74d1 100644 --- a/test/jdk/tools/jlink/plugins/CDSPluginTest.java +++ b/test/jdk/tools/jlink/plugins/CDSPluginTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, 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 @@ -77,15 +77,13 @@ public static void main(String[] args) throws Throwable { subDir += "server" + sep; WhiteBox wb = WhiteBox.getWhiteBox(); - boolean COMPACT_HEADERS = Platform.is64bit() && - wb.getBooleanVMFlag("UseCompactObjectHeaders") && - wb.isDefaultVMFlag("UseCompactObjectHeaders"); - - String suffix = COMPACT_HEADERS ? "_coh.jsa" : ".jsa"; + boolean NOCOMPACT_HEADERS = Platform.is64bit() && + !wb.getBooleanVMFlag("UseCompactObjectHeaders"); + String suffix = NOCOMPACT_HEADERS ? "_nocoh.jsa" : ".jsa"; if (Platform.isAArch64() || Platform.isX64()) { helper.checkImage(image, module, null, null, - new String[] { subDir + "classes" + suffix, subDir + "classes_nocoops" + suffix }); + new String[] { subDir + "classes" + suffix, subDir + "classes_nocoops" + suffix}); } else { helper.checkImage(image, module, null, null, new String[] { subDir + "classes" + suffix }); diff --git a/test/langtools/tools/javac/recovery/AttrRecovery.java b/test/langtools/tools/javac/recovery/AttrRecovery.java index bd74eb6c3f0..64aaad2a184 100644 --- a/test/langtools/tools/javac/recovery/AttrRecovery.java +++ b/test/langtools/tools/javac/recovery/AttrRecovery.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8301580 8322159 8333107 8332230 8338678 8351260 8366196 8372336 8373094 + * @bug 8301580 8322159 8333107 8332230 8338678 8351260 8366196 8372336 8373094 8384229 * @summary Verify error recovery w.r.t. Attr * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -800,6 +800,66 @@ public Void visitVariable(VariableTree tree, Void p) { assertEquals(expected, actual); } + @Test //JDK-8384229 + public void testStaticFieldTypeLookup() throws Exception { + Path out = base.resolve("out"); + + Files.createDirectories(out); + + new JavacTask(tb) + .options("-XDrawDiagnostics", + "-XDdev") + .sources(""" + package test; + import static test.A.Object; + enum A { + Object; + } + class Test { + void foo() { + Object f = ""; + } + } + """) + .outdir(out) + .run() + .writeAll(); + + new JavacTask(tb) + .options("-XDrawDiagnostics", + "-XDdev") + .sources(""" + package test; + import static test.A.Object; + enum A { + Object; + } + class Test { + private static final Object f = ""; + } + """) + .outdir(out) + .run() + .writeAll(); + + new JavacTask(tb) + .options("-XDrawDiagnostics", + "-XDdev") + .sources(""" + package test; + import static test.A.Object; + class A { + public static java.lang.Object Object() { return null; } + } + class Test { + private static final Object f = Object(); + } + """) + .outdir(out) + .run() + .writeAll(); + } + @BeforeEach public void setUp(TestInfo info) throws IOException { base = Path.of(info.getTestMethod().orElseThrow().getName()); diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/MaskLogicOperationsBenchmark.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/MaskLogicOperationsBenchmark.java new file mode 100644 index 00000000000..b70588906af --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/MaskLogicOperationsBenchmark.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2026, NVIDIA CORPORATION & 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.jdk.incubator.vector; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.*; + +import jdk.incubator.vector.*; +import java.util.concurrent.TimeUnit; +import java.util.Random; + +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(value = 2, jvmArgs = { "--add-modules=jdk.incubator.vector" }) +public class MaskLogicOperationsBenchmark { + @Param({"256", "512", "1024"}) + private int size; + + private static final VectorSpecies B_SPECIES = VectorSpecies.ofLargestShape(byte.class); + private static final VectorSpecies S_SPECIES = VectorSpecies.ofLargestShape(short.class); + private static final VectorSpecies I_SPECIES = VectorSpecies.ofLargestShape(int.class); + private static final VectorSpecies L_SPECIES = VectorSpecies.ofLargestShape(long.class); + + private Random r = new Random(); + private boolean[] ma; + private boolean[] mb; + private boolean[] mc; + + @Setup + public void init() { + ma = new boolean[size]; + mb = new boolean[size]; + mc = new boolean[size]; + + for (int i = 0; i < size; i++) { + ma[i] = r.nextInt() % 2 == 0; + mb[i] = r.nextInt() % 2 == 0; + } + } + + @Benchmark + public void byteMaskAndNot() { + VectorMask vm1 = VectorMask.fromArray(B_SPECIES, ma, 0); + for (int i = 0; i < B_SPECIES.loopBound(size); i += B_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(B_SPECIES, mb, i); + vm1.andNot(vm2).intoArray(mc, i); + } + } + + @Benchmark + public void shortMaskAndNot() { + VectorMask vm1 = VectorMask.fromArray(S_SPECIES, ma, 0); + for (int i = 0; i < S_SPECIES.loopBound(size); i += S_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(S_SPECIES, mb, i); + vm1.andNot(vm2).intoArray(mc, i); + } + } + + @Benchmark + public void intMaskAndNot() { + VectorMask vm1 = VectorMask.fromArray(I_SPECIES, ma, 0); + for (int i = 0; i < I_SPECIES.loopBound(size); i += I_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(I_SPECIES, mb, i); + vm1.andNot(vm2).intoArray(mc, i); + } + } + + @Benchmark + public void longMaskAndNot() { + VectorMask vm1 = VectorMask.fromArray(L_SPECIES, ma, 0); + for (int i = 0; i < L_SPECIES.loopBound(size); i += L_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(L_SPECIES, mb, i); + vm1.andNot(vm2).intoArray(mc, i); + } + } + + @Benchmark + public int highMaskRegisterPressureWithNots() { + int res = 0; + VectorMask vm1 = VectorMask.fromArray(B_SPECIES, ma, 0); + for (int i = 0; i < B_SPECIES.loopBound(size); i += B_SPECIES.length()) { + VectorMask vm2 = VectorMask.fromArray(B_SPECIES, mb, i).not(); + VectorMask vm3 = vm1.or(vm2).not(); + VectorMask vm4 = vm1.xor(vm3).not(); + VectorMask vm5 = vm1.or(vm4).not(); + res += vm2.trueCount(); + res += vm3.trueCount(); + res += vm4.trueCount(); + res += vm5.trueCount(); + } + return res; + } +} \ No newline at end of file