You will need X11 libraries suitable for your target system.
-In most cases, using Debian's pre-built libraries work fine.
-
Note that X11 is needed even if you only want to build a headless
-JDK.
+
When not building a headless JDK, you will need X11 libraries
+suitable for your target system. In most cases, using Debian's
+pre-built libraries work fine.
Go to Debian
Package Search, search for the following packages for your
diff --git a/doc/building.md b/doc/building.md
index 11af23d94477..986643094ec2 100644
--- a/doc/building.md
+++ b/doc/building.md
@@ -1173,10 +1173,8 @@ Note that alsa is needed even if you only want to build a headless JDK.
#### X11
-You will need X11 libraries suitable for your *target* system. In most cases,
-using Debian's pre-built libraries work fine.
-
-Note that X11 is needed even if you only want to build a headless JDK.
+When not building a headless JDK, you will need X11 libraries suitable for your
+*target* system. In most cases, using Debian's pre-built libraries work fine.
* Go to [Debian Package Search](https://www.debian.org/distrib/packages),
search for the following packages for your *target* system, and download them
diff --git a/make/autoconf/basic_tools.m4 b/make/autoconf/basic_tools.m4
index 0f5691759b6d..675e1c7eec7e 100644
--- a/make/autoconf/basic_tools.m4
+++ b/make/autoconf/basic_tools.m4
@@ -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
@@ -148,7 +148,7 @@ AC_DEFUN([BASIC_CHECK_MAKE_VERSION],
if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
MAKE_EXPECTED_ENV='cygwin'
elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys2"; then
- MAKE_EXPECTED_ENV='msys'
+ MAKE_EXPECTED_ENV='cygwin|msys'
elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl1" || test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl2"; then
if test "x$OPENJDK_BUILD_CPU" = "xaarch64"; then
MAKE_EXPECTED_ENV='aarch64-.*-linux-gnu'
@@ -159,7 +159,7 @@ AC_DEFUN([BASIC_CHECK_MAKE_VERSION],
AC_MSG_ERROR([Unknown Windows environment])
fi
MAKE_BUILT_FOR=`$MAKE_CANDIDATE --version | $GREP -i 'built for'`
- IS_MAKE_CORRECT_ENV=`$ECHO $MAKE_BUILT_FOR | $GREP $MAKE_EXPECTED_ENV`
+ IS_MAKE_CORRECT_ENV=`$ECHO $MAKE_BUILT_FOR | $GREP -E $MAKE_EXPECTED_ENV`
else
# Not relevant for non-Windows
IS_MAKE_CORRECT_ENV=true
@@ -384,6 +384,10 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS],
IS_GNU_DATE=yes
else
AC_MSG_RESULT([no])
+ # Likely at the AIX provided version of the date utility here, which is not compatible
+ if test "x$OPENJDK_TARGET_OS" = "xaix"; then
+ AC_MSG_ERROR([gnu date from AIX toolbox is required])
+ fi
IS_GNU_DATE=no
fi
AC_SUBST(IS_GNU_DATE)
diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4
index 3a61840e8c97..9bea6b5062e8 100644
--- a/make/autoconf/flags-cflags.m4
+++ b/make/autoconf/flags-cflags.m4
@@ -565,6 +565,11 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
TOOLCHAIN_CFLAGS_JDK_CONLY="-fno-strict-aliasing" # technically NOT for CXX
fi
+ if test "x$ENABLE_LINKTIME_GC" = xtrue; then
+ TOOLCHAIN_CFLAGS_JDK="$TOOLCHAIN_CFLAGS_JDK -ffunction-sections -fdata-sections"
+ TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -ffunction-sections -fdata-sections"
+ fi
+
if test "x$OPENJDK_TARGET_OS" = xaix; then
TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -ffunction-sections -ftls-model -fno-math-errno"
TOOLCHAIN_CFLAGS_JDK="-ffunction-sections -fsigned-char"
diff --git a/make/autoconf/flags-ldflags.m4 b/make/autoconf/flags-ldflags.m4
index 509e0dd825f0..77ea7a693c91 100644
--- a/make/autoconf/flags-ldflags.m4
+++ b/make/autoconf/flags-ldflags.m4
@@ -76,6 +76,10 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER],
if test "x$CXX_IS_USER_SUPPLIED" = xfalse && test "x$CC_IS_USER_SUPPLIED" = xfalse; then
UTIL_REQUIRE_PROGS(LLD, lld, $TOOLCHAIN_PATH:$PATH)
fi
+
+ if test "x$ENABLE_LINKTIME_GC" = xtrue; then
+ BASIC_LDFLAGS_JDK_ONLY="$BASIC_LDFLAGS_JDK_ONLY -Wl,--gc-sections"
+ fi
fi
if test "x$OPENJDK_TARGET_OS" = xaix; then
BASIC_LDFLAGS="-Wl,-b64 -Wl,-brtl -Wl,-bnorwexec -Wl,-blibpath:/usr/lib:lib -Wl,-bnoexpall \
@@ -98,6 +102,9 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER],
# Setup OS-dependent LDFLAGS
if test "x$OPENJDK_TARGET_OS" = xmacosx && test "x$TOOLCHAIN_TYPE" = xclang; then
+ if test x$DEBUG_LEVEL = xrelease; then
+ BASIC_LDFLAGS_JDK_ONLY="$BASIC_LDFLAGS_JDK_ONLY -Wl,-dead_strip"
+ fi
# FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead.
OS_LDFLAGS_JVM_ONLY="-Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.."
OS_LDFLAGS="-mmacosx-version-min=$MACOSX_VERSION_MIN -Wl,-reproducible"
diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4
index a66ce7875064..6d5e59d3db61 100644
--- a/make/autoconf/jdk-options.m4
+++ b/make/autoconf/jdk-options.m4
@@ -102,9 +102,20 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS],
CHECKING_MSG: [if we should build headless-only (no GUI)])
AC_SUBST(ENABLE_HEADLESS_ONLY)
+ # Avoid headless-only on macOS and Windows, it is not supported there
+ if test "x$ENABLE_HEADLESS_ONLY" = xtrue; then
+ if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then
+ AC_MSG_ERROR([headless-only is not supported on macOS and Windows])
+ fi
+ fi
+
# should we linktime gc unused code sections in the JDK build ?
- if test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = xs390x; then
- LINKTIME_GC_DEFAULT=true
+ if test "x$OPENJDK_TARGET_OS" = "xlinux"; then
+ if test "x$OPENJDK_TARGET_CPU" = "xs390x" || test "x$OPENJDK_TARGET_CPU" = "xppc64le"; then
+ LINKTIME_GC_DEFAULT=true
+ else
+ LINKTIME_GC_DEFAULT=false
+ fi
else
LINKTIME_GC_DEFAULT=false
fi
diff --git a/make/autoconf/libraries.m4 b/make/autoconf/libraries.m4
index db93e23b6733..47aa60f8277e 100644
--- a/make/autoconf/libraries.m4
+++ b/make/autoconf/libraries.m4
@@ -46,14 +46,14 @@ m4_include([lib-tests.m4])
AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES],
[
# Check if X11, wayland and vulkan is needed
- if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then
- # No X11 and wayland support on windows or macosx
+ if test "x$OPENJDK_TARGET_OS" = xwindows ||
+ test "x$OPENJDK_TARGET_OS" = xmacosx ||
+ test "x$ENABLE_HEADLESS_ONLY" = xtrue; then
NEEDS_LIB_X11=false
NEEDS_LIB_SPEECHD=false
NEEDS_LIB_WAYLAND=false
else
- # All other instances need X11, even if building headless only, libawt still
- # needs X11 headers.
+ # All other instances need X11 for libawt.
NEEDS_LIB_X11=true
if test "x$ENABLE_HEADLESS_ONLY" = xtrue; then
diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf
index 438e4b3ce8d0..16432a56ba28 100644
--- a/make/conf/github-actions.conf
+++ b/make/conf/github-actions.conf
@@ -29,21 +29,21 @@ GTEST_VERSION=1.14.0
JTREG_VERSION=8+2
LINUX_X64_BOOT_JDK_EXT=tar.gz
-LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_linux-x64_bin.tar.gz
-LINUX_X64_BOOT_JDK_SHA256=88b090fa80c6c1d084ec9a755233967458788e2c0777ae2e172230c5c692d7ef
+LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25.0.3%2B9/OpenJDK25U-jdk_x64_linux_hotspot_25.0.3_9.tar.gz
+LINUX_X64_BOOT_JDK_SHA256=69264a7a211bf5029830d07bc3370f879769d62ebc5b5488e90c9343a2da0e1f
ALPINE_LINUX_X64_BOOT_JDK_EXT=tar.gz
-ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin24-binaries/releases/download/jdk-24%2B36/OpenJDK24U-jdk_x64_alpine-linux_hotspot_24_36.tar.gz
-ALPINE_LINUX_X64_BOOT_JDK_SHA256=a642608f0da78344ee6812fb1490b8bc1d7ad5a18064c70994d6f330568c51cb
+ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25.0.3%2B9/OpenJDK25U-jdk_x64_alpine-linux_hotspot_25.0.3_9.tar.gz
+ALPINE_LINUX_X64_BOOT_JDK_SHA256=51c2415b370aac7c3796b0c4663c8fcf91bc22d76f03df95b25fa5667cb5fdd8
MACOS_AARCH64_BOOT_JDK_EXT=tar.gz
-MACOS_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_macos-aarch64_bin.tar.gz
-MACOS_AARCH64_BOOT_JDK_SHA256=f7133238a12714a62c5ad2bd4da6741130be1a82512065da9ca23dee26b2d3d3
+MACOS_AARCH64_BOOT_JDK_URL=https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25.0.3%2B9/OpenJDK25U-jdk_aarch64_mac_hotspot_25.0.3_9.tar.gz
+MACOS_AARCH64_BOOT_JDK_SHA256=7baab4d69a15554e119b86ff78d40e3fdc28819b5b322955c913cebfe3f6a37c
MACOS_X64_BOOT_JDK_EXT=tar.gz
-MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_macos-x64_bin.tar.gz
-MACOS_X64_BOOT_JDK_SHA256=6bbfb1d01741cbe55ab90299cb91464b695de9a3ace85c15131aa2f50292f321
+MACOS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25.0.3%2B9/OpenJDK25U-jdk_x64_mac_hotspot_25.0.3_9.tar.gz
+MACOS_X64_BOOT_JDK_SHA256=4c539a18b4d656960ff6766727e9ca546fc17f7a29714dba9e7b47bdcb37c447
WINDOWS_X64_BOOT_JDK_EXT=zip
-WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_windows-x64_bin.zip
-WINDOWS_X64_BOOT_JDK_SHA256=11d1d9f6ac272d5361c8a0bef01894364081c7fb1a6914c2ad2fc312ae83d63b
+WINDOWS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25.0.3%2B9/OpenJDK25U-jdk_x64_windows_hotspot_25.0.3_9.zip
+WINDOWS_X64_BOOT_JDK_SHA256=709312cd0420296d9b9de917fe6e28a5b979e875ee5ab91783fb79bcd5857235
diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf
index f82c7822485d..c6b3e674c7a4 100644
--- a/make/conf/version-numbers.conf
+++ b/make/conf/version-numbers.conf
@@ -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
@@ -28,15 +28,15 @@
DEFAULT_VERSION_FEATURE=25
DEFAULT_VERSION_INTERIM=0
-DEFAULT_VERSION_UPDATE=3
+DEFAULT_VERSION_UPDATE=4
DEFAULT_VERSION_PATCH=0
DEFAULT_VERSION_EXTRA1=0
DEFAULT_VERSION_EXTRA2=0
DEFAULT_VERSION_EXTRA3=0
-DEFAULT_VERSION_DATE=2026-04-21
+DEFAULT_VERSION_DATE=2026-07-21
DEFAULT_VERSION_CLASSFILE_MAJOR=69 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_VERSION_DOCS_API_SINCE=11
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="24 25"
DEFAULT_JDK_SOURCE_TARGET_VERSION=25
-DEFAULT_PROMOTED_VERSION_PRE=ea
+DEFAULT_PROMOTED_VERSION_PRE=
diff --git a/make/hotspot/lib/CompileGtest.gmk b/make/hotspot/lib/CompileGtest.gmk
index d2cdc7685c92..544adf572b1b 100644
--- a/make/hotspot/lib/CompileGtest.gmk
+++ b/make/hotspot/lib/CompileGtest.gmk
@@ -45,6 +45,15 @@ else
GTEST_COPY_DEBUG_SYMBOLS := false
endif
+GTEST_LIBJVM_CFLAGS := $(JVM_CFLAGS)
+# Decoder does not work with debuginfo of the gtest libjvm when sections are used,
+# so we get wrong file names. That's why we filter out the section flags.
+ifeq ($(ENABLE_LINKTIME_GC), true)
+ ifeq ($(TOOLCHAIN_TYPE), gcc)
+ GTEST_LIBJVM_CFLAGS := $(filter-out -ffunction-sections -fdata-sections, $(JVM_CFLAGS))
+ endif
+endif
+
################################################################################
## Build libgtest
################################################################################
@@ -94,7 +103,7 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBJVM, \
EXCLUDE_PATTERNS := $(JVM_EXCLUDE_PATTERNS), \
EXTRA_OBJECT_FILES := $(BUILD_LIBJVM_ALL_OBJS), \
DEFAULT_CFLAGS := false, \
- CFLAGS := $(JVM_CFLAGS) \
+ CFLAGS := $(GTEST_LIBJVM_CFLAGS) \
-I$(GTEST_FRAMEWORK_SRC)/googletest/include \
-I$(GTEST_FRAMEWORK_SRC)/googlemock/include \
$(addprefix -I, $(GTEST_TEST_SRC)), \
diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk
index f7a7732993a2..cead9e644360 100644
--- a/make/hotspot/lib/CompileJvm.gmk
+++ b/make/hotspot/lib/CompileJvm.gmk
@@ -204,6 +204,8 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \
DISABLED_WARNINGS_gcc_jvmtiTagMap.cpp := stringop-overflow, \
DISABLED_WARNINGS_gcc_macroAssembler_ppc_sha.cpp := unused-const-variable, \
DISABLED_WARNINGS_gcc_postaloc.cpp := address, \
+ DISABLED_WARNINGS_gcc_safepointMechanism.cpp := stringop-overflow, \
+ DISABLED_WARNINGS_gcc_shenandoahGenerationalHeap.cpp := stringop-overflow, \
DISABLED_WARNINGS_gcc_shenandoahLock.cpp := stringop-overflow, \
DISABLED_WARNINGS_gcc_stubGenerator_s390.cpp := unused-const-variable, \
DISABLED_WARNINGS_gcc_synchronizer.cpp := stringop-overflow, \
diff --git a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java
index 55dd6a8d6ad5..da8eba96dc7b 100644
--- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java
+++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java
@@ -787,10 +787,7 @@ private static Map extractZoneNames(Map map, Str
String tzKey = Optional.ofNullable((String)handlerSupplMeta.get(tzid))
.orElse(tzid);
// Follow link, if needed
- String tzLink = null;
- for (var k = tzKey; tzdbLinks.containsKey(k);) {
- k = tzLink = tzdbLinks.get(k);
- }
+ String tzLink = getTZDBLink(tzKey);
if (tzLink == null && tzdbLinks.containsValue(tzKey)) {
// reverse link search
// this is needed as in tzdb, "America/Buenos_Aires" links to
@@ -810,6 +807,13 @@ private static Map extractZoneNames(Map map, Str
data = map.get(TIMEZONE_ID_PREFIX + tzLink);
}
+ String meta = handlerMetaZones.get(tzKey);
+ if (meta == null && tzLink != null) {
+ // Check for tzLink
+ meta = handlerMetaZones.get(tzLink);
+ }
+ String metaKey = meta != null ? METAZONE_ID_PREFIX + meta : null;
+
if (data instanceof String[] tznames) {
// Hack for UTC. UTC is an alias to Etc/UTC in CLDR
if (tzid.equals("Etc/UTC") && !map.containsKey(TIMEZONE_ID_PREFIX + "UTC")) {
@@ -819,24 +823,16 @@ private static Map extractZoneNames(Map map, Str
} else {
// TZDB short names
tznames = Arrays.copyOf(tznames, tznames.length);
- fillTZDBShortNames(tzid, tznames);
+ fillTZDBShortNames(tzKey, tznames);
names.put(tzid, tznames);
+ if (meta != null && map.get(metaKey) instanceof String[] metaNames) {
+ recordMetazone(names, meta, tzKey, metaNames);
+ }
}
} else {
- String meta = handlerMetaZones.get(tzKey);
- if (meta == null && tzLink != null) {
- // Check for tzLink
- meta = handlerMetaZones.get(tzLink);
- }
if (meta != null) {
- String metaKey = METAZONE_ID_PREFIX + meta;
- data = map.get(metaKey);
- if (data instanceof String[] tznames) {
- // TZDB short names
- tznames = Arrays.copyOf((String[])names.getOrDefault(metaKey, tznames), 6);
- fillTZDBShortNames(tzid, tznames);
- // Keep the metazone prefix here.
- names.putIfAbsent(metaKey, tznames);
+ if (map.get(metaKey) instanceof String[] metaNames) {
+ recordMetazone(names, meta, tzKey, metaNames);
names.put(tzid, meta);
if (tzLink != null && availableIds.contains(tzLink)) {
names.put(tzLink, meta);
@@ -1484,12 +1480,12 @@ private static String flipIfNeeded(boolean inVanguard, String format) {
* Fill the TZDB short names if there is no name provided by the CLDR
*/
private static void fillTZDBShortNames(String tzid, String[] names) {
- var val = tzdbShortNamesMap.get(tzdbLinks.getOrDefault(tzid, tzid));
+ var val = tzdbShortNamesMap.getOrDefault(tzid, tzdbShortNamesMap.get(getTZDBLink(tzid)));
if (val != null) {
var format = val.split(NBSP)[0];
var rule = val.split(NBSP)[1];
IntStream.of(1, 3, 5).forEach(i -> {
- if (names[i] == null) {
+ if (names[i] == null || names[i].isEmpty()) {
if (format.contains("%s")) {
names[i] = switch (i) {
case 1 -> format.formatted(tzdbSubstLetters.get(rule + NBSP + STD));
@@ -1511,6 +1507,28 @@ private static void fillTZDBShortNames(String tzid, String[] names) {
}
}
+ private static void recordMetazone(Map names, String meta, String tzid, String[] tznames) {
+ String zone001 = handlerMetaZones.zidMap().get(meta);
+ var tzLink = getTZDBLink(tzid);
+
+ // Record the metazone names only from the default
+ // (001) zone, with short names filled from TZDB
+ if (canonicalTZMap.getOrDefault(tzid, tzid).equals(zone001) ||
+ tzLink != null && canonicalTZMap.getOrDefault(tzLink, tzLink).equals(zone001)) {
+ tznames = Arrays.copyOf(tznames, tznames.length);
+ fillTZDBShortNames(tzid, tznames);
+ names.put(METAZONE_ID_PREFIX + meta, tznames);
+ }
+ }
+
+ private static String getTZDBLink(String tzid) {
+ String tzLink = null;
+ for (var k = tzid; tzdbLinks.containsKey(k);) {
+ k = tzLink = tzdbLinks.get(k);
+ }
+ return tzLink;
+ }
+
/*
* Convert TZDB offsets to JDK's offsets, eg, "-08" to "GMT-08:00".
* If it cannot recognize the pattern, return the argument as is.
diff --git a/make/modules/java.desktop/lib/AwtLibraries.gmk b/make/modules/java.desktop/lib/AwtLibraries.gmk
index 197e0a17e8dd..cff8cd84ab61 100644
--- a/make/modules/java.desktop/lib/AwtLibraries.gmk
+++ b/make/modules/java.desktop/lib/AwtLibraries.gmk
@@ -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
@@ -102,6 +102,10 @@ ifeq ($(DBUS_FOUND), true)
LIBAWT_CFLAGS += -DDBUS_FOUND
endif
+ifeq ($(ENABLE_HEADLESS_ONLY), true)
+ LIBAWT_CFLAGS += -DHEADLESS
+endif
+
ifeq ($(call isTargetOs, windows), true)
LIBAWT_CFLAGS += -EHsc -DUNICODE -D_UNICODE -DMLIB_OS64BIT
LIBAWT_RCFLAGS ?= -I$(TOPDIR)/src/java.base/windows/native/launcher/icons
@@ -279,13 +283,17 @@ ifeq ($(call isTargetOs, windows macosx), false)
LIBAWT_HEADLESS_EXCLUDE_FILES := \
screencast_pipewire.c \
screencast_portal.c \
+ GLXGraphicsConfig.c \
+ GLXSurfaceData.c \
+ X11PMBlitLoops.c \
+ X11Renderer.c \
+ X11SurfaceData.c \
#
LIBAWT_HEADLESS_EXTRA_HEADER_DIRS := \
$(LIBAWT_DEFAULT_HEADER_DIRS) \
common/awt/debug \
common/font \
- common/java2d/opengl \
java.base:libjvm \
#
@@ -305,7 +313,7 @@ ifeq ($(call isTargetOs, windows macosx), false)
$(eval $(call SetupJdkLibrary, BUILD_LIBAWT_HEADLESS, \
NAME := awt_headless, \
EXTRA_SRC := $(LIBAWT_HEADLESS_EXTRA_SRC), \
- EXCLUDES := medialib wl $(VULKAN_EXCLUDES), \
+ EXCLUDES := medialib opengl wl $(VULKAN_EXCLUDES), \
EXCLUDE_FILES := $(LIBAWT_HEADLESS_EXCLUDE_FILES), \
ONLY_EXPORTED := $(LIBAWT_HEADLESS_ONLY_EXPORTED), \
OPTIMIZATION := LOW, \
@@ -641,6 +649,9 @@ endif
ifeq ($(call isTargetOs, linux)+$(ENABLE_HEADLESS_ONLY), true+true)
LIBJAWT_CFLAGS += -DHEADLESS
endif
+ifeq ($(call isTargetOs, aix)+$(ENABLE_HEADLESS_ONLY), true+true)
+ LIBJAWT_CFLAGS += -DHEADLESS
+endif
ifeq ($(call isTargetOs, windows)+$(call isTargetCpu, x86), true+true)
LIBJAWT_LIBS_windows := kernel32.lib
diff --git a/make/modules/jdk.jdwp.agent/Lib.gmk b/make/modules/jdk.jdwp.agent/Lib.gmk
index 6ae053d4bec1..ce58e145f59b 100644
--- a/make/modules/jdk.jdwp.agent/Lib.gmk
+++ b/make/modules/jdk.jdwp.agent/Lib.gmk
@@ -54,21 +54,6 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJDWP, \
NAME := jdwp, \
OPTIMIZATION := LOW, \
CFLAGS := -DJDWP_LOGGING $(ICONV_CFLAGS), \
- DISABLED_WARNINGS_gcc_eventFilter.c := unused-variable, \
- DISABLED_WARNINGS_gcc_SDE.c := unused-function, \
- DISABLED_WARNINGS_gcc_threadControl.c := unused-but-set-variable \
- unused-variable, \
- DISABLED_WARNINGS_gcc_utf_util.c := unused-but-set-variable, \
- DISABLED_WARNINGS_clang_error_messages.c := format-nonliteral, \
- DISABLED_WARNINGS_clang_eventFilter.c := unused-variable, \
- DISABLED_WARNINGS_clang_EventRequestImpl.c := self-assign, \
- DISABLED_WARNINGS_clang_inStream.c := sometimes-uninitialized, \
- DISABLED_WARNINGS_clang_log_messages.c := format-nonliteral, \
- DISABLED_WARNINGS_clang_SDE.c := unused-function, \
- DISABLED_WARNINGS_clang_threadControl.c := unused-but-set-variable \
- unused-variable, \
- DISABLED_WARNINGS_clang_utf_util.c := unused-but-set-variable, \
- DISABLED_WARNINGS_microsoft_debugInit.c := 5287, \
LDFLAGS := $(ICONV_LDFLAGS), \
EXTRA_HEADER_DIRS := \
include \
diff --git a/make/test/JtregNativeJdk.gmk b/make/test/JtregNativeJdk.gmk
index 7e1417a0dad1..c97ad3f72cfd 100644
--- a/make/test/JtregNativeJdk.gmk
+++ b/make/test/JtregNativeJdk.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 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
@@ -65,7 +65,8 @@ ifeq ($(call isTargetOs, windows), true)
BUILD_JDK_JTREG_EXCLUDE += libDirectIO.c libInheritedChannel.c \
libExplicitAttach.c libImplicitAttach.c \
exelauncher.c \
- libChangeSignalDisposition.c exePrintSignalDisposition.c
+ libChangeSignalDisposition.c exePrintSignalDisposition.c \
+ libConcNativeFork.c libPipesCloseOnExec.c
BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerTest := $(LIBCXX)
BUILD_JDK_JTREG_EXECUTABLES_LIBS_exerevokeall := advapi32.lib
@@ -79,6 +80,8 @@ else
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLinkerInvokerUnnamed := -pthread
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLinkerInvokerModule := -pthread
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libLoaderLookupInvoker := -pthread
+ BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libConcNativeFork := -pthread
+ BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libPipesCloseOnExec := -pthread
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libExplicitAttach := -pthread
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libImplicitAttach := -pthread
diff --git a/src/hotspot/cpu/arm/arm_32.ad b/src/hotspot/cpu/arm/arm_32.ad
index 1c15d55fbc3d..be4dc825e9c7 100644
--- a/src/hotspot/cpu/arm/arm_32.ad
+++ b/src/hotspot/cpu/arm/arm_32.ad
@@ -62,22 +62,22 @@ register %{
// Integer/Long Registers
// ----------------------------
-reg_def R_R0 (SOC, SOC, Op_RegI, 0, R(0)->as_VMReg());
-reg_def R_R1 (SOC, SOC, Op_RegI, 1, R(1)->as_VMReg());
-reg_def R_R2 (SOC, SOC, Op_RegI, 2, R(2)->as_VMReg());
-reg_def R_R3 (SOC, SOC, Op_RegI, 3, R(3)->as_VMReg());
-reg_def R_R4 (SOC, SOE, Op_RegI, 4, R(4)->as_VMReg());
-reg_def R_R5 (SOC, SOE, Op_RegI, 5, R(5)->as_VMReg());
-reg_def R_R6 (SOC, SOE, Op_RegI, 6, R(6)->as_VMReg());
-reg_def R_R7 (SOC, SOE, Op_RegI, 7, R(7)->as_VMReg());
-reg_def R_R8 (SOC, SOE, Op_RegI, 8, R(8)->as_VMReg());
-reg_def R_R9 (SOC, SOE, Op_RegI, 9, R(9)->as_VMReg());
-reg_def R_R10(NS, SOE, Op_RegI, 10, R(10)->as_VMReg());
-reg_def R_R11(NS, SOE, Op_RegI, 11, R(11)->as_VMReg());
-reg_def R_R12(SOC, SOC, Op_RegI, 12, R(12)->as_VMReg());
-reg_def R_R13(NS, NS, Op_RegI, 13, R(13)->as_VMReg());
-reg_def R_R14(SOC, SOC, Op_RegI, 14, R(14)->as_VMReg());
-reg_def R_R15(NS, NS, Op_RegI, 15, R(15)->as_VMReg());
+reg_def R_R0 (SOC, SOC, Op_RegI, 0, as_Register(0)->as_VMReg());
+reg_def R_R1 (SOC, SOC, Op_RegI, 1, as_Register(1)->as_VMReg());
+reg_def R_R2 (SOC, SOC, Op_RegI, 2, as_Register(2)->as_VMReg());
+reg_def R_R3 (SOC, SOC, Op_RegI, 3, as_Register(3)->as_VMReg());
+reg_def R_R4 (SOC, SOE, Op_RegI, 4, as_Register(4)->as_VMReg());
+reg_def R_R5 (SOC, SOE, Op_RegI, 5, as_Register(5)->as_VMReg());
+reg_def R_R6 (SOC, SOE, Op_RegI, 6, as_Register(6)->as_VMReg());
+reg_def R_R7 (SOC, SOE, Op_RegI, 7, as_Register(7)->as_VMReg());
+reg_def R_R8 (SOC, SOE, Op_RegI, 8, as_Register(8)->as_VMReg());
+reg_def R_R9 (SOC, SOE, Op_RegI, 9, as_Register(9)->as_VMReg());
+reg_def R_R10(NS, SOE, Op_RegI, 10, as_Register(10)->as_VMReg());
+reg_def R_R11(NS, SOE, Op_RegI, 11, as_Register(11)->as_VMReg());
+reg_def R_R12(SOC, SOC, Op_RegI, 12, as_Register(12)->as_VMReg());
+reg_def R_R13(NS, NS, Op_RegI, 13, as_Register(13)->as_VMReg());
+reg_def R_R14(SOC, SOC, Op_RegI, 14, as_Register(14)->as_VMReg());
+reg_def R_R15(NS, NS, Op_RegI, 15, as_Register(15)->as_VMReg());
// ----------------------------
// Float/Double Registers
diff --git a/src/hotspot/cpu/arm/assembler_arm_32.hpp b/src/hotspot/cpu/arm/assembler_arm_32.hpp
index ae13644ecf9e..d6524f086800 100644
--- a/src/hotspot/cpu/arm/assembler_arm_32.hpp
+++ b/src/hotspot/cpu/arm/assembler_arm_32.hpp
@@ -114,7 +114,7 @@ class RegisterSet {
}
RegisterSet(Register first, Register last) {
- assert(first < last, "encoding constraint");
+ assert(first->encoding() < last->encoding(), "encoding constraint");
_encoding = (1 << (last->encoding() + 1)) - (1 << first->encoding());
}
diff --git a/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp b/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp
index 5683bc59d5c0..60eae37e2193 100644
--- a/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp
+++ b/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp
@@ -181,7 +181,7 @@ void MonitorEnterStub::emit_code(LIR_Assembler* ce) {
const Register lock_reg = _lock_reg->as_pointer_register();
ce->verify_reserved_argument_area_size(2);
- if (obj_reg < lock_reg) {
+ if (obj_reg->encoding() < lock_reg->encoding()) {
__ stmia(SP, RegisterSet(obj_reg) | RegisterSet(lock_reg));
} else {
__ str(obj_reg, Address(SP));
diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp
index 66c7b916f1ff..2f7901db82e3 100644
--- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp
+++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp
@@ -2655,11 +2655,11 @@ void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type,
const Register src_hi = src->as_register_hi();
assert(addr->index()->is_illegal() && addr->disp() == 0, "The address is simple already");
- if (src_lo < src_hi) {
+ if (src_lo->encoding() < src_hi->encoding()) {
null_check_offset = __ offset();
__ stmia(addr->base()->as_register(), RegisterSet(src_lo) | RegisterSet(src_hi));
} else {
- assert(src_lo < Rtemp, "Rtemp is higher than any allocatable register");
+ assert(src_lo->encoding() < Rtemp->encoding(), "Rtemp is higher than any allocatable register");
__ mov(Rtemp, src_hi);
null_check_offset = __ offset();
__ stmia(addr->base()->as_register(), RegisterSet(src_lo) | RegisterSet(Rtemp));
@@ -2672,10 +2672,10 @@ void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type,
assert(addr->index()->is_illegal() && addr->disp() == 0, "The address is simple already");
null_check_offset = __ offset();
- if (dest_lo < dest_hi) {
+ if (dest_lo->encoding() < dest_hi->encoding()) {
__ ldmia(addr->base()->as_register(), RegisterSet(dest_lo) | RegisterSet(dest_hi));
} else {
- assert(dest_lo < Rtemp, "Rtemp is higher than any allocatable register");
+ assert(dest_lo->encoding() < Rtemp->encoding(), "Rtemp is higher than any allocatable register");
__ ldmia(addr->base()->as_register(), RegisterSet(dest_lo) | RegisterSet(Rtemp));
__ mov(dest_hi, Rtemp);
}
diff --git a/src/hotspot/cpu/arm/interp_masm_arm.cpp b/src/hotspot/cpu/arm/interp_masm_arm.cpp
index e9e6187a6d18..69f3f726ab2d 100644
--- a/src/hotspot/cpu/arm/interp_masm_arm.cpp
+++ b/src/hotspot/cpu/arm/interp_masm_arm.cpp
@@ -409,7 +409,7 @@ void InterpreterMacroAssembler::pop_i(Register r) {
void InterpreterMacroAssembler::pop_l(Register lo, Register hi) {
assert_different_registers(lo, hi);
- assert(lo < hi, "lo must be < hi");
+ assert(lo->encoding() < hi->encoding(), "lo must be < hi");
pop(RegisterSet(lo) | RegisterSet(hi));
}
@@ -459,7 +459,7 @@ void InterpreterMacroAssembler::push_i(Register r) {
void InterpreterMacroAssembler::push_l(Register lo, Register hi) {
assert_different_registers(lo, hi);
- assert(lo < hi, "lo must be < hi");
+ assert(lo->encoding() < hi->encoding(), "lo must be < hi");
push(RegisterSet(lo) | RegisterSet(hi));
}
diff --git a/src/hotspot/cpu/arm/register_arm.cpp b/src/hotspot/cpu/arm/register_arm.cpp
index ea3ef87e6708..296c55e2e164 100644
--- a/src/hotspot/cpu/arm/register_arm.cpp
+++ b/src/hotspot/cpu/arm/register_arm.cpp
@@ -25,12 +25,19 @@
#include "register_arm.hpp"
#include "utilities/debug.hpp"
-const int ConcreteRegisterImpl::max_gpr = ConcreteRegisterImpl::num_gpr;
-const int ConcreteRegisterImpl::max_fpr = ConcreteRegisterImpl::num_fpr +
- ConcreteRegisterImpl::max_gpr;
+Register::RegisterImpl all_RegisterImpls [Register::number_of_registers + 1];
+FloatRegister::FloatRegisterImpl all_FloatRegisterImpls [FloatRegister::number_of_registers + 1];
+VFPSystemRegister::VFPSystemRegisterImpl all_VFPSystemRegisterImpls [VFPSystemRegister::number_of_registers + 1] {
+ { -1 }, //vfpsnoreg
+ { VFPSystemRegister::FPSID },
+ { VFPSystemRegister::FPSCR },
+ { VFPSystemRegister::MVFR0 },
+ { VFPSystemRegister::MVFR1 }
+};
-const char* RegisterImpl::name() const {
- const char* names[number_of_registers] = {
+const char* Register::RegisterImpl::name() const {
+ static const char* names[number_of_registers + 1] = {
+ "noreg",
"r0", "r1", "r2", "r3", "r4", "r5", "r6",
#if (FP_REG_NUM == 7)
"fp",
@@ -45,13 +52,14 @@ const char* RegisterImpl::name() const {
#endif
"r12", "sp", "lr", "pc"
};
- return is_valid() ? names[encoding()] : "noreg";
+ return names[encoding() + 1];
}
-const char* FloatRegisterImpl::name() const {
- const char* names[number_of_registers] = {
- "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
- "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
+const char* FloatRegister::FloatRegisterImpl::name() const {
+ static const char* names[number_of_registers + 1] = {
+ "fnoreg",
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
"s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
"s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"
#ifdef COMPILER2
@@ -61,5 +69,5 @@ const char* FloatRegisterImpl::name() const {
"s56", "s57?","s58", "s59?","s60", "s61?","s62", "s63?"
#endif
};
- return is_valid() ? names[encoding()] : "fnoreg";
+ return names[encoding() + 1];
}
diff --git a/src/hotspot/cpu/arm/register_arm.hpp b/src/hotspot/cpu/arm/register_arm.hpp
index fca23d07fee5..b7286bb68a45 100644
--- a/src/hotspot/cpu/arm/register_arm.hpp
+++ b/src/hotspot/cpu/arm/register_arm.hpp
@@ -31,26 +31,6 @@
class VMRegImpl;
typedef VMRegImpl* VMReg;
-// These are declared ucontext.h
-#undef R0
-#undef R1
-#undef R2
-#undef R3
-#undef R4
-#undef R5
-#undef R6
-#undef R7
-#undef R8
-#undef R9
-#undef R10
-#undef R11
-#undef R12
-#undef R13
-#undef R14
-#undef R15
-
-#define R(r) ((Register)(r))
-
/////////////////////////////////
// Support for different ARM ABIs
// Note: default ABI is for linux
@@ -94,25 +74,86 @@ typedef VMRegImpl* VMReg;
#define ALIGN_WIDE_ARGUMENTS 1
#endif
-#define R0 ((Register)0)
-#define R1 ((Register)1)
-#define R2 ((Register)2)
-#define R3 ((Register)3)
-#define R4 ((Register)4)
-#define R5 ((Register)5)
-#define R6 ((Register)6)
-#define R7 ((Register)7)
-#define R8 ((Register)8)
-#define R9 ((Register)9)
-#define R10 ((Register)10)
-#define R11 ((Register)11)
-#define R12 ((Register)12)
-#define R13 ((Register)13)
-#define R14 ((Register)14)
-#define R15 ((Register)15)
-
-
-#define FP ((Register)FP_REG_NUM)
+class Register {
+ private:
+ int _encoding;
+
+ constexpr explicit Register(int encoding) : _encoding(encoding) {}
+
+ public:
+ enum {
+ number_of_registers = 16,
+ max_slots_per_register = 1
+ };
+
+ class RegisterImpl : public AbstractRegisterImpl {
+ friend class Register;
+
+ static constexpr const RegisterImpl* first();
+
+ public:
+
+ // accessors and testers
+ int raw_encoding() const { return this - first(); }
+ int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); }
+ bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; }
+
+ inline Register successor() const;
+
+ VMReg as_VMReg() const;
+
+ const char* name() const;
+ };
+
+
+ inline friend constexpr Register as_Register(int encoding);
+
+ constexpr Register() : _encoding(-1) {} //noreg
+
+ int operator==(const Register r) const { return _encoding == r._encoding; }
+ int operator!=(const Register r) const { return _encoding != r._encoding; }
+
+ const RegisterImpl* operator->() const { return RegisterImpl::first() + _encoding; }
+};
+
+extern Register::RegisterImpl all_RegisterImpls[Register::number_of_registers + 1] INTERNAL_VISIBILITY;
+
+inline constexpr const Register::RegisterImpl* Register::RegisterImpl::first() {
+ return all_RegisterImpls + 1;
+}
+
+constexpr Register noreg = Register();
+
+inline constexpr Register as_Register(int encoding) {
+ if (0 <= encoding && encoding < Register::number_of_registers) {
+ return Register(encoding);
+ }
+ return noreg;
+}
+
+inline Register Register::RegisterImpl::successor() const {
+ assert(is_valid(), "sainty");
+ return as_Register(encoding() + 1);
+}
+
+constexpr Register R0 = as_Register( 0);
+constexpr Register R1 = as_Register( 1);
+constexpr Register R2 = as_Register( 2);
+constexpr Register R3 = as_Register( 3);
+constexpr Register R4 = as_Register( 4);
+constexpr Register R5 = as_Register( 5);
+constexpr Register R6 = as_Register( 6);
+constexpr Register R7 = as_Register( 7);
+constexpr Register R8 = as_Register( 8);
+constexpr Register R9 = as_Register( 9);
+constexpr Register R10 = as_Register(10);
+constexpr Register R11 = as_Register(11);
+constexpr Register R12 = as_Register(12);
+constexpr Register R13 = as_Register(13);
+constexpr Register R14 = as_Register(14);
+constexpr Register R15 = as_Register(15);
+
+constexpr Register FP = as_Register(FP_REG_NUM);
// Safe use of registers which may be FP on some platforms.
//
@@ -122,185 +163,170 @@ typedef VMRegImpl* VMReg;
// as FP on supported ABIs (and replace R# by altFP_#_11). altFP_#_11
// must be #define to R11 if and only if # is FP_REG_NUM.
#if (FP_REG_NUM == 7)
-#define altFP_7_11 ((Register)11)
+constexpr Register altFP_7_11 = R11;
#else
-#define altFP_7_11 ((Register)7)
+constexpr Register altFP_7_11 = R7;
#endif
-#define SP R13
-#define LR R14
-#define PC R15
+constexpr Register SP = R13;
+constexpr Register LR = R14;
+constexpr Register PC = R15;
-class RegisterImpl;
-typedef RegisterImpl* Register;
+class FloatRegister {
+ private:
+ int _encoding;
-inline Register as_Register(int encoding) {
- return (Register)(intptr_t)encoding;
-}
+ constexpr explicit FloatRegister(int encoding) : _encoding(encoding) {}
-class RegisterImpl : public AbstractRegisterImpl {
public:
enum {
- number_of_registers = 16
+ number_of_registers = NOT_COMPILER2(32) COMPILER2_PRESENT(64),
+ max_slots_per_register = 1
};
- Register successor() const { return as_Register(encoding() + 1); }
+ class FloatRegisterImpl : public AbstractRegisterImpl {
+ friend class FloatRegister;
- inline friend Register as_Register(int encoding);
+ static constexpr const FloatRegisterImpl* first();
- VMReg as_VMReg();
+ public:
- // accessors
- int encoding() const { assert(is_valid(), "invalid register"); return value(); }
- const char* name() const;
+ // accessors and testers
+ int raw_encoding() const { return this - first(); }
+ int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); }
+ bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; }
+ inline FloatRegister successor() const;
- // testers
- bool is_valid() const { return 0 <= value() && value() < number_of_registers; }
-
-};
+ VMReg as_VMReg() const;
-CONSTANT_REGISTER_DECLARATION(Register, noreg, (-1));
+ int hi_bits() const {
+ return (encoding() >> 1) & 0xf;
+ }
+ int lo_bit() const {
+ return encoding() & 1;
+ }
-// Use FloatRegister as shortcut
-class FloatRegisterImpl;
-typedef FloatRegisterImpl* FloatRegister;
+ int hi_bit() const {
+ return encoding() >> 5;
+ }
-inline FloatRegister as_FloatRegister(int encoding) {
- return (FloatRegister)(intptr_t)encoding;
-}
-
-class FloatRegisterImpl : public AbstractRegisterImpl {
- public:
- enum {
- number_of_registers = NOT_COMPILER2(32) COMPILER2_PRESENT(64)
+ const char* name() const;
};
- inline friend FloatRegister as_FloatRegister(int encoding);
+ inline friend constexpr FloatRegister as_FloatRegister(int encoding);
- VMReg as_VMReg();
+ constexpr FloatRegister() : _encoding(-1) {} // fnoreg
- int encoding() const { assert(is_valid(), "invalid register"); return value(); }
- bool is_valid() const { return 0 <= (intx)this && (intx)this < number_of_registers; }
- FloatRegister successor() const { return as_FloatRegister(encoding() + 1); }
+ int operator==(const FloatRegister r) const { return _encoding == r._encoding; }
+ int operator!=(const FloatRegister r) const { return _encoding != r._encoding; }
- const char* name() const;
+ const FloatRegisterImpl* operator->() const { return FloatRegisterImpl::first() + _encoding; }
+};
- int hi_bits() const {
- return (encoding() >> 1) & 0xf;
- }
+extern FloatRegister::FloatRegisterImpl all_FloatRegisterImpls[FloatRegister::number_of_registers + 1] INTERNAL_VISIBILITY;
- int lo_bit() const {
- return encoding() & 1;
- }
+inline constexpr const FloatRegister::FloatRegisterImpl* FloatRegister::FloatRegisterImpl::first() {
+ return all_FloatRegisterImpls + 1;
+}
+
+constexpr FloatRegister fnoreg = FloatRegister();
- int hi_bit() const {
- return encoding() >> 5;
+inline constexpr FloatRegister as_FloatRegister(int encoding) {
+ if (0 <= encoding && encoding < FloatRegister::number_of_registers) {
+ return FloatRegister(encoding);
}
-};
+ return fnoreg;
+}
-CONSTANT_REGISTER_DECLARATION(FloatRegister, fnoreg, (-1));
+inline FloatRegister FloatRegister::FloatRegisterImpl::successor() const {
+ assert(is_valid(), "sainty");
+ return as_FloatRegister(encoding() + 1);
+}
/*
* S1-S6 are named with "_reg" suffix to avoid conflict with
* constants defined in sharedRuntimeTrig.cpp
*/
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S0, ( 0));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S1_reg, ( 1));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S2_reg, ( 2));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S3_reg, ( 3));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S4_reg, ( 4));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S5_reg, ( 5));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S6_reg, ( 6));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S7, ( 7));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S8, ( 8));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S9, ( 9));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S10, (10));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S11, (11));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S12, (12));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S13, (13));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S14, (14));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S15, (15));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S16, (16));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S17, (17));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S18, (18));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S19, (19));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S20, (20));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S21, (21));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S22, (22));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S23, (23));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S24, (24));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S25, (25));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S26, (26));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S27, (27));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S28, (28));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S29, (29));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S30, (30));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, S31, (31));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, Stemp, (30));
-
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D0, ( 0));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D1, ( 2));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D2, ( 4));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D3, ( 6));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D4, ( 8));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D5, ( 10));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D6, ( 12));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D7, ( 14));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D8, ( 16));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D9, ( 18));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D10, ( 20));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D11, ( 22));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D12, ( 24));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D13, ( 26));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D14, ( 28));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D15, (30));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D16, (32));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D17, (34));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D18, (36));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D19, (38));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D20, (40));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D21, (42));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D22, (44));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D23, (46));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D24, (48));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D25, (50));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D26, (52));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D27, (54));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D28, (56));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D29, (58));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D30, (60));
-CONSTANT_REGISTER_DECLARATION(FloatRegister, D31, (62));
+constexpr FloatRegister S0 = as_FloatRegister( 0);
+constexpr FloatRegister S1_reg = as_FloatRegister(1);
+constexpr FloatRegister S2_reg = as_FloatRegister(2);
+constexpr FloatRegister S3_reg = as_FloatRegister(3);
+constexpr FloatRegister S4_reg = as_FloatRegister(4);
+constexpr FloatRegister S5_reg = as_FloatRegister(5);
+constexpr FloatRegister S6_reg = as_FloatRegister(6);
+constexpr FloatRegister S7 = as_FloatRegister( 7);
+constexpr FloatRegister S8 = as_FloatRegister( 8);
+constexpr FloatRegister S9 = as_FloatRegister( 9);
+constexpr FloatRegister S10 = as_FloatRegister(10);
+constexpr FloatRegister S11 = as_FloatRegister(11);
+constexpr FloatRegister S12 = as_FloatRegister(12);
+constexpr FloatRegister S13 = as_FloatRegister(13);
+constexpr FloatRegister S14 = as_FloatRegister(14);
+constexpr FloatRegister S15 = as_FloatRegister(15);
+constexpr FloatRegister S16 = as_FloatRegister(16);
+constexpr FloatRegister S17 = as_FloatRegister(17);
+constexpr FloatRegister S18 = as_FloatRegister(18);
+constexpr FloatRegister S19 = as_FloatRegister(19);
+constexpr FloatRegister S20 = as_FloatRegister(20);
+constexpr FloatRegister S21 = as_FloatRegister(21);
+constexpr FloatRegister S22 = as_FloatRegister(22);
+constexpr FloatRegister S23 = as_FloatRegister(23);
+constexpr FloatRegister S24 = as_FloatRegister(24);
+constexpr FloatRegister S25 = as_FloatRegister(25);
+constexpr FloatRegister S26 = as_FloatRegister(26);
+constexpr FloatRegister S27 = as_FloatRegister(27);
+constexpr FloatRegister S28 = as_FloatRegister(28);
+constexpr FloatRegister S29 = as_FloatRegister(29);
+constexpr FloatRegister S30 = as_FloatRegister(30);
+constexpr FloatRegister S31 = as_FloatRegister(31);
+constexpr FloatRegister Stemp = S30;
+
+constexpr FloatRegister D0 = as_FloatRegister( 0);
+constexpr FloatRegister D1 = as_FloatRegister( 2);
+constexpr FloatRegister D2 = as_FloatRegister( 4);
+constexpr FloatRegister D3 = as_FloatRegister( 6);
+constexpr FloatRegister D4 = as_FloatRegister( 8);
+constexpr FloatRegister D5 = as_FloatRegister(10);
+constexpr FloatRegister D6 = as_FloatRegister(12);
+constexpr FloatRegister D7 = as_FloatRegister(14);
+constexpr FloatRegister D8 = as_FloatRegister(16);
+constexpr FloatRegister D9 = as_FloatRegister(18);
+constexpr FloatRegister D10 = as_FloatRegister(20);
+constexpr FloatRegister D11 = as_FloatRegister(22);
+constexpr FloatRegister D12 = as_FloatRegister(24);
+constexpr FloatRegister D13 = as_FloatRegister(26);
+constexpr FloatRegister D14 = as_FloatRegister(28);
+constexpr FloatRegister D15 = as_FloatRegister(30);
+constexpr FloatRegister D16 = as_FloatRegister(32);
+constexpr FloatRegister D17 = as_FloatRegister(34);
+constexpr FloatRegister D18 = as_FloatRegister(36);
+constexpr FloatRegister D19 = as_FloatRegister(38);
+constexpr FloatRegister D20 = as_FloatRegister(40);
+constexpr FloatRegister D21 = as_FloatRegister(42);
+constexpr FloatRegister D22 = as_FloatRegister(44);
+constexpr FloatRegister D23 = as_FloatRegister(46);
+constexpr FloatRegister D24 = as_FloatRegister(48);
+constexpr FloatRegister D25 = as_FloatRegister(50);
+constexpr FloatRegister D26 = as_FloatRegister(52);
+constexpr FloatRegister D27 = as_FloatRegister(54);
+constexpr FloatRegister D28 = as_FloatRegister(56);
+constexpr FloatRegister D29 = as_FloatRegister(58);
+constexpr FloatRegister D30 = as_FloatRegister(60);
+constexpr FloatRegister D31 = as_FloatRegister(62);
class ConcreteRegisterImpl : public AbstractRegisterImpl {
public:
enum {
- log_vmregs_per_word = LogBytesPerWord - LogBytesPerInt, // VMRegs are of 4-byte size
-#ifdef COMPILER2
- log_bytes_per_fpr = 2, // quad vectors
-#else
- log_bytes_per_fpr = 2, // double vectors
-#endif
- log_words_per_fpr = log_bytes_per_fpr - LogBytesPerWord,
- words_per_fpr = 1 << log_words_per_fpr,
- log_vmregs_per_fpr = log_bytes_per_fpr - LogBytesPerInt,
- log_vmregs_per_gpr = log_vmregs_per_word,
- vmregs_per_gpr = 1 << log_vmregs_per_gpr,
- vmregs_per_fpr = 1 << log_vmregs_per_fpr,
-
- num_gpr = RegisterImpl::number_of_registers << log_vmregs_per_gpr,
- max_gpr0 = num_gpr,
- num_fpr = FloatRegisterImpl::number_of_registers << log_vmregs_per_fpr,
- max_fpr0 = max_gpr0 + num_fpr,
- number_of_registers = num_gpr + num_fpr + 1+1 // APSR and FPSCR so that c2's REG_COUNT <= ConcreteRegisterImpl::number_of_registers
- };
+ max_gpr = Register::number_of_registers * Register::max_slots_per_register,
+ max_fpr = max_gpr + FloatRegister::number_of_registers * FloatRegister::max_slots_per_register,
- static const int max_gpr;
- static const int max_fpr;
+ number_of_registers = max_fpr + 1+1 // APSR and FPSCR so that c2's REG_COUNT <= ConcreteRegisterImpl::number_of_registers
+ };
};
typedef AbstractRegSet RegSet;
@@ -328,101 +354,157 @@ inline FloatRegister AbstractRegSet::last() {
-class VFPSystemRegisterImpl;
-typedef VFPSystemRegisterImpl* VFPSystemRegister;
-class VFPSystemRegisterImpl : public AbstractRegisterImpl {
+class VFPSystemRegister {
+ private:
+ int _store_idx;
+
+ constexpr explicit VFPSystemRegister(int store_idx) : _store_idx(store_idx) {}
+
+ enum {
+ _FPSID_store_idx = 0,
+ _FPSCR_store_idx = 1,
+ _MVFR0_store_idx = 2,
+ _MVFR1_store_idx = 3
+ };
+
public:
- int encoding() const { return value(); }
+ enum {
+ FPSID = 0,
+ FPSCR = 1,
+ MVFR0 = 6,
+ MVFR1 = 7,
+ number_of_registers = 4
+ };
+
+ class VFPSystemRegisterImpl : public AbstractRegisterImpl {
+ friend class VFPSystemRegister;
+
+ int _encoding;
+
+ static constexpr const VFPSystemRegisterImpl* first();
+
+ public:
+ constexpr VFPSystemRegisterImpl(int encoding) : _encoding(encoding) {}
+
+ int encoding() const { return _encoding; }
+ };
+
+ inline friend constexpr VFPSystemRegister as_VFPSystemRegister(int encoding);
+
+ constexpr VFPSystemRegister() : _store_idx(-1) {} // vfpsnoreg
+
+ int operator==(const VFPSystemRegister r) const { return _store_idx == r._store_idx; }
+ int operator!=(const VFPSystemRegister r) const { return _store_idx != r._store_idx; }
+
+ const VFPSystemRegisterImpl* operator->() const { return VFPSystemRegisterImpl::first() + _store_idx; }
};
-#define FPSID ((VFPSystemRegister)0)
-#define FPSCR ((VFPSystemRegister)1)
-#define MVFR0 ((VFPSystemRegister)0x6)
-#define MVFR1 ((VFPSystemRegister)0x7)
+extern VFPSystemRegister::VFPSystemRegisterImpl all_VFPSystemRegisterImpls[VFPSystemRegister::number_of_registers + 1] INTERNAL_VISIBILITY;
+
+inline constexpr const VFPSystemRegister::VFPSystemRegisterImpl* VFPSystemRegister::VFPSystemRegisterImpl::first() {
+ return all_VFPSystemRegisterImpls + 1;
+}
+
+constexpr VFPSystemRegister vfpsnoreg = VFPSystemRegister();
+
+inline constexpr VFPSystemRegister as_VFPSystemRegister(int encoding) {
+ switch (encoding) {
+ case VFPSystemRegister::FPSID: return VFPSystemRegister(VFPSystemRegister::_FPSID_store_idx);
+ case VFPSystemRegister::FPSCR: return VFPSystemRegister(VFPSystemRegister::_FPSCR_store_idx);
+ case VFPSystemRegister::MVFR0: return VFPSystemRegister(VFPSystemRegister::_MVFR0_store_idx);
+ case VFPSystemRegister::MVFR1: return VFPSystemRegister(VFPSystemRegister::_MVFR1_store_idx);
+ default: return vfpsnoreg;
+ }
+}
+
+constexpr VFPSystemRegister FPSID = as_VFPSystemRegister(VFPSystemRegister::FPSID);
+constexpr VFPSystemRegister FPSCR = as_VFPSystemRegister(VFPSystemRegister::FPSCR);
+constexpr VFPSystemRegister MVFR0 = as_VFPSystemRegister(VFPSystemRegister::MVFR0);
+constexpr VFPSystemRegister MVFR1 = as_VFPSystemRegister(VFPSystemRegister::MVFR1);
/*
* Register definitions shared across interpreter and compiler
*/
-#define Rexception_obj R4
-#define Rexception_pc R5
+constexpr Register Rexception_obj = R4;
+constexpr Register Rexception_pc = R5;
/*
* Interpreter register definitions common to C++ and template interpreters.
*/
-#define Rlocals R8
-#define Rmethod R9
-#define Rthread R10
-#define Rtemp R12
+constexpr Register Rlocals = R8;
+constexpr Register Rmethod = R9;
+constexpr Register Rthread = R10;
+constexpr Register Rtemp = R12;
// Interpreter calling conventions
-#define Rparams SP
-#define Rsender_sp R4
+constexpr Register Rparams = SP;
+constexpr Register Rsender_sp = R4;
// JSR292
// Note: R5_mh is needed only during the call setup, including adapters
// This does not seem to conflict with Rexception_pc
// In case of issues, R3 might be OK but adapters calling the runtime would have to save it
-#define R5_mh R5 // MethodHandle register, used during the call setup
-#define Rmh_SP_save FP // for C1
+constexpr Register R5_mh = R5; // MethodHandle register, used during the call setup
+constexpr Register Rmh_SP_save = FP; // for C1
/*
* C++ Interpreter Register Defines
*/
-#define Rsave0 R4
-#define Rsave1 R5
-#define Rsave2 R6
-#define Rstate altFP_7_11 // R7 or R11
-#define Ricklass R8
+constexpr Register Rsave0 = R4;
+constexpr Register Rsave1 = R5;
+constexpr Register Rsave2 = R6;
+constexpr Register Rstate = altFP_7_11; // R7 or R11
+constexpr Register Ricklass = R8;
/*
* TemplateTable Interpreter Register Usage
*/
// Temporary registers
-#define R0_tmp R0
-#define R1_tmp R1
-#define R2_tmp R2
-#define R3_tmp R3
-#define R4_tmp R4
-#define R5_tmp R5
-#define R12_tmp R12
-#define LR_tmp LR
+constexpr Register R0_tmp = R0;
+constexpr Register R1_tmp = R1;
+constexpr Register R2_tmp = R2;
+constexpr Register R3_tmp = R3;
+constexpr Register R4_tmp = R4;
+constexpr Register R5_tmp = R5;
+constexpr Register R12_tmp = R12;
+constexpr Register LR_tmp = LR;
-#define S0_tmp S0
-#define S1_tmp S1_reg
+constexpr FloatRegister S0_tmp = S0;
+constexpr FloatRegister S1_tmp = S1_reg;
-#define D0_tmp D0
-#define D1_tmp D1
+constexpr FloatRegister D0_tmp = D0;
+constexpr FloatRegister D1_tmp = D1;
// Temporary registers saved across VM calls (according to C calling conventions)
-#define Rtmp_save0 R4
-#define Rtmp_save1 R5
+constexpr Register Rtmp_save0 = R4;
+constexpr Register Rtmp_save1 = R5;
// Cached TOS value
-#define R0_tos R0
+constexpr Register R0_tos = R0;
-#define R0_tos_lo R0
-#define R1_tos_hi R1
+constexpr Register R0_tos_lo = R0;
+constexpr Register R1_tos_hi = R1;
-#define S0_tos S0
-#define D0_tos D0
+constexpr FloatRegister S0_tos = S0;
+constexpr FloatRegister D0_tos = D0;
// Dispatch table
-#define RdispatchTable R6
+constexpr Register RdispatchTable = R6;
// Bytecode pointer
-#define Rbcp altFP_7_11
+constexpr Register Rbcp = altFP_7_11;
// Pre-loaded next bytecode for the dispatch
-#define R3_bytecode R3
+constexpr Register R3_bytecode = R3;
// Conventions between bytecode templates and stubs
-#define R2_ClassCastException_obj R2
-#define R4_ArrayIndexOutOfBounds_index R4
+constexpr Register R2_ClassCastException_obj = R2;
+constexpr Register R4_ArrayIndexOutOfBounds_index = R4;
// Interpreter expression stack top
-#define Rstack_top SP
+constexpr Register Rstack_top = SP;
/*
* Linux 32-bit ARM C ABI Register calling conventions
@@ -445,10 +527,11 @@ class VFPSystemRegisterImpl : public AbstractRegisterImpl {
* R14 (LR) Link register
* R15 (PC) Program Counter
*/
-#define c_rarg0 R0
-#define c_rarg1 R1
-#define c_rarg2 R2
-#define c_rarg3 R3
+
+constexpr Register c_rarg0 = R0;
+constexpr Register c_rarg1 = R1;
+constexpr Register c_rarg2 = R2;
+constexpr Register c_rarg3 = R3;
#define GPR_PARAMS 4
@@ -456,10 +539,10 @@ class VFPSystemRegisterImpl : public AbstractRegisterImpl {
// Java ABI
// XXX Is this correct?
-#define j_rarg0 c_rarg0
-#define j_rarg1 c_rarg1
-#define j_rarg2 c_rarg2
-#define j_rarg3 c_rarg3
+constexpr Register j_rarg0 = c_rarg0;
+constexpr Register j_rarg1 = c_rarg1;
+constexpr Register j_rarg2 = c_rarg2;
+constexpr Register j_rarg3 = c_rarg3;
#endif // CPU_ARM_REGISTER_ARM_HPP
diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
index 8ba847e7e328..2fc317cbb286 100644
--- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
+++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
@@ -70,7 +70,7 @@ class RegisterSaver {
enum RegisterLayout {
- fpu_save_size = FloatRegisterImpl::number_of_registers,
+ fpu_save_size = FloatRegister::number_of_registers,
#ifndef __SOFTFP__
D0_offset = 0,
#endif
@@ -139,8 +139,8 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm,
if (VM_Version::has_vfp3_32()) {
__ fpush(FloatRegisterSet(D16, 16));
} else {
- if (FloatRegisterImpl::number_of_registers > 32) {
- assert(FloatRegisterImpl::number_of_registers == 64, "nb fp registers should be 64");
+ if (FloatRegister::number_of_registers > 32) {
+ assert(FloatRegister::number_of_registers == 64, "nb fp registers should be 64");
__ sub(SP, SP, 32 * wordSize);
}
}
@@ -182,8 +182,8 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_lr
if (VM_Version::has_vfp3_32()) {
__ fpop(FloatRegisterSet(D16, 16));
} else {
- if (FloatRegisterImpl::number_of_registers > 32) {
- assert(FloatRegisterImpl::number_of_registers == 64, "nb fp registers should be 64");
+ if (FloatRegister::number_of_registers > 32) {
+ assert(FloatRegister::number_of_registers == 64, "nb fp registers should be 64");
__ add(SP, SP, 32 * wordSize);
}
}
diff --git a/src/hotspot/cpu/arm/vmreg_arm.cpp b/src/hotspot/cpu/arm/vmreg_arm.cpp
index 4ce1dd0be20f..efaf38ef7297 100644
--- a/src/hotspot/cpu/arm/vmreg_arm.cpp
+++ b/src/hotspot/cpu/arm/vmreg_arm.cpp
@@ -30,14 +30,14 @@ void VMRegImpl::set_regName() {
Register reg = ::as_Register(0);
int i;
for (i = 0; i < ConcreteRegisterImpl::max_gpr; reg = reg->successor()) {
- for (int j = 0; j < (1 << ConcreteRegisterImpl::log_vmregs_per_gpr); j++) {
+ for (int j = 0; j < Register::max_slots_per_register; j++) {
regName[i++] = reg->name();
}
}
#ifndef __SOFTFP__
FloatRegister freg = ::as_FloatRegister(0);
for ( ; i < ConcreteRegisterImpl::max_fpr ; ) {
- for (int j = 0; j < (1 << ConcreteRegisterImpl::log_vmregs_per_fpr); j++) {
+ for (int j = 0; j < Register::max_slots_per_register; j++) {
regName[i++] = freg->name();
}
freg = freg->successor();
diff --git a/src/hotspot/cpu/arm/vmreg_arm.hpp b/src/hotspot/cpu/arm/vmreg_arm.hpp
index c13f443b804f..f1dfd09a1e69 100644
--- a/src/hotspot/cpu/arm/vmreg_arm.hpp
+++ b/src/hotspot/cpu/arm/vmreg_arm.hpp
@@ -36,20 +36,20 @@
inline Register as_Register() {
assert(is_Register(), "must be");
assert(is_concrete(), "concrete register expected");
- return ::as_Register(value() >> ConcreteRegisterImpl::log_vmregs_per_gpr);
+ return ::as_Register(value() / Register::max_slots_per_register);
}
inline FloatRegister as_FloatRegister() {
assert(is_FloatRegister(), "must be");
assert(is_concrete(), "concrete register expected");
- return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) >> ConcreteRegisterImpl::log_vmregs_per_fpr);
+ return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) / FloatRegister::max_slots_per_register);
}
inline bool is_concrete() {
if (is_Register()) {
- return ((value() & right_n_bits(ConcreteRegisterImpl::log_vmregs_per_gpr)) == 0);
+ return (value() % Register::max_slots_per_register == 0);
} else if (is_FloatRegister()) {
- return (((value() - ConcreteRegisterImpl::max_gpr) & right_n_bits(ConcreteRegisterImpl::log_vmregs_per_fpr)) == 0);
+ return (value() % FloatRegister::max_slots_per_register == 0); // Single slot
} else {
return false;
}
diff --git a/src/hotspot/cpu/arm/vmreg_arm.inline.hpp b/src/hotspot/cpu/arm/vmreg_arm.inline.hpp
index f122b9ede701..3e5c18dbda0a 100644
--- a/src/hotspot/cpu/arm/vmreg_arm.inline.hpp
+++ b/src/hotspot/cpu/arm/vmreg_arm.inline.hpp
@@ -25,11 +25,11 @@
#ifndef CPU_ARM_VMREG_ARM_INLINE_HPP
#define CPU_ARM_VMREG_ARM_INLINE_HPP
-inline VMReg RegisterImpl::as_VMReg() {
- return VMRegImpl::as_VMReg(encoding() << ConcreteRegisterImpl::log_vmregs_per_gpr);
+inline VMReg Register::RegisterImpl::as_VMReg() const {
+ return VMRegImpl::as_VMReg(encoding() * Register::max_slots_per_register);
}
-inline VMReg FloatRegisterImpl::as_VMReg() {
- return VMRegImpl::as_VMReg((encoding() << ConcreteRegisterImpl::log_vmregs_per_fpr) + ConcreteRegisterImpl::max_gpr);
+inline VMReg FloatRegister::FloatRegisterImpl::as_VMReg() const {
+ return VMRegImpl::as_VMReg((encoding() * FloatRegister::max_slots_per_register) + ConcreteRegisterImpl::max_gpr);
}
#endif // CPU_ARM_VMREG_ARM_INLINE_HPP
diff --git a/src/hotspot/cpu/ppc/assembler_ppc.hpp b/src/hotspot/cpu/ppc/assembler_ppc.hpp
index 314517fd56a7..3c444207b114 100644
--- a/src/hotspot/cpu/ppc/assembler_ppc.hpp
+++ b/src/hotspot/cpu/ppc/assembler_ppc.hpp
@@ -1573,10 +1573,6 @@ class Assembler : public AbstractAssembler {
static bool is_nop(int x) {
return x == 0x60000000;
}
- // endgroup opcode for Power6
- static bool is_endgroup(int x) {
- return is_ori(x) && inv_ra_field(x) == 1 && inv_rs_field(x) == 1 && inv_d1_field(x) == 0;
- }
private:
@@ -1652,9 +1648,6 @@ class Assembler : public AbstractAssembler {
inline void ori_opt( Register d, int ui16);
inline void oris_opt(Register d, int ui16);
- // endgroup opcode for Power6
- inline void endgroup();
-
// count instructions
inline void cntlzw( Register a, Register s);
inline void cntlzw_( Register a, Register s);
diff --git a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp
index 792e5d6d5ad2..482d01bdab2c 100644
--- a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp
+++ b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp
@@ -253,8 +253,6 @@ inline void Assembler::mr( Register d, Register s) { Assembler::orr(d, s,
inline void Assembler::ori_opt( Register d, int ui16) { if (ui16!=0) Assembler::ori( d, d, ui16); }
inline void Assembler::oris_opt(Register d, int ui16) { if (ui16!=0) Assembler::oris(d, d, ui16); }
-inline void Assembler::endgroup() { Assembler::ori(R1, R1, 0); }
-
// count instructions
inline void Assembler::cntlzw( Register a, Register s) { emit_int32(CNTLZW_OPCODE | rta(a) | rs(s) | rc(0)); }
inline void Assembler::cntlzw_( Register a, Register s) { emit_int32(CNTLZW_OPCODE | rta(a) | rs(s) | rc(1)); }
diff --git a/src/hotspot/cpu/ppc/disassembler_ppc.cpp b/src/hotspot/cpu/ppc/disassembler_ppc.cpp
index fb3cb50cdeca..2e16e1a301f5 100644
--- a/src/hotspot/cpu/ppc/disassembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/disassembler_ppc.cpp
@@ -119,9 +119,6 @@ address Disassembler::decode_instruction0(address here, outputStream * st, addre
} else if (instruction == 0xbadbabe) {
st->print(".data 0xbadbabe");
next = here + Assembler::instr_len(here);
- } else if (Assembler::is_endgroup(instruction)) {
- st->print("endgroup");
- next = here + Assembler::instr_len(here);
} else {
next = here;
}
diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp
index 32a7011ac261..405ac4b2310e 100644
--- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp
@@ -333,9 +333,9 @@ int SaveLiveRegisters::iterate_over_register_mask(IterationAction action, int of
}
} else if (vm_reg->is_ConditionRegister()) {
// NOP. Conditions registers are covered by save_LR_CR
- } else if (vm_reg->is_VectorSRegister()) {
+ } else if (vm_reg->is_VectorRegister()) {
assert(SuperwordUseVSX, "or should not reach here");
- VectorSRegister vs_reg = vm_reg->as_VectorSRegister();
+ VectorSRegister vs_reg = (vm_reg->as_VectorRegister()).to_vsr();
if (vs_reg->encoding() >= VSR32->encoding() && vs_reg->encoding() <= VSR51->encoding()) {
reg_save_index += (2 + (reg_save_index & 1)); // 2 slots + alignment if needed
diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
index 396a50427f85..1bd74ca03d6c 100644
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
@@ -482,7 +482,7 @@ void MacroAssembler::set_dest_of_bc_far_at(address instruction_addr, address des
// variant 3, far cond branch to the next instruction, already patched to nops:
//
// nop
- // endgroup
+ // nop
// SKIP/DEST:
//
return;
@@ -499,7 +499,7 @@ void MacroAssembler::set_dest_of_bc_far_at(address instruction_addr, address des
if (is_bc_far_variant2_at(instruction_addr) && dest == instruction_addr + 8) {
// Far branch to next instruction: Optimize it by patching nops (produce variant 3).
masm.nop();
- masm.endgroup();
+ masm.nop();
} else {
if (is_bc_far_variant1_at(instruction_addr)) {
// variant 1, the 1st instruction contains the destination address:
@@ -3436,23 +3436,19 @@ void MacroAssembler::store_klass_gap(Register dst_oop, Register val) {
}
}
-int MacroAssembler::instr_size_for_decode_klass_not_null() {
+int MacroAssembler::instr_size_for_load_klass() {
static int computed_size = -1;
// Not yet computed?
if (computed_size == -1) {
- if (!UseCompressedClassPointers) {
- computed_size = 0;
- } else {
- // Determine by scratch emit.
- ResourceMark rm;
- int code_size = 8 * BytesPerInstWord;
- CodeBuffer cb("decode_klass_not_null scratch buffer", code_size, 0);
- MacroAssembler* a = new MacroAssembler(&cb);
- a->decode_klass_not_null(R11_scratch1);
- computed_size = a->offset();
- }
+ // Determine by scratch emit.
+ ResourceMark rm;
+ int code_size = 16 * BytesPerInstWord;
+ CodeBuffer cb("load_klass scratch buffer", code_size, 0);
+ MacroAssembler* a = new MacroAssembler(&cb);
+ a->load_klass(R11_scratch1, R11_scratch1);
+ computed_size = a->offset();
}
return computed_size;
@@ -4752,7 +4748,7 @@ void MacroAssembler::push_cont_fastpath() {
Label done;
ld_ptr(R0, JavaThread::cont_fastpath_offset(), R16_thread);
cmpld(CR0, R1_SP, R0);
- ble(CR0, done);
+ ble(CR0, done); // if (SP <= _cont_fastpath) goto done;
st_ptr(R1_SP, JavaThread::cont_fastpath_offset(), R16_thread);
bind(done);
}
@@ -4763,7 +4759,7 @@ void MacroAssembler::pop_cont_fastpath() {
Label done;
ld_ptr(R0, JavaThread::cont_fastpath_offset(), R16_thread);
cmpld(CR0, R1_SP, R0);
- ble(CR0, done);
+ blt(CR0, done); // if (SP < _cont_fastpath) goto done;
li(R0, 0);
st_ptr(R0, JavaThread::cont_fastpath_offset(), R16_thread);
bind(done);
diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
index 471ebb7459a1..ab7bb653d113 100644
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
@@ -70,14 +70,6 @@ class MacroAssembler: public Assembler {
// Move register if destination register and target register are different
inline void mr_if_needed(Register rd, Register rs);
inline void fmr_if_needed(FloatRegister rd, FloatRegister rs);
- // This is dedicated for emitting scheduled mach nodes. For better
- // readability of the ad file I put it here.
- // Endgroups are not needed if
- // - the scheduler is off
- // - the scheduler found that there is a natural group end, in that
- // case it reduced the size of the instruction used in the test
- // yielding 'needed'.
- inline void endgroup_if_needed(bool needed);
// Memory barriers.
inline void membar(int bits);
@@ -818,7 +810,7 @@ class MacroAssembler: public Assembler {
MacroAssembler::PreservationLevel preservation_level);
void load_method_holder(Register holder, Register method);
- static int instr_size_for_decode_klass_not_null();
+ static int instr_size_for_load_klass();
void decode_klass_not_null(Register dst, Register src = noreg);
Register encode_klass_not_null(Register dst, Register src = noreg);
diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp
index d27011112e2b..6212958b819d 100644
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2025 SAP SE. All rights reserved.
+ * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2026 SAP SE. 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
@@ -71,11 +71,6 @@ inline void MacroAssembler::mr_if_needed(Register rd, Register rs) {
inline void MacroAssembler::fmr_if_needed(FloatRegister rd, FloatRegister rs) {
if (rs != rd) fmr(rd, rs);
}
-inline void MacroAssembler::endgroup_if_needed(bool needed) {
- if (needed) {
- endgroup();
- }
-}
inline void MacroAssembler::membar(int bits) {
// Comment: Usage of elemental_membar(bits) is not recommended for Power 8.
@@ -239,13 +234,13 @@ inline bool MacroAssembler::is_bc_far_variant3_at(address instruction_addr) {
// Variant 3, far cond branch to the next instruction, already patched to nops:
//
// nop
- // endgroup
+ // nop
// SKIP/DEST:
//
const int instruction_1 = *(int*)(instruction_addr);
const int instruction_2 = *(int*)(instruction_addr + 4);
return is_nop(instruction_1) &&
- is_endgroup(instruction_2);
+ is_nop(instruction_2);
}
// set dst to -1, 0, +1 as follows: if CR0bi is "greater than", dst is set to 1,
diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad
index 18a99e5bc9af..b68632f0b377 100644
--- a/src/hotspot/cpu/ppc/ppc.ad
+++ b/src/hotspot/cpu/ppc/ppc.ad
@@ -255,329 +255,168 @@ register %{
reg_def SR_PPR( SOC, SOC, Op_RegP, 5, SR_PPR->as_VMReg()); // v
// ----------------------------
-// Vector-Scalar Registers
+// Vector Registers
// ----------------------------
- // 1st 32 VSRs are aliases for the FPRs which are already defined above.
- reg_def VSR0 (SOC, SOC, Op_RegF, 0, VMRegImpl::Bad());
- reg_def VSR0_H (SOC, SOC, Op_RegF, 0, VMRegImpl::Bad());
- reg_def VSR0_J (SOC, SOC, Op_RegF, 0, VMRegImpl::Bad());
- reg_def VSR0_K (SOC, SOC, Op_RegF, 0, VMRegImpl::Bad());
-
- reg_def VSR1 (SOC, SOC, Op_RegF, 1, VMRegImpl::Bad());
- reg_def VSR1_H (SOC, SOC, Op_RegF, 1, VMRegImpl::Bad());
- reg_def VSR1_J (SOC, SOC, Op_RegF, 1, VMRegImpl::Bad());
- reg_def VSR1_K (SOC, SOC, Op_RegF, 1, VMRegImpl::Bad());
-
- reg_def VSR2 (SOC, SOC, Op_RegF, 2, VMRegImpl::Bad());
- reg_def VSR2_H (SOC, SOC, Op_RegF, 2, VMRegImpl::Bad());
- reg_def VSR2_J (SOC, SOC, Op_RegF, 2, VMRegImpl::Bad());
- reg_def VSR2_K (SOC, SOC, Op_RegF, 2, VMRegImpl::Bad());
-
- reg_def VSR3 (SOC, SOC, Op_RegF, 3, VMRegImpl::Bad());
- reg_def VSR3_H (SOC, SOC, Op_RegF, 3, VMRegImpl::Bad());
- reg_def VSR3_J (SOC, SOC, Op_RegF, 3, VMRegImpl::Bad());
- reg_def VSR3_K (SOC, SOC, Op_RegF, 3, VMRegImpl::Bad());
-
- reg_def VSR4 (SOC, SOC, Op_RegF, 4, VMRegImpl::Bad());
- reg_def VSR4_H (SOC, SOC, Op_RegF, 4, VMRegImpl::Bad());
- reg_def VSR4_J (SOC, SOC, Op_RegF, 4, VMRegImpl::Bad());
- reg_def VSR4_K (SOC, SOC, Op_RegF, 4, VMRegImpl::Bad());
-
- reg_def VSR5 (SOC, SOC, Op_RegF, 5, VMRegImpl::Bad());
- reg_def VSR5_H (SOC, SOC, Op_RegF, 5, VMRegImpl::Bad());
- reg_def VSR5_J (SOC, SOC, Op_RegF, 5, VMRegImpl::Bad());
- reg_def VSR5_K (SOC, SOC, Op_RegF, 5, VMRegImpl::Bad());
-
- reg_def VSR6 (SOC, SOC, Op_RegF, 6, VMRegImpl::Bad());
- reg_def VSR6_H (SOC, SOC, Op_RegF, 6, VMRegImpl::Bad());
- reg_def VSR6_J (SOC, SOC, Op_RegF, 6, VMRegImpl::Bad());
- reg_def VSR6_K (SOC, SOC, Op_RegF, 6, VMRegImpl::Bad());
-
- reg_def VSR7 (SOC, SOC, Op_RegF, 7, VMRegImpl::Bad());
- reg_def VSR7_H (SOC, SOC, Op_RegF, 7, VMRegImpl::Bad());
- reg_def VSR7_J (SOC, SOC, Op_RegF, 7, VMRegImpl::Bad());
- reg_def VSR7_K (SOC, SOC, Op_RegF, 7, VMRegImpl::Bad());
-
- reg_def VSR8 (SOC, SOC, Op_RegF, 8, VMRegImpl::Bad());
- reg_def VSR8_H (SOC, SOC, Op_RegF, 8, VMRegImpl::Bad());
- reg_def VSR8_J (SOC, SOC, Op_RegF, 8, VMRegImpl::Bad());
- reg_def VSR8_K (SOC, SOC, Op_RegF, 8, VMRegImpl::Bad());
-
- reg_def VSR9 (SOC, SOC, Op_RegF, 9, VMRegImpl::Bad());
- reg_def VSR9_H (SOC, SOC, Op_RegF, 9, VMRegImpl::Bad());
- reg_def VSR9_J (SOC, SOC, Op_RegF, 9, VMRegImpl::Bad());
- reg_def VSR9_K (SOC, SOC, Op_RegF, 9, VMRegImpl::Bad());
-
- reg_def VSR10 (SOC, SOC, Op_RegF, 10, VMRegImpl::Bad());
- reg_def VSR10_H(SOC, SOC, Op_RegF, 10, VMRegImpl::Bad());
- reg_def VSR10_J(SOC, SOC, Op_RegF, 10, VMRegImpl::Bad());
- reg_def VSR10_K(SOC, SOC, Op_RegF, 10, VMRegImpl::Bad());
-
- reg_def VSR11 (SOC, SOC, Op_RegF, 11, VMRegImpl::Bad());
- reg_def VSR11_H(SOC, SOC, Op_RegF, 11, VMRegImpl::Bad());
- reg_def VSR11_J(SOC, SOC, Op_RegF, 11, VMRegImpl::Bad());
- reg_def VSR11_K(SOC, SOC, Op_RegF, 11, VMRegImpl::Bad());
-
- reg_def VSR12 (SOC, SOC, Op_RegF, 12, VMRegImpl::Bad());
- reg_def VSR12_H(SOC, SOC, Op_RegF, 12, VMRegImpl::Bad());
- reg_def VSR12_J(SOC, SOC, Op_RegF, 12, VMRegImpl::Bad());
- reg_def VSR12_K(SOC, SOC, Op_RegF, 12, VMRegImpl::Bad());
-
- reg_def VSR13 (SOC, SOC, Op_RegF, 13, VMRegImpl::Bad());
- reg_def VSR13_H(SOC, SOC, Op_RegF, 13, VMRegImpl::Bad());
- reg_def VSR13_J(SOC, SOC, Op_RegF, 13, VMRegImpl::Bad());
- reg_def VSR13_K(SOC, SOC, Op_RegF, 13, VMRegImpl::Bad());
-
- reg_def VSR14 (SOC, SOC, Op_RegF, 14, VMRegImpl::Bad());
- reg_def VSR14_H(SOC, SOC, Op_RegF, 14, VMRegImpl::Bad());
- reg_def VSR14_J(SOC, SOC, Op_RegF, 14, VMRegImpl::Bad());
- reg_def VSR14_K(SOC, SOC, Op_RegF, 14, VMRegImpl::Bad());
-
- reg_def VSR15 (SOC, SOC, Op_RegF, 15, VMRegImpl::Bad());
- reg_def VSR15_H(SOC, SOC, Op_RegF, 15, VMRegImpl::Bad());
- reg_def VSR15_J(SOC, SOC, Op_RegF, 15, VMRegImpl::Bad());
- reg_def VSR15_K(SOC, SOC, Op_RegF, 15, VMRegImpl::Bad());
-
- reg_def VSR16 (SOC, SOC, Op_RegF, 16, VMRegImpl::Bad());
- reg_def VSR16_H(SOC, SOC, Op_RegF, 16, VMRegImpl::Bad());
- reg_def VSR16_J(SOC, SOC, Op_RegF, 16, VMRegImpl::Bad());
- reg_def VSR16_K(SOC, SOC, Op_RegF, 16, VMRegImpl::Bad());
-
- reg_def VSR17 (SOC, SOC, Op_RegF, 17, VMRegImpl::Bad());
- reg_def VSR17_H(SOC, SOC, Op_RegF, 17, VMRegImpl::Bad());
- reg_def VSR17_J(SOC, SOC, Op_RegF, 17, VMRegImpl::Bad());
- reg_def VSR17_K(SOC, SOC, Op_RegF, 17, VMRegImpl::Bad());
-
- reg_def VSR18 (SOC, SOC, Op_RegF, 18, VMRegImpl::Bad());
- reg_def VSR18_H(SOC, SOC, Op_RegF, 18, VMRegImpl::Bad());
- reg_def VSR18_J(SOC, SOC, Op_RegF, 18, VMRegImpl::Bad());
- reg_def VSR18_K(SOC, SOC, Op_RegF, 18, VMRegImpl::Bad());
-
- reg_def VSR19 (SOC, SOC, Op_RegF, 19, VMRegImpl::Bad());
- reg_def VSR19_H(SOC, SOC, Op_RegF, 19, VMRegImpl::Bad());
- reg_def VSR19_J(SOC, SOC, Op_RegF, 19, VMRegImpl::Bad());
- reg_def VSR19_K(SOC, SOC, Op_RegF, 19, VMRegImpl::Bad());
-
- reg_def VSR20 (SOC, SOC, Op_RegF, 20, VMRegImpl::Bad());
- reg_def VSR20_H(SOC, SOC, Op_RegF, 20, VMRegImpl::Bad());
- reg_def VSR20_J(SOC, SOC, Op_RegF, 20, VMRegImpl::Bad());
- reg_def VSR20_K(SOC, SOC, Op_RegF, 20, VMRegImpl::Bad());
-
- reg_def VSR21 (SOC, SOC, Op_RegF, 21, VMRegImpl::Bad());
- reg_def VSR21_H(SOC, SOC, Op_RegF, 21, VMRegImpl::Bad());
- reg_def VSR21_J(SOC, SOC, Op_RegF, 21, VMRegImpl::Bad());
- reg_def VSR21_K(SOC, SOC, Op_RegF, 21, VMRegImpl::Bad());
-
- reg_def VSR22 (SOC, SOC, Op_RegF, 22, VMRegImpl::Bad());
- reg_def VSR22_H(SOC, SOC, Op_RegF, 22, VMRegImpl::Bad());
- reg_def VSR22_J(SOC, SOC, Op_RegF, 22, VMRegImpl::Bad());
- reg_def VSR22_K(SOC, SOC, Op_RegF, 22, VMRegImpl::Bad());
-
- reg_def VSR23 (SOC, SOC, Op_RegF, 23, VMRegImpl::Bad());
- reg_def VSR23_H(SOC, SOC, Op_RegF, 23, VMRegImpl::Bad());
- reg_def VSR23_J(SOC, SOC, Op_RegF, 23, VMRegImpl::Bad());
- reg_def VSR23_K(SOC, SOC, Op_RegF, 23, VMRegImpl::Bad());
-
- reg_def VSR24 (SOC, SOC, Op_RegF, 24, VMRegImpl::Bad());
- reg_def VSR24_H(SOC, SOC, Op_RegF, 24, VMRegImpl::Bad());
- reg_def VSR24_J(SOC, SOC, Op_RegF, 24, VMRegImpl::Bad());
- reg_def VSR24_K(SOC, SOC, Op_RegF, 24, VMRegImpl::Bad());
-
- reg_def VSR25 (SOC, SOC, Op_RegF, 25, VMRegImpl::Bad());
- reg_def VSR25_H(SOC, SOC, Op_RegF, 25, VMRegImpl::Bad());
- reg_def VSR25_J(SOC, SOC, Op_RegF, 25, VMRegImpl::Bad());
- reg_def VSR25_K(SOC, SOC, Op_RegF, 25, VMRegImpl::Bad());
-
- reg_def VSR26 (SOC, SOC, Op_RegF, 26, VMRegImpl::Bad());
- reg_def VSR26_H(SOC, SOC, Op_RegF, 26, VMRegImpl::Bad());
- reg_def VSR26_J(SOC, SOC, Op_RegF, 26, VMRegImpl::Bad());
- reg_def VSR26_K(SOC, SOC, Op_RegF, 26, VMRegImpl::Bad());
-
- reg_def VSR27 (SOC, SOC, Op_RegF, 27, VMRegImpl::Bad());
- reg_def VSR27_H(SOC, SOC, Op_RegF, 27, VMRegImpl::Bad());
- reg_def VSR27_J(SOC, SOC, Op_RegF, 27, VMRegImpl::Bad());
- reg_def VSR27_K(SOC, SOC, Op_RegF, 27, VMRegImpl::Bad());
-
- reg_def VSR28 (SOC, SOC, Op_RegF, 28, VMRegImpl::Bad());
- reg_def VSR28_H(SOC, SOC, Op_RegF, 28, VMRegImpl::Bad());
- reg_def VSR28_J(SOC, SOC, Op_RegF, 28, VMRegImpl::Bad());
- reg_def VSR28_K(SOC, SOC, Op_RegF, 28, VMRegImpl::Bad());
-
- reg_def VSR29 (SOC, SOC, Op_RegF, 29, VMRegImpl::Bad());
- reg_def VSR29_H(SOC, SOC, Op_RegF, 29, VMRegImpl::Bad());
- reg_def VSR29_J(SOC, SOC, Op_RegF, 29, VMRegImpl::Bad());
- reg_def VSR29_K(SOC, SOC, Op_RegF, 29, VMRegImpl::Bad());
-
- reg_def VSR30 (SOC, SOC, Op_RegF, 30, VMRegImpl::Bad());
- reg_def VSR30_H(SOC, SOC, Op_RegF, 30, VMRegImpl::Bad());
- reg_def VSR30_J(SOC, SOC, Op_RegF, 30, VMRegImpl::Bad());
- reg_def VSR30_K(SOC, SOC, Op_RegF, 30, VMRegImpl::Bad());
-
- reg_def VSR31 (SOC, SOC, Op_RegF, 31, VMRegImpl::Bad());
- reg_def VSR31_H(SOC, SOC, Op_RegF, 31, VMRegImpl::Bad());
- reg_def VSR31_J(SOC, SOC, Op_RegF, 31, VMRegImpl::Bad());
- reg_def VSR31_K(SOC, SOC, Op_RegF, 31, VMRegImpl::Bad());
-
- // 2nd 32 VSRs are aliases for the VRs which are only defined here.
- reg_def VSR32 (SOC, SOC, Op_RegF, 32, VSR32->as_VMReg() );
- reg_def VSR32_H(SOC, SOC, Op_RegF, 32, VSR32->as_VMReg()->next() );
- reg_def VSR32_J(SOC, SOC, Op_RegF, 32, VSR32->as_VMReg()->next(2));
- reg_def VSR32_K(SOC, SOC, Op_RegF, 32, VSR32->as_VMReg()->next(3));
-
- reg_def VSR33 (SOC, SOC, Op_RegF, 33, VSR33->as_VMReg() );
- reg_def VSR33_H(SOC, SOC, Op_RegF, 33, VSR33->as_VMReg()->next() );
- reg_def VSR33_J(SOC, SOC, Op_RegF, 33, VSR33->as_VMReg()->next(2));
- reg_def VSR33_K(SOC, SOC, Op_RegF, 33, VSR33->as_VMReg()->next(3));
-
- reg_def VSR34 (SOC, SOC, Op_RegF, 34, VSR34->as_VMReg() );
- reg_def VSR34_H(SOC, SOC, Op_RegF, 34, VSR34->as_VMReg()->next() );
- reg_def VSR34_J(SOC, SOC, Op_RegF, 34, VSR34->as_VMReg()->next(2));
- reg_def VSR34_K(SOC, SOC, Op_RegF, 34, VSR34->as_VMReg()->next(3));
-
- reg_def VSR35 (SOC, SOC, Op_RegF, 35, VSR35->as_VMReg() );
- reg_def VSR35_H(SOC, SOC, Op_RegF, 35, VSR35->as_VMReg()->next() );
- reg_def VSR35_J(SOC, SOC, Op_RegF, 35, VSR35->as_VMReg()->next(2));
- reg_def VSR35_K(SOC, SOC, Op_RegF, 35, VSR35->as_VMReg()->next(3));
-
- reg_def VSR36 (SOC, SOC, Op_RegF, 36, VSR36->as_VMReg() );
- reg_def VSR36_H(SOC, SOC, Op_RegF, 36, VSR36->as_VMReg()->next() );
- reg_def VSR36_J(SOC, SOC, Op_RegF, 36, VSR36->as_VMReg()->next(2));
- reg_def VSR36_K(SOC, SOC, Op_RegF, 36, VSR36->as_VMReg()->next(3));
-
- reg_def VSR37 (SOC, SOC, Op_RegF, 37, VSR37->as_VMReg() );
- reg_def VSR37_H(SOC, SOC, Op_RegF, 37, VSR37->as_VMReg()->next() );
- reg_def VSR37_J(SOC, SOC, Op_RegF, 37, VSR37->as_VMReg()->next(2));
- reg_def VSR37_K(SOC, SOC, Op_RegF, 37, VSR37->as_VMReg()->next(3));
-
- reg_def VSR38 (SOC, SOC, Op_RegF, 38, VSR38->as_VMReg() );
- reg_def VSR38_H(SOC, SOC, Op_RegF, 38, VSR38->as_VMReg()->next() );
- reg_def VSR38_J(SOC, SOC, Op_RegF, 38, VSR38->as_VMReg()->next(2));
- reg_def VSR38_K(SOC, SOC, Op_RegF, 38, VSR38->as_VMReg()->next(3));
-
- reg_def VSR39 (SOC, SOC, Op_RegF, 39, VSR39->as_VMReg() );
- reg_def VSR39_H(SOC, SOC, Op_RegF, 39, VSR39->as_VMReg()->next() );
- reg_def VSR39_J(SOC, SOC, Op_RegF, 39, VSR39->as_VMReg()->next(2));
- reg_def VSR39_K(SOC, SOC, Op_RegF, 39, VSR39->as_VMReg()->next(3));
-
- reg_def VSR40 (SOC, SOC, Op_RegF, 40, VSR40->as_VMReg() );
- reg_def VSR40_H(SOC, SOC, Op_RegF, 40, VSR40->as_VMReg()->next() );
- reg_def VSR40_J(SOC, SOC, Op_RegF, 40, VSR40->as_VMReg()->next(2));
- reg_def VSR40_K(SOC, SOC, Op_RegF, 40, VSR40->as_VMReg()->next(3));
-
- reg_def VSR41 (SOC, SOC, Op_RegF, 41, VSR41->as_VMReg() );
- reg_def VSR41_H(SOC, SOC, Op_RegF, 41, VSR41->as_VMReg()->next() );
- reg_def VSR41_J(SOC, SOC, Op_RegF, 41, VSR41->as_VMReg()->next(2));
- reg_def VSR41_K(SOC, SOC, Op_RegF, 41, VSR41->as_VMReg()->next(3));
-
- reg_def VSR42 (SOC, SOC, Op_RegF, 42, VSR42->as_VMReg() );
- reg_def VSR42_H(SOC, SOC, Op_RegF, 42, VSR42->as_VMReg()->next() );
- reg_def VSR42_J(SOC, SOC, Op_RegF, 42, VSR42->as_VMReg()->next(2));
- reg_def VSR42_K(SOC, SOC, Op_RegF, 42, VSR42->as_VMReg()->next(3));
-
- reg_def VSR43 (SOC, SOC, Op_RegF, 43, VSR43->as_VMReg() );
- reg_def VSR43_H(SOC, SOC, Op_RegF, 43, VSR43->as_VMReg()->next() );
- reg_def VSR43_J(SOC, SOC, Op_RegF, 43, VSR43->as_VMReg()->next(2));
- reg_def VSR43_K(SOC, SOC, Op_RegF, 43, VSR43->as_VMReg()->next(3));
-
- reg_def VSR44 (SOC, SOC, Op_RegF, 44, VSR44->as_VMReg() );
- reg_def VSR44_H(SOC, SOC, Op_RegF, 44, VSR44->as_VMReg()->next() );
- reg_def VSR44_J(SOC, SOC, Op_RegF, 44, VSR44->as_VMReg()->next(2));
- reg_def VSR44_K(SOC, SOC, Op_RegF, 44, VSR44->as_VMReg()->next(3));
-
- reg_def VSR45 (SOC, SOC, Op_RegF, 45, VSR45->as_VMReg() );
- reg_def VSR45_H(SOC, SOC, Op_RegF, 45, VSR45->as_VMReg()->next() );
- reg_def VSR45_J(SOC, SOC, Op_RegF, 45, VSR45->as_VMReg()->next(2));
- reg_def VSR45_K(SOC, SOC, Op_RegF, 45, VSR45->as_VMReg()->next(3));
-
- reg_def VSR46 (SOC, SOC, Op_RegF, 46, VSR46->as_VMReg() );
- reg_def VSR46_H(SOC, SOC, Op_RegF, 46, VSR46->as_VMReg()->next() );
- reg_def VSR46_J(SOC, SOC, Op_RegF, 46, VSR46->as_VMReg()->next(2));
- reg_def VSR46_K(SOC, SOC, Op_RegF, 46, VSR46->as_VMReg()->next(3));
-
- reg_def VSR47 (SOC, SOC, Op_RegF, 47, VSR47->as_VMReg() );
- reg_def VSR47_H(SOC, SOC, Op_RegF, 47, VSR47->as_VMReg()->next() );
- reg_def VSR47_J(SOC, SOC, Op_RegF, 47, VSR47->as_VMReg()->next(2));
- reg_def VSR47_K(SOC, SOC, Op_RegF, 47, VSR47->as_VMReg()->next(3));
-
- reg_def VSR48 (SOC, SOC, Op_RegF, 48, VSR48->as_VMReg() );
- reg_def VSR48_H(SOC, SOC, Op_RegF, 48, VSR48->as_VMReg()->next() );
- reg_def VSR48_J(SOC, SOC, Op_RegF, 48, VSR48->as_VMReg()->next(2));
- reg_def VSR48_K(SOC, SOC, Op_RegF, 48, VSR48->as_VMReg()->next(3));
-
- reg_def VSR49 (SOC, SOC, Op_RegF, 49, VSR49->as_VMReg() );
- reg_def VSR49_H(SOC, SOC, Op_RegF, 49, VSR49->as_VMReg()->next() );
- reg_def VSR49_J(SOC, SOC, Op_RegF, 49, VSR49->as_VMReg()->next(2));
- reg_def VSR49_K(SOC, SOC, Op_RegF, 49, VSR49->as_VMReg()->next(3));
-
- reg_def VSR50 (SOC, SOC, Op_RegF, 50, VSR50->as_VMReg() );
- reg_def VSR50_H(SOC, SOC, Op_RegF, 50, VSR50->as_VMReg()->next() );
- reg_def VSR50_J(SOC, SOC, Op_RegF, 50, VSR50->as_VMReg()->next(2));
- reg_def VSR50_K(SOC, SOC, Op_RegF, 50, VSR50->as_VMReg()->next(3));
-
- reg_def VSR51 (SOC, SOC, Op_RegF, 51, VSR51->as_VMReg() );
- reg_def VSR51_H(SOC, SOC, Op_RegF, 51, VSR51->as_VMReg()->next() );
- reg_def VSR51_J(SOC, SOC, Op_RegF, 51, VSR51->as_VMReg()->next(2));
- reg_def VSR51_K(SOC, SOC, Op_RegF, 51, VSR51->as_VMReg()->next(3));
-
- reg_def VSR52 (SOC, SOE, Op_RegF, 52, VSR52->as_VMReg() );
- reg_def VSR52_H(SOC, SOE, Op_RegF, 52, VSR52->as_VMReg()->next() );
- reg_def VSR52_J(SOC, SOE, Op_RegF, 52, VSR52->as_VMReg()->next(2));
- reg_def VSR52_K(SOC, SOE, Op_RegF, 52, VSR52->as_VMReg()->next(3));
-
- reg_def VSR53 (SOC, SOE, Op_RegF, 53, VSR53->as_VMReg() );
- reg_def VSR53_H(SOC, SOE, Op_RegF, 53, VSR53->as_VMReg()->next() );
- reg_def VSR53_J(SOC, SOE, Op_RegF, 53, VSR53->as_VMReg()->next(2));
- reg_def VSR53_K(SOC, SOE, Op_RegF, 53, VSR53->as_VMReg()->next(3));
-
- reg_def VSR54 (SOC, SOE, Op_RegF, 54, VSR54->as_VMReg() );
- reg_def VSR54_H(SOC, SOE, Op_RegF, 54, VSR54->as_VMReg()->next() );
- reg_def VSR54_J(SOC, SOE, Op_RegF, 54, VSR54->as_VMReg()->next(2));
- reg_def VSR54_K(SOC, SOE, Op_RegF, 54, VSR54->as_VMReg()->next(3));
-
- reg_def VSR55 (SOC, SOE, Op_RegF, 55, VSR55->as_VMReg() );
- reg_def VSR55_H(SOC, SOE, Op_RegF, 55, VSR55->as_VMReg()->next() );
- reg_def VSR55_J(SOC, SOE, Op_RegF, 55, VSR55->as_VMReg()->next(2));
- reg_def VSR55_K(SOC, SOE, Op_RegF, 55, VSR55->as_VMReg()->next(3));
-
- reg_def VSR56 (SOC, SOE, Op_RegF, 56, VSR56->as_VMReg() );
- reg_def VSR56_H(SOC, SOE, Op_RegF, 56, VSR56->as_VMReg()->next() );
- reg_def VSR56_J(SOC, SOE, Op_RegF, 56, VSR56->as_VMReg()->next(2));
- reg_def VSR56_K(SOC, SOE, Op_RegF, 56, VSR56->as_VMReg()->next(3));
-
- reg_def VSR57 (SOC, SOE, Op_RegF, 57, VSR57->as_VMReg() );
- reg_def VSR57_H(SOC, SOE, Op_RegF, 57, VSR57->as_VMReg()->next() );
- reg_def VSR57_J(SOC, SOE, Op_RegF, 57, VSR57->as_VMReg()->next(2));
- reg_def VSR57_K(SOC, SOE, Op_RegF, 57, VSR57->as_VMReg()->next(3));
-
- reg_def VSR58 (SOC, SOE, Op_RegF, 58, VSR58->as_VMReg() );
- reg_def VSR58_H(SOC, SOE, Op_RegF, 58, VSR58->as_VMReg()->next() );
- reg_def VSR58_J(SOC, SOE, Op_RegF, 58, VSR58->as_VMReg()->next(2));
- reg_def VSR58_K(SOC, SOE, Op_RegF, 58, VSR58->as_VMReg()->next(3));
-
- reg_def VSR59 (SOC, SOE, Op_RegF, 59, VSR59->as_VMReg() );
- reg_def VSR59_H(SOC, SOE, Op_RegF, 59, VSR59->as_VMReg()->next() );
- reg_def VSR59_J(SOC, SOE, Op_RegF, 59, VSR59->as_VMReg()->next(2));
- reg_def VSR59_K(SOC, SOE, Op_RegF, 59, VSR59->as_VMReg()->next(3));
-
- reg_def VSR60 (SOC, SOE, Op_RegF, 60, VSR60->as_VMReg() );
- reg_def VSR60_H(SOC, SOE, Op_RegF, 60, VSR60->as_VMReg()->next() );
- reg_def VSR60_J(SOC, SOE, Op_RegF, 60, VSR60->as_VMReg()->next(2));
- reg_def VSR60_K(SOC, SOE, Op_RegF, 60, VSR60->as_VMReg()->next(3));
-
- reg_def VSR61 (SOC, SOE, Op_RegF, 61, VSR61->as_VMReg() );
- reg_def VSR61_H(SOC, SOE, Op_RegF, 61, VSR61->as_VMReg()->next() );
- reg_def VSR61_J(SOC, SOE, Op_RegF, 61, VSR61->as_VMReg()->next(2));
- reg_def VSR61_K(SOC, SOE, Op_RegF, 61, VSR61->as_VMReg()->next(3));
-
- reg_def VSR62 (SOC, SOE, Op_RegF, 62, VSR62->as_VMReg() );
- reg_def VSR62_H(SOC, SOE, Op_RegF, 62, VSR62->as_VMReg()->next() );
- reg_def VSR62_J(SOC, SOE, Op_RegF, 62, VSR62->as_VMReg()->next(2));
- reg_def VSR62_K(SOC, SOE, Op_RegF, 62, VSR62->as_VMReg()->next(3));
-
- reg_def VSR63 (SOC, SOE, Op_RegF, 63, VSR63->as_VMReg() );
- reg_def VSR63_H(SOC, SOE, Op_RegF, 63, VSR63->as_VMReg()->next() );
- reg_def VSR63_J(SOC, SOE, Op_RegF, 63, VSR63->as_VMReg()->next(2));
- reg_def VSR63_K(SOC, SOE, Op_RegF, 63, VSR63->as_VMReg()->next(3));
+
+ reg_def VR0 (SOC, SOC, Op_RegF, 0, VR0->as_VMReg() );
+ reg_def VR0_H(SOC, SOC, Op_RegF, 0, VR0->as_VMReg()->next() );
+ reg_def VR0_J(SOC, SOC, Op_RegF, 0, VR0->as_VMReg()->next(2));
+ reg_def VR0_K(SOC, SOC, Op_RegF, 0, VR0->as_VMReg()->next(3));
+
+ reg_def VR1 (SOC, SOC, Op_RegF, 1, VR1->as_VMReg() );
+ reg_def VR1_H(SOC, SOC, Op_RegF, 1, VR1->as_VMReg()->next() );
+ reg_def VR1_J(SOC, SOC, Op_RegF, 1, VR1->as_VMReg()->next(2));
+ reg_def VR1_K(SOC, SOC, Op_RegF, 1, VR1->as_VMReg()->next(3));
+
+ reg_def VR2 (SOC, SOC, Op_RegF, 2, VR2->as_VMReg() );
+ reg_def VR2_H(SOC, SOC, Op_RegF, 2, VR2->as_VMReg()->next() );
+ reg_def VR2_J(SOC, SOC, Op_RegF, 2, VR2->as_VMReg()->next(2));
+ reg_def VR2_K(SOC, SOC, Op_RegF, 2, VR2->as_VMReg()->next(3));
+
+ reg_def VR3 (SOC, SOC, Op_RegF, 3, VR3->as_VMReg() );
+ reg_def VR3_H(SOC, SOC, Op_RegF, 3, VR3->as_VMReg()->next() );
+ reg_def VR3_J(SOC, SOC, Op_RegF, 3, VR3->as_VMReg()->next(2));
+ reg_def VR3_K(SOC, SOC, Op_RegF, 3, VR3->as_VMReg()->next(3));
+
+ reg_def VR4 (SOC, SOC, Op_RegF, 4, VR4->as_VMReg() );
+ reg_def VR4_H(SOC, SOC, Op_RegF, 4, VR4->as_VMReg()->next() );
+ reg_def VR4_J(SOC, SOC, Op_RegF, 4, VR4->as_VMReg()->next(2));
+ reg_def VR4_K(SOC, SOC, Op_RegF, 4, VR4->as_VMReg()->next(3));
+
+ reg_def VR5 (SOC, SOC, Op_RegF, 5, VR5->as_VMReg() );
+ reg_def VR5_H(SOC, SOC, Op_RegF, 5, VR5->as_VMReg()->next() );
+ reg_def VR5_J(SOC, SOC, Op_RegF, 5, VR5->as_VMReg()->next(2));
+ reg_def VR5_K(SOC, SOC, Op_RegF, 5, VR5->as_VMReg()->next(3));
+
+ reg_def VR6 (SOC, SOC, Op_RegF, 6, VR6->as_VMReg() );
+ reg_def VR6_H(SOC, SOC, Op_RegF, 6, VR6->as_VMReg()->next() );
+ reg_def VR6_J(SOC, SOC, Op_RegF, 6, VR6->as_VMReg()->next(2));
+ reg_def VR6_K(SOC, SOC, Op_RegF, 6, VR6->as_VMReg()->next(3));
+
+ reg_def VR7 (SOC, SOC, Op_RegF, 7, VR7->as_VMReg() );
+ reg_def VR7_H(SOC, SOC, Op_RegF, 7, VR7->as_VMReg()->next() );
+ reg_def VR7_J(SOC, SOC, Op_RegF, 7, VR7->as_VMReg()->next(2));
+ reg_def VR7_K(SOC, SOC, Op_RegF, 7, VR7->as_VMReg()->next(3));
+
+ reg_def VR8 (SOC, SOC, Op_RegF, 8, VR8->as_VMReg() );
+ reg_def VR8_H(SOC, SOC, Op_RegF, 8, VR8->as_VMReg()->next() );
+ reg_def VR8_J(SOC, SOC, Op_RegF, 8, VR8->as_VMReg()->next(2));
+ reg_def VR8_K(SOC, SOC, Op_RegF, 8, VR8->as_VMReg()->next(3));
+
+ reg_def VR9 (SOC, SOC, Op_RegF, 9, VR9->as_VMReg() );
+ reg_def VR9_H(SOC, SOC, Op_RegF, 9, VR9->as_VMReg()->next() );
+ reg_def VR9_J(SOC, SOC, Op_RegF, 9, VR9->as_VMReg()->next(2));
+ reg_def VR9_K(SOC, SOC, Op_RegF, 9, VR9->as_VMReg()->next(3));
+
+ reg_def VR10 (SOC, SOC, Op_RegF, 10, VR10->as_VMReg() );
+ reg_def VR10_H(SOC, SOC, Op_RegF, 10, VR10->as_VMReg()->next() );
+ reg_def VR10_J(SOC, SOC, Op_RegF, 10, VR10->as_VMReg()->next(2));
+ reg_def VR10_K(SOC, SOC, Op_RegF, 10, VR10->as_VMReg()->next(3));
+
+ reg_def VR11 (SOC, SOC, Op_RegF, 11, VR11->as_VMReg() );
+ reg_def VR11_H(SOC, SOC, Op_RegF, 11, VR11->as_VMReg()->next() );
+ reg_def VR11_J(SOC, SOC, Op_RegF, 11, VR11->as_VMReg()->next(2));
+ reg_def VR11_K(SOC, SOC, Op_RegF, 11, VR11->as_VMReg()->next(3));
+
+ reg_def VR12 (SOC, SOC, Op_RegF, 12, VR12->as_VMReg() );
+ reg_def VR12_H(SOC, SOC, Op_RegF, 12, VR12->as_VMReg()->next() );
+ reg_def VR12_J(SOC, SOC, Op_RegF, 12, VR12->as_VMReg()->next(2));
+ reg_def VR12_K(SOC, SOC, Op_RegF, 12, VR12->as_VMReg()->next(3));
+
+ reg_def VR13 (SOC, SOC, Op_RegF, 13, VR13->as_VMReg() );
+ reg_def VR13_H(SOC, SOC, Op_RegF, 13, VR13->as_VMReg()->next() );
+ reg_def VR13_J(SOC, SOC, Op_RegF, 13, VR13->as_VMReg()->next(2));
+ reg_def VR13_K(SOC, SOC, Op_RegF, 13, VR13->as_VMReg()->next(3));
+
+ reg_def VR14 (SOC, SOC, Op_RegF, 14, VR14->as_VMReg() );
+ reg_def VR14_H(SOC, SOC, Op_RegF, 14, VR14->as_VMReg()->next() );
+ reg_def VR14_J(SOC, SOC, Op_RegF, 14, VR14->as_VMReg()->next(2));
+ reg_def VR14_K(SOC, SOC, Op_RegF, 14, VR14->as_VMReg()->next(3));
+
+ reg_def VR15 (SOC, SOC, Op_RegF, 15, VR15->as_VMReg() );
+ reg_def VR15_H(SOC, SOC, Op_RegF, 15, VR15->as_VMReg()->next() );
+ reg_def VR15_J(SOC, SOC, Op_RegF, 15, VR15->as_VMReg()->next(2));
+ reg_def VR15_K(SOC, SOC, Op_RegF, 15, VR15->as_VMReg()->next(3));
+
+ reg_def VR16 (SOC, SOC, Op_RegF, 16, VR16->as_VMReg() );
+ reg_def VR16_H(SOC, SOC, Op_RegF, 16, VR16->as_VMReg()->next() );
+ reg_def VR16_J(SOC, SOC, Op_RegF, 16, VR16->as_VMReg()->next(2));
+ reg_def VR16_K(SOC, SOC, Op_RegF, 16, VR16->as_VMReg()->next(3));
+
+ reg_def VR17 (SOC, SOC, Op_RegF, 17, VR17->as_VMReg() );
+ reg_def VR17_H(SOC, SOC, Op_RegF, 17, VR17->as_VMReg()->next() );
+ reg_def VR17_J(SOC, SOC, Op_RegF, 17, VR17->as_VMReg()->next(2));
+ reg_def VR17_K(SOC, SOC, Op_RegF, 17, VR17->as_VMReg()->next(3));
+
+ reg_def VR18 (SOC, SOC, Op_RegF, 18, VR18->as_VMReg() );
+ reg_def VR18_H(SOC, SOC, Op_RegF, 18, VR18->as_VMReg()->next() );
+ reg_def VR18_J(SOC, SOC, Op_RegF, 18, VR18->as_VMReg()->next(2));
+ reg_def VR18_K(SOC, SOC, Op_RegF, 18, VR18->as_VMReg()->next(3));
+
+ reg_def VR19 (SOC, SOC, Op_RegF, 19, VR19->as_VMReg() );
+ reg_def VR19_H(SOC, SOC, Op_RegF, 19, VR19->as_VMReg()->next() );
+ reg_def VR19_J(SOC, SOC, Op_RegF, 19, VR19->as_VMReg()->next(2));
+ reg_def VR19_K(SOC, SOC, Op_RegF, 19, VR19->as_VMReg()->next(3));
+
+ reg_def VR20 (SOC, SOE, Op_RegF, 20, VR20->as_VMReg() );
+ reg_def VR20_H(SOC, SOE, Op_RegF, 20, VR20->as_VMReg()->next() );
+ reg_def VR20_J(SOC, SOE, Op_RegF, 20, VR20->as_VMReg()->next(2));
+ reg_def VR20_K(SOC, SOE, Op_RegF, 20, VR20->as_VMReg()->next(3));
+
+ reg_def VR21 (SOC, SOE, Op_RegF, 21, VR21->as_VMReg() );
+ reg_def VR21_H(SOC, SOE, Op_RegF, 21, VR21->as_VMReg()->next() );
+ reg_def VR21_J(SOC, SOE, Op_RegF, 21, VR21->as_VMReg()->next(2));
+ reg_def VR21_K(SOC, SOE, Op_RegF, 21, VR21->as_VMReg()->next(3));
+
+ reg_def VR22 (SOC, SOE, Op_RegF, 22, VR22->as_VMReg() );
+ reg_def VR22_H(SOC, SOE, Op_RegF, 22, VR22->as_VMReg()->next() );
+ reg_def VR22_J(SOC, SOE, Op_RegF, 22, VR22->as_VMReg()->next(2));
+ reg_def VR22_K(SOC, SOE, Op_RegF, 22, VR22->as_VMReg()->next(3));
+
+ reg_def VR23 (SOC, SOE, Op_RegF, 23, VR23->as_VMReg() );
+ reg_def VR23_H(SOC, SOE, Op_RegF, 23, VR23->as_VMReg()->next() );
+ reg_def VR23_J(SOC, SOE, Op_RegF, 23, VR23->as_VMReg()->next(2));
+ reg_def VR23_K(SOC, SOE, Op_RegF, 23, VR23->as_VMReg()->next(3));
+
+ reg_def VR24 (SOC, SOE, Op_RegF, 24, VR24->as_VMReg() );
+ reg_def VR24_H(SOC, SOE, Op_RegF, 24, VR24->as_VMReg()->next() );
+ reg_def VR24_J(SOC, SOE, Op_RegF, 24, VR24->as_VMReg()->next(2));
+ reg_def VR24_K(SOC, SOE, Op_RegF, 24, VR24->as_VMReg()->next(3));
+
+ reg_def VR25 (SOC, SOE, Op_RegF, 25, VR25->as_VMReg() );
+ reg_def VR25_H(SOC, SOE, Op_RegF, 25, VR25->as_VMReg()->next() );
+ reg_def VR25_J(SOC, SOE, Op_RegF, 25, VR25->as_VMReg()->next(2));
+ reg_def VR25_K(SOC, SOE, Op_RegF, 25, VR25->as_VMReg()->next(3));
+
+ reg_def VR26 (SOC, SOE, Op_RegF, 26, VR26->as_VMReg() );
+ reg_def VR26_H(SOC, SOE, Op_RegF, 26, VR26->as_VMReg()->next() );
+ reg_def VR26_J(SOC, SOE, Op_RegF, 26, VR26->as_VMReg()->next(2));
+ reg_def VR26_K(SOC, SOE, Op_RegF, 26, VR26->as_VMReg()->next(3));
+
+ reg_def VR27 (SOC, SOE, Op_RegF, 27, VR27->as_VMReg() );
+ reg_def VR27_H(SOC, SOE, Op_RegF, 27, VR27->as_VMReg()->next() );
+ reg_def VR27_J(SOC, SOE, Op_RegF, 27, VR27->as_VMReg()->next(2));
+ reg_def VR27_K(SOC, SOE, Op_RegF, 27, VR27->as_VMReg()->next(3));
+
+ reg_def VR28 (SOC, SOE, Op_RegF, 28, VR28->as_VMReg() );
+ reg_def VR28_H(SOC, SOE, Op_RegF, 28, VR28->as_VMReg()->next() );
+ reg_def VR28_J(SOC, SOE, Op_RegF, 28, VR28->as_VMReg()->next(2));
+ reg_def VR28_K(SOC, SOE, Op_RegF, 28, VR28->as_VMReg()->next(3));
+
+ reg_def VR29 (SOC, SOE, Op_RegF, 29, VR29->as_VMReg() );
+ reg_def VR29_H(SOC, SOE, Op_RegF, 29, VR29->as_VMReg()->next() );
+ reg_def VR29_J(SOC, SOE, Op_RegF, 29, VR29->as_VMReg()->next(2));
+ reg_def VR29_K(SOC, SOE, Op_RegF, 29, VR29->as_VMReg()->next(3));
+
+ reg_def VR30 (SOC, SOE, Op_RegF, 30, VR30->as_VMReg() );
+ reg_def VR30_H(SOC, SOE, Op_RegF, 30, VR30->as_VMReg()->next() );
+ reg_def VR30_J(SOC, SOE, Op_RegF, 30, VR30->as_VMReg()->next(2));
+ reg_def VR30_K(SOC, SOE, Op_RegF, 30, VR30->as_VMReg()->next(3));
+
+ reg_def VR31 (SOC, SOE, Op_RegF, 31, VR31->as_VMReg() );
+ reg_def VR31_H(SOC, SOE, Op_RegF, 31, VR31->as_VMReg()->next() );
+ reg_def VR31_J(SOC, SOE, Op_RegF, 31, VR31->as_VMReg()->next(2));
+ reg_def VR31_K(SOC, SOE, Op_RegF, 31, VR31->as_VMReg()->next(3));
// ----------------------------
// Specify priority of register selection within phases of register
@@ -696,70 +535,38 @@ alloc_class chunk1 (
);
alloc_class chunk2 (
- VSR0 , VSR0_H , VSR0_J , VSR0_K ,
- VSR1 , VSR1_H , VSR1_J , VSR1_K ,
- VSR2 , VSR2_H , VSR2_J , VSR2_K ,
- VSR3 , VSR3_H , VSR3_J , VSR3_K ,
- VSR4 , VSR4_H , VSR4_J , VSR4_K ,
- VSR5 , VSR5_H , VSR5_J , VSR5_K ,
- VSR6 , VSR6_H , VSR6_J , VSR6_K ,
- VSR7 , VSR7_H , VSR7_J , VSR7_K ,
- VSR8 , VSR8_H , VSR8_J , VSR8_K ,
- VSR9 , VSR9_H , VSR9_J , VSR9_K ,
- VSR10, VSR10_H, VSR10_J, VSR10_K,
- VSR11, VSR11_H, VSR11_J, VSR11_K,
- VSR12, VSR12_H, VSR12_J, VSR12_K,
- VSR13, VSR13_H, VSR13_J, VSR13_K,
- VSR14, VSR14_H, VSR14_J, VSR14_K,
- VSR15, VSR15_H, VSR15_J, VSR15_K,
- VSR16, VSR16_H, VSR16_J, VSR16_K,
- VSR17, VSR17_H, VSR17_J, VSR17_K,
- VSR18, VSR18_H, VSR18_J, VSR18_K,
- VSR19, VSR19_H, VSR19_J, VSR19_K,
- VSR20, VSR20_H, VSR20_J, VSR20_K,
- VSR21, VSR21_H, VSR21_J, VSR21_K,
- VSR22, VSR22_H, VSR22_J, VSR22_K,
- VSR23, VSR23_H, VSR23_J, VSR23_K,
- VSR24, VSR24_H, VSR24_J, VSR24_K,
- VSR25, VSR25_H, VSR25_J, VSR25_K,
- VSR26, VSR26_H, VSR26_J, VSR26_K,
- VSR27, VSR27_H, VSR27_J, VSR27_K,
- VSR28, VSR28_H, VSR28_J, VSR28_K,
- VSR29, VSR29_H, VSR29_J, VSR29_K,
- VSR30, VSR30_H, VSR30_J, VSR30_K,
- VSR31, VSR31_H, VSR31_J, VSR31_K,
- VSR32, VSR32_H, VSR32_J, VSR32_K,
- VSR33, VSR33_H, VSR33_J, VSR33_K,
- VSR34, VSR34_H, VSR34_J, VSR34_K,
- VSR35, VSR35_H, VSR35_J, VSR35_K,
- VSR36, VSR36_H, VSR36_J, VSR36_K,
- VSR37, VSR37_H, VSR37_J, VSR37_K,
- VSR38, VSR38_H, VSR38_J, VSR38_K,
- VSR39, VSR39_H, VSR39_J, VSR39_K,
- VSR40, VSR40_H, VSR40_J, VSR40_K,
- VSR41, VSR41_H, VSR41_J, VSR41_K,
- VSR42, VSR42_H, VSR42_J, VSR42_K,
- VSR43, VSR43_H, VSR43_J, VSR43_K,
- VSR44, VSR44_H, VSR44_J, VSR44_K,
- VSR45, VSR45_H, VSR45_J, VSR45_K,
- VSR46, VSR46_H, VSR46_J, VSR46_K,
- VSR47, VSR47_H, VSR47_J, VSR47_K,
- VSR48, VSR48_H, VSR48_J, VSR48_K,
- VSR49, VSR49_H, VSR49_J, VSR49_K,
- VSR50, VSR50_H, VSR50_J, VSR50_K,
- VSR51, VSR51_H, VSR51_J, VSR51_K,
- VSR52, VSR52_H, VSR52_J, VSR52_K,
- VSR53, VSR53_H, VSR53_J, VSR53_K,
- VSR54, VSR54_H, VSR54_J, VSR54_K,
- VSR55, VSR55_H, VSR55_J, VSR55_K,
- VSR56, VSR56_H, VSR56_J, VSR56_K,
- VSR57, VSR57_H, VSR57_J, VSR57_K,
- VSR58, VSR58_H, VSR58_J, VSR58_K,
- VSR59, VSR59_H, VSR59_J, VSR59_K,
- VSR60, VSR60_H, VSR60_J, VSR60_K,
- VSR61, VSR61_H, VSR61_J, VSR61_K,
- VSR62, VSR62_H, VSR62_J, VSR62_K,
- VSR63, VSR63_H, VSR63_J, VSR63_K
+ VR0 , VR0_H , VR0_J , VR0_K ,
+ VR1 , VR1_H , VR1_J , VR1_K ,
+ VR2 , VR2_H , VR2_J , VR2_K ,
+ VR3 , VR3_H , VR3_J , VR3_K ,
+ VR4 , VR4_H , VR4_J , VR4_K ,
+ VR5 , VR5_H , VR5_J , VR5_K ,
+ VR6 , VR6_H , VR6_J , VR6_K ,
+ VR7 , VR7_H , VR7_J , VR7_K ,
+ VR8 , VR8_H , VR8_J , VR8_K ,
+ VR9 , VR9_H , VR9_J , VR9_K ,
+ VR10, VR10_H, VR10_J, VR10_K,
+ VR11, VR11_H, VR11_J, VR11_K,
+ VR12, VR12_H, VR12_J, VR12_K,
+ VR13, VR13_H, VR13_J, VR13_K,
+ VR14, VR14_H, VR14_J, VR14_K,
+ VR15, VR15_H, VR15_J, VR15_K,
+ VR16, VR16_H, VR16_J, VR16_K,
+ VR17, VR17_H, VR17_J, VR17_K,
+ VR18, VR18_H, VR18_J, VR18_K,
+ VR19, VR19_H, VR19_J, VR19_K,
+ VR20, VR20_H, VR20_J, VR20_K,
+ VR21, VR21_H, VR21_J, VR21_K,
+ VR22, VR22_H, VR22_J, VR22_K,
+ VR23, VR23_H, VR23_J, VR23_K,
+ VR24, VR24_H, VR24_J, VR24_K,
+ VR25, VR25_H, VR25_J, VR25_K,
+ VR26, VR26_H, VR26_J, VR26_K,
+ VR27, VR27_H, VR27_J, VR27_K,
+ VR28, VR28_H, VR28_J, VR28_K,
+ VR29, VR29_H, VR29_J, VR29_K,
+ VR30, VR30_H, VR30_J, VR30_K,
+ VR31, VR31_H, VR31_J, VR31_K
);
alloc_class chunk3 (
@@ -1163,39 +970,39 @@ reg_class dbl_reg(
// Vector-Scalar Register Class
// ----------------------------
-reg_class vs_reg(
- VSR32, VSR32_H, VSR32_J, VSR32_K,
- VSR33, VSR33_H, VSR33_J, VSR33_K,
- VSR34, VSR34_H, VSR34_J, VSR34_K,
- VSR35, VSR35_H, VSR35_J, VSR35_K,
- VSR36, VSR36_H, VSR36_J, VSR36_K,
- VSR37, VSR37_H, VSR37_J, VSR37_K,
- VSR38, VSR38_H, VSR38_J, VSR38_K,
- VSR39, VSR39_H, VSR39_J, VSR39_K,
- VSR40, VSR40_H, VSR40_J, VSR40_K,
- VSR41, VSR41_H, VSR41_J, VSR41_K,
- VSR42, VSR42_H, VSR42_J, VSR42_K,
- VSR43, VSR43_H, VSR43_J, VSR43_K,
- VSR44, VSR44_H, VSR44_J, VSR44_K,
- VSR45, VSR45_H, VSR45_J, VSR45_K,
- VSR46, VSR46_H, VSR46_J, VSR46_K,
- VSR47, VSR47_H, VSR47_J, VSR47_K,
- VSR48, VSR48_H, VSR48_J, VSR48_K,
- VSR49, VSR49_H, VSR49_J, VSR49_K,
- VSR50, VSR50_H, VSR50_J, VSR50_K,
- VSR51, VSR51_H, VSR51_J, VSR51_K,
- VSR52, VSR52_H, VSR52_J, VSR52_K, // non-volatile
- VSR53, VSR53_H, VSR53_J, VSR53_K, // non-volatile
- VSR54, VSR54_H, VSR54_J, VSR54_K, // non-volatile
- VSR55, VSR55_H, VSR55_J, VSR55_K, // non-volatile
- VSR56, VSR56_H, VSR56_J, VSR56_K, // non-volatile
- VSR57, VSR57_H, VSR57_J, VSR57_K, // non-volatile
- VSR58, VSR58_H, VSR58_J, VSR58_K, // non-volatile
- VSR59, VSR59_H, VSR59_J, VSR59_K, // non-volatile
- VSR60, VSR60_H, VSR60_J, VSR60_K, // non-volatile
- VSR61, VSR61_H, VSR61_J, VSR61_K, // non-volatile
- VSR62, VSR62_H, VSR62_J, VSR62_K, // non-volatile
- VSR63, VSR63_H, VSR63_J, VSR63_K // non-volatile
+reg_class v_reg(
+ VR0 , VR0_H , VR0_J , VR0_K ,
+ VR1 , VR1_H , VR1_J , VR1_K ,
+ VR2 , VR2_H , VR2_J , VR2_K ,
+ VR3 , VR3_H , VR3_J , VR3_K ,
+ VR4 , VR4_H , VR4_J , VR4_K ,
+ VR5 , VR5_H , VR5_J , VR5_K ,
+ VR6 , VR6_H , VR6_J , VR6_K ,
+ VR7 , VR7_H , VR7_J , VR7_K ,
+ VR8 , VR8_H , VR8_J , VR8_K ,
+ VR9 , VR9_H , VR9_J , VR9_K ,
+ VR10, VR10_H, VR10_J, VR10_K,
+ VR11, VR11_H, VR11_J, VR11_K,
+ VR12, VR12_H, VR12_J, VR12_K,
+ VR13, VR13_H, VR13_J, VR13_K,
+ VR14, VR14_H, VR14_J, VR14_K,
+ VR15, VR15_H, VR15_J, VR15_K,
+ VR16, VR16_H, VR16_J, VR16_K,
+ VR17, VR17_H, VR17_J, VR17_K,
+ VR18, VR18_H, VR18_J, VR18_K,
+ VR19, VR19_H, VR19_J, VR19_K,
+ VR20, VR20_H, VR20_J, VR20_K,
+ VR21, VR21_H, VR21_J, VR21_K,
+ VR22, VR22_H, VR22_J, VR22_K,
+ VR23, VR23_H, VR23_J, VR23_K,
+ VR24, VR24_H, VR24_J, VR24_K,
+ VR25, VR25_H, VR25_J, VR25_K,
+ VR26, VR26_H, VR26_J, VR26_K,
+ VR27, VR27_H, VR27_J, VR27_K,
+ VR28, VR28_H, VR28_J, VR28_K,
+ VR29, VR29_H, VR29_J, VR29_K,
+ VR30, VR30_H, VR30_J, VR30_K,
+ VR31, VR31_H, VR31_J, VR31_K
);
%}
@@ -1380,7 +1187,7 @@ int MachCallDynamicJavaNode::ret_addr_offset() {
assert(vtable_index == Method::invalid_vtable_index, "correct sentinel value");
return 12;
} else {
- return 24 + MacroAssembler::instr_size_for_decode_klass_not_null();
+ return 20 + MacroAssembler::instr_size_for_load_klass();
}
}
@@ -1908,9 +1715,9 @@ const Pipeline * MachEpilogNode::pipeline() const {
// =============================================================================
-// Figure out which register class each belongs in: rc_int, rc_float, rc_vs or
+// Figure out which register class each belongs in: rc_int, rc_float, rc_vec or
// rc_stack.
-enum RC { rc_bad, rc_int, rc_float, rc_vs, rc_stack };
+enum RC { rc_bad, rc_int, rc_float, rc_vec, rc_stack };
static enum RC rc_class(OptoReg::Name reg) {
// Return the register class for the given register. The given register
@@ -1924,12 +1731,12 @@ static enum RC rc_class(OptoReg::Name reg) {
if (reg < ConcreteRegisterImpl::max_gpr) return rc_int;
// We have 64 floating-point register halves, starting at index 64.
- STATIC_ASSERT((int)ConcreteRegisterImpl::max_fpr == (int)MachRegisterNumbers::VSR0_num);
+ STATIC_ASSERT((int)ConcreteRegisterImpl::max_fpr == (int)MachRegisterNumbers::VR0_num);
if (reg < ConcreteRegisterImpl::max_fpr) return rc_float;
// We have 64 vector-scalar registers, starting at index 128.
- STATIC_ASSERT((int)ConcreteRegisterImpl::max_vsr == (int)MachRegisterNumbers::CR0_num);
- if (reg < ConcreteRegisterImpl::max_vsr) return rc_vs;
+ STATIC_ASSERT((int)ConcreteRegisterImpl::max_vr == (int)MachRegisterNumbers::CR0_num);
+ if (reg < ConcreteRegisterImpl::max_vr) return rc_vec;
// Condition and special purpose registers are not allocated. We only accept stack from here.
assert(OptoReg::is_stack(reg), "what else is it?");
@@ -2005,9 +1812,9 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r
}
size += 16;
}
- // VectorSRegister->Memory Spill.
- else if (src_lo_rc == rc_vs && dst_lo_rc == rc_stack) {
- VectorSRegister Rsrc = as_VectorSRegister(Matcher::_regEncode[src_lo]);
+ // VectorRegister->Memory Spill.
+ else if (src_lo_rc == rc_vec && dst_lo_rc == rc_stack) {
+ VectorSRegister Rsrc = as_VectorRegister(Matcher::_regEncode[src_lo]).to_vsr();
int dst_offset = ra_->reg2offset(dst_lo);
if (PowerArchitecturePPC64 >= 9) {
if (is_aligned(dst_offset, 16)) {
@@ -2032,9 +1839,9 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r
size += 8;
}
}
- // Memory->VectorSRegister Spill.
- else if (src_lo_rc == rc_stack && dst_lo_rc == rc_vs) {
- VectorSRegister Rdst = as_VectorSRegister(Matcher::_regEncode[dst_lo]);
+ // Memory->VectorRegister Spill.
+ else if (src_lo_rc == rc_stack && dst_lo_rc == rc_vec) {
+ VectorSRegister Rdst = as_VectorRegister(Matcher::_regEncode[dst_lo]).to_vsr();
int src_offset = ra_->reg2offset(src_lo);
if (PowerArchitecturePPC64 >= 9) {
if (is_aligned(src_offset, 16)) {
@@ -2057,17 +1864,17 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r
size += 8;
}
}
- // VectorSRegister->VectorSRegister.
- else if (src_lo_rc == rc_vs && dst_lo_rc == rc_vs) {
- VectorSRegister Rsrc = as_VectorSRegister(Matcher::_regEncode[src_lo]);
- VectorSRegister Rdst = as_VectorSRegister(Matcher::_regEncode[dst_lo]);
+ // VectorRegister->VectorRegister.
+ else if (src_lo_rc == rc_vec && dst_lo_rc == rc_vec) {
+ VectorSRegister Rsrc = as_VectorRegister(Matcher::_regEncode[src_lo]).to_vsr();
+ VectorSRegister Rdst = as_VectorRegister(Matcher::_regEncode[dst_lo]).to_vsr();
if (masm) {
__ xxlor(Rdst, Rsrc, Rsrc);
}
size += 4;
}
else {
- ShouldNotReachHere(); // No VSR spill.
+ ShouldNotReachHere(); // No VR spill.
}
return size;
}
@@ -4044,7 +3851,7 @@ ins_attrib ins_field_load_ic_node(0);
// Formats are generated automatically for constants and base registers.
operand vecX() %{
- constraint(ALLOC_IN_RC(vs_reg));
+ constraint(ALLOC_IN_RC(v_reg));
match(VecX);
format %{ %}
@@ -5620,7 +5427,7 @@ instruct loadV16_Power8(vecX dst, indirect mem) %{
format %{ "LXVD2X $dst, $mem \t// load 16-byte Vector" %}
size(4);
ins_encode %{
- __ lxvd2x($dst$$VectorSRegister, $mem$$Register);
+ __ lxvd2x($dst$$VectorRegister.to_vsr(), $mem$$Register);
%}
ins_pipe(pipe_class_default);
%}
@@ -5633,7 +5440,7 @@ instruct loadV16_Power9(vecX dst, memoryAlg16 mem) %{
format %{ "LXV $dst, $mem \t// load 16-byte Vector" %}
size(4);
ins_encode %{
- __ lxv($dst$$VectorSRegister, $mem$$disp, $mem$$Register);
+ __ lxv($dst$$VectorRegister.to_vsr(), $mem$$disp, $mem$$Register);
%}
ins_pipe(pipe_class_default);
%}
@@ -6660,7 +6467,7 @@ instruct storeV16_Power8(indirect mem, vecX src) %{
format %{ "STXVD2X $mem, $src \t// store 16-byte Vector" %}
size(4);
ins_encode %{
- __ stxvd2x($src$$VectorSRegister, $mem$$Register);
+ __ stxvd2x($src$$VectorRegister.to_vsr(), $mem$$Register);
%}
ins_pipe(pipe_class_default);
%}
@@ -6673,7 +6480,7 @@ instruct storeV16_Power9(memoryAlg16 mem, vecX src) %{
format %{ "STXV $mem, $src \t// store 16-byte Vector" %}
size(4);
ins_encode %{
- __ stxv($src$$VectorSRegister, $mem$$disp, $mem$$Register);
+ __ stxv($src$$VectorRegister.to_vsr(), $mem$$disp, $mem$$Register);
%}
ins_pipe(pipe_class_default);
%}
@@ -12658,9 +12465,9 @@ instruct bytes_reverse_int_vec(iRegIdst dst, iRegIsrc src, vecX tmpV) %{
"\tMFVSRWZ $dst, $tmpV" %}
ins_encode %{
- __ mtvsrwz($tmpV$$VectorSRegister, $src$$Register);
- __ xxbrw($tmpV$$VectorSRegister, $tmpV$$VectorSRegister);
- __ mfvsrwz($dst$$Register, $tmpV$$VectorSRegister);
+ __ mtvsrwz($tmpV$$VectorRegister.to_vsr(), $src$$Register);
+ __ xxbrw($tmpV$$VectorRegister.to_vsr(), $tmpV$$VectorRegister->to_vsr());
+ __ mfvsrwz($dst$$Register, $tmpV$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -12730,9 +12537,9 @@ instruct bytes_reverse_long_vec(iRegLdst dst, iRegLsrc src, vecX tmpV) %{
"\tMFVSRD $dst, $tmpV" %}
ins_encode %{
- __ mtvsrd($tmpV$$VectorSRegister, $src$$Register);
- __ xxbrd($tmpV$$VectorSRegister, $tmpV$$VectorSRegister);
- __ mfvsrd($dst$$Register, $tmpV$$VectorSRegister);
+ __ mtvsrd($tmpV$$VectorRegister->to_vsr(), $src$$Register);
+ __ xxbrd($tmpV$$VectorRegister->to_vsr(), $tmpV$$VectorRegister->to_vsr());
+ __ mfvsrd($dst$$Register, $tmpV$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -12959,7 +12766,7 @@ instruct mtvsrwz(vecX temp1, iRegIsrc src) %{
format %{ "MTVSRWZ $temp1, $src \t// Move to 16-byte register" %}
size(4);
ins_encode %{
- __ mtvsrwz($temp1$$VectorSRegister, $src$$Register);
+ __ mtvsrwz($temp1$$VectorRegister->to_vsr(), $src$$Register);
%}
ins_pipe(pipe_class_default);
%}
@@ -12970,7 +12777,7 @@ instruct xxspltw(vecX dst, vecX src, immI8 imm1) %{
format %{ "XXSPLTW $dst, $src, $imm1 \t// Splat word" %}
size(4);
ins_encode %{
- __ xxspltw($dst$$VectorSRegister, $src$$VectorSRegister, $imm1$$constant);
+ __ xxspltw($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr(), $imm1$$constant);
%}
ins_pipe(pipe_class_default);
%}
@@ -12981,7 +12788,7 @@ instruct xscvdpspn_regF(vecX dst, regF src) %{
format %{ "XSCVDPSPN $dst, $src \t// Convert scalar single precision to vector single precision" %}
size(4);
ins_encode %{
- __ xscvdpspn($dst$$VectorSRegister, $src$$FloatRegister->to_vsr());
+ __ xscvdpspn($dst$$VectorRegister->to_vsr(), $src$$FloatRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13088,7 +12895,7 @@ instruct repl16B_immI0(vecX dst, immI_0 zero) %{
format %{ "XXLXOR $dst, $zero \t// replicate16B" %}
size(4);
ins_encode %{
- __ xxlxor($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister);
+ __ xxlxor($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13101,7 +12908,7 @@ instruct repl16B_immIminus1(vecX dst, immI_minus1 src) %{
format %{ "XXLEQV $dst, $src \t// replicate16B" %}
size(4);
ins_encode %{
- __ xxleqv($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister);
+ __ xxleqv($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13166,7 +12973,7 @@ instruct repl8S_immI0(vecX dst, immI_0 zero) %{
format %{ "XXLXOR $dst, $zero \t// replicate8S" %}
size(4);
ins_encode %{
- __ xxlxor($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister);
+ __ xxlxor($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13179,7 +12986,7 @@ instruct repl8S_immIminus1(vecX dst, immI_minus1 src) %{
format %{ "XXLEQV $dst, $src \t// replicate8S" %}
size(4);
ins_encode %{
- __ xxleqv($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister);
+ __ xxleqv($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13244,7 +13051,7 @@ instruct repl4I_immI0(vecX dst, immI_0 zero) %{
format %{ "XXLXOR $dst, $zero \t// replicate4I" %}
size(4);
ins_encode %{
- __ xxlxor($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister);
+ __ xxlxor($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13257,7 +13064,7 @@ instruct repl4I_immIminus1(vecX dst, immI_minus1 src) %{
format %{ "XXLEQV $dst, $dst, $dst \t// replicate4I" %}
size(4);
ins_encode %{
- __ xxleqv($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister);
+ __ xxleqv($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13313,7 +13120,7 @@ instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "VADDUBM $dst,$src1,$src2\t// add packed16B" %}
size(4);
ins_encode %{
- __ vaddubm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vaddubm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13324,7 +13131,7 @@ instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "VADDUHM $dst,$src1,$src2\t// add packed8S" %}
size(4);
ins_encode %{
- __ vadduhm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vadduhm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13335,7 +13142,7 @@ instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "VADDUWM $dst,$src1,$src2\t// add packed4I" %}
size(4);
ins_encode %{
- __ vadduwm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vadduwm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13346,7 +13153,7 @@ instruct vadd4F_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "VADDFP $dst,$src1,$src2\t// add packed4F" %}
size(4);
ins_encode %{
- __ vaddfp($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vaddfp($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13357,7 +13164,7 @@ instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "VADDUDM $dst,$src1,$src2\t// add packed2L" %}
size(4);
ins_encode %{
- __ vaddudm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vaddudm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13368,7 +13175,7 @@ instruct vadd2D_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "XVADDDP $dst,$src1,$src2\t// add packed2D" %}
size(4);
ins_encode %{
- __ xvadddp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
+ __ xvadddp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13381,7 +13188,7 @@ instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "VSUBUBM $dst,$src1,$src2\t// sub packed16B" %}
size(4);
ins_encode %{
- __ vsububm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vsububm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13392,7 +13199,7 @@ instruct vsub8S_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "VSUBUHM $dst,$src1,$src2\t// sub packed8S" %}
size(4);
ins_encode %{
- __ vsubuhm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vsubuhm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13403,7 +13210,7 @@ instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "VSUBUWM $dst,$src1,$src2\t// sub packed4I" %}
size(4);
ins_encode %{
- __ vsubuwm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vsubuwm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13414,7 +13221,7 @@ instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "VSUBFP $dst,$src1,$src2\t// sub packed4F" %}
size(4);
ins_encode %{
- __ vsubfp($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vsubfp($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13425,7 +13232,7 @@ instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "VSUBUDM $dst,$src1,$src2\t// sub packed2L" %}
size(4);
ins_encode %{
- __ vsubudm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vsubudm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13436,7 +13243,7 @@ instruct vsub2D_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "XVSUBDP $dst,$src1,$src2\t// sub packed2D" %}
size(4);
ins_encode %{
- __ xvsubdp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
+ __ xvsubdp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13451,8 +13258,8 @@ instruct vmul8S_reg(vecX dst, vecX src1, vecX src2, vecX tmp) %{
format %{ "VMLADDUHM $dst,$src1,$src2\t// mul packed8S" %}
size(8);
ins_encode %{
- __ vspltish($tmp$$VectorSRegister->to_vr(), 0);
- __ vmladduhm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr(), $tmp$$VectorSRegister->to_vr());
+ __ vspltish($tmp$$VectorRegister, 0);
+ __ vmladduhm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister, $tmp$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13463,7 +13270,7 @@ instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "VMULUWM $dst,$src1,$src2\t// mul packed4I" %}
size(4);
ins_encode %{
- __ vmuluwm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vmuluwm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13474,7 +13281,7 @@ instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "XVMULSP $dst,$src1,$src2\t// mul packed4F" %}
size(4);
ins_encode %{
- __ xvmulsp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
+ __ xvmulsp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13485,7 +13292,7 @@ instruct vmul2D_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "XVMULDP $dst,$src1,$src2\t// mul packed2D" %}
size(4);
ins_encode %{
- __ xvmuldp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
+ __ xvmuldp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13498,7 +13305,7 @@ instruct vdiv4F_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "XVDIVSP $dst,$src1,$src2\t// div packed4F" %}
size(4);
ins_encode %{
- __ xvdivsp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
+ __ xvdivsp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13509,7 +13316,7 @@ instruct vdiv2D_reg(vecX dst, vecX src1, vecX src2) %{
format %{ "XVDIVDP $dst,$src1,$src2\t// div packed2D" %}
size(4);
ins_encode %{
- __ xvdivdp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
+ __ xvdivdp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13524,10 +13331,10 @@ instruct vmin_reg(vecX dst, vecX src1, vecX src2) %{
BasicType bt = Matcher::vector_element_basic_type(this);
switch (bt) {
case T_INT:
- __ vminsw($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vminsw($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
break;
case T_LONG:
- __ vminsd($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vminsd($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
break;
default:
ShouldNotReachHere();
@@ -13544,10 +13351,10 @@ instruct vmax_reg(vecX dst, vecX src1, vecX src2) %{
BasicType bt = Matcher::vector_element_basic_type(this);
switch (bt) {
case T_INT:
- __ vmaxsw($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vmaxsw($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
break;
case T_LONG:
- __ vmaxsd($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vmaxsd($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
break;
default:
ShouldNotReachHere();
@@ -13561,7 +13368,7 @@ instruct vand(vecX dst, vecX src1, vecX src2) %{
size(4);
format %{ "VAND $dst,$src1,$src2\t// and vectors" %}
ins_encode %{
- __ vand($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vand($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13571,7 +13378,7 @@ instruct vor(vecX dst, vecX src1, vecX src2) %{
size(4);
format %{ "VOR $dst,$src1,$src2\t// or vectors" %}
ins_encode %{
- __ vor($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vor($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13581,7 +13388,7 @@ instruct vxor(vecX dst, vecX src1, vecX src2) %{
size(4);
format %{ "VXOR $dst,$src1,$src2\t// xor vectors" %}
ins_encode %{
- __ vxor($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr());
+ __ vxor($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13599,8 +13406,8 @@ instruct reductionI_arith_logic(iRegIdst dst, iRegIsrc srcInt, vecX srcVec, vecX
size(24);
ins_encode %{
int opcode = this->ideal_Opcode();
- __ reduceI(opcode, $dst$$Register, $srcInt$$Register, $srcVec$$VectorSRegister->to_vr(),
- $tmp1$$VectorSRegister->to_vr(), $tmp2$$VectorSRegister->to_vr());
+ __ reduceI(opcode, $dst$$Register, $srcInt$$Register, $srcVec$$VectorRegister,
+ $tmp1$$VectorRegister, $tmp2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13615,8 +13422,8 @@ instruct reductionI_min_max(iRegIdst dst, iRegIsrc srcInt, vecX srcVec, vecX tmp
size(28);
ins_encode %{
int opcode = this->ideal_Opcode();
- __ reduceI(opcode, $dst$$Register, $srcInt$$Register, $srcVec$$VectorSRegister->to_vr(),
- $tmp1$$VectorSRegister->to_vr(), $tmp2$$VectorSRegister->to_vr());
+ __ reduceI(opcode, $dst$$Register, $srcInt$$Register, $srcVec$$VectorRegister,
+ $tmp1$$VectorRegister, $tmp2$$VectorRegister);
%}
ins_pipe(pipe_class_default);
%}
@@ -13629,7 +13436,7 @@ instruct vabs4F_reg(vecX dst, vecX src) %{
format %{ "XVABSSP $dst,$src\t// absolute packed4F" %}
size(4);
ins_encode %{
- __ xvabssp($dst$$VectorSRegister, $src$$VectorSRegister);
+ __ xvabssp($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13640,7 +13447,7 @@ instruct vabs2D_reg(vecX dst, vecX src) %{
format %{ "XVABSDP $dst,$src\t// absolute packed2D" %}
size(4);
ins_encode %{
- __ xvabsdp($dst$$VectorSRegister, $src$$VectorSRegister);
+ __ xvabsdp($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13677,13 +13484,13 @@ instruct vround2D_reg(vecX dst, vecX src, immI8 rmode) %{
ins_encode %{
switch ($rmode$$constant) {
case RoundDoubleModeNode::rmode_rint:
- __ xvrdpic($dst$$VectorSRegister, $src$$VectorSRegister);
+ __ xvrdpic($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr());
break;
case RoundDoubleModeNode::rmode_floor:
- __ xvrdpim($dst$$VectorSRegister, $src$$VectorSRegister);
+ __ xvrdpim($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr());
break;
case RoundDoubleModeNode::rmode_ceil:
- __ xvrdpip($dst$$VectorSRegister, $src$$VectorSRegister);
+ __ xvrdpip($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr());
break;
default:
ShouldNotReachHere();
@@ -13700,7 +13507,7 @@ instruct vneg4F_reg(vecX dst, vecX src) %{
format %{ "XVNEGSP $dst,$src\t// negate packed4F" %}
size(4);
ins_encode %{
- __ xvnegsp($dst$$VectorSRegister, $src$$VectorSRegister);
+ __ xvnegsp($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13711,7 +13518,7 @@ instruct vneg2D_reg(vecX dst, vecX src) %{
format %{ "XVNEGDP $dst,$src\t// negate packed2D" %}
size(4);
ins_encode %{
- __ xvnegdp($dst$$VectorSRegister, $src$$VectorSRegister);
+ __ xvnegdp($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13724,7 +13531,7 @@ instruct vsqrt4F_reg(vecX dst, vecX src) %{
format %{ "XVSQRTSP $dst,$src\t// sqrt packed4F" %}
size(4);
ins_encode %{
- __ xvsqrtsp($dst$$VectorSRegister, $src$$VectorSRegister);
+ __ xvsqrtsp($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13735,7 +13542,7 @@ instruct vsqrt2D_reg(vecX dst, vecX src) %{
format %{ "XVSQRTDP $dst,$src\t// sqrt packed2D" %}
size(4);
ins_encode %{
- __ xvsqrtdp($dst$$VectorSRegister, $src$$VectorSRegister);
+ __ xvsqrtdp($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13751,16 +13558,16 @@ instruct vpopcnt_reg(vecX dst, vecX src) %{
BasicType bt = Matcher::vector_element_basic_type(this);
switch (bt) {
case T_BYTE:
- __ vpopcntb($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr());
+ __ vpopcntb($dst$$VectorRegister, $src$$VectorRegister);
break;
case T_SHORT:
- __ vpopcnth($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr());
+ __ vpopcnth($dst$$VectorRegister, $src$$VectorRegister);
break;
case T_INT:
- __ vpopcntw($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr());
+ __ vpopcntw($dst$$VectorRegister, $src$$VectorRegister);
break;
case T_LONG:
- __ vpopcntd($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr());
+ __ vpopcntd($dst$$VectorRegister, $src$$VectorRegister);
break;
default:
ShouldNotReachHere();
@@ -13777,16 +13584,16 @@ instruct vcount_leading_zeros_reg(vecX dst, vecX src) %{
BasicType bt = Matcher::vector_element_basic_type(this);
switch (bt) {
case T_BYTE:
- __ vclzb($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr());
+ __ vclzb($dst$$VectorRegister, $src$$VectorRegister);
break;
case T_SHORT:
- __ vclzh($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr());
+ __ vclzh($dst$$VectorRegister, $src$$VectorRegister);
break;
case T_INT:
- __ vclzw($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr());
+ __ vclzw($dst$$VectorRegister, $src$$VectorRegister);
break;
case T_LONG:
- __ vclzd($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr());
+ __ vclzd($dst$$VectorRegister, $src$$VectorRegister);
break;
default:
ShouldNotReachHere();
@@ -13803,16 +13610,16 @@ instruct vcount_trailing_zeros_reg(vecX dst, vecX src) %{
BasicType bt = Matcher::vector_element_basic_type(this);
switch (bt) {
case T_BYTE:
- __ vctzb($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr());
+ __ vctzb($dst$$VectorRegister, $src$$VectorRegister);
break;
case T_SHORT:
- __ vctzh($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr());
+ __ vctzh($dst$$VectorRegister, $src$$VectorRegister);
break;
case T_INT:
- __ vctzw($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr());
+ __ vctzw($dst$$VectorRegister, $src$$VectorRegister);
break;
case T_LONG:
- __ vctzd($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr());
+ __ vctzd($dst$$VectorRegister, $src$$VectorRegister);
break;
default:
ShouldNotReachHere();
@@ -13832,7 +13639,7 @@ instruct vfma4F(vecX dst, vecX src1, vecX src2) %{
size(4);
ins_encode %{
assert(UseFMA, "Needs FMA instructions support.");
- __ xvmaddasp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
+ __ xvmaddasp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13848,7 +13655,7 @@ instruct vfma4F_neg1(vecX dst, vecX src1, vecX src2) %{
size(4);
ins_encode %{
assert(UseFMA, "Needs FMA instructions support.");
- __ xvnmsubasp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
+ __ xvnmsubasp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13863,7 +13670,7 @@ instruct vfma4F_neg2(vecX dst, vecX src1, vecX src2) %{
size(4);
ins_encode %{
assert(UseFMA, "Needs FMA instructions support.");
- __ xvmsubasp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
+ __ xvmsubasp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13878,7 +13685,7 @@ instruct vfma2D(vecX dst, vecX src1, vecX src2) %{
size(4);
ins_encode %{
assert(UseFMA, "Needs FMA instructions support.");
- __ xvmaddadp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
+ __ xvmaddadp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13894,7 +13701,7 @@ instruct vfma2D_neg1(vecX dst, vecX src1, vecX src2) %{
size(4);
ins_encode %{
assert(UseFMA, "Needs FMA instructions support.");
- __ xvnmsubadp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
+ __ xvnmsubadp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13909,7 +13716,7 @@ instruct vfma2D_neg2(vecX dst, vecX src1, vecX src2) %{
size(4);
ins_encode %{
assert(UseFMA, "Needs FMA instructions support.");
- __ xvmsubadp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
+ __ xvmsubadp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -13999,7 +13806,7 @@ instruct repl4F_immF0(vecX dst, immF_0 zero) %{
format %{ "XXLXOR $dst, $zero \t// replicate4F" %}
ins_encode %{
- __ xxlxor($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister);
+ __ xxlxor($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -14012,7 +13819,7 @@ instruct repl2D_reg_Ex(vecX dst, regD src) %{
format %{ "XXPERMDI $dst, $src, $src, 0 \t// Splat doubleword" %}
size(4);
ins_encode %{
- __ xxpermdi($dst$$VectorSRegister, $src$$FloatRegister->to_vsr(), $src$$FloatRegister->to_vsr(), 0);
+ __ xxpermdi($dst$$VectorRegister->to_vsr(), $src$$FloatRegister->to_vsr(), $src$$FloatRegister->to_vsr(), 0);
%}
ins_pipe(pipe_class_default);
%}
@@ -14025,7 +13832,7 @@ instruct repl2D_immD0(vecX dst, immD_0 zero) %{
format %{ "XXLXOR $dst, $zero \t// replicate2D" %}
size(4);
ins_encode %{
- __ xxlxor($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister);
+ __ xxlxor($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -14037,7 +13844,7 @@ instruct mtvsrd(vecX dst, iRegLsrc src) %{
format %{ "MTVSRD $dst, $src \t// Move to 16-byte register" %}
size(4);
ins_encode %{
- __ mtvsrd($dst$$VectorSRegister, $src$$Register);
+ __ mtvsrd($dst$$VectorRegister->to_vsr(), $src$$Register);
%}
ins_pipe(pipe_class_default);
%}
@@ -14048,7 +13855,7 @@ instruct xxspltd(vecX dst, vecX src, immI8 zero) %{
format %{ "XXSPLATD $dst, $src, $zero \t// Splat doubleword" %}
size(4);
ins_encode %{
- __ xxpermdi($dst$$VectorSRegister, $src$$VectorSRegister, $src$$VectorSRegister, $zero$$constant);
+ __ xxpermdi($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr(), $zero$$constant);
%}
ins_pipe(pipe_class_default);
%}
@@ -14059,7 +13866,7 @@ instruct xxpermdi(vecX dst, vecX src1, vecX src2, immI8 zero) %{
format %{ "XXPERMDI $dst, $src1, $src2, $zero \t// Splat doubleword" %}
size(4);
ins_encode %{
- __ xxpermdi($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister, $zero$$constant);
+ __ xxpermdi($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr(), $zero$$constant);
%}
ins_pipe(pipe_class_default);
%}
@@ -14084,7 +13891,7 @@ instruct repl2L_immI0(vecX dst, immI_0 zero) %{
format %{ "XXLXOR $dst, $zero \t// replicate2L" %}
size(4);
ins_encode %{
- __ xxlxor($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister);
+ __ xxlxor($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -14097,7 +13904,7 @@ instruct repl2L_immIminus1(vecX dst, immI_minus1 src) %{
format %{ "XXLEQV $dst, $src \t// replicate2L" %}
size(4);
ins_encode %{
- __ xxleqv($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister);
+ __ xxleqv($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr());
%}
ins_pipe(pipe_class_default);
%}
@@ -14404,20 +14211,6 @@ instruct tlsLoadP(threadRegP dst) %{
//---Some PPC specific nodes---------------------------------------------------
-// Stop a group.
-instruct endGroup() %{
- ins_cost(0);
-
- ins_is_nop(true);
-
- format %{ "End Bundle (ori r1, r1, 0)" %}
- size(4);
- ins_encode %{
- __ endgroup();
- %}
- ins_pipe(pipe_class_default);
-%}
-
// Nop instructions
instruct fxNop() %{
diff --git a/src/hotspot/cpu/ppc/registerMap_ppc.cpp b/src/hotspot/cpu/ppc/registerMap_ppc.cpp
new file mode 100644
index 000000000000..2e7f8af89d35
--- /dev/null
+++ b/src/hotspot/cpu/ppc/registerMap_ppc.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2026 SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "runtime/registerMap.hpp"
+
+address RegisterMap::pd_location(VMReg base_reg, int slot_idx) const {
+ if (base_reg->is_VectorRegister()) {
+ // Not all physical slots belonging to a VectorRegister have corresponding
+ // valid VMReg locations in the RegisterMap.
+ // (See RegisterSaver::push_frame_reg_args_and_save_live_registers.)
+ // However, the slots are always saved to the stack in a contiguous region
+ // of memory so we can calculate the address of the upper slots by
+ // offsetting from the base address.
+ assert(base_reg->is_concrete(), "must pass base reg");
+ address base_location = location(base_reg, nullptr);
+ if (base_location != nullptr) {
+ intptr_t offset_in_bytes = slot_idx * VMRegImpl::stack_slot_size;
+ return base_location + offset_in_bytes;
+ } else {
+ return nullptr;
+ }
+ } else {
+ return location(base_reg->next(slot_idx), nullptr);
+ }
+}
diff --git a/src/hotspot/cpu/ppc/registerMap_ppc.hpp b/src/hotspot/cpu/ppc/registerMap_ppc.hpp
index 01eb642107cb..607c712d10f2 100644
--- a/src/hotspot/cpu/ppc/registerMap_ppc.hpp
+++ b/src/hotspot/cpu/ppc/registerMap_ppc.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2013 SAP SE. All rights reserved.
+ * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2026 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,9 +35,7 @@
// Since there is none, we just return null.
address pd_location(VMReg reg) const { return nullptr; }
- address pd_location(VMReg base_reg, int slot_idx) const {
- return location(base_reg->next(slot_idx), nullptr);
- }
+ address pd_location(VMReg base_reg, int slot_idx) const;
// no PD state to clear or copy:
void pd_clear() {}
diff --git a/src/hotspot/cpu/ppc/register_ppc.hpp b/src/hotspot/cpu/ppc/register_ppc.hpp
index b7949750dcc9..2613d6c98222 100644
--- a/src/hotspot/cpu/ppc/register_ppc.hpp
+++ b/src/hotspot/cpu/ppc/register_ppc.hpp
@@ -321,6 +321,7 @@ class VectorRegister {
// accessors
constexpr int encoding() const { assert(is_valid(), "invalid register"); return _encoding; }
+ inline VMReg as_VMReg() const;
// testers
constexpr bool is_valid() const { return (0 <= _encoding && _encoding < number_of_registers); }
@@ -392,7 +393,6 @@ class VectorSRegister {
// accessors
constexpr int encoding() const { assert(is_valid(), "invalid register"); return _encoding; }
- inline VMReg as_VMReg() const;
VectorSRegister successor() const { return VectorSRegister(encoding() + 1); }
// testers
@@ -484,8 +484,8 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl {
enum {
max_gpr = Register::number_of_registers * 2,
max_fpr = max_gpr + FloatRegister::number_of_registers * 2,
- max_vsr = max_fpr + VectorSRegister::number_of_registers * 4,
- max_cnd = max_vsr + ConditionRegister::number_of_registers,
+ max_vr = max_fpr + VectorRegister::number_of_registers * 4,
+ max_cnd = max_vr + ConditionRegister::number_of_registers,
max_spr = max_cnd + SpecialRegister::number_of_registers,
// This number must be large enough to cover REG_COUNT (defined by c2) registers.
// There is no requirement that any ordering here matches any ordering c2 gives
diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
index 4ec2483b267c..8d34f494d96b 100644
--- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
+++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
@@ -103,7 +103,7 @@ class RegisterSaver {
// During deoptimization only the result registers need to be restored
// all the other values have already been extracted.
- static void restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes);
+ static void restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes, bool save_vectors);
// Constants and data structures:
@@ -111,13 +111,13 @@ class RegisterSaver {
int_reg,
float_reg,
special_reg,
- vs_reg
+ vec_reg
} RegisterType;
typedef enum {
reg_size = 8,
half_reg_size = reg_size / 2,
- vs_reg_size = 16
+ vec_reg_size = 16
} RegisterConstants;
typedef struct {
@@ -137,8 +137,8 @@ class RegisterSaver {
#define RegisterSaver_LiveSpecialReg(regname) \
{ RegisterSaver::special_reg, regname->encoding(), regname->as_VMReg() }
-#define RegisterSaver_LiveVSReg(regname) \
- { RegisterSaver::vs_reg, regname->encoding(), regname->as_VMReg() }
+#define RegisterSaver_LiveVecReg(regname) \
+ { RegisterSaver::vec_reg, regname->encoding(), regname->as_VMReg() }
static const RegisterSaver::LiveRegType RegisterSaver_LiveRegs[] = {
// Live registers which get spilled to the stack. Register
@@ -220,42 +220,42 @@ static const RegisterSaver::LiveRegType RegisterSaver_LiveRegs[] = {
RegisterSaver_LiveIntReg( R31 ) // must be the last register (see save/restore functions below)
};
-static const RegisterSaver::LiveRegType RegisterSaver_LiveVSRegs[] = {
+static const RegisterSaver::LiveRegType RegisterSaver_LiveVecRegs[] = {
//
- // live vector scalar registers (optional, only these ones are used by C2):
+ // live vector registers (optional, only these ones are used by C2):
//
- RegisterSaver_LiveVSReg( VSR32 ),
- RegisterSaver_LiveVSReg( VSR33 ),
- RegisterSaver_LiveVSReg( VSR34 ),
- RegisterSaver_LiveVSReg( VSR35 ),
- RegisterSaver_LiveVSReg( VSR36 ),
- RegisterSaver_LiveVSReg( VSR37 ),
- RegisterSaver_LiveVSReg( VSR38 ),
- RegisterSaver_LiveVSReg( VSR39 ),
- RegisterSaver_LiveVSReg( VSR40 ),
- RegisterSaver_LiveVSReg( VSR41 ),
- RegisterSaver_LiveVSReg( VSR42 ),
- RegisterSaver_LiveVSReg( VSR43 ),
- RegisterSaver_LiveVSReg( VSR44 ),
- RegisterSaver_LiveVSReg( VSR45 ),
- RegisterSaver_LiveVSReg( VSR46 ),
- RegisterSaver_LiveVSReg( VSR47 ),
- RegisterSaver_LiveVSReg( VSR48 ),
- RegisterSaver_LiveVSReg( VSR49 ),
- RegisterSaver_LiveVSReg( VSR50 ),
- RegisterSaver_LiveVSReg( VSR51 ),
- RegisterSaver_LiveVSReg( VSR52 ),
- RegisterSaver_LiveVSReg( VSR53 ),
- RegisterSaver_LiveVSReg( VSR54 ),
- RegisterSaver_LiveVSReg( VSR55 ),
- RegisterSaver_LiveVSReg( VSR56 ),
- RegisterSaver_LiveVSReg( VSR57 ),
- RegisterSaver_LiveVSReg( VSR58 ),
- RegisterSaver_LiveVSReg( VSR59 ),
- RegisterSaver_LiveVSReg( VSR60 ),
- RegisterSaver_LiveVSReg( VSR61 ),
- RegisterSaver_LiveVSReg( VSR62 ),
- RegisterSaver_LiveVSReg( VSR63 )
+ RegisterSaver_LiveVecReg( VR0 ),
+ RegisterSaver_LiveVecReg( VR1 ),
+ RegisterSaver_LiveVecReg( VR2 ),
+ RegisterSaver_LiveVecReg( VR3 ),
+ RegisterSaver_LiveVecReg( VR4 ),
+ RegisterSaver_LiveVecReg( VR5 ),
+ RegisterSaver_LiveVecReg( VR6 ),
+ RegisterSaver_LiveVecReg( VR7 ),
+ RegisterSaver_LiveVecReg( VR8 ),
+ RegisterSaver_LiveVecReg( VR9 ),
+ RegisterSaver_LiveVecReg( VR10 ),
+ RegisterSaver_LiveVecReg( VR11 ),
+ RegisterSaver_LiveVecReg( VR12 ),
+ RegisterSaver_LiveVecReg( VR13 ),
+ RegisterSaver_LiveVecReg( VR14 ),
+ RegisterSaver_LiveVecReg( VR15 ),
+ RegisterSaver_LiveVecReg( VR16 ),
+ RegisterSaver_LiveVecReg( VR17 ),
+ RegisterSaver_LiveVecReg( VR18 ),
+ RegisterSaver_LiveVecReg( VR19 ),
+ RegisterSaver_LiveVecReg( VR20 ),
+ RegisterSaver_LiveVecReg( VR21 ),
+ RegisterSaver_LiveVecReg( VR22 ),
+ RegisterSaver_LiveVecReg( VR23 ),
+ RegisterSaver_LiveVecReg( VR24 ),
+ RegisterSaver_LiveVecReg( VR25 ),
+ RegisterSaver_LiveVecReg( VR26 ),
+ RegisterSaver_LiveVecReg( VR27 ),
+ RegisterSaver_LiveVecReg( VR28 ),
+ RegisterSaver_LiveVecReg( VR29 ),
+ RegisterSaver_LiveVecReg( VR30 ),
+ RegisterSaver_LiveVecReg( VR31 )
};
@@ -277,10 +277,10 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble
// calculate frame size
const int regstosave_num = sizeof(RegisterSaver_LiveRegs) /
sizeof(RegisterSaver::LiveRegType);
- const int vsregstosave_num = save_vectors ? (sizeof(RegisterSaver_LiveVSRegs) /
+ const int vecregstosave_num = save_vectors ? (sizeof(RegisterSaver_LiveVecRegs) /
sizeof(RegisterSaver::LiveRegType))
: 0;
- const int register_save_size = regstosave_num * reg_size + vsregstosave_num * vs_reg_size;
+ const int register_save_size = regstosave_num * reg_size + vecregstosave_num * vec_reg_size;
const int frame_size_in_bytes = align_up(register_save_size, frame::alignment_in_bytes)
+ frame::native_abi_reg_args_size;
@@ -298,8 +298,8 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble
// Save some registers in the last (non-vector) slots of the new frame so we
// can use them as scratch regs or to determine the return pc.
- __ std(R31, frame_size_in_bytes - reg_size - vsregstosave_num * vs_reg_size, R1_SP);
- __ std(R30, frame_size_in_bytes - 2*reg_size - vsregstosave_num * vs_reg_size, R1_SP);
+ __ std(R31, frame_size_in_bytes - reg_size - vecregstosave_num * vec_reg_size, R1_SP);
+ __ std(R30, frame_size_in_bytes - 2*reg_size - vecregstosave_num * vec_reg_size, R1_SP);
// save the flags
// Do the save_LR by hand and adjust the return pc if requested.
@@ -355,42 +355,44 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble
}
// Note that generate_oop_map in the following loop is only used for the
- // polling_page_vectors_safepoint_handler_blob.
+ // polling_page_vectors_safepoint_handler_blob and the deopt_blob.
// The order in which the vector contents are stored depends on Endianess and
// the utilized instructions (PowerArchitecturePPC64).
assert(is_aligned(offset, StackAlignmentInBytes), "should be");
if (PowerArchitecturePPC64 >= 10) {
- assert(is_even(vsregstosave_num), "expectation");
- for (int i = 0; i < vsregstosave_num; i += 2) {
- int reg_num = RegisterSaver_LiveVSRegs[i].reg_num;
- assert(RegisterSaver_LiveVSRegs[i + 1].reg_num == reg_num + 1, "or use other instructions!");
+ assert(is_even(vecregstosave_num), "expectation");
+ for (int i = 0; i < vecregstosave_num; i += 2) {
+ int reg_num = RegisterSaver_LiveVecRegs[i].reg_num;
+ assert(RegisterSaver_LiveVecRegs[i + 1].reg_num == reg_num + 1, "or use other instructions!");
- __ stxvp(as_VectorSRegister(reg_num), offset, R1_SP);
+ __ stxvp(as_VectorRegister(reg_num).to_vsr(), offset, R1_SP);
// Note: The contents were read in the same order (see loadV16_Power9 node in ppc.ad).
+ // RegisterMap::pd_location only uses the first VMReg for each VectorRegister.
if (generate_oop_map) {
map->set_callee_saved(VMRegImpl::stack2reg(offset >> 2),
- RegisterSaver_LiveVSRegs[i LITTLE_ENDIAN_ONLY(+1) ].vmreg);
- map->set_callee_saved(VMRegImpl::stack2reg((offset + vs_reg_size) >> 2),
- RegisterSaver_LiveVSRegs[i BIG_ENDIAN_ONLY(+1) ].vmreg);
+ RegisterSaver_LiveVecRegs[i LITTLE_ENDIAN_ONLY(+1) ].vmreg);
+ map->set_callee_saved(VMRegImpl::stack2reg((offset + vec_reg_size) >> 2),
+ RegisterSaver_LiveVecRegs[i BIG_ENDIAN_ONLY(+1) ].vmreg);
}
- offset += (2 * vs_reg_size);
+ offset += (2 * vec_reg_size);
}
} else {
- for (int i = 0; i < vsregstosave_num; i++) {
- int reg_num = RegisterSaver_LiveVSRegs[i].reg_num;
+ for (int i = 0; i < vecregstosave_num; i++) {
+ int reg_num = RegisterSaver_LiveVecRegs[i].reg_num;
if (PowerArchitecturePPC64 >= 9) {
- __ stxv(as_VectorSRegister(reg_num), offset, R1_SP);
+ __ stxv(as_VectorRegister(reg_num)->to_vsr(), offset, R1_SP);
} else {
__ li(R31, offset);
- __ stxvd2x(as_VectorSRegister(reg_num), R31, R1_SP);
+ __ stxvd2x(as_VectorRegister(reg_num)->to_vsr(), R31, R1_SP);
}
// Note: The contents were read in the same order (see loadV16_Power8 / loadV16_Power9 node in ppc.ad).
+ // RegisterMap::pd_location only uses the first VMReg for each VectorRegister.
if (generate_oop_map) {
- VMReg vsr = RegisterSaver_LiveVSRegs[i].vmreg;
+ VMReg vsr = RegisterSaver_LiveVecRegs[i].vmreg;
map->set_callee_saved(VMRegImpl::stack2reg(offset >> 2), vsr);
}
- offset += vs_reg_size;
+ offset += vec_reg_size;
}
}
@@ -411,10 +413,10 @@ void RegisterSaver::restore_live_registers_and_pop_frame(MacroAssembler* masm,
bool save_vectors) {
const int regstosave_num = sizeof(RegisterSaver_LiveRegs) /
sizeof(RegisterSaver::LiveRegType);
- const int vsregstosave_num = save_vectors ? (sizeof(RegisterSaver_LiveVSRegs) /
+ const int vecregstosave_num = save_vectors ? (sizeof(RegisterSaver_LiveVecRegs) /
sizeof(RegisterSaver::LiveRegType))
: 0;
- const int register_save_size = regstosave_num * reg_size + vsregstosave_num * vs_reg_size;
+ const int register_save_size = regstosave_num * reg_size + vecregstosave_num * vec_reg_size;
const int register_save_offset = frame_size_in_bytes - register_save_size;
@@ -456,26 +458,26 @@ void RegisterSaver::restore_live_registers_and_pop_frame(MacroAssembler* masm,
assert(is_aligned(offset, StackAlignmentInBytes), "should be");
if (PowerArchitecturePPC64 >= 10) {
- for (int i = 0; i < vsregstosave_num; i += 2) {
- int reg_num = RegisterSaver_LiveVSRegs[i].reg_num;
- assert(RegisterSaver_LiveVSRegs[i + 1].reg_num == reg_num + 1, "or use other instructions!");
+ for (int i = 0; i < vecregstosave_num; i += 2) {
+ int reg_num = RegisterSaver_LiveVecRegs[i].reg_num;
+ assert(RegisterSaver_LiveVecRegs[i + 1].reg_num == reg_num + 1, "or use other instructions!");
- __ lxvp(as_VectorSRegister(reg_num), offset, R1_SP);
+ __ lxvp(as_VectorRegister(reg_num).to_vsr(), offset, R1_SP);
- offset += (2 * vs_reg_size);
+ offset += (2 * vec_reg_size);
}
} else {
- for (int i = 0; i < vsregstosave_num; i++) {
- int reg_num = RegisterSaver_LiveVSRegs[i].reg_num;
+ for (int i = 0; i < vecregstosave_num; i++) {
+ int reg_num = RegisterSaver_LiveVecRegs[i].reg_num;
if (PowerArchitecturePPC64 >= 9) {
- __ lxv(as_VectorSRegister(reg_num), offset, R1_SP);
+ __ lxv(as_VectorRegister(reg_num).to_vsr(), offset, R1_SP);
} else {
__ li(R31, offset);
- __ lxvd2x(as_VectorSRegister(reg_num), R31, R1_SP);
+ __ lxvd2x(as_VectorRegister(reg_num).to_vsr(), R31, R1_SP);
}
- offset += vs_reg_size;
+ offset += vec_reg_size;
}
}
@@ -486,7 +488,7 @@ void RegisterSaver::restore_live_registers_and_pop_frame(MacroAssembler* masm,
__ mtlr(R31);
// restore scratch register's value
- __ ld(R31, frame_size_in_bytes - reg_size - vsregstosave_num * vs_reg_size, R1_SP);
+ __ ld(R31, frame_size_in_bytes - reg_size - vecregstosave_num * vec_reg_size, R1_SP);
// pop the frame
__ addi(R1_SP, R1_SP, frame_size_in_bytes);
@@ -572,10 +574,14 @@ void RegisterSaver::restore_argument_registers_and_pop_frame(MacroAssembler*masm
}
// Restore the registers that might be holding a result.
-void RegisterSaver::restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes) {
+void RegisterSaver::restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes, bool save_vectors) {
const int regstosave_num = sizeof(RegisterSaver_LiveRegs) /
sizeof(RegisterSaver::LiveRegType);
- const int register_save_size = regstosave_num * reg_size; // VS registers not relevant here.
+ const int vecregstosave_num = save_vectors ? (sizeof(RegisterSaver_LiveVecRegs) /
+ sizeof(RegisterSaver::LiveRegType))
+ : 0;
+ const int register_save_size = regstosave_num * reg_size + vecregstosave_num * vec_reg_size;
+
const int register_save_offset = frame_size_in_bytes - register_save_size;
// restore all result registers (ints and floats)
@@ -604,7 +610,7 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm, int frame_siz
offset += reg_size;
}
- assert(offset == frame_size_in_bytes, "consistency check");
+ assert(offset == frame_size_in_bytes - (save_vectors ? vecregstosave_num * vec_reg_size : 0), "consistency check");
}
// Is vector's size (in bytes) bigger than a size saved by default?
@@ -2993,7 +2999,8 @@ void SharedRuntime::generate_deopt_blob() {
&first_frame_size_in_bytes,
/*generate_oop_map=*/ true,
return_pc_adjustment_no_exception,
- RegisterSaver::return_pc_is_lr);
+ RegisterSaver::return_pc_is_lr,
+ /*save_vectors*/ SuperwordUseVSX);
assert(map != nullptr, "OopMap must have been created");
__ li(exec_mode_reg, Deoptimization::Unpack_deopt);
@@ -3028,7 +3035,8 @@ void SharedRuntime::generate_deopt_blob() {
&first_frame_size_in_bytes,
/*generate_oop_map=*/ false,
/*return_pc_adjustment_exception=*/ 0,
- RegisterSaver::return_pc_is_pre_saved);
+ RegisterSaver::return_pc_is_pre_saved,
+ /*save_vectors*/ SuperwordUseVSX);
// Deopt during an exception. Save exec mode for unpack_frames.
__ li(exec_mode_reg, Deoptimization::Unpack_exception);
@@ -3046,7 +3054,8 @@ void SharedRuntime::generate_deopt_blob() {
&first_frame_size_in_bytes,
/*generate_oop_map=*/ false,
/*return_pc_adjustment_reexecute=*/ 0,
- RegisterSaver::return_pc_is_pre_saved);
+ RegisterSaver::return_pc_is_pre_saved,
+ /*save_vectors*/ SuperwordUseVSX);
__ li(exec_mode_reg, Deoptimization::Unpack_reexecute);
#endif
@@ -3072,7 +3081,7 @@ void SharedRuntime::generate_deopt_blob() {
// Restore only the result registers that have been saved
// by save_volatile_registers(...).
- RegisterSaver::restore_result_registers(masm, first_frame_size_in_bytes);
+ RegisterSaver::restore_result_registers(masm, first_frame_size_in_bytes, /*save_vectors*/ SuperwordUseVSX);
// reload the exec mode from the UnrollBlock (it might have changed)
__ lwz(exec_mode_reg, in_bytes(Deoptimization::UnrollBlock::unpack_kind_offset()), unroll_block_reg);
diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp
index 721364ce412b..d076308026b6 100644
--- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp
+++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp
@@ -25,6 +25,7 @@
#include "asm/assembler.inline.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "compiler/compilerDefinitions.inline.hpp"
#include "compiler/disassembler.hpp"
#include "jvm.h"
#include "memory/resourceArea.hpp"
@@ -103,7 +104,7 @@ void VM_Version::initialize() {
if (PowerArchitecturePPC64 >= 9) {
// Performance is good since Power9.
- if (FLAG_IS_DEFAULT(SuperwordUseVSX)) {
+ if (FLAG_IS_DEFAULT(SuperwordUseVSX) && CompilerConfig::is_c2_enabled()) {
FLAG_SET_ERGO(SuperwordUseVSX, true);
}
}
diff --git a/src/hotspot/cpu/ppc/vmreg_ppc.cpp b/src/hotspot/cpu/ppc/vmreg_ppc.cpp
index 2ed68578a80a..0edbf700ec61 100644
--- a/src/hotspot/cpu/ppc/vmreg_ppc.cpp
+++ b/src/hotspot/cpu/ppc/vmreg_ppc.cpp
@@ -47,7 +47,7 @@ void VMRegImpl::set_regName() {
}
VectorSRegister vsreg = ::as_VectorSRegister(0);
- for ( ; i < ConcreteRegisterImpl::max_vsr; ) {
+ for ( ; i < ConcreteRegisterImpl::max_vr; ) {
regName[i++] = vsreg->name();
regName[i++] = vsreg->name();
regName[i++] = vsreg->name();
diff --git a/src/hotspot/cpu/ppc/vmreg_ppc.hpp b/src/hotspot/cpu/ppc/vmreg_ppc.hpp
index 4e25c8b3cead..194b5fd93ef6 100644
--- a/src/hotspot/cpu/ppc/vmreg_ppc.hpp
+++ b/src/hotspot/cpu/ppc/vmreg_ppc.hpp
@@ -35,13 +35,13 @@ inline bool is_FloatRegister() {
value() < ConcreteRegisterImpl::max_fpr;
}
-inline bool is_VectorSRegister() {
+inline bool is_VectorRegister() {
return value() >= ConcreteRegisterImpl::max_fpr &&
- value() < ConcreteRegisterImpl::max_vsr;
+ value() < ConcreteRegisterImpl::max_vr;
}
inline bool is_ConditionRegister() {
- return value() >= ConcreteRegisterImpl::max_vsr &&
+ return value() >= ConcreteRegisterImpl::max_vr &&
value() < ConcreteRegisterImpl::max_cnd;
}
@@ -60,15 +60,15 @@ inline FloatRegister as_FloatRegister() {
return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) >> 1);
}
-inline VectorSRegister as_VectorSRegister() {
- assert(is_VectorSRegister(), "must be");
- return ::as_VectorSRegister((value() - ConcreteRegisterImpl::max_fpr) >> 2);
+inline VectorRegister as_VectorRegister() {
+ assert(is_VectorRegister(), "must be");
+ return ::as_VectorRegister((value() - ConcreteRegisterImpl::max_fpr) >> 2);
}
inline bool is_concrete() {
assert(is_reg(), "must be");
if (is_Register() || is_FloatRegister()) return is_even(value());
- if (is_VectorSRegister()) {
+ if (is_VectorRegister()) {
int base = value() - ConcreteRegisterImpl::max_fpr;
return (base & 3) == 0;
}
diff --git a/src/hotspot/cpu/ppc/vmreg_ppc.inline.hpp b/src/hotspot/cpu/ppc/vmreg_ppc.inline.hpp
index 2424df8da01e..a7810266b897 100644
--- a/src/hotspot/cpu/ppc/vmreg_ppc.inline.hpp
+++ b/src/hotspot/cpu/ppc/vmreg_ppc.inline.hpp
@@ -40,13 +40,13 @@ inline VMReg FloatRegister::as_VMReg() const {
return VMRegImpl::as_VMReg((encoding() << 1) + ConcreteRegisterImpl::max_gpr);
}
-inline VMReg VectorSRegister::as_VMReg() const {
+inline VMReg VectorRegister::as_VMReg() const {
// Four halves, multiply by 4.
return VMRegImpl::as_VMReg((encoding() << 2) + ConcreteRegisterImpl::max_fpr);
}
inline VMReg ConditionRegister::as_VMReg() const {
- return VMRegImpl::as_VMReg((encoding()) + ConcreteRegisterImpl::max_vsr);
+ return VMRegImpl::as_VMReg((encoding()) + ConcreteRegisterImpl::max_vr);
}
inline VMReg SpecialRegister::as_VMReg() const {
diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp
index 387db778c1fd..a0be79d02813 100644
--- a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp
@@ -228,7 +228,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo
BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
Assembler::IncompressibleScope scope(masm); // Fixed length: see entry_barrier_offset()
- Label local_guard;
+ Label local_guard, skip_barrier;
NMethodPatchingType patching_type = nmethod_patching_type();
if (slow_path == nullptr) {
@@ -290,24 +290,26 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slo
ShouldNotReachHere();
}
+ Label& barrier_target = slow_path == nullptr ? skip_barrier : *slow_path;
if (slow_path == nullptr) {
- Label skip_barrier;
- __ beq(t0, t1, skip_barrier);
+ __ beq(t0, t1, barrier_target, true /* is_far */);
+ } else {
+ __ bne(t0, t1, barrier_target, true /* is_far */);
+ }
+ if (slow_path == nullptr) {
__ rt_call(StubRoutines::method_entry_barrier());
-
__ j(skip_barrier);
__ bind(local_guard);
MacroAssembler::assert_alignment(__ pc());
__ emit_int32(0); // nmethod guard value. Skipped over in common case.
- __ bind(skip_barrier);
} else {
- __ beq(t0, t1, *continuation);
- __ j(*slow_path);
__ bind(*continuation);
}
+
+ __ bind(skip_barrier);
}
void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) {
diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp
index ac619f83f7de..0d398e08d3df 100644
--- a/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp
+++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.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.
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -41,17 +41,16 @@
static int slow_path_size(nmethod* nm) {
// The slow path code is out of line with C2.
- // Leave a jal to the stub in the fast path.
- return nm->is_compiled_by_c2() ? 1 : 8;
+ return nm->is_compiled_by_c2() ? 0 : 4;
}
static int entry_barrier_offset(nmethod* nm) {
BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler();
switch (bs_asm->nmethod_patching_type()) {
case NMethodPatchingType::stw_instruction_and_data_patch:
- return -4 * (4 + slow_path_size(nm));
+ return -4 * (5 + slow_path_size(nm));
case NMethodPatchingType::conc_instruction_and_data_patch:
- return -4 * (15 + slow_path_size(nm));
+ return -4 * ((UseZtso ? 14 : 16) + slow_path_size(nm));
}
ShouldNotReachHere();
return 0;
@@ -103,6 +102,10 @@ class NativeNMethodBarrier {
}
_guard_addr = reinterpret_cast(instruction_address() + local_guard_offset(nm));
}
+
+ // Perform the checking as verification.
+ err_msg msg("%s", "");
+ assert(check_barrier(msg), "%s", msg.buffer());
}
int get_value() {
@@ -114,10 +117,6 @@ class NativeNMethodBarrier {
}
bool check_barrier(err_msg& msg) const;
- void verify() const {
- err_msg msg("%s", "");
- assert(check_barrier(msg), "%s", msg.buffer());
- }
};
// Store the instruction bitmask, bits and name for checking the barrier.
@@ -128,8 +127,8 @@ struct CheckInsn {
};
static const struct CheckInsn barrierInsn[] = {
- { 0x00000fff, 0x00000297, "auipc t0, 0 "},
- { 0x000fffff, 0x0002e283, "lwu t0, guard_offset(t0) "},
+ { 0x00000fff, 0x00000297, "auipc t0, 0 " },
+ { 0x000fffff, 0x0002e283, "lwu t0, guard_offset(t0)" },
/* ...... */
/* ...... */
/* guard: */
@@ -141,10 +140,11 @@ static const struct CheckInsn barrierInsn[] = {
// register numbers and immediate values in the encoding.
bool NativeNMethodBarrier::check_barrier(err_msg& msg) const {
address addr = instruction_address();
- for(unsigned int i = 0; i < sizeof(barrierInsn)/sizeof(struct CheckInsn); i++ ) {
+ for (unsigned int i = 0; i < sizeof(barrierInsn) / sizeof(struct CheckInsn); i++) {
uint32_t inst = Assembler::ld_instr(addr);
if ((inst & barrierInsn[i].mask) != barrierInsn[i].bits) {
- msg.print("Addr: " INTPTR_FORMAT " Code: 0x%x not an %s instruction", p2i(addr), inst, barrierInsn[i].name);
+ msg.print("Nmethod entry barrier did not start with auipc & lwu as expected. "
+ "Addr: " INTPTR_FORMAT " Code: 0x%x not an %s instruction.", p2i(addr), inst, barrierInsn[i].name);
return false;
}
addr += 4;
diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp
index 4c1056e75a55..f936ae9ba27b 100644
--- a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp
@@ -301,7 +301,7 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm,
} else {
assert(is_phantom, "only remaining strength");
assert(!is_narrow, "phantom access cannot be narrow");
- target = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak);
+ target = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom);
}
__ rt_call(target);
__ mv(t0, x10);
diff --git a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp
index 09dea62b6d18..a294fba8e1ff 100644
--- a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp
@@ -713,6 +713,7 @@ class ZSetupArguments {
#define __ masm->
void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, ZLoadBarrierStubC2* stub) const {
+ Assembler::InlineSkippedInstructionsCounter skipped_counter(masm);
BLOCK_COMMENT("ZLoadBarrierStubC2");
// Stub entry
@@ -732,6 +733,7 @@ void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, Z
}
void ZBarrierSetAssembler::generate_c2_store_barrier_stub(MacroAssembler* masm, ZStoreBarrierStubC2* stub) const {
+ Assembler::InlineSkippedInstructionsCounter skipped_counter(masm);
BLOCK_COMMENT("ZStoreBarrierStubC2");
// Stub entry
diff --git a/src/hotspot/cpu/riscv/gc/z/z_riscv.ad b/src/hotspot/cpu/riscv/gc/z/z_riscv.ad
index fd9a1d43afc6..4a17e512ae3c 100644
--- a/src/hotspot/cpu/riscv/gc/z/z_riscv.ad
+++ b/src/hotspot/cpu/riscv/gc/z/z_riscv.ad
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
@@ -57,6 +57,7 @@ static void check_color(MacroAssembler* masm, Register ref, bool on_non_strong,
}
static void z_load_barrier(MacroAssembler* masm, const MachNode* node, Address ref_addr, Register ref, Register tmp) {
+ Assembler::InlineSkippedInstructionsCounter skipped_counter(masm);
const bool on_non_strong =
((node->barrier_data() & ZBarrierWeak) != 0) ||
((node->barrier_data() & ZBarrierPhantom) != 0);
@@ -78,6 +79,7 @@ static void z_load_barrier(MacroAssembler* masm, const MachNode* node, Address r
}
static void z_store_barrier(MacroAssembler* masm, const MachNode* node, Address ref_addr, Register rnew_zaddress, Register rnew_zpointer, Register tmp, bool is_atomic) {
+ Assembler::InlineSkippedInstructionsCounter skipped_counter(masm);
if (node->barrier_data() == ZBarrierElided) {
z_color(masm, node, rnew_zpointer, rnew_zaddress, tmp);
} else {
diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp
index 8fc9c2f9eaa8..32675a12cb07 100644
--- a/src/hotspot/cpu/x86/vm_version_x86.cpp
+++ b/src/hotspot/cpu/x86/vm_version_x86.cpp
@@ -140,7 +140,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4, std_cpuid24, std_cpuid29;
Label sef_cpuid, sefsl1_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7;
- Label ext_cpuid8, done, wrapup, vector_save_restore, apx_save_restore_warning;
+ Label ext_cpuid8, done, wrapup, vector_save_restore, apx_save_restore_warning, apx_xstate;
Label legacy_setup, save_restore_except, legacy_save_restore, start_simd_check;
StubCodeMark mark(this, "VM_Version", "get_cpu_info_stub");
@@ -465,6 +465,20 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movq(Address(rsi, 0), r16);
__ movq(Address(rsi, 8), r31);
+ //
+ // Query CPUID 0xD.19 for APX XSAVE offset
+ // Extended State Enumeration Sub-leaf 19 (APX)
+ // EAX = size of APX state (should be 128)
+ // EBX = offset in standard XSAVE format
+ //
+ __ movl(rax, 0xD);
+ __ movl(rcx, 19);
+ __ cpuid();
+ __ lea(rsi, Address(rbp, in_bytes(VM_Version::apx_xstate_size_offset())));
+ __ movl(Address(rsi, 0), rax);
+ __ lea(rsi, Address(rbp, in_bytes(VM_Version::apx_xstate_offset_offset())));
+ __ movl(Address(rsi, 0), rbx);
+
UseAPX = save_apx;
__ bind(vector_save_restore);
//
diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp
index 78ae45ef4f8c..64b9102b5cb8 100644
--- a/src/hotspot/cpu/x86/vm_version_x86.hpp
+++ b/src/hotspot/cpu/x86/vm_version_x86.hpp
@@ -672,6 +672,10 @@ class VM_Version : public Abstract_VM_Version {
// Space to save apx registers after signal handle
jlong apx_save[2]; // Save r16 and r31
+ // cpuid function 0xD, subleaf 19 (APX extended state)
+ uint32_t apx_xstate_size; // EAX: size of APX state (128)
+ uint32_t apx_xstate_offset; // EBX: offset in standard XSAVE area
+
VM_Features feature_flags() const;
// Asserts
@@ -735,6 +739,11 @@ class VM_Version : public Abstract_VM_Version {
static ByteSize ymm_save_offset() { return byte_offset_of(CpuidInfo, ymm_save); }
static ByteSize zmm_save_offset() { return byte_offset_of(CpuidInfo, zmm_save); }
static ByteSize apx_save_offset() { return byte_offset_of(CpuidInfo, apx_save); }
+ static ByteSize apx_xstate_offset_offset() { return byte_offset_of(CpuidInfo, apx_xstate_offset); }
+ static ByteSize apx_xstate_size_offset() { return byte_offset_of(CpuidInfo, apx_xstate_size); }
+
+ static uint32_t apx_xstate_offset() { return _cpuid_info.apx_xstate_offset; }
+ static uint32_t apx_xstate_size() { return _cpuid_info.apx_xstate_size; }
// The value used to check ymm register after signal handle
static int ymm_test_value() { return 0xCAFEBABE; }
diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp
index 1872e24920e5..cb7f0855f71d 100644
--- a/src/hotspot/os/aix/os_aix.cpp
+++ b/src/hotspot/os/aix/os_aix.cpp
@@ -169,7 +169,7 @@ static void vmembk_print_on(outputStream* os);
////////////////////////////////////////////////////////////////////////////////
// global variables (for a description see os_aix.hpp)
-julong os::Aix::_physical_memory = 0;
+physical_memory_size_type os::Aix::_physical_memory = 0;
pthread_t os::Aix::_main_thread = ((pthread_t)0);
@@ -254,40 +254,43 @@ static bool is_close_to_brk(address a) {
return false;
}
-julong os::free_memory() {
- return Aix::available_memory();
+bool os::free_memory(physical_memory_size_type& value) {
+ return Aix::available_memory(value);
}
-julong os::available_memory() {
- return Aix::available_memory();
+bool os::available_memory(physical_memory_size_type& value) {
+ return Aix::available_memory(value);
}
-julong os::Aix::available_memory() {
+bool os::Aix::available_memory(physical_memory_size_type& value) {
os::Aix::meminfo_t mi;
if (os::Aix::get_meminfo(&mi)) {
- return mi.real_free;
+ value = static_cast(mi.real_free);
+ return true;
} else {
- return ULONG_MAX;
+ return false;
}
}
-jlong os::total_swap_space() {
+bool os::total_swap_space(physical_memory_size_type& value) {
perfstat_memory_total_t memory_info;
if (libperfstat::perfstat_memory_total(nullptr, &memory_info, sizeof(perfstat_memory_total_t), 1) == -1) {
- return -1;
+ return false;
}
- return (jlong)(memory_info.pgsp_total * 4 * K);
+ value = static_cast(memory_info.pgsp_total * 4 * K);
+ return true;
}
-jlong os::free_swap_space() {
+bool os::free_swap_space(physical_memory_size_type& value) {
perfstat_memory_total_t memory_info;
if (libperfstat::perfstat_memory_total(nullptr, &memory_info, sizeof(perfstat_memory_total_t), 1) == -1) {
- return -1;
+ return false;
}
- return (jlong)(memory_info.pgsp_free * 4 * K);
+ value = static_cast(memory_info.pgsp_free * 4 * K);
+ return true;
}
-julong os::physical_memory() {
+physical_memory_size_type os::physical_memory() {
return Aix::physical_memory();
}
@@ -326,7 +329,7 @@ void os::Aix::initialize_system_info() {
if (!os::Aix::get_meminfo(&mi)) {
assert(false, "os::Aix::get_meminfo failed.");
}
- _physical_memory = (julong) mi.real_total;
+ _physical_memory = static_cast(mi.real_total);
}
// Helper function for tracing page sizes.
@@ -1046,6 +1049,8 @@ static void* dll_load_library(const char *filename, int *eno, char *ebuf, int eb
dflags |= RTLD_MEMBER;
}
+ Events::log_dll_message(nullptr, "Attempting to load shared library %s", filename);
+
void* result;
const char* error_report = nullptr;
JFR_ONLY(NativeLibraryLoadEvent load_event(filename, &result);)
@@ -2271,7 +2276,7 @@ jint os::init_2(void) {
os::Posix::init_2();
trcVerbose("processor count: %d", os::_processor_count);
- trcVerbose("physical memory: %lu", Aix::_physical_memory);
+ trcVerbose("physical memory: " PHYS_MEM_TYPE_FORMAT, Aix::_physical_memory);
// Initially build up the loaded dll map.
LoadedLibraries::reload();
diff --git a/src/hotspot/os/aix/os_aix.hpp b/src/hotspot/os/aix/os_aix.hpp
index d17c022e4113..a7bac40e79b9 100644
--- a/src/hotspot/os/aix/os_aix.hpp
+++ b/src/hotspot/os/aix/os_aix.hpp
@@ -35,7 +35,7 @@ class os::Aix {
private:
- static julong _physical_memory;
+ static physical_memory_size_type _physical_memory;
static pthread_t _main_thread;
// 0 = uninitialized, otherwise 16 bit number:
@@ -54,9 +54,9 @@ class os::Aix {
// 1 - EXTSHM=ON
static int _extshm;
- static julong available_memory();
- static julong free_memory();
- static julong physical_memory() { return _physical_memory; }
+ static bool available_memory(physical_memory_size_type& value);
+ static bool free_memory(physical_memory_size_type& value);
+ static physical_memory_size_type physical_memory() { return _physical_memory; }
static void initialize_system_info();
// OS recognitions (AIX OS level) call this before calling Aix::os_version().
diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp
index e8b852ad9dfe..86178c51e974 100644
--- a/src/hotspot/os/bsd/os_bsd.cpp
+++ b/src/hotspot/os/bsd/os_bsd.cpp
@@ -114,7 +114,7 @@
////////////////////////////////////////////////////////////////////////////////
// global variables
-julong os::Bsd::_physical_memory = 0;
+physical_memory_size_type os::Bsd::_physical_memory = 0;
#ifdef __APPLE__
mach_timebase_info_data_t os::Bsd::_timebase_info = {0, 0};
@@ -133,19 +133,19 @@ static volatile int processor_id_next = 0;
////////////////////////////////////////////////////////////////////////////////
// utility functions
-julong os::available_memory() {
- return Bsd::available_memory();
+bool os::available_memory(physical_memory_size_type& value) {
+ return Bsd::available_memory(value);
}
-julong os::free_memory() {
- return Bsd::available_memory();
+bool os::free_memory(physical_memory_size_type& value) {
+ return Bsd::available_memory(value);
}
// Available here means free. Note that this number is of no much use. As an estimate
// for future memory pressure it is far too conservative, since MacOS will use a lot
// of unused memory for caches, and return it willingly in case of needs.
-julong os::Bsd::available_memory() {
- uint64_t available = physical_memory() >> 2;
+bool os::Bsd::available_memory(physical_memory_size_type& value) {
+ physical_memory_size_type available = physical_memory() >> 2;
#ifdef __APPLE__
mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
vm_statistics64_data_t vmstat;
@@ -156,9 +156,12 @@ julong os::Bsd::available_memory() {
if (kerr == KERN_SUCCESS) {
// free_count is just a lowerbound, other page categories can be freed too and make memory available
available = (vmstat.free_count + vmstat.inactive_count + vmstat.purgeable_count) * os::vm_page_size();
+ } else {
+ return false;
}
#endif
- return available;
+ value = available;
+ return true;
}
// for more info see :
@@ -177,33 +180,35 @@ void os::Bsd::print_uptime_info(outputStream* st) {
}
}
-jlong os::total_swap_space() {
+bool os::total_swap_space(physical_memory_size_type& value) {
#if defined(__APPLE__)
struct xsw_usage vmusage;
size_t size = sizeof(vmusage);
if (sysctlbyname("vm.swapusage", &vmusage, &size, nullptr, 0) != 0) {
- return -1;
+ return false;
}
- return (jlong)vmusage.xsu_total;
+ value = static_cast(vmusage.xsu_total);
+ return true;
#else
- return -1;
+ return false;
#endif
}
-jlong os::free_swap_space() {
+bool os::free_swap_space(physical_memory_size_type& value) {
#if defined(__APPLE__)
struct xsw_usage vmusage;
size_t size = sizeof(vmusage);
if (sysctlbyname("vm.swapusage", &vmusage, &size, nullptr, 0) != 0) {
- return -1;
+ return false;
}
- return (jlong)vmusage.xsu_avail;
+ value = static_cast(vmusage.xsu_avail);
+ return true;
#else
- return -1;
+ return false;
#endif
}
-julong os::physical_memory() {
+physical_memory_size_type os::physical_memory() {
return Bsd::physical_memory();
}
@@ -281,7 +286,7 @@ void os::Bsd::initialize_system_info() {
len = sizeof(mem_val);
if (sysctl(mib, 2, &mem_val, &len, nullptr, 0) != -1) {
assert(len == sizeof(mem_val), "unexpected data size");
- _physical_memory = mem_val;
+ _physical_memory = static_cast(mem_val);
} else {
_physical_memory = 256 * 1024 * 1024; // fallback (XXXBSD?)
}
@@ -292,7 +297,7 @@ void os::Bsd::initialize_system_info() {
// datasize rlimit restricts us anyway.
struct rlimit limits;
getrlimit(RLIMIT_DATA, &limits);
- _physical_memory = MIN2(_physical_memory, (julong)limits.rlim_cur);
+ _physical_memory = MIN2(_physical_memory, static_cast(limits.rlim_cur));
}
#endif
}
@@ -1042,6 +1047,8 @@ void *os::Bsd::dlopen_helper(const char *filename, int mode, char *ebuf, int ebu
assert(rtn == 0, "fegetenv must succeed");
#endif // IA32
+ Events::log_dll_message(nullptr, "Attempting to load shared library %s", filename);
+
void* result;
JFR_ONLY(NativeLibraryLoadEvent load_event(filename, &result);)
result = ::dlopen(filename, RTLD_LAZY);
@@ -1469,11 +1476,13 @@ void os::print_memory_info(outputStream* st) {
st->print("Memory:");
st->print(" %zuk page", os::vm_page_size()>>10);
-
- st->print(", physical " UINT64_FORMAT "k",
- os::physical_memory() >> 10);
- st->print("(" UINT64_FORMAT "k free)",
- os::available_memory() >> 10);
+ physical_memory_size_type phys_mem = os::physical_memory();
+ st->print(", physical " PHYS_MEM_TYPE_FORMAT "k",
+ phys_mem >> 10);
+ physical_memory_size_type avail_mem = 0;
+ (void)os::available_memory(avail_mem);
+ st->print("(" PHYS_MEM_TYPE_FORMAT "k free)",
+ avail_mem >> 10);
if((sysctlbyname("vm.swapusage", &swap_usage, &size, nullptr, 0) == 0) || (errno == ENOMEM)) {
if (size >= offset_of(xsw_usage, xsu_used)) {
diff --git a/src/hotspot/os/bsd/os_bsd.hpp b/src/hotspot/os/bsd/os_bsd.hpp
index 72de9ca59719..82002917f39d 100644
--- a/src/hotspot/os/bsd/os_bsd.hpp
+++ b/src/hotspot/os/bsd/os_bsd.hpp
@@ -42,12 +42,12 @@ class os::Bsd {
protected:
- static julong _physical_memory;
+ static physical_memory_size_type _physical_memory;
static pthread_t _main_thread;
- static julong available_memory();
- static julong free_memory();
- static julong physical_memory() { return _physical_memory; }
+ static bool available_memory(physical_memory_size_type& value);
+ static bool free_memory(physical_memory_size_type& value);
+ static physical_memory_size_type physical_memory() { return _physical_memory; }
static void initialize_system_info();
static void rebuild_cpu_to_node_map();
diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp
index a9cabc873356..3186d97ec614 100644
--- a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp
+++ b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp
@@ -670,8 +670,8 @@ jlong CgroupSubsystem::memory_limit_in_bytes() {
if (!memory_limit->should_check_metric()) {
return memory_limit->value();
}
- jlong phys_mem = os::Linux::physical_memory();
- log_trace(os, container)("total physical memory: " JLONG_FORMAT, phys_mem);
+ julong phys_mem = static_cast(os::Linux::physical_memory());
+ log_trace(os, container)("total physical memory: " JULONG_FORMAT, phys_mem);
jlong mem_limit = contrl->controller()->read_memory_limit_in_bytes(phys_mem);
// Update cached metric to avoid re-reading container settings too often
memory_limit->set_value(mem_limit, OSCONTAINER_CACHE_TIMEOUT);
@@ -841,19 +841,19 @@ jlong CgroupController::limit_from_str(char* limit_str) {
// CgroupSubsystem implementations
jlong CgroupSubsystem::memory_and_swap_limit_in_bytes() {
- julong phys_mem = os::Linux::physical_memory();
+ julong phys_mem = static_cast(os::Linux::physical_memory());
julong host_swap = os::Linux::host_swap();
return memory_controller()->controller()->memory_and_swap_limit_in_bytes(phys_mem, host_swap);
}
jlong CgroupSubsystem::memory_and_swap_usage_in_bytes() {
- julong phys_mem = os::Linux::physical_memory();
+ julong phys_mem = static_cast(os::Linux::physical_memory());
julong host_swap = os::Linux::host_swap();
return memory_controller()->controller()->memory_and_swap_usage_in_bytes(phys_mem, host_swap);
}
jlong CgroupSubsystem::memory_soft_limit_in_bytes() {
- julong phys_mem = os::Linux::physical_memory();
+ julong phys_mem = static_cast(os::Linux::physical_memory());
return memory_controller()->controller()->memory_soft_limit_in_bytes(phys_mem);
}
@@ -894,6 +894,6 @@ jlong CgroupSubsystem::cpu_usage_in_micros() {
}
void CgroupSubsystem::print_version_specific_info(outputStream* st) {
- julong phys_mem = os::Linux::physical_memory();
+ julong phys_mem = static_cast(os::Linux::physical_memory());
memory_controller()->controller()->print_version_specific_info(st, phys_mem);
}
diff --git a/src/hotspot/os/linux/cgroupUtil_linux.cpp b/src/hotspot/os/linux/cgroupUtil_linux.cpp
index b52ef87dcaee..72dda36504d3 100644
--- a/src/hotspot/os/linux/cgroupUtil_linux.cpp
+++ b/src/hotspot/os/linux/cgroupUtil_linux.cpp
@@ -65,7 +65,7 @@ void CgroupUtil::adjust_controller(CgroupMemoryController* mem) {
char* cg_path = os::strdup(orig);
char* last_slash;
assert(cg_path[0] == '/', "cgroup path must start with '/'");
- julong phys_mem = os::Linux::physical_memory();
+ julong phys_mem = static_cast(os::Linux::physical_memory());
char* limit_cg_path = nullptr;
jlong limit = mem->read_memory_limit_in_bytes(phys_mem);
jlong lowest_limit = limit < 0 ? phys_mem : limit;
diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp
index 42cbfdf72d61..87df7c5b66cf 100644
--- a/src/hotspot/os/linux/os_linux.cpp
+++ b/src/hotspot/os/linux/os_linux.cpp
@@ -157,7 +157,7 @@ enum CoredumpFilterBit {
////////////////////////////////////////////////////////////////////////////////
// global variables
-julong os::Linux::_physical_memory = 0;
+physical_memory_size_type os::Linux::_physical_memory = 0;
address os::Linux::_initial_thread_stack_bottom = nullptr;
uintptr_t os::Linux::_initial_thread_stack_size = 0;
@@ -232,15 +232,16 @@ julong os::Linux::available_memory_in_container() {
return avail_mem;
}
-julong os::available_memory() {
- return Linux::available_memory();
+bool os::available_memory(physical_memory_size_type& value) {
+ return Linux::available_memory(value);
}
-julong os::Linux::available_memory() {
+bool os::Linux::available_memory(physical_memory_size_type& value) {
julong avail_mem = available_memory_in_container();
if (avail_mem != static_cast(-1L)) {
log_trace(os)("available container memory: " JULONG_FORMAT, avail_mem);
- return avail_mem;
+ value = static_cast(avail_mem);
+ return true;
}
FILE *fp = os::fopen("/proc/meminfo", "r");
@@ -255,66 +256,88 @@ julong os::Linux::available_memory() {
fclose(fp);
}
if (avail_mem == static_cast(-1L)) {
- avail_mem = free_memory();
+ physical_memory_size_type free_mem = 0;
+ if (!free_memory(free_mem)) {
+ return false;
+ }
+ avail_mem = static_cast(free_mem);
}
log_trace(os)("available memory: " JULONG_FORMAT, avail_mem);
- return avail_mem;
+ value = static_cast(avail_mem);
+ return true;
}
-julong os::free_memory() {
- return Linux::free_memory();
+bool os::free_memory(physical_memory_size_type& value) {
+ return Linux::free_memory(value);
}
-julong os::Linux::free_memory() {
+bool os::Linux::free_memory(physical_memory_size_type& value) {
// values in struct sysinfo are "unsigned long"
struct sysinfo si;
julong free_mem = available_memory_in_container();
if (free_mem != static_cast(-1L)) {
log_trace(os)("free container memory: " JULONG_FORMAT, free_mem);
- return free_mem;
+ value = static_cast(free_mem);
+ return true;
}
- sysinfo(&si);
+ int ret = sysinfo(&si);
+ if (ret != 0) {
+ return false;
+ }
free_mem = (julong)si.freeram * si.mem_unit;
log_trace(os)("free memory: " JULONG_FORMAT, free_mem);
- return free_mem;
+ value = static_cast(free_mem);
+ return true;
}
-jlong os::total_swap_space() {
+bool os::total_swap_space(physical_memory_size_type& value) {
if (OSContainer::is_containerized()) {
- if (OSContainer::memory_limit_in_bytes() > 0) {
- return (jlong)(OSContainer::memory_and_swap_limit_in_bytes() - OSContainer::memory_limit_in_bytes());
+ jlong memory_and_swap_limit_in_bytes = OSContainer::memory_and_swap_limit_in_bytes();
+ jlong memory_limit_in_bytes = OSContainer::memory_limit_in_bytes();
+ if (memory_limit_in_bytes > 0 && memory_and_swap_limit_in_bytes > 0) {
+ value = static_cast(memory_and_swap_limit_in_bytes - memory_limit_in_bytes);
+ return true;
}
- }
+ } // fallback to the host swap space if the container did return the unbound value of -1
struct sysinfo si;
int ret = sysinfo(&si);
if (ret != 0) {
- return -1;
+ assert(false, "sysinfo failed in total_swap_space(): %s", os::strerror(errno));
+ return false;
}
- return (jlong)(si.totalswap * si.mem_unit);
+ value = static_cast(si.totalswap) * si.mem_unit;
+ return true;
}
-static jlong host_free_swap() {
+static bool host_free_swap_f(physical_memory_size_type& value) {
struct sysinfo si;
int ret = sysinfo(&si);
if (ret != 0) {
- return -1;
+ assert(false, "sysinfo failed in host_free_swap_f(): %s", os::strerror(errno));
+ return false;
}
- return (jlong)(si.freeswap * si.mem_unit);
+ value = static_cast(si.freeswap) * si.mem_unit;
+ return true;
}
-jlong os::free_swap_space() {
+bool os::free_swap_space(physical_memory_size_type& value) {
// os::total_swap_space() might return the containerized limit which might be
// less than host_free_swap(). The upper bound of free swap needs to be the lower of the two.
- jlong host_free_swap_val = MIN2(os::total_swap_space(), host_free_swap());
- assert(host_free_swap_val >= 0, "sysinfo failed?");
+ physical_memory_size_type total_swap_space = 0;
+ physical_memory_size_type host_free_swap = 0;
+ if (!os::total_swap_space(total_swap_space) || !host_free_swap_f(host_free_swap)) {
+ return false;
+ }
+ physical_memory_size_type host_free_swap_val = MIN2(total_swap_space, host_free_swap);
if (OSContainer::is_containerized()) {
jlong mem_swap_limit = OSContainer::memory_and_swap_limit_in_bytes();
jlong mem_limit = OSContainer::memory_limit_in_bytes();
if (mem_swap_limit >= 0 && mem_limit >= 0) {
jlong delta_limit = mem_swap_limit - mem_limit;
if (delta_limit <= 0) {
- return 0;
+ value = 0;
+ return true;
}
jlong mem_swap_usage = OSContainer::memory_and_swap_usage_in_bytes();
jlong mem_usage = OSContainer::memory_usage_in_bytes();
@@ -322,30 +345,31 @@ jlong os::free_swap_space() {
jlong delta_usage = mem_swap_usage - mem_usage;
if (delta_usage >= 0) {
jlong free_swap = delta_limit - delta_usage;
- return free_swap >= 0 ? free_swap : 0;
+ value = free_swap >= 0 ? static_cast(free_swap) : 0;
+ return true;
}
}
}
// unlimited or not supported. Fall through to return host value
log_trace(os,container)("os::free_swap_space: container_swap_limit=" JLONG_FORMAT
- " container_mem_limit=" JLONG_FORMAT " returning host value: " JLONG_FORMAT,
+ " container_mem_limit=" JLONG_FORMAT " returning host value: " PHYS_MEM_TYPE_FORMAT,
mem_swap_limit, mem_limit, host_free_swap_val);
}
- return host_free_swap_val;
+ value = host_free_swap_val;
+ return true;
}
-julong os::physical_memory() {
- jlong phys_mem = 0;
+physical_memory_size_type os::physical_memory() {
if (OSContainer::is_containerized()) {
jlong mem_limit;
if ((mem_limit = OSContainer::memory_limit_in_bytes()) > 0) {
log_trace(os)("total container memory: " JLONG_FORMAT, mem_limit);
- return mem_limit;
+ return static_cast(mem_limit);
}
}
- phys_mem = Linux::physical_memory();
- log_trace(os)("total system memory: " JLONG_FORMAT, phys_mem);
+ physical_memory_size_type phys_mem = Linux::physical_memory();
+ log_trace(os)("total system memory: " PHYS_MEM_TYPE_FORMAT, phys_mem);
return phys_mem;
}
@@ -527,7 +551,7 @@ void os::Linux::initialize_system_info() {
fclose(fp);
}
}
- _physical_memory = (julong)sysconf(_SC_PHYS_PAGES) * (julong)sysconf(_SC_PAGESIZE);
+ _physical_memory = static_cast(sysconf(_SC_PHYS_PAGES)) * static_cast(sysconf(_SC_PAGESIZE));
assert(processor_count() > 0, "linux error");
}
@@ -1929,6 +1953,8 @@ void * os::Linux::dlopen_helper(const char *filename, char *ebuf, int ebuflen) {
assert(rtn == 0, "fegetenv must succeed");
#endif // IA32
+ Events::log_dll_message(nullptr, "Attempting to load shared library %s", filename);
+
void* result;
JFR_ONLY(NativeLibraryLoadEvent load_event(filename, &result);)
result = ::dlopen(filename, RTLD_LAZY);
@@ -2597,10 +2623,13 @@ void os::print_memory_info(outputStream* st) {
struct sysinfo si;
int ret = sysinfo(&si);
assert(ret == 0, "sysinfo failed: %s", os::strerror(errno));
- st->print(", physical " UINT64_FORMAT "k",
- os::physical_memory() >> 10);
- st->print("(" UINT64_FORMAT "k free)",
- os::available_memory() >> 10);
+ physical_memory_size_type phys_mem = physical_memory();
+ st->print(", physical " PHYS_MEM_TYPE_FORMAT "k",
+ phys_mem >> 10);
+ physical_memory_size_type avail_mem = 0;
+ (void)os::available_memory(avail_mem);
+ st->print("(" PHYS_MEM_TYPE_FORMAT "k free)",
+ avail_mem >> 10);
if (ret == 0) {
st->print(", swap " UINT64_FORMAT "k",
((jlong)si.totalswap * si.mem_unit) >> 10);
diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp
index 4e208a11300e..e2bd8eb3d31f 100644
--- a/src/hotspot/os/linux/os_linux.hpp
+++ b/src/hotspot/os/linux/os_linux.hpp
@@ -50,11 +50,11 @@ class os::Linux {
protected:
- static julong _physical_memory;
+ static physical_memory_size_type _physical_memory;
static pthread_t _main_thread;
- static julong available_memory();
- static julong free_memory();
+ static bool available_memory(physical_memory_size_type& value);
+ static bool free_memory(physical_memory_size_type& value);
static void initialize_system_info();
@@ -117,7 +117,7 @@ class os::Linux {
static address initial_thread_stack_bottom(void) { return _initial_thread_stack_bottom; }
static uintptr_t initial_thread_stack_size(void) { return _initial_thread_stack_size; }
- static julong physical_memory() { return _physical_memory; }
+ static physical_memory_size_type physical_memory() { return _physical_memory; }
static julong host_swap();
static intptr_t* ucontext_get_sp(const ucontext_t* uc);
diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp
index e3483781794e..3deb7efeb9bc 100644
--- a/src/hotspot/os/posix/perfMemory_posix.cpp
+++ b/src/hotspot/os/posix/perfMemory_posix.cpp
@@ -111,6 +111,10 @@ static void save_memory_to_file(char* addr, size_t size) {
result = ::close(fd);
if (result == OS_ERR) {
warning("Could not close %s: %s\n", destfile, os::strerror(errno));
+ } else {
+ if (!successful_write) {
+ remove(destfile);
+ }
}
}
FREE_C_HEAP_ARRAY(char, destfile);
@@ -953,6 +957,7 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size
warning("Insufficient space for shared memory file: %s/%s\n", dirname, filename);
}
result = OS_ERR;
+ remove(filename);
break;
}
}
diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp
index f730e54ed587..e219655815aa 100644
--- a/src/hotspot/os/windows/os_windows.cpp
+++ b/src/hotspot/os/windows/os_windows.cpp
@@ -848,39 +848,56 @@ jlong os::elapsed_frequency() {
}
-julong os::available_memory() {
- return win32::available_memory();
+bool os::available_memory(physical_memory_size_type& value) {
+ return win32::available_memory(value);
}
-julong os::free_memory() {
- return win32::available_memory();
+bool os::free_memory(physical_memory_size_type& value) {
+ return win32::available_memory(value);
}
-julong os::win32::available_memory() {
+bool os::win32::available_memory(physical_memory_size_type& value) {
// Use GlobalMemoryStatusEx() because GlobalMemoryStatus() may return incorrect
// value if total memory is larger than 4GB
MEMORYSTATUSEX ms;
ms.dwLength = sizeof(ms);
- GlobalMemoryStatusEx(&ms);
-
- return (julong)ms.ullAvailPhys;
+ BOOL res = GlobalMemoryStatusEx(&ms);
+ if (res == TRUE) {
+ value = static_cast(ms.ullAvailPhys);
+ return true;
+ } else {
+ assert(false, "GlobalMemoryStatusEx failed in os::win32::available_memory(): %lu", ::GetLastError());
+ return false;
+ }
}
-jlong os::total_swap_space() {
+bool os::total_swap_space(physical_memory_size_type& value) {
MEMORYSTATUSEX ms;
ms.dwLength = sizeof(ms);
- GlobalMemoryStatusEx(&ms);
- return (jlong) ms.ullTotalPageFile;
+ BOOL res = GlobalMemoryStatusEx(&ms);
+ if (res == TRUE) {
+ value = static_cast(ms.ullTotalPageFile);
+ return true;
+ } else {
+ assert(false, "GlobalMemoryStatusEx failed in os::total_swap_space(): %lu", ::GetLastError());
+ return false;
+ }
}
-jlong os::free_swap_space() {
+bool os::free_swap_space(physical_memory_size_type& value) {
MEMORYSTATUSEX ms;
ms.dwLength = sizeof(ms);
- GlobalMemoryStatusEx(&ms);
- return (jlong) ms.ullAvailPageFile;
+ BOOL res = GlobalMemoryStatusEx(&ms);
+ if (res == TRUE) {
+ value = static_cast(ms.ullAvailPageFile);
+ return true;
+ } else {
+ assert(false, "GlobalMemoryStatusEx failed in os::free_swap_space(): %lu", ::GetLastError());
+ return false;
+ }
}
-julong os::physical_memory() {
+physical_memory_size_type os::physical_memory() {
return win32::physical_memory();
}
@@ -1914,6 +1931,8 @@ void * os::dll_load_utf8(const char *utf8_name, char *ebuf, int ebuflen) {
void * os::dll_load(const char *name, char *ebuf, int ebuflen) {
log_info(os)("attempting shared library load of %s", name);
+ Events::log_dll_message(nullptr, "Attempting to load shared library %s", name);
+
void* result;
JFR_ONLY(NativeLibraryLoadEvent load_event(name, &result);)
result = LoadLibrary(name);
@@ -4107,25 +4126,25 @@ int os::current_process_id() {
return (_initial_pid ? _initial_pid : _getpid());
}
-int os::win32::_processor_type = 0;
+int os::win32::_processor_type = 0;
// Processor level is not available on non-NT systems, use vm_version instead
-int os::win32::_processor_level = 0;
-julong os::win32::_physical_memory = 0;
+int os::win32::_processor_level = 0;
+physical_memory_size_type os::win32::_physical_memory = 0;
-bool os::win32::_is_windows_server = false;
+bool os::win32::_is_windows_server = false;
// 6573254
// Currently, the bug is observed across all the supported Windows releases,
// including the latest one (as of this writing - Windows Server 2012 R2)
-bool os::win32::_has_exit_bug = true;
+bool os::win32::_has_exit_bug = true;
-int os::win32::_major_version = 0;
-int os::win32::_minor_version = 0;
-int os::win32::_build_number = 0;
-int os::win32::_build_minor = 0;
+int os::win32::_major_version = 0;
+int os::win32::_minor_version = 0;
+int os::win32::_build_number = 0;
+int os::win32::_build_minor = 0;
-bool os::win32::_processor_group_warning_displayed = false;
-bool os::win32::_job_object_processor_group_warning_displayed = false;
+bool os::win32::_processor_group_warning_displayed = false;
+bool os::win32::_job_object_processor_group_warning_displayed = false;
void getWindowsInstallationType(char* buffer, int bufferSize) {
HKEY hKey;
@@ -4340,8 +4359,11 @@ void os::win32::initialize_system_info() {
// also returns dwAvailPhys (free physical memory bytes), dwTotalVirtual, dwAvailVirtual,
// dwMemoryLoad (% of memory in use)
- GlobalMemoryStatusEx(&ms);
- _physical_memory = ms.ullTotalPhys;
+ BOOL res = GlobalMemoryStatusEx(&ms);
+ if (res != TRUE) {
+ assert(false, "GlobalMemoryStatusEx failed in os::win32::initialize_system_info(): %lu", ::GetLastError());
+ }
+ _physical_memory = static_cast(ms.ullTotalPhys);
if (FLAG_IS_DEFAULT(MaxRAM)) {
// Adjust MaxRAM according to the maximum virtual address space available.
diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp
index 1aba43fb3d25..efb7b4149897 100644
--- a/src/hotspot/os/windows/os_windows.hpp
+++ b/src/hotspot/os/windows/os_windows.hpp
@@ -38,18 +38,18 @@ class os::win32 {
friend class os;
protected:
- static int _processor_type;
- static int _processor_level;
- static julong _physical_memory;
- static bool _is_windows_server;
- static bool _has_exit_bug;
- static bool _processor_group_warning_displayed;
- static bool _job_object_processor_group_warning_displayed;
-
- static int _major_version;
- static int _minor_version;
- static int _build_number;
- static int _build_minor;
+ static int _processor_type;
+ static int _processor_level;
+ static physical_memory_size_type _physical_memory;
+ static bool _is_windows_server;
+ static bool _has_exit_bug;
+ static bool _processor_group_warning_displayed;
+ static bool _job_object_processor_group_warning_displayed;
+
+ static int _major_version;
+ static int _minor_version;
+ static int _build_number;
+ static int _build_minor;
static void print_windows_version(outputStream* st);
static void print_uptime_info(outputStream* st);
@@ -102,9 +102,9 @@ class os::win32 {
static int processor_level() {
return _processor_level;
}
- static julong available_memory();
- static julong free_memory();
- static julong physical_memory() { return _physical_memory; }
+ static bool available_memory(physical_memory_size_type& value);
+ static bool free_memory(physical_memory_size_type& value);
+ static physical_memory_size_type physical_memory() { return _physical_memory; }
// load dll from Windows system directory or Windows directory
static HINSTANCE load_Windows_dll(const char* name, char *ebuf, int ebuflen);
diff --git a/src/hotspot/os_cpu/linux_arm/macroAssembler_linux_arm_32.cpp b/src/hotspot/os_cpu/linux_arm/macroAssembler_linux_arm_32.cpp
index e74daaa6d666..e4737191cfcd 100644
--- a/src/hotspot/os_cpu/linux_arm/macroAssembler_linux_arm_32.cpp
+++ b/src/hotspot/os_cpu/linux_arm/macroAssembler_linux_arm_32.cpp
@@ -246,9 +246,9 @@ void MacroAssembler::atomic_cas64(Register memval_lo, Register memval_hi, Regist
Label loop;
assert_different_registers(memval_lo, memval_hi, result, oldval_lo,
oldval_hi, newval_lo, newval_hi, base);
- assert(memval_hi == memval_lo + 1 && memval_lo < R9, "cmpxchg_long: illegal registers");
- assert(oldval_hi == oldval_lo + 1 && oldval_lo < R9, "cmpxchg_long: illegal registers");
- assert(newval_hi == newval_lo + 1 && newval_lo < R9, "cmpxchg_long: illegal registers");
+ assert(memval_hi == as_Register(memval_lo->encoding() + 1) && memval_lo->encoding() < R9->encoding(), "cmpxchg_long: illegal registers");
+ assert(oldval_hi == as_Register(oldval_lo->encoding() + 1) && oldval_lo->encoding() < R9->encoding(), "cmpxchg_long: illegal registers");
+ assert(newval_hi == as_Register(newval_lo->encoding() + 1) && newval_lo->encoding() < R9->encoding(), "cmpxchg_long: illegal registers");
assert(result != R10, "cmpxchg_long: illegal registers");
assert(base != R10, "cmpxchg_long: illegal registers");
diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
index ff7fce234c4c..5a84cfef7bda 100644
--- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
+++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
@@ -51,6 +51,7 @@
#include "utilities/debug.hpp"
#include "utilities/events.hpp"
#include "utilities/vmError.hpp"
+#include "runtime/vm_version.hpp"
// put OS-includes here
# include
@@ -516,6 +517,43 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
+// XSAVE constants - from Intel SDM Vol. 1, Chapter 13
+#define XSAVE_HDR_OFFSET 512
+#define XFEATURE_APX (1ULL << 19)
+
+// XSAVE header structure
+// See: Intel SDM Vol. 1, Section 13.4.2 "XSAVE Header"
+// Also: Linux kernel arch/x86/include/asm/fpu/types.h
+struct xstate_header {
+ uint64_t xfeatures;
+ uint64_t xcomp_bv;
+ uint64_t reserved[6];
+};
+
+// APX extended state - R16-R31 (16 x 64-bit registers)
+// See: Intel APX Architecture Specification
+struct apx_state {
+ uint64_t regs[16]; // r16-r31
+};
+
+static apx_state* get_apx_state(const ucontext_t* uc) {
+ uint32_t offset = VM_Version::apx_xstate_offset();
+ if (offset == 0 || uc->uc_mcontext.fpregs == nullptr) {
+ return nullptr;
+ }
+
+ char* xsave = (char*)uc->uc_mcontext.fpregs;
+ xstate_header* hdr = (xstate_header*)(xsave + XSAVE_HDR_OFFSET);
+
+ // Check if APX state is present in this context
+ if (!(hdr->xfeatures & XFEATURE_APX)) {
+ return nullptr;
+ }
+
+ return (apx_state*)(xsave + offset);
+}
+
+
void os::print_context(outputStream *st, const void *context) {
if (context == nullptr) return;
@@ -543,6 +581,14 @@ void os::print_context(outputStream *st, const void *context) {
st->print(", R14=" INTPTR_FORMAT, (intptr_t)uc->uc_mcontext.gregs[REG_R14]);
st->print(", R15=" INTPTR_FORMAT, (intptr_t)uc->uc_mcontext.gregs[REG_R15]);
st->cr();
+ // Dump APX EGPRs (R16-R31)
+ apx_state* apx = UseAPX ? get_apx_state(uc) : nullptr;
+ if (apx != nullptr) {
+ for (int i = 0; i < 16; i++) {
+ st->print("%sR%d=" INTPTR_FORMAT, (i % 4 == 0) ? "" : ", ", 16 + i, (intptr_t)apx->regs[i]);
+ if (i % 4 == 3) st->cr();
+ }
+ }
st->print( "RIP=" INTPTR_FORMAT, (intptr_t)uc->uc_mcontext.gregs[REG_RIP]);
st->print(", EFLAGS=" INTPTR_FORMAT, (intptr_t)uc->uc_mcontext.gregs[REG_EFL]);
st->print(", CSGSFS=" INTPTR_FORMAT, (intptr_t)uc->uc_mcontext.gregs[REG_CSGSFS]);
@@ -584,36 +630,44 @@ void os::print_context(outputStream *st, const void *context) {
}
void os::print_register_info(outputStream *st, const void *context, int& continuation) {
- const int register_count = AMD64_ONLY(16) NOT_AMD64(8);
+ if (context == nullptr) {
+ return;
+ }
+ const ucontext_t *uc = (const ucontext_t*)context;
+ apx_state* apx = UseAPX ? get_apx_state(uc) : nullptr;
+
+ const int register_count = AMD64_ONLY(16 + (apx != nullptr ? 16 : 0)) NOT_AMD64(8);
int n = continuation;
assert(n >= 0 && n <= register_count, "Invalid continuation value");
- if (context == nullptr || n == register_count) {
+ if (n == register_count) {
return;
}
- const ucontext_t *uc = (const ucontext_t*)context;
while (n < register_count) {
// Update continuation with next index before printing location
continuation = n + 1;
+
+ if (n < 16) {
+ // Standard registers (RAX-R15)
# define CASE_PRINT_REG(n, str, id) case n: st->print(str); print_location(st, uc->uc_mcontext.gregs[REG_##id]);
- switch (n) {
+ switch (n) {
#ifdef AMD64
- CASE_PRINT_REG( 0, "RAX=", RAX); break;
- CASE_PRINT_REG( 1, "RBX=", RBX); break;
- CASE_PRINT_REG( 2, "RCX=", RCX); break;
- CASE_PRINT_REG( 3, "RDX=", RDX); break;
- CASE_PRINT_REG( 4, "RSP=", RSP); break;
- CASE_PRINT_REG( 5, "RBP=", RBP); break;
- CASE_PRINT_REG( 6, "RSI=", RSI); break;
- CASE_PRINT_REG( 7, "RDI=", RDI); break;
- CASE_PRINT_REG( 8, "R8 =", R8); break;
- CASE_PRINT_REG( 9, "R9 =", R9); break;
- CASE_PRINT_REG(10, "R10=", R10); break;
- CASE_PRINT_REG(11, "R11=", R11); break;
- CASE_PRINT_REG(12, "R12=", R12); break;
- CASE_PRINT_REG(13, "R13=", R13); break;
- CASE_PRINT_REG(14, "R14=", R14); break;
- CASE_PRINT_REG(15, "R15=", R15); break;
+ CASE_PRINT_REG( 0, "RAX=", RAX); break;
+ CASE_PRINT_REG( 1, "RBX=", RBX); break;
+ CASE_PRINT_REG( 2, "RCX=", RCX); break;
+ CASE_PRINT_REG( 3, "RDX=", RDX); break;
+ CASE_PRINT_REG( 4, "RSP=", RSP); break;
+ CASE_PRINT_REG( 5, "RBP=", RBP); break;
+ CASE_PRINT_REG( 6, "RSI=", RSI); break;
+ CASE_PRINT_REG( 7, "RDI=", RDI); break;
+ CASE_PRINT_REG( 8, "R8 =", R8); break;
+ CASE_PRINT_REG( 9, "R9 =", R9); break;
+ CASE_PRINT_REG(10, "R10=", R10); break;
+ CASE_PRINT_REG(11, "R11=", R11); break;
+ CASE_PRINT_REG(12, "R12=", R12); break;
+ CASE_PRINT_REG(13, "R13=", R13); break;
+ CASE_PRINT_REG(14, "R14=", R14); break;
+ CASE_PRINT_REG(15, "R15=", R15); break;
#else
CASE_PRINT_REG(0, "EAX=", EAX); break;
CASE_PRINT_REG(1, "EBX=", EBX); break;
@@ -624,8 +678,13 @@ void os::print_register_info(outputStream *st, const void *context, int& continu
CASE_PRINT_REG(6, "ESI=", ESI); break;
CASE_PRINT_REG(7, "EDI=", EDI); break;
#endif // AMD64
- }
+ }
# undef CASE_PRINT_REG
+ } else {
+ // APX extended general purpose registers (R16-R31)
+ st->print("R%d=", n);
+ print_location(st, apx->regs[n - 16]);
+ }
++n;
}
}
diff --git a/src/hotspot/share/cds/aotArtifactFinder.cpp b/src/hotspot/share/cds/aotArtifactFinder.cpp
index d8999774a53b..dada68447948 100644
--- a/src/hotspot/share/cds/aotArtifactFinder.cpp
+++ b/src/hotspot/share/cds/aotArtifactFinder.cpp
@@ -1,5 +1,5 @@
/*
- * 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
@@ -31,6 +31,7 @@
#include "cds/heapShared.hpp"
#include "cds/lambdaProxyClassDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
+#include "classfile/vmClasses.hpp"
#include "logging/log.hpp"
#include "memory/metaspaceClosure.hpp"
#include "oops/instanceKlass.hpp"
@@ -168,6 +169,7 @@ void AOTArtifactFinder::find_artifacts() {
end_scanning_for_oops();
TrainingData::cleanup_training_data();
+ check_critical_classes();
}
void AOTArtifactFinder::start_scanning_for_oops() {
@@ -228,6 +230,7 @@ void AOTArtifactFinder::add_cached_instance_class(InstanceKlass* ik) {
bool created;
_seen_classes->put_if_absent(ik, &created);
if (created) {
+ check_critical_class(ik);
append_to_all_cached_classes(ik);
// All super types must be added.
@@ -300,3 +303,25 @@ void AOTArtifactFinder::all_cached_classes_do(MetaspaceClosure* it) {
it->push(_all_cached_classes->adr_at(i));
}
}
+
+void AOTArtifactFinder::check_critical_classes() {
+ if (CDSConfig::is_dumping_static_archive()) {
+ // vmClasses are store in the AOT cache (or AOT config file, or static archive).
+ // If any of the vmClasses is excluded, (usually due to incompatible JVMTI agent),
+ // the resulting cache/config/archive is unusable.
+ for (auto id : EnumRange{}) {
+ check_critical_class(vmClasses::klass_at(id));
+ }
+ }
+}
+
+void AOTArtifactFinder::check_critical_class(InstanceKlass* ik) {
+ if (SystemDictionaryShared::is_excluded_class(ik)) {
+ ResourceMark rm;
+ const char* msg = err_msg("Critical class %s has been excluded. %s cannot be written.",
+ ik->external_name(),
+ CDSConfig::type_of_archive_being_written());
+ MetaspaceShared::unrecoverable_writing_error(msg);
+ }
+}
+
diff --git a/src/hotspot/share/cds/aotArtifactFinder.hpp b/src/hotspot/share/cds/aotArtifactFinder.hpp
index 5d293f20af07..48919b1295d0 100644
--- a/src/hotspot/share/cds/aotArtifactFinder.hpp
+++ b/src/hotspot/share/cds/aotArtifactFinder.hpp
@@ -1,5 +1,5 @@
/*
- * 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
@@ -39,7 +39,7 @@ class TypeArrayKlass;
// It also decides what Klasses must be cached in aot-initialized state.
//
// ArchiveBuilder uses [1] as roots to scan for all MetaspaceObjs that need to be cached.
-// ArchiveHeapWriter uses [2] to create an image of the archived heap.
+// HeapShared uses [2] to create an image of the archived heap.
//
// [1] is stored in _all_cached_classes in aotArtifactFinder.cpp.
// [2] is stored in HeapShared::archived_object_cache().
@@ -80,12 +80,14 @@ class AOTArtifactFinder : AllStatic {
static void add_cached_type_array_class(TypeArrayKlass* tak);
static void add_cached_instance_class(InstanceKlass* ik);
static void append_to_all_cached_classes(Klass* k);
+ static void check_critical_class(InstanceKlass* ik);
public:
static void initialize();
static void find_artifacts();
static void add_cached_class(Klass* k);
static void add_aot_inited_class(InstanceKlass* ik);
static void all_cached_classes_do(MetaspaceClosure* it);
+ static void check_critical_classes();
static void dispose();
};
diff --git a/src/hotspot/share/cds/aotClassLocation.cpp b/src/hotspot/share/cds/aotClassLocation.cpp
index b662c5a1b478..ed23f255173b 100644
--- a/src/hotspot/share/cds/aotClassLocation.cpp
+++ b/src/hotspot/share/cds/aotClassLocation.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -432,7 +432,8 @@ bool AOTClassLocation::check(const char* runtime_path, bool has_aot_linked_class
bool size_differs = _filesize != st.st_size;
bool time_differs = _check_time && (_timestamp != st.st_mtime);
if (size_differs || time_differs) {
- aot_log_warning(aot)("This file is not the one used while building the shared archive file: '%s'%s%s",
+ aot_log_warning(aot)("This file is not the one used while building the %s: '%s'%s%s",
+ CDSConfig::type_of_archive_being_loaded(),
runtime_path,
time_differs ? ", timestamp has changed" : "",
size_differs ? ", size has changed" : "");
@@ -454,6 +455,13 @@ void AOTClassLocationConfig::dumptime_init(JavaThread* current) {
java_lang_Throwable::print(current->pending_exception(), tty);
vm_exit_during_initialization("AOTClassLocationConfig::dumptime_init_helper() failed unexpectedly");
}
+
+ if (CDSConfig::is_dumping_final_static_archive()) {
+ // The _max_used_index is usually updated by ClassLoader::record_result(). However,
+ // when dumping the final archive, the classes are loaded from their images in
+ // the AOT config file, so we don't go through ClassLoader::record_result().
+ dumptime_update_max_used_index(runtime()->_max_used_index); // Same value as recorded in the training run.
+ }
}
void AOTClassLocationConfig::dumptime_init_helper(TRAPS) {
diff --git a/src/hotspot/share/cds/aotConstantPoolResolver.cpp b/src/hotspot/share/cds/aotConstantPoolResolver.cpp
index 6ab63418e09e..3ea0c76f8702 100644
--- a/src/hotspot/share/cds/aotConstantPoolResolver.cpp
+++ b/src/hotspot/share/cds/aotConstantPoolResolver.cpp
@@ -81,6 +81,7 @@ bool AOTConstantPoolResolver::is_resolution_deterministic(ConstantPool* cp, int
bool AOTConstantPoolResolver::is_class_resolution_deterministic(InstanceKlass* cp_holder, Klass* resolved_class) {
assert(!is_in_archivebuilder_buffer(cp_holder), "sanity");
assert(!is_in_archivebuilder_buffer(resolved_class), "sanity");
+ assert_at_safepoint(); // try_add_candidate() is called below and requires to be at safepoint.
if (resolved_class->is_instance_klass()) {
InstanceKlass* ik = InstanceKlass::cast(resolved_class);
@@ -285,7 +286,15 @@ void AOTConstantPoolResolver::maybe_resolve_fmi_ref(InstanceKlass* ik, Method* m
break;
case Bytecodes::_invokehandle:
- InterpreterRuntime::cds_resolve_invokehandle(raw_index, cp, CHECK);
+ if (CDSConfig::is_dumping_method_handles()) {
+ ResolvedMethodEntry* method_entry = cp->resolved_method_entry_at(raw_index);
+ int cp_index = method_entry->constant_pool_index();
+ Symbol* sig = cp->uncached_signature_ref_at(cp_index);
+ Klass* k;
+ if (check_methodtype_signature(cp(), sig, &k, true)) {
+ InterpreterRuntime::cds_resolve_invokehandle(raw_index, cp, CHECK);
+ }
+ }
break;
default:
@@ -339,7 +348,7 @@ void AOTConstantPoolResolver::preresolve_indy_cp_entries(JavaThread* current, In
// Check the MethodType signatures used by parameters to the indy BSMs. Make sure we don't
// use types that have been excluded, or else we might end up creating MethodTypes that cannot be stored
// in the AOT cache.
-bool AOTConstantPoolResolver::check_methodtype_signature(ConstantPool* cp, Symbol* sig, Klass** return_type_ret) {
+bool AOTConstantPoolResolver::check_methodtype_signature(ConstantPool* cp, Symbol* sig, Klass** return_type_ret, bool is_invokehandle) {
ResourceMark rm;
for (SignatureStream ss(sig); !ss.is_done(); ss.next()) {
if (ss.is_reference()) {
@@ -352,11 +361,18 @@ bool AOTConstantPoolResolver::check_methodtype_signature(ConstantPool* cp, Symbo
if (SystemDictionaryShared::should_be_excluded(k)) {
if (log_is_enabled(Warning, aot, resolve)) {
ResourceMark rm;
- log_warning(aot, resolve)("Cannot aot-resolve Lambda proxy because %s is excluded", k->external_name());
+ log_warning(aot, resolve)("Cannot aot-resolve %s because %s is excluded",
+ is_invokehandle ? "invokehandle" : "Lambda proxy",
+ k->external_name());
}
return false;
}
+ // cp->pool_holder() must be able to resolve k in production run
+ precond(CDSConfig::is_dumping_aot_linked_classes());
+ precond(SystemDictionaryShared::is_builtin_loader(cp->pool_holder()->class_loader_data()));
+ precond(SystemDictionaryShared::is_builtin_loader(k->class_loader_data()));
+
if (ss.at_return_type() && return_type_ret != nullptr) {
*return_type_ret = k;
}
@@ -414,11 +430,44 @@ bool AOTConstantPoolResolver::check_lambda_metafactory_methodhandle_arg(Constant
return false;
}
+ // klass and sigature of the method (no need to check the method name)
Symbol* sig = cp->method_handle_signature_ref_at(mh_index);
+ Symbol* klass_name = cp->klass_name_at(cp->method_handle_klass_index_at(mh_index));
+
if (log_is_enabled(Debug, aot, resolve)) {
ResourceMark rm;
log_debug(aot, resolve)("Checking MethodType of MethodHandle for LambdaMetafactory BSM arg %d: %s", arg_i, sig->as_C_string());
}
+
+ {
+ Klass* k = find_loaded_class(Thread::current(), cp->pool_holder()->class_loader(), klass_name);
+ if (k == nullptr) {
+ // Dumping AOT cache: all classes should have been loaded by FinalImageRecipes::load_all_classes(). k must have
+ // been a class that was excluded when FinalImageRecipes recorded all classes at the end of the training run.
+ //
+ // Dumping static CDS archive: all classes in the classlist have already been loaded, before we resolve
+ // constants. k must have been a class that was excluded when the classlist was written
+ // at the end of the training run.
+ if (log_is_enabled(Warning, aot, resolve)) {
+ ResourceMark rm;
+ log_warning(aot, resolve)("Cannot aot-resolve Lambda proxy because %s is not loaded", klass_name->as_C_string());
+ }
+ return false;
+ }
+ if (SystemDictionaryShared::should_be_excluded(k)) {
+ if (log_is_enabled(Warning, aot, resolve)) {
+ ResourceMark rm;
+ log_warning(aot, resolve)("Cannot aot-resolve Lambda proxy because %s is excluded", k->external_name());
+ }
+ return false;
+ }
+
+ // cp->pool_holder() must be able to resolve k in production run
+ precond(CDSConfig::is_dumping_aot_linked_classes());
+ precond(SystemDictionaryShared::is_builtin_loader(cp->pool_holder()->class_loader_data()));
+ precond(SystemDictionaryShared::is_builtin_loader(k->class_loader_data()));
+ }
+
return check_methodtype_signature(cp, sig);
}
diff --git a/src/hotspot/share/cds/aotConstantPoolResolver.hpp b/src/hotspot/share/cds/aotConstantPoolResolver.hpp
index 89d9d5c24764..6ad762b4121d 100644
--- a/src/hotspot/share/cds/aotConstantPoolResolver.hpp
+++ b/src/hotspot/share/cds/aotConstantPoolResolver.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 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
@@ -74,7 +74,10 @@ class AOTConstantPoolResolver : AllStatic {
static void maybe_resolve_fmi_ref(InstanceKlass* ik, Method* m, Bytecodes::Code bc, int raw_index,
GrowableArray* resolve_fmi_list, TRAPS);
- static bool check_methodtype_signature(ConstantPool* cp, Symbol* sig, Klass** return_type_ret = nullptr);
+public:
+ static bool check_methodtype_signature(ConstantPool* cp, Symbol* sig, Klass** return_type_ret = nullptr, bool is_invokehandle = false);
+
+private:
static bool check_lambda_metafactory_signature(ConstantPool* cp, Symbol* sig);
static bool check_lambda_metafactory_methodtype_arg(ConstantPool* cp, int bsms_attribute_index, int arg_i);
static bool check_lambda_metafactory_methodhandle_arg(ConstantPool* cp, int bsms_attribute_index, int arg_i);
diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp
index 5f197f70ecca..cd7386e31e87 100644
--- a/src/hotspot/share/cds/archiveBuilder.cpp
+++ b/src/hotspot/share/cds/archiveBuilder.cpp
@@ -1504,7 +1504,14 @@ class ArchiveBuilder::CDSMapLogger : AllStatic {
st->print(PTR_FORMAT " ", p2i(requested_obj));
}
if (UseCompressedOops) {
- st->print("(0x%08x) ", CompressedOops::narrow_oop_value(requested_obj));
+ uint32_t narrow_oop;
+ if (ArchiveHeapWriter::is_writing_deterministic_heap()) {
+ // Don't decode in case of deterministic heap.
+ narrow_oop = checked_cast(cast_from_oop(requested_obj));
+ } else {
+ narrow_oop = CompressedOops::narrow_oop_value(requested_obj);
+ }
+ st->print("(0x%08x) ", narrow_oop);
}
if (source_oop->is_array()) {
int array_len = arrayOop(source_oop)->length();
diff --git a/src/hotspot/share/cds/archiveHeapWriter.cpp b/src/hotspot/share/cds/archiveHeapWriter.cpp
index ee1e334e84bf..c4965be8ed12 100644
--- a/src/hotspot/share/cds/archiveHeapWriter.cpp
+++ b/src/hotspot/share/cds/archiveHeapWriter.cpp
@@ -52,7 +52,7 @@
GrowableArrayCHeap* ArchiveHeapWriter::_buffer = nullptr;
-// The following are offsets from buffer_bottom()
+bool ArchiveHeapWriter::_is_writing_deterministic_heap = false;
size_t ArchiveHeapWriter::_buffer_used;
// Heap root segments
@@ -91,6 +91,45 @@ void ArchiveHeapWriter::init() {
_source_objs = new GrowableArrayCHeap(10000);
guarantee(MIN_GC_REGION_ALIGNMENT <= G1HeapRegion::min_region_size_in_words() * HeapWordSize, "must be");
+
+ if (CDSConfig::old_cds_flags_used()) {
+ // With the old CDS workflow, we can guatantee determninistic output: given
+ // the same classlist file, we can generate the same static CDS archive.
+ // To ensure determinism, we always use the same compressed oop encoding
+ // (zero-based, no shift). See set_requested_address_range().
+ _is_writing_deterministic_heap = true;
+ } else {
+ // Determninistic output is not supported by the new AOT workflow, so
+ // we don't force the (zero-based, no shift) encoding. This way, it is more
+ // likely that we can avoid oop relocation in the production run.
+ _is_writing_deterministic_heap = false;
+ }
+ }
+}
+
+// For ArchiveHeapWriter::narrow_oop_{mode, base, shift}(), see comments
+// in ArchiveHeapWriter::set_requested_address_range(),
+CompressedOops::Mode ArchiveHeapWriter::narrow_oop_mode() {
+ if (is_writing_deterministic_heap()) {
+ return CompressedOops::UnscaledNarrowOop;
+ } else {
+ return CompressedOops::mode();
+ }
+}
+
+address ArchiveHeapWriter::narrow_oop_base() {
+ if (is_writing_deterministic_heap()) {
+ return (address)0;
+ } else {
+ return CompressedOops::base();
+ }
+}
+
+int ArchiveHeapWriter::narrow_oop_shift() {
+ if (is_writing_deterministic_heap()) {
+ return 0;
+ } else {
+ return CompressedOops::shift();
}
}
@@ -103,7 +142,7 @@ void ArchiveHeapWriter::write(GrowableArrayCHeap* roots,
assert(CDSConfig::is_dumping_heap(), "sanity");
allocate_buffer();
copy_source_objs_to_buffer(roots);
- set_requested_address(heap_info);
+ set_requested_address_range(heap_info);
relocate_embedded_oops(roots, heap_info);
}
@@ -465,14 +504,55 @@ size_t ArchiveHeapWriter::copy_one_source_obj_to_buffer(oop src_obj) {
return buffered_obj_offset;
}
-void ArchiveHeapWriter::set_requested_address(ArchiveHeapInfo* info) {
+// Set the range [_requested_bottom, _requested_top), the requested address range of all
+// the archived heap objects in the production run.
+//
+// (1) UseCompressedOops == true && !is_writing_deterministic_heap()
+//
+// The archived objects are stored using the COOPS encoding of the assembly phase.
+// We pick a range within the heap used by the assembly phase.
+//
+// In the production run, if different COOPS encodings are used:
+// - The heap contents needs to be relocated.
+//
+// (2) UseCompressedOops == true && is_writing_deterministic_heap()
+//
+// We always use zero-based, zero-shift encoding. _requested_top is aligned to 0x10000000.
+//
+// (3) UseCompressedOops == false:
+//
+// In the production run, the heap range is usually picked (randomly) by the OS, so we
+// will almost always need to perform relocation, regardless of how we pick the requested
+// address range.
+//
+// So we just hard code it to NOCOOPS_REQUESTED_BASE.
+//
+void ArchiveHeapWriter::set_requested_address_range(ArchiveHeapInfo* info) {
assert(!info->is_used(), "only set once");
size_t heap_region_byte_size = _buffer_used;
assert(heap_region_byte_size > 0, "must archived at least one object!");
if (UseCompressedOops) {
- if (UseG1GC) {
+ if (is_writing_deterministic_heap()) {
+ // Pick a heap range so that requested addresses can be encoded with zero-base/no shift.
+ // We align the requested bottom to at least 1 MB: if the production run uses G1 with a small
+ // heap (e.g., -Xmx256m), it's likely that we can map the archived objects at the
+ // requested location to avoid relocation.
+ //
+ // For other collectors or larger heaps, relocation is unavoidable, but is usually
+ // quite cheap. If you really want to avoid relocation, use the AOT workflow instead.
+ address heap_end = (address)0x100000000;
+ size_t alignment = MAX2(MIN_GC_REGION_ALIGNMENT, 1024 * 1024);
+ if (align_up(heap_region_byte_size, alignment) >= (size_t)heap_end) {
+ log_error(aot, heap)("cached heap space is too large: %zu bytes", heap_region_byte_size);
+ MetaspaceShared::unrecoverable_writing_error();
+ }
+ _requested_bottom = align_down(heap_end - heap_region_byte_size, alignment);
+ } else if (UseG1GC) {
+ // For G1, pick the range at the top of the current heap. If the exact same heap sizes
+ // are used in the production run, it's likely that we can map the archived objects
+ // at the requested location to avoid relocation.
address heap_end = (address)G1CollectedHeap::heap()->reserved().end();
log_info(aot, heap)("Heap end = %p", heap_end);
_requested_bottom = align_down(heap_end - heap_region_byte_size, G1HeapRegion::GrainBytes);
@@ -550,7 +630,14 @@ template void ArchiveHeapWriter::relocate_field_in_buffer(T* field_
assert(source_referent != nullptr, "must be");
}
oop request_referent = source_obj_to_requested_obj(source_referent);
- store_requested_oop_in_buffer(field_addr_in_buffer, request_referent);
+ if (UseCompressedOops && is_writing_deterministic_heap()) {
+ // We use zero-based, 0-shift encoding, so the narrowOop is just the lower
+ // 32 bits of request_referent
+ intptr_t addr = cast_from_oop(request_referent);
+ *((narrowOop*)field_addr_in_buffer) = CompressedOops::narrow_oop_cast(addr);
+ } else {
+ store_requested_oop_in_buffer(field_addr_in_buffer, request_referent);
+ }
mark_oop_pointer(field_addr_in_buffer, oopmap);
}
}
@@ -754,8 +841,15 @@ void ArchiveHeapWriter::compute_ptrmap(ArchiveHeapInfo* heap_info) {
Metadata** buffered_field_addr = requested_addr_to_buffered_addr(requested_field_addr);
Metadata* native_ptr = *buffered_field_addr;
guarantee(native_ptr != nullptr, "sanity");
- guarantee(ArchiveBuilder::current()->has_been_buffered((address)native_ptr),
- "Metadata %p should have been archived", native_ptr);
+
+ if (!ArchiveBuilder::current()->has_been_archived((address)native_ptr)) {
+ ResourceMark rm;
+ LogStreamHandle(Error, aot) log;
+ log.print("Marking native pointer for oop %p (type = %s, offset = %d)",
+ cast_from_oop(src_obj), src_obj->klass()->external_name(), field_offset);
+ src_obj->print_on(&log);
+ fatal("Metadata %p should have been archived", native_ptr);
+ }
address buffered_native_ptr = ArchiveBuilder::current()->get_buffered_addr((address)native_ptr);
address requested_native_ptr = ArchiveBuilder::current()->to_requested(buffered_native_ptr);
diff --git a/src/hotspot/share/cds/archiveHeapWriter.hpp b/src/hotspot/share/cds/archiveHeapWriter.hpp
index 1e1319cccc34..87359c16fc28 100644
--- a/src/hotspot/share/cds/archiveHeapWriter.hpp
+++ b/src/hotspot/share/cds/archiveHeapWriter.hpp
@@ -28,6 +28,7 @@
#include "cds/heapShared.hpp"
#include "memory/allocation.hpp"
#include "memory/allStatic.hpp"
+#include "oops/compressedOops.hpp"
#include "oops/oopHandle.hpp"
#include "utilities/bitMap.hpp"
#include "utilities/exceptions.hpp"
@@ -87,26 +88,11 @@ class ArchiveHeapWriter : AllStatic {
// - Each archived object has a "requested address" -- at run time, if the object
// can be mapped at this address, we can avoid relocation.
//
- // The requested address is implemented differently depending on UseCompressedOops:
+ // The requested address of an archived object is essentially its buffered_addr + delta,
+ // where delta is (_requested_bottom - buffer_bottom());
//
- // UseCompressedOops == true:
- // The archived objects are stored assuming that the runtime COOPS compression
- // scheme is exactly the same as in dump time (or else a more expensive runtime relocation
- // would be needed.)
- //
- // At dump time, we assume that the runtime heap range is exactly the same as
- // in dump time. The requested addresses of the archived objects are chosen such that
- // they would occupy the top end of a G1 heap (TBD when dumping is supported by other
- // collectors. See JDK-8298614).
- //
- // UseCompressedOops == false:
- // At runtime, the heap range is usually picked (randomly) by the OS, so we will almost always
- // need to perform relocation. Hence, the goal of the "requested address" is to ensure that
- // the contents of the archived objects are deterministic. I.e., the oop fields of archived
- // objects will always point to deterministic addresses.
- //
- // For G1, the archived heap is written such that the lowest archived object is placed
- // at NOCOOPS_REQUESTED_BASE. (TBD after JDK-8298614).
+ // The requested addresses of all archived objects are within [_requested_bottom, _requested_top).
+ // See ArchiveHeapWriter::set_requested_address_range() for more info.
// ----------------------------------------------------------------------
public:
@@ -117,6 +103,15 @@ class ArchiveHeapWriter : AllStatic {
// Shenandoah heap region size can never be smaller than 256K.
static constexpr int MIN_GC_REGION_ALIGNMENT = 256 * K;
+ // The heap contents are required to be deterministic when dumping "old" CDS archives, in order
+ // to support reproducible lib/server/classes*.jsa when building the JDK.
+ static bool is_writing_deterministic_heap() { return _is_writing_deterministic_heap; }
+
+ // The oop encoding used by the archived heap objects.
+ static CompressedOops::Mode narrow_oop_mode();
+ static address narrow_oop_base();
+ static int narrow_oop_shift();
+
private:
class EmbeddedOopRelocator;
struct NativePointerInfo {
@@ -124,6 +119,7 @@ class ArchiveHeapWriter : AllStatic {
int _field_offset;
};
+ static bool _is_writing_deterministic_heap;
static GrowableArrayCHeap* _buffer;
// The number of bytes that have written into _buffer (may be smaller than _buffer->length()).
@@ -133,8 +129,8 @@ class ArchiveHeapWriter : AllStatic {
static HeapRootSegments _heap_root_segments;
// The address range of the requested location of the archived heap objects.
- static address _requested_bottom;
- static address _requested_top;
+ static address _requested_bottom; // The requested address of the lowest archived heap object
+ static address _requested_top; // The exclusive end of the highest archived heap object
static GrowableArrayCHeap* _native_pointers;
static GrowableArrayCHeap* _source_objs;
@@ -202,7 +198,7 @@ class ArchiveHeapWriter : AllStatic {
static int filler_array_length(size_t fill_bytes);
static HeapWord* init_filler_array_at_buffer_top(int array_length, size_t fill_bytes);
- static void set_requested_address(ArchiveHeapInfo* info);
+ static void set_requested_address_range(ArchiveHeapInfo* info);
static void relocate_embedded_oops(GrowableArrayCHeap* roots, ArchiveHeapInfo* info);
static void compute_ptrmap(ArchiveHeapInfo *info);
static bool is_in_requested_range(oop o);
diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp
index 80dfa5f19f33..9dd1db0c4c12 100644
--- a/src/hotspot/share/cds/filemap.cpp
+++ b/src/hotspot/share/cds/filemap.cpp
@@ -217,11 +217,13 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment,
_obj_alignment = ObjectAlignmentInBytes;
_compact_strings = CompactStrings;
_compact_headers = UseCompactObjectHeaders;
+#if INCLUDE_CDS_JAVA_HEAP
if (CDSConfig::is_dumping_heap()) {
- _narrow_oop_mode = CompressedOops::mode();
- _narrow_oop_base = CompressedOops::base();
- _narrow_oop_shift = CompressedOops::shift();
+ _narrow_oop_mode = ArchiveHeapWriter::narrow_oop_mode();
+ _narrow_oop_base = ArchiveHeapWriter::narrow_oop_base();
+ _narrow_oop_shift = ArchiveHeapWriter::narrow_oop_shift();
}
+#endif
_compressed_oops = UseCompressedOops;
_compressed_class_ptrs = UseCompressedClassPointers;
if (UseCompressedClassPointers) {
@@ -901,7 +903,7 @@ void FileMapInfo::write_region(int region, char* base, size_t size,
assert(!CDSConfig::is_dumping_dynamic_archive(), "must be");
requested_base = (char*)ArchiveHeapWriter::requested_address();
if (UseCompressedOops) {
- mapping_offset = (size_t)((address)requested_base - CompressedOops::base());
+ mapping_offset = (size_t)((address)requested_base - ArchiveHeapWriter::narrow_oop_base());
assert((mapping_offset >> CompressedOops::shift()) << CompressedOops::shift() == mapping_offset, "must be");
} else {
mapping_offset = 0; // not used with !UseCompressedOops
@@ -1605,7 +1607,7 @@ address FileMapInfo::heap_region_requested_address() {
// Runtime base = 0x4000 and shift is also 0. If we map this region at 0x5000, then
// the value P can remain 0x1200. The decoded address = (0x4000 + (0x1200 << 0)) = 0x5200,
// which is the runtime location of the referenced object.
- return /*runtime*/ (address)((uintptr_t)CompressedOops::base() + r->mapping_offset());
+ return /*runtime*/ (address)((uintptr_t)ArchiveHeapWriter::narrow_oop_base() + r->mapping_offset());
} else {
// This was the hard-coded requested base address used at dump time. With uncompressed oops,
// the heap range is assigned by the OS so we will most likely have to relocate anyway, no matter
diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp
index 06cbaf1dbe79..1e2047a27c47 100644
--- a/src/hotspot/share/cds/heapShared.cpp
+++ b/src/hotspot/share/cds/heapShared.cpp
@@ -300,6 +300,7 @@ bool HeapShared::archive_object(oop obj, oop referrer, KlassSubGraphInfo* subgra
debug_trace();
return false;
} else {
+ AOTArtifactFinder::add_cached_class(obj->klass());
count_allocation(obj->size());
ArchiveHeapWriter::add_source_obj(obj);
CachedOopInfo info = make_cached_oop_info(obj, referrer);
diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp
index f4e86aa5895a..b7b9f0ecaa2f 100644
--- a/src/hotspot/share/cds/heapShared.hpp
+++ b/src/hotspot/share/cds/heapShared.hpp
@@ -177,7 +177,7 @@ class HeapShared: AllStatic {
// Used by CDSHeapVerifier.
oop _orig_referrer;
- // The location of this object inside ArchiveHeapWriter::_buffer
+ // The location of this object inside {AOTMappedHeapWriter, AOTStreamedHeapWriter}::_buffer
size_t _buffer_offset;
// One or more fields in this object are pointing to non-null oops.
diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp
index 3d70893d98c5..75698b7c8657 100644
--- a/src/hotspot/share/classfile/classLoader.cpp
+++ b/src/hotspot/share/classfile/classLoader.cpp
@@ -1388,6 +1388,10 @@ char* ClassLoader::lookup_vm_options() {
jio_snprintf(modules_path, JVM_MAXPATHLEN, "%s%slib%smodules", Arguments::get_java_home(), fileSep, fileSep);
JImage_file =(*JImageOpen)(modules_path, &error);
if (JImage_file == nullptr) {
+ if (Arguments::has_jimage()) {
+ // The modules file exists but is unreadable or corrupt
+ vm_exit_during_initialization(err_msg("Unable to load %s", modules_path));
+ }
return nullptr;
}
diff --git a/src/hotspot/share/code/dependencies.cpp b/src/hotspot/share/code/dependencies.cpp
index 7f925388eb03..324b72f051da 100644
--- a/src/hotspot/share/code/dependencies.cpp
+++ b/src/hotspot/share/code/dependencies.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -1125,7 +1125,7 @@ class AbstractClassHierarchyWalker {
Klass* find_witness(InstanceKlass* context_type, KlassDepChange* changes = nullptr);
static void init();
- static void print_statistics();
+ NOT_PRODUCT(static void print_statistics();)
};
PerfCounter* AbstractClassHierarchyWalker::_perf_find_witness_anywhere_calls_count = nullptr;
@@ -2278,6 +2278,7 @@ bool KlassDepChange::involves_context(Klass* k) {
return is_contained;
}
+#ifndef PRODUCT
void Dependencies::print_statistics() {
AbstractClassHierarchyWalker::print_statistics();
}
@@ -2303,6 +2304,7 @@ void AbstractClassHierarchyWalker::print_statistics() {
}
}
}
+#endif
CallSiteDepChange::CallSiteDepChange(Handle call_site, Handle method_handle) :
_call_site(call_site),
diff --git a/src/hotspot/share/code/dependencies.hpp b/src/hotspot/share/code/dependencies.hpp
index d11c51a66dc6..582a08183f9c 100644
--- a/src/hotspot/share/code/dependencies.hpp
+++ b/src/hotspot/share/code/dependencies.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -649,7 +649,7 @@ class Dependencies: public ResourceObj {
};
friend class Dependencies::DepStream;
- static void print_statistics();
+ NOT_PRODUCT(static void print_statistics();)
};
diff --git a/src/hotspot/share/compiler/compilationMemoryStatistic.cpp b/src/hotspot/share/compiler/compilationMemoryStatistic.cpp
index d842bcb2b6f8..49549b1142cc 100644
--- a/src/hotspot/share/compiler/compilationMemoryStatistic.cpp
+++ b/src/hotspot/share/compiler/compilationMemoryStatistic.cpp
@@ -1010,8 +1010,10 @@ void CompilationMemoryStatistic::print_error_report(outputStream* st) {
oom_stats->print_peak_state_on(st);
st->cr();
}
- st->print_cr("Compiler Memory Statistic, 10 most expensive compilations:");
- print_all_by_size(st, false, false, 0, 10);
+ if (Thread::current_or_null_safe() != nullptr) {
+ st->print_cr("Compiler Memory Statistic, 10 most expensive compilations:");
+ print_all_by_size(st, false, false, 0, 10);
+ }
}
void CompilationMemoryStatistic::print_final_report(outputStream* st) {
diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp
index 9e6692abcacb..c31563a3c2e5 100644
--- a/src/hotspot/share/compiler/compileBroker.cpp
+++ b/src/hotspot/share/compiler/compileBroker.cpp
@@ -1060,7 +1060,9 @@ void CompileBroker::possibly_add_compiler_threads(JavaThread* THREAD) {
if (new_c2_count <= old_c2_count && new_c1_count <= old_c1_count) return;
// Now, we do the more expensive operations.
- julong free_memory = os::free_memory();
+ physical_memory_size_type free_memory = 0;
+ // Return value ignored - defaulting to 0 on failure.
+ (void)os::free_memory(free_memory);
// If SegmentedCodeCache is off, both values refer to the single heap (with type CodeBlobType::All).
size_t available_cc_np = CodeCache::unallocated_capacity(CodeBlobType::MethodNonProfiled),
available_cc_p = CodeCache::unallocated_capacity(CodeBlobType::MethodProfiled);
diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
index e8636e97cd81..976dbdac9edb 100644
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
@@ -2245,7 +2245,8 @@ void G1CollectedHeap::print_heap_regions() const {
}
void G1CollectedHeap::print_heap_on(outputStream* st) const {
- size_t heap_used = Heap_lock->owned_by_self() ? used() : used_unlocked();
+ size_t heap_used = (Thread::current_or_null_safe() != nullptr &&
+ Heap_lock->owned_by_self()) ? used() : used_unlocked();
st->print("%-20s", "garbage-first heap");
st->print(" total reserved %zuK, committed %zuK, used %zuK",
_hrm.reserved().byte_size()/K, capacity()/K, heap_used/K);
diff --git a/src/hotspot/share/gc/shared/gcInitLogger.cpp b/src/hotspot/share/gc/shared/gcInitLogger.cpp
index 91bebf726c12..ba6399458603 100644
--- a/src/hotspot/share/gc/shared/gcInitLogger.cpp
+++ b/src/hotspot/share/gc/shared/gcInitLogger.cpp
@@ -62,8 +62,8 @@ void GCInitLogger::print_cpu() {
}
void GCInitLogger::print_memory() {
- julong memory = os::physical_memory();
- log_info_p(gc, init)("Memory: " JULONG_FORMAT "%s",
+ physical_memory_size_type memory = os::physical_memory();
+ log_info_p(gc, init)("Memory: " PHYS_MEM_TYPE_FORMAT "%s",
byte_size_in_proper_unit(memory), proper_unit_for_byte_size(memory));
}
diff --git a/src/hotspot/share/gc/shared/gcLogPrecious.cpp b/src/hotspot/share/gc/shared/gcLogPrecious.cpp
index 43bd58db1aa0..d556eed1b690 100644
--- a/src/hotspot/share/gc/shared/gcLogPrecious.cpp
+++ b/src/hotspot/share/gc/shared/gcLogPrecious.cpp
@@ -25,6 +25,7 @@
#include "runtime/mutex.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
+#include "runtime/thread.hpp"
#include "utilities/ostream.hpp"
stringStream* GCLogPrecious::_lines = nullptr;
@@ -83,7 +84,8 @@ void GCLogPrecious::print_on_error(outputStream* st) {
return;
}
- if (!_lock->try_lock_without_rank_check()) {
+ if (Thread::current_or_null_safe() == nullptr ||
+ !_lock->try_lock_without_rank_check()) {
st->print_cr("\n");
return;
}
diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp
index 4b3cbf04b40e..9fdf0d63eccf 100644
--- a/src/hotspot/share/gc/shared/gc_globals.hpp
+++ b/src/hotspot/share/gc/shared/gc_globals.hpp
@@ -260,6 +260,7 @@
develop(uintx, ObjArrayMarkingStride, 2048, \
"Number of object array elements to push onto the marking stack " \
"before pushing a continuation entry") \
+ range(1, INT_MAX/2) \
\
product_pd(bool, NeverActAsServerClassMachine, \
"Never act like a server-class machine") \
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp
index 144773908caa..05e226288972 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp
@@ -184,8 +184,8 @@ void ShenandoahAdaptiveHeuristics::record_success_concurrent() {
}
}
-void ShenandoahAdaptiveHeuristics::record_success_degenerated() {
- ShenandoahHeuristics::record_success_degenerated();
+void ShenandoahAdaptiveHeuristics::record_degenerated() {
+ ShenandoahHeuristics::record_degenerated();
// Adjust both trigger's parameters in the case of a degenerated GC because
// either of them should have triggered earlier to avoid this case.
adjust_margin_of_error(DEGENERATE_PENALTY_SD);
@@ -240,13 +240,14 @@ bool ShenandoahAdaptiveHeuristics::should_start_gc() {
log_debug(gc)("should_start_gc? available: %zu, soft_max_capacity: %zu"
", allocated: %zu", available, capacity, allocated);
+ // Track allocation rate even if we decide to start a cycle for other reasons.
+ double rate = _allocation_rate.sample(allocated);
+
if (_start_gc_is_pending) {
log_trigger("GC start is already pending");
return true;
}
- // Track allocation rate even if we decide to start a cycle for other reasons.
- double rate = _allocation_rate.sample(allocated);
_last_trigger = OTHER;
size_t min_threshold = min_free_threshold();
@@ -360,16 +361,32 @@ ShenandoahAllocationRate::ShenandoahAllocationRate() :
_rate_avg(int(ShenandoahAdaptiveSampleSizeSeconds * ShenandoahAdaptiveSampleFrequencyHz), ShenandoahAdaptiveDecayFactor) {
}
+double ShenandoahAllocationRate::force_sample(size_t allocated, size_t &unaccounted_bytes_allocated) {
+ const double MinSampleTime = 0.002; // Do not sample if time since last update is less than 2 ms
+ double now = os::elapsedTime();
+ double time_since_last_update = now -_last_sample_time;
+ if (time_since_last_update < MinSampleTime) {
+ unaccounted_bytes_allocated = allocated - _last_sample_value;
+ _last_sample_value = 0;
+ return 0.0;
+ } else {
+ double rate = instantaneous_rate(now, allocated);
+ _rate.add(rate);
+ _rate_avg.add(_rate.avg());
+ _last_sample_time = now;
+ _last_sample_value = allocated;
+ unaccounted_bytes_allocated = 0;
+ return rate;
+ }
+}
+
double ShenandoahAllocationRate::sample(size_t allocated) {
double now = os::elapsedTime();
double rate = 0.0;
if (now - _last_sample_time > _interval_sec) {
- if (allocated >= _last_sample_value) {
- rate = instantaneous_rate(now, allocated);
- _rate.add(rate);
- _rate_avg.add(_rate.avg());
- }
-
+ rate = instantaneous_rate(now, allocated);
+ _rate.add(rate);
+ _rate_avg.add(_rate.avg());
_last_sample_time = now;
_last_sample_value = allocated;
}
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp
index 68e540960c79..1ba18f37c2bb 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp
@@ -32,23 +32,62 @@
#include "memory/allocation.hpp"
#include "utilities/numberSeq.hpp"
+/**
+ * ShenanoahAllocationRate maintains a truncated history of recently sampled allocation rates for the purpose of providing
+ * informed estimates of current and future allocation rates based on weighted averages and standard deviations of the
+ * truncated history. More recently sampled allocations are weighted more heavily than older samples when computing
+ * averages and standard deviations.
+ */
class ShenandoahAllocationRate : public CHeapObj {
public:
explicit ShenandoahAllocationRate();
+
+ // Reset the _last_sample_value to zero, _last_sample_time to current time.
void allocation_counter_reset();
+ // Force an allocation rate sample to be taken, even if the time since last sample is not greater than
+ // 1s/ShenandoahAdaptiveSampleFrequencyHz, except when current_time - _last_sample_time < MinSampleTime (2 ms).
+ // The sampled allocation rate is computed from (allocated - _last_sample_value) / (current_time - _last_sample_time).
+ // Return the newly computed rate if the sample is taken, zero if it is not an appropriate time to add a sample.
+ // In the case that a new sample is not taken, overwrite unaccounted_bytes_allocated with bytes allocated since
+ // the previous sample was taken (allocated - _last_sample_value). Otherwise, overwrite unaccounted_bytes_allocated
+ // with 0.
+ double force_sample(size_t allocated, size_t &unaccounted_bytes_allocated);
+
+ // Add an allocation rate sample if the time since last sample is greater than 1s/ShenandoahAdaptiveSampleFrequencyHz.
+ // The sampled allocation rate is computed from (allocated - _last_sample_value) / (current_time - _last_sample_time).
+ // Return the newly computed rate if the sample is taken, zero if it is not an appropriate time to add a sample.
double sample(size_t allocated);
+ // Return an estimate of the upper bound on allocation rate, with the upper bound computed as the weighted average
+ // of recently sampled instantaneous allocation rates added to sds times the standard deviation computed for the
+ // sequence of recently sampled average allocation rates.
double upper_bound(double sds) const;
+
+ // Test whether rate significantly diverges from the computed average allocation rate. If so, return true.
+ // Otherwise, return false. Significant divergence is recognized if (rate - _rate.avg()) / _rate.sd() > threshold.
bool is_spiking(double rate, double threshold) const;
+
private:
+ // Return the instantaneous rate calculated from (allocated - _last_sample_value) / (time - _last_sample_time).
+ // Return Sentinel value 0.0 if (time - _last_sample_time) == 0 or if (allocated <= _last_sample_value).
double instantaneous_rate(double time, size_t allocated) const;
+ // Time at which previous allocation rate sample was collected.
double _last_sample_time;
+
+ // Bytes allocated as of the time at which previous allocation rate sample was collected.
size_t _last_sample_value;
+
+ // The desired interval of time between consecutive samples of the allocation rate.
double _interval_sec;
+
+ // Holds a sequence of the most recently sampled instantaneous allocation rates
TruncatedSeq _rate;
+
+ // Holds a sequence of the most recently computed weighted average of allocation rates, with each weighted average
+ // computed immediately after an instantaneous rate was sampled
TruncatedSeq _rate_avg;
};
@@ -71,18 +110,18 @@ class ShenandoahAdaptiveHeuristics : public ShenandoahHeuristics {
virtual void choose_collection_set_from_regiondata(ShenandoahCollectionSet* cset,
RegionData* data, size_t size,
- size_t actual_free);
+ size_t actual_free) override;
- void record_cycle_start();
- void record_success_concurrent();
- void record_success_degenerated();
- void record_success_full();
+ virtual void record_cycle_start() override;
+ virtual void record_success_concurrent() override;
+ virtual void record_degenerated() override;
+ virtual void record_success_full() override;
- virtual bool should_start_gc();
+ virtual bool should_start_gc() override;
- virtual const char* name() { return "Adaptive"; }
- virtual bool is_diagnostic() { return false; }
- virtual bool is_experimental() { return false; }
+ virtual const char* name() override { return "Adaptive"; }
+ virtual bool is_diagnostic() override { return false; }
+ virtual bool is_experimental() override { return false; }
private:
// These are used to adjust the margin of error and the spike threshold
@@ -150,6 +189,15 @@ class ShenandoahAdaptiveHeuristics : public ShenandoahHeuristics {
_last_trigger = trigger_type;
ShenandoahHeuristics::accept_trigger();
}
+
+public:
+ // Sample the allocation rate at GC trigger time if possible. Return the number of allocated bytes that were
+ // not accounted for in the sample. This must be called before resetting bytes allocated since gc start.
+ virtual size_t force_alloc_rate_sample(size_t bytes_allocated) override {
+ size_t unaccounted_bytes;
+ _allocation_rate.force_sample(bytes_allocated, unaccounted_bytes);
+ return unaccounted_bytes;
+ }
};
#endif // SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHADAPTIVEHEURISTICS_HPP
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp
index 592bba677574..f8a77d95d51c 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp
@@ -38,6 +38,7 @@ ShenandoahCompactHeuristics::ShenandoahCompactHeuristics(ShenandoahSpaceInfo* sp
SHENANDOAH_ERGO_ENABLE_FLAG(ShenandoahImplicitGCInvokesConcurrent);
SHENANDOAH_ERGO_ENABLE_FLAG(ShenandoahUncommit);
SHENANDOAH_ERGO_ENABLE_FLAG(ShenandoahAlwaysClearSoftRefs);
+ SHENANDOAH_ERGO_ENABLE_FLAG(UseStringDeduplication);
SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahAllocationThreshold, 10);
SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahImmediateThreshold, 100);
SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahUncommitDelay, 1000);
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp
index dfae90402424..c7067b2e5abf 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp
@@ -26,7 +26,6 @@
#include "gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp"
#include "gc/shenandoah/shenandoahCollectionSet.hpp"
#include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
-#include "gc/shenandoah/shenandoahEvacInfo.hpp"
#include "gc/shenandoah/shenandoahGeneration.hpp"
#include "gc/shenandoah/shenandoahGenerationalHeap.inline.hpp"
#include "gc/shenandoah/shenandoahHeapRegion.inline.hpp"
@@ -185,59 +184,16 @@ void ShenandoahGenerationalHeuristics::choose_collection_set(ShenandoahCollectio
heap->shenandoah_policy()->record_mixed_cycle();
}
- size_t cset_percent = (total_garbage == 0) ? 0 : (collection_set->garbage() * 100 / total_garbage);
- size_t collectable_garbage = collection_set->garbage() + immediate_garbage;
- size_t collectable_garbage_percent = (total_garbage == 0) ? 0 : (collectable_garbage * 100 / total_garbage);
+ collection_set->summarize(total_garbage, immediate_garbage, immediate_regions);
- log_info(gc, ergo)("Collectable Garbage: %zu%s (%zu%%), "
- "Immediate: %zu%s (%zu%%), %zu regions, "
- "CSet: %zu%s (%zu%%), %zu regions",
-
- byte_size_in_proper_unit(collectable_garbage),
- proper_unit_for_byte_size(collectable_garbage),
- collectable_garbage_percent,
-
- byte_size_in_proper_unit(immediate_garbage),
- proper_unit_for_byte_size(immediate_garbage),
- immediate_percent,
- immediate_regions,
-
- byte_size_in_proper_unit(collection_set->garbage()),
- proper_unit_for_byte_size(collection_set->garbage()),
- cset_percent,
- collection_set->count());
-
- if (collection_set->garbage() > 0) {
- size_t young_evac_bytes = collection_set->get_young_bytes_reserved_for_evacuation();
- size_t promote_evac_bytes = collection_set->get_young_bytes_to_be_promoted();
- size_t old_evac_bytes = collection_set->get_old_bytes_reserved_for_evacuation();
- size_t total_evac_bytes = young_evac_bytes + promote_evac_bytes + old_evac_bytes;
- log_info(gc, ergo)("Evacuation Targets: YOUNG: %zu%s, "
- "PROMOTE: %zu%s, "
- "OLD: %zu%s, "
- "TOTAL: %zu%s",
- byte_size_in_proper_unit(young_evac_bytes), proper_unit_for_byte_size(young_evac_bytes),
- byte_size_in_proper_unit(promote_evac_bytes), proper_unit_for_byte_size(promote_evac_bytes),
- byte_size_in_proper_unit(old_evac_bytes), proper_unit_for_byte_size(old_evac_bytes),
- byte_size_in_proper_unit(total_evac_bytes), proper_unit_for_byte_size(total_evac_bytes));
-
- ShenandoahEvacuationInformation evacInfo;
- evacInfo.set_collection_set_regions(collection_set->count());
- evacInfo.set_collection_set_used_before(collection_set->used());
- evacInfo.set_collection_set_used_after(collection_set->live());
- evacInfo.set_collected_old(old_evac_bytes);
- evacInfo.set_collected_promoted(promote_evac_bytes);
- evacInfo.set_collected_young(young_evac_bytes);
- evacInfo.set_regions_promoted_humongous(humongous_regions_promoted);
- evacInfo.set_regions_promoted_regular(regular_regions_promoted_in_place);
- evacInfo.set_regular_promoted_garbage(regular_regions_promoted_garbage);
- evacInfo.set_regular_promoted_free(regular_regions_promoted_free);
- evacInfo.set_regions_immediate(immediate_regions);
- evacInfo.set_immediate_size(immediate_garbage);
- evacInfo.set_free_regions(free_regions);
-
- ShenandoahTracer().report_evacuation_info(&evacInfo);
- }
+ ShenandoahTracer::report_evacuation_info(collection_set,
+ free_regions,
+ humongous_regions_promoted,
+ regular_regions_promoted_in_place,
+ regular_regions_promoted_garbage,
+ regular_regions_promoted_free,
+ immediate_regions,
+ immediate_garbage);
}
@@ -268,15 +224,3 @@ size_t ShenandoahGenerationalHeuristics::add_preselected_regions_to_collection_s
return cur_young_garbage;
}
-void ShenandoahGenerationalHeuristics::log_cset_composition(ShenandoahCollectionSet* cset) const {
- size_t collected_old = cset->get_old_bytes_reserved_for_evacuation();
- size_t collected_promoted = cset->get_young_bytes_to_be_promoted();
- size_t collected_young = cset->get_young_bytes_reserved_for_evacuation();
-
- log_info(gc, ergo)(
- "Chosen CSet evacuates young: %zu%s (of which at least: %zu%s are to be promoted), "
- "old: %zu%s",
- byte_size_in_proper_unit(collected_young), proper_unit_for_byte_size(collected_young),
- byte_size_in_proper_unit(collected_promoted), proper_unit_for_byte_size(collected_promoted),
- byte_size_in_proper_unit(collected_old), proper_unit_for_byte_size(collected_old));
-}
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp
index 6708c63f0425..31c016bb4b7f 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp
@@ -51,9 +51,8 @@ class ShenandoahGenerationalHeuristics : public ShenandoahAdaptiveHeuristics {
size_t add_preselected_regions_to_collection_set(ShenandoahCollectionSet* cset,
const RegionData* data,
size_t size) const;
-
- void log_cset_composition(ShenandoahCollectionSet* cset) const;
};
#endif //SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHGENERATIONALHEURISTICS_HPP
+
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp
index 331bd0405752..93f9b18ad9f5 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp
@@ -42,8 +42,6 @@ void ShenandoahGlobalHeuristics::choose_collection_set_from_regiondata(Shenandoa
QuickSort::sort(data, (int) size, compare_by_garbage);
choose_global_collection_set(cset, data, size, actual_free, 0 /* cur_young_garbage */);
-
- log_cset_composition(cset);
}
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp
index b151a75e6e7e..0aa117385cff 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp
@@ -153,27 +153,7 @@ void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collec
choose_collection_set_from_regiondata(collection_set, candidates, cand_idx, immediate_garbage + free);
}
- size_t cset_percent = (total_garbage == 0) ? 0 : (collection_set->garbage() * 100 / total_garbage);
- size_t collectable_garbage = collection_set->garbage() + immediate_garbage;
- size_t collectable_garbage_percent = (total_garbage == 0) ? 0 : (collectable_garbage * 100 / total_garbage);
-
- log_info(gc, ergo)("Collectable Garbage: %zu%s (%zu%%), "
- "Immediate: %zu%s (%zu%%), %zu regions, "
- "CSet: %zu%s (%zu%%), %zu regions",
-
- byte_size_in_proper_unit(collectable_garbage),
- proper_unit_for_byte_size(collectable_garbage),
- collectable_garbage_percent,
-
- byte_size_in_proper_unit(immediate_garbage),
- proper_unit_for_byte_size(immediate_garbage),
- immediate_percent,
- immediate_regions,
-
- byte_size_in_proper_unit(collection_set->garbage()),
- proper_unit_for_byte_size(collection_set->garbage()),
- cset_percent,
- collection_set->count());
+ collection_set->summarize(total_garbage, immediate_garbage, immediate_regions);
}
void ShenandoahHeuristics::record_cycle_start() {
@@ -262,7 +242,7 @@ void ShenandoahHeuristics::record_success_concurrent() {
adjust_penalty(Concurrent_Adjust);
}
-void ShenandoahHeuristics::record_success_degenerated() {
+void ShenandoahHeuristics::record_degenerated() {
adjust_penalty(Degenerated_Penalty);
}
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.hpp
index d036a62a32cf..e1139765022a 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.hpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.hpp
@@ -36,7 +36,7 @@
do { \
if (FLAG_IS_DEFAULT(name) && (name)) { \
log_info(gc)("Heuristics ergonomically sets -XX:-" #name); \
- FLAG_SET_DEFAULT(name, false); \
+ FLAG_SET_ERGO(name, false); \
} \
} while (0)
@@ -44,7 +44,7 @@
do { \
if (FLAG_IS_DEFAULT(name) && !(name)) { \
log_info(gc)("Heuristics ergonomically sets -XX:+" #name); \
- FLAG_SET_DEFAULT(name, true); \
+ FLAG_SET_ERGO(name, true); \
} \
} while (0)
@@ -52,7 +52,7 @@
do { \
if (FLAG_IS_DEFAULT(name)) { \
log_info(gc)("Heuristics ergonomically sets -XX:" #name "=" #value); \
- FLAG_SET_DEFAULT(name, value); \
+ FLAG_SET_ERGO(name, value); \
} \
} while (0)
@@ -129,6 +129,13 @@ class ShenandoahHeuristics : public CHeapObj {
#endif
}
+ inline void update_livedata(size_t live) {
+ _region_union._live_data = live;
+#ifdef ASSERT
+ _union_tag = is_live_data;
+#endif
+ }
+
inline ShenandoahHeapRegion* get_region() const {
assert(_union_tag != is_uninitialized, "Cannot fetch region from uninitialized RegionData");
return _region;
@@ -218,7 +225,7 @@ class ShenandoahHeuristics : public CHeapObj {
virtual void record_success_concurrent();
- virtual void record_success_degenerated();
+ virtual void record_degenerated();
virtual void record_success_full();
@@ -241,6 +248,11 @@ class ShenandoahHeuristics : public CHeapObj {
double elapsed_cycle_time() const;
+ virtual size_t force_alloc_rate_sample(size_t bytes_allocated) {
+ // do nothing
+ return 0;
+ }
+
// Format prefix and emit log message indicating a GC cycle hs been triggered
void log_trigger(const char* fmt, ...) ATTRIBUTE_PRINTF(2, 3);
};
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp
index 2d0bbfd5e4a3..21eb73e5796d 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp
@@ -88,6 +88,17 @@ bool ShenandoahOldHeuristics::prime_collection_set(ShenandoahCollectionSet* coll
return false;
}
+ // Between consecutive mixed-evacuation cycles, the live data within each candidate region may change due to
+ // promotions and old-gen evacuations. Re-sort the candidate regions in order to first evacuate regions that have
+ // the smallest amount of live data. These are easiest to evacuate with least effort. Doing these first allows
+ // us to more quickly replenish free memory with empty regions.
+ for (uint i = _next_old_collection_candidate; i < _last_old_collection_candidate; i++) {
+ ShenandoahHeapRegion* r = _region_data[i].get_region();
+ _region_data[i].update_livedata(r->get_mixed_candidate_live_data_bytes());
+ }
+ QuickSort::sort(_region_data + _next_old_collection_candidate, unprocessed_old_collection_candidates(),
+ compare_by_live);
+
_first_pinned_candidate = NOT_FOUND;
uint included_old_regions = 0;
@@ -141,7 +152,7 @@ bool ShenandoahOldHeuristics::prime_collection_set(ShenandoahCollectionSet* coll
// If region r is evacuated to fragmented memory (to free memory within a partially used region), then we need
// to decrease the capacity of the fragmented memory by the scaled loss.
- size_t live_data_for_evacuation = r->get_live_data_bytes();
+ const size_t live_data_for_evacuation = r->get_live_data_bytes();
size_t lost_available = r->free();
if ((lost_available > 0) && (excess_fragmented_available > 0)) {
@@ -169,7 +180,9 @@ bool ShenandoahOldHeuristics::prime_collection_set(ShenandoahCollectionSet* coll
// We were not able to account for the lost free memory within fragmented memory, so we need to take this
// allocation out of unfragmented memory. Unfragmented memory does not need to account for loss of free.
if (live_data_for_evacuation > unfragmented_available) {
- // There is not room to evacuate this region or any that come after it in within the candidates array.
+ // There is no room to evacuate this region or any that come after it in within the candidates array.
+ log_debug(gc, cset)("Not enough unfragmented memory (%zu) to hold evacuees (%zu) from region: (%zu)",
+ unfragmented_available, live_data_for_evacuation, r->index());
break;
} else {
unfragmented_available -= live_data_for_evacuation;
@@ -187,7 +200,9 @@ bool ShenandoahOldHeuristics::prime_collection_set(ShenandoahCollectionSet* coll
evacuation_need = 0;
}
if (evacuation_need > unfragmented_available) {
- // There is not room to evacuate this region or any that come after it in within the candidates array.
+ // There is no room to evacuate this region or any that come after it in within the candidates array.
+ log_debug(gc, cset)("Not enough unfragmented memory (%zu) to hold evacuees (%zu) from region: (%zu)",
+ unfragmented_available, live_data_for_evacuation, r->index());
break;
} else {
unfragmented_available -= evacuation_need;
@@ -403,6 +418,8 @@ void ShenandoahOldHeuristics::prepare_for_old_collections() {
ShenandoahHeapRegion* r = candidates[i].get_region();
size_t region_garbage = r->garbage();
size_t region_free = r->free();
+
+ r->capture_mixed_candidate_garbage();
candidates_garbage += region_garbage;
unfragmented += region_free;
}
@@ -412,7 +429,7 @@ void ShenandoahOldHeuristics::prepare_for_old_collections() {
size_t defrag_count = 0;
size_t total_uncollected_old_regions = _last_old_region - _last_old_collection_candidate;
- if (cand_idx > _last_old_collection_candidate) {
+ if ((ShenandoahGenerationalHumongousReserve > 0) && (cand_idx > _last_old_collection_candidate)) {
// Above, we have added into the set of mixed-evacuation candidates all old-gen regions for which the live memory
// that they contain is below a particular old-garbage threshold. Regions that were not selected for the collection
// set hold enough live memory that it is not considered efficient (by "garbage-first standards") to compact these
@@ -445,6 +462,8 @@ void ShenandoahOldHeuristics::prepare_for_old_collections() {
r->index(), ShenandoahHeapRegion::region_state_to_string(r->state()));
const size_t region_garbage = r->garbage();
const size_t region_free = r->free();
+
+ r->capture_mixed_candidate_garbage();
candidates_garbage += region_garbage;
unfragmented += region_free;
defrag_count++;
@@ -717,10 +736,10 @@ void ShenandoahOldHeuristics::record_success_concurrent() {
this->ShenandoahHeuristics::record_success_concurrent();
}
-void ShenandoahOldHeuristics::record_success_degenerated() {
+void ShenandoahOldHeuristics::record_degenerated() {
// Forget any triggers that occurred while OLD GC was ongoing. If we really need to start another, it will retrigger.
clear_triggers();
- this->ShenandoahHeuristics::record_success_degenerated();
+ this->ShenandoahHeuristics::record_degenerated();
}
void ShenandoahOldHeuristics::record_success_full() {
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp
index 8d3fec746bae..b4ef625aac7d 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp
@@ -190,7 +190,7 @@ class ShenandoahOldHeuristics : public ShenandoahHeuristics {
void record_success_concurrent() override;
- void record_success_degenerated() override;
+ void record_degenerated() override;
void record_success_full() override;
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp
index 2131f95b413d..7fb44c7b71ba 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp
@@ -41,6 +41,10 @@ class ShenandoahSpaceInfo {
virtual size_t soft_available() const = 0;
virtual size_t available() const = 0;
virtual size_t used() const = 0;
+
+ // Return an approximation of the bytes allocated since GC start. The value returned is monotonically non-decreasing
+ // in time within each GC cycle. For certain GC cycles, the value returned may include some bytes allocated before
+ // the start of the current GC cycle.
virtual size_t bytes_allocated_since_gc_start() const = 0;
};
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp
index d236be8c9e60..15d1058d7cd5 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp
@@ -55,8 +55,6 @@ void ShenandoahYoungHeuristics::choose_collection_set_from_regiondata(Shenandoah
size_t cur_young_garbage = add_preselected_regions_to_collection_set(cset, data, size);
choose_young_collection_set(cset, data, size, actual_free, cur_young_garbage);
-
- log_cset_composition(cset);
}
void ShenandoahYoungHeuristics::choose_young_collection_set(ShenandoahCollectionSet* cset,
diff --git a/src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp b/src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp
index 296a1979b01b..2dfa52b86bb9 100644
--- a/src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp
+++ b/src/hotspot/share/gc/shenandoah/mode/shenandoahPassiveMode.cpp
@@ -29,6 +29,7 @@
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
#include "logging/log.hpp"
#include "logging/logTag.hpp"
+#include "runtime/globals_extension.hpp"
#include "runtime/java.hpp"
void ShenandoahPassiveMode::initialize_flags() const {
@@ -41,7 +42,10 @@ void ShenandoahPassiveMode::initialize_flags() const {
// No need for evacuation reserve with Full GC, only for Degenerated GC.
if (!ShenandoahDegeneratedGC) {
- SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahEvacReserve, 0);
+ if (FLAG_IS_DEFAULT(ShenandoahEvacReserve)) {
+ log_info(gc)("Heuristics sets -XX:ShenandoahEvacReserve=0");
+ FLAG_SET_DEFAULT(ShenandoahEvacReserve, 0);
+ }
}
// Disable known barriers by default.
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp
index bd66f55bd8fa..71fd6e376148 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp
@@ -43,7 +43,7 @@ ShenandoahAgeCensus::ShenandoahAgeCensus(uint max_workers)
ShenandoahGenerationalMinTenuringAge, ShenandoahGenerationalMaxTenuringAge));
}
- _global_age_table = NEW_C_HEAP_ARRAY(AgeTable*, MAX_SNAPSHOTS, mtGC);
+ _global_age_tables = NEW_C_HEAP_ARRAY(AgeTable*, MAX_SNAPSHOTS, mtGC);
CENSUS_NOISE(_global_noise = NEW_C_HEAP_ARRAY(ShenandoahNoiseStats, MAX_SNAPSHOTS, mtGC);)
_tenuring_threshold = NEW_C_HEAP_ARRAY(uint, MAX_SNAPSHOTS, mtGC);
CENSUS_NOISE(_skipped = 0);
@@ -52,36 +52,32 @@ ShenandoahAgeCensus::ShenandoahAgeCensus(uint max_workers)
for (int i = 0; i < MAX_SNAPSHOTS; i++) {
// Note that we don't now get perfdata from age_table
- _global_age_table[i] = new AgeTable(false);
+ _global_age_tables[i] = new AgeTable(false);
CENSUS_NOISE(_global_noise[i].clear();)
// Sentinel value
_tenuring_threshold[i] = MAX_COHORTS;
}
- if (ShenandoahGenerationalAdaptiveTenuring && !ShenandoahGenerationalCensusAtEvac) {
- _local_age_table = NEW_C_HEAP_ARRAY(AgeTable*, _max_workers, mtGC);
- CENSUS_NOISE(_local_noise = NEW_C_HEAP_ARRAY(ShenandoahNoiseStats, max_workers, mtGC);)
- for (uint i = 0; i < _max_workers; i++) {
- _local_age_table[i] = new AgeTable(false);
- CENSUS_NOISE(_local_noise[i].clear();)
- }
- } else {
- _local_age_table = nullptr;
+ _local_age_tables = NEW_C_HEAP_ARRAY(AgeTable*, _max_workers, mtGC);
+ CENSUS_NOISE(_local_noise = NEW_C_HEAP_ARRAY(ShenandoahNoiseStats, max_workers, mtGC);)
+ for (uint i = 0; i < _max_workers; i++) {
+ _local_age_tables[i] = new AgeTable(false);
+ CENSUS_NOISE(_local_noise[i].clear();)
}
- _epoch = MAX_SNAPSHOTS - 1; // see update_epoch()
+ _epoch = MAX_SNAPSHOTS - 1; // see prepare_for_census_update()
}
ShenandoahAgeCensus::~ShenandoahAgeCensus() {
for (uint i = 0; i < MAX_SNAPSHOTS; i++) {
- delete _global_age_table[i];
+ delete _global_age_tables[i];
}
- FREE_C_HEAP_ARRAY(AgeTable*, _global_age_table);
+ FREE_C_HEAP_ARRAY(AgeTable*, _global_age_tables);
FREE_C_HEAP_ARRAY(uint, _tenuring_threshold);
CENSUS_NOISE(FREE_C_HEAP_ARRAY(ShenandoahNoiseStats, _global_noise));
- if (_local_age_table) {
+ if (_local_age_tables) {
for (uint i = 0; i < _max_workers; i++) {
- delete _local_age_table[i];
+ delete _local_age_tables[i];
}
- FREE_C_HEAP_ARRAY(AgeTable*, _local_age_table);
+ FREE_C_HEAP_ARRAY(AgeTable*, _local_age_tables);
CENSUS_NOISE(FREE_C_HEAP_ARRAY(ShenandoahNoiseStats, _local_noise));
}
}
@@ -142,37 +138,30 @@ void ShenandoahAgeCensus::prepare_for_census_update() {
if (++_epoch >= MAX_SNAPSHOTS) {
_epoch=0;
}
- _global_age_table[_epoch]->clear();
+ _global_age_tables[_epoch]->clear();
CENSUS_NOISE(_global_noise[_epoch].clear();)
}
// Update the census data from appropriate sources,
// and compute the new tenuring threshold.
-void ShenandoahAgeCensus::update_census(size_t age0_pop, AgeTable* pv1, AgeTable* pv2) {
+void ShenandoahAgeCensus::update_census(size_t age0_pop) {
prepare_for_census_update();
- assert(_global_age_table[_epoch]->is_clear(), "Dirty decks");
+ assert(_global_age_tables[_epoch]->is_clear(), "Dirty decks");
CENSUS_NOISE(assert(_global_noise[_epoch].is_clear(), "Dirty decks");)
- if (ShenandoahGenerationalAdaptiveTenuring && !ShenandoahGenerationalCensusAtEvac) {
- assert(pv1 == nullptr && pv2 == nullptr, "Error, check caller");
- // Seed cohort 0 with population that may have been missed during
- // regular census.
- _global_age_table[_epoch]->add(0u, age0_pop);
-
- // Merge data from local age tables into the global age table for the epoch,
- // clearing the local tables.
- for (uint i = 0; i < _max_workers; i++) {
- // age stats
- _global_age_table[_epoch]->merge(_local_age_table[i]);
- _local_age_table[i]->clear(); // clear for next census
- // Merge noise stats
- CENSUS_NOISE(_global_noise[_epoch].merge(_local_noise[i]);)
- CENSUS_NOISE(_local_noise[i].clear();)
- }
- } else {
- // census during evac
- assert(pv1 != nullptr && pv2 != nullptr, "Error, check caller");
- _global_age_table[_epoch]->merge(pv1);
- _global_age_table[_epoch]->merge(pv2);
+
+ // Seed cohort 0 with population that may have been missed during
+ // regular census.
+ _global_age_tables[_epoch]->add(0u, age0_pop);
+
+ // Merge data from local age tables into the global age table for the epoch,
+ // clearing the local tables.
+ for (uint i = 0; i < _max_workers; i++) {
+ // age stats
+ _global_age_tables[_epoch]->merge(_local_age_tables[i]);
+ _local_age_tables[i]->clear(); // clear for next census
+ // Merge noise stats
+ CENSUS_NOISE(_global_noise[_epoch].merge(_local_noise[i]);)
+ CENSUS_NOISE(_local_noise[i].clear();)
}
update_tenuring_threshold();
@@ -188,7 +177,7 @@ void ShenandoahAgeCensus::update_census(size_t age0_pop, AgeTable* pv1, AgeTable
void ShenandoahAgeCensus::reset_global() {
assert(_epoch < MAX_SNAPSHOTS, "Out of bounds");
for (uint i = 0; i < MAX_SNAPSHOTS; i++) {
- _global_age_table[i]->clear();
+ _global_age_tables[i]->clear();
CENSUS_NOISE(_global_noise[i].clear();)
}
_epoch = MAX_SNAPSHOTS;
@@ -197,12 +186,8 @@ void ShenandoahAgeCensus::reset_global() {
// Reset the local age tables, clearing any partial census.
void ShenandoahAgeCensus::reset_local() {
- if (!ShenandoahGenerationalAdaptiveTenuring || ShenandoahGenerationalCensusAtEvac) {
- assert(_local_age_table == nullptr, "Error");
- return;
- }
for (uint i = 0; i < _max_workers; i++) {
- _local_age_table[i]->clear();
+ _local_age_tables[i]->clear();
CENSUS_NOISE(_local_noise[i].clear();)
}
}
@@ -212,7 +197,7 @@ void ShenandoahAgeCensus::reset_local() {
bool ShenandoahAgeCensus::is_clear_global() {
assert(_epoch < MAX_SNAPSHOTS, "Out of bounds");
for (uint i = 0; i < MAX_SNAPSHOTS; i++) {
- bool clear = _global_age_table[i]->is_clear();
+ bool clear = _global_age_tables[i]->is_clear();
CENSUS_NOISE(clear |= _global_noise[i].is_clear();)
if (!clear) {
return false;
@@ -223,12 +208,8 @@ bool ShenandoahAgeCensus::is_clear_global() {
// Is local census information clear?
bool ShenandoahAgeCensus::is_clear_local() {
- if (!ShenandoahGenerationalAdaptiveTenuring || ShenandoahGenerationalCensusAtEvac) {
- assert(_local_age_table == nullptr, "Error");
- return true;
- }
for (uint i = 0; i < _max_workers; i++) {
- bool clear = _local_age_table[i]->is_clear();
+ bool clear = _local_age_tables[i]->is_clear();
CENSUS_NOISE(clear |= _local_noise[i].is_clear();)
if (!clear) {
return false;
@@ -240,7 +221,7 @@ bool ShenandoahAgeCensus::is_clear_local() {
size_t ShenandoahAgeCensus::get_all_ages(uint snap) {
assert(snap < MAX_SNAPSHOTS, "Out of bounds");
size_t pop = 0;
- const AgeTable* pv = _global_age_table[snap];
+ const AgeTable* pv = _global_age_tables[snap];
for (uint i = 0; i < MAX_COHORTS; i++) {
pop += pv->sizes[i];
}
@@ -260,13 +241,10 @@ void ShenandoahAgeCensus::update_total() {
#endif // !PRODUCT
void ShenandoahAgeCensus::update_tenuring_threshold() {
- if (!ShenandoahGenerationalAdaptiveTenuring) {
- _tenuring_threshold[_epoch] = InitialTenuringThreshold;
- } else {
- uint tt = compute_tenuring_threshold();
- assert(tt <= MAX_COHORTS, "Out of bounds");
- _tenuring_threshold[_epoch] = tt;
- }
+ uint tt = compute_tenuring_threshold();
+ assert(tt <= MAX_COHORTS, "Out of bounds");
+ _tenuring_threshold[_epoch] = tt;
+
print();
log_info(gc, age)("New tenuring threshold %zu (min %zu, max %zu)",
(uintx) _tenuring_threshold[_epoch], ShenandoahGenerationalMinTenuringAge, ShenandoahGenerationalMaxTenuringAge);
@@ -296,8 +274,8 @@ uint ShenandoahAgeCensus::compute_tenuring_threshold() {
const uint prev_epoch = cur_epoch > 0 ? cur_epoch - 1 : markWord::max_age;
// Current and previous population vectors in ring
- const AgeTable* cur_pv = _global_age_table[cur_epoch];
- const AgeTable* prev_pv = _global_age_table[prev_epoch];
+ const AgeTable* cur_pv = _global_age_tables[cur_epoch];
+ const AgeTable* prev_pv = _global_age_tables[prev_epoch];
uint upper_bound = ShenandoahGenerationalMaxTenuringAge;
const uint prev_tt = previous_tenuring_threshold();
if (ShenandoahGenerationalCensusIgnoreOlderCohorts && prev_tt > 0) {
@@ -372,8 +350,8 @@ void ShenandoahAgeCensus::print() {
const uint cur_epoch = _epoch;
const uint prev_epoch = cur_epoch > 0 ? cur_epoch - 1: markWord::max_age;
- const AgeTable* cur_pv = _global_age_table[cur_epoch];
- const AgeTable* prev_pv = _global_age_table[prev_epoch];
+ const AgeTable* cur_pv = _global_age_tables[cur_epoch];
+ const AgeTable* prev_pv = _global_age_tables[prev_epoch];
const uint tt = tenuring_threshold();
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp
index 90d188e1fcae..5ccd0b21398f 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp
@@ -97,8 +97,8 @@ struct ShenandoahNoiseStats {
// once the per-worker data is consolidated into the appropriate population vector
// per minor collection. The _local_age_table is thus C x N, for N GC workers.
class ShenandoahAgeCensus: public CHeapObj {
- AgeTable** _global_age_table; // Global age table used for adapting tenuring threshold, one per snapshot
- AgeTable** _local_age_table; // Local scratch age tables to track object ages, one per worker
+ AgeTable** _global_age_tables; // Global age tables used for adapting tenuring threshold, one per snapshot
+ AgeTable** _local_age_tables; // Local scratch age tables to track object ages, one per worker
#ifdef SHENANDOAH_CENSUS_NOISE
ShenandoahNoiseStats* _global_noise; // Noise stats, one per snapshot
@@ -173,9 +173,8 @@ class ShenandoahAgeCensus: public CHeapObj {
~ShenandoahAgeCensus();
// Return the local age table (population vector) for worker_id.
- // Only used in the case of (ShenandoahGenerationalAdaptiveTenuring && !ShenandoahGenerationalCensusAtEvac)
AgeTable* get_local_age_table(uint worker_id) const {
- return _local_age_table[worker_id];
+ return _local_age_tables[worker_id];
}
// Return the most recently computed tenuring threshold.
@@ -204,17 +203,12 @@ class ShenandoahAgeCensus: public CHeapObj {
#endif // SHENANDOAH_CENSUS_NOISE
// Update the census data, and compute the new tenuring threshold.
- // This method should be called at the end of each marking (or optionally
- // evacuation) cycle to update the tenuring threshold to be used in
- // the next cycle.
+ // This method should be called at the end of each marking cycle to update
+ // the tenuring threshold to be used in the next cycle.
// age0_pop is the population of Cohort 0 that may have been missed in
// the regular census during the marking cycle, corresponding to objects
// allocated when the concurrent marking was in progress.
- // Optional parameters, pv1 and pv2 are population vectors that together
- // provide object census data (only) for the case when
- // ShenandoahGenerationalCensusAtEvac. In this case, the age0_pop
- // is 0, because the evacuated objects have all had their ages incremented.
- void update_census(size_t age0_pop, AgeTable* pv1 = nullptr, AgeTable* pv2 = nullptr);
+ void update_census(size_t age0_pop);
// Reset the epoch, clearing accumulated census history
// Note: this isn't currently used, but reserved for planned
@@ -231,7 +225,7 @@ class ShenandoahAgeCensus: public CHeapObj {
// Return the net size of objects encountered (counted or skipped) in census
// at most recent epoch.
- size_t get_total() { return _total; }
+ size_t get_total() const { return _total; }
#endif // !PRODUCT
// Print the age census information
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp
index 65495882ef0b..171ee770db38 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp
@@ -37,6 +37,7 @@
#include "runtime/globals_extension.hpp"
#include "runtime/java.hpp"
#include "utilities/defaultStream.hpp"
+#include "utilities/powerOfTwo.hpp"
void ShenandoahArguments::initialize() {
#if !(defined AARCH64 || defined AMD64 || defined IA32 || defined PPC64 || defined RISCV64)
@@ -198,13 +199,14 @@ void ShenandoahArguments::initialize() {
&& strcmp(ShenandoahGCHeuristics, "adaptive") != 0) {
log_warning(gc)("Ignoring -XX:ShenandoahGCHeuristics input: %s, because generational shenandoah only"
" supports adaptive heuristics", ShenandoahGCHeuristics);
+ FLAG_SET_ERGO(ShenandoahGCHeuristics, "adaptive");
}
FullGCForwarding::initialize_flags(MaxHeapSize);
}
size_t ShenandoahArguments::conservative_max_heap_alignment() {
- size_t align = ShenandoahMaxRegionSize;
+ size_t align = next_power_of_2(ShenandoahMaxRegionSize);
if (UseLargePages) {
align = MAX2(align, os::large_page_size());
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp
index c23f30a55e9d..ad00ab2ada9a 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp
@@ -499,7 +499,8 @@ void ShenandoahAsserts::assert_control_or_vm_thread_at_safepoint(bool at_safepoi
}
void ShenandoahAsserts::assert_generations_reconciled(const char* file, int line) {
- if (!SafepointSynchronize::is_at_safepoint()) {
+ if (!ShenandoahSafepoint::is_at_shenandoah_safepoint()) {
+ // Only shenandoah safepoint operations participate in the active/gc generation scheme
return;
}
@@ -510,6 +511,6 @@ void ShenandoahAsserts::assert_generations_reconciled(const char* file, int line
return;
}
- ShenandoahMessageBuffer msg("Active(%d) & GC(%d) Generations aren't reconciled", agen->type(), ggen->type());
+ ShenandoahMessageBuffer msg("Active(%s) & GC(%s) Generations aren't reconciled", agen->name(), ggen->name());
report_vm_error(file, line, msg.buffer());
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp
index 5d19a6a34e31..f6733d4a923d 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp
@@ -89,8 +89,19 @@ bool ShenandoahBarrierSet::need_keep_alive_barrier(DecoratorSet decorators, Basi
void ShenandoahBarrierSet::on_slowpath_allocation_exit(JavaThread* thread, oop new_obj) {
#if COMPILER2_OR_JVMCI
- assert(!ReduceInitialCardMarks || !ShenandoahCardBarrier || ShenandoahGenerationalHeap::heap()->is_in_young(new_obj),
- "Allocating new object outside of young generation: " INTPTR_FORMAT, p2i(new_obj));
+ if (ReduceInitialCardMarks && ShenandoahCardBarrier && !ShenandoahHeap::heap()->is_in_young(new_obj)) {
+ log_debug(gc)("Newly allocated object (" PTR_FORMAT ") is not in the young generation", p2i(new_obj));
+ // This can happen when an object is newly allocated, but we come to a safepoint before returning
+ // the object. If the safepoint runs a degenerated cycle that is upgraded to a full GC, this object
+ // will have survived two GC cycles. If the tenuring age is very low (1), this object may be promoted.
+ // In this case, we have an allocated object, but it has received no stores yet. If card marking barriers
+ // have been elided, we could end up with an object in old holding pointers to young that won't be in
+ // the remembered set. The solution here is conservative, but this problem should be rare, and it will
+ // correct itself on subsequent cycles when the remembered set is updated.
+ ShenandoahGenerationalHeap::heap()->old_generation()->card_scan()->mark_range_as_dirty(
+ cast_from_oop(new_obj), new_obj->size()
+ );
+ }
#endif // COMPILER2_OR_JVMCI
assert(thread->deferred_card_mark().is_empty(), "We don't use this");
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp
index b176446452a1..86244711844f 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp
@@ -191,6 +191,20 @@ inline void ShenandoahBarrierSet::keep_alive_if_weak(DecoratorSet decorators, oo
template
inline void ShenandoahBarrierSet::write_ref_field_post(T* field) {
assert(ShenandoahCardBarrier, "Should have been checked by caller");
+ if (_heap->is_in_young(field)) {
+ // Young field stores do not require card mark.
+ return;
+ }
+ T heap_oop = RawAccess<>::oop_load(field);
+ if (CompressedOops::is_null(heap_oop)) {
+ // Null reference store do not require card mark.
+ return;
+ }
+ oop obj = CompressedOops::decode_not_null(heap_oop);
+ if (!_heap->is_in_young(obj)) {
+ // Not an old->young reference store.
+ return;
+ }
volatile CardTable::CardValue* byte = card_table()->byte_for(field);
*byte = CardTable::dirty_card_val();
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp
index 35faa40af771..2d808cef834b 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp
@@ -200,3 +200,38 @@ void ShenandoahCollectionSet::print_on(outputStream* out) const {
}
assert(regions == count(), "Must match");
}
+
+void ShenandoahCollectionSet::summarize(size_t total_garbage, size_t immediate_garbage, size_t immediate_regions) const {
+ const LogTarget(Info, gc, ergo) lt;
+ LogStream ls(lt);
+ if (lt.is_enabled()) {
+ const size_t cset_percent = (total_garbage == 0) ? 0 : (garbage() * 100 / total_garbage);
+ const size_t collectable_garbage = garbage() + immediate_garbage;
+ const size_t collectable_garbage_percent = (total_garbage == 0) ? 0 : (collectable_garbage * 100 / total_garbage);
+ const size_t immediate_percent = (total_garbage == 0) ? 0 : (immediate_garbage * 100 / total_garbage);
+
+ ls.print_cr("Collectable Garbage: " PROPERFMT " (%zu%%), "
+ "Immediate: " PROPERFMT " (%zu%%), %zu regions, "
+ "CSet: " PROPERFMT " (%zu%%), %zu regions",
+ PROPERFMTARGS(collectable_garbage),
+ collectable_garbage_percent,
+
+ PROPERFMTARGS(immediate_garbage),
+ immediate_percent,
+ immediate_regions,
+
+ PROPERFMTARGS(garbage()),
+ cset_percent,
+ count());
+
+ if (garbage() > 0) {
+ const size_t young_evac_bytes = get_live_bytes_in_untenurable_regions();
+ const size_t promote_evac_bytes = get_live_bytes_in_tenurable_regions();
+ const size_t old_evac_bytes = get_live_bytes_in_old_regions();
+ const size_t total_evac_bytes = young_evac_bytes + promote_evac_bytes + old_evac_bytes;
+ ls.print_cr("Evacuation Targets: "
+ "YOUNG: " PROPERFMT ", " "PROMOTE: " PROPERFMT ", " "OLD: " PROPERFMT ", " "TOTAL: " PROPERFMT,
+ PROPERFMTARGS(young_evac_bytes), PROPERFMTARGS(promote_evac_bytes), PROPERFMTARGS(old_evac_bytes), PROPERFMTARGS(total_evac_bytes));
+ }
+ }
+}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp
index 4f9f6fc20522..a1b77baa2d3c 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp
@@ -103,20 +103,29 @@ class ShenandoahCollectionSet : public CHeapObj {
inline bool is_in(oop obj) const;
inline bool is_in_loc(void* loc) const;
+ // Prints a detailed accounting of all regions in the collection set when gc+cset=debug
void print_on(outputStream* out) const;
- // It is not known how many of these bytes will be promoted.
- inline size_t get_young_bytes_reserved_for_evacuation();
- inline size_t get_old_bytes_reserved_for_evacuation();
+ // Prints a summary of the collection set when gc+ergo=info
+ void summarize(size_t total_garbage, size_t immediate_garbage, size_t immediate_regions) const;
- inline size_t get_young_bytes_to_be_promoted();
+ // Returns the amount of live bytes in young regions with an age below the tenuring threshold.
+ inline size_t get_live_bytes_in_untenurable_regions() const;
- size_t get_young_available_bytes_collected() { return _young_available_bytes_collected; }
+ // Returns the amount of live bytes in old regions in the collection set.
+ inline size_t get_live_bytes_in_old_regions() const;
- inline size_t get_old_garbage();
+ // Returns the amount of live bytes in young regions with an age at or above the tenuring threshold.
+ inline size_t get_live_bytes_in_tenurable_regions() const;
+
+ // Returns the amount of free bytes in young regions in the collection set.
+ size_t get_young_available_bytes_collected() const { return _young_available_bytes_collected; }
+
+ // Returns the amount of garbage in old regions in the collection set.
+ inline size_t get_old_garbage() const;
bool is_preselected(size_t region_idx) {
- assert(_preselected_regions != nullptr, "Missing etsablish after abandon");
+ assert(_preselected_regions != nullptr, "Missing establish after abandon");
return _preselected_regions[region_idx];
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.inline.hpp
index 791e9c73b28e..3ff5f2f81d70 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.inline.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.inline.hpp
@@ -54,19 +54,19 @@ bool ShenandoahCollectionSet::is_in_loc(void* p) const {
return _biased_cset_map[index] == 1;
}
-size_t ShenandoahCollectionSet::get_old_bytes_reserved_for_evacuation() {
+size_t ShenandoahCollectionSet::get_live_bytes_in_old_regions() const {
return _old_bytes_to_evacuate;
}
-size_t ShenandoahCollectionSet::get_young_bytes_reserved_for_evacuation() {
+size_t ShenandoahCollectionSet::get_live_bytes_in_untenurable_regions() const {
return _young_bytes_to_evacuate - _young_bytes_to_promote;
}
-size_t ShenandoahCollectionSet::get_young_bytes_to_be_promoted() {
+size_t ShenandoahCollectionSet::get_live_bytes_in_tenurable_regions() const {
return _young_bytes_to_promote;
}
-size_t ShenandoahCollectionSet::get_old_garbage() {
+size_t ShenandoahCollectionSet::get_old_garbage() const {
return _old_garbage;
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp
index d79e7dcefb9d..5dfbf0af469b 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectorPolicy.cpp
@@ -257,10 +257,10 @@ void ShenandoahCollectorPolicy::print_gc_stats(outputStream* out) const {
out->print_cr("%5zu Full GCs (%.2f%%)", _success_full_gcs, percent_of(_success_full_gcs, completed_gcs));
if (!ExplicitGCInvokesConcurrent) {
- out->print_cr(" %5zu invoked explicitly (%.2f%%)", explicit_requests, percent_of(explicit_requests, _success_concurrent_gcs));
+ out->print_cr(" %5zu invoked explicitly (%.2f%%)", explicit_requests, percent_of(explicit_requests, _success_full_gcs));
}
if (!ShenandoahImplicitGCInvokesConcurrent) {
- out->print_cr(" %5zu invoked implicitly (%.2f%%)", implicit_requests, percent_of(implicit_requests, _success_concurrent_gcs));
+ out->print_cr(" %5zu invoked implicitly (%.2f%%)", implicit_requests, percent_of(implicit_requests, _success_full_gcs));
}
out->print_cr(" %5zu caused by allocation failure (%.2f%%)", _alloc_failure_full, percent_of(_alloc_failure_full, _success_full_gcs));
out->print_cr(" %5zu upgraded from Degenerated GC (%.2f%%)", _alloc_failure_degenerated_upgrade_to_full, percent_of(_alloc_failure_degenerated_upgrade_to_full, _success_full_gcs));
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp
index 64093a7c4bf1..b207b8d2ea6e 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp
@@ -1168,7 +1168,7 @@ void ShenandoahConcurrentGC::op_final_update_refs() {
// Clear cancelled GC, if set. On cancellation path, the block before would handle
// everything.
if (heap->cancelled_gc()) {
- heap->clear_cancelled_gc(true /* clear oom handler */);
+ heap->clear_cancelled_gc();
}
// Has to be done before cset is clear
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
index 9cab6807bd06..458b7ab99afc 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
@@ -43,7 +43,8 @@
ShenandoahControlThread::ShenandoahControlThread() :
ShenandoahController(),
_requested_gc_cause(GCCause::_no_cause_specified),
- _degen_point(ShenandoahGC::_degenerated_outside_cycle) {
+ _degen_point(ShenandoahGC::_degenerated_outside_cycle),
+ _control_lock(CONTROL_LOCK_RANK, "ShenandoahControl_lock", true) {
set_name("Shenandoah Control Thread");
create_and_start();
}
@@ -202,27 +203,8 @@ void ShenandoahControlThread::run_service() {
heuristics->clear_metaspace_oom();
}
- // Commit worker statistics to cycle data
- heap->phase_timings()->flush_par_workers_to_cycle();
- if (ShenandoahPacing) {
- heap->pacer()->flush_stats_to_cycle();
- }
-
- // Print GC stats for current cycle
- {
- LogTarget(Info, gc, stats) lt;
- if (lt.is_enabled()) {
- ResourceMark rm;
- LogStream ls(lt);
- heap->phase_timings()->print_cycle_on(&ls);
- if (ShenandoahPacing) {
- heap->pacer()->print_cycle_on(&ls);
- }
- }
- }
-
- // Commit statistics to globals
- heap->phase_timings()->flush_cycle_to_global();
+ // Manage and print gc stats
+ heap->process_gc_stats();
// Print Metaspace change following GC (if logging is enabled).
MetaspaceUtils::print_metaspace_change(meta_sizes);
@@ -258,7 +240,9 @@ void ShenandoahControlThread::run_service() {
sleep = MIN2(ShenandoahControlIntervalMax, MAX2(1, sleep * 2));
last_sleep_adjust_time = current;
}
- os::naked_short_sleep(sleep);
+
+ MonitorLocker ml(&_control_lock, Mutex::_no_safepoint_check_flag);
+ ml.wait(sleep);
}
}
@@ -368,6 +352,16 @@ void ShenandoahControlThread::request_gc(GCCause::Cause cause) {
}
}
+void ShenandoahControlThread::notify_control_thread(GCCause::Cause cause) {
+ // Although setting gc request is under _controller_lock, the read side (run_service())
+ // does not take the lock. We need to enforce following order, so that read side sees
+ // latest requested gc cause when the flag is set.
+ MonitorLocker controller(&_control_lock, Mutex::_no_safepoint_check_flag);
+ _requested_gc_cause = cause;
+ _gc_requested.set();
+ controller.notify();
+}
+
void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) {
if (should_terminate()) {
log_info(gc)("Control thread is terminating, no more GCs");
@@ -379,8 +373,7 @@ void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) {
// The whitebox caller thread will arrange for itself to wait until the GC notifies
// it that has reached the requested breakpoint (phase in the GC).
if (cause == GCCause::_wb_breakpoint) {
- _requested_gc_cause = cause;
- _gc_requested.set();
+ notify_control_thread(cause);
return;
}
@@ -397,12 +390,7 @@ void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) {
size_t current_gc_id = get_gc_id();
size_t required_gc_id = current_gc_id + 1;
while (current_gc_id < required_gc_id && !should_terminate()) {
- // Although setting gc request is under _gc_waiters_lock, but read side (run_service())
- // does not take the lock. We need to enforce following order, so that read side sees
- // latest requested gc cause when the flag is set.
- _requested_gc_cause = cause;
- _gc_requested.set();
-
+ notify_control_thread(cause);
ml.wait();
current_gc_id = get_gc_id();
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.hpp
index 9d95b5df7ed3..42955d133ac0 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.hpp
@@ -47,6 +47,9 @@ class ShenandoahControlThread: public ShenandoahController {
GCCause::Cause _requested_gc_cause;
ShenandoahGC::ShenandoahDegenPoint _degen_point;
+ // This lock is used to coordinate waking up the control thread
+ Monitor _control_lock;
+
public:
ShenandoahControlThread();
@@ -56,6 +59,8 @@ class ShenandoahControlThread: public ShenandoahController {
void request_gc(GCCause::Cause cause) override;
private:
+ // Sets the requested cause and flag and notifies the control thread
+ void notify_control_thread(GCCause::Cause cause);
bool check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point);
void service_concurrent_normal_cycle(GCCause::Cause cause);
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahController.hpp b/src/hotspot/share/gc/shenandoah/shenandoahController.hpp
index d24f52cb3f17..7837075b0ede 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahController.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahController.hpp
@@ -44,6 +44,9 @@ class ShenandoahController: public ConcurrentGCThread {
shenandoah_padding(2);
protected:
+ const Mutex::Rank WAITERS_LOCK_RANK = Mutex::safepoint - 5;
+ const Mutex::Rank CONTROL_LOCK_RANK = Mutex::nosafepoint - 2;
+
// While we could have a single lock for these, it may risk unblocking
// GC waiters when alloc failure GC cycle finishes. We want instead
// to make complete explicit cycle for demanding customers.
@@ -57,8 +60,8 @@ class ShenandoahController: public ConcurrentGCThread {
ShenandoahController():
_allocs_seen(0),
_gc_id(0),
- _alloc_failure_waiters_lock(Mutex::safepoint-2, "ShenandoahAllocFailureGC_lock", true),
- _gc_waiters_lock(Mutex::safepoint-2, "ShenandoahRequestedGC_lock", true)
+ _alloc_failure_waiters_lock(WAITERS_LOCK_RANK, "ShenandoahAllocFailureWaiters_lock", true),
+ _gc_waiters_lock(WAITERS_LOCK_RANK, "ShenandoahGCWaiters_lock", true)
{ }
// Request a collection cycle. This handles "explicit" gc requests
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp
index 8a0eba5cd9f2..641274d30720 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp
@@ -94,7 +94,7 @@ void ShenandoahDegenGC::op_degenerated() {
// Degenerated GC is STW, but it can also fail. Current mechanics communicates
// GC failure via cancelled_concgc() flag. So, if we detect the failure after
// some phase, we have to upgrade the Degenerate GC to Full GC.
- heap->clear_cancelled_gc(true /* clear oom handler */);
+ heap->clear_cancelled_gc();
#ifdef ASSERT
if (heap->mode()->is_generational()) {
@@ -115,8 +115,7 @@ void ShenandoahDegenGC::op_degenerated() {
}
#endif
- ShenandoahMetricsSnapshot metrics;
- metrics.snap_before();
+ ShenandoahMetricsSnapshot metrics(heap->free_set());
switch (_degen_point) {
// The cases below form the Duff's-like device: it describes the actual GC cycle,
@@ -308,16 +307,18 @@ void ShenandoahDegenGC::op_degenerated() {
Universe::verify();
}
- metrics.snap_after();
-
// Decide if this cycle made good progress, and, if not, should it upgrade to a full GC.
- const bool progress = metrics.is_good_progress(_generation);
+ const bool progress = metrics.is_good_progress();
ShenandoahCollectorPolicy* policy = heap->shenandoah_policy();
policy->record_degenerated(_generation->is_young(), _abbreviated, progress);
if (progress) {
heap->notify_gc_progress();
+ _generation->heuristics()->record_degenerated();
} else if (!heap->mode()->is_generational() || policy->generational_should_upgrade_degenerated_gc()) {
+ // Upgrade to full GC, register full-GC impact on heuristics.
op_degenerated_futile();
+ } else {
+ _generation->heuristics()->record_degenerated();
}
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahEvacInfo.hpp b/src/hotspot/share/gc/shenandoah/shenandoahEvacInfo.hpp
deleted file mode 100644
index 8069fd13afa6..000000000000
--- a/src/hotspot/share/gc/shenandoah/shenandoahEvacInfo.hpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHEVACINFO_HPP
-#define SHARE_GC_SHENANDOAH_SHENANDOAHEVACINFO_HPP
-
-#include "memory/allocation.hpp"
-
-class ShenandoahEvacuationInformation : public StackObj {
- // Values for ShenandoahEvacuationInformation jfr event, sizes stored as bytes
- size_t _collection_set_regions;
- size_t _collection_set_used_before;
- size_t _collection_set_used_after;
- size_t _collected_old;
- size_t _collected_promoted;
- size_t _collected_young;
- size_t _free_regions;
- size_t _regions_promoted_humongous;
- size_t _regions_promoted_regular;
- size_t _regular_promoted_garbage;
- size_t _regular_promoted_free;
- size_t _regions_immediate;
- size_t _immediate_size;
-
-public:
- ShenandoahEvacuationInformation() :
- _collection_set_regions(0), _collection_set_used_before(0), _collection_set_used_after(0),
- _collected_old(0), _collected_promoted(0), _collected_young(0), _free_regions(0),
- _regions_promoted_humongous(0), _regions_promoted_regular(0), _regular_promoted_garbage(0),
- _regular_promoted_free(0), _regions_immediate(0), _immediate_size(0) { }
-
- void set_collection_set_regions(size_t collection_set_regions) {
- _collection_set_regions = collection_set_regions;
- }
-
- void set_collection_set_used_before(size_t used) {
- _collection_set_used_before = used;
- }
-
- void set_collection_set_used_after(size_t used) {
- _collection_set_used_after = used;
- }
-
- void set_collected_old(size_t collected) {
- _collected_old = collected;
- }
-
- void set_collected_promoted(size_t collected) {
- _collected_promoted = collected;
- }
-
- void set_collected_young(size_t collected) {
- _collected_young = collected;
- }
-
- void set_free_regions(size_t freed) {
- _free_regions = freed;
- }
-
- void set_regions_promoted_humongous(size_t humongous) {
- _regions_promoted_humongous = humongous;
- }
-
- void set_regions_promoted_regular(size_t regular) {
- _regions_promoted_regular = regular;
- }
-
- void set_regular_promoted_garbage(size_t garbage) {
- _regular_promoted_garbage = garbage;
- }
-
- void set_regular_promoted_free(size_t free) {
- _regular_promoted_free = free;
- }
-
- void set_regions_immediate(size_t immediate) {
- _regions_immediate = immediate;
- }
-
- void set_immediate_size(size_t size) {
- _immediate_size = size;
- }
-
- size_t collection_set_regions() { return _collection_set_regions; }
- size_t collection_set_used_before() { return _collection_set_used_before; }
- size_t collection_set_used_after() { return _collection_set_used_after; }
- size_t collected_old() { return _collected_old; }
- size_t collected_promoted() { return _collected_promoted; }
- size_t collected_young() { return _collected_young; }
- size_t regions_promoted_humongous() { return _regions_promoted_humongous; }
- size_t regions_promoted_regular() { return _regions_promoted_regular; }
- size_t regular_promoted_garbage() { return _regular_promoted_garbage; }
- size_t regular_promoted_free() { return _regular_promoted_free; }
- size_t free_regions() { return _free_regions; }
- size_t regions_immediate() { return _regions_immediate; }
- size_t immediate_size() { return _immediate_size; }
-};
-
-#endif // SHARE_GC_SHENANDOAH_SHENANDOAHEVACINFO_HPP
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp b/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp
index b1d474fa78da..72d0773eccdf 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp
@@ -23,76 +23,65 @@
*
*/
-#include "gc/shenandoah/shenandoahAgeCensus.hpp"
#include "gc/shenandoah/shenandoahEvacTracker.hpp"
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
#include "gc/shenandoah/shenandoahThreadLocalData.hpp"
#include "runtime/thread.hpp"
#include "runtime/threadSMR.inline.hpp"
-ShenandoahEvacuationStats::ShenandoahEvacuationStats()
- : _evacuations_completed(0), _bytes_completed(0),
- _evacuations_attempted(0), _bytes_attempted(0),
- _use_age_table(ShenandoahGenerationalCensusAtEvac || !ShenandoahGenerationalAdaptiveTenuring),
- _age_table(nullptr) {
- if (_use_age_table) {
- _age_table = new AgeTable(false);
+ShenandoahEvacuationStats::ShenandoahEvacuations* ShenandoahEvacuationStats::get_category(
+ ShenandoahAffiliation from,
+ ShenandoahAffiliation to) {
+ if (from == YOUNG_GENERATION) {
+ if (to == YOUNG_GENERATION) {
+ return &_young;
+ }
+ assert(to == OLD_GENERATION, "If not evacuating to young, must be promotion to old");
+ return &_promotion;
}
+ assert(from == OLD_GENERATION, "If not evacuating from young, then must be from old");
+ return &_old;
}
-AgeTable* ShenandoahEvacuationStats::age_table() const {
- assert(_use_age_table, "Don't call");
- return _age_table;
-}
+void ShenandoahEvacuationStats::begin_evacuation(size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to) {
+ ShenandoahEvacuations* category = get_category(from, to);
+ category->_evacuations_attempted++;
+ category->_bytes_attempted += bytes;
-void ShenandoahEvacuationStats::begin_evacuation(size_t bytes) {
- ++_evacuations_attempted;
- _bytes_attempted += bytes;
}
-void ShenandoahEvacuationStats::end_evacuation(size_t bytes) {
- ++_evacuations_completed;
- _bytes_completed += bytes;
-}
-
-void ShenandoahEvacuationStats::record_age(size_t bytes, uint age) {
- assert(_use_age_table, "Don't call!");
- if (age <= markWord::max_age) { // Filter age sentinel.
- _age_table->add(age, bytes >> LogBytesPerWord);
- }
+void ShenandoahEvacuationStats::end_evacuation(size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to) {
+ ShenandoahEvacuations* category = get_category(from, to);
+ category->_evacuations_completed++;
+ category->_bytes_completed += bytes;
}
void ShenandoahEvacuationStats::accumulate(const ShenandoahEvacuationStats* other) {
- _evacuations_completed += other->_evacuations_completed;
- _bytes_completed += other->_bytes_completed;
- _evacuations_attempted += other->_evacuations_attempted;
- _bytes_attempted += other->_bytes_attempted;
- if (_use_age_table) {
- _age_table->merge(other->age_table());
- }
+ _young.accumulate(other->_young);
+ _old.accumulate(other->_old);
+ _promotion.accumulate(other->_promotion);
}
void ShenandoahEvacuationStats::reset() {
- _evacuations_completed = _evacuations_attempted = 0;
- _bytes_completed = _bytes_attempted = 0;
- if (_use_age_table) {
- _age_table->clear();
- }
+ _young.reset();
+ _old.reset();
+ _promotion.reset();
}
-void ShenandoahEvacuationStats::print_on(outputStream* st) {
-#ifndef PRODUCT
+void ShenandoahEvacuationStats::ShenandoahEvacuations::print_on(outputStream* st) const {
size_t abandoned_size = _bytes_attempted - _bytes_completed;
size_t abandoned_count = _evacuations_attempted - _evacuations_completed;
- st->print_cr("Evacuated %zu%s across %zu objects, "
- "abandoned %zu%s across %zu objects.",
- byte_size_in_proper_unit(_bytes_completed), proper_unit_for_byte_size(_bytes_completed),
- _evacuations_completed,
- byte_size_in_proper_unit(abandoned_size), proper_unit_for_byte_size(abandoned_size),
- abandoned_count);
-#endif
- if (_use_age_table) {
- _age_table->print_on(st);
+ st->print_cr("Evacuated " PROPERFMT" across %zu objects, "
+ "abandoned " PROPERFMT " across %zu objects.",
+ PROPERFMTARGS(_bytes_completed), _evacuations_completed,
+ PROPERFMTARGS(abandoned_size), abandoned_count);
+}
+
+void ShenandoahEvacuationStats::print_on(outputStream* st) const {
+ st->print("Young: "); _young.print_on(st);
+ if (ShenandoahHeap::heap()->mode()->is_generational()) {
+ st->print("Promotion: "); _promotion.print_on(st);
+ st->print("Old: "); _old.print_on(st);
}
}
@@ -103,25 +92,13 @@ void ShenandoahEvacuationTracker::print_global_on(outputStream* st) {
void ShenandoahEvacuationTracker::print_evacuations_on(outputStream* st,
ShenandoahEvacuationStats* workers,
ShenandoahEvacuationStats* mutators) {
- st->print("Workers: ");
+ assert(ShenandoahEvacTracking, "Only when evac tracking is enabled");
+ st->print_cr("Workers: ");
workers->print_on(st);
st->cr();
- st->print("Mutators: ");
+ st->print_cr("Mutators: ");
mutators->print_on(st);
st->cr();
-
- ShenandoahHeap* heap = ShenandoahHeap::heap();
-
- AgeTable young_region_ages(false);
- for (uint i = 0; i < heap->num_regions(); ++i) {
- ShenandoahHeapRegion* r = heap->get_region(i);
- if (r->is_young()) {
- young_region_ages.add(r->age(), r->get_live_data_words());
- }
- }
- st->print("Young regions: ");
- young_region_ages.print_on(st);
- st->cr();
}
class ShenandoahStatAggregator : public ThreadClosure {
@@ -148,26 +125,13 @@ ShenandoahCycleStats ShenandoahEvacuationTracker::flush_cycle_to_global() {
_mutators_global.accumulate(&mutators);
_workers_global.accumulate(&workers);
- if (ShenandoahGenerationalCensusAtEvac || !ShenandoahGenerationalAdaptiveTenuring) {
- // Ingest mutator & worker collected population vectors into the heap's
- // global census data, and use it to compute an appropriate tenuring threshold
- // for use in the next cycle.
- // The first argument is used for any age 0 cohort population that we may otherwise have
- // missed during the census. This is non-zero only when census happens at marking.
- ShenandoahGenerationalHeap::heap()->age_census()->update_census(0, mutators.age_table(), workers.age_table());
- }
-
return {workers, mutators};
}
-void ShenandoahEvacuationTracker::begin_evacuation(Thread* thread, size_t bytes) {
- ShenandoahThreadLocalData::begin_evacuation(thread, bytes);
-}
-
-void ShenandoahEvacuationTracker::end_evacuation(Thread* thread, size_t bytes) {
- ShenandoahThreadLocalData::end_evacuation(thread, bytes);
+void ShenandoahEvacuationTracker::begin_evacuation(Thread* thread, size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to) {
+ ShenandoahThreadLocalData::begin_evacuation(thread, bytes, from, to);
}
-void ShenandoahEvacuationTracker::record_age(Thread* thread, size_t bytes, uint age) {
- ShenandoahThreadLocalData::record_age(thread, bytes, age);
+void ShenandoahEvacuationTracker::end_evacuation(Thread* thread, size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to) {
+ ShenandoahThreadLocalData::end_evacuation(thread, bytes, from, to);
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.hpp b/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.hpp
index 7d195656b111..6e1182680a55 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.hpp
@@ -26,28 +26,54 @@
#define SHARE_GC_SHENANDOAH_SHENANDOAHEVACTRACKER_HPP
#include "gc/shared/ageTable.hpp"
+#include "gc/shenandoah/shenandoahAffiliation.hpp"
#include "utilities/ostream.hpp"
class ShenandoahEvacuationStats : public CHeapObj {
private:
- size_t _evacuations_completed;
- size_t _bytes_completed;
- size_t _evacuations_attempted;
- size_t _bytes_attempted;
-
- bool _use_age_table;
- AgeTable* _age_table;
+ struct ShenandoahEvacuations {
+ size_t _evacuations_completed;
+ size_t _bytes_completed;
+ size_t _evacuations_attempted;
+ size_t _bytes_attempted;
+ ShenandoahEvacuations()
+ : _evacuations_completed(0)
+ , _bytes_completed(0)
+ , _evacuations_attempted(0)
+ , _bytes_attempted(0) {
+ }
+
+ void accumulate(const ShenandoahEvacuations& other) {
+ _evacuations_completed += other._evacuations_completed;
+ _bytes_completed += other._bytes_completed;
+ _evacuations_attempted += other._evacuations_attempted;
+ _bytes_attempted += other._bytes_attempted;
+ }
+
+ void reset() {
+ _evacuations_completed = 0;
+ _bytes_completed = 0;
+ _evacuations_attempted = 0;
+ _bytes_attempted = 0;
+ }
+
+ void print_on(outputStream* st) const;
+ };
+
+ ShenandoahEvacuations* get_category(ShenandoahAffiliation from, ShenandoahAffiliation to);
+
+ ShenandoahEvacuations _young;
+ ShenandoahEvacuations _old;
+ ShenandoahEvacuations _promotion;
public:
- ShenandoahEvacuationStats();
-
- AgeTable* age_table() const;
+ // Record that the current thread is attempting to copy this many bytes.
+ void begin_evacuation(size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to);
- void begin_evacuation(size_t bytes);
- void end_evacuation(size_t bytes);
- void record_age(size_t bytes, uint age);
+ // Record that the current thread has completed copying this many bytes.
+ void end_evacuation(size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to);
- void print_on(outputStream* st);
+ void print_on(outputStream* st) const;
void accumulate(const ShenandoahEvacuationStats* other);
void reset();
};
@@ -66,9 +92,12 @@ class ShenandoahEvacuationTracker : public CHeapObj {
public:
ShenandoahEvacuationTracker() = default;
- void begin_evacuation(Thread* thread, size_t bytes);
- void end_evacuation(Thread* thread, size_t bytes);
- void record_age(Thread* thread, size_t bytes, uint age);
+ // Record that the given thread has begun to evacuate an object of this size.
+ void begin_evacuation(Thread* thread, size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to);
+
+ // Multiple threads may attempt to evacuate the same object, but only the successful thread will end the evacuation.
+ // Evacuations that were begun, but not ended are considered 'abandoned'.
+ void end_evacuation(Thread* thread, size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to);
void print_global_on(outputStream* st);
void print_evacuations_on(outputStream* st,
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp
index 27ff45e67de1..b9455ebfeb0f 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp
@@ -104,21 +104,18 @@ void ShenandoahFullGC::entry_full(GCCause::Cause cause) {
}
void ShenandoahFullGC::op_full(GCCause::Cause cause) {
- ShenandoahMetricsSnapshot metrics;
- metrics.snap_before();
+ ShenandoahHeap* const heap = ShenandoahHeap::heap();
+
+ ShenandoahMetricsSnapshot metrics(heap->free_set());
// Perform full GC
do_it(cause);
- ShenandoahHeap* const heap = ShenandoahHeap::heap();
-
if (heap->mode()->is_generational()) {
ShenandoahGenerationalFullGC::handle_completion(heap);
}
- metrics.snap_after();
-
- if (metrics.is_good_progress(heap->global_generation())) {
+ if (metrics.is_good_progress()) {
heap->notify_gc_progress();
} else {
// Nothing to do. Tell the allocation path that we have failed to make
@@ -893,8 +890,11 @@ class ShenandoahCompactObjectsClosure : public ObjectClosure {
Copy::aligned_conjoint_words(compact_from, compact_to, size);
oop new_obj = cast_to_oop(compact_to);
- ContinuationGCSupport::relativize_stack_chunk(new_obj);
+ // Restore the mark word before relativizing the stack chunk. The copy's
+ // mark word contains the full GC forwarding encoding, which would cause
+ // is_stackChunk() to read garbage (especially with compact headers).
new_obj->init_mark();
+ ContinuationGCSupport::relativize_stack_chunk(new_obj);
}
}
};
@@ -1168,7 +1168,7 @@ ShenandoahGenerationalHeap::TransferResult ShenandoahFullGC::phase5_epilog() {
// Set mark incomplete because the marking bitmaps have been reset except pinned regions.
heap->global_generation()->set_mark_incomplete();
- heap->clear_cancelled_gc(true /* clear oom handler */);
+ heap->clear_cancelled_gc();
}
_preserved_marks->restore(heap->workers());
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp
index 7b3839dc1980..664ec40e37e0 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp
@@ -74,6 +74,9 @@ class ShenandoahResetBitmapClosure final : public ShenandoahHeapRegionClosure {
}
}
+ // Bitmap reset task is heavy-weight and benefits from much smaller tasks than the default.
+ size_t parallel_region_stride() override { return 8; }
+
bool is_thread_safe() override { return true; }
};
@@ -151,8 +154,8 @@ size_t ShenandoahGeneration::bytes_allocated_since_gc_start() const {
return Atomic::load(&_bytes_allocated_since_gc_start);
}
-void ShenandoahGeneration::reset_bytes_allocated_since_gc_start() {
- Atomic::store(&_bytes_allocated_since_gc_start, (size_t)0);
+void ShenandoahGeneration::reset_bytes_allocated_since_gc_start(size_t initial_bytes_allocated) {
+ Atomic::store(&_bytes_allocated_since_gc_start, initial_bytes_allocated);
}
void ShenandoahGeneration::increase_allocated(size_t bytes) {
@@ -382,11 +385,11 @@ void ShenandoahGeneration::adjust_evacuation_budgets(ShenandoahHeap* const heap,
// available that results from a decrease in memory consumed by old evacuation is not necessarily available to be loaned
// to young-gen.
- size_t region_size_bytes = ShenandoahHeapRegion::region_size_bytes();
+ const size_t region_size_bytes = ShenandoahHeapRegion::region_size_bytes();
ShenandoahOldGeneration* const old_generation = heap->old_generation();
ShenandoahYoungGeneration* const young_generation = heap->young_generation();
- size_t old_evacuated = collection_set->get_old_bytes_reserved_for_evacuation();
+ const size_t old_evacuated = collection_set->get_live_bytes_in_old_regions();
size_t old_evacuated_committed = (size_t) (ShenandoahOldEvacWaste * double(old_evacuated));
size_t old_evacuation_reserve = old_generation->get_evacuation_reserve();
@@ -399,14 +402,15 @@ void ShenandoahGeneration::adjust_evacuation_budgets(ShenandoahHeap* const heap,
// Leave old_evac_reserve as previously configured
} else if (old_evacuated_committed < old_evacuation_reserve) {
// This happens if the old-gen collection consumes less than full budget.
+ log_debug(gc, cset)("Shrinking old evac reserve to match old_evac_commited: " PROPERFMT, PROPERFMTARGS(old_evacuated_committed));
old_evacuation_reserve = old_evacuated_committed;
old_generation->set_evacuation_reserve(old_evacuation_reserve);
}
- size_t young_advance_promoted = collection_set->get_young_bytes_to_be_promoted();
+ size_t young_advance_promoted = collection_set->get_live_bytes_in_tenurable_regions();
size_t young_advance_promoted_reserve_used = (size_t) (ShenandoahPromoEvacWaste * double(young_advance_promoted));
- size_t young_evacuated = collection_set->get_young_bytes_reserved_for_evacuation();
+ size_t young_evacuated = collection_set->get_live_bytes_in_untenurable_regions();
size_t young_evacuated_reserve_used = (size_t) (ShenandoahEvacWaste * double(young_evacuated));
size_t total_young_available = young_generation->available_with_reserve();
@@ -524,7 +528,7 @@ inline void assert_no_in_place_promotions() {
// that this allows us to more accurately budget memory to hold the results of evacuation. Memory for evacuation
// of aged regions must be reserved in the old generation. Memory for evacuation of all other regions must be
// reserved in the young generation.
-size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
+size_t ShenandoahGeneration::select_aged_regions(const size_t old_promotion_reserve) {
// There should be no regions configured for subsequent in-place-promotions carried over from the previous cycle.
assert_no_in_place_promotions();
@@ -535,7 +539,8 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
const size_t old_garbage_threshold = (ShenandoahHeapRegion::region_size_bytes() * ShenandoahOldGarbageThreshold) / 100;
- size_t old_consumed = 0;
+ const size_t pip_used_threshold = (ShenandoahHeapRegion::region_size_bytes() * ShenandoahGenerationalMinPIPUsage) / 100;
+
size_t promo_potential = 0;
size_t candidates = 0;
@@ -557,10 +562,8 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
continue;
}
if (heap->is_tenurable(r)) {
- if ((r->garbage() < old_garbage_threshold)) {
- // This tenure-worthy region has too little garbage, so we do not want to expend the copying effort to
- // reclaim the garbage; instead this region may be eligible for promotion-in-place to the
- // old generation.
+ if ((r->garbage() < old_garbage_threshold) && (r->used() > pip_used_threshold)) {
+ // We prefer to promote this region in place because it has a small amount of garbage and a large usage.
HeapWord* tams = ctx->top_at_mark_start(r);
HeapWord* original_top = r->top();
if (!heap->is_concurrent_old_mark_in_progress() && tams == original_top) {
@@ -586,7 +589,7 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
// Else, we do not promote this region (either in place or by copy) because it has received new allocations.
// During evacuation, we exclude from promotion regions for which age > tenure threshold, garbage < garbage-threshold,
- // and get_top_before_promote() != tams
+ // used > pip_used_threshold, and get_top_before_promote() != tams
} else {
// Record this promotion-eligible candidate region. After sorting and selecting the best candidates below,
// we may still decide to exclude this promotion-eligible region from the current collection set. If this
@@ -620,17 +623,21 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
// Note that we keep going even if one region is excluded from selection.
// Subsequent regions may be selected if they have smaller live data.
}
+
+ log_info(gc, ergo)("Promotion potential of aged regions with sufficient garbage: " PROPERFMT, PROPERFMTARGS(promo_potential));
+
// Sort in increasing order according to live data bytes. Note that candidates represents the number of regions
// that qualify to be promoted by evacuation.
+ size_t old_consumed = 0;
if (candidates > 0) {
size_t selected_regions = 0;
size_t selected_live = 0;
QuickSort::sort(sorted_regions, candidates, compare_by_aged_live);
for (size_t i = 0; i < candidates; i++) {
ShenandoahHeapRegion* const region = sorted_regions[i]._region;
- size_t region_live_data = sorted_regions[i]._live_data;
- size_t promotion_need = (size_t) (region_live_data * ShenandoahPromoEvacWaste);
- if (old_consumed + promotion_need <= old_available) {
+ const size_t region_live_data = sorted_regions[i]._live_data;
+ const size_t promotion_need = (size_t) (region_live_data * ShenandoahPromoEvacWaste);
+ if (old_consumed + promotion_need <= old_promotion_reserve) {
old_consumed += promotion_need;
candidate_regions_for_promotion_by_copy[region->index()] = true;
selected_regions++;
@@ -644,9 +651,9 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
// We keep going even if one region is excluded from selection because we need to accumulate all eligible
// regions that are not preselected into promo_potential
}
- log_debug(gc)("Preselected %zu regions containing %zu live bytes,"
- " consuming: %zu of budgeted: %zu",
- selected_regions, selected_live, old_consumed, old_available);
+ log_debug(gc, ergo)("Preselected %zu regions containing " PROPERFMT " live data,"
+ " consuming: " PROPERFMT " of budgeted: " PROPERFMT,
+ selected_regions, PROPERFMTARGS(selected_live), PROPERFMTARGS(old_consumed), PROPERFMTARGS(old_promotion_reserve));
}
heap->old_generation()->set_pad_for_promote_in_place(promote_in_place_pad);
@@ -678,7 +685,7 @@ void ShenandoahGeneration::prepare_regions_and_collection_set(bool concurrent) {
}
// Tally the census counts and compute the adaptive tenuring threshold
- if (is_generational && ShenandoahGenerationalAdaptiveTenuring && !ShenandoahGenerationalCensusAtEvac) {
+ if (is_generational) {
// Objects above TAMS weren't included in the age census. Since they were all
// allocated in this cycle they belong in the age 0 cohort. We walk over all
// young regions and sum the volume of objects between TAMS and top.
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp
index 2b7aca342dad..52b08fc0c520 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp
@@ -97,7 +97,7 @@ class ShenandoahGeneration : public CHeapObj, public ShenandoahSpaceInfo {
// regions, which are marked in the preselected_regions() indicator
// array of the heap's collection set, which should be initialized
// to false.
- size_t select_aged_regions(size_t old_available);
+ size_t select_aged_regions(size_t old_promotion_reserve);
size_t available(size_t capacity) const;
@@ -142,7 +142,12 @@ class ShenandoahGeneration : public CHeapObj, public ShenandoahSpaceInfo {
size_t soft_available() const override;
size_t bytes_allocated_since_gc_start() const override;
- void reset_bytes_allocated_since_gc_start();
+
+ // Reset the bytes allocated within this generation since the start of GC. The argument initial_bytes_allocated
+ // is normally zero. In the case that some memory was allocated following the last allocation rate sample that
+ // precedes the start of GC, the number of bytes allocated is supplied as the initial value of bytes_allocated_since_gc_start.
+ // We will behave as if these bytes were allocated after the start of GC.
+ void reset_bytes_allocated_since_gc_start(size_t initial_bytes_allocated);
void increase_allocated(size_t bytes);
// These methods change the capacity of the generation by adding or subtracting the given number of bytes from the current
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp
index 2555f73d018d..125c60b54460 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp
@@ -47,7 +47,7 @@
#include "utilities/events.hpp"
ShenandoahGenerationalControlThread::ShenandoahGenerationalControlThread() :
- _control_lock(Mutex::nosafepoint - 2, "ShenandoahGCRequest_lock", true),
+ _control_lock(CONTROL_LOCK_RANK, "ShenandoahGCRequest_lock", true),
_requested_gc_cause(GCCause::_no_gc),
_requested_generation(nullptr),
_gc_mode(none),
@@ -119,10 +119,9 @@ void ShenandoahGenerationalControlThread::check_for_request(ShenandoahGCRequest&
// failure (degenerated cycle), or old marking was cancelled to run a young collection.
// In either case, the correct generation for the next cycle can be determined by
// the cancellation cause.
- request.cause = _heap->cancelled_cause();
+ request.cause = _heap->clear_cancellation(GCCause::_shenandoah_concurrent_gc);
if (request.cause == GCCause::_shenandoah_concurrent_gc) {
request.generation = _heap->young_generation();
- _heap->clear_cancelled_gc(false);
}
} else {
request.cause = _requested_gc_cause;
@@ -210,6 +209,24 @@ ShenandoahGenerationalControlThread::GCMode ShenandoahGenerationalControlThread:
return request.generation->is_old() ? servicing_old : concurrent_normal;
}
+void ShenandoahGenerationalControlThread::maybe_print_young_region_ages() const {
+ LogTarget(Debug, gc, age) lt;
+ if (lt.is_enabled()) {
+ LogStream ls(lt);
+ AgeTable young_region_ages(false);
+ for (uint i = 0; i < _heap->num_regions(); ++i) {
+ const ShenandoahHeapRegion* r = _heap->get_region(i);
+ if (r->is_young()) {
+ young_region_ages.add(r->age(), r->get_live_data_words());
+ }
+ }
+
+ ls.print("Young regions: ");
+ young_region_ages.print_on(&ls);
+ ls.cr();
+ }
+}
+
void ShenandoahGenerationalControlThread::maybe_set_aging_cycle() {
if (_age_period-- == 0) {
_heap->set_aging_cycle(true);
@@ -304,7 +321,11 @@ void ShenandoahGenerationalControlThread::run_gc_cycle(const ShenandoahGCRequest
_heap->global_generation()->heuristics()->clear_metaspace_oom();
}
- process_phase_timings();
+ // Manage and print gc stats
+ _heap->process_gc_stats();
+
+ // Print table for young region ages if log is enabled
+ maybe_print_young_region_ages();
// Print Metaspace change following GC (if logging is enabled).
MetaspaceUtils::print_metaspace_change(meta_sizes);
@@ -328,35 +349,6 @@ void ShenandoahGenerationalControlThread::run_gc_cycle(const ShenandoahGCRequest
gc_mode_name(gc_mode()), GCCause::to_string(request.cause), request.generation->name(), GCCause::to_string(_heap->cancelled_cause()));
}
-void ShenandoahGenerationalControlThread::process_phase_timings() const {
- // Commit worker statistics to cycle data
- _heap->phase_timings()->flush_par_workers_to_cycle();
- if (ShenandoahPacing) {
- _heap->pacer()->flush_stats_to_cycle();
- }
-
- ShenandoahEvacuationTracker* evac_tracker = _heap->evac_tracker();
- ShenandoahCycleStats evac_stats = evac_tracker->flush_cycle_to_global();
-
- // Print GC stats for current cycle
- {
- LogTarget(Info, gc, stats) lt;
- if (lt.is_enabled()) {
- ResourceMark rm;
- LogStream ls(lt);
- _heap->phase_timings()->print_cycle_on(&ls);
- evac_tracker->print_evacuations_on(&ls, &evac_stats.workers,
- &evac_stats.mutators);
- if (ShenandoahPacing) {
- _heap->pacer()->print_cycle_on(&ls);
- }
- }
- }
-
- // Commit statistics to globals
- _heap->phase_timings()->flush_cycle_to_global();
-}
-
// Young and old concurrent cycles are initiated by the regulator. Implicit
// and explicit GC requests are handled by the controller thread and always
// run a global cycle (which is concurrent by default, but may be overridden
@@ -432,7 +424,7 @@ void ShenandoahGenerationalControlThread::service_concurrent_old_cycle(const She
set_gc_mode(bootstrapping_old);
young_generation->set_old_gen_task_queues(old_generation->task_queues());
service_concurrent_cycle(young_generation, request.cause, true);
- process_phase_timings();
+ _heap->process_gc_stats();
if (_heap->cancelled_gc()) {
// Young generation bootstrap cycle has failed. Concurrent mark for old generation
// is going to resume after degenerated bootstrap cycle completes.
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp
index 1586205742a7..6a4f5bde5789 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp
@@ -129,9 +129,6 @@ class ShenandoahGenerationalControlThread: public ShenandoahController {
// Returns true if the old generation marking was interrupted to allow a young cycle.
bool preempt_old_marking(ShenandoahGeneration* generation);
- // Flushes cycle timings to global timings and prints the phase timings for the last completed cycle.
- void process_phase_timings() const;
-
// Set the gc mode and post a notification if it has changed. The overloaded variant should be used
// when the _control_lock is already held.
void set_gc_mode(GCMode new_mode);
@@ -160,6 +157,9 @@ class ShenandoahGenerationalControlThread: public ShenandoahController {
GCMode prepare_for_allocation_failure_gc(ShenandoahGCRequest &request);
GCMode prepare_for_explicit_gc(ShenandoahGCRequest &request) const;
GCMode prepare_for_concurrent_gc(const ShenandoahGCRequest &request) const;
+
+ // Print table for young region ages if log is enabled
+ void maybe_print_young_region_ages() const;
};
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHGENERATIONALCONTROLTHREAD_HPP
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp
index b538f7b1417e..3f0db4fb8eab 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp
@@ -150,7 +150,13 @@ void ShenandoahGenerationalEvacuationTask::maybe_promote_region(ShenandoahHeapRe
// more garbage than ShenandoahOldGarbageThreshold, we'll promote by evacuation. If there is room for evacuation
// in this cycle, the region will be in the collection set. If there is not room, the region will be promoted
// by evacuation in some future GC cycle.
- promote_humongous(r);
+
+ // We do not promote primitive arrays because there's no performance penalty keeping them in young. When/if they
+ // become garbage, reclaiming the memory from young is much quicker and more efficient than reclaiming them from old.
+ oop obj = cast_to_oop(r->bottom());
+ if (!obj->is_typeArray()) {
+ promote_humongous(r);
+ }
} else if (r->is_regular() && (r->get_top_before_promote() != nullptr)) {
// Likewise, we cannot put promote-in-place regions into the collection set because that would also trigger
// the LRB to copy on reference fetch.
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp
index feb82dd05271..2c817774b374 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp
@@ -80,7 +80,6 @@ size_t ShenandoahGenerationalHeap::unsafe_max_tlab_alloc(Thread *thread) const {
ShenandoahGenerationalHeap::ShenandoahGenerationalHeap(ShenandoahCollectorPolicy* policy) :
ShenandoahHeap(policy),
_age_census(nullptr),
- _evac_tracker(new ShenandoahEvacuationTracker()),
_min_plab_size(calculate_min_plab()),
_max_plab_size(calculate_max_plab()),
_regulator_thread(nullptr),
@@ -100,18 +99,6 @@ void ShenandoahGenerationalHeap::print_init_logger() const {
logger.print_all();
}
-void ShenandoahGenerationalHeap::print_tracing_info() const {
- ShenandoahHeap::print_tracing_info();
-
- LogTarget(Info, gc, stats) lt;
- if (lt.is_enabled()) {
- LogStream ls(lt);
- ls.cr();
- ls.cr();
- evac_tracker()->print_global_on(&ls);
- }
-}
-
void ShenandoahGenerationalHeap::initialize_heuristics() {
// Initialize global generation and heuristics even in generational mode.
ShenandoahHeap::initialize_heuristics();
@@ -123,7 +110,6 @@ void ShenandoahGenerationalHeap::initialize_heuristics() {
_generation_sizer.heap_size_changed(max_capacity());
size_t initial_capacity_young = _generation_sizer.max_young_size();
size_t max_capacity_young = _generation_sizer.max_young_size();
- size_t initial_capacity_old = max_capacity() - max_capacity_young;
size_t max_capacity_old = max_capacity() - initial_capacity_young;
_young_generation = new ShenandoahYoungGeneration(max_workers(), max_capacity_young);
@@ -280,6 +266,7 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, Shena
// the requested object does not fit within the current plab but the plab still has an "abundance" of memory,
// where abundance is defined as >= ShenGenHeap::plab_min_size(). In the former case, we try shrinking the
// desired PLAB size to the minimum and retry PLAB allocation to avoid cascading of shared memory allocations.
+ // Shrinking the desired PLAB size may allow us to eke out a small PLAB while staying beneath evacuation reserve.
if (plab->words_remaining() < plab_min_size()) {
ShenandoahThreadLocalData::set_plab_size(thread, plab_min_size());
copy = allocate_from_plab(thread, size, is_promotion);
@@ -337,8 +324,11 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, Shena
return ShenandoahBarrierSet::resolve_forwarded(p);
}
+ if (ShenandoahEvacTracking) {
+ evac_tracker()->begin_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen);
+ }
+
// Copy the object:
- NOT_PRODUCT(evac_tracker()->begin_evacuation(thread, size * HeapWordSize));
Copy::aligned_disjoint_words(cast_from_oop(p), copy, size);
oop copy_val = cast_to_oop(copy);
@@ -347,20 +337,23 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, Shena
ShenandoahHeap::increase_object_age(copy_val, from_region->age() + 1);
}
+ // Relativize stack chunks before publishing the copy. After the forwarding CAS,
+ // mutators can see the copy and thaw it via the fast path if flags == 0. We must
+ // relativize derived pointers and set gc_mode before that happens. Skip if the
+ // copy's mark word is already a forwarding pointer (another thread won the race
+ // and overwrote the original's header before we copied it).
+ if (!ShenandoahForwarding::is_forwarded(copy_val)) {
+ ContinuationGCSupport::relativize_stack_chunk(copy_val);
+ }
+
// Try to install the new forwarding pointer.
oop result = ShenandoahForwarding::try_update_forwardee(p, copy_val);
if (result == copy_val) {
// Successfully evacuated. Our copy is now the public one!
-
- // This is necessary for virtual thread support. This uses the mark word without
- // considering that it may now be a forwarding pointer (and could therefore crash).
- // Secondarily, we do not want to spend cycles relativizing stack chunks for oops
- // that lost the evacuation race (and will therefore not become visible). It is
- // safe to do this on the public copy (this is also done during concurrent mark).
- ContinuationGCSupport::relativize_stack_chunk(copy_val);
-
- // Record that the evacuation succeeded
- NOT_PRODUCT(evac_tracker()->end_evacuation(thread, size * HeapWordSize));
+ if (ShenandoahEvacTracking) {
+ // Record that the evacuation succeeded
+ evac_tracker()->end_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen);
+ }
if (target_gen == OLD_GENERATION) {
old_generation()->handle_evacuation(copy, size, from_region->is_young());
@@ -368,11 +361,6 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, Shena
// When copying to the old generation above, we don't care
// about recording object age in the census stats.
assert(target_gen == YOUNG_GENERATION, "Error");
- // We record this census only when simulating pre-adaptive tenuring behavior, or
- // when we have been asked to record the census at evacuation rather than at mark
- if (ShenandoahGenerationalCensusAtEvac || !ShenandoahGenerationalAdaptiveTenuring) {
- evac_tracker()->record_age(thread, size * HeapWordSize, ShenandoahHeap::get_object_age(copy_val));
- }
}
shenandoah_assert_correct(nullptr, copy_val);
return copy_val;
@@ -449,9 +437,8 @@ inline HeapWord* ShenandoahGenerationalHeap::allocate_from_plab(Thread* thread,
// Establish a new PLAB and allocate size HeapWords within it.
HeapWord* ShenandoahGenerationalHeap::allocate_from_plab_slow(Thread* thread, size_t size, bool is_promotion) {
- // New object should fit the PLAB size
-
assert(mode()->is_generational(), "PLABs only relevant to generational GC");
+
const size_t plab_min_size = this->plab_min_size();
// PLABs are aligned to card boundaries to avoid synchronization with concurrent
// allocations in other PLABs.
@@ -464,23 +451,24 @@ HeapWord* ShenandoahGenerationalHeap::allocate_from_plab_slow(Thread* thread, si
}
// Expand aggressively, doubling at each refill in this epoch, ceiling at plab_max_size()
- size_t future_size = MIN2(cur_size * 2, plab_max_size());
+ const size_t future_size = MIN2(cur_size * 2, plab_max_size());
// Doubling, starting at a card-multiple, should give us a card-multiple. (Ceiling and floor
// are card multiples.)
assert(is_aligned(future_size, CardTable::card_size_in_words()), "Card multiple by construction, future_size: %zu"
- ", card_size: %zu, cur_size: %zu, max: %zu",
- future_size, (size_t) CardTable::card_size_in_words(), cur_size, plab_max_size());
+ ", card_size: %u, cur_size: %zu, max: %zu",
+ future_size, CardTable::card_size_in_words(), cur_size, plab_max_size());
// Record new heuristic value even if we take any shortcut. This captures
// the case when moderately-sized objects always take a shortcut. At some point,
// heuristics should catch up with them. Note that the requested cur_size may
// not be honored, but we remember that this is the preferred size.
- log_debug(gc, free)("Set new PLAB size: %zu", future_size);
+ log_debug(gc, plab)("Set next PLAB refill size: %zu bytes", future_size * HeapWordSize);
ShenandoahThreadLocalData::set_plab_size(thread, future_size);
+
if (cur_size < size) {
// The PLAB to be allocated is still not large enough to hold the object. Fall back to shared allocation.
// This avoids retiring perfectly good PLABs in order to represent a single large object allocation.
- log_debug(gc, free)("Current PLAB size (%zu) is too small for %zu", cur_size, size);
+ log_debug(gc, plab)("Current PLAB size (%zu) is too small for %zu", cur_size * HeapWordSize, size * HeapWordSize);
return nullptr;
}
@@ -566,6 +554,7 @@ void ShenandoahGenerationalHeap::retire_plab(PLAB* plab, Thread* thread) {
ShenandoahThreadLocalData::reset_plab_promoted(thread);
ShenandoahThreadLocalData::set_plab_actual_size(thread, 0);
if (not_promoted > 0) {
+ log_debug(gc, plab)("Retire PLAB, unexpend unpromoted: %zu", not_promoted * HeapWordSize);
old_generation()->unexpend_promoted(not_promoted);
}
const size_t original_waste = plab->waste();
@@ -577,8 +566,8 @@ void ShenandoahGenerationalHeap::retire_plab(PLAB* plab, Thread* thread) {
if (top != nullptr && plab->waste() > original_waste && is_in_old(top)) {
// If retiring the plab created a filler object, then we need to register it with our card scanner so it can
// safely walk the region backing the plab.
- log_debug(gc)("retire_plab() is registering remnant of size %zu at " PTR_FORMAT,
- plab->waste() - original_waste, p2i(top));
+ log_debug(gc, plab)("retire_plab() is registering remnant of size %zu at " PTR_FORMAT,
+ (plab->waste() - original_waste) * HeapWordSize, p2i(top));
// No lock is necessary because the PLAB memory is aligned on card boundaries.
old_generation()->card_scan()->register_object_without_lock(top);
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp
index fb356873356d..adf9c73a2322 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp
@@ -53,7 +53,6 @@ class ShenandoahGenerationalHeap : public ShenandoahHeap {
}
void print_init_logger() const override;
- void print_tracing_info() const override;
size_t unsafe_max_tlab_alloc(Thread *thread) const override;
@@ -64,8 +63,6 @@ class ShenandoahGenerationalHeap : public ShenandoahHeap {
ShenandoahSharedFlag _is_aging_cycle;
// Age census used for adapting tenuring threshold
ShenandoahAgeCensus* _age_census;
- // Used primarily to look for failed evacuation attempts.
- ShenandoahEvacuationTracker* _evac_tracker;
public:
void set_aging_cycle(bool cond) {
@@ -83,9 +80,6 @@ class ShenandoahGenerationalHeap : public ShenandoahHeap {
inline bool is_tenurable(const ShenandoahHeapRegion* r) const;
- ShenandoahEvacuationTracker* evac_tracker() const {
- return _evac_tracker;
- }
// Ages regions that haven't been used for allocations in the current cycle.
// Resets ages for regions that have been used for allocations.
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
index a56ada222d7e..c6e529fcaa2d 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
@@ -574,7 +574,8 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) :
_bitmap_region_special(false),
_aux_bitmap_region_special(false),
_liveness_cache(nullptr),
- _collection_set(nullptr)
+ _collection_set(nullptr),
+ _evac_tracker(new ShenandoahEvacuationTracker())
{
// Initialize GC mode early, many subsequent initialization procedures depend on it
initialize_mode();
@@ -1287,7 +1288,7 @@ void ShenandoahHeap::evacuate_collection_set(bool concurrent) {
void ShenandoahHeap::concurrent_prepare_for_update_refs() {
{
- // Java threads take this lock while they are being attached and added to the list of thread.
+ // Java threads take this lock while they are being attached and added to the list of threads.
// If another thread holds this lock before we update the gc state, it will receive a stale
// gc state, but they will have been added to the list of java threads and so will be corrected
// by the following handshake.
@@ -1394,16 +1395,32 @@ oop ShenandoahHeap::try_evacuate_object(oop p, Thread* thread, ShenandoahHeapReg
return ShenandoahBarrierSet::resolve_forwarded(p);
}
+ if (ShenandoahEvacTracking) {
+ evac_tracker()->begin_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen);
+ }
+
// Copy the object:
Copy::aligned_disjoint_words(cast_from_oop(p), copy, size);
- // Try to install the new forwarding pointer.
oop copy_val = cast_to_oop(copy);
+
+ // Relativize stack chunks before publishing the copy. After the forwarding CAS,
+ // mutators can see the copy and thaw it via the fast path if flags == 0. We must
+ // relativize derived pointers and set gc_mode before that happens. Skip if the
+ // copy's mark word is already a forwarding pointer (another thread won the race
+ // and overwrote the original's header before we copied it).
+ if (!ShenandoahForwarding::is_forwarded(copy_val)) {
+ ContinuationGCSupport::relativize_stack_chunk(copy_val);
+ }
+
+ // Try to install the new forwarding pointer.
oop result = ShenandoahForwarding::try_update_forwardee(p, copy_val);
if (result == copy_val) {
// Successfully evacuated. Our copy is now the public one!
- ContinuationGCSupport::relativize_stack_chunk(copy_val);
shenandoah_assert_correct(nullptr, copy_val);
+ if (ShenandoahEvacTracking) {
+ evac_tracker()->end_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen);
+ }
return copy_val;
} else {
// Failed to evacuate. We need to deal with the object that is left behind. Since this
@@ -1457,6 +1474,31 @@ void ShenandoahHeap::print_heap_regions_on(outputStream* st) const {
}
}
+void ShenandoahHeap::process_gc_stats() const {
+ // Commit worker statistics to cycle data
+ phase_timings()->flush_par_workers_to_cycle();
+
+ if (ShenandoahPacing) {
+ pacer()->flush_stats_to_cycle();
+ }
+
+ // Print GC stats for current cycle
+ LogTarget(Info, gc, stats) lt;
+ if (lt.is_enabled()) {
+ ResourceMark rm;
+ LogStream ls(lt);
+ phase_timings()->print_cycle_on(&ls);
+ if (ShenandoahEvacTracking) {
+ ShenandoahCycleStats evac_stats = evac_tracker()->flush_cycle_to_global();
+ evac_tracker()->print_evacuations_on(&ls, &evac_stats.workers,
+ &evac_stats.mutators);
+ }
+ }
+
+ // Commit statistics to globals
+ phase_timings()->flush_cycle_to_global();
+}
+
size_t ShenandoahHeap::trash_humongous_region_at(ShenandoahHeapRegion* start) const {
assert(start->is_humongous_start(), "reclaim regions starting with the first one");
assert(!start->has_live(), "liveness must be zero");
@@ -1571,8 +1613,8 @@ void ShenandoahHeap::collect_as_vm_thread(GCCause::Cause cause) {
// cycle. We _could_ cancel the concurrent cycle and then try to run a cycle directly
// on the VM thread, but this would confuse the control thread mightily and doesn't
// seem worth the trouble. Instead, we will have the caller thread run (and wait for) a
- // concurrent cycle in the prologue of the heap inspect/dump operation. This is how
- // other concurrent collectors in the JVM handle this scenario as well.
+ // concurrent cycle in the prologue of the heap inspect/dump operation (see VM_HeapDumper::doit_prologue).
+ // This is how other concurrent collectors in the JVM handle this scenario as well.
assert(Thread::current()->is_VM_thread(), "Should be the VM thread");
guarantee(cause == GCCause::_heap_dump || cause == GCCause::_heap_inspection, "Invalid cause");
}
@@ -1582,7 +1624,10 @@ void ShenandoahHeap::collect(GCCause::Cause cause) {
}
void ShenandoahHeap::do_full_collection(bool clear_all_soft_refs) {
- //assert(false, "Shouldn't need to do full collections");
+ // This method is only called by `CollectedHeap::collect_as_vm_thread`, which we have
+ // overridden to do nothing. See the comment there for an explanation of how heap inspections
+ // work for Shenandoah.
+ ShouldNotReachHere();
}
HeapWord* ShenandoahHeap::block_start(const void* addr) const {
@@ -1633,6 +1678,12 @@ void ShenandoahHeap::print_tracing_info() const {
ResourceMark rm;
LogStream ls(lt);
+ if (ShenandoahEvacTracking) {
+ evac_tracker()->print_global_on(&ls);
+ ls.cr();
+ ls.cr();
+ }
+
phase_timings()->print_global_on(&ls);
ls.cr();
@@ -2003,7 +2054,7 @@ void ShenandoahHeap::parallel_heap_region_iterate(ShenandoahHeapRegionClosure* b
assert(blk->is_thread_safe(), "Only thread-safe closures here");
const uint active_workers = workers()->active_workers();
const size_t n_regions = num_regions();
- size_t stride = ShenandoahParallelRegionStride;
+ size_t stride = blk->parallel_region_stride();
if (stride == 0 && active_workers > 1) {
// Automatically derive the stride to balance the work between threads
// evenly. Do not try to split work if below the reasonable threshold.
@@ -2322,12 +2373,27 @@ address ShenandoahHeap::in_cset_fast_test_addr() {
}
void ShenandoahHeap::reset_bytes_allocated_since_gc_start() {
+ // It is important to force_alloc_rate_sample() before the associated generation's bytes_allocated has been reset.
+ // Note that there is no lock to prevent additional alloations between sampling bytes_allocated_since_gc_start() and
+ // reset_bytes_allocated_since_gc_start(). If additional allocations happen, they will be ignored in the average
+ // allocation rate computations. This effect is considered to be be negligible.
+
+ // unaccounted_bytes is the bytes not accounted for by our forced sample. If the sample interval is too short,
+ // the "forced sample" will not happen, and any recently allocated bytes are "unaccounted for". We pretend these
+ // bytes are allocated after the start of subsequent gc.
+ size_t unaccounted_bytes;
if (mode()->is_generational()) {
- young_generation()->reset_bytes_allocated_since_gc_start();
- old_generation()->reset_bytes_allocated_since_gc_start();
+ size_t bytes_allocated = young_generation()->bytes_allocated_since_gc_start();
+ unaccounted_bytes = young_generation()->heuristics()->force_alloc_rate_sample(bytes_allocated);
+ young_generation()->reset_bytes_allocated_since_gc_start(unaccounted_bytes);
+ unaccounted_bytes = 0;
+ old_generation()->reset_bytes_allocated_since_gc_start(unaccounted_bytes);
+ } else {
+ size_t bytes_allocated = global_generation()->bytes_allocated_since_gc_start();
+ // Single-gen Shenandoah uses global heuristics.
+ unaccounted_bytes = heuristics()->force_alloc_rate_sample(bytes_allocated);
}
-
- global_generation()->reset_bytes_allocated_since_gc_start();
+ global_generation()->reset_bytes_allocated_since_gc_start(unaccounted_bytes);
}
void ShenandoahHeap::set_degenerated_gc_in_progress(bool in_progress) {
@@ -2739,18 +2805,6 @@ bool ShenandoahRegionIterator::has_next() const {
return _index < _heap->num_regions();
}
-char ShenandoahHeap::gc_state() const {
- return _gc_state.raw_value();
-}
-
-bool ShenandoahHeap::is_gc_state(GCState state) const {
- // If the global gc state has been changed, but hasn't yet been propagated to all threads, then
- // the global gc state is the correct value. Once the gc state has been synchronized with all threads,
- // _gc_state_changed will be toggled to false and we need to use the thread local state.
- return _gc_state_changed ? _gc_state.is_set(state) : ShenandoahThreadLocalData::is_gc_state(state);
-}
-
-
ShenandoahLiveData* ShenandoahHeap::get_liveness_cache(uint worker_id) {
#ifdef ASSERT
assert(_liveness_cache != nullptr, "sanity");
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp
index 509ba1db9c2d..b5b7200329ad 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp
@@ -115,6 +115,7 @@ class ShenandoahRegionIterator : public StackObj {
class ShenandoahHeapRegionClosure : public StackObj {
public:
virtual void heap_region_do(ShenandoahHeapRegion* r) = 0;
+ virtual size_t parallel_region_stride() { return ShenandoahParallelRegionStride; }
virtual bool is_thread_safe() { return false; }
};
@@ -203,10 +204,13 @@ class ShenandoahHeap : public CollectedHeap {
void initialize_serviceability() override;
void print_heap_on(outputStream* st) const override;
- void print_gc_on(outputStream *st) const override;
+ void print_gc_on(outputStream* st) const override;
void print_tracing_info() const override;
void print_heap_regions_on(outputStream* st) const;
+ // Flushes cycle timings to global timings and prints the phase timings for the last completed cycle.
+ void process_gc_stats() const;
+
void stop() override;
void prepare_for_verify() override;
@@ -375,7 +379,7 @@ class ShenandoahHeap : public CollectedHeap {
public:
// This returns the raw value of the singular, global gc state.
- char gc_state() const;
+ inline char gc_state() const;
// Compares the given state against either the global gc state, or the thread local state.
// The global gc state may change on a safepoint and is the correct value to use until
@@ -383,7 +387,7 @@ class ShenandoahHeap : public CollectedHeap {
// compare against the thread local state). The thread local gc state may also be changed
// by a handshake operation, in which case, this function continues using the updated thread
// local value.
- bool is_gc_state(GCState state) const;
+ inline bool is_gc_state(GCState state) const;
// This copies the global gc state into a thread local variable for all threads.
// The thread local gc state is primarily intended to support quick access at barriers.
@@ -454,9 +458,12 @@ class ShenandoahHeap : public CollectedHeap {
// This indicates the reason the last GC cycle was cancelled.
inline GCCause::Cause cancelled_cause() const;
- // Clears the cancellation cause and optionally resets the oom handler (cancelling an
- // old mark does _not_ touch the oom handler).
- inline void clear_cancelled_gc(bool clear_oom_handler = true);
+ // Clears the cancellation cause and resets the oom handler
+ inline void clear_cancelled_gc();
+
+ // Clears the cancellation cause iff the current cancellation reason equals the given
+ // expected cancellation cause. Does not reset the oom handler.
+ inline GCCause::Cause clear_cancellation(GCCause::Cause expected);
void cancel_concurrent_mark();
@@ -473,6 +480,8 @@ class ShenandoahHeap : public CollectedHeap {
ShenandoahRegionIterator _update_refs_iterator;
private:
+ inline void reset_cancellation_time();
+
// GC support
// Evacuation
virtual void evacuate_collection_set(bool concurrent);
@@ -557,6 +566,10 @@ class ShenandoahHeap : public CollectedHeap {
ShenandoahEvacOOMHandler* oom_evac_handler() { return &_oom_evac_handler; }
+ ShenandoahEvacuationTracker* evac_tracker() const {
+ return _evac_tracker;
+ }
+
void on_cycle_start(GCCause::Cause cause, ShenandoahGeneration* generation);
void on_cycle_end(ShenandoahGeneration* generation);
@@ -789,6 +802,10 @@ class ShenandoahHeap : public CollectedHeap {
oop try_evacuate_object(oop src, Thread* thread, ShenandoahHeapRegion* from_region, ShenandoahAffiliation target_gen);
+protected:
+ // Used primarily to look for failed evacuation attempts.
+ ShenandoahEvacuationTracker* _evac_tracker;
+
public:
static address in_cset_fast_test_addr();
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp
index cf9d808f7ce8..08c0ae6a6233 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp
@@ -31,6 +31,7 @@
#include "classfile/javaClasses.inline.hpp"
#include "gc/shared/continuationGCSupport.inline.hpp"
+#include "gc/shared/gcCause.hpp"
#include "gc/shared/markBitMap.inline.hpp"
#include "gc/shared/suspendibleThreadSet.hpp"
#include "gc/shared/threadLocalAllocBuffer.inline.hpp"
@@ -268,16 +269,25 @@ inline GCCause::Cause ShenandoahHeap::cancelled_cause() const {
return _cancelled_gc.get();
}
-inline void ShenandoahHeap::clear_cancelled_gc(bool clear_oom_handler) {
+inline void ShenandoahHeap::clear_cancelled_gc() {
_cancelled_gc.set(GCCause::_no_gc);
+ reset_cancellation_time();
+ _oom_evac_handler.clear();
+}
+
+inline GCCause::Cause ShenandoahHeap::clear_cancellation(const GCCause::Cause expected) {
+ const GCCause::Cause cancellation_cause = _cancelled_gc.cmpxchg(GCCause::_no_gc, expected);
+ if (cancellation_cause == expected) {
+ reset_cancellation_time();
+ }
+ return cancellation_cause;
+}
+
+inline void ShenandoahHeap::reset_cancellation_time() {
if (_cancel_requested_time > 0) {
log_debug(gc)("GC cancellation took %.3fs", (os::elapsedTime() - _cancel_requested_time));
_cancel_requested_time = 0;
}
-
- if (clear_oom_handler) {
- _oom_evac_handler.clear();
- }
}
inline HeapWord* ShenandoahHeap::allocate_from_gclab(Thread* thread, size_t size) {
@@ -451,6 +461,17 @@ inline bool ShenandoahHeap::in_collection_set_loc(void* p) const {
return collection_set()->is_in_loc(p);
}
+inline char ShenandoahHeap::gc_state() const {
+ return _gc_state.raw_value();
+}
+
+inline bool ShenandoahHeap::is_gc_state(GCState state) const {
+ // If the global gc state has been changed, but hasn't yet been propagated to all threads, then
+ // the global gc state is the correct value. Once the gc state has been synchronized with all threads,
+ // _gc_state_changed will be toggled to false and we need to use the thread local state.
+ return _gc_state_changed ? _gc_state.is_set(state) : ShenandoahThreadLocalData::is_gc_state(state);
+}
+
inline bool ShenandoahHeap::is_idle() const {
return _gc_state_changed ? _gc_state.is_clear() : ShenandoahThreadLocalData::gc_state(Thread::current()) == 0;
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp
index b959494ae99f..2736376fe9a2 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp
@@ -75,6 +75,7 @@ ShenandoahHeapRegion::ShenandoahHeapRegion(HeapWord* start, size_t index, bool c
_plab_allocs(0),
_live_data(0),
_critical_pins(0),
+ _mixed_candidate_garbage_words(0),
_update_watermark(start),
_age(0),
#ifdef SHENANDOAH_CENSUS_NOISE
@@ -565,22 +566,27 @@ void ShenandoahHeapRegion::recycle_internal() {
assert(_recycling.is_set() && is_trash(), "Wrong state");
ShenandoahHeap* heap = ShenandoahHeap::heap();
- set_top(bottom());
+ _mixed_candidate_garbage_words = 0;
clear_live_data();
reset_alloc_metadata();
heap->marking_context()->reset_top_at_mark_start(this);
set_update_watermark(bottom());
if (ZapUnusedHeapArea) {
- SpaceMangler::mangle_region(MemRegion(bottom(), end()));
+ SpaceMangler::mangle_region(MemRegion(bottom(), top()));
}
+ set_top(bottom());
+ set_affiliation(FREE);
+ // Lastly, set region state to empty
make_empty();
- set_affiliation(FREE);
}
void ShenandoahHeapRegion::try_recycle_under_lock() {
shenandoah_assert_heaplocked();
- if (is_trash() && _recycling.try_set()) {
+ if (!is_trash()) {
+ return;
+ }
+ if (_recycling.try_set()) {
if (is_trash()) {
ShenandoahHeap* heap = ShenandoahHeap::heap();
ShenandoahGeneration* generation = heap->generation_for(affiliation());
@@ -600,12 +606,16 @@ void ShenandoahHeapRegion::try_recycle_under_lock() {
os::naked_yield();
}
}
+ assert(!is_trash(), "Must not");
}
}
void ShenandoahHeapRegion::try_recycle() {
shenandoah_assert_not_heaplocked();
- if (is_trash() && _recycling.try_set()) {
+ if (!is_trash()) {
+ return;
+ }
+ if (_recycling.try_set()) {
// Double check region state after win the race to set recycling flag
if (is_trash()) {
ShenandoahHeap* heap = ShenandoahHeap::heap();
@@ -825,7 +835,7 @@ void ShenandoahHeapRegion::set_state(RegionState to) {
evt.set_to(to);
evt.commit();
}
- Atomic::store(&_state, to);
+ Atomic::release_store(&_state, to);
}
void ShenandoahHeapRegion::record_pin() {
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp
index 4c99364bc6ed..20040eebafd8 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp
@@ -43,6 +43,7 @@ class ShenandoahHeapRegion {
friend class VMStructs;
friend class ShenandoahHeapRegionStateConstant;
private:
+
/*
Region state is described by a state machine. Transitions are guarded by
heap lock, which allows changing the state of several regions atomically.
@@ -216,7 +217,7 @@ class ShenandoahHeapRegion {
bool is_alloc_allowed() const { auto cur_state = state(); return is_empty_state(cur_state) || cur_state == _regular || cur_state == _pinned; }
bool is_stw_move_allowed() const { auto cur_state = state(); return cur_state == _regular || cur_state == _cset || (ShenandoahHumongousMoves && cur_state == _humongous_start); }
- RegionState state() const { return Atomic::load(&_state); }
+ RegionState state() const { return Atomic::load_acquire(&_state); }
int state_ordinal() const { return region_state_to_ordinal(state()); }
void record_pin();
@@ -259,6 +260,8 @@ class ShenandoahHeapRegion {
volatile size_t _live_data;
volatile size_t _critical_pins;
+ size_t _mixed_candidate_garbage_words;
+
HeapWord* volatile _update_watermark;
uint _age;
@@ -379,6 +382,14 @@ class ShenandoahHeapRegion {
inline size_t get_live_data_bytes() const;
inline size_t get_live_data_words() const;
+ inline size_t get_mixed_candidate_live_data_bytes() const;
+ inline size_t get_mixed_candidate_live_data_words() const;
+
+ inline void capture_mixed_candidate_garbage();
+
+ // Returns garbage by calculating difference between used and get_live_data_words. The value returned is only
+ // meaningful immediately following completion of marking. If there have been subsequent allocations in this region,
+ // use a different approach to determine garbage, such as (used() - get_mixed_candidate_live_data_bytes())
inline size_t garbage() const;
void print_on(outputStream* st) const;
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp
index 57a5391ffe90..71b23d1f6fdb 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp
@@ -157,6 +157,23 @@ inline size_t ShenandoahHeapRegion::get_live_data_bytes() const {
return get_live_data_words() * HeapWordSize;
}
+inline size_t ShenandoahHeapRegion::get_mixed_candidate_live_data_bytes() const {
+ shenandoah_assert_heaplocked_or_safepoint();
+ assert(used() >= _mixed_candidate_garbage_words * HeapWordSize, "used must exceed garbage");
+ return used() - _mixed_candidate_garbage_words * HeapWordSize;
+}
+
+inline size_t ShenandoahHeapRegion::get_mixed_candidate_live_data_words() const {
+ shenandoah_assert_heaplocked_or_safepoint();
+ assert(used() >= _mixed_candidate_garbage_words * HeapWordSize, "used must exceed garbage");
+ return used() / HeapWordSize - _mixed_candidate_garbage_words;
+}
+
+inline void ShenandoahHeapRegion::capture_mixed_candidate_garbage() {
+ shenandoah_assert_heaplocked_or_safepoint();
+ _mixed_candidate_garbage_words = garbage() / HeapWordSize;
+}
+
inline bool ShenandoahHeapRegion::has_live() const {
return get_live_data_words() != 0;
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionClosures.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionClosures.hpp
index 0daf268628c1..3f3b57c9bb2d 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionClosures.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionClosures.hpp
@@ -44,6 +44,10 @@ class ShenandoahIncludeRegionClosure : public ShenandoahHeapRegionClosure {
}
}
+ size_t parallel_region_stride() override {
+ return _closure->parallel_region_stride();
+ }
+
bool is_thread_safe() override {
return _closure->is_thread_safe();
}
@@ -64,6 +68,10 @@ class ShenandoahExcludeRegionClosure : public ShenandoahHeapRegionClosure {
}
}
+ size_t parallel_region_stride() override {
+ return _closure->parallel_region_stride();
+ }
+
bool is_thread_safe() override {
return _closure->is_thread_safe();
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp
index 2dc0813e5135..09b872deadad 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMark.inline.hpp
@@ -77,10 +77,9 @@ void ShenandoahMark::do_task(ShenandoahObjToScanQueue* q, T* cl, ShenandoahLiveD
if (task->is_not_chunked()) {
if (obj->is_instance()) {
// Case 1: Normal oop, process as usual.
- if (ContinuationGCSupport::relativize_stack_chunk(obj)) {
- // Loom doesn't support mixing of weak marking and strong marking of
- // stack chunks.
- cl->set_weak(false);
+ if (obj->is_stackChunk()) {
+ // Loom doesn't support mixing of weak marking and strong marking of stack chunks.
+ cl->set_weak(false);
}
obj->oop_iterate(cl);
@@ -118,13 +117,11 @@ inline void ShenandoahMark::count_liveness(ShenandoahLiveData* live_data, oop ob
// Age census for objects in the young generation
if (GENERATION == YOUNG || (GENERATION == GLOBAL && region->is_young())) {
assert(heap->mode()->is_generational(), "Only if generational");
- if (ShenandoahGenerationalAdaptiveTenuring && !ShenandoahGenerationalCensusAtEvac) {
- assert(region->is_young(), "Only for young objects");
- uint age = ShenandoahHeap::get_object_age(obj);
- ShenandoahAgeCensus* const census = ShenandoahGenerationalHeap::heap()->age_census();
- CENSUS_NOISE(census->add(age, region->age(), region->youth(), size, worker_id);)
- NO_CENSUS_NOISE(census->add(age, region->age(), size, worker_id);)
- }
+ assert(region->is_young(), "Only for young objects");
+ const uint age = ShenandoahHeap::get_object_age(obj);
+ ShenandoahAgeCensus* const census = ShenandoahGenerationalHeap::heap()->age_census();
+ CENSUS_NOISE(census->add(age, region->age(), region->youth(), size, worker_id);)
+ NO_CENSUS_NOISE(census->add(age, region->age(), size, worker_id);)
}
if (!region->is_humongous_start()) {
@@ -226,8 +223,6 @@ inline void ShenandoahMark::do_chunked_array(ShenandoahObjToScanQueue* q, T* cl,
assert(obj->is_objArray(), "expect object array");
objArrayOop array = objArrayOop(obj);
- assert (ObjArrayMarkingStride > 0, "sanity");
-
// Split out tasks, as suggested in ShenandoahMarkTask docs. Avoid pushing tasks that
// are known to start beyond the array.
while ((1 << pow) > (int)ObjArrayMarkingStride && (chunk*2 < ShenandoahMarkTask::chunk_size())) {
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp
index 21b526f99954..73442ff0520a 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp
@@ -136,14 +136,12 @@ inline ShenandoahMarkBitMap::idx_t ShenandoahMarkBitMap::get_next_bit_impl(idx_t
// Get the word containing l_index, and shift out low bits.
idx_t index = to_words_align_down(l_index);
bm_word_t cword = (map(index) ^ flip) >> bit_in_word(l_index);
- if ((cword & 1) != 0) {
- // The first bit is similarly often interesting. When it matters
- // (density or features of the calling algorithm make it likely
- // the first bit is set), going straight to the next clause compares
- // poorly with doing this check first; count_trailing_zeros can be
- // relatively expensive, plus there is the additional range check.
- // But when the first bit isn't set, the cost of having tested for
- // it is relatively small compared to the rest of the search.
+ if ((cword & 0x03) != 0) {
+ // The first bits (representing weak mark or strong mark) are similarly often interesting. When it matters
+ // (density or features of the calling algorithm make it likely the first bits are set), going straight to
+ // the next clause compares poorly with doing this check first; count_trailing_zeros can be relatively expensive,
+ // plus there is the additional range check. But when the first bits are not set, the cost of having tested for
+ // them is relatively small compared to the rest of the search.
return l_index;
} else if (cword != 0) {
// Flipped and shifted first word is non-zero.
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp
index 0babeaffd3e0..40eee8c342ba 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp
@@ -74,8 +74,8 @@ void ShenandoahMarkingContext::initialize_top_at_mark_start(ShenandoahHeapRegion
_top_at_mark_starts_base[idx] = bottom;
_top_bitmaps[idx] = bottom;
- log_debug(gc)("SMC:initialize_top_at_mark_start for Region %zu, TAMS: " PTR_FORMAT ", TopOfBitMap: " PTR_FORMAT,
- r->index(), p2i(bottom), p2i(r->end()));
+ log_debug(gc, mark)("SMC:initialize_top_at_mark_start for Region %zu, TAMS: " PTR_FORMAT ", TopOfBitMap: " PTR_FORMAT,
+ r->index(), p2i(bottom), p2i(r->end()));
}
HeapWord* ShenandoahMarkingContext::top_bitmap(ShenandoahHeapRegion* r) {
@@ -86,8 +86,8 @@ void ShenandoahMarkingContext::clear_bitmap(ShenandoahHeapRegion* r) {
HeapWord* bottom = r->bottom();
HeapWord* top_bitmap = _top_bitmaps[r->index()];
- log_debug(gc)("SMC:clear_bitmap for %s Region %zu, top_bitmap: " PTR_FORMAT,
- r->affiliation_name(), r->index(), p2i(top_bitmap));
+ log_debug(gc, mark)("SMC:clear_bitmap for %s Region %zu, top_bitmap: " PTR_FORMAT,
+ r->affiliation_name(), r->index(), p2i(top_bitmap));
if (top_bitmap > bottom) {
_mark_bit_map.clear_range_large(MemRegion(bottom, top_bitmap));
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp
index fe98413a8ccb..637dbf47c3f4 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp
@@ -108,8 +108,8 @@ inline void ShenandoahMarkingContext::capture_top_at_mark_start(ShenandoahHeapRe
"Region %zu, bitmap should be clear while adjusting TAMS: " PTR_FORMAT " -> " PTR_FORMAT,
idx, p2i(old_tams), p2i(new_tams));
- log_debug(gc)("Capturing TAMS for %s Region %zu, was: " PTR_FORMAT ", now: " PTR_FORMAT,
- r->affiliation_name(), idx, p2i(old_tams), p2i(new_tams));
+ log_debug(gc, mark)("Capturing TAMS for %s Region %zu, was: " PTR_FORMAT ", now: " PTR_FORMAT,
+ r->affiliation_name(), idx, p2i(old_tams), p2i(new_tams));
_top_at_mark_starts_base[idx] = new_tams;
_top_bitmaps[idx] = new_tams;
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMetrics.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMetrics.cpp
index dc666a34c595..d774a8dba427 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahMetrics.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMetrics.cpp
@@ -28,69 +28,45 @@
#include "gc/shenandoah/shenandoahHeapRegion.hpp"
#include "gc/shenandoah/shenandoahMetrics.hpp"
-ShenandoahMetricsSnapshot::ShenandoahMetricsSnapshot() {
- _heap = ShenandoahHeap::heap();
+ShenandoahMetricsSnapshot::ShenandoahMetricsSnapshot(ShenandoahFreeSet* free_set)
+ : _free_set(free_set)
+ , _used_before(free_set->used())
+ , _if_before(free_set->internal_fragmentation())
+ , _ef_before(free_set->external_fragmentation()) {
}
-void ShenandoahMetricsSnapshot::snap_before() {
- _used_before = _heap->used();
- _if_before = _heap->free_set()->internal_fragmentation();
- _ef_before = _heap->free_set()->external_fragmentation();
-}
-void ShenandoahMetricsSnapshot::snap_after() {
- _used_after = _heap->used();
- _if_after = _heap->free_set()->internal_fragmentation();
- _ef_after = _heap->free_set()->external_fragmentation();
-}
-
-// For degenerated GC, generation is Young in generational mode, Global in non-generational mode.
-// For full GC, generation is always Global.
-//
-// Note that the size of the chosen collection set is proportional to the relevant generation's collection set.
-// Note also that the generation size may change following selection of the collection set, as a side effect
-// of evacuation. Evacuation may promote objects, causing old to grow and young to shrink. Or this may be a
-// mixed evacuation. When old regions are evacuated, this typically allows young to expand. In all of these
-// various scenarios, the purpose of asking is_good_progress() is to determine if there is enough memory available
-// within young generation to justify making an attempt to perform a concurrent collection. For this reason, we'll
-// use the current size of the generation (which may not be different than when the collection set was chosen) to
-// assess how much free memory we require in order to consider the most recent GC to have had good progress.
-
-bool ShenandoahMetricsSnapshot::is_good_progress(ShenandoahGeneration* generation) {
+bool ShenandoahMetricsSnapshot::is_good_progress() const {
// Under the critical threshold?
- ShenandoahFreeSet* free_set = _heap->free_set();
- size_t free_actual = free_set->available();
+ const size_t free_actual = _free_set->available();
assert(free_actual != ShenandoahFreeSet::FreeSetUnderConstruction, "Avoid this race");
- // ShenandoahCriticalFreeThreshold is expressed as a percentage. We multiple this percentage by 1/100th
- // of the generation capacity to determine whether the available memory within the generation exceeds the
- // critical threshold.
- size_t free_expected = (ShenandoahHeap::heap()->soft_max_capacity() / 100) * ShenandoahCriticalFreeThreshold;
-
- bool prog_free = free_actual >= free_expected;
- log_info(gc, ergo)("%s progress for free space: %zu%s, need %zu%s",
- prog_free ? "Good" : "Bad",
- byte_size_in_proper_unit(free_actual), proper_unit_for_byte_size(free_actual),
- byte_size_in_proper_unit(free_expected), proper_unit_for_byte_size(free_expected));
+ // ShenandoahCriticalFreeThreshold is expressed as a percentage. We multiply this percentage by 1/100th
+ // of the soft max capacity to determine whether the available memory within the mutator partition of the
+ // freeset exceeds the critical threshold.
+ const size_t free_expected = (ShenandoahHeap::heap()->soft_max_capacity() / 100) * ShenandoahCriticalFreeThreshold;
+ const bool prog_free = free_actual >= free_expected;
+ log_info(gc, ergo)("%s progress for free space: " PROPERFMT ", need " PROPERFMT,
+ prog_free ? "Good" : "Bad", PROPERFMTARGS(free_actual), PROPERFMTARGS(free_expected));
if (!prog_free) {
return false;
}
// Freed up enough?
- size_t progress_actual = (_used_before > _used_after) ? _used_before - _used_after : 0;
- size_t progress_expected = ShenandoahHeapRegion::region_size_bytes();
- bool prog_used = progress_actual >= progress_expected;
- log_info(gc, ergo)("%s progress for used space: %zu%s, need %zu%s",
- prog_used ? "Good" : "Bad",
- byte_size_in_proper_unit(progress_actual), proper_unit_for_byte_size(progress_actual),
- byte_size_in_proper_unit(progress_expected), proper_unit_for_byte_size(progress_expected));
+ const size_t used_after = _free_set->used();
+ const size_t progress_actual = (_used_before > used_after) ? _used_before - used_after : 0;
+ const size_t progress_expected = ShenandoahHeapRegion::region_size_bytes();
+ const bool prog_used = progress_actual >= progress_expected;
+ log_info(gc, ergo)("%s progress for used space: " PROPERFMT ", need " PROPERFMT,
+ prog_used ? "Good" : "Bad", PROPERFMTARGS(progress_actual), PROPERFMTARGS(progress_expected));
if (prog_used) {
return true;
}
// Internal fragmentation is down?
- double if_actual = _if_before - _if_after;
- double if_expected = 0.01; // 1% should be enough
- bool prog_if = if_actual >= if_expected;
+ const double if_after = _free_set->internal_fragmentation();
+ const double if_actual = _if_before - if_after;
+ const double if_expected = 0.01; // 1% should be enough
+ const bool prog_if = if_actual >= if_expected;
log_info(gc, ergo)("%s progress for internal fragmentation: %.1f%%, need %.1f%%",
prog_if ? "Good" : "Bad",
if_actual * 100, if_expected * 100);
@@ -99,9 +75,10 @@ bool ShenandoahMetricsSnapshot::is_good_progress(ShenandoahGeneration* generatio
}
// External fragmentation is down?
- double ef_actual = _ef_before - _ef_after;
- double ef_expected = 0.01; // 1% should be enough
- bool prog_ef = ef_actual >= ef_expected;
+ const double ef_after = _free_set->external_fragmentation();
+ const double ef_actual = _ef_before - ef_after;
+ const double ef_expected = 0.01; // 1% should be enough
+ const bool prog_ef = ef_actual >= ef_expected;
log_info(gc, ergo)("%s progress for external fragmentation: %.1f%%, need %.1f%%",
prog_ef ? "Good" : "Bad",
ef_actual * 100, ef_expected * 100);
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMetrics.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMetrics.hpp
index 20d8ebfd5957..c554a0653867 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahMetrics.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMetrics.hpp
@@ -25,22 +25,20 @@
#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHMETRICS_HPP
#define SHARE_GC_SHENANDOAH_SHENANDOAHMETRICS_HPP
-#include "gc/shenandoah/shenandoahHeap.hpp"
+#include "gc/shenandoah/shenandoahFreeSet.hpp"
class ShenandoahMetricsSnapshot : public StackObj {
private:
- ShenandoahHeap* _heap;
- size_t _used_before, _used_after;
- double _if_before, _if_after;
- double _ef_before, _ef_after;
+ ShenandoahFreeSet* _free_set;
+ size_t _used_before;
+ double _if_before;
+ double _ef_before;
public:
- ShenandoahMetricsSnapshot();
+ explicit ShenandoahMetricsSnapshot(ShenandoahFreeSet* free_set);
- void snap_before();
- void snap_after();
-
- bool is_good_progress(ShenandoahGeneration *generation);
+ // Decide if the GC made "good" progress (i.e., reduced fragmentation, freed up sufficient memory).
+ bool is_good_progress() const;
};
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHMETRICS_HPP
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp
index 1724fc2849f7..707c2690b581 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp
@@ -69,12 +69,6 @@ void ShenandoahOldGC::op_final_mark() {
heap->set_unload_classes(false);
heap->prepare_concurrent_roots();
- // Believe verification following old-gen concurrent mark needs to be different than verification following
- // young-gen concurrent mark, so am commenting this out for now:
- // if (ShenandoahVerify) {
- // heap->verifier()->verify_after_concmark();
- // }
-
if (VerifyAfterGC) {
Universe::verify();
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp
index 5cccd395d381..0d5a13fa5471 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp
@@ -300,6 +300,8 @@ ShenandoahOldGeneration::configure_plab_for_current_thread(const ShenandoahAlloc
if (can_promote(actual_size)) {
// Assume the entirety of this PLAB will be used for promotion. This prevents promotion from overreach.
// When we retire this plab, we'll unexpend what we don't really use.
+ log_debug(gc, plab)("Thread can promote using PLAB of %zu bytes. Expended: %zu, available: %zu",
+ actual_size, get_promoted_expended(), get_promoted_reserve());
expend_promoted(actual_size);
ShenandoahThreadLocalData::enable_plab_promotions(thread);
ShenandoahThreadLocalData::set_plab_actual_size(thread, actual_size);
@@ -307,9 +309,12 @@ ShenandoahOldGeneration::configure_plab_for_current_thread(const ShenandoahAlloc
// Disable promotions in this thread because entirety of this PLAB must be available to hold old-gen evacuations.
ShenandoahThreadLocalData::disable_plab_promotions(thread);
ShenandoahThreadLocalData::set_plab_actual_size(thread, 0);
+ log_debug(gc, plab)("Thread cannot promote using PLAB of %zu bytes. Expended: %zu, available: %zu, mixed evacuations? %s",
+ actual_size, get_promoted_expended(), get_promoted_reserve(), BOOL_TO_STR(ShenandoahHeap::heap()->collection_set()->has_old_regions()));
}
} else if (req.is_promotion()) {
// Shared promotion.
+ log_debug(gc, plab)("Expend shared promotion of %zu bytes", actual_size);
expend_promoted(actual_size);
}
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp
index ea94c2926e86..1643b34e853a 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp
@@ -323,7 +323,6 @@ HeapWord* ShenandoahCardCluster::first_object_start(const size_t card_index, con
if (ctx->is_marked(p)) {
oop obj = cast_to_oop(p);
assert(oopDesc::is_oop(obj), "Should be an object");
- assert(Klass::is_valid(obj->klass()), "Not a valid klass ptr");
assert(p + obj->size() > left, "This object should span start of card");
assert(p < right, "Result must precede right");
return p;
@@ -350,15 +349,15 @@ HeapWord* ShenandoahCardCluster::first_object_start(const size_t card_index, con
// Recall that we already dealt with the co-initial object case above
assert(p < left, "obj should start before left");
- // While it is safe to ask an object its size in the loop that
- // follows, the (ifdef'd out) loop should never be needed.
+ // While it is safe to ask an object its size in the block that
+ // follows, the (ifdef'd out) block should never be needed.
// 1. we ask this question only for regions in the old generation, and those
// that are not humongous regions
// 2. there is no direct allocation ever by mutators in old generation
// regions walked by this code. Only GC will ever allocate in old regions,
// and then too only during promotion/evacuation phases. Thus there is no danger
// of races between reading from and writing to the object start array,
- // or of asking partially initialized objects their size (in the loop below).
+ // or of asking partially initialized objects their size (in the ifdef below).
// Furthermore, humongous regions (and their dirty cards) are never processed
// by this code.
// 3. only GC asks this question during phases when it is not concurrently
@@ -370,15 +369,6 @@ HeapWord* ShenandoahCardCluster::first_object_start(const size_t card_index, con
#ifdef ASSERT
oop obj = cast_to_oop(p);
assert(oopDesc::is_oop(obj), "Should be an object");
- while (p + obj->size() < left) {
- p += obj->size();
- obj = cast_to_oop(p);
- assert(oopDesc::is_oop(obj), "Should be an object");
- assert(Klass::is_valid(obj->klass()), "Not a valid klass ptr");
- // Check assumptions in previous block comment if this assert fires
- fatal("Should never need forward walk in block start");
- }
- assert(p <= left, "p should start at or before left end of card");
assert(p + obj->size() > left, "obj should end after left end of card");
#endif // ASSERT
return p;
@@ -777,9 +767,9 @@ void ShenandoahScanRememberedTask::do_work(uint worker_id) {
struct ShenandoahRegionChunk assignment;
while (_work_list->next(&assignment)) {
ShenandoahHeapRegion* region = assignment._r;
- log_debug(gc)("ShenandoahScanRememberedTask::do_work(%u), processing slice of region "
- "%zu at offset %zu, size: %zu",
- worker_id, region->index(), assignment._chunk_offset, assignment._chunk_size);
+ log_debug(gc, remset)("ShenandoahScanRememberedTask::do_work(%u), processing slice of region "
+ "%zu at offset %zu, size: %zu",
+ worker_id, region->index(), assignment._chunk_offset, assignment._chunk_size);
if (region->is_old()) {
size_t cluster_size =
CardTable::card_size_in_words() * ShenandoahCardCluster::CardsPerCluster;
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp
index 82022420a2a8..998e786eff28 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp
@@ -361,9 +361,9 @@ ShenandoahScanRemembered::process_region_slice(ShenandoahHeapRegion *region, siz
}
}
- log_debug(gc)("Remembered set scan processing Region %zu, from " PTR_FORMAT " to " PTR_FORMAT ", using %s table",
- region->index(), p2i(start_of_range), p2i(end_of_range),
- use_write_table? "read/write (updating)": "read (marking)");
+ log_debug(gc, remset)("Remembered set scan processing Region %zu, from " PTR_FORMAT " to " PTR_FORMAT ", using %s table",
+ region->index(), p2i(start_of_range), p2i(end_of_range),
+ use_write_table? "read/write (updating)": "read (marking)");
// Note that end_of_range may point to the middle of a cluster because we limit scanning to
// region->top() or region->get_update_watermark(). We avoid processing past end_of_range.
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahSharedVariables.hpp b/src/hotspot/share/gc/shenandoah/shenandoahSharedVariables.hpp
index 1d1c93599464..1c86531f21e5 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahSharedVariables.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahSharedVariables.hpp
@@ -29,11 +29,7 @@
#include "memory/allocation.hpp"
#include "runtime/atomic.hpp"
-typedef jbyte ShenandoahSharedValue;
-
-// Needed for cooperation with generated code.
-STATIC_ASSERT(sizeof(ShenandoahSharedValue) == 1);
-
+typedef int32_t ShenandoahSharedValue;
typedef struct ShenandoahSharedFlag {
enum {
UNSET = 0,
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.cpp b/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.cpp
index c444a0ba86a6..dd500462d0ff 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.cpp
@@ -44,10 +44,7 @@ ShenandoahThreadLocalData::ShenandoahThreadLocalData() :
_plab_promoted(0),
_plab_allows_promotion(true),
_plab_retries_enabled(true),
- _evacuation_stats(nullptr) {
- if (ShenandoahHeap::heap()->mode()->is_generational()) {
- _evacuation_stats = new ShenandoahEvacuationStats();
- }
+ _evacuation_stats(new ShenandoahEvacuationStats()) {
}
ShenandoahThreadLocalData::~ShenandoahThreadLocalData() {
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp b/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp
index c1cebdf1ddef..8a3132bdf171 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp
@@ -30,6 +30,7 @@
#include "gc/shared/gcThreadLocalData.hpp"
#include "gc/shared/plab.hpp"
#include "gc/shenandoah/mode/shenandoahMode.hpp"
+#include "gc/shenandoah/shenandoahAffiliation.hpp"
#include "gc/shenandoah/shenandoahBarrierSet.hpp"
#include "gc/shenandoah/shenandoahCardTable.hpp"
#include "gc/shenandoah/shenandoahCodeRoots.hpp"
@@ -159,20 +160,15 @@ class ShenandoahThreadLocalData {
data(thread)->_gclab_size = v;
}
- static void begin_evacuation(Thread* thread, size_t bytes) {
- data(thread)->_evacuation_stats->begin_evacuation(bytes);
+ static void begin_evacuation(Thread* thread, size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to) {
+ data(thread)->_evacuation_stats->begin_evacuation(bytes, from, to);
}
- static void end_evacuation(Thread* thread, size_t bytes) {
- data(thread)->_evacuation_stats->end_evacuation(bytes);
- }
-
- static void record_age(Thread* thread, size_t bytes, uint age) {
- data(thread)->_evacuation_stats->record_age(bytes, age);
+ static void end_evacuation(Thread* thread, size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to) {
+ data(thread)->_evacuation_stats->end_evacuation(bytes, from, to);
}
static ShenandoahEvacuationStats* evacuation_stats(Thread* thread) {
- shenandoah_assert_generational();
return data(thread)->_evacuation_stats;
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTrace.cpp b/src/hotspot/share/gc/shenandoah/shenandoahTrace.cpp
index dd153718c9f1..bbb44348355b 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahTrace.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTrace.cpp
@@ -22,31 +22,31 @@
*
*/
-#include "gc/shenandoah/shenandoahEvacInfo.hpp"
+#include "gc/shenandoah/shenandoahCollectionSet.inline.hpp"
#include "gc/shenandoah/shenandoahTrace.hpp"
#include "jfr/jfrEvents.hpp"
-void ShenandoahTracer::report_evacuation_info(ShenandoahEvacuationInformation* info) {
- send_evacuation_info_event(info);
-}
+void ShenandoahTracer::report_evacuation_info(const ShenandoahCollectionSet* cset,
+ size_t free_regions, size_t regions_promoted_humongous, size_t regions_promoted_regular,
+ size_t regular_promoted_garbage, size_t regular_promoted_free, size_t regions_immediate,
+ size_t immediate_size) {
-void ShenandoahTracer::send_evacuation_info_event(ShenandoahEvacuationInformation* info) {
EventShenandoahEvacuationInformation e;
if (e.should_commit()) {
e.set_gcId(GCId::current());
- e.set_cSetRegions(info->collection_set_regions());
- e.set_cSetUsedBefore(info->collection_set_used_before());
- e.set_cSetUsedAfter(info->collection_set_used_after());
- e.set_collectedOld(info->collected_old());
- e.set_collectedPromoted(info->collected_promoted());
- e.set_collectedYoung(info->collected_young());
- e.set_regionsPromotedHumongous(info->regions_promoted_humongous());
- e.set_regionsPromotedRegular(info->regions_promoted_regular());
- e.set_regularPromotedGarbage(info->regular_promoted_garbage());
- e.set_regularPromotedFree(info->regular_promoted_free());
- e.set_freeRegions(info->free_regions());
- e.set_regionsImmediate(info->regions_immediate());
- e.set_immediateBytes(info->immediate_size());
+ e.set_cSetRegions(cset->count());
+ e.set_cSetUsedBefore(cset->used());
+ e.set_cSetUsedAfter(cset->live());
+ e.set_collectedOld(cset->get_live_bytes_in_old_regions());
+ e.set_collectedPromoted(cset->get_live_bytes_in_tenurable_regions());
+ e.set_collectedYoung(cset->get_live_bytes_in_untenurable_regions());
+ e.set_regionsPromotedHumongous(regions_promoted_humongous);
+ e.set_regionsPromotedRegular(regions_promoted_regular);
+ e.set_regularPromotedGarbage(regular_promoted_garbage);
+ e.set_regularPromotedFree(regular_promoted_free);
+ e.set_freeRegions(free_regions);
+ e.set_regionsImmediate(regions_immediate);
+ e.set_immediateBytes(immediate_size);
e.commit();
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTrace.hpp b/src/hotspot/share/gc/shenandoah/shenandoahTrace.hpp
index a5351f4ef281..116968103dea 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahTrace.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTrace.hpp
@@ -28,15 +28,17 @@
#include "gc/shared/gcTrace.hpp"
#include "memory/allocation.hpp"
-class ShenandoahEvacuationInformation;
+class ShenandoahCollectionSet;
class ShenandoahTracer : public GCTracer, public CHeapObj {
public:
ShenandoahTracer() : GCTracer(Shenandoah) {}
- void report_evacuation_info(ShenandoahEvacuationInformation* info);
-private:
- void send_evacuation_info_event(ShenandoahEvacuationInformation* info);
+ // Sends a JFR event (if enabled) summarizing the composition of the collection set
+ static void report_evacuation_info(const ShenandoahCollectionSet* cset,
+ size_t free_regions, size_t regions_promoted_humongous, size_t regions_promoted_regular,
+ size_t regular_promoted_garbage, size_t regular_promoted_free, size_t regions_immediate,
+ size_t immediate_size);
};
#endif
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp
index cdf784852076..82358aafd3ce 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp
@@ -115,15 +115,15 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure {
void do_oop_work(T* p) {
T o = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(o)) {
- oop obj = CompressedOops::decode_not_null(o);
+ // Basic verification should happen before we touch anything else.
+ // For performance reasons, only fully verify non-marked field values.
+ // We are here when the host object for *p is already marked.
+ oop obj = CompressedOops::decode_raw_not_null(o);
+ verify_oop_at_basic(p, obj);
+
if (is_instance_ref_klass(ShenandoahForwarding::klass(obj))) {
obj = ShenandoahForwarding::get_forwardee(obj);
}
- // Single threaded verification can use faster non-atomic stack and bitmap
- // methods.
- //
- // For performance reasons, only fully verify non-marked field values.
- // We are here when the host object for *p is already marked.
if (in_generation(obj) && _map->par_mark(obj)) {
verify_oop_at(p, obj);
_stack->push(ShenandoahVerifierTask(obj));
@@ -140,7 +140,7 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure {
return _generation->contains(region);
}
- void verify_oop(oop obj) {
+ void verify_oop(oop obj, bool basic = false) {
// Perform consistency checks with gradually decreasing safety level. This guarantees
// that failure report would not try to touch something that was not yet verified to be
// safe to process.
@@ -177,10 +177,14 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure {
}
}
+ check(ShenandoahAsserts::_safe_unknown, obj, obj_reg->is_active(),
+ "Object should be in active region");
+
// ------------ obj is safe at this point --------------
- check(ShenandoahAsserts::_safe_oop, obj, obj_reg->is_active(),
- "Object should be in active region");
+ if (basic) {
+ return;
+ }
switch (_options._verify_liveness) {
case ShenandoahVerifier::_verify_liveness_disable:
@@ -333,6 +337,18 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure {
_interior_loc = nullptr;
}
+ /**
+ * Verify object with known interior reference, with only basic verification.
+ * @param p interior reference where the object is referenced from; can be off-heap
+ * @param obj verified object
+ */
+ template
+ void verify_oop_at_basic(T* p, oop obj) {
+ _interior_loc = p;
+ verify_oop(obj, /* basic = */ true);
+ _interior_loc = nullptr;
+ }
+
/**
* Verify object without known interior reference.
* Useful when picking up the object at known offset in heap,
@@ -1203,7 +1219,9 @@ class ShenandoahVerifyNoForwarded : public BasicOopIterateClosure {
void do_oop_work(T* p) {
T o = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(o)) {
- oop obj = CompressedOops::decode_not_null(o);
+ oop obj = CompressedOops::decode_raw_not_null(o);
+ ShenandoahAsserts::assert_correct(p, obj, __FILE__, __LINE__);
+
oop fwd = ShenandoahForwarding::get_forwardee_raw_unchecked(obj);
if (obj != fwd) {
ShenandoahAsserts::print_failure(ShenandoahAsserts::_safe_all, obj, p, nullptr,
@@ -1223,7 +1241,9 @@ class ShenandoahVerifyInToSpaceClosure : public BasicOopIterateClosure {
void do_oop_work(T* p) {
T o = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(o)) {
- oop obj = CompressedOops::decode_not_null(o);
+ oop obj = CompressedOops::decode_raw_not_null(o);
+ ShenandoahAsserts::assert_correct(p, obj, __FILE__, __LINE__);
+
ShenandoahHeap* heap = ShenandoahHeap::heap();
if (!heap->marking_context()->is_marked_or_old(obj)) {
@@ -1277,7 +1297,9 @@ class ShenandoahVerifyRemSetClosure : public BasicOopIterateClosure {
inline void work(T* p) {
T o = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(o)) {
- oop obj = CompressedOops::decode_not_null(o);
+ oop obj = CompressedOops::decode_raw_not_null(o);
+ ShenandoahAsserts::assert_correct(p, obj, __FILE__, __LINE__);
+
if (_heap->is_in_young(obj) && !_scanner->is_card_dirty((HeapWord*) p)) {
ShenandoahAsserts::print_failure(ShenandoahAsserts::_safe_all, obj, p, nullptr,
_message, "clean card, it should be dirty.", __FILE__, __LINE__);
diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp
index 6811c042e2ab..c510c2a3601f 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp
@@ -34,6 +34,20 @@
range, \
constraint) \
\
+ product(uintx, ShenandoahGenerationalMinPIPUsage, 30, EXPERIMENTAL, \
+ "(Generational mode only) What percent of a heap region " \
+ "should be used before we consider promoting a region in " \
+ "place? Regions with less than this amount of used will " \
+ "promoted by evacuation. A benefit of promoting in place " \
+ "is that less work is required by the GC at the time the " \
+ "region is promoted. A disadvantage of promoting in place " \
+ "is that this introduces fragmentation of old-gen memory, " \
+ "with old-gen regions scattered throughout the heap. Regions " \
+ "that have been promoted in place may need to be evacuated at " \
+ "a later time in order to compact old-gen memory to enable " \
+ "future humongous allocations.") \
+ range(0,100) \
+ \
product(uintx, ShenandoahGenerationalHumongousReserve, 0, EXPERIMENTAL, \
"(Generational mode only) What percent of the heap should be " \
"reserved for humongous objects if possible. Old-generation " \
@@ -70,13 +84,6 @@
"many consecutive young-gen collections have been " \
"completed following the preceding old-gen collection.") \
\
- product(bool, ShenandoahGenerationalCensusAtEvac, false, EXPERIMENTAL, \
- "(Generational mode only) Object age census at evacuation, " \
- "rather than during marking.") \
- \
- product(bool, ShenandoahGenerationalAdaptiveTenuring, true, EXPERIMENTAL, \
- "(Generational mode only) Dynamically adapt tenuring age.") \
- \
product(bool, ShenandoahGenerationalCensusIgnoreOlderCohorts, true, \
EXPERIMENTAL,\
"(Generational mode only) Ignore mortality rates older than the " \
@@ -101,8 +108,7 @@
"(Generational mode only) Cohort mortality rates below this " \
"value will be treated as indicative of longevity, leading to " \
"tenuring. A lower value delays tenuring, a higher value hastens "\
- "it. Used only when ShenandoahGenerationalhenAdaptiveTenuring is "\
- "enabled.") \
+ "it.") \
range(0.001,0.999) \
\
product(size_t, ShenandoahGenerationalTenuringCohortPopulationThreshold, \
@@ -169,7 +175,7 @@
"collector accepts. In percents of heap region size.") \
range(0,100) \
\
- product(uintx, ShenandoahOldGarbageThreshold, 15, EXPERIMENTAL, \
+ product(uintx, ShenandoahOldGarbageThreshold, 25, EXPERIMENTAL, \
"How much garbage an old region has to contain before it would " \
"be taken for collection.") \
range(0,100) \
@@ -377,13 +383,13 @@
\
product(uintx, ShenandoahOldEvacRatioPercent, 75, EXPERIMENTAL, \
"The maximum proportion of evacuation from old-gen memory, " \
- "expressed as a percentage. The default value 75 denotes that no" \
- "more than 75% of the collection set evacuation workload may be " \
- "towards evacuation of old-gen heap regions. This limits both the"\
- "promotion of aged regions and the compaction of existing old " \
- "regions. A value of 75 denotes that the total evacuation work" \
- "may increase to up to four times the young gen evacuation work." \
- "A larger value allows quicker promotion and allows" \
+ "expressed as a percentage. The default value 75 denotes that " \
+ "no more than 75% of the collection set evacuation workload may " \
+ "be towards evacuation of old-gen heap regions. This limits both "\
+ "the promotion of aged regions and the compaction of existing " \
+ "old regions. A value of 75 denotes that the total evacuation " \
+ "work may increase to up to four times the young gen evacuation " \
+ "work. A larger value allows quicker promotion and allows " \
"a smaller number of mixed evacuations to process " \
"the entire list of old-gen collection candidates at the cost " \
"of an increased disruption of the normal cadence of young-gen " \
@@ -391,13 +397,20 @@
"focus entirely on old-gen memory, allowing no young-gen " \
"regions to be collected, likely resulting in subsequent " \
"allocation failures because the allocation pool is not " \
- "replenished. A value of 0 allows a mixed evacuation to" \
+ "replenished. A value of 0 allows a mixed evacuation to " \
"focus entirely on young-gen memory, allowing no old-gen " \
"regions to be collected, likely resulting in subsequent " \
"promotion failures and triggering of stop-the-world full GC " \
"events.") \
range(0,100) \
\
+ product(bool, ShenandoahEvacTracking, false, DIAGNOSTIC, \
+ "Collect additional metrics about evacuations. Enabling this " \
+ "tracks how many objects and how many bytes were evacuated, and " \
+ "how many were abandoned. The information will be categorized " \
+ "by thread type (worker or mutator) and evacuation type (young, " \
+ "old, or promotion.") \
+ \
product(uintx, ShenandoahMinYoungPercentage, 20, EXPERIMENTAL, \
"The minimum percentage of the heap to use for the young " \
"generation. Heuristics will not adjust the young generation " \
diff --git a/src/hotspot/share/gc/z/zLargePages.cpp b/src/hotspot/share/gc/z/zLargePages.cpp
index 56c94a75713c..c259448563bd 100644
--- a/src/hotspot/share/gc/z/zLargePages.cpp
+++ b/src/hotspot/share/gc/z/zLargePages.cpp
@@ -31,7 +31,8 @@ bool ZLargePages::_os_enforced_transparent_mode;
void ZLargePages::initialize() {
pd_initialize();
- log_info_p(gc, init)("Memory: " JULONG_FORMAT "M", os::physical_memory() / M);
+ const size_t memory = static_cast(os::physical_memory());
+ log_info_p(gc, init)("Memory: " PROPERFMT, PROPERFMTARGS(memory));
log_info_p(gc, init)("Large Page Support: %s", to_string());
}
diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h
index 73f60765a702..a01bad14ab70 100644
--- a/src/hotspot/share/include/jvm.h
+++ b/src/hotspot/share/include/jvm.h
@@ -87,6 +87,9 @@ JVM_InternString(JNIEnv *env, jstring str);
/*
* java.lang.System
*/
+JNIEXPORT jboolean JNICALL
+JVM_AOTEndRecording(JNIEnv *env);
+
JNIEXPORT jlong JNICALL
JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored);
diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp
index 0b4ab5320648..9b4ead7b17b9 100644
--- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp
+++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp
@@ -411,9 +411,9 @@ JVM_ENTRY_NO_ENV(jlong, jfr_host_total_memory(JNIEnv* env, jclass jvm))
#ifdef LINUX
// We want the host memory, not the container limit.
// os::physical_memory() would return the container limit.
- return os::Linux::physical_memory();
+ return static_cast(os::Linux::physical_memory());
#else
- return os::physical_memory();
+ return static_cast(os::physical_memory());
#endif
JVM_END
@@ -422,7 +422,10 @@ JVM_ENTRY_NO_ENV(jlong, jfr_host_total_swap_memory(JNIEnv* env, jclass jvm))
// We want the host swap memory, not the container value.
return os::Linux::host_swap();
#else
- return os::total_swap_space();
+ physical_memory_size_type total_swap_space = 0;
+ // Return value ignored - defaulting to 0 on failure.
+ (void)os::total_swap_space(total_swap_space);
+ return static_cast(total_swap_space);
#endif
JVM_END
diff --git a/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp b/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp
index 83eee96091e0..8b5819e92c40 100644
--- a/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp
+++ b/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp
@@ -34,6 +34,7 @@
#include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
+#include "runtime/os.hpp"
#include "utilities/align.hpp"
UnifiedOopRef DFSClosure::_reference_stack[max_dfs_depth];
@@ -67,9 +68,27 @@ void DFSClosure::find_leaks_from_root_set(EdgeStore* edge_store,
rs.process();
}
+static address calculate_headroom_limit() {
+ static constexpr size_t required_headroom = K * 64;
+ const Thread* const t = Thread::current_or_null();
+ return t->stack_end() + required_headroom;
+}
+
DFSClosure::DFSClosure(EdgeStore* edge_store, JFRBitSet* mark_bits, const Edge* start_edge)
:_edge_store(edge_store), _mark_bits(mark_bits), _start_edge(start_edge),
- _max_depth(max_dfs_depth), _depth(0), _ignore_root_set(false) {
+ _max_depth(max_dfs_depth), _depth(0), _ignore_root_set(false),
+ _headroom_limit(calculate_headroom_limit()) {
+}
+
+bool DFSClosure::have_headroom() const {
+ const address sp = (address) os::current_stack_pointer();
+#ifdef ASSERT
+ const Thread* const t = Thread::current_or_null();
+ assert(t->is_VM_thread(), "invariant");
+ assert(t->is_in_full_stack(_headroom_limit), "invariant");
+ assert(t->is_in_full_stack(sp), "invariant");
+#endif
+ return sp > _headroom_limit;
}
void DFSClosure::closure_impl(UnifiedOopRef reference, const oop pointee) {
@@ -97,7 +116,7 @@ void DFSClosure::closure_impl(UnifiedOopRef reference, const oop pointee) {
}
}
assert(_max_depth >= 1, "invariant");
- if (_depth < _max_depth - 1) {
+ if (_depth < _max_depth - 1 && have_headroom()) {
_depth++;
pointee->oop_iterate(this);
assert(_depth > 0, "invariant");
diff --git a/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.hpp b/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.hpp
index be0cd2a5d7eb..a22b5137380f 100644
--- a/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.hpp
+++ b/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.hpp
@@ -46,12 +46,15 @@ class DFSClosure : public BasicOopIterateClosure {
size_t _max_depth;
size_t _depth;
bool _ignore_root_set;
+ const address _headroom_limit;
DFSClosure(EdgeStore* edge_store, JFRBitSet* mark_bits, const Edge* start_edge);
void add_chain();
void closure_impl(UnifiedOopRef reference, const oop pointee);
+ bool have_headroom() const;
+
public:
virtual ReferenceIterationMode reference_iteration_mode() { return DO_FIELDS_EXCEPT_REFERENT; }
diff --git a/src/hotspot/share/jfr/leakprofiler/leakProfiler.cpp b/src/hotspot/share/jfr/leakprofiler/leakProfiler.cpp
index a5b4babb2b19..11be1c87ff41 100644
--- a/src/hotspot/share/jfr/leakprofiler/leakProfiler.cpp
+++ b/src/hotspot/share/jfr/leakprofiler/leakProfiler.cpp
@@ -34,9 +34,15 @@
#include "runtime/vmThread.hpp"
bool LeakProfiler::is_supported() {
- if (UseShenandoahGC) {
+ if (UseShenandoahGC || UseZGC) {
// Leak Profiler uses mark words in the ways that might interfere
// with concurrent GC uses of them. This affects Shenandoah.
+ //
+ // Generational ZGC only does weak reference processing in the old generation.
+ // All objects that would usually die, because we are sampling stuff
+ // that immediately becomes garbage, will be artificially kept alive
+ // until an old-generation collection. This incurs a significant
+ // performance hit by causing allocation stalls.
return false;
}
return true;
@@ -58,7 +64,8 @@ bool LeakProfiler::start(int sample_count) {
// Exit cleanly if not supported
if (!is_supported()) {
- log_trace(jfr, system)("Object sampling is not supported");
+ log_info(jfr, system)("jdk.OldObjectSample event is currently not supported for %s.",
+ UseShenandoahGC ? "ShenandoahGC" : "ZGC");
return false;
}
diff --git a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp
index 00d41a10bf0e..e7f12f7428f0 100644
--- a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp
+++ b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp
@@ -528,17 +528,26 @@ TRACE_REQUEST_FUNC(ThreadAllocationStatistics) {
* the total memory reported is the amount of memory configured for the guest OS by the hypervisor.
*/
TRACE_REQUEST_FUNC(PhysicalMemory) {
- u8 totalPhysicalMemory = os::physical_memory();
+ physical_memory_size_type totalPhysicalMemory = os::physical_memory();
EventPhysicalMemory event;
event.set_totalSize(totalPhysicalMemory);
- event.set_usedSize(totalPhysicalMemory - os::available_memory());
+ physical_memory_size_type avail_mem = 0;
+ // Return value ignored - defaulting to 0 on failure.
+ (void)os::available_memory(avail_mem);
+ event.set_usedSize(totalPhysicalMemory - avail_mem);
event.commit();
}
TRACE_REQUEST_FUNC(SwapSpace) {
EventSwapSpace event;
- event.set_totalSize(os::total_swap_space());
- event.set_freeSize(os::free_swap_space());
+ physical_memory_size_type total_swap_space = 0;
+ // Return value ignored - defaulting to 0 on failure.
+ (void)os::total_swap_space(total_swap_space);
+ event.set_totalSize(static_cast(total_swap_space));
+ physical_memory_size_type free_swap_space = 0;
+ // Return value ignored - defaulting to 0 on failure.
+ (void)os::free_swap_space(free_swap_space);
+ event.set_freeSize(static_cast(free_swap_space));
event.commit();
}
diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp
index 63695ab73353..4e5567fec6ee 100644
--- a/src/hotspot/share/oops/cpCache.cpp
+++ b/src/hotspot/share/oops/cpCache.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -550,6 +550,8 @@ bool ConstantPoolCache::can_archive_resolved_method(ConstantPool* src_cp, Resolv
return false;
}
+ int cp_index = method_entry->constant_pool_index();
+
if (!method_entry->is_resolved(Bytecodes::_invokevirtual)) {
if (method_entry->method() == nullptr) {
return false;
@@ -557,9 +559,27 @@ bool ConstantPoolCache::can_archive_resolved_method(ConstantPool* src_cp, Resolv
if (method_entry->method()->is_continuation_native_intrinsic()) {
return false; // FIXME: corresponding stub is generated on demand during method resolution (see LinkResolver::resolve_static_call).
}
+ if (method_entry->is_resolved(Bytecodes::_invokehandle)) {
+ if (!CDSConfig::is_dumping_method_handles()) {
+ return false;
+ }
+
+ Symbol* sig = constant_pool()->uncached_signature_ref_at(cp_index);
+ Klass* k;
+ if (!AOTConstantPoolResolver::check_methodtype_signature(constant_pool(), sig, &k, true)) {
+ // invokehandles that were resolved in the training run should have been filtered in
+ // AOTConstantPoolResolver::maybe_resolve_fmi_ref so we shouldn't come to here.
+ //
+ // If we come here it's because the AOT assembly phase has executed an invokehandle
+ // that uses an excluded type like jdk.jfr.Event. This should not happen because the
+ // AOT assembly phase should execute only a very limited set of Java code.
+ ResourceMark rm;
+ fatal("AOT assembly phase must not resolve any invokehandles whose signatures include an excluded type");
+ }
+ return true;
+ }
}
- int cp_index = method_entry->constant_pool_index();
assert(src_cp->tag_at(cp_index).is_method() || src_cp->tag_at(cp_index).is_interface_method(), "sanity");
if (!AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index)) {
@@ -570,13 +590,6 @@ bool ConstantPoolCache::can_archive_resolved_method(ConstantPool* src_cp, Resolv
method_entry->is_resolved(Bytecodes::_invokevirtual) ||
method_entry->is_resolved(Bytecodes::_invokespecial)) {
return true;
- } else if (method_entry->is_resolved(Bytecodes::_invokehandle)) {
- if (CDSConfig::is_dumping_method_handles()) {
- // invokehandle depends on archived MethodType and LambdaForms.
- return true;
- } else {
- return false;
- }
} else {
return false;
}
diff --git a/src/hotspot/share/opto/arraycopynode.cpp b/src/hotspot/share/opto/arraycopynode.cpp
index 85b6bd21aece..c02aefc79437 100644
--- a/src/hotspot/share/opto/arraycopynode.cpp
+++ b/src/hotspot/share/opto/arraycopynode.cpp
@@ -212,6 +212,15 @@ Node* ArrayCopyNode::try_clone_instance(PhaseGVN *phase, bool can_reshape, int c
}
}
+ const TypeInstPtr* dest_type = phase->type(base_dest)->is_instptr();
+ if (dest_type->instance_klass() != ik) {
+ // At parse time, the exact type of the object to clone was not known. That inexact type was captured by the CheckCastPP
+ // of the newly allocated cloned object (in dest). The exact type is now known (in src), but the type for the cloned object
+ // (dest) was not updated. When copying the fields below, Store nodes may write to offsets for fields that don't exist in
+ // the inexact class. The stores would then be assigned an incorrect slice.
+ return NodeSentinel;
+ }
+
assert(ik->nof_nonstatic_fields() <= ArrayCopyLoadStoreMaxElem, "too many fields");
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp
index e0ad2f00ab57..fa78fa73e37c 100644
--- a/src/hotspot/share/opto/callGenerator.cpp
+++ b/src/hotspot/share/opto/callGenerator.cpp
@@ -424,7 +424,6 @@ bool LateInlineMHCallGenerator::do_late_inline_check(Compile* C, JVMState* jvms)
}
assert(!cg->is_late_inline() || cg->is_mh_late_inline() || AlwaysIncrementalInline || StressIncrementalInlining, "we're doing late inlining");
_inline_cg = cg;
- C->dec_number_of_mh_late_inlines();
return true;
} else {
// Method handle call which has a constant appendix argument should be either inlined or replaced with a direct call
@@ -436,7 +435,7 @@ bool LateInlineMHCallGenerator::do_late_inline_check(Compile* C, JVMState* jvms)
CallGenerator* CallGenerator::for_mh_late_inline(ciMethod* caller, ciMethod* callee, bool input_not_const) {
assert(IncrementalInlineMH, "required");
- Compile::current()->inc_number_of_mh_late_inlines();
+ Compile::current()->mark_has_mh_late_inlines();
CallGenerator* cg = new LateInlineMHCallGenerator(caller, callee, input_not_const);
return cg;
}
diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp
index f0fa73f11ce7..6f13ce0f809a 100644
--- a/src/hotspot/share/opto/callnode.cpp
+++ b/src/hotspot/share/opto/callnode.cpp
@@ -1145,7 +1145,6 @@ Node* CallStaticJavaNode::Ideal(PhaseGVN* phase, bool can_reshape) {
assert(callee->has_member_arg(), "wrong type of call?");
if (in(TypeFunc::Parms + callee->arg_size() - 1)->Opcode() == Op_ConP) {
register_for_late_inline();
- phase->C->inc_number_of_mh_late_inlines();
}
}
} else {
diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp
index 210f58e134f8..8b8c641c57c1 100644
--- a/src/hotspot/share/opto/callnode.hpp
+++ b/src/hotspot/share/opto/callnode.hpp
@@ -729,9 +729,10 @@ class CallNode : public SafePointNode {
// for some macro nodes whose expansion does not have a safepoint on the fast path.
virtual bool guaranteed_safepoint() { return true; }
// For macro nodes, the JVMState gets modified during expansion. If calls
- // use MachConstantBase, it gets modified during matching. So when cloning
- // the node the JVMState must be deep cloned. Default is to shallow clone.
- virtual bool needs_deep_clone_jvms(Compile* C) { return C->needs_deep_clone_jvms(); }
+ // use MachConstantBase, it gets modified during matching. If the call is
+ // late inlined, it also needs the full JVMState. So when cloning the
+ // node the JVMState must be deep cloned. Default is to shallow clone.
+ virtual bool needs_deep_clone_jvms(Compile* C) { return _generator != nullptr || C->needs_deep_clone_jvms(); }
// Returns true if the call may modify n
virtual bool may_modify(const TypeOopPtr* t_oop, PhaseValues* phase);
diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp
index 92f6c938dbac..cdcfe3a6b351 100644
--- a/src/hotspot/share/opto/cfgnode.cpp
+++ b/src/hotspot/share/opto/cfgnode.cpp
@@ -2580,6 +2580,10 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
for( uint i=1; i _vector_reboxing_late_inlines; // same but for vector reboxing operations
int _late_inlines_pos; // Where in the queue should the next late inlining candidate go (emulate depth first inlining)
- uint _number_of_mh_late_inlines; // number of method handle late inlining still pending
+ bool _has_mh_late_inlines; // Can there still be a method handle late inlining pending?
+ // false: there can't be one
+ // true: we've enqueued one at some point so there may still be one
// "MemLimit" directive was specified and the memory limit was hit during compilation
bool _oom;
@@ -1087,9 +1089,8 @@ class Compile : public Phase {
}
}
- void inc_number_of_mh_late_inlines() { _number_of_mh_late_inlines++; }
- void dec_number_of_mh_late_inlines() { assert(_number_of_mh_late_inlines > 0, "_number_of_mh_late_inlines < 0 !"); _number_of_mh_late_inlines--; }
- bool has_mh_late_inlines() const { return _number_of_mh_late_inlines > 0; }
+ void mark_has_mh_late_inlines() { _has_mh_late_inlines = true; }
+ bool has_mh_late_inlines() const { return _has_mh_late_inlines; }
bool inline_incrementally_one();
void inline_incrementally_cleanup(PhaseIterGVN& igvn);
diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp
index 3dd43f12b2f5..d7253b065995 100644
--- a/src/hotspot/share/opto/escape.cpp
+++ b/src/hotspot/share/opto/escape.cpp
@@ -3129,6 +3129,14 @@ void ConnectionGraph::find_scalar_replaceable_allocs(GrowableArrayis_LocalVar()) {
+ Node* phi = use->ideal_node();
+ if (phi->Opcode() == Op_Phi && reducible_merges.member(phi) && !can_reduce_phi(phi->as_Phi())) {
+ set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is merged in a non-reducible phi"));
+ reducible_merges.yank(phi);
+ found_nsr_alloc = true;
+ break;
+ }
}
}
}
diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp
index 99fedcdf8802..acf1dbabf198 100644
--- a/src/hotspot/share/opto/macro.cpp
+++ b/src/hotspot/share/opto/macro.cpp
@@ -2312,12 +2312,7 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) {
// No need for a null check on unlock
// Make the merge point
- Node *region;
- Node *mem_phi;
-
- region = new RegionNode(3);
- // create a Phi for the memory state
- mem_phi = new PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM);
+ Node* region = new RegionNode(3);
FastUnlockNode *funlock = new FastUnlockNode( ctrl, obj, box );
funlock = transform_later( funlock )->as_FastUnlock();
@@ -2346,12 +2341,15 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) {
transform_later(region);
_igvn.replace_node(_callprojs.fallthrough_proj, region);
- Node *memproj = transform_later(new ProjNode(call, TypeFunc::Memory) );
- mem_phi->init_req(1, memproj );
- mem_phi->init_req(2, mem);
- transform_later(mem_phi);
-
- _igvn.replace_node(_callprojs.fallthrough_memproj, mem_phi);
+ if (_callprojs.fallthrough_memproj != nullptr) {
+ // create a Phi for the memory state
+ Node* mem_phi = new PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM);
+ Node* memproj = transform_later(new ProjNode(call, TypeFunc::Memory));
+ mem_phi->init_req(1, memproj);
+ mem_phi->init_req(2, mem);
+ transform_later(mem_phi);
+ _igvn.replace_node(_callprojs.fallthrough_memproj, mem_phi);
+ }
}
void PhaseMacroExpand::expand_subtypecheck_node(SubTypeCheckNode *check) {
diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp
index c1413929b6c3..f7d7aa15fc47 100644
--- a/src/hotspot/share/prims/jvm.cpp
+++ b/src/hotspot/share/prims/jvm.cpp
@@ -228,6 +228,19 @@ extern void trace_class_resolution(Klass* to_class) {
// java.lang.System //////////////////////////////////////////////////////////////////////
+JVM_ENTRY(jboolean, JVM_AOTEndRecording(JNIEnv *env))
+#if INCLUDE_CDS
+ if (CDSConfig::is_dumping_preimage_static_archive()) {
+ if (!MetaspaceShared::preimage_static_archive_dumped()) {
+ MetaspaceShared::preload_and_dump(THREAD);
+ return JNI_TRUE;
+ }
+ }
+ return JNI_FALSE;
+#else
+ return JNI_FALSE;
+#endif // INCLUDE_CDS
+JVM_END
JVM_LEAF(jlong, JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored))
return os::javaTimeMillis();
diff --git a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
index 614470f22c9b..a2edf7296575 100644
--- a/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
+++ b/src/hotspot/share/prims/jvmtiEnhancedRedefineClasses.cpp
@@ -1150,9 +1150,11 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions_single_step(Old2N
}
}
+ physical_memory_size_type avail_mem = 0;
+ (void)os::available_memory(avail_mem);
log_debug(redefine, class, load)
- ("loading name=%s kind=%d (avail_mem=" UINT64_FORMAT "K)",
- the_class->external_name(), _class_load_kind, os::available_memory() >> 10);
+ ("loading name=%s kind=%d (avail_mem=" PHYS_MEM_TYPE_FORMAT "K)",
+ the_class->external_name(), _class_load_kind, avail_mem >> 10);
// class bytes...
const unsigned char* class_bytes;
@@ -1304,8 +1306,9 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions_single_step(Old2N
_object_klass_redefined = true;
}
+ (void)os::available_memory(avail_mem);
log_debug(redefine, class, load)
- ("loaded name=%s (avail_mem=" UINT64_FORMAT "K)", the_class->external_name(), os::available_memory() >> 10);
+ ("loaded name=%s (avail_mem=" PHYS_MEM_TYPE_FORMAT "K)", the_class->external_name(), avail_mem >> 10);
}
return JVMTI_ERROR_NONE;
@@ -2366,9 +2369,11 @@ void VM_EnhancedRedefineClasses::redefine_single_class(Thread *current, Instance
// increment the classRedefinedCount field in the_class and in any
// direct and indirect subclasses of the_class
increment_class_counter(current, new_class);
+ physical_memory_size_type avail_mem = 0;
+ (void)os::available_memory(avail_mem);
log_info(redefine, class, load)
- ("redefined name=%s, count=%d (avail_mem=" UINT64_FORMAT "K)",
- new_class->external_name(), java_lang_Class::classRedefinedCount(new_class->java_mirror()), os::available_memory() >> 10);
+ ("redefined name=%s, count=%d (avail_mem=" PHYS_MEM_TYPE_FORMAT "K)",
+ new_class->external_name(), java_lang_Class::classRedefinedCount(new_class->java_mirror()), avail_mem >> 10);
Events::log_redefinition(current, "redefined class name=%s, count=%d",
new_class->external_name(),
java_lang_Class::classRedefinedCount(new_class->java_mirror()));
diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp
index 845a806e0140..5b633d3aab09 100644
--- a/src/hotspot/share/prims/jvmtiExport.cpp
+++ b/src/hotspot/share/prims/jvmtiExport.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -71,6 +71,7 @@
#include "runtime/threadSMR.hpp"
#include "runtime/vframe.inline.hpp"
#include "runtime/vm_version.hpp"
+#include "utilities/events.hpp"
#include "utilities/macros.hpp"
#ifdef JVMTI_TRACE
@@ -626,22 +627,27 @@ JvmtiExport::decode_version_values(jint version, int * major, int * minor,
}
void JvmtiExport::enter_primordial_phase() {
+ Events::log(Thread::current_or_null(), "JVMTI - enter primordial phase");
JvmtiEnvBase::set_phase(JVMTI_PHASE_PRIMORDIAL);
}
void JvmtiExport::enter_early_start_phase() {
+ Events::log(Thread::current_or_null(), "JVMTI - enter early start phase");
set_early_vmstart_recorded(true);
}
void JvmtiExport::enter_start_phase() {
+ Events::log(Thread::current_or_null(), "JVMTI - enter start phase");
JvmtiEnvBase::set_phase(JVMTI_PHASE_START);
}
void JvmtiExport::enter_onload_phase() {
+ Events::log(Thread::current_or_null(), "JVMTI - enter onload phase");
JvmtiEnvBase::set_phase(JVMTI_PHASE_ONLOAD);
}
void JvmtiExport::enter_live_phase() {
+ Events::log(Thread::current_or_null(), "JVMTI - enter live phase");
JvmtiEnvBase::set_phase(JVMTI_PHASE_LIVE);
}
@@ -779,6 +785,7 @@ void JvmtiExport::post_vm_death() {
}
}
+ Events::log(Thread::current_or_null(), "JVMTI - enter dead phase");
JvmtiEnvBase::set_phase(JVMTI_PHASE_DEAD);
JvmtiEventController::vm_death();
}
@@ -1726,6 +1733,23 @@ void JvmtiExport::post_vthread_unmount(jobject vthread) {
}
}
+bool JvmtiExport::has_frame_pops(JavaThread* thread) {
+ if (!can_post_frame_pop()) {
+ return false;
+ }
+ JvmtiThreadState *state = get_jvmti_thread_state(thread);
+ if (state == nullptr) {
+ return false;
+ }
+ JvmtiEnvThreadStateIterator it(state);
+ for (JvmtiEnvThreadState* ets = it.first(); ets != nullptr; ets = it.next(ets)) {
+ if (ets->has_frame_pops()) {
+ return true;
+ }
+ }
+ return false;
+}
+
void JvmtiExport::continuation_yield_cleanup(JavaThread* thread, jint continuation_frame_count) {
if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
return;
diff --git a/src/hotspot/share/prims/jvmtiExport.hpp b/src/hotspot/share/prims/jvmtiExport.hpp
index dd9254f303b7..83a8c31d0a00 100644
--- a/src/hotspot/share/prims/jvmtiExport.hpp
+++ b/src/hotspot/share/prims/jvmtiExport.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2025, 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
@@ -374,6 +374,7 @@ class JvmtiExport : public AllStatic {
JVMTI_ONLY(return _should_post_class_file_load_hook);
NOT_JVMTI(return false;)
}
+ static bool has_frame_pops(JavaThread* thread) NOT_JVMTI_RETURN_(false);
static bool is_early_phase() NOT_JVMTI_RETURN_(false);
static bool has_early_class_hook_env() NOT_JVMTI_RETURN_(false);
static bool has_early_vmstart_env() NOT_JVMTI_RETURN_(false);
diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
index d2c1fc423f94..c8f519568b46 100644
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
@@ -1356,10 +1356,12 @@ jvmtiError VM_RedefineClasses::load_new_class_versions() {
// constant pools
HandleMark hm(current);
InstanceKlass* the_class = get_ik(_class_defs[i].klass);
-
+ physical_memory_size_type avail_mem = 0;
+ // Return value ignored - defaulting to 0 on failure.
+ (void)os::available_memory(avail_mem);
log_debug(redefine, class, load)
- ("loading name=%s kind=%d (avail_mem=" UINT64_FORMAT "K)",
- the_class->external_name(), _class_load_kind, os::available_memory() >> 10);
+ ("loading name=%s kind=%d (avail_mem=" PHYS_MEM_TYPE_FORMAT "K)",
+ the_class->external_name(), _class_load_kind, avail_mem >> 10);
ClassFileStream st((u1*)_class_defs[i].class_bytes,
_class_defs[i].class_byte_count,
@@ -1484,6 +1486,8 @@ jvmtiError VM_RedefineClasses::load_new_class_versions() {
} else {
return JVMTI_ERROR_INTERNAL;
}
+ } else if (res != JVMTI_ERROR_NONE) {
+ return res;
}
#ifdef ASSERT
@@ -1524,9 +1528,10 @@ jvmtiError VM_RedefineClasses::load_new_class_versions() {
return JVMTI_ERROR_INTERNAL;
}
}
-
+ // Return value ignored - defaulting to 0 on failure.
+ (void)os::available_memory(avail_mem);
log_debug(redefine, class, load)
- ("loaded name=%s (avail_mem=" UINT64_FORMAT "K)", the_class->external_name(), os::available_memory() >> 10);
+ ("loaded name=%s (avail_mem=" PHYS_MEM_TYPE_FORMAT "K)", the_class->external_name(), avail_mem >> 10);
}
return JVMTI_ERROR_NONE;
@@ -2055,7 +2060,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_record_attribute(InstanceKlass* scra
AnnotationArray* type_annotations = component->type_annotations();
if (type_annotations != nullptr && type_annotations->length() != 0) {
int byte_i = 0; // byte index into annotations
- if (!rewrite_cp_refs_in_annotations_typeArray(type_annotations, byte_i)) {
+ if (!rewrite_cp_refs_in_type_annotations_typeArray(type_annotations, byte_i, "record_info")) {
log_debug(redefine, class, annotation)("bad record_component_type_annotations at %d", i);
// propagate failure back to caller
return false;
@@ -4423,9 +4428,12 @@ void VM_RedefineClasses::redefine_single_class(Thread* current, jclass the_jclas
ResourceMark rm(current);
// increment the classRedefinedCount field in the_class and in any
// direct and indirect subclasses of the_class
+ physical_memory_size_type avail_mem = 0;
+ // Return value ignored - defaulting to 0 on failure.
+ (void)os::available_memory(avail_mem);
log_info(redefine, class, load)
- ("redefined name=%s, count=%d (avail_mem=" UINT64_FORMAT "K)",
- the_class->external_name(), java_lang_Class::classRedefinedCount(the_class->java_mirror()), os::available_memory() >> 10);
+ ("redefined name=%s, count=%d (avail_mem=" PHYS_MEM_TYPE_FORMAT "K)",
+ the_class->external_name(), java_lang_Class::classRedefinedCount(the_class->java_mirror()), avail_mem >> 10);
Events::log_redefinition(current, "redefined class name=%s, count=%d",
the_class->external_name(),
java_lang_Class::classRedefinedCount(the_class->java_mirror()));
diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp
index f9f37d84ddef..9999b59decee 100644
--- a/src/hotspot/share/prims/whitebox.cpp
+++ b/src/hotspot/share/prims/whitebox.cpp
@@ -2544,13 +2544,16 @@ WB_END
// Physical memory of the host machine (including containers)
WB_ENTRY(jlong, WB_HostPhysicalMemory(JNIEnv* env, jobject o))
- LINUX_ONLY(return os::Linux::physical_memory();)
- return os::physical_memory();
+ LINUX_ONLY(return static_cast(os::Linux::physical_memory());)
+ return static_cast(os::physical_memory());
WB_END
// Available memory of the host machine (container-aware)
WB_ENTRY(jlong, WB_HostAvailableMemory(JNIEnv* env, jobject o))
- return os::available_memory();
+ physical_memory_size_type avail_mem = 0;
+ // Return value ignored - defaulting to 0 on failure.
+ (void)os::available_memory(avail_mem);
+ return static_cast(avail_mem);
WB_END
// Physical swap of the host machine (including containers), Linux only.
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
index 00dd260c750b..e908d4cfc90d 100644
--- a/src/hotspot/share/runtime/arguments.cpp
+++ b/src/hotspot/share/runtime/arguments.cpp
@@ -1483,6 +1483,7 @@ void Arguments::set_conservative_max_heap_alignment() {
os::vm_allocation_granularity(),
os::max_page_size(),
GCArguments::compute_heap_alignment());
+ assert(is_power_of_2(_conservative_max_heap_alignment), "Expected to be a power-of-2");
}
jint Arguments::set_ergonomics_flags() {
@@ -1534,13 +1535,13 @@ void Arguments::set_heap_size() {
!FLAG_IS_DEFAULT(MaxRAM));
if (override_coop_limit) {
if (FLAG_IS_DEFAULT(MaxRAM)) {
- phys_mem = os::physical_memory();
+ phys_mem = static_cast(os::physical_memory());
FLAG_SET_ERGO(MaxRAM, (uint64_t)phys_mem);
} else {
phys_mem = (julong)MaxRAM;
}
} else {
- phys_mem = FLAG_IS_DEFAULT(MaxRAM) ? MIN2(os::physical_memory(), (julong)MaxRAM)
+ phys_mem = FLAG_IS_DEFAULT(MaxRAM) ? MIN2(static_cast(os::physical_memory()), (julong)MaxRAM)
: (julong)MaxRAM;
}
@@ -1662,7 +1663,8 @@ jint Arguments::set_aggressive_heap_flags() {
// Thus, we need to make sure we're using a julong for intermediate
// calculations.
julong initHeapSize;
- julong total_memory = os::physical_memory();
+ physical_memory_size_type phys_mem = os::physical_memory();
+ julong total_memory = static_cast(phys_mem);
if (total_memory < (julong) 256 * M) {
jio_fprintf(defaultStream::error_stream(),
diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp
index a928b0443eef..821b32f21ed2 100644
--- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp
+++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp
@@ -1623,15 +1623,14 @@ static int num_java_frames(ContinuationWrapper& cont) {
}
static void invalidate_jvmti_stack(JavaThread* thread) {
- if (thread->is_interp_only_mode()) {
- JvmtiThreadState *state = thread->jvmti_thread_state();
- if (state != nullptr)
- state->invalidate_cur_stack_depth();
+ JvmtiThreadState *state = thread->jvmti_thread_state();
+ if (state != nullptr) {
+ state->invalidate_cur_stack_depth();
}
}
static void jvmti_yield_cleanup(JavaThread* thread, ContinuationWrapper& cont) {
- if (JvmtiExport::can_post_frame_pop()) {
+ if (JvmtiExport::has_frame_pops(thread)) {
int num_frames = num_java_frames(cont);
ContinuationWrapper::SafepointOp so(Thread::current(), cont);
diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp
index 6f8d492e1403..462c3a4073aa 100644
--- a/src/hotspot/share/runtime/os.cpp
+++ b/src/hotspot/share/runtime/os.cpp
@@ -1184,12 +1184,13 @@ void os::print_summary_info(outputStream* st, char* buf, size_t buflen) {
#endif // PRODUCT
get_summary_cpu_info(buf, buflen);
st->print("%s, ", buf);
- size_t mem = physical_memory()/G;
+ physical_memory_size_type phys_mem = physical_memory();
+ physical_memory_size_type mem = phys_mem/G;
if (mem == 0) { // for low memory systems
- mem = physical_memory()/M;
- st->print("%d cores, %zuM, ", processor_count(), mem);
+ mem = phys_mem/M;
+ st->print("%d cores, " PHYS_MEM_TYPE_FORMAT "M, ", processor_count(), mem);
} else {
- st->print("%d cores, %zuG, ", processor_count(), mem);
+ st->print("%d cores, " PHYS_MEM_TYPE_FORMAT "G, ", processor_count(), mem);
}
get_summary_os_info(buf, buflen);
st->print_raw(buf);
@@ -1934,17 +1935,17 @@ bool os::is_server_class_machine() {
return true;
}
// Then actually look at the machine
- bool result = false;
- const unsigned int server_processors = 2;
- const julong server_memory = 2UL * G;
+ bool result = false;
+ const unsigned int server_processors = 2;
+ const physical_memory_size_type server_memory = 2UL * G;
// We seem not to get our full complement of memory.
// We allow some part (1/8?) of the memory to be "missing",
// based on the sizes of DIMMs, and maybe graphics cards.
- const julong missing_memory = 256UL * M;
-
+ const physical_memory_size_type missing_memory = 256UL * M;
+ physical_memory_size_type phys_mem = os::physical_memory();
/* Is this a server class machine? */
if ((os::active_processor_count() >= (int)server_processors) &&
- (os::physical_memory() >= (server_memory - missing_memory))) {
+ (phys_mem >= server_memory - missing_memory)) {
const unsigned int logical_processors =
VM_Version::logical_processors_per_package();
if (logical_processors > 1) {
@@ -2203,16 +2204,24 @@ static void assert_nonempty_range(const char* addr, size_t bytes) {
p2i(addr), p2i(addr) + bytes);
}
-julong os::used_memory() {
+bool os::used_memory(physical_memory_size_type& value) {
#ifdef LINUX
if (OSContainer::is_containerized()) {
jlong mem_usage = OSContainer::memory_usage_in_bytes();
if (mem_usage > 0) {
- return mem_usage;
+ value = static_cast(mem_usage);
+ return true;
+ } else {
+ return false;
}
}
#endif
- return os::physical_memory() - os::available_memory();
+ physical_memory_size_type avail_mem = 0;
+ // Return value ignored - defaulting to 0 on failure.
+ (void)os::available_memory(avail_mem);
+ physical_memory_size_type phys_mem = os::physical_memory();
+ value = phys_mem - avail_mem;
+ return true;
}
diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp
index b23336f2b739..dfe46f6ddd3f 100644
--- a/src/hotspot/share/runtime/os.hpp
+++ b/src/hotspot/share/runtime/os.hpp
@@ -337,14 +337,14 @@ class os: AllStatic {
// For example, on Linux, "available" memory (`MemAvailable` in `/proc/meminfo`) is greater
// than "free" memory (`MemFree` in `/proc/meminfo`) because Linux can free memory
// aggressively (e.g. clear caches) so that it becomes available.
- static julong available_memory();
- static julong used_memory();
- static julong free_memory();
+ [[nodiscard]] static bool available_memory(physical_memory_size_type& value);
+ [[nodiscard]] static bool used_memory(physical_memory_size_type& value);
+ [[nodiscard]] static bool free_memory(physical_memory_size_type& value);
- static jlong total_swap_space();
- static jlong free_swap_space();
+ [[nodiscard]] static bool total_swap_space(physical_memory_size_type& value);
+ [[nodiscard]] static bool free_swap_space(physical_memory_size_type& value);
- static julong physical_memory();
+ static physical_memory_size_type physical_memory();
static bool has_allocatable_memory_limit(size_t* limit);
static bool is_server_class_machine();
static size_t rss();
diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp
index 503b78333517..6c1591e57cec 100644
--- a/src/hotspot/share/runtime/synchronizer.cpp
+++ b/src/hotspot/share/runtime/synchronizer.cpp
@@ -2048,7 +2048,11 @@ void ObjectSynchronizer::chk_in_use_entry(ObjectMonitor* n, outputStream* out,
}
const markWord mark = obj->mark();
- if (!mark.has_monitor()) {
+ // Note: When using ObjectMonitorTable we may observe an intermediate state,
+ // where the monitor is globally visible, but no thread has yet transitioned
+ // the markWord. To avoid reporting a false positive during this transition, we
+ // skip the `!mark.has_monitor()` test if we are using the ObjectMonitorTable.
+ if (!UseObjectMonitorTable && !mark.has_monitor()) {
out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use monitor's "
"object does not think it has a monitor: obj="
INTPTR_FORMAT ", mark=" INTPTR_FORMAT, p2i(n),
diff --git a/src/hotspot/share/runtime/threadSMR.cpp b/src/hotspot/share/runtime/threadSMR.cpp
index 631a7ed8d797..1eb6195543a1 100644
--- a/src/hotspot/share/runtime/threadSMR.cpp
+++ b/src/hotspot/share/runtime/threadSMR.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -726,7 +726,8 @@ JavaThread* ThreadsList::find_JavaThread_from_java_tid(jlong java_tid) const {
}
}
}
- } else if (!thread->is_exiting()) {
+ } else if (includes(thread) && !thread->is_exiting()) {
+ // The thread is protected by this list and has not yet exited
return thread;
}
return nullptr;
@@ -865,7 +866,7 @@ void ThreadsSMRSupport::add_thread(JavaThread *thread){
ThreadsList *old_list = xchg_java_thread_list(new_list);
free_list(old_list);
- if (ThreadIdTable::is_initialized()) {
+ if (ThreadIdTable::is_initialized_acquire()) {
jlong tid = SharedRuntime::get_java_tid(thread);
ThreadIdTable::add_thread(tid, thread);
}
diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp
index f4b4415eef20..7218a3e6c8fa 100644
--- a/src/hotspot/share/runtime/threads.cpp
+++ b/src/hotspot/share/runtime/threads.cpp
@@ -1108,7 +1108,7 @@ void Threads::remove(JavaThread* p, bool is_daemon) {
ConditionalMutexLocker throttle_ml(ThreadsLockThrottle_lock, UseThreadsLockThrottleLock);
MonitorLocker ml(Threads_lock);
- if (ThreadIdTable::is_initialized()) {
+ if (ThreadIdTable::is_initialized_acquire()) {
// This cleanup must be done before the current thread's GC barrier
// is detached since we need to touch the threadObj oop.
jlong tid = SharedRuntime::get_java_tid(p);
diff --git a/src/hotspot/share/services/heapDumper.cpp b/src/hotspot/share/services/heapDumper.cpp
index 731a26f7cf1e..c9ac86063d0d 100644
--- a/src/hotspot/share/services/heapDumper.cpp
+++ b/src/hotspot/share/services/heapDumper.cpp
@@ -2612,7 +2612,10 @@ int HeapDumper::dump(const char* path, outputStream* out, int compression, bool
// (DumpWriter buffer, DumperClassCacheTable, GZipCompressor buffers).
// For the OOM handling we may already be limited in memory.
// Lets ensure we have at least 20MB per thread.
- julong max_threads = os::free_memory() / (20 * M);
+ physical_memory_size_type free_memory = 0;
+ // Return value ignored - defaulting to 0 on failure.
+ (void)os::free_memory(free_memory);
+ julong max_threads = free_memory / (20 * M);
if (num_dump_threads > max_threads) {
num_dump_threads = MAX2(1, (uint)max_threads);
}
diff --git a/src/hotspot/share/services/management.cpp b/src/hotspot/share/services/management.cpp
index 070d4daa3fb5..9d4ed5ff94a5 100644
--- a/src/hotspot/share/services/management.cpp
+++ b/src/hotspot/share/services/management.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -975,7 +975,7 @@ static jlong get_long_attribute(jmmLongAttribute att) {
return ClassLoadingService::class_method_data_size();
case JMM_OS_MEM_TOTAL_PHYSICAL_BYTES:
- return os::physical_memory();
+ return static_cast(os::physical_memory());
default:
return -1;
@@ -1127,6 +1127,7 @@ JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jo
// create dummy snapshot
dump_result.add_thread_snapshot();
} else {
+ assert(dump_result.t_list()->includes(jt), "Must be protected");
dump_result.add_thread_snapshot(jt);
}
}
diff --git a/src/hotspot/share/services/threadIdTable.cpp b/src/hotspot/share/services/threadIdTable.cpp
index e7fd97911483..54041dfbb83c 100644
--- a/src/hotspot/share/services/threadIdTable.cpp
+++ b/src/hotspot/share/services/threadIdTable.cpp
@@ -1,6 +1,6 @@
/*
-* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2019, 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
@@ -24,7 +24,7 @@
*/
#include "classfile/javaClasses.inline.hpp"
-#include "runtime/atomic.hpp"
+#include "runtime/handles.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/javaThread.inline.hpp"
#include "runtime/threadSMR.hpp"
@@ -82,24 +82,25 @@ class ThreadIdTableConfig : public AllStatic {
// Lazily creates the table and populates it with the given
// thread list
void ThreadIdTable::lazy_initialize(const ThreadsList *threads) {
- if (!_is_initialized) {
+ if (!Atomic::load_acquire(&_is_initialized)) {
{
// There is no obvious benefit in allowing the thread table
// to be concurrently populated during initialization.
MutexLocker ml(ThreadIdTableCreate_lock);
- if (_is_initialized) {
+ if (Atomic::load(&_is_initialized)) {
return;
}
create_table(threads->length());
- _is_initialized = true;
+ Atomic::release_store(&_is_initialized, true);
}
+
for (uint i = 0; i < threads->length(); i++) {
JavaThread* thread = threads->thread_at(i);
- oop tobj = thread->threadObj();
+ Handle tobj = Handle(JavaThread::current(), thread->threadObj());
if (tobj != nullptr) {
- jlong java_tid = java_lang_Thread::thread_id(tobj);
MutexLocker ml(Threads_lock);
if (!thread->is_exiting()) {
+ jlong java_tid = java_lang_Thread::thread_id(tobj());
// Must be inside the lock to ensure that we don't add a thread to the table
// that has just passed the removal point in Threads::remove().
add_thread(java_tid, thread);
@@ -212,7 +213,7 @@ class ThreadGet : public StackObj {
};
void ThreadIdTable::do_concurrent_work(JavaThread* jt) {
- assert(_is_initialized, "Thread table is not initialized");
+ assert(Atomic::load(&_is_initialized), "Thread table is not initialized");
_has_work = false;
double load_factor = get_load_factor();
log_debug(thread, table)("Concurrent work, load factor: %g", load_factor);
@@ -222,7 +223,8 @@ void ThreadIdTable::do_concurrent_work(JavaThread* jt) {
}
JavaThread* ThreadIdTable::add_thread(jlong tid, JavaThread* java_thread) {
- assert(_is_initialized, "Thread table is not initialized");
+ assert(Threads_lock->owned_by_self(), "Must hold Threads_lock");
+ assert(Atomic::load(&_is_initialized), "Thread table is not initialized");
Thread* thread = Thread::current();
ThreadIdTableLookup lookup(tid);
ThreadGet tg;
@@ -241,7 +243,7 @@ JavaThread* ThreadIdTable::add_thread(jlong tid, JavaThread* java_thread) {
}
JavaThread* ThreadIdTable::find_thread_by_tid(jlong tid) {
- assert(_is_initialized, "Thread table is not initialized");
+ assert(Atomic::load(&_is_initialized), "Thread table is not initialized");
Thread* thread = Thread::current();
ThreadIdTableLookup lookup(tid);
ThreadGet tg;
@@ -250,7 +252,8 @@ JavaThread* ThreadIdTable::find_thread_by_tid(jlong tid) {
}
bool ThreadIdTable::remove_thread(jlong tid) {
- assert(_is_initialized, "Thread table is not initialized");
+ assert(Threads_lock->owned_by_self(), "Must hold Threads_lock");
+ assert(Atomic::load(&_is_initialized), "Thread table is not initialized");
Thread* thread = Thread::current();
ThreadIdTableLookup lookup(tid);
return _local_table->remove(thread, lookup);
diff --git a/src/hotspot/share/services/threadIdTable.hpp b/src/hotspot/share/services/threadIdTable.hpp
index 12772aed88c0..a292d04452a2 100644
--- a/src/hotspot/share/services/threadIdTable.hpp
+++ b/src/hotspot/share/services/threadIdTable.hpp
@@ -1,6 +1,6 @@
/*
-* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2019, 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
@@ -27,6 +27,7 @@
#define SHARE_SERVICES_THREADIDTABLE_HPP
#include "memory/allStatic.hpp"
+#include "runtime/atomic.hpp"
class JavaThread;
class ThreadsList;
@@ -41,7 +42,9 @@ class ThreadIdTable : public AllStatic {
public:
// Initialization
static void lazy_initialize(const ThreadsList* threads);
- static bool is_initialized() { return _is_initialized; }
+ static bool is_initialized_acquire() {
+ return Atomic::load_acquire(&_is_initialized);
+ }
// Lookup and list management
static JavaThread* find_thread_by_tid(jlong tid);
diff --git a/src/hotspot/share/services/threadService.cpp b/src/hotspot/share/services/threadService.cpp
index 57c5f330bfcb..e7a934787f49 100644
--- a/src/hotspot/share/services/threadService.cpp
+++ b/src/hotspot/share/services/threadService.cpp
@@ -1161,9 +1161,11 @@ class GetThreadSnapshotClosure: public HandshakeClosure {
Type _type;
// park blocker or an object the thread waiting on/trying to lock
OopHandle _obj;
+ // thread that owns park blocker object when park blocker is AbstractOwnableSynchronizer
+ OopHandle _owner;
- Blocker(Type type, OopHandle obj): _type(type), _obj(obj) {}
- Blocker(): _type(NOTHING), _obj(nullptr) {}
+ Blocker(Type type, OopHandle obj): _type(type), _obj(obj), _owner() {}
+ Blocker(): _type(NOTHING), _obj(), _owner() {}
bool is_empty() const {
return _type == NOTHING;
@@ -1198,6 +1200,7 @@ class GetThreadSnapshotClosure: public HandshakeClosure {
delete _locks;
}
_blocker._obj.release(oop_storage());
+ _blocker._owner.release(oop_storage());
}
private:
@@ -1299,6 +1302,13 @@ class GetThreadSnapshotClosure: public HandshakeClosure {
oop park_blocker = java_lang_Thread::park_blocker(_thread_h());
if (park_blocker != nullptr) {
_blocker = Blocker(Blocker::PARK_BLOCKER, OopHandle(oop_storage(), park_blocker));
+ if (park_blocker->is_a(vmClasses::java_util_concurrent_locks_AbstractOwnableSynchronizer_klass())) {
+ // could be stale (unlikely in practice), but it's good enough to see deadlocks
+ oop ownerObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(park_blocker);
+ if (ownerObj != nullptr) {
+ _blocker._owner = OopHandle(oop_storage(), ownerObj);
+ }
+ }
}
ResourceMark rm(current);
@@ -1380,6 +1390,7 @@ class jdk_internal_vm_ThreadSnapshot: AllStatic {
static int _locks_offset;
static int _blockerTypeOrdinal_offset;
static int _blockerObject_offset;
+ static int _parkBlockerOwner_offset;
static void compute_offsets(InstanceKlass* klass, TRAPS) {
JavaClasses::compute_offset(_name_offset, klass, "name", vmSymbols::string_signature(), false);
@@ -1389,6 +1400,7 @@ class jdk_internal_vm_ThreadSnapshot: AllStatic {
JavaClasses::compute_offset(_locks_offset, klass, "locks", vmSymbols::jdk_internal_vm_ThreadLock_array(), false);
JavaClasses::compute_offset(_blockerTypeOrdinal_offset, klass, "blockerTypeOrdinal", vmSymbols::int_signature(), false);
JavaClasses::compute_offset(_blockerObject_offset, klass, "blockerObject", vmSymbols::object_signature(), false);
+ JavaClasses::compute_offset(_parkBlockerOwner_offset, klass, "parkBlockerOwner", vmSymbols::thread_signature(), false);
}
public:
static void init(InstanceKlass* klass, TRAPS) {
@@ -1419,9 +1431,10 @@ class jdk_internal_vm_ThreadSnapshot: AllStatic {
static void set_locks(oop snapshot, oop locks) {
snapshot->obj_field_put(_locks_offset, locks);
}
- static void set_blocker(oop snapshot, int type_ordinal, oop lock) {
+ static void set_blocker(oop snapshot, int type_ordinal, oop lock, oop owner) {
snapshot->int_field_put(_blockerTypeOrdinal_offset, type_ordinal);
snapshot->obj_field_put(_blockerObject_offset, lock);
+ snapshot->obj_field_put(_parkBlockerOwner_offset, owner);
}
};
@@ -1433,6 +1446,7 @@ int jdk_internal_vm_ThreadSnapshot::_stackTrace_offset;
int jdk_internal_vm_ThreadSnapshot::_locks_offset;
int jdk_internal_vm_ThreadSnapshot::_blockerTypeOrdinal_offset;
int jdk_internal_vm_ThreadSnapshot::_blockerObject_offset;
+int jdk_internal_vm_ThreadSnapshot::_parkBlockerOwner_offset;
oop ThreadSnapshotFactory::get_thread_snapshot(jobject jthread, TRAPS) {
ThreadsListHandle tlh(THREAD);
@@ -1548,7 +1562,8 @@ oop ThreadSnapshotFactory::get_thread_snapshot(jobject jthread, TRAPS) {
jdk_internal_vm_ThreadSnapshot::set_stack_trace(snapshot(), trace());
jdk_internal_vm_ThreadSnapshot::set_locks(snapshot(), locks());
if (!cl._blocker.is_empty()) {
- jdk_internal_vm_ThreadSnapshot::set_blocker(snapshot(), cl._blocker._type, cl._blocker._obj.resolve());
+ jdk_internal_vm_ThreadSnapshot::set_blocker(snapshot(),
+ cl._blocker._type, cl._blocker._obj.resolve(), cl._blocker._owner.resolve());
}
return snapshot();
}
diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp
index 4ec61babec3d..bc6944175879 100644
--- a/src/hotspot/share/utilities/globalDefinitions.hpp
+++ b/src/hotspot/share/utilities/globalDefinitions.hpp
@@ -134,6 +134,7 @@ class oopDesc;
#define UINT64_FORMAT_X_0 "0x%016" PRIx64
#define UINT64_FORMAT_W(width) "%" #width PRIu64
#define UINT64_FORMAT_0 "%016" PRIx64
+#define PHYS_MEM_TYPE_FORMAT "%" PRIu64
// Format jlong, if necessary
#ifndef JLONG_FORMAT
@@ -413,6 +414,11 @@ const uintx max_uintx = (uintx)-1;
typedef unsigned int uint; NEEDS_CLEANUP
+// This typedef is to address the issue of running a 32-bit VM. In this case the amount
+// of physical memory may not fit in size_t, so we have to have a larger type. Once 32-bit
+// is deprecated, one can use size_t.
+typedef uint64_t physical_memory_size_type;
+
//----------------------------------------------------------------------------------------------------
// Java type definitions
diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp
index f3ca6be60421..8d40af0fd654 100644
--- a/src/hotspot/share/utilities/vmError.cpp
+++ b/src/hotspot/share/utilities/vmError.cpp
@@ -677,6 +677,7 @@ void VMError::report(outputStream* st, bool _verbose) {
BEGIN
if (MemTracker::enabled() &&
NmtVirtualMemory_lock != nullptr &&
+ _thread != nullptr &&
NmtVirtualMemory_lock->owned_by_self()) {
// Manually unlock to avoid reentrancy due to mallocs in detailed mode.
NmtVirtualMemory_lock->unlock();
@@ -1301,7 +1302,7 @@ void VMError::report(outputStream* st, bool _verbose) {
os::print_signal_handlers(st, buf, sizeof(buf));
st->cr();
- STEP_IF("Native Memory Tracking", _verbose)
+ STEP_IF("Native Memory Tracking", _verbose && _thread != nullptr)
MemTracker::error_report(st);
st->cr();
@@ -2395,10 +2396,12 @@ static void print_process_memory_usage_platform(outputStream *st)
os::Linux::meminfo_t info;
if (os::Linux::query_process_memory_info(&info)) {
ssize_t phys_total_kb = os::physical_memory() / K;
- ssize_t phys_avail_kb = os::available_memory() / K;
+ physical_memory_size_type avail_mem = 0;
+ (void)os::available_memory(avail_mem);
+ physical_memory_size_type phys_avail_kb = avail_mem / K;
int rss_percentile = (int)(info.vmrss * 100.0 / phys_total_kb);
st->print_cr("Resident Set Size: %zdK (%d%% of "
- "%zdK total physical memory with %zdK free physical memory)",
+ "%zdK total physical memory with " PHYS_MEM_TYPE_FORMAT "K free physical memory)",
info.vmrss, rss_percentile, phys_total_kb, phys_avail_kb);
} else {
st->print_cr("Could not open /proc/self/status to get process memory related information");
@@ -2418,10 +2421,12 @@ static void print_process_memory_usage_platform(outputStream *st)
if (ret != 0) {
ssize_t rss_kb = pmex.WorkingSetSize / K;
ssize_t phys_total_kb = os::physical_memory() / K;
- ssize_t phys_avail_kb = os::available_memory() / K;
+ physical_memory_size_type avail_mem = 0;
+ (void)os::available_memory(avail_mem);
+ physical_memory_size_type phys_avail_kb = avail_mem / K;
int rss_percentile = (int)(rss_kb * 100.0 / phys_total_kb);
st->print_cr("Resident Set Size: %zdK (%d%% of "
- "%zdK total physical memory with %zdK free physical memory)",
+ "%zdK total physical memory with " PHYS_MEM_TYPE_FORMAT "K free physical memory)",
rss_kb, rss_percentile, phys_total_kb, phys_avail_kb);
} else {
st->print_cr("GetProcessMemoryInfo() call did not succeed");
@@ -2440,10 +2445,12 @@ static void print_process_memory_usage_platform(outputStream *st)
if (ret == KERN_SUCCESS) {
ssize_t rss_kb = info.resident_size / K;
ssize_t phys_total_kb = os::physical_memory() / K;
- ssize_t phys_avail_kb = os::available_memory() / K;
+ physical_memory_size_type avail_mem = 0;
+ (void)os::available_memory(avail_mem);
+ physical_memory_size_type phys_avail_kb = avail_mem / K;
int rss_percentile = (int)(rss_kb * 100.0 / phys_total_kb);
st->print_cr("Resident Set Size: %zdK (%d%% of "
- "%zdK total physical memory with %zdK free physical memory)",
+ "%zdK total physical memory with " PHYS_MEM_TYPE_FORMAT "K free physical memory)",
rss_kb, rss_percentile, phys_total_kb, phys_avail_kb);
} else {
st->print_cr("task_info() call did not succeed");
diff --git a/src/java.base/linux/native/libnio/ch/FileDispatcherImpl.c b/src/java.base/linux/native/libnio/ch/FileDispatcherImpl.c
index efbd0ca56847..54d640b03a44 100644
--- a/src/java.base/linux/native/libnio/ch/FileDispatcherImpl.c
+++ b/src/java.base/linux/native/libnio/ch/FileDispatcherImpl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -63,7 +63,7 @@ Java_sun_nio_ch_FileDispatcherImpl_transferFrom0(JNIEnv *env, jobject this,
if (n < 0) {
if (errno == EAGAIN)
return IOS_UNAVAILABLE;
- if (errno == ENOSYS)
+ if (errno == ENOSYS || errno == EOPNOTSUPP)
return IOS_UNSUPPORTED_CASE;
if ((errno == EBADF || errno == EINVAL || errno == EXDEV) &&
((ssize_t)count >= 0))
@@ -103,6 +103,7 @@ Java_sun_nio_ch_FileDispatcherImpl_transferTo0(JNIEnv *env, jobject this,
case EINVAL:
case ENOSYS:
case EXDEV:
+ case EOPNOTSUPP:
// ignore and try sendfile()
break;
default:
diff --git a/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c b/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c
index c90e99dda07b..4677411b0bad 100644
--- a/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c
+++ b/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2024, 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
@@ -193,6 +193,7 @@ Java_sun_nio_fs_LinuxNativeDispatcher_directCopy0
case EINVAL:
case ENOSYS:
case EXDEV:
+ case EOPNOTSUPP:
// ignore and try sendfile()
break;
default:
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM.java b/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM.java
index 1280ccdad74d..b463f3599952 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM.java
@@ -498,7 +498,7 @@ protected Object checkPrivateKey(byte[] sk) throws InvalidKeyException {
/*
Main internal algorithms from Section 6 of specification
*/
- protected ML_KEM_KeyPair generateKemKeyPair(byte[] kem_d, byte[] kem_z) {
+ protected ML_KEM_KeyPair generateKemKeyPair(byte[] kem_d_z) {
MessageDigest mlKemH;
try {
mlKemH = MessageDigest.getInstance(HASH_H_NAME);
@@ -508,7 +508,8 @@ protected ML_KEM_KeyPair generateKemKeyPair(byte[] kem_d, byte[] kem_z) {
}
//Generate K-PKE keys
- var kPkeKeyPair = generateK_PkeKeyPair(kem_d);
+ //The 1st 32-byte `d` is used in K-PKE key pair generation
+ var kPkeKeyPair = generateK_PkeKeyPair(kem_d_z);
//encaps key = kPke encryption key
byte[] encapsKey = kPkeKeyPair.publicKey.keyBytes;
@@ -527,7 +528,8 @@ protected ML_KEM_KeyPair generateKemKeyPair(byte[] kem_d, byte[] kem_z) {
// This should never happen.
throw new RuntimeException(e);
}
- System.arraycopy(kem_z, 0, decapsKey,
+ // The 2nd 32-byte `z` is copied into decapsKey
+ System.arraycopy(kem_d_z, 32, decapsKey,
kPkePrivateKey.length + encapsKey.length + 32, 32);
return new ML_KEM_KeyPair(
@@ -535,6 +537,12 @@ protected ML_KEM_KeyPair generateKemKeyPair(byte[] kem_d, byte[] kem_z) {
new ML_KEM_DecapsulationKey(decapsKey));
}
+ public byte[] privKeyToPubKey(byte[] decapsKey) {
+ int pkLen = (mlKem_k * ML_KEM_N * 12) / 8 + 32 /* rho */;
+ int skLen = (mlKem_k * ML_KEM_N * 12) / 8;
+ return Arrays.copyOfRange(decapsKey, skLen, skLen + pkLen);
+ }
+
protected ML_KEM_EncapsulateResult encapsulate(
ML_KEM_EncapsulationKey encapsulationKey, byte[] randomMessage) {
MessageDigest mlKemH;
@@ -648,10 +656,12 @@ private K_PKE_KeyPair generateK_PkeKeyPair(byte[] seed) {
throw new RuntimeException(e);
}
- mlKemG.update(seed);
+ // Note: only the 1st 32-byte in the seed is used
+ mlKemG.update(seed, 0, 32);
mlKemG.update((byte)mlKem_k);
var rhoSigma = mlKemG.digest();
+ mlKemG.reset();
var rho = Arrays.copyOfRange(rhoSigma, 0, 32);
var sigma = Arrays.copyOfRange(rhoSigma, 32, 64);
Arrays.fill(rhoSigma, (byte)0);
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM_Impls.java b/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM_Impls.java
index 2ce5b3324e76..117f26e69810 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM_Impls.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM_Impls.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,9 +26,12 @@
package com.sun.crypto.provider;
import sun.security.jca.JCAUtil;
+import sun.security.pkcs.NamedPKCS8Key;
import sun.security.provider.NamedKEM;
import sun.security.provider.NamedKeyFactory;
import sun.security.provider.NamedKeyPairGenerator;
+import sun.security.util.KeyChoices;
+import sun.security.x509.NamedX509Key;
import java.security.*;
import java.util.Arrays;
@@ -37,6 +40,20 @@
public final class ML_KEM_Impls {
+ private static final int SEED_LEN = 64;
+
+ public static byte[] seedToExpanded(String pname, byte[] seed) {
+ return new ML_KEM(pname).generateKemKeyPair(seed)
+ .decapsulationKey()
+ .keyBytes();
+ }
+
+ public static NamedX509Key privKeyToPubKey(NamedPKCS8Key npk) {
+ return new NamedX509Key(npk.getAlgorithm(),
+ npk.getParams().getName(),
+ new ML_KEM(npk.getParams().getName()).privKeyToPubKey(npk.getExpanded()));
+ }
+
public sealed static class KPG
extends NamedKeyPairGenerator permits KPG2, KPG3, KPG5 {
@@ -50,25 +67,27 @@ protected KPG(String pname) {
}
@Override
- protected byte[][] implGenerateKeyPair(String name, SecureRandom random) {
- byte[] seed = new byte[32];
+ protected byte[][] implGenerateKeyPair(String pname, SecureRandom random) {
+ byte[] seed = new byte[SEED_LEN];
var r = random != null ? random : JCAUtil.getDefSecureRandom();
r.nextBytes(seed);
- byte[] z = new byte[32];
- r.nextBytes(z);
- ML_KEM mlKem = new ML_KEM(name);
+ ML_KEM mlKem = new ML_KEM(pname);
ML_KEM.ML_KEM_KeyPair kp;
+ kp = mlKem.generateKemKeyPair(seed);
+ var expanded = kp.decapsulationKey().keyBytes();
+
try {
- kp = mlKem.generateKemKeyPair(seed, z);
+ return new byte[][]{
+ kp.encapsulationKey().keyBytes(),
+ KeyChoices.writeToChoice(
+ KeyChoices.getPreferred("mlkem"),
+ seed, expanded),
+ expanded
+ };
} finally {
- Arrays.fill(seed, (byte)0);
- Arrays.fill(z, (byte)0);
+ Arrays.fill(seed, (byte) 0);
}
- return new byte[][] {
- kp.encapsulationKey().keyBytes(),
- kp.decapsulationKey().keyBytes()
- };
}
}
@@ -94,8 +113,39 @@ public sealed static class KF extends NamedKeyFactory permits KF2, KF3, KF5 {
public KF() {
super("ML-KEM", "ML-KEM-512", "ML-KEM-768", "ML-KEM-1024");
}
- public KF(String name) {
- super("ML-KEM", name);
+ public KF(String pname) {
+ super("ML-KEM", pname);
+ }
+
+ @Override
+ protected byte[] implExpand(String pname, byte[] input)
+ throws InvalidKeyException {
+ return KeyChoices.choiceToExpanded(pname, SEED_LEN, input,
+ ML_KEM_Impls::seedToExpanded);
+ }
+
+ @Override
+ protected Key engineTranslateKey(Key key) throws InvalidKeyException {
+ var nk = toNamedKey(key);
+ if (nk instanceof NamedPKCS8Key npk) {
+ var type = KeyChoices.getPreferred("mlkem");
+ if (KeyChoices.typeOfChoice(npk.getRawBytes()) != type) {
+ var encoding = KeyChoices.choiceToChoice(
+ type,
+ npk.getParams().getName(),
+ SEED_LEN, npk.getRawBytes(),
+ ML_KEM_Impls::seedToExpanded);
+ nk = NamedPKCS8Key.internalCreate(
+ npk.getAlgorithm(),
+ npk.getParams().getName(),
+ encoding,
+ npk.getExpanded().clone());
+ if (npk != key) { // npk is neither input or output
+ npk.destroy();
+ }
+ }
+ }
+ return nk;
}
}
@@ -121,15 +171,15 @@ public sealed static class K extends NamedKEM permits K2, K3, K5 {
private static final int SEED_SIZE = 32;
@Override
- protected byte[][] implEncapsulate(String name, byte[] encapsulationKey,
+ protected byte[][] implEncapsulate(String pname, byte[] encapsulationKey,
Object ek, SecureRandom secureRandom) {
byte[] randomBytes = new byte[SEED_SIZE];
var r = secureRandom != null ? secureRandom : JCAUtil.getDefSecureRandom();
r.nextBytes(randomBytes);
- ML_KEM mlKem = new ML_KEM(name);
- ML_KEM.ML_KEM_EncapsulateResult mlKemEncapsulateResult = null;
+ ML_KEM mlKem = new ML_KEM(pname);
+ ML_KEM.ML_KEM_EncapsulateResult mlKemEncapsulateResult;
try {
mlKemEncapsulateResult = mlKem.encapsulate(
new ML_KEM.ML_KEM_EncapsulationKey(
@@ -145,49 +195,49 @@ protected byte[][] implEncapsulate(String name, byte[] encapsulationKey,
}
@Override
- protected byte[] implDecapsulate(String name, byte[] decapsulationKey,
+ protected byte[] implDecapsulate(String pname, byte[] decapsulationKey,
Object dk, byte[] cipherText)
throws DecapsulateException {
- ML_KEM mlKem = new ML_KEM(name);
+ ML_KEM mlKem = new ML_KEM(pname);
var kpkeCipherText = new ML_KEM.K_PKE_CipherText(cipherText);
return mlKem.decapsulate(new ML_KEM.ML_KEM_DecapsulationKey(
decapsulationKey), kpkeCipherText);
}
@Override
- protected int implSecretSize(String name) {
+ protected int implSecretSize(String pname) {
return ML_KEM.SECRET_SIZE;
}
@Override
- protected int implEncapsulationSize(String name) {
- ML_KEM mlKem = new ML_KEM(name);
+ protected int implEncapsulationSize(String pname) {
+ ML_KEM mlKem = new ML_KEM(pname);
return mlKem.getEncapsulationSize();
}
@Override
- protected Object implCheckPublicKey(String name, byte[] pk)
+ protected Object implCheckPublicKey(String pname, byte[] pk)
throws InvalidKeyException {
- ML_KEM mlKem = new ML_KEM(name);
+ ML_KEM mlKem = new ML_KEM(pname);
return mlKem.checkPublicKey(pk);
}
@Override
- protected Object implCheckPrivateKey(String name, byte[] sk)
+ protected Object implCheckPrivateKey(String pname, byte[] sk)
throws InvalidKeyException {
- ML_KEM mlKem = new ML_KEM(name);
+ ML_KEM mlKem = new ML_KEM(pname);
return mlKem.checkPrivateKey(sk);
}
public K() {
- super("ML-KEM", "ML-KEM-512", "ML-KEM-768", "ML-KEM-1024");
+ super("ML-KEM", new KF());
}
- public K(String name) {
- super("ML-KEM", name);
+ public K(String pname) {
+ super("ML-KEM", new KF(pname));
}
}
diff --git a/src/java.base/share/classes/java/lang/VirtualThread.java b/src/java.base/share/classes/java/lang/VirtualThread.java
index b0b134e69a35..c4b01f9f76fe 100644
--- a/src/java.base/share/classes/java/lang/VirtualThread.java
+++ b/src/java.base/share/classes/java/lang/VirtualThread.java
@@ -603,8 +603,11 @@ private void afterYield() {
// Object.wait
if (s == WAITING || s == TIMED_WAITING) {
int newState;
+ boolean blocked;
if (s == WAITING) {
setState(newState = WAIT);
+ // may have been notified while in transition
+ blocked = notified && compareAndSetState(WAIT, BLOCKED);
} else {
// For timed-wait, a timeout task is scheduled to execute. The timeout
// task will change the thread state to UNBLOCKED and submit the thread
@@ -619,22 +622,22 @@ private void afterYield() {
byte seqNo = ++timedWaitSeqNo;
timeoutTask = schedule(() -> waitTimeoutExpired(seqNo), timeout, MILLISECONDS);
setState(newState = TIMED_WAIT);
+ // May have been notified while in transition. This must be done while
+ // holding the monitor to avoid changing the state of a new timed wait call.
+ blocked = notified && compareAndSetState(TIMED_WAIT, BLOCKED);
}
}
- // may have been notified while in transition to wait state
- if (notified && compareAndSetState(newState, BLOCKED)) {
- // may have even been unblocked already
+ if (blocked) {
+ // may have been unblocked already
if (blockPermit && compareAndSetState(BLOCKED, UNBLOCKED)) {
- submitRunContinuation();
+ lazySubmitRunContinuation();
+ }
+ } else {
+ // may have been interrupted while in transition to wait state
+ if (interrupted && compareAndSetState(newState, UNBLOCKED)) {
+ lazySubmitRunContinuation();
}
- return;
- }
-
- // may have been interrupted while in transition to wait state
- if (interrupted && compareAndSetState(newState, UNBLOCKED)) {
- submitRunContinuation();
- return;
}
return;
}
diff --git a/src/java.base/share/classes/java/security/KeyStore.java b/src/java.base/share/classes/java/security/KeyStore.java
index f477110a46c3..561758f09379 100644
--- a/src/java.base/share/classes/java/security/KeyStore.java
+++ b/src/java.base/share/classes/java/security/KeyStore.java
@@ -1799,6 +1799,7 @@ private static final KeyStore getInstance(File file, char[] password,
}
KeyStore keystore = null;
+ String matched = null;
try (DataInputStream dataStream =
new DataInputStream(
@@ -1822,8 +1823,10 @@ private static final KeyStore getInstance(File file, char[] password,
if (CryptoAlgorithmConstraints.permits(
"KEYSTORE", ksAlgo)) {
keystore = new KeyStore(impl, p, ksAlgo);
- break;
+ } else {
+ matched = ksAlgo;
}
+ break;
}
} catch (NoSuchAlgorithmException e) {
// ignore
@@ -1853,9 +1856,14 @@ private static final KeyStore getInstance(File file, char[] password,
return keystore;
}
}
-
- throw new KeyStoreException("Unrecognized keystore format. "
- + "Please load it with a specified type");
+ if (matched == null) {
+ throw new KeyStoreException("Unrecognized keystore format. "
+ + "Please load it with a specified type");
+ } else {
+ throw new KeyStoreException("Keystore format " +
+ matched +
+ " disabled by jdk.crypto.disabledAlgorithms property");
+ }
}
/**
diff --git a/src/java.base/share/classes/java/util/jar/JarVerifier.java b/src/java.base/share/classes/java/util/jar/JarVerifier.java
index fe58c4dffecc..e3bdb0307b9c 100644
--- a/src/java.base/share/classes/java/util/jar/JarVerifier.java
+++ b/src/java.base/share/classes/java/util/jar/JarVerifier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -68,7 +68,7 @@ class JarVerifier {
private ArrayList pendingBlocks;
/* cache of CodeSigner objects */
- private ArrayList signerCache;
+ private List signerCache;
/* Are we parsing a block? */
private boolean parsingBlockOrSF = false;
@@ -288,7 +288,7 @@ private void processEntry(ManifestEntryVerifier mev)
String key = uname.substring(0, uname.lastIndexOf('.'));
if (signerCache == null)
- signerCache = new ArrayList<>();
+ signerCache = new LinkedList<>();
if (manDig == null) {
synchronized(manifestRawBytes) {
diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/CallArranger.java
index 0fd90ef6f73a..c9994ec29306 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/CallArranger.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/CallArranger.java
@@ -245,7 +245,12 @@ VMStorage nextStorage(int type, boolean is32Bit) {
// Regular struct, no HFA.
VMStorage[] structAlloc(MemoryLayout layout) {
// Allocate enough gp slots (regs and stack) such that the struct fits in them.
- int numChunks = (int) Utils.alignUp(layout.byteSize(), MAX_COPY_SIZE) / MAX_COPY_SIZE;
+ final int numChunks;
+ try {
+ numChunks = Math.toIntExact(Utils.alignUp(layout.byteSize(), MAX_COPY_SIZE) / MAX_COPY_SIZE);
+ } catch (ArithmeticException ae) {
+ throw new IllegalArgumentException("Layout too large: " + layout, ae);
+ }
VMStorage[] result = new VMStorage[numChunks];
for (int i = 0; i < numChunks; i++) {
result[i] = nextStorage(StorageType.INTEGER, false);
diff --git a/src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java b/src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java
index a26003a3afbe..276c379a5646 100644
--- a/src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java
+++ b/src/java.base/share/classes/jdk/internal/vm/ThreadDumper.java
@@ -205,7 +205,10 @@ private static boolean dumpThread(Thread thread, TextWriter writer) {
// park blocker
Object parkBlocker = snapshot.parkBlocker();
if (parkBlocker != null) {
- writer.println(" - parking to wait for " + decorateObject(parkBlocker));
+ String suffix = (snapshot.parkBlockerOwner() instanceof Thread owner)
+ ? ", owner #" + owner.threadId()
+ : "";
+ writer.println(" - parking to wait for " + decorateObject(parkBlocker) + suffix);
}
// blocked on monitor enter or Object.wait
@@ -335,6 +338,9 @@ private static boolean dumpThread(Thread thread, JsonWriter jsonWriter) {
// parkBlocker is an object to allow for exclusiveOwnerThread in the future
jsonWriter.startObject("parkBlocker");
jsonWriter.writeProperty("object", Objects.toIdentityString(parkBlocker));
+ if (snapshot.parkBlockerOwner() instanceof Thread owner) {
+ jsonWriter.writeProperty("owner", owner.threadId());
+ }
jsonWriter.endObject();
}
diff --git a/src/java.base/share/classes/jdk/internal/vm/ThreadSnapshot.java b/src/java.base/share/classes/jdk/internal/vm/ThreadSnapshot.java
index 4fcbaf24d2e6..357d38008d15 100644
--- a/src/java.base/share/classes/jdk/internal/vm/ThreadSnapshot.java
+++ b/src/java.base/share/classes/jdk/internal/vm/ThreadSnapshot.java
@@ -44,6 +44,8 @@ class ThreadSnapshot {
// an object the thread is blocked/waiting on, converted to ThreadBlocker by ThreadSnapshot.of()
private int blockerTypeOrdinal;
private Object blockerObject;
+ // the owner of the blockerObject when the object is park blocker and is AbstractOwnableSynchronizer
+ private Thread parkBlockerOwner;
// set by ThreadSnapshot.of()
private ThreadBlocker blocker;
@@ -70,8 +72,11 @@ static ThreadSnapshot of(Thread thread) {
snapshot.locks = EMPTY_LOCKS;
}
if (snapshot.blockerObject != null) {
- snapshot.blocker = new ThreadBlocker(snapshot.blockerTypeOrdinal, snapshot.blockerObject);
+ snapshot.blocker = new ThreadBlocker(snapshot.blockerTypeOrdinal,
+ snapshot.blockerObject,
+ snapshot.parkBlockerOwner);
snapshot.blockerObject = null; // release
+ snapshot.parkBlockerOwner = null;
}
return snapshot;
}
@@ -104,6 +109,13 @@ Object parkBlocker() {
return getBlocker(BlockerLockType.PARK_BLOCKER);
}
+ /**
+ * Returns the owner of the parkBlocker if the parkBlocker is an AbstractOwnableSynchronizer.
+ */
+ Thread parkBlockerOwner() {
+ return (blocker != null && blocker.type == BlockerLockType.PARK_BLOCKER) ? blocker.owner : null;
+ }
+
/**
* Returns the object that the thread is blocked on.
* @throws IllegalStateException if not in the blocked state
@@ -211,11 +223,11 @@ Object lockObject() {
}
}
- private record ThreadBlocker(BlockerLockType type, Object obj) {
+ private record ThreadBlocker(BlockerLockType type, Object obj, Thread owner) {
private static final BlockerLockType[] lockTypeValues = BlockerLockType.values(); // cache
- ThreadBlocker(int typeOrdinal, Object obj) {
- this(lockTypeValues[typeOrdinal], obj);
+ ThreadBlocker(int typeOrdinal, Object obj, Thread owner) {
+ this(lockTypeValues[typeOrdinal], obj, owner);
}
}
diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
index 857c2f6ad6d1..2905003d5cba 100644
--- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
+++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -570,8 +570,8 @@ public void setRequestMethod(String method)
throws ProtocolException {
lock();
try {
- if (connecting) {
- throw new IllegalStateException("connect in progress");
+ if (connected || connecting) {
+ throw new IllegalStateException("Already connected");
}
super.setRequestMethod(method);
} finally {
@@ -1652,11 +1652,7 @@ private InputStream getInputStream0() throws IOException {
if (method.equals("HEAD") || cl == 0 ||
respCode == HTTP_NOT_MODIFIED ||
respCode == HTTP_NO_CONTENT) {
-
- http.finished();
- http = null;
- inputStream = new EmptyInputStream();
- connected = false;
+ noResponseBody();
}
if (respCode == 200 || respCode == 203 || respCode == 206 ||
@@ -1738,6 +1734,24 @@ private InputStream getInputStream0() throws IOException {
}
}
+ /**
+ * This method is called when a response with no response
+ * body is received, and arrange for the http client to
+ * be returned to the pool (or released) immediately when
+ * possible.
+ * @apiNote Used by {@link sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection}
+ * to preserve the TLS information after receiving an empty body.
+ * @implSpec
+ * Subclasses that override this method should call the super class
+ * implementation.
+ */
+ protected void noResponseBody() {
+ http.finished();
+ http = null;
+ inputStream = new EmptyInputStream();
+ connected = false;
+ }
+
/*
* Creates a chained exception that has the same type as
* original exception and with the same message. Right now,
diff --git a/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java
index 7bf8280a7ada..88449caaf096 100644
--- a/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java
+++ b/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -51,6 +51,7 @@
public abstract class AbstractDelegateHttpsURLConnection extends
HttpURLConnection {
+ private SSLSession savedSession = null;
protected AbstractDelegateHttpsURLConnection(URL url,
sun.net.www.protocol.http.Handler handler) throws IOException {
this(url, null, handler);
@@ -92,6 +93,7 @@ public void setNewClient (URL url)
public void setNewClient (URL url, boolean useCache)
throws IOException {
int readTimeout = getReadTimeout();
+ savedSession = null;
http = HttpsClient.New (getSSLSocketFactory(),
url,
getHostnameVerifier(),
@@ -176,7 +178,7 @@ public void setConnected(boolean conn) {
public void connect() throws IOException {
if (connected)
return;
- plainConnect();
+ super.connect();
if (cachedResponse != null) {
// using cached response
return;
@@ -184,6 +186,7 @@ public void connect() throws IOException {
if (!http.isCachedConnection() && http.needsTunneling()) {
doTunneling();
}
+ savedSession = null;
((HttpsClient)http).afterConnect();
}
@@ -204,6 +207,19 @@ protected HttpClient getNewHttpClient(URL url, Proxy p, int connectTimeout,
useCache, connectTimeout, this);
}
+ @Override
+ protected void noResponseBody() {
+ savedSession = ((HttpsClient)http).getSSLSession();
+ super.noResponseBody();
+ }
+
+ private SSLSession session() {
+ if (http instanceof HttpsClient https) {
+ return https.getSSLSession();
+ }
+ return savedSession;
+ }
+
/**
* Returns the cipher suite in use on this connection.
*/
@@ -211,11 +227,12 @@ public String getCipherSuite () {
if (cachedResponse != null) {
return ((SecureCacheResponse)cachedResponse).getCipherSuite();
}
- if (http == null) {
+
+ var session = session();
+ if (session == null) {
throw new IllegalStateException("connection not yet open");
- } else {
- return ((HttpsClient)http).getCipherSuite ();
}
+ return session.getCipherSuite();
}
/**
@@ -231,11 +248,12 @@ public java.security.cert.Certificate[] getLocalCertificates() {
return l.toArray(new java.security.cert.Certificate[0]);
}
}
- if (http == null) {
+
+ var session = session();
+ if (session == null) {
throw new IllegalStateException("connection not yet open");
- } else {
- return (((HttpsClient)http).getLocalCertificates ());
}
+ return session.getLocalCertificates();
}
/**
@@ -256,11 +274,11 @@ public java.security.cert.Certificate[] getServerCertificates()
}
}
- if (http == null) {
+ var session = session();
+ if (session == null) {
throw new IllegalStateException("connection not yet open");
- } else {
- return (((HttpsClient)http).getServerCertificates ());
}
+ return session.getPeerCertificates();
}
/**
@@ -274,11 +292,11 @@ Principal getPeerPrincipal()
return ((SecureCacheResponse)cachedResponse).getPeerPrincipal();
}
- if (http == null) {
+ var session = session();
+ if (session == null) {
throw new IllegalStateException("connection not yet open");
- } else {
- return (((HttpsClient)http).getPeerPrincipal());
}
+ return getPeerPrincipal(session);
}
/**
@@ -291,11 +309,11 @@ Principal getLocalPrincipal()
return ((SecureCacheResponse)cachedResponse).getLocalPrincipal();
}
- if (http == null) {
+ var session = session();
+ if (session == null) {
throw new IllegalStateException("connection not yet open");
- } else {
- return (((HttpsClient)http).getLocalPrincipal());
}
+ return getLocalPrincipal(session);
}
SSLSession getSSLSession() {
@@ -307,11 +325,12 @@ SSLSession getSSLSession() {
}
}
- if (http == null) {
+ var session = session();
+ if (session == null) {
throw new IllegalStateException("connection not yet open");
}
- return ((HttpsClient)http).getSSLSession();
+ return session;
}
/*
@@ -354,7 +373,7 @@ protected HttpCallerInfo getHttpCallerInfo(URL url, String proxy, int port,
}
HttpsClient https = (HttpsClient)http;
try {
- Certificate[] certs = https.getServerCertificates();
+ Certificate[] certs = https.getSSLSession().getPeerCertificates();
if (certs[0] instanceof X509Certificate x509Cert) {
return new HttpCallerInfo(url, proxy, port, x509Cert, authenticator);
}
@@ -372,7 +391,7 @@ protected HttpCallerInfo getHttpCallerInfo(URL url, Authenticator authenticator)
}
HttpsClient https = (HttpsClient)http;
try {
- Certificate[] certs = https.getServerCertificates();
+ Certificate[] certs = https.getSSLSession().getPeerCertificates();
if (certs[0] instanceof X509Certificate x509Cert) {
return new HttpCallerInfo(url, x509Cert, authenticator);
}
@@ -381,4 +400,58 @@ protected HttpCallerInfo getHttpCallerInfo(URL url, Authenticator authenticator)
}
return super.getHttpCallerInfo(url, authenticator);
}
+
+ @Override
+ public void disconnect() {
+ super.disconnect();
+ savedSession = null;
+ }
+
+ /**
+ * Returns the principal with which the server authenticated
+ * itself, or throw a SSLPeerUnverifiedException if the
+ * server did not authenticate.
+ * @param session The {@linkplain #getSSLSession() SSL session}
+ */
+ private static Principal getPeerPrincipal(SSLSession session)
+ throws SSLPeerUnverifiedException
+ {
+ Principal principal;
+ try {
+ principal = session.getPeerPrincipal();
+ } catch (AbstractMethodError e) {
+ // if the provider does not support it, fallback to peer certs.
+ // return the X500Principal of the end-entity cert.
+ java.security.cert.Certificate[] certs =
+ session.getPeerCertificates();
+ principal = ((X509Certificate)certs[0]).getSubjectX500Principal();
+ }
+ return principal;
+ }
+
+ /**
+ * Returns the principal the client sent to the
+ * server, or null if the client did not authenticate.
+ * @param session The {@linkplain #getSSLSession() SSL session}
+ */
+ private static Principal getLocalPrincipal(SSLSession session)
+ {
+ Principal principal;
+ try {
+ principal = session.getLocalPrincipal();
+ } catch (AbstractMethodError e) {
+ principal = null;
+ // if the provider does not support it, fallback to local certs.
+ // return the X500Principal of the end-entity cert.
+ java.security.cert.Certificate[] certs =
+ session.getLocalCertificates();
+ if (certs != null) {
+ principal = ((X509Certificate)certs[0]).getSubjectX500Principal();
+ }
+ }
+ return principal;
+ }
+
+
+
}
diff --git a/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java b/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java
index 2f011f5805b4..f5804cd83bd8 100644
--- a/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java
+++ b/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -44,6 +44,7 @@
import java.util.StringTokenizer;
import javax.net.ssl.*;
+import sun.net.util.IPAddressUtil;
import sun.net.www.http.HttpClient;
import sun.net.www.protocol.http.AuthCacheImpl;
import sun.net.www.protocol.http.HttpURLConnection;
@@ -471,7 +472,13 @@ public void afterConnect() throws IOException, UnknownHostException {
SSLParameters parameters = s.getSSLParameters();
parameters.setEndpointIdentificationAlgorithm("HTTPS");
// host has been set previously for SSLSocketImpl
- if (!(s instanceof SSLSocketImpl)) {
+ if (!(s instanceof SSLSocketImpl) &&
+ !IPAddressUtil.isIPv4LiteralAddress(host) &&
+ !(host.charAt(0) == '[' && host.charAt(host.length() - 1) == ']' &&
+ IPAddressUtil.isIPv6LiteralAddress(host.substring(1, host.length() - 1))
+ )) {
+ // Fully qualified DNS hostname of the server, as per section 3, RFC 6066
+ // Literal IPv4 and IPv6 addresses are not permitted in "HostName".
parameters.setServerNames(List.of(new SNIHostName(host)));
}
s.setSSLParameters(parameters);
@@ -592,75 +599,6 @@ public void closeIdleConnection() {
}
}
- /**
- * Returns the cipher suite in use on this connection.
- */
- String getCipherSuite() {
- return session.getCipherSuite();
- }
-
- /**
- * Returns the certificate chain the client sent to the
- * server, or null if the client did not authenticate.
- */
- public java.security.cert.Certificate [] getLocalCertificates() {
- return session.getLocalCertificates();
- }
-
- /**
- * Returns the certificate chain with which the server
- * authenticated itself, or throw a SSLPeerUnverifiedException
- * if the server did not authenticate.
- */
- java.security.cert.Certificate [] getServerCertificates()
- throws SSLPeerUnverifiedException
- {
- return session.getPeerCertificates();
- }
-
- /**
- * Returns the principal with which the server authenticated
- * itself, or throw a SSLPeerUnverifiedException if the
- * server did not authenticate.
- */
- Principal getPeerPrincipal()
- throws SSLPeerUnverifiedException
- {
- Principal principal;
- try {
- principal = session.getPeerPrincipal();
- } catch (AbstractMethodError e) {
- // if the provider does not support it, fallback to peer certs.
- // return the X500Principal of the end-entity cert.
- java.security.cert.Certificate[] certs =
- session.getPeerCertificates();
- principal = ((X509Certificate)certs[0]).getSubjectX500Principal();
- }
- return principal;
- }
-
- /**
- * Returns the principal the client sent to the
- * server, or null if the client did not authenticate.
- */
- Principal getLocalPrincipal()
- {
- Principal principal;
- try {
- principal = session.getLocalPrincipal();
- } catch (AbstractMethodError e) {
- principal = null;
- // if the provider does not support it, fallback to local certs.
- // return the X500Principal of the end-entity cert.
- java.security.cert.Certificate[] certs =
- session.getLocalCertificates();
- if (certs != null) {
- principal = ((X509Certificate)certs[0]).getSubjectX500Principal();
- }
- }
- return principal;
- }
-
/**
* Returns the {@code SSLSession} in use on this connection.
*/
diff --git a/src/java.base/share/classes/sun/security/pkcs/NamedPKCS8Key.java b/src/java.base/share/classes/sun/security/pkcs/NamedPKCS8Key.java
index a748433da875..e1beb8b6b9bc 100644
--- a/src/java.base/share/classes/sun/security/pkcs/NamedPKCS8Key.java
+++ b/src/java.base/share/classes/sun/security/pkcs/NamedPKCS8Key.java
@@ -25,11 +25,8 @@
package sun.security.pkcs;
-import sun.security.util.DerInputStream;
-import sun.security.util.DerValue;
import sun.security.x509.AlgorithmId;
-import javax.security.auth.DestroyFailedException;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
@@ -39,6 +36,7 @@
import java.security.ProviderException;
import java.security.spec.NamedParameterSpec;
import java.util.Arrays;
+import java.util.Objects;
/// Represents a private key from an algorithm family that is specialized
/// with a named parameter set.
@@ -50,6 +48,28 @@
/// identifier in the PKCS #8 encoding of the key is always a single OID derived
/// from the parameter set name.
///
+/// Besides the existing [PKCS8Key#privKeyMaterial] field, this class optionally
+/// supports an expanded format stored in [#expanded]. While `privKeyMaterial`
+/// always represents the format used for encoding, `expanded` is always used
+/// in computations. The expanded format must be self-sufficient for
+/// cryptographic computations without requiring the encoding format.
+///
+/// 1. If only `privKeyMaterial` is present, it's also the expanded format.
+/// 2. If both `privKeyMaterial` and `expanded` are available, `privKeyMaterial`
+/// is the encoding format, and `expanded` is the expanded format.
+///
+/// If the two formats are the same, only `privKeyMaterial` is included, and
+/// `expanded` must be `null`. Some implementations might be tempted to put the
+/// same value into `privKeyMaterial` and `expanded`. However, problems can
+/// arise if they happen to be the same object. To avoid ambiguity, always set
+/// `expanded` to `null`.
+///
+/// If the `expanded` field is required by the algorithm, it is either
+/// [calculated from the PKCS #8 encoding][#NamedPKCS8Key(String, byte\[\], Expander)],
+/// or [provided directly][#internalCreate(String, String, byte\[\], byte\[\])].
+/// In the latter case, the caller must ensure the consistency of the `encoded`
+/// and `expanded` arguments. For example, seed and expanded key must match.
+///
/// @see sun.security.provider.NamedKeyPairGenerator
public final class NamedPKCS8Key extends PKCS8Key {
@Serial
@@ -57,42 +77,64 @@ public final class NamedPKCS8Key extends PKCS8Key {
private final String fname;
private final transient NamedParameterSpec paramSpec;
- private final byte[] rawBytes;
+ private final transient byte[] expanded;
private transient boolean destroyed = false;
- /// Ctor from family name, parameter set name, raw key bytes.
- /// Key bytes won't be cloned, caller must relinquish ownership
- public NamedPKCS8Key(String fname, String pname, byte[] rawBytes) {
+ /// Creates a `NamedPKCS8Key` from raw components.
+ ///
+ /// @param fname family name
+ /// @param pname parameter set name
+ /// @param encoded raw key bytes, not null
+ /// @param expanded expanded key format, can be `null`.
+ private NamedPKCS8Key(String fname, String pname, byte[] encoded, byte[] expanded) {
this.fname = fname;
this.paramSpec = new NamedParameterSpec(pname);
+ this.expanded = expanded;
+ this.privKeyMaterial = Objects.requireNonNull(encoded);
try {
this.algid = AlgorithmId.get(pname);
} catch (NoSuchAlgorithmException e) {
throw new ProviderException(e);
}
- this.rawBytes = rawBytes;
+ }
- DerValue val = new DerValue(DerValue.tag_OctetString, rawBytes);
- try {
- this.privKeyMaterial = val.toByteArray();
- } finally {
- val.clear();
- }
+ /// Creates a `NamedPKCS8Key` from raw components.
+ ///
+ /// `encoded` and `expanded` won't be cloned, caller must relinquish
+ /// ownership. This caller must ensure `encoded` and `expanded` match
+ /// each other and `encoded` is valid and internally-consistent.
+ ///
+ /// @param fname family name
+ /// @param pname parameter set name
+ /// @param encoded raw key bytes, not null
+ /// @param expanded expanded key format, can be `null`.
+ public static NamedPKCS8Key internalCreate(String fname, String pname,
+ byte[] encoded, byte[] expanded) {
+ return new NamedPKCS8Key(fname, pname, encoded, expanded);
}
- /// Ctor from family name, and PKCS #8 bytes
- public NamedPKCS8Key(String fname, byte[] encoded) throws InvalidKeyException {
+ /// Creates a `NamedPKCS8Key` from family name and PKCS #8 encoding.
+ ///
+ /// @param fname family name
+ /// @param encoded PKCS #8 encoding. It is copied so caller can modify
+ /// it after the method call.
+ /// @param expander a function that is able to calculate the expanded
+ /// format from the encoding format inside `encoded`. If it recognizes
+ /// the input already in expanded format, it must return `null`.
+ /// This argument must be `null` if the algorithm's expanded format
+ /// is always the same as its encoding format. Whatever the case, the
+ /// ownership of the result is fully granted to this object.
+ public NamedPKCS8Key(String fname, byte[] encoded, Expander expander)
+ throws InvalidKeyException {
super(encoded);
this.fname = fname;
- try {
- paramSpec = new NamedParameterSpec(algid.getName());
- if (algid.getEncodedParams() != null) {
- throw new InvalidKeyException("algorithm identifier has params");
- }
- rawBytes = new DerInputStream(privKeyMaterial).getOctetString();
- } catch (IOException e) {
- throw new InvalidKeyException("Cannot parse input", e);
+ this.expanded = expander == null
+ ? null
+ : expander.expand(algid.getName(), this.privKeyMaterial);
+ paramSpec = new NamedParameterSpec(algid.getName());
+ if (algid.getEncodedParams() != null) {
+ throw new InvalidKeyException("algorithm identifier has params");
}
}
@@ -104,9 +146,15 @@ public String toString() {
}
/// Returns the reference to the internal key. Caller must not modify
- /// the content or keep a reference.
+ /// the content or pass the reference to untrusted application code.
public byte[] getRawBytes() {
- return rawBytes;
+ return privKeyMaterial;
+ }
+
+ /// Returns the reference to the key in expanded format. Caller must not
+ /// modify the content or pass the reference to untrusted application code.
+ public byte[] getExpanded() {
+ return expanded == null ? privKeyMaterial : expanded;
}
@Override
@@ -127,9 +175,11 @@ private void readObject(ObjectInputStream stream)
}
@Override
- public void destroy() throws DestroyFailedException {
- Arrays.fill(rawBytes, (byte)0);
+ public void destroy() {
Arrays.fill(privKeyMaterial, (byte)0);
+ if (expanded != null) {
+ Arrays.fill(expanded, (byte)0);
+ }
if (encodedKey != null) {
Arrays.fill(encodedKey, (byte)0);
}
@@ -140,4 +190,17 @@ public void destroy() throws DestroyFailedException {
public boolean isDestroyed() {
return destroyed;
}
+
+ /// Expands from encoding format to expanded format.
+ @FunctionalInterface
+ public interface Expander {
+ /// The expand method
+ ///
+ /// @param pname parameter set name
+ /// @param input input encoding
+ /// @return the expanded key, `null` if `input` is already in expanded
+ /// @throws InvalidKeyException if `input` is invalid, for example,
+ /// wrong encoding, or internal inconsistency
+ byte[] expand(String pname, byte[] input) throws InvalidKeyException;
+ }
}
diff --git a/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java b/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java
index b1b8fea83538..09adf25c3faf 100644
--- a/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java
+++ b/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -336,6 +336,21 @@ SignerInfo verify(PKCS7 block, byte[] data)
// if there are authenticated attributes, get the message
// digest and compare it with the digest of data
if (authenticatedAttributes == null) {
+ // RFC 5652 Section 5.3. "[signedAttrs] MUST be present if the
+ // content type of the EncapsulatedContentInfo value being
+ // signed is not id-data."
+ if (!content.getContentType().equals(ContentInfo.DATA_OID)) {
+ throw new SignatureException("Missing authenticatedAttributes");
+ } else {
+ try {
+ var c = new DerValue(data);
+ if (c.tag == DerValue.tag_Set) {
+ throw new SignatureException("Not a .SF file content");
+ }
+ } catch (IOException e) {
+ // Expected or ignored
+ }
+ }
dataSigned = data;
} else {
@@ -668,6 +683,12 @@ public Timestamp getTimestamp()
return null;
}
+ // RFC 3161 Section 2.4.2. id-ct-TSTInfo.
+ if (!tsToken.getContentInfo().getContentType()
+ .equals(ContentInfo.TIMESTAMP_TOKEN_INFO_OID)) {
+ throw new SignatureException("Not using id-ct-TSTInfo");
+ }
+
// Extract the content (an encoded timestamp token info)
byte[] encTsTokenInfo = tsToken.getContentInfo().getData();
// Extract the signer (the Timestamping Authority)
diff --git a/src/java.base/share/classes/sun/security/provider/ML_DSA.java b/src/java.base/share/classes/sun/security/provider/ML_DSA.java
index af64ef399a8d..a55f7d258b16 100644
--- a/src/java.base/share/classes/sun/security/provider/ML_DSA.java
+++ b/src/java.base/share/classes/sun/security/provider/ML_DSA.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025, 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
@@ -568,6 +568,54 @@ public ML_DSA_KeyPair generateKeyPairInternal(byte[] randomBytes) {
return new ML_DSA_KeyPair(sk, pk);
}
+ private static int[][] deepClone(int[][] array) {
+ int[][] clone = new int[array.length][];
+ for (int i = 0; i < array.length; i++) {
+ clone[i] = array[i].clone();
+ }
+ return clone;
+ }
+
+ // This is similar to the generateKeyPairInternal method. Instead of
+ // generating from a seed, it uses stored fields inside the private key
+ // to calculate the public key. It performs several checks during the
+ // calculation to make sure the private key is a valid one. Otherwise,
+ // an IllegalArgumentException is thrown.
+ public ML_DSA_PublicKey privKeyToPubKey(ML_DSA_PrivateKey sk) {
+ // Sample A
+ int[][][] keygenA = generateA(sk.rho); //A is in NTT domain
+
+ // Compute t and tr
+ // make a copy of sk.s1 and modify it. Although we can also
+ // take it out of NTT domain later, it was modified for a while.
+ var s1 = deepClone(sk.s1);
+ mlDsaVectorNtt(s1); //s1 now in NTT domain
+ int[][] As1 = integerMatrixAlloc(mlDsa_k, ML_DSA_N);
+ matrixVectorPointwiseMultiply(As1, keygenA, s1);
+
+ mlDsaVectorInverseNtt(As1);
+ int[][] t = vectorAddPos(As1, sk.s2);
+ int[][] t0 = integerMatrixAlloc(mlDsa_k, ML_DSA_N);
+ int[][] t1 = integerMatrixAlloc(mlDsa_k, ML_DSA_N);
+ power2Round(t, t0, t1);
+ if (!Arrays.deepEquals(t0, sk.t0)) {
+ throw new IllegalArgumentException("t0 does not patch");
+ }
+
+ var crHash = new SHAKE256(TR_LEN);
+
+ ML_DSA_PublicKey pk = new ML_DSA_PublicKey(sk.rho, t1);
+ byte[] publicKeyBytes = pkEncode(pk);
+ crHash.update(publicKeyBytes);
+ byte[] tr = crHash.digest();
+ if (!Arrays.equals(tr, sk.tr)) {
+ throw new IllegalArgumentException("tr does not patch");
+ }
+
+ //Encode PK
+ return new ML_DSA_PublicKey(sk.rho, t1);
+ }
+
public ML_DSA_Signature signInternal(byte[] message, byte[] rnd, byte[] skBytes) {
//Decode private key and initialize hash function
ML_DSA_PrivateKey sk = skDecode(skBytes);
diff --git a/src/java.base/share/classes/sun/security/provider/ML_DSA_Impls.java b/src/java.base/share/classes/sun/security/provider/ML_DSA_Impls.java
index dffe7c5cdb18..730e253f407f 100644
--- a/src/java.base/share/classes/sun/security/provider/ML_DSA_Impls.java
+++ b/src/java.base/share/classes/sun/security/provider/ML_DSA_Impls.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,12 +26,35 @@
package sun.security.provider;
import sun.security.jca.JCAUtil;
+import sun.security.pkcs.NamedPKCS8Key;
+import sun.security.util.KeyChoices;
+import sun.security.x509.NamedX509Key;
+
import java.security.*;
import java.security.SecureRandom;
import java.util.Arrays;
public class ML_DSA_Impls {
+ private static final int SEED_LEN = 32;
+
+ public static byte[] seedToExpanded(String pname, byte[] seed) {
+ var impl = new ML_DSA(name2int(pname));
+ var sk = impl.generateKeyPairInternal(seed).privateKey();
+ try {
+ return impl.skEncode(sk);
+ } finally {
+ sk.destroy();
+ }
+ }
+
+ public static NamedX509Key privKeyToPubKey(NamedPKCS8Key npk) {
+ var dsa = new ML_DSA(name2int(npk.getParams().getName()));
+ return new NamedX509Key(npk.getAlgorithm(),
+ npk.getParams().getName(),
+ dsa.pkEncode(dsa.privKeyToPubKey(dsa.skDecode(npk.getExpanded()))));
+ }
+
public enum Version {
DRAFT, FINAL
}
@@ -43,16 +66,16 @@ public enum Version {
// --add-exports java.base/sun.security.provider=ALL-UNNAMED
public static Version version = Version.FINAL;
- static int name2int(String name) {
- if (name.endsWith("44")) {
+ static int name2int(String pname) {
+ if (pname.endsWith("44")) {
return 2;
- } else if (name.endsWith("65")) {
+ } else if (pname.endsWith("65")) {
return 3;
- } else if (name.endsWith("87")) {
+ } else if (pname.endsWith("87")) {
return 5;
} else {
// should not happen
- throw new ProviderException("Unknown name " + name);
+ throw new ProviderException("Unknown name " + pname);
}
}
@@ -69,20 +92,26 @@ public KPG(String pname) {
}
@Override
- protected byte[][] implGenerateKeyPair(String name, SecureRandom sr) {
- byte[] seed = new byte[32];
- var r = sr != null ? sr : JCAUtil.getDefSecureRandom();
+ protected byte[][] implGenerateKeyPair(String pname, SecureRandom random) {
+ byte[] seed = new byte[SEED_LEN];
+ var r = random != null ? random : JCAUtil.getDefSecureRandom();
r.nextBytes(seed);
- ML_DSA mlDsa = new ML_DSA(name2int(name));
+
+ ML_DSA mlDsa = new ML_DSA(name2int(pname));
ML_DSA.ML_DSA_KeyPair kp = mlDsa.generateKeyPairInternal(seed);
+ var expanded = mlDsa.skEncode(kp.privateKey());
+
try {
return new byte[][]{
mlDsa.pkEncode(kp.publicKey()),
- mlDsa.skEncode(kp.privateKey())
+ KeyChoices.writeToChoice(
+ KeyChoices.getPreferred("mldsa"),
+ seed, expanded),
+ expanded
};
} finally {
kp.privateKey().destroy();
- Arrays.fill(seed, (byte)0);
+ Arrays.fill(seed, (byte) 0);
}
}
}
@@ -109,8 +138,39 @@ public sealed static class KF extends NamedKeyFactory permits KF2, KF3, KF5 {
public KF() {
super("ML-DSA", "ML-DSA-44", "ML-DSA-65", "ML-DSA-87");
}
- public KF(String name) {
- super("ML-DSA", name);
+ public KF(String pname) {
+ super("ML-DSA", pname);
+ }
+
+ @Override
+ protected byte[] implExpand(String pname, byte[] input)
+ throws InvalidKeyException {
+ return KeyChoices.choiceToExpanded(pname, SEED_LEN, input,
+ ML_DSA_Impls::seedToExpanded);
+ }
+
+ @Override
+ protected Key engineTranslateKey(Key key) throws InvalidKeyException {
+ var nk = toNamedKey(key);
+ if (nk instanceof NamedPKCS8Key npk) {
+ var type = KeyChoices.getPreferred("mldsa");
+ if (KeyChoices.typeOfChoice(npk.getRawBytes()) != type) {
+ var encoding = KeyChoices.choiceToChoice(
+ type,
+ npk.getParams().getName(),
+ SEED_LEN, npk.getRawBytes(),
+ ML_DSA_Impls::seedToExpanded);
+ nk = NamedPKCS8Key.internalCreate(
+ npk.getAlgorithm(),
+ npk.getParams().getName(),
+ encoding,
+ npk.getExpanded().clone());
+ if (npk != key) { // npk is neither input or output
+ npk.destroy();
+ }
+ }
+ }
+ return nk;
}
}
@@ -134,16 +194,16 @@ public KF5() {
public sealed static class SIG extends NamedSignature permits SIG2, SIG3, SIG5 {
public SIG() {
- super("ML-DSA", "ML-DSA-44", "ML-DSA-65", "ML-DSA-87");
+ super("ML-DSA", new KF());
}
- public SIG(String name) {
- super("ML-DSA", name);
+ public SIG(String pname) {
+ super("ML-DSA", new KF(pname));
}
@Override
- protected byte[] implSign(String name, byte[] skBytes,
+ protected byte[] implSign(String pname, byte[] skBytes,
Object sk2, byte[] msg, SecureRandom sr) {
- var size = name2int(name);
+ var size = name2int(pname);
var r = sr != null ? sr : JCAUtil.getDefSecureRandom();
byte[] rnd = new byte[32];
r.nextBytes(rnd);
@@ -160,10 +220,10 @@ protected byte[] implSign(String name, byte[] skBytes,
}
@Override
- protected boolean implVerify(String name, byte[] pkBytes,
+ protected boolean implVerify(String pname, byte[] pkBytes,
Object pk2, byte[] msg, byte[] sigBytes)
throws SignatureException {
- var size = name2int(name);
+ var size = name2int(pname);
var mlDsa = new ML_DSA(size);
if (version == Version.FINAL) {
// FIPS 204 Algorithm 3 ML-DSA.Verify prepend {0, len(ctx)}
@@ -176,18 +236,18 @@ protected boolean implVerify(String name, byte[] pkBytes,
}
@Override
- protected Object implCheckPublicKey(String name, byte[] pk)
+ protected Object implCheckPublicKey(String pname, byte[] pk)
throws InvalidKeyException {
- ML_DSA mlDsa = new ML_DSA(name2int(name));
+ ML_DSA mlDsa = new ML_DSA(name2int(pname));
return mlDsa.checkPublicKey(pk);
}
@Override
- protected Object implCheckPrivateKey(String name, byte[] sk)
+ protected Object implCheckPrivateKey(String pname, byte[] sk)
throws InvalidKeyException {
- ML_DSA mlDsa = new ML_DSA(name2int(name));
+ ML_DSA mlDsa = new ML_DSA(name2int(pname));
return mlDsa.checkPrivateKey(sk);
}
}
diff --git a/src/java.base/share/classes/sun/security/provider/NamedKEM.java b/src/java.base/share/classes/sun/security/provider/NamedKEM.java
index 2731b3460af3..60449396d4d8 100644
--- a/src/java.base/share/classes/sun/security/provider/NamedKEM.java
+++ b/src/java.base/share/classes/sun/security/provider/NamedKEM.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,6 @@
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.NamedParameterSpec;
import java.util.Arrays;
-import java.util.Objects;
/// A base class for all `KEM` implementations that can be
/// configured with a named parameter set. See [NamedKeyPairGenerator]
@@ -50,21 +49,19 @@
public abstract class NamedKEM implements KEMSpi {
private final String fname; // family name
- private final String[] pnames; // allowed parameter set name (at least one)
+ private final NamedKeyFactory fac;
/// Creates a new `NamedKEM` object.
///
/// @param fname the family name
- /// @param pnames the standard parameter set names, at least one is needed.
- protected NamedKEM(String fname, String... pnames) {
+ /// @param fac the `KeyFactory` used to translate foreign keys and
+ /// perform key validation
+ protected NamedKEM(String fname, NamedKeyFactory fac) {
if (fname == null) {
throw new AssertionError("fname cannot be null");
}
- if (pnames == null || pnames.length == 0) {
- throw new AssertionError("pnames cannot be null or empty");
- }
this.fname = fname;
- this.pnames = pnames;
+ this.fac = fac;
}
@Override
@@ -76,8 +73,7 @@ public EncapsulatorSpi engineNewEncapsulator(PublicKey publicKey,
"The " + fname + " algorithm does not take any parameters");
}
// translate also check the key
- var nk = (NamedX509Key) new NamedKeyFactory(fname, pnames)
- .engineTranslateKey(publicKey);
+ var nk = (NamedX509Key) fac.toNamedKey(publicKey);
var pk = nk.getRawBytes();
return getKeyConsumerImpl(this, nk.getParams(), pk,
implCheckPublicKey(nk.getParams().getName(), pk), secureRandom);
@@ -92,16 +88,15 @@ public DecapsulatorSpi engineNewDecapsulator(
"The " + fname + " algorithm does not take any parameters");
}
// translate also check the key
- var nk = (NamedPKCS8Key) new NamedKeyFactory(fname, pnames)
- .engineTranslateKey(privateKey);
- var sk = nk.getRawBytes();
+ var nk = (NamedPKCS8Key) fac.toNamedKey(privateKey);
+ var sk = nk.getExpanded();
return getKeyConsumerImpl(this, nk.getParams(), sk,
implCheckPrivateKey(nk.getParams().getName(), sk), null);
}
// We don't have a flag on whether key is public key or private key.
// The correct method should always be called.
- private record KeyConsumerImpl(NamedKEM kem, String name, int sslen,
+ private record KeyConsumerImpl(NamedKEM kem, String pname, int sslen,
int clen, byte[] key, Object k2, SecureRandom sr)
implements KEMSpi.EncapsulatorSpi, KEMSpi.DecapsulatorSpi {
@Override
@@ -110,7 +105,7 @@ public SecretKey engineDecapsulate(byte[] encapsulation, int from, int to,
if (encapsulation.length != clen) {
throw new DecapsulateException("Invalid key encapsulation message length");
}
- var ss = kem.implDecapsulate(name, key, k2, encapsulation);
+ var ss = kem.implDecapsulate(pname, key, k2, encapsulation);
try {
return new SecretKeySpec(ss,
from, to - from, algorithm);
@@ -121,7 +116,7 @@ public SecretKey engineDecapsulate(byte[] encapsulation, int from, int to,
@Override
public KEM.Encapsulated engineEncapsulate(int from, int to, String algorithm) {
- var enc = kem.implEncapsulate(name, key, k2, sr);
+ var enc = kem.implEncapsulate(pname, key, k2, sr);
try {
return new KEM.Encapsulated(
new SecretKeySpec(enc[1],
@@ -146,46 +141,46 @@ public int engineEncapsulationSize() {
private static KeyConsumerImpl getKeyConsumerImpl(NamedKEM kem,
NamedParameterSpec nps, byte[] key, Object k2, SecureRandom sr) {
- String name = nps.getName();
- return new KeyConsumerImpl(kem, name, kem.implSecretSize(name), kem.implEncapsulationSize(name),
+ String pname = nps.getName();
+ return new KeyConsumerImpl(kem, pname, kem.implSecretSize(pname), kem.implEncapsulationSize(pname),
key, k2, sr);
}
/// User-defined encap function.
///
- /// @param name parameter name
+ /// @param pname parameter name
/// @param pk public key in raw bytes
/// @param pk2 parsed public key, `null` if none. See [#implCheckPublicKey].
/// @param sr SecureRandom object, `null` if not initialized
/// @return the key encapsulation message and the shared key (in this order)
/// @throws ProviderException if there is an internal error
- protected abstract byte[][] implEncapsulate(String name, byte[] pk, Object pk2, SecureRandom sr);
+ protected abstract byte[][] implEncapsulate(String pname, byte[] pk, Object pk2, SecureRandom sr);
/// User-defined decap function.
///
- /// @param name parameter name
+ /// @param pname parameter name
/// @param sk private key in raw bytes
/// @param sk2 parsed private key, `null` if none. See [#implCheckPrivateKey].
/// @param encap the key encapsulation message
/// @return the shared key
/// @throws ProviderException if there is an internal error
/// @throws DecapsulateException if there is another error
- protected abstract byte[] implDecapsulate(String name, byte[] sk, Object sk2, byte[] encap)
+ protected abstract byte[] implDecapsulate(String pname, byte[] sk, Object sk2, byte[] encap)
throws DecapsulateException;
/// User-defined function returning shared secret key length.
///
- /// @param name parameter name
+ /// @param pname parameter name
/// @return shared secret key length
/// @throws ProviderException if there is an internal error
- protected abstract int implSecretSize(String name);
+ protected abstract int implSecretSize(String pname);
/// User-defined function returning key encapsulation message length.
///
- /// @param name parameter name
+ /// @param pname parameter name
/// @return key encapsulation message length
/// @throws ProviderException if there is an internal error
- protected abstract int implEncapsulationSize(String name);
+ protected abstract int implEncapsulationSize(String pname);
/// User-defined function to validate a public key.
///
@@ -196,11 +191,11 @@ protected abstract byte[] implDecapsulate(String name, byte[] sk, Object sk2, by
///
/// The default implementation returns `null`.
///
- /// @param name parameter name
+ /// @param pname parameter name
/// @param pk public key in raw bytes
/// @return a parsed key, `null` if none.
/// @throws InvalidKeyException if the key is invalid
- protected Object implCheckPublicKey(String name, byte[] pk) throws InvalidKeyException {
+ protected Object implCheckPublicKey(String pname, byte[] pk) throws InvalidKeyException {
return null;
}
@@ -213,11 +208,11 @@ protected Object implCheckPublicKey(String name, byte[] pk) throws InvalidKeyExc
///
/// The default implementation returns `null`.
///
- /// @param name parameter name
+ /// @param pname parameter name
/// @param sk private key in raw bytes
/// @return a parsed key, `null` if none.
/// @throws InvalidKeyException if the key is invalid
- protected Object implCheckPrivateKey(String name, byte[] sk) throws InvalidKeyException {
+ protected Object implCheckPrivateKey(String pname, byte[] sk) throws InvalidKeyException {
return null;
}
}
diff --git a/src/java.base/share/classes/sun/security/provider/NamedKeyFactory.java b/src/java.base/share/classes/sun/security/provider/NamedKeyFactory.java
index 727358dd0749..9099f1446ff9 100644
--- a/src/java.base/share/classes/sun/security/provider/NamedKeyFactory.java
+++ b/src/java.base/share/classes/sun/security/provider/NamedKeyFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,6 @@
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
-import java.util.Objects;
/// A base class for all `KeyFactory` implementations that can be
/// configured with a named parameter set. See [NamedKeyPairGenerator]
@@ -58,7 +57,7 @@
///
/// When reading from a RAW format, it needs enough info to derive the
/// parameter set name.
-public class NamedKeyFactory extends KeyFactorySpi {
+public abstract class NamedKeyFactory extends KeyFactorySpi {
private final String fname; // family name
private final String[] pnames; // allowed parameter set name (at least one)
@@ -78,92 +77,110 @@ protected NamedKeyFactory(String fname, String... pnames) {
this.pnames = pnames;
}
- private String checkName(String name) throws InvalidKeyException {
- for (var pname : pnames) {
- if (pname.equalsIgnoreCase(name)) {
+ private String checkName(String pname) throws InvalidKeyException {
+ for (var n : pnames) {
+ if (n.equalsIgnoreCase(pname)) {
// return the stored standard name
- return pname;
+ return n;
}
}
- throw new InvalidKeyException("Unsupported parameter set name: " + name);
+ throw new InvalidKeyException("Unsupported parameter set name: " + pname);
}
@Override
protected PublicKey engineGeneratePublic(KeySpec keySpec)
throws InvalidKeySpecException {
- if (keySpec instanceof X509EncodedKeySpec xspec) {
- try {
- return fromX509(xspec.getEncoded());
- } catch (InvalidKeyException e) {
- throw new InvalidKeySpecException(e);
+ return switch (keySpec) {
+ case X509EncodedKeySpec xspec -> {
+ try {
+ yield fromX509(xspec.getEncoded());
+ } catch (InvalidKeyException e) {
+ throw new InvalidKeySpecException(e);
+ }
}
- } else if (keySpec instanceof RawKeySpec rks) {
- if (pnames.length == 1) {
- return new NamedX509Key(fname, pnames[0], rks.getKeyArr());
- } else {
- throw new InvalidKeySpecException("Parameter set name unavailable");
+ case RawKeySpec rks -> {
+ if (pnames.length == 1) {
+ yield new NamedX509Key(fname, pnames[0], rks.getKeyArr());
+ } else {
+ throw new InvalidKeySpecException("Parameter set name unavailable");
+ }
}
- } else if (keySpec instanceof EncodedKeySpec espec
- && espec.getFormat().equalsIgnoreCase("RAW")) {
- if (pnames.length == 1) {
- return new NamedX509Key(fname, pnames[0], espec.getEncoded());
- } else {
- throw new InvalidKeySpecException("Parameter set name unavailable");
+ case EncodedKeySpec espec when espec.getFormat().equalsIgnoreCase("RAW") -> {
+ if (pnames.length == 1) {
+ yield new NamedX509Key(fname, pnames[0], espec.getEncoded());
+ } else {
+ throw new InvalidKeySpecException("Parameter set name unavailable");
+ }
}
- } else {
- throw new InvalidKeySpecException("Unsupported keyspec: " + keySpec);
- }
+ case null -> throw new InvalidKeySpecException(
+ "keySpec must not be null");
+ default ->
+ throw new InvalidKeySpecException(keySpec.getClass().getName() +
+ " not supported.");
+ };
}
@Override
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
throws InvalidKeySpecException {
- if (keySpec instanceof PKCS8EncodedKeySpec pspec) {
- var bytes = pspec.getEncoded();
- try {
- return fromPKCS8(bytes);
- } catch (InvalidKeyException e) {
- throw new InvalidKeySpecException(e);
- } finally {
- Arrays.fill(bytes, (byte) 0);
- }
- } else if (keySpec instanceof RawKeySpec rks) {
- if (pnames.length == 1) {
- var bytes = rks.getKeyArr();
+ return switch (keySpec) {
+ case PKCS8EncodedKeySpec pspec -> {
+ var bytes = pspec.getEncoded();
try {
- return new NamedPKCS8Key(fname, pnames[0], bytes);
+ yield fromPKCS8(bytes);
+ } catch (InvalidKeyException e) {
+ throw new InvalidKeySpecException(e);
} finally {
Arrays.fill(bytes, (byte) 0);
}
- } else {
- throw new InvalidKeySpecException("Parameter set name unavailable");
}
- } else if (keySpec instanceof EncodedKeySpec espec
- && espec.getFormat().equalsIgnoreCase("RAW")) {
- if (pnames.length == 1) {
- var bytes = espec.getEncoded();
- try {
- return new NamedPKCS8Key(fname, pnames[0], bytes);
- } finally {
- Arrays.fill(bytes, (byte) 0);
+ case RawKeySpec rks -> {
+ if (pnames.length == 1) {
+ var raw = rks.getKeyArr();
+ try {
+ yield fromRaw(pnames[0], raw);
+ } catch (InvalidKeyException e) {
+ throw new InvalidKeySpecException("Invalid key input", e);
+ }
+ } else {
+ throw new InvalidKeySpecException("Parameter set name unavailable");
}
- } else {
- throw new InvalidKeySpecException("Parameter set name unavailable");
}
- } else {
- throw new InvalidKeySpecException("Unsupported keyspec: " + keySpec);
- }
+ case EncodedKeySpec espec when espec.getFormat().equalsIgnoreCase("RAW") -> {
+ if (pnames.length == 1) {
+ var raw = espec.getEncoded();
+ try {
+ yield fromRaw(pnames[0], raw);
+ } catch (InvalidKeyException e) {
+ throw new InvalidKeySpecException("Invalid key input", e);
+ }
+ } else {
+ throw new InvalidKeySpecException("Parameter set name unavailable");
+ }
+ }
+ case null -> throw new InvalidKeySpecException(
+ "keySpec must not be null");
+ default ->
+ throw new InvalidKeySpecException(keySpec.getClass().getName() +
+ " not supported.");
+ };
+ }
+
+ private PrivateKey fromRaw(String pname, byte[] raw)
+ throws InvalidKeyException {
+ return NamedPKCS8Key.internalCreate(
+ fname, pname, raw, implExpand(pname, raw));
}
private PrivateKey fromPKCS8(byte[] bytes)
- throws InvalidKeyException, InvalidKeySpecException {
- var k = new NamedPKCS8Key(fname, bytes);
+ throws InvalidKeyException {
+ var k = new NamedPKCS8Key(fname, bytes, this::implExpand);
checkName(k.getParams().getName());
return k;
}
private PublicKey fromX509(byte[] bytes)
- throws InvalidKeyException, InvalidKeySpecException {
+ throws InvalidKeyException {
var k = new NamedX509Key(fname, bytes);
checkName(k.getParams().getName());
return k;
@@ -184,7 +201,7 @@ public String getFormat() {
protected T engineGetKeySpec(Key key, Class keySpec)
throws InvalidKeySpecException {
try {
- key = engineTranslateKey(key);
+ key = toNamedKey(key);
} catch (InvalidKeyException e) {
throw new InvalidKeySpecException(e);
}
@@ -225,6 +242,12 @@ protected T engineGetKeySpec(Key key, Class keySpec)
@Override
protected Key engineTranslateKey(Key key) throws InvalidKeyException {
+ // The base toNamedKey only makes sure key is translated into a NamedKey.
+ // the key material is still the same as the input.
+ return toNamedKey(key);
+ }
+
+ protected Key toNamedKey(Key key) throws InvalidKeyException {
if (key == null) {
throw new InvalidKeyException("Key must not be null");
}
@@ -242,27 +265,28 @@ protected Key engineTranslateKey(Key key) throws InvalidKeyException {
} else if (format.equalsIgnoreCase("RAW")) {
var kAlg = key.getAlgorithm();
if (key instanceof AsymmetricKey pk) {
- String name;
+ String pname;
// Three cases that we can find the parameter set name from a RAW key:
// 1. getParams() returns one
// 2. getAlgorithm() returns param set name (some provider does this)
// 3. getAlgorithm() returns family name but this KF is for param set name
if (pk.getParams() instanceof NamedParameterSpec nps) {
- name = checkName(nps.getName());
+ pname = checkName(nps.getName());
} else {
if (kAlg.equalsIgnoreCase(fname)) {
if (pnames.length == 1) {
- name = pnames[0];
+ pname = pnames[0];
} else {
throw new InvalidKeyException("No parameter set info");
}
} else {
- name = checkName(kAlg);
+ pname = checkName(kAlg);
}
}
+ var raw = key.getEncoded();
return key instanceof PrivateKey
- ? new NamedPKCS8Key(fname, name, key.getEncoded())
- : new NamedX509Key(fname, name, key.getEncoded());
+ ? fromRaw(pname, raw)
+ : new NamedX509Key(fname, pname, raw);
} else {
throw new InvalidKeyException("Unsupported key type: " + key.getClass());
}
@@ -270,19 +294,26 @@ protected Key engineTranslateKey(Key key) throws InvalidKeyException {
var bytes = key.getEncoded();
try {
return fromPKCS8(bytes);
- } catch (InvalidKeySpecException e) {
- throw new InvalidKeyException("Invalid PKCS#8 key", e);
} finally {
Arrays.fill(bytes, (byte) 0);
}
} else if (format.equalsIgnoreCase("X.509") && key instanceof PublicKey) {
- try {
- return fromX509(key.getEncoded());
- } catch (InvalidKeySpecException e) {
- throw new InvalidKeyException("Invalid X.509 key", e);
- }
+ return fromX509(key.getEncoded());
} else {
throw new InvalidKeyException("Unsupported key format: " + key.getFormat());
}
}
+
+ /// User-defined function to generate the expanded format of
+ /// a [NamedPKCS8Key] from its encoding format.
+ ///
+ /// This method is called when the key factory is constructing a private
+ /// key. The ownership of the result is fully granted to the caller.
+ ///
+ /// @param pname the parameter set name
+ /// @param input the encoding, could be any format
+ /// @return the expanded key, not null
+ /// @throws InvalidKeyException if `input` is invalid
+ protected abstract byte[] implExpand(String pname, byte[] input)
+ throws InvalidKeyException;
}
diff --git a/src/java.base/share/classes/sun/security/provider/NamedKeyPairGenerator.java b/src/java.base/share/classes/sun/security/provider/NamedKeyPairGenerator.java
index 5be2b2b2a08b..6b55924b0fe2 100644
--- a/src/java.base/share/classes/sun/security/provider/NamedKeyPairGenerator.java
+++ b/src/java.base/share/classes/sun/security/provider/NamedKeyPairGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,6 @@
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.NamedParameterSpec;
-import java.util.Objects;
/// A base class for all `KeyPairGenerator` implementations that can be
/// configured with a named parameter set.
@@ -52,15 +51,21 @@
/// with `getAlgorithm` returning the family name, and `getParams` returning
/// the parameter set name as a [NamedParameterSpec] object.
///
-/// An implementation must include a zero-argument public constructor that
-/// calls `super(fname, pnames)`, where `fname` is the family name of the
-/// algorithm and `pnames` are its supported parameter set names. `pnames`
-/// must contain at least one element. For an implementation of
-/// `NamedKeyPairGenerator`, the first element becomes its default parameter
-/// set, i.e. the parameter set to be used in key pair generation unless
+/// A `NamedKeyPairGenerator` or `NamedKeyFactory` implementation must include
+/// a zero-argument public constructor that calls `super(fname, pnames)`, where
+/// `fname` is the family name of the algorithm and `pnames` are its supported
+/// parameter set names. `pnames` must contain at least one element. For an
+/// implementation of `NamedKeyPairGenerator`, the first element becomes its
+/// default parameter set, i.e. the parameter set used by generated keys unless
/// [#initialize(AlgorithmParameterSpec, java.security.SecureRandom)]
/// is called on a different parameter set.
///
+/// A `NamedKEM` or `NamedSignature` implementation must include a zero-argument
+/// public constructor that calls `super(fname, factory)`, where `fname` is the
+/// family name of the algorithm and `factory` is the `NamedKeyFactory` object
+/// that is used to translate foreign keys. `factory` only recognizes
+/// parameter sets supported by this implementation.
+///
/// An implementation must implement all abstract methods. For all these
/// methods, the implementation must relinquish any "ownership" of any input
/// and output array argument. Precisely, the implementation must not retain
@@ -69,8 +74,8 @@
/// array argument and must not retain any reference to an input array argument
/// after the call.
///
-/// Also, an implementation must not keep any extra copy of a private key.
-/// For key generation, the only copy is the one returned in the
+/// Also, an implementation must not keep any extra copy of a private key in
+/// any format. For key generation, the only copy is the one returned in the
/// [#implGenerateKeyPair] call. For all other methods, it must not make
/// a copy of the input private key. A `KEM` implementation also must not
/// keep a copy of the shared secret key, no matter if it's an encapsulator
@@ -84,6 +89,34 @@
/// (For example, `implSign`) later. An implementation must not retain
/// a reference of the parsed key.
///
+/// The private key, represented as a byte array when used in `NamedKEM` or
+/// `NamedSignature`, is referred to as its expanded format. For some
+/// algorithms, this format may differ from the
+/// [key material][NamedPKCS8Key#getRawBytes()] inside a PKCS #8 file. For example,
+/// [FIPS 204](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf)
+/// Table 2 defines the ML-DSA-65 private key as a 4032-byte array, which is
+/// used in the ML-DSA.Sign function in Algorithm 2, representing the
+/// expanded format. However, in
+/// [RFC 9881](https://datatracker.ietf.org/doc/html/rfc9881#name-private-key-format),
+/// a private key can be encoded into a CHOICE of three formats, none in the
+/// same as the FIPS 204 format. The choices are defined in
+/// [sun.security.util.KeyChoices]. A `NamedKeyPairGenerator` implementation
+/// should return both the expanded key and a preferred encoding in its
+/// [#implGenerateKeyPair] method.
+///
+/// A `NamedKeyFactory` must override the `implExpand` method to derive
+/// the expanded format from an encoding format, or return `null` if there
+/// is no difference.
+///
+/// Implementations may support multiple encoding formats.
+///
+/// A `NamedKeyFactory` must not modify the encoding when generating a key
+/// from a `KeySpec` object, ensuring that when re-encoded, the key retains
+/// its original encoding format.
+///
+/// A `NamedKeyFactory` can choose a different encoding format when
+/// `translateKey` is called.
+///
/// When constructing a [NamedX509Key] or [NamedPKCS8Key] object from raw key
/// bytes, the key bytes are directly referenced within the object, so the
/// caller must not modify them afterward. Similarly, the key's `getRawBytes`
@@ -105,9 +138,9 @@
public abstract class NamedKeyPairGenerator extends KeyPairGeneratorSpi {
private final String fname; // family name
- private final String[] pnames; // allowed parameter set name (at least one)
+ private final String[] pnames; // allowed parameter set names (at least one)
- protected String name; // init as
+ protected String pname; // parameter set name, if can be determined
private SecureRandom secureRandom;
/// Creates a new `NamedKeyPairGenerator` object.
@@ -126,22 +159,22 @@ protected NamedKeyPairGenerator(String fname, String... pnames) {
this.pnames = pnames;
}
- private String checkName(String name) throws InvalidAlgorithmParameterException {
- for (var pname : pnames) {
- if (pname.equalsIgnoreCase(name)) {
- // return the stored standard name
- return pname;
+ private String checkName(String pname) throws InvalidAlgorithmParameterException {
+ for (var n : pnames) {
+ if (n.equalsIgnoreCase(pname)) {
+ // return the stored standard pname
+ return n;
}
}
throw new InvalidAlgorithmParameterException(
- "Unsupported parameter set name: " + name);
+ "Unsupported parameter set name: " + pname);
}
@Override
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
throws InvalidAlgorithmParameterException {
if (params instanceof NamedParameterSpec spec) {
- name = checkName(spec.getName());
+ pname = checkName(spec.getName());
} else {
throw new InvalidAlgorithmParameterException(
"Unsupported AlgorithmParameterSpec: " + params);
@@ -161,17 +194,21 @@ public void initialize(int keysize, SecureRandom random) {
@Override
public KeyPair generateKeyPair() {
- String pname = name != null ? name : pnames[0];
- var keys = implGenerateKeyPair(pname, secureRandom);
- return new KeyPair(new NamedX509Key(fname, pname, keys[0]),
- new NamedPKCS8Key(fname, pname, keys[1]));
+ String tmpName = pname != null ? pname : pnames[0];
+ var keys = implGenerateKeyPair(tmpName, secureRandom);
+ return new KeyPair(new NamedX509Key(fname, tmpName, keys[0]),
+ NamedPKCS8Key.internalCreate(fname, tmpName, keys[1],
+ keys.length == 2 ? null : keys[2]));
}
/// User-defined key pair generator.
///
/// @param pname parameter set name
/// @param sr `SecureRandom` object, `null` if not initialized
- /// @return public key and private key (in this order) in raw bytes
+ /// @return the public key, the private key in its encoding format, and
+ /// the private key in its expanded format (in this order) in
+ /// raw bytes. If the expanded format of the private key is the
+ /// same as its encoding format, the 3rd element must be omitted.
/// @throws ProviderException if there is an internal error
protected abstract byte[][] implGenerateKeyPair(String pname, SecureRandom sr);
}
diff --git a/src/java.base/share/classes/sun/security/provider/NamedSignature.java b/src/java.base/share/classes/sun/security/provider/NamedSignature.java
index 921a39cfc926..07d20828c3c1 100644
--- a/src/java.base/share/classes/sun/security/provider/NamedSignature.java
+++ b/src/java.base/share/classes/sun/security/provider/NamedSignature.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025, 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
@@ -40,7 +40,6 @@
import java.security.SignatureException;
import java.security.SignatureSpi;
import java.security.spec.AlgorithmParameterSpec;
-import java.util.Objects;
/// A base class for all `Signature` implementations that can be
/// configured with a named parameter set. See [NamedKeyPairGenerator]
@@ -50,12 +49,12 @@
public abstract class NamedSignature extends SignatureSpi {
private final String fname; // family name
- private final String[] pnames; // allowed parameter set name (at least one)
+ private final NamedKeyFactory fac;
private final ByteArrayOutputStream bout = new ByteArrayOutputStream();
// init with...
- private String name;
+ private String pname;
private byte[] secKey;
private byte[] pubKey;
@@ -65,26 +64,23 @@ public abstract class NamedSignature extends SignatureSpi {
/// Creates a new `NamedSignature` object.
///
/// @param fname the family name
- /// @param pnames the standard parameter set names, at least one is needed.
- protected NamedSignature(String fname, String... pnames) {
+ /// @param fac the `KeyFactory` used to translate foreign keys and
+ /// perform key validation
+ protected NamedSignature(String fname, NamedKeyFactory fac) {
if (fname == null) {
throw new AssertionError("fname cannot be null");
}
- if (pnames == null || pnames.length == 0) {
- throw new AssertionError("pnames cannot be null or empty");
- }
this.fname = fname;
- this.pnames = pnames;
+ this.fac = fac;
}
@Override
protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
// translate also check the key
- var nk = (NamedX509Key) new NamedKeyFactory(fname, pnames)
- .engineTranslateKey(publicKey);
- name = nk.getParams().getName();
+ var nk = (NamedX509Key) fac.toNamedKey(publicKey);
+ pname = nk.getParams().getName();
pubKey = nk.getRawBytes();
- pk2 = implCheckPublicKey(name, pubKey);
+ pk2 = implCheckPublicKey(pname, pubKey);
secKey = null;
bout.reset();
}
@@ -92,11 +88,10 @@ protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException
@Override
protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
// translate also check the key
- var nk = (NamedPKCS8Key) new NamedKeyFactory(fname, pnames)
- .engineTranslateKey(privateKey);
- name = nk.getParams().getName();
- secKey = nk.getRawBytes();
- sk2 = implCheckPrivateKey(name, secKey);
+ var nk = (NamedPKCS8Key) fac.toNamedKey(privateKey);
+ pname = nk.getParams().getName();
+ secKey = nk.getExpanded();
+ sk2 = implCheckPrivateKey(pname, secKey);
pubKey = null;
bout.reset();
}
@@ -116,7 +111,7 @@ protected byte[] engineSign() throws SignatureException {
if (secKey != null) {
var msg = bout.toByteArray();
bout.reset();
- return implSign(name, secKey, sk2, msg, appRandom);
+ return implSign(pname, secKey, sk2, msg, appRandom);
} else {
throw new SignatureException("No private key");
}
@@ -127,21 +122,21 @@ protected boolean engineVerify(byte[] sig) throws SignatureException {
if (pubKey != null) {
var msg = bout.toByteArray();
bout.reset();
- return implVerify(name, pubKey, pk2, msg, sig);
+ return implVerify(pname, pubKey, pk2, msg, sig);
} else {
throw new SignatureException("No public key");
}
}
@Override
- @SuppressWarnings("deprecation")
+ @Deprecated
protected void engineSetParameter(String param, Object value)
throws InvalidParameterException {
throw new InvalidParameterException("setParameter() not supported");
}
@Override
- @SuppressWarnings("deprecation")
+ @Deprecated
protected Object engineGetParameter(String param) throws InvalidParameterException {
throw new InvalidParameterException("getParameter() not supported");
}
@@ -162,7 +157,7 @@ protected AlgorithmParameters engineGetParameters() {
/// User-defined sign function.
///
- /// @param name parameter name
+ /// @param pname parameter name
/// @param sk private key in raw bytes
/// @param sk2 parsed private key, `null` if none. See [#implCheckPrivateKey].
/// @param msg the message
@@ -170,12 +165,12 @@ protected AlgorithmParameters engineGetParameters() {
/// @return the signature
/// @throws ProviderException if there is an internal error
/// @throws SignatureException if there is another error
- protected abstract byte[] implSign(String name, byte[] sk, Object sk2,
+ protected abstract byte[] implSign(String pname, byte[] sk, Object sk2,
byte[] msg, SecureRandom sr) throws SignatureException;
/// User-defined verify function.
///
- /// @param name parameter name
+ /// @param pname parameter name
/// @param pk public key in raw bytes
/// @param pk2 parsed public key, `null` if none. See [#implCheckPublicKey].
/// @param msg the message
@@ -183,7 +178,7 @@ protected abstract byte[] implSign(String name, byte[] sk, Object sk2,
/// @return true if verified
/// @throws ProviderException if there is an internal error
/// @throws SignatureException if there is another error
- protected abstract boolean implVerify(String name, byte[] pk, Object pk2,
+ protected abstract boolean implVerify(String pname, byte[] pk, Object pk2,
byte[] msg, byte[] sig) throws SignatureException;
/// User-defined function to validate a public key.
@@ -195,11 +190,11 @@ protected abstract boolean implVerify(String name, byte[] pk, Object pk2,
///
/// The default implementation returns `null`.
///
- /// @param name parameter name
+ /// @param pname parameter name
/// @param pk public key in raw bytes
/// @return a parsed key, `null` if none.
/// @throws InvalidKeyException if the key is invalid
- protected Object implCheckPublicKey(String name, byte[] pk) throws InvalidKeyException {
+ protected Object implCheckPublicKey(String pname, byte[] pk) throws InvalidKeyException {
return null;
}
@@ -212,11 +207,11 @@ protected Object implCheckPublicKey(String name, byte[] pk) throws InvalidKeyExc
///
/// The default implementation returns `null`.
///
- /// @param name parameter name
+ /// @param pname parameter name
/// @param sk private key in raw bytes
/// @return a parsed key, `null` if none.
/// @throws InvalidKeyException if the key is invalid
- protected Object implCheckPrivateKey(String name, byte[] sk) throws InvalidKeyException {
+ protected Object implCheckPrivateKey(String pname, byte[] sk) throws InvalidKeyException {
return null;
}
}
diff --git a/src/java.base/share/classes/sun/security/provider/certpath/URICertStore.java b/src/java.base/share/classes/sun/security/provider/certpath/URICertStore.java
index 3e1fc8db1644..6eb95f92246d 100644
--- a/src/java.base/share/classes/sun/security/provider/certpath/URICertStore.java
+++ b/src/java.base/share/classes/sun/security/provider/certpath/URICertStore.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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,6 +25,7 @@
package sun.security.provider.certpath;
+import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
@@ -188,6 +189,16 @@ private static int initializeTimeout(String prop, int def) {
return timeoutVal;
}
+ /**
+ * Maximum size for a CRL downloaded through a URICertStore
+ * in bytes. This can be controlled by the com.sun.security.crl.maxSize
+ * Security or System property. The System property, if set, overrides
+ * the Security property. The default size is 20MiB.
+ */
+ private static final long MAX_CRL_DOWNLOAD_SIZE =
+ SecurityProperties.getOverridableLongProp(
+ "com.sun.security.crl.maxSize", 20971520, debug);
+
/**
* Enumeration for the allowed schemes we support when following a
* URI from an authorityInfoAccess extension on a certificate.
@@ -228,6 +239,13 @@ static AllowedScheme nameOf(String name) {
private static final boolean CA_ISS_ALLOW_ANY;
static {
+ // Add a debug message for the configured CRL download limit
+ if (debug != null) {
+ debug.println("Maximum downloadable CRL size: " +
+ MAX_CRL_DOWNLOAD_SIZE +
+ ((MAX_CRL_DOWNLOAD_SIZE < 0) ? " (DISABLED)" : ""));
+ }
+
boolean allowAny = false;
try {
if (Builder.USE_AIA) {
@@ -623,7 +641,19 @@ public synchronized Collection engineGetCRLs(CRLSelector selector)
if (debug != null) {
debug.println("Downloading new CRL...");
}
- crl = (X509CRL) factory.generateCRL(in);
+ InputStream crlIn = (MAX_CRL_DOWNLOAD_SIZE > -1) ?
+ new SizeLimitedInputStream(in, MAX_CRL_DOWNLOAD_SIZE) :
+ in;
+ try {
+ crl = (X509CRL) factory.generateCRL(crlIn);
+ } catch (IllegalArgumentException iae) {
+ // IAE should only be thrown when the CRL exceeds a
+ // configured maximum length.
+ if (debug != null) {
+ debug.println("Discarding CRL: " + iae.getMessage());
+ crl = null;
+ }
+ }
}
return getMatchingCRLs(crl, selector);
} catch (IOException | CRLException e) {
@@ -816,4 +846,59 @@ boolean matchRule(URI filterRule, URI caIssuer) {
return true;
}
}
+
+ /**
+ * Stream wrapper used when an InputStream passed into a CertificateFactory
+ * needs to be size limited. It will throw IllegalArgumentException when
+ * the downloaded resource via the underlying stream exceeds the maximum
+ * limit.
+ */
+ private static class SizeLimitedInputStream extends FilterInputStream {
+
+ private final long maxBytes;
+ private long bytesRead = 0;
+
+ private SizeLimitedInputStream(InputStream in, long maxBytes) {
+ super(in);
+ this.maxBytes = maxBytes;
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (bytesRead >= maxBytes) {
+ // We will use IAE here to differentiate this special case
+ // from other IOEs that the underlying input stream might
+ // legitimately throw.
+ throw new IllegalArgumentException("InputStream exceeded max " +
+ "size of " + maxBytes);
+ }
+
+ int b = super.read();
+ if (b != -1) {
+ bytesRead++;
+ }
+ return b;
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+
+ if (bytesRead >= maxBytes) {
+ // We will use IAE here to differentiate this special case
+ // from other IOEs that the underlying input stream might
+ // legitimately throw.
+ throw new IllegalArgumentException("InputStream exceeded max " +
+ "size of " + maxBytes);
+ }
+
+ long remaining = maxBytes - bytesRead;
+ int toRead = (int) Math.min(len, remaining);
+
+ int n = super.read(b, off, toRead);
+ if (n != -1) {
+ bytesRead += n;
+ }
+ return n;
+ }
+ }
}
diff --git a/src/java.base/share/classes/sun/security/ssl/Alert.java b/src/java.base/share/classes/sun/security/ssl/Alert.java
index 4e1ccf385c72..5b1881da9723 100644
--- a/src/java.base/share/classes/sun/security/ssl/Alert.java
+++ b/src/java.base/share/classes/sun/security/ssl/Alert.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -254,25 +254,37 @@ public void consume(ConnectionContext context,
} else if ((level == Level.WARNING) && (alert != null)) {
// Terminate the connection if an alert with a level of warning
// is received during handshaking, except the no_certificate
- // warning.
- if (alert.handshakeOnly && (tc.handshakeContext != null)) {
- // It's OK to get a no_certificate alert from a client of
- // which we requested client authentication. However,
- // if we required it, then this is not acceptable.
- if (tc.sslConfig.isClientMode ||
- alert != Alert.NO_CERTIFICATE ||
- (tc.sslConfig.clientAuthType !=
+ // warning for SSLv3.
+ HandshakeContext hc = tc.handshakeContext;
+ if (alert.handshakeOnly && (hc != null)) {
+ // In SSLv3, it's OK to get a no_certificate alert from a
+ // client where we requested (want) client authentication.
+ // If we required it (need), this is not acceptable
+ // and must fail.
+ //
+ // no_certificate alerts are not acceptable in TLSv1.*.
+ //
+ if (!tc.sslConfig.isClientMode &&
+ (hc.negotiatedProtocol == ProtocolVersion.SSL30) &&
+ (alert == Alert.NO_CERTIFICATE) &&
+ (tc.sslConfig.clientAuthType ==
ClientAuthType.CLIENT_AUTH_REQUESTED)) {
- throw tc.fatal(Alert.HANDSHAKE_FAILURE,
- "received handshake warning: " + alert.description);
- } else {
- // Otherwise, ignore the warning but remove the
- // Certificate and CertificateVerify handshake
- // consumer so the state machine doesn't expect it.
- tc.handshakeContext.handshakeConsumers.remove(
- SSLHandshake.CERTIFICATE.id);
- tc.handshakeContext.handshakeConsumers.remove(
+
+ // We'll ignore the warning and remove the Certificate
+ // and CertificateVerify handshake consumers so the
+ // state machine isn't expecting them.
+ if (hc.handshakeConsumers.remove(
+ SSLHandshake.CERTIFICATE.id) != null) {
+ hc.handshakeConsumers.remove(
SSLHandshake.CERTIFICATE_VERIFY.id);
+ } else {
+ throw tc.fatal(Alert.HANDSHAKE_FAILURE,
+ "NO_CERTIFICATE alert received when certs" +
+ " were not expected or already received");
+ }
+ } else {
+ throw tc.fatal(Alert.HANDSHAKE_FAILURE,
+ "Received handshake warning: " + alert.description);
}
} // Otherwise, ignore the warning
} else { // fatal or unknown
diff --git a/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java b/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java
index b3155f5170a8..4268b9779bd8 100644
--- a/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java
+++ b/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java
@@ -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
@@ -26,6 +26,7 @@
package sun.security.ssl;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
@@ -121,6 +122,7 @@ abstract boolean isCookieValid(ServerHandshakeContext context,
private static final
class D10HelloCookieManager extends HelloCookieManager {
+ private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
final SecureRandom secureRandom;
private int cookieVersion; // allow to wrap, version + sequence
private final byte[] cookieSecret;
@@ -170,6 +172,7 @@ byte[] createCookie(ServerHandshakeContext context,
}
byte[] helloBytes = clientHello.getHelloCookieBytes();
md.update(helloBytes);
+ md.update(getHostPortBytes(context));
byte[] cookie = md.digest(secret); // 32 bytes
cookie[0] = (byte)((version >> 24) & 0xFF);
@@ -205,11 +208,30 @@ boolean isCookieValid(ServerHandshakeContext context,
}
byte[] helloBytes = clientHello.getHelloCookieBytes();
md.update(helloBytes);
+ md.update(getHostPortBytes(context));
byte[] target = md.digest(secret); // 32 bytes
target[0] = cookie[0];
return MessageDigest.isEqual(target, cookie);
}
+
+ /**
+ * Returns host and port bytes if those are set.
+ * Using ASCII unit separator character to separate host and port so we
+ * can differentiate between otherwise identical host and port string
+ * concatenations, for example host 172.0.0.1 with port 25 and host
+ * 172.0.0.12 with port 5.
+ */
+ private static byte[] getHostPortBytes(ServerHandshakeContext context) {
+ final String host = context.conContext.transport.getPeerHost();
+ final int port = context.conContext.transport.getPeerPort();
+ final String hostStr = host != null ? host : "";
+ final String portStr = port > -1 ? Integer.toString(port) : "";
+ return hostStr.isEmpty() && portStr.isEmpty() ?
+ EMPTY_BYTE_ARRAY :
+ (hostStr + '\u001F' + portStr).getBytes(
+ StandardCharsets.UTF_8);
+ }
}
private static final
diff --git a/src/java.base/share/classes/sun/security/timestamp/TSResponse.java b/src/java.base/share/classes/sun/security/timestamp/TSResponse.java
index 16ba761bff04..82287540b631 100644
--- a/src/java.base/share/classes/sun/security/timestamp/TSResponse.java
+++ b/src/java.base/share/classes/sun/security/timestamp/TSResponse.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -26,6 +26,8 @@
package sun.security.timestamp;
import java.io.IOException;
+
+import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.util.Debug;
import sun.security.util.DerValue;
@@ -357,6 +359,11 @@ private void parse(byte[] tsReply) throws IOException {
DerValue timestampToken = derValue.data.getDerValue();
encodedTsToken = timestampToken.toByteArray();
tsToken = new PKCS7(encodedTsToken);
+ // RFC 3161 Section 2.4.2. id-ct-TSTInfo.
+ if (!tsToken.getContentInfo().getContentType()
+ .equals(ContentInfo.TIMESTAMP_TOKEN_INFO_OID)) {
+ throw new TimestampException("Not using id-ct-TSTInfo");
+ }
tstInfo = new TimestampToken(tsToken.getContentInfo().getData());
}
diff --git a/src/java.base/share/classes/sun/security/util/DerValue.java b/src/java.base/share/classes/sun/security/util/DerValue.java
index ec8b482b07dc..8d86c8dd1439 100644
--- a/src/java.base/share/classes/sun/security/util/DerValue.java
+++ b/src/java.base/share/classes/sun/security/util/DerValue.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -157,6 +157,9 @@ public class DerValue {
*/
public static final byte tag_SetOf = 0x31;
+ // Max nested depth for constructed data
+ private static final int MAX_CONSTRUCTED_NEST = 30;
+
// This class is mostly immutable except that:
//
// 1. resetTag() modifies the tag
@@ -564,6 +567,14 @@ public ObjectIdentifier getOID() throws IOException {
* @return the octet string held in this DER value
*/
public byte[] getOctetString() throws IOException {
+ return getOctetString(0);
+ }
+
+ private byte[] getOctetString(int limit) throws IOException {
+ if (++limit > MAX_CONSTRUCTED_NEST) {
+ throw new IOException("Nested OctetString limit reached ("
+ + MAX_CONSTRUCTED_NEST + ").");
+ }
if (tag != tag_OctetString && !isConstructed(tag_OctetString)) {
throw new IOException(
@@ -582,7 +593,7 @@ public byte[] getOctetString() throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DerInputStream dis = data();
while (dis.available() > 0) {
- bout.write(dis.getDerValue().getOctetString());
+ bout.write(dis.getDerValue().getOctetString(limit));
}
return bout.toByteArray();
}
diff --git a/src/java.base/share/classes/sun/security/util/HostnameChecker.java b/src/java.base/share/classes/sun/security/util/HostnameChecker.java
index 1374bc6d5352..c7ab49a15797 100644
--- a/src/java.base/share/classes/sun/security/util/HostnameChecker.java
+++ b/src/java.base/share/classes/sun/security/util/HostnameChecker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -263,7 +263,7 @@ public static X500Name getSubjectX500Name(X509Certificate cert)
* The name parameter should represent a DNS name. The
* template parameter may contain the wildcard character '*'.
*/
- private boolean isMatched(String name, String template,
+ public boolean isMatched(String name, String template,
boolean chainsToPublicCA) {
// Normalize to Unicode, because PSL is in Unicode.
diff --git a/src/java.base/share/classes/sun/security/util/KeyChoices.java b/src/java.base/share/classes/sun/security/util/KeyChoices.java
new file mode 100644
index 000000000000..00c4463d0987
--- /dev/null
+++ b/src/java.base/share/classes/sun/security/util/KeyChoices.java
@@ -0,0 +1,289 @@
+/*
+ * 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
+ * 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.
+ */
+
+package sun.security.util;
+
+import java.security.*;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.function.BiFunction;
+
+/**
+ * The content of an ML-KEM or ML-DSA private key is defined as a CHOICE
+ * among three different representations. For example:
+ *
+ * This class supports reading, writing, and converting between them.
+ *
+ * Current code follows RFC 9935 and RFC 9881.
+ */
+public final class KeyChoices {
+
+ public enum Type { SEED, EXPANDED_KEY, BOTH }
+
+ private record Choice(Type type, byte[] seed, byte[] expanded) {}
+
+ /**
+ * Gets the preferred choice type for an algorithm, defined as an
+ * overridable security property "jdk..pkcs8.encoding".
+ *
+ * @param name "mlkem" or "mldsa".
+ * @throws IllegalArgumentException if property is invalid value
+ * @return the type
+ */
+ public static Type getPreferred(String name) {
+ var prop = SecurityProperties.getOverridableProperty(
+ "jdk." + name + ".pkcs8.encoding");
+ if (prop == null) {
+ return Type.SEED;
+ }
+ return switch (prop.toLowerCase(Locale.ROOT)) {
+ case "seed" -> Type.SEED;
+ case "expandedkey" -> Type.EXPANDED_KEY;
+ case "both" -> Type.BOTH;
+ default -> throw new IllegalArgumentException("Unknown format: " + prop);
+ };
+ }
+
+ /**
+ * Writes one of the ML-KEM or ML-DSA private key formats.
+ *
+ * This method does not check the length of the inputs or whether
+ * they match each other. The caller must make sure `seed` and/or
+ * `expanded` are provided if `type` requires any of them.
+ *
+ * @param type preferred output choice type
+ * @param seed the seed, could be null
+ * @param expanded the expanded key, could be null
+ * @return one of the choices
+ */
+ public static byte[] writeToChoice(Type type, byte[] seed, byte[] expanded) {
+ byte[] skOctets;
+ // Ensures using one-byte len in DER
+ assert seed == null || seed.length < 128;
+ // Ensures using two-byte len in DER
+ assert expanded == null || expanded.length > 256 && expanded.length < 60000;
+
+ return switch (type) {
+ case SEED -> {
+ assert seed != null;
+ skOctets = new byte[seed.length + 2];
+ skOctets[0] = (byte)0x80;
+ skOctets[1] = (byte) seed.length;
+ System.arraycopy(seed, 0, skOctets, 2, seed.length);
+ yield skOctets;
+ }
+ case EXPANDED_KEY -> {
+ assert expanded != null;
+ skOctets = new byte[expanded.length + 4];
+ skOctets[0] = 0x04;
+ writeShortLength(skOctets, 1, expanded.length);
+ System.arraycopy(expanded, 0, skOctets, 4, expanded.length);
+ yield skOctets;
+ }
+ case BOTH -> {
+ assert seed != null;
+ assert expanded != null;
+ skOctets = new byte[10 + seed.length + expanded.length];
+ skOctets[0] = 0x30;
+ writeShortLength(skOctets, 1, 6 + seed.length + expanded.length);
+ skOctets[4] = 0x04;
+ skOctets[5] = (byte)seed.length;
+ System.arraycopy(seed, 0, skOctets, 6, seed.length);
+ skOctets[6 + seed.length] = 0x04;
+ writeShortLength(skOctets, 7 + seed.length, expanded.length);
+ System.arraycopy(expanded, 0, skOctets, 10 + seed.length, expanded.length);
+ yield skOctets;
+ }
+ };
+ }
+
+ /**
+ * Gets the type of input.
+ *
+ * @param input input bytes
+ * @return the type
+ * @throws InvalidKeyException if input is invalid
+ */
+ public static Type typeOfChoice(byte[] input) throws InvalidKeyException {
+ if (input.length < 1) {
+ throw new InvalidKeyException("Empty key");
+ }
+ return switch (input[0]) {
+ case (byte) 0x80 -> Type.SEED;
+ case 0x04 -> Type.EXPANDED_KEY;
+ case 0x30 -> Type.BOTH;
+ default -> throw new InvalidKeyException("Wrong tag: " + input[0]);
+ };
+ }
+
+ /**
+ * Splits one of the ML-KEM or ML-DSA private key formats into
+ * seed and expandedKey, if exists.
+ *
+ * @param seedLen correct seed length
+ * @param input input bytes
+ * @return a {@code Choice} object. Byte arrays inside are newly allocated
+ * @throws InvalidKeyException if input is invalid
+ */
+ private static Choice readFromChoice(int seedLen, byte[] input)
+ throws InvalidKeyException {
+ if (input.length < seedLen + 2) {
+ throw new InvalidKeyException("Too short");
+ }
+ return switch (input[0]) {
+ case (byte) 0x80 -> {
+ // 80 SEED_LEN
+ if (input[1] != seedLen && input.length != seedLen + 2) {
+ throw new InvalidKeyException("Invalid seed");
+ }
+ yield new Choice(Type.SEED,
+ Arrays.copyOfRange(input, 2, seedLen + 2), null);
+ }
+ case 0x04 -> {
+ // 04 82 nn nn
+ if (readShortLength(input, 1) != input.length - 4) {
+ throw new InvalidKeyException("Invalid expandedKey");
+ }
+ yield new Choice(Type.EXPANDED_KEY,
+ null, Arrays.copyOfRange(input, 4, input.length));
+ }
+ case 0x30 -> {
+ // 30 82 mm mm 04 SEED_LEN 04 82 nn nn
+ if (input.length < 6 + seedLen + 4) {
+ throw new InvalidKeyException("Too short");
+ }
+ if (readShortLength(input, 1) != input.length - 4
+ || input[4] != 0x04
+ || input[5] != (byte)seedLen
+ || input[seedLen + 6] != 0x04
+ || readShortLength(input, seedLen + 7)
+ != input.length - 10 - seedLen) {
+ throw new InvalidKeyException("Invalid both");
+ }
+ yield new Choice(Type.BOTH,
+ Arrays.copyOfRange(input, 6, 6 + seedLen),
+ Arrays.copyOfRange(input, seedLen + 10, input.length));
+ }
+ default -> throw new InvalidKeyException("Wrong tag: " + input[0]);
+ };
+ }
+
+ /**
+ * Reads from any encoding and write to the specified type.
+ *
+ * @param type preferred output choice type
+ * @param pname parameter set name
+ * @param seedLen seed length
+ * @param input the input encoding
+ * @param expander function to calculate expanded from seed, could be null
+ * if there is already expanded in input
+ * @return the preferred encoding
+ * @throws InvalidKeyException if input is invalid or does not have enough
+ * information to generate the output
+ */
+ public static byte[] choiceToChoice(Type type, String pname,
+ int seedLen, byte[] input,
+ BiFunction expander)
+ throws InvalidKeyException {
+ var choice = readFromChoice(seedLen, input);
+ try {
+ if (type != Type.EXPANDED_KEY && choice.type == Type.EXPANDED_KEY) {
+ throw new InvalidKeyException(
+ "key contains not enough info to translate");
+ }
+ var expanded = (choice.expanded == null && type != Type.SEED)
+ ? expander.apply(pname, choice.seed)
+ : choice.expanded;
+ return writeToChoice(type, choice.seed, expanded);
+ } finally {
+ if (choice.seed != null) {
+ Arrays.fill(choice.seed, (byte) 0);
+ }
+ if (choice.expanded != null) {
+ Arrays.fill(choice.expanded, (byte) 0);
+ }
+ }
+ }
+
+ /**
+ * Reads from any choice of encoding and return the expanded format.
+ *
+ * @param pname parameter set name
+ * @param seedLen seed length
+ * @param input input encoding
+ * @param expander function to calculate expanded from seed, could be null
+ * if there is already expanded in input
+ * @return the expanded key
+ * @throws InvalidKeyException if input is invalid
+ */
+ public static byte[] choiceToExpanded(String pname,
+ int seedLen, byte[] input,
+ BiFunction expander)
+ throws InvalidKeyException {
+ var choice = readFromChoice(seedLen, input);
+ if (choice.type == Type.BOTH) {
+ var calculated = expander.apply(pname, choice.seed);
+ if (!Arrays.equals(choice.expanded, calculated)) {
+ throw new InvalidKeyException("seed and expandedKey do not match");
+ }
+ Arrays.fill(calculated, (byte)0);
+ }
+ try {
+ if (choice.expanded != null) {
+ return choice.expanded;
+ }
+ return expander.apply(pname, choice.seed);
+ } finally {
+ if (choice.seed != null) {
+ Arrays.fill(choice.seed, (byte)0);
+ }
+ }
+ }
+
+ // Reads a 2 bytes length from DER encoding
+ private static int readShortLength(byte[] input, int from)
+ throws InvalidKeyException {
+ if (input[from] != (byte)0x82) {
+ throw new InvalidKeyException("Unexpected length");
+ }
+ return ((input[from + 1] & 0xff) << 8) + (input[from + 2] & 0xff);
+ }
+
+ // Writes a 2 bytes length to DER encoding
+ private static void writeShortLength(byte[] input, int from, int value) {
+ input[from] = (byte)0x82;
+ input[from + 1] = (byte) (value >> 8);
+ input[from + 2] = (byte) (value);
+ }
+}
diff --git a/src/java.base/share/classes/sun/security/util/SecurityProperties.java b/src/java.base/share/classes/sun/security/util/SecurityProperties.java
index 98bc71d829be..da69ecbf5d66 100644
--- a/src/java.base/share/classes/sun/security/util/SecurityProperties.java
+++ b/src/java.base/share/classes/sun/security/util/SecurityProperties.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.
* Copyright (c) 2018 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -139,6 +139,36 @@ public static int getTimeoutSystemProp(String prop, int def, Debug dbg) {
}
}
+ /**
+ * A convenience routine for fetching a numeric value from a Security
+ * or System property and returning it as a long. The value from the
+ * property is obtained according to the logic in
+ * {@link SecurityProperties#getOverridableProperty(String)}
+ *
+ * @param prop the property to query
+ * @param defaultValue the default value
+ * @param dbg a Debug object, if null no debug messages will be sent
+ * @return the value of the property as a {@code long}. If a non-numeric
+ * value is supplied, the default value will be returned.
+ */
+ public static long getOverridableLongProp(String prop, long defaultValue,
+ Debug dbg) {
+ long longVal = defaultValue;
+ try {
+ String propVal = SecurityProperties.getOverridableProperty(prop);
+ if (propVal != null) {
+ longVal = Long.parseLong(propVal);
+ }
+ } catch (NumberFormatException nfe) {
+ // We will use the default, but add a warning debug message
+ if (dbg != null) {
+ dbg.println("Warning: Non-numeric value found in property " +
+ prop + ", using default value of " + defaultValue);
+ }
+ }
+ return longVal;
+ }
+
/**
* Convenience method for fetching System property values that are booleans.
*
diff --git a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java
index d7e65b6aef0f..0b21ccbd294c 100644
--- a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java
+++ b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -46,7 +46,12 @@ public class SignatureFileVerifier {
/* Are we debugging ? */
private static final Debug debug = Debug.getInstance("jar");
- private final ArrayList signerCache;
+ private final List signerCache;
+
+ // The maximum size of the signerCache. This is for debug only
+ // and not intended to be adjusted by users.
+ private static int SIGNER_CACHE_SIZE
+ = Integer.getInteger("sun.security.util.jar.signer.cache.size", 5);
private static final String ATTR_DIGEST =
"-DIGEST-" + ManifestDigester.MF_MAIN_ATTRS.toUpperCase(Locale.ENGLISH);
@@ -97,7 +102,7 @@ public class SignatureFileVerifier {
*
* @param rawBytes the raw bytes of the signature block file
*/
- public SignatureFileVerifier(ArrayList signerCache,
+ public SignatureFileVerifier(List signerCache,
ManifestDigester md,
String name,
byte[] rawBytes)
@@ -282,7 +287,6 @@ public void process(Hashtable signers,
} finally {
Providers.stopJarVerification(obj);
}
-
}
private void processImpl(Hashtable signers,
@@ -850,6 +854,9 @@ void updateSigners(CodeSigner[] newSigners,
newSigners.length);
}
signerCache.add(cachedSigners);
+ if (signerCache.size() > SIGNER_CACHE_SIZE) {
+ signerCache.remove(0);
+ }
signers.put(name, cachedSigners);
}
diff --git a/src/java.base/share/classes/sun/security/x509/DNSName.java b/src/java.base/share/classes/sun/security/x509/DNSName.java
index 597652022ced..cf72bb15ed24 100644
--- a/src/java.base/share/classes/sun/security/x509/DNSName.java
+++ b/src/java.base/share/classes/sun/security/x509/DNSName.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -52,6 +52,8 @@
public class DNSName implements GeneralNameInterface {
private final String name;
+ private static final HostnameChecker HOSTNAME_CHECKER =
+ HostnameChecker.getInstance(HostnameChecker.TYPE_TLS);
private static final String alphaDigits =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
@@ -206,6 +208,9 @@ public int hashCode() {
* For example, www.host.example.com would satisfy the constraint but
* host1.example.com would not.
*
+ * RFC6125: Match wildcard pattern in the input name being constrained,
+ * any wildcard in this name will be matched as a literal character.
+ *
MIT License
-Copyright (C) 1998-2025 Marti Maria Saguer
+Copyright (C) 1998-2026 Marti Maria Saguer
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the "Software"),
@@ -86,6 +86,7 @@ Amyspark
Lovell Fuller
Eli Schwartz
Diogo Teles Sant'Anna
+Vlad Erium
Special Thanks
--------------
diff --git a/src/java.desktop/share/legal/libpng.md b/src/java.desktop/share/legal/libpng.md
index 7783fc7ff032..4c17a52a7ef2 100644
--- a/src/java.desktop/share/legal/libpng.md
+++ b/src/java.desktop/share/legal/libpng.md
@@ -1,4 +1,4 @@
-## libpng v1.6.57
+## libpng v1.6.58
### libpng License
diff --git a/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c b/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c
index ae86b309465a..d2d622f08985 100644
--- a/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c
+++ b/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -2216,7 +2216,11 @@ allocateArray(JNIEnv *env, BufImageS_t *imageP,
/* Means we need to fill in alpha */
if (!cvtToDefault && addAlpha) {
*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height);
- if (*mlibImagePP != NULL) {
+ if (*mlibImagePP == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
+ JNI_ABORT);
+ return -1;
+ } else {
unsigned int *dstP = (unsigned int *)
mlib_ImageGetData(*mlibImagePP);
int dstride = (*mlibImagePP)->stride>>2;
@@ -2232,10 +2236,10 @@ allocateArray(JNIEnv *env, BufImageS_t *imageP,
dP[x] = sP[x] | 0xff000000;
}
}
+ (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
+ JNI_ABORT);
+ return 0;
}
- (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
- JNI_ABORT);
- return 0;
}
else if ((hintP->packing & BYTE_INTERLEAVED) == BYTE_INTERLEAVED) {
int nChans = (cmP->isDefaultCompatCM ? 4 : hintP->numChans);
@@ -2250,6 +2254,11 @@ allocateArray(JNIEnv *env, BufImageS_t *imageP,
hintP->sStride,
(unsigned char *)dataP
+ hintP->dataOffset);
+ if (*mlibImagePP == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
+ JNI_ABORT);
+ return -1;
+ }
}
else if ((hintP->packing & SHORT_INTERLEAVED) == SHORT_INTERLEAVED) {
*mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_SHORT,
@@ -2259,6 +2268,11 @@ allocateArray(JNIEnv *env, BufImageS_t *imageP,
imageP->raster.scanlineStride*2,
(unsigned short *)dataP
+ hintP->channelOffset);
+ if (*mlibImagePP == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
+ JNI_ABORT);
+ return -1;
+ }
}
else {
/* Release the data array */
@@ -2358,6 +2372,11 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
width, height,
rasterP->scanlineStride*4,
(unsigned char *)dataP + offset);
+ if (*mlibImagePP == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
+ JNI_ABORT);
+ return -1;
+ }
*dataPP = dataP;
return 0;
case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_SAMPLES:
@@ -2386,6 +2405,11 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
width, height,
rasterP->scanlineStride,
(unsigned char *)dataP + offset);
+ if (*mlibImagePP == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
+ JNI_ABORT);
+ return -1;
+ }
*dataPP = dataP;
return 0;
case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_SAMPLES:
@@ -2416,6 +2440,11 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
width, height,
rasterP->scanlineStride*2,
(unsigned char *)dataP + offset);
+ if (*mlibImagePP == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
+ JNI_ABORT);
+ return -1;
+ }
*dataPP = dataP;
return 0;
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h
index d66c5df9976f..9800e99adf95 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h
@@ -4,7 +4,7 @@
*
* ANSI-specific configuration file (specification only).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h
index 16eab9048fce..24a9161e2f11 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h
@@ -4,7 +4,7 @@
*
* Build macros of the FreeType 2 library.
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h
index a0a1a410b681..a4e9c7f3e831 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h
@@ -4,7 +4,7 @@
*
* User-selectable configuration macros (specification only).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h
index f846b4456c11..1c63e8d654c1 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h
@@ -5,7 +5,7 @@
* ANSI-specific library and header configuration file (specification
* only).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h
index a0b892ece4bc..4ab4c0c78bd3 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h
@@ -4,7 +4,7 @@
*
* FreeType integer types definitions.
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h
index bd350851d560..ac48995320fe 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h
@@ -4,7 +4,7 @@
*
* Mac/OS X support configuration header.
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h
index 9f28b3947374..c76509a99f7f 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h
@@ -4,7 +4,7 @@
*
* Define a set of compiler macros used in public FreeType headers.
*
- * Copyright (C) 2020-2025 by
+ * Copyright (C) 2020-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h b/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h
index e8a1b1e2f3ea..68a9e0c6bd2c 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h
@@ -4,7 +4,7 @@
*
* FreeType high-level API and common types (specification only).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -5169,7 +5169,7 @@ FT_BEGIN_HEADER
*/
#define FREETYPE_MAJOR 2
#define FREETYPE_MINOR 14
-#define FREETYPE_PATCH 2
+#define FREETYPE_PATCH 3
/**************************************************************************
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h
index 62a856ccbd71..876a8a55cb9f 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h
@@ -4,7 +4,7 @@
*
* Quick computation of advance widths (specification only).
*
- * Copyright (C) 2008-2025 by
+ * Copyright (C) 2008-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h
index 348b4b3a268d..0107d94986bc 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h
@@ -4,7 +4,7 @@
*
* FreeType exact bbox computation (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h
index ab142249217c..fb1f31864861 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h
@@ -4,7 +4,7 @@
*
* FreeType API for accessing BDF-specific strings (specification).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h
index a22d43adf14b..1df5f29aca1a 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h
@@ -4,7 +4,7 @@
*
* FreeType utility functions for bitmaps (specification).
*
- * Copyright (C) 2004-2025 by
+ * Copyright (C) 2004-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h
index 7cda8ff3f39a..f9744716d986 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h
@@ -4,7 +4,7 @@
*
* FreeType API for accessing CID font information (specification).
*
- * Copyright (C) 2007-2025 by
+ * Copyright (C) 2007-2026 by
* Dereg Clegg and Michael Toftdal.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h
index 129b1a23fb03..1cce74711573 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h
@@ -4,7 +4,7 @@
*
* FreeType's glyph color management (specification).
*
- * Copyright (C) 2018-2025 by
+ * Copyright (C) 2018-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h
index b65a06ab69b0..39635f86c3ec 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h
@@ -4,7 +4,7 @@
*
* FreeType API for controlling driver modules (specification only).
*
- * Copyright (C) 2017-2025 by
+ * Copyright (C) 2017-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h b/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h
index 3e591bede8d8..ce3817e55df3 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h
@@ -4,7 +4,7 @@
*
* FreeType error codes (specification).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h b/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h
index eca494f90c08..218c4610e218 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h
@@ -4,7 +4,7 @@
*
* FreeType error code handling (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h
index 5df82447d0ee..2ea0c5f4d708 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h
@@ -4,7 +4,7 @@
*
* Support functions for font formats.
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h
index 77e5a7e7bfd3..632b536b471a 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h
@@ -4,7 +4,7 @@
*
* Access of TrueType's 'gasp' table (specification).
*
- * Copyright (C) 2007-2025 by
+ * Copyright (C) 2007-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h
index 3691781cf523..e967110e81eb 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h
@@ -4,7 +4,7 @@
*
* FreeType convenience functions to handle glyphs (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h
index e26c334c11a1..f0c1550f61d3 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h
@@ -4,7 +4,7 @@
*
* Gzip-compressed stream support.
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h
index a4dc724f3499..1fff76b20d91 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h
@@ -5,7 +5,7 @@
* FreeType glyph image formats and default raster interface
* (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h
index 2233044754e6..32637fe5af02 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h
@@ -4,7 +4,7 @@
*
* FreeType incremental loading (specification).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h
index 37bb5e1b8fb1..72dbe2acccbb 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h
@@ -5,7 +5,7 @@
* FreeType API for color filtering of subpixel bitmap glyphs
* (specification).
*
- * Copyright (C) 2006-2025 by
+ * Copyright (C) 2006-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h
index 14958b0ff371..74b3ffaee9f1 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h
@@ -4,7 +4,7 @@
*
* Generic list support for FreeType (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h
index d155171136c2..1670b12caf51 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h
@@ -4,7 +4,7 @@
*
* Additional debugging APIs.
*
- * Copyright (C) 2020-2025 by
+ * Copyright (C) 2020-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h
index c5ac49101a47..a3ed7fba6f73 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h
@@ -4,7 +4,7 @@
*
* Additional Mac-specific API.
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h
index ff0bbab59f95..fb239bda1223 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h
@@ -4,7 +4,7 @@
*
* FreeType variation font interface (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h
index 2669e4a03b33..7af33e33afee 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h
@@ -4,7 +4,7 @@
*
* FreeType modules public interface (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h
index 8e2ef2f01f87..7c1b1fd3c040 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h
@@ -4,7 +4,7 @@
*
* FreeType module error offsets (specification).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h
index 2545ca8486b6..68cf65bae159 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h
@@ -5,7 +5,7 @@
* Support for the FT_Outline type used to store glyph shapes of
* most scalable font formats (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h
index 94dcd6399a6e..3f6af8681f3b 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h
@@ -4,7 +4,7 @@
*
* FreeType API for possible FT_Parameter tags (specification only).
*
- * Copyright (C) 2017-2025 by
+ * Copyright (C) 2017-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h
index cc3102073b1d..292c797cce58 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h
@@ -4,7 +4,7 @@
*
* FreeType renderer modules public interface (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h
index fdb89f24ccca..f609eb2d76a7 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h
@@ -4,7 +4,7 @@
*
* FreeType size objects management (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h
index 99728574db64..f5511495f048 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h
@@ -7,7 +7,7 @@
*
* This is _not_ used to retrieve glyph names!
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h
index 2c4761c768d4..c7f1d4643f04 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h
@@ -4,7 +4,7 @@
*
* FreeType path stroker (specification).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h
index 93499a4b4f10..90b4b19c25f8 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h
@@ -5,7 +5,7 @@
* FreeType synthesizing code for emboldening and slanting
* (specification).
*
- * Copyright (C) 2000-2025 by
+ * Copyright (C) 2000-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h
index 1de9f8e603dd..2ad3d7286dc7 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h
@@ -4,7 +4,7 @@
*
* FreeType low-level system interface definition (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h b/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h
index ed7bd06a78fc..ebedc3a8d1eb 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h
@@ -4,7 +4,7 @@
*
* FreeType trigonometric functions (specification).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h
index e207c5ebe09a..97ddcde65aa6 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h
@@ -4,7 +4,7 @@
*
* FreeType simple types definitions (specification only).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h
index 987e704e9b0f..a22d8af7cd98 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h
@@ -4,7 +4,7 @@
*
* High-level 'autohint' module-specific interface (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h
index 26ee43bb9a9f..8d6acbce7acb 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h
@@ -4,7 +4,7 @@
*
* Basic OpenType/CFF object type definitions (specification).
*
- * Copyright (C) 2017-2025 by
+ * Copyright (C) 2017-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h
index 754122fa6467..d474dcf40ea7 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h
@@ -5,7 +5,7 @@
* Basic OpenType/CFF type definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h
index e6d0166d8882..4863d6de75e8 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h
@@ -4,7 +4,7 @@
*
* Compiler-specific macro definitions used internally by FreeType.
*
- * Copyright (C) 2020-2025 by
+ * Copyright (C) 2020-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h
index 16a732224ef6..4c4943164a38 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h
@@ -4,7 +4,7 @@
*
* Arithmetic computations (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h
index d7facf40d127..62b9ec2f79c7 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h
@@ -4,7 +4,7 @@
*
* Debugging and logging component (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h
index 24be4dad36be..d52fc84f0fd9 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h
@@ -4,7 +4,7 @@
*
* FreeType internal font driver interface (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h
index 8f2a54c015b6..902135e460cd 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h
@@ -4,7 +4,7 @@
*
* The FreeType glyph loader (specification).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h
index c75c33f28959..ca840cb510be 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h
@@ -4,7 +4,7 @@
*
* The FreeType memory management macros (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h
index be3747bbf94a..a4db9c487b75 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h
@@ -5,7 +5,7 @@
* OpenType Variations type definitions for internal use
* with the multi-masters service (specification).
*
- * Copyright (C) 2022-2025 by
+ * Copyright (C) 2022-2026 by
* David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and
* Dominik Röttsches.
*
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h
index d4d7bc00fe90..4fa4991dd88c 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h
@@ -4,7 +4,7 @@
*
* The FreeType private base classes (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h
index 18a954d22f50..5967199a3bc9 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h
@@ -4,7 +4,7 @@
*
* Get and set properties of PostScript drivers (specification).
*
- * Copyright (C) 2017-2025 by
+ * Copyright (C) 2017-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h
index e077f98bfb96..d0bb6b5bb002 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h
@@ -4,7 +4,7 @@
*
* Embedded resource forks accessor (specification).
*
- * Copyright (C) 2004-2025 by
+ * Copyright (C) 2004-2026 by
* Masatake YAMATO and Redhat K.K.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h
index ce11bba19b26..9c6406c82d8a 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h
@@ -4,7 +4,7 @@
*
* The FreeType services (specification only).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h
index 20c1dd7c4b00..d60cd481c893 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h
@@ -4,7 +4,7 @@
*
* Stream handling (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h
index 3fd592800e2a..798896cd0c82 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h
@@ -4,7 +4,7 @@
*
* Tracing handling (specification only).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h
index 03a726c82cb5..fbcf2c63efaf 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h
@@ -4,7 +4,7 @@
*
* FreeType validation support (specification).
*
- * Copyright (C) 2004-2025 by
+ * Copyright (C) 2004-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h
index 344be0f19a70..ee574fef11b1 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h
@@ -5,7 +5,7 @@
* Auxiliary functions and data structures related to PostScript fonts
* (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h
index 96c5d84f058c..e7adcd380587 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h
@@ -6,7 +6,7 @@
* recorders (specification only). These are used to support native
* T1/T2 hints in the 'type1', 'cid', and 'cff' font drivers.
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h
index 5bd51da23f4c..52212cc7a2b8 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h
@@ -4,7 +4,7 @@
*
* The FreeType BDF services (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h
index c97bf84fb2e0..ab29dede537e 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h
@@ -4,7 +4,7 @@
*
* The FreeType CFF tables loader service (specification).
*
- * Copyright (C) 2017-2025 by
+ * Copyright (C) 2017-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h
index 748a8caf887c..9063211ee017 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h
@@ -4,7 +4,7 @@
*
* The FreeType CID font services (specification).
*
- * Copyright (C) 2007-2025 by
+ * Copyright (C) 2007-2026 by
* Derek Clegg and Michael Toftdal.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h
index 690fdc2a24fa..770381da67a1 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h
@@ -4,7 +4,7 @@
*
* The FreeType font format service (specification only).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h
index 7128d6f3d7aa..6020f9f78a6e 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h
@@ -4,7 +4,7 @@
*
* The FreeType glyph dictionary services (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h
index 1ca3e0a031b6..056114e6f8cc 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h
@@ -4,7 +4,7 @@
*
* FreeType API for validating TrueTypeGX/AAT tables (specification).
*
- * Copyright (C) 2004-2025 by
+ * Copyright (C) 2004-2026 by
* Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h
index 8a3d59bec6d6..7a06a01e8f01 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h
@@ -4,7 +4,7 @@
*
* The FreeType Kerning service (specification).
*
- * Copyright (C) 2006-2025 by
+ * Copyright (C) 2006-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h
index 4dde3a8151af..b6559d2b1ad3 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h
@@ -4,7 +4,7 @@
*
* The FreeType services for metrics variations (specification).
*
- * Copyright (C) 2016-2025 by
+ * Copyright (C) 2016-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h
index 9be133e2db0b..fd851dba120f 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h
@@ -4,7 +4,7 @@
*
* The FreeType Multiple Masters and GX var services (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h
index 933e5de98da5..487dca3f0435 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h
@@ -4,7 +4,7 @@
*
* The FreeType OpenType validation service (specification).
*
- * Copyright (C) 2004-2025 by
+ * Copyright (C) 2004-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h
index c81b6a68a8bc..94cd695eb00f 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h
@@ -4,7 +4,7 @@
*
* Internal PFR service functions (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h
index 33864ebc3443..d99f4f681ef4 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h
@@ -4,7 +4,7 @@
*
* The FreeType PostScript name services (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h
index 0eb79c885d81..b6cba4c7f42b 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h
@@ -4,7 +4,7 @@
*
* The FreeType property service (specification).
*
- * Copyright (C) 2012-2025 by
+ * Copyright (C) 2012-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h
index 8f85d12157cc..310eb53f3330 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h
@@ -4,7 +4,7 @@
*
* The FreeType PostScript charmap service (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h
index 83de04478dfc..78725a48fa5d 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h
@@ -4,7 +4,7 @@
*
* The FreeType PostScript info service (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h
index 9bf5e3473c45..0ce5aca13761 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h
@@ -4,7 +4,7 @@
*
* The FreeType SFNT table loading service (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h
index fc9b0aeb8e39..14921304ebfc 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h
@@ -4,7 +4,7 @@
*
* The FreeType TrueType/sfnt cmap extra information service.
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* Masatake YAMATO, Redhat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h
index 979e9ea102e2..d4a9bab6ded8 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h
@@ -4,7 +4,7 @@
*
* The FreeType TrueType engine query service (specification).
*
- * Copyright (C) 2006-2025 by
+ * Copyright (C) 2006-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h
index e4f54c100377..528238024baa 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h
@@ -4,7 +4,7 @@
*
* The FreeType TrueType glyph service.
*
- * Copyright (C) 2007-2025 by
+ * Copyright (C) 2007-2026 by
* David Turner.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h
index ff887ffdc038..e5a3a6649b6f 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h
@@ -4,7 +4,7 @@
*
* The FreeType Windows FNT/FONT service (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h
index adba2178877e..cc1ac7a6e4cf 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h
@@ -4,7 +4,7 @@
*
* High-level 'sfnt' driver interface (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h
index 20c73b2fbd2f..3a4ca314ddb2 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h
@@ -4,7 +4,7 @@
*
* Interface of ot-svg module (specification only).
*
- * Copyright (C) 2022-2025 by
+ * Copyright (C) 2022-2026 by
* David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h
index 5b26e4620d0c..e39076f19563 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h
@@ -5,7 +5,7 @@
* Basic Type1/Type2 type definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h
index d0e5eee89bc4..65341a3a259e 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h
@@ -5,7 +5,7 @@
* Basic SFNT/TrueType type definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h
index 7d5b7df0fa19..b8ef95e27aad 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h
@@ -5,7 +5,7 @@
* Basic WOFF/WOFF2 type definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h b/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h
index 326bbcd01534..42330a703b02 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h
@@ -4,7 +4,7 @@
*
* Interface for OT-SVG support related things (specification).
*
- * Copyright (C) 2022-2025 by
+ * Copyright (C) 2022-2026 by
* David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h b/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h
index fe769f607faa..badfdf40762d 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h
@@ -5,7 +5,7 @@
* Basic Type 1/Type 2 tables definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h b/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h
index 3ef61091cc96..76ddb6f0a51a 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h
@@ -4,7 +4,7 @@
*
* TrueType name ID definitions (specification only).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -169,7 +169,7 @@ FT_BEGIN_HEADER
#define TT_MAC_ID_LAOTIAN 22
#define TT_MAC_ID_GEORGIAN 23
#define TT_MAC_ID_ARMENIAN 24
-#define TT_MAC_ID_MALDIVIAN 25
+#define TT_MAC_ID_MALDIVIAN 25 /* TrueType version 1.66 */
#define TT_MAC_ID_SIMPLIFIED_CHINESE 25
#define TT_MAC_ID_TIBETAN 26
#define TT_MAC_ID_MONGOLIAN 27
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h b/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h
index aa4336435d93..a2ec304483a5 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h
@@ -5,7 +5,7 @@
* Basic SFNT/TrueType tables definitions and interface
* (specification only).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h b/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h
index 56bb0a3ee5e8..3be3e2ff9055 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h
@@ -4,7 +4,7 @@
*
* Tags for TrueType and OpenType tables (specification only).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/ft2build.h b/src/java.desktop/share/native/libfreetype/include/ft2build.h
index 3008aea7cf5a..ffbf4a1e6ad1 100644
--- a/src/java.desktop/share/native/libfreetype/include/ft2build.h
+++ b/src/java.desktop/share/native/libfreetype/include/ft2build.h
@@ -4,7 +4,7 @@
*
* FreeType 2 build and setup macros.
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.c b/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.c
index a1aa45914d07..6940baf68cc3 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.c
@@ -4,7 +4,7 @@
*
* Auto-fitter routines to adjust components based on charcode (body).
*
- * Copyright (C) 2023-2025 by
+ * Copyright (C) 2023-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Written by Craig White .
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.h b/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.h
index 4837451ae4cf..85dbfaad29e0 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.h
@@ -4,7 +4,7 @@
*
* Auto-fitter routines to adjust components based on charcode (header).
*
- * Copyright (C) 2023-2025 by
+ * Copyright (C) 2023-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Written by Craig White .
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c
index a6219bdfe41c..77c8389ec7fe 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c
@@ -7,7 +7,7 @@
*
* Auto-fitter data for blue strings (body).
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin
index 786c6b3b9e6f..70b7e025214d 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin
@@ -4,7 +4,7 @@
*
* Auto-fitter data for blue strings (body).
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat
index f6e96ff8189d..e62754fc7e06 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat
@@ -2,7 +2,7 @@
//
// Auto-fitter data for blue strings.
//
-// Copyright (C) 2013-2025 by
+// Copyright (C) 2013-2026 by
// David Turner, Robert Wilhelm, and Werner Lemberg.
//
// This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h
index 5bb8406dc2b4..f124eedee4d1 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h
@@ -7,7 +7,7 @@
*
* Auto-fitter data for blue strings (specification).
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin
index dbac14548d55..931c5010606c 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin
@@ -4,7 +4,7 @@
*
* Auto-fitter data for blue strings (specification).
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c
index 7086601838c3..7a1cc32c9d46 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for CJK writing system (body).
*
- * Copyright (C) 2006-2025 by
+ * Copyright (C) 2006-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h
index bd1b39358e08..98681868a85e 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for CJK writing system (specification).
*
- * Copyright (C) 2006-2025 by
+ * Copyright (C) 2006-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h b/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h
index b93bcd1a2c54..d60e0050bece 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h
@@ -4,7 +4,7 @@
*
* Auto-fitter coverages (specification only).
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c
index 8613544f913c..f9d1dd38dba4 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c
@@ -5,7 +5,7 @@
* Auto-fitter dummy routines to be used if no hinting should be
* performed (body).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h
index 78a79439d95a..14546b1e50e2 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h
@@ -5,7 +5,7 @@
* Auto-fitter dummy routines to be used if no hinting should be
* performed (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h b/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h
index f3093fc90dfb..3d7538ba2d88 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h
@@ -4,7 +4,7 @@
*
* Autofitter error codes (specification only).
*
- * Copyright (C) 2005-2025 by
+ * Copyright (C) 2005-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c
index e74d81411619..ff6903cc174a 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c
@@ -4,7 +4,7 @@
*
* Auto-fitter routines to compute global hinting values (body).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h
index dc061159492e..c4dd93358398 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h
@@ -5,7 +5,7 @@
* Auto-fitter routines to compute global hinting values
* (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c
index 11faa655f62f..376912a5d121 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines (body).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h
index 46b3ed3366f2..84244d6f5c70 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c
index a2cd14f88171..29b6d22ed650 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for Indic writing system (body).
*
- * Copyright (C) 2007-2025 by
+ * Copyright (C) 2007-2026 by
* Rahul Bhalerao , .
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h
index a2e825e9f868..df4892a9f1ce 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h
@@ -5,7 +5,7 @@
* Auto-fitter hinting routines for Indic writing system
* (specification).
*
- * Copyright (C) 2007-2025 by
+ * Copyright (C) 2007-2026 by
* Rahul Bhalerao , .
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c
index 4a42d9194745..73addf28eb42 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for latin writing system (body).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h
index 82b4b0d480d4..b6bdc5177f7f 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h
@@ -5,7 +5,7 @@
* Auto-fitter hinting routines for latin writing system
* (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c
index 4e2ac1f1ce3f..8ac7b53856bc 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c
@@ -4,7 +4,7 @@
*
* Auto-fitter glyph loading routines (body).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h
index a04b4df0b3bd..8efd0fd57e99 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h
@@ -4,7 +4,7 @@
*
* Auto-fitter glyph loading routines (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c
index 22d85a889e80..57d5d47dfbda 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
*
* Auto-fitter module implementation (body).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h
index c62421ef696f..1f8a68122d3b 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h
@@ -4,7 +4,7 @@
*
* Auto-fitter module implementation (specification).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c
index fd54948f3a5b..4d0755decb20 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c
@@ -4,7 +4,7 @@
*
* Auto-fitter Unicode script ranges (body).
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h
index fa00eb750469..f29369451286 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h
@@ -4,7 +4,7 @@
*
* Auto-fitter Unicode script ranges (specification).
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h b/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h
index 5c4cbbcb922a..d071ed68b7e5 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h
@@ -4,7 +4,7 @@
*
* Auto-fitter scripts (specification only).
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c
index f3c0744fd9d6..5c9e5376ad05 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c
@@ -4,7 +4,7 @@
*
* HarfBuzz interface for accessing OpenType features (body).
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h
index 757368fc9c0f..6e73b9fb2ebd 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h
@@ -4,7 +4,7 @@
*
* HarfBuzz interface for accessing OpenType features (specification).
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h b/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h
index 206232efe250..e7a7fe531baa 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h
@@ -4,7 +4,7 @@
*
* Auto-fitter styles (specification only).
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h b/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h
index 959640a12ec2..a3a881eedeb0 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
*
* Auto-fitter types (specification only).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h b/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h
index 12fa7a27a2b5..ddebdcd1e785 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h
@@ -4,7 +4,7 @@
*
* Auto-fitter writing system declarations (specification only).
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h b/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h
index 1752697b375a..720c2dc50c90 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h
@@ -4,7 +4,7 @@
*
* Auto-fitter writing systems iterator (specification only).
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.c b/src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.c
index 3c145d046403..ed438da6afe6 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.c
@@ -4,7 +4,7 @@
*
* FreeType-HarfBuzz bridge (body).
*
- * Copyright (C) 2025 by
+ * Copyright (C) 2025-2026 by
* Behdad Esfahbod.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.h b/src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.h
index 95914deb8d36..d2cc0482eb6b 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.h
@@ -4,7 +4,7 @@
*
* FreeType-HarfBuzz bridge (specification).
*
- * Copyright (C) 2025 by
+ * Copyright (C) 2025-2026 by
* Behdad Esfahbod.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c b/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c
index 7b965c62d584..648583466662 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c
@@ -4,7 +4,7 @@
*
* Quick computation of advance widths (body).
*
- * Copyright (C) 2008-2025 by
+ * Copyright (C) 2008-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbase.h b/src/java.desktop/share/native/libfreetype/src/base/ftbase.h
index 66f091165fe4..952ac51d503a 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftbase.h
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftbase.h
@@ -4,7 +4,7 @@
*
* Private functions used in the `base' module (specification).
*
- * Copyright (C) 2008-2025 by
+ * Copyright (C) 2008-2026 by
* David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c b/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c
index feccdee5dd78..4641ce27e829 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c
@@ -4,7 +4,7 @@
*
* FreeType bbox computation (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c b/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c
index 364f881e4355..f88cbc11e636 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c
@@ -4,7 +4,7 @@
*
* FreeType utility functions for bitmaps (body).
*
- * Copyright (C) 2004-2025 by
+ * Copyright (C) 2004-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c b/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c
index 7d6e12e2543e..d233dba3d6bf 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c
@@ -4,7 +4,7 @@
*
* Arithmetic computations (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcid.c b/src/java.desktop/share/native/libfreetype/src/base/ftcid.c
index 35cd0fcd2be7..878c666e1298 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftcid.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftcid.c
@@ -4,7 +4,7 @@
*
* FreeType API for accessing CID font information.
*
- * Copyright (C) 2007-2025 by
+ * Copyright (C) 2007-2026 by
* Derek Clegg and Michael Toftdal.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c b/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c
index 90b02b7d2de9..ed6b5f0599fc 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c
@@ -4,7 +4,7 @@
*
* FreeType's glyph color management (body).
*
- * Copyright (C) 2018-2025 by
+ * Copyright (C) 2018-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c b/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c
index 7f54e759b162..0335f142562a 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c
@@ -4,7 +4,7 @@
*
* Memory debugger (body).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c b/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c
index c615f29e521d..27091a557984 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c
@@ -4,7 +4,7 @@
*
* Debugging and logging component (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c b/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c
index 7f4f14ffdb07..99e8c2b17dfe 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c
@@ -4,7 +4,7 @@
*
* FreeType utility file for font formats (body).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c b/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c
index 3a95752ffaa8..58d5144a9e02 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c
@@ -4,7 +4,7 @@
*
* FreeType utility file to access FSType data (body).
*
- * Copyright (C) 2008-2025 by
+ * Copyright (C) 2008-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c b/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c
index 2202240b57eb..3c13456802e6 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c
@@ -4,7 +4,7 @@
*
* Access of TrueType's `gasp' table (body).
*
- * Copyright (C) 2007-2025 by
+ * Copyright (C) 2007-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c b/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c
index 47781bc4d5cb..bd66e61d1c28 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c
@@ -4,7 +4,7 @@
*
* The FreeType glyph loader (body).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c b/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c
index 6138cfeec2cc..096f4d965e87 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c
@@ -4,7 +4,7 @@
*
* FreeType convenience functions to handle glyphs (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -856,9 +856,9 @@
goto Exit;
/* in case of success, copy the bitmap to the glyph bitmap */
- error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy );
- if ( error )
- goto Exit;
+ bitmap->left = dummy.bitmap_left;
+ bitmap->top = dummy.bitmap_top;
+ bitmap->bitmap = dummy.bitmap;
/* copy advance */
bitmap->root.advance = glyph->advance;
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftinit.c b/src/java.desktop/share/native/libfreetype/src/base/ftinit.c
index 37d7f87bcb95..b20289316dc2 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftinit.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftinit.c
@@ -4,7 +4,7 @@
*
* FreeType initialization layer (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c b/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c
index 51c6fd48a1b5..9adbf7518f60 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c
@@ -4,7 +4,7 @@
*
* FreeType API for color filtering of subpixel bitmap glyphs (body).
*
- * Copyright (C) 2006-2025 by
+ * Copyright (C) 2006-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftmac.c b/src/java.desktop/share/native/libfreetype/src/base/ftmac.c
index 37d97be18385..7251a4cb9621 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftmac.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftmac.c
@@ -8,7 +8,7 @@
* This file is for Mac OS X only; see builds/mac/ftoldmac.c for
* classic platforms built by MPW.
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftmm.c b/src/java.desktop/share/native/libfreetype/src/base/ftmm.c
index 9e67001406ca..0d3bf3b77d84 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftmm.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftmm.c
@@ -4,7 +4,7 @@
*
* Multiple Master font support (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c b/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c
index 323dd5efac2c..f9f64c40fec3 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c
@@ -4,7 +4,7 @@
*
* The FreeType private base classes (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -385,6 +385,7 @@
FT_Pos y_shift = 0;
FT_Pos x_left, y_top;
FT_Pos width, height, pitch;
+ FT_Bool ret;
if ( slot->format == FT_GLYPH_FORMAT_SVG )
@@ -495,6 +496,20 @@
width = pbox.xMax - pbox.xMin;
height = pbox.yMax - pbox.yMin;
+ /* Flag the width or height unsuitable for rendering. */
+ /* The limit is based on the ppem value when available. */
+ /* FT_Renderer modules should check the return value. */
+ ret = FT_BOOL( width >= 0x10000 || height >= 0x10000 ||
+ pbox.xMin < -0x1000000 || pbox.xMax >= 0x1000000 ||
+ pbox.yMin < -0x1000000 || pbox.yMax >= 0x1000000 ||
+ ( slot->face &&
+ ( width > 10 * slot->face->size->metrics.x_ppem ||
+ height > 10 * slot->face->size->metrics.y_ppem ) ) );
+
+ if ( ret )
+ FT_TRACE3(( "ft_glyphslot_preset_bitmap: [%ld %ld %ld %ld]\n",
+ pbox.xMin, pbox.yMin, pbox.xMax, pbox.yMax ));
+
switch ( pixel_mode )
{
case FT_PIXEL_MODE_MONO:
@@ -524,31 +539,7 @@
bitmap->rows = (unsigned int)height;
bitmap->pitch = pitch;
- /* Flag the bounding box size unsuitable for rendering. */
- /* FT_Renderer modules should check the return value. */
- /* The limit is based on the ppem value when available. */
- {
- FT_Face face = slot->face;
- FT_Pos xlim = 0x8000;
- FT_Pos ylim = 0x8000;
-
-
- if ( face )
- {
- xlim = FT_MIN( xlim, 10 * face->size->metrics.x_ppem );
- ylim = FT_MIN( ylim, 10 * face->size->metrics.y_ppem );
- }
-
- if ( pbox.xMin < -xlim || pbox.xMax >= xlim ||
- pbox.yMin < -ylim || pbox.yMax >= ylim )
- {
- FT_TRACE3(( "ft_glyphslot_preset_bitmap: [%ld %ld %ld %ld]\n",
- pbox.xMin, pbox.yMin, pbox.xMax, pbox.yMax ));
- return 1;
- }
- }
-
- return 0;
+ return ret;
}
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c b/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c
index 8a15b03eb83a..a0a1549adaaa 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c
@@ -4,7 +4,7 @@
*
* FreeType outline management (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c b/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c
index 664bc34deea3..3f149eb607fd 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c
@@ -5,7 +5,7 @@
* FreeType API for checking patented TrueType bytecode instructions
* (body). Obsolete, retained for backward compatibility.
*
- * Copyright (C) 2007-2025 by
+ * Copyright (C) 2007-2026 by
* David Turner.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c b/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c
index 0631cd63f62d..13f6c5102ccd 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c
@@ -5,7 +5,7 @@
* Get and set properties of PostScript drivers (body).
* See `ftdriver.h' for available properties.
*
- * Copyright (C) 2017-2025 by
+ * Copyright (C) 2017-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c b/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c
index 1e241f4f95bd..fbb8ace7173a 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c
@@ -4,7 +4,7 @@
*
* Embedded resource forks accessor (body).
*
- * Copyright (C) 2004-2025 by
+ * Copyright (C) 2004-2026 by
* Masatake YAMATO and Redhat K.K.
*
* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c b/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c
index 34a67a148fc0..d8274cccd406 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c
@@ -7,7 +7,7 @@
*
* This is _not_ used to retrieve glyph names!
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftstream.c b/src/java.desktop/share/native/libfreetype/src/base/ftstream.c
index c04a0506def6..b08a1a9b6580 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftstream.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftstream.c
@@ -4,7 +4,7 @@
*
* I/O stream support (body).
*
- * Copyright (C) 2000-2025 by
+ * Copyright (C) 2000-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c b/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c
index 591f18eaa832..e599ecaf46f5 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c
@@ -4,7 +4,7 @@
*
* FreeType path stroker (body).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -693,6 +693,7 @@
Fail:
num_points = 0;
num_contours = 0;
+ error = FT_THROW( Invalid_Outline );
goto Exit;
}
@@ -2251,7 +2252,7 @@
FT_Stroker stroker,
FT_Bool destroy )
{
- FT_Error error = FT_ERR( Invalid_Argument );
+ FT_Error error = FT_THROW( Invalid_Argument );
FT_Glyph glyph = NULL;
@@ -2283,7 +2284,9 @@
if ( error )
goto Fail;
- FT_Stroker_GetCounts( stroker, &num_points, &num_contours );
+ error = FT_Stroker_GetCounts( stroker, &num_points, &num_contours );
+ if ( error )
+ goto Fail;
FT_Outline_Done( glyph->library, outline );
@@ -2326,7 +2329,7 @@
FT_Bool inside,
FT_Bool destroy )
{
- FT_Error error = FT_ERR( Invalid_Argument );
+ FT_Error error = FT_THROW( Invalid_Argument );
FT_Glyph glyph = NULL;
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c b/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c
index 08bc17422021..23960eda3a96 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c
@@ -4,7 +4,7 @@
*
* FreeType synthesizing code for emboldening and slanting (body).
*
- * Copyright (C) 2000-2025 by
+ * Copyright (C) 2000-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c b/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c
index 186119d5581d..be9159f6141d 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c
@@ -4,7 +4,7 @@
*
* ANSI-specific FreeType low-level system interface (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c b/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c
index 29eff639c51c..baa47eba0841 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c
@@ -4,7 +4,7 @@
*
* FreeType trigonometric functions (body).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/fttype1.c b/src/java.desktop/share/native/libfreetype/src/base/fttype1.c
index 77978df674da..f9a46801f3ce 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/fttype1.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/fttype1.c
@@ -4,7 +4,7 @@
*
* FreeType utility file for PS names support (body).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftutil.c b/src/java.desktop/share/native/libfreetype/src/base/ftutil.c
index f83c43948936..5d8fc7b9bf37 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftutil.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftutil.c
@@ -4,7 +4,7 @@
*
* FreeType utility file for memory and list management (body).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c
index cb69abdb90ff..75e2420d99e9 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c
@@ -4,7 +4,7 @@
*
* CFF character mapping table (cmap) support (body).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h
index 60e16d948753..e812e7a89e51 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h
@@ -4,7 +4,7 @@
*
* CFF character mapping table (cmap) support (specification).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c
index 44ff44aecbd9..18c7b879048b 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c
@@ -4,7 +4,7 @@
*
* OpenType font driver implementation (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h
index 52a1e727a6af..2f3c58b67d77 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h
@@ -4,7 +4,7 @@
*
* High-level OpenType driver interface (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h b/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h
index 7491886c7be8..ca1158c0dfdc 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h
@@ -4,7 +4,7 @@
*
* CFF error codes (specification only).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c
index e8bab3c1e334..0c986930cee6 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c
@@ -4,7 +4,7 @@
*
* OpenType Glyph Loader (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h
index 662bb7cff53f..eb4b5f30b5ea 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h
@@ -4,7 +4,7 @@
*
* OpenType Glyph Loader (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffload.c b/src/java.desktop/share/native/libfreetype/src/cff/cffload.c
index 39d662eb4345..9d067cfeeb83 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffload.c
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffload.c
@@ -4,7 +4,7 @@
*
* OpenType and CFF data/program tables loader (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffload.h b/src/java.desktop/share/native/libfreetype/src/cff/cffload.h
index fdc132c8f3f9..ab02ca2d7f64 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffload.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffload.h
@@ -4,7 +4,7 @@
*
* OpenType & CFF data/program tables loader (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c
index 9e00943a95df..c6ba35e27344 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c
@@ -4,7 +4,7 @@
*
* OpenType objects manager (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -16,7 +16,6 @@
*/
-
#include
#include
#include
@@ -45,6 +44,7 @@
#define CFF_fixedToInt( x ) \
( (FT_Short)( ( (x) + 0x8000U ) >> 16 ) )
+
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h
index 982dcd64dd03..c6ab805c5be9 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h
@@ -4,7 +4,7 @@
*
* OpenType objects manager (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -20,8 +20,6 @@
#define CFFOBJS_H_
-
-
FT_BEGIN_HEADER
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c
index 864b2490b3b4..fadc3258c960 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c
@@ -4,7 +4,7 @@
*
* CFF token stream parser (body)
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h
index 47cceb1a4a07..1daf548cbcca 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h
@@ -4,7 +4,7 @@
*
* CFF token stream parser (specification)
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h b/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h
index a7ee1cb3fe76..0eadc7118fb1 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h
@@ -4,7 +4,7 @@
*
* CFF token definitions (specification only).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h b/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h
index 1591979d370c..00497b796b38 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h
+++ b/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h
@@ -4,7 +4,7 @@
*
* CID error codes (specification only).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c
index 249ede5757d9..cc68b4a96009 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 Glyph Loader (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -193,6 +193,37 @@
p = (FT_Byte*)glyph_data.pointer;
fd_select = cid_get_offset( &p, cid->fd_bytes );
+ if ( fd_select >= cid->num_dicts )
+ {
+ /*
+ * fd_select == 0xFF is often used to indicate that the CID
+ * has no charstring to be rendered, similar to GID = 0xFFFF
+ * in TrueType fonts.
+ */
+ if ( ( cid->fd_bytes == 1 && fd_select == 0xFFU ) ||
+ ( cid->fd_bytes == 2 && fd_select == 0xFFFFU ) )
+ {
+ FT_TRACE1(( "cid_load_glyph: fail for glyph index %u:\n",
+ glyph_index ));
+ FT_TRACE1(( " FD number %lu is the maximum\n",
+ fd_select ));
+ FT_TRACE1(( " integer fitting into %u byte%s\n",
+ cid->fd_bytes, cid->fd_bytes == 1 ? "" : "s" ));
+ }
+ else
+ {
+ FT_TRACE0(( "cid_load_glyph: fail for glyph index %u:\n",
+ glyph_index ));
+ FT_TRACE0(( " FD number %lu is larger\n",
+ fd_select ));
+ FT_TRACE0(( " than number of dictionaries (%u)\n",
+ cid->num_dicts ));
+ }
+
+ error = FT_THROW( Invalid_Offset );
+ goto Exit;
+ }
+
glyph_length = glyph_data.length - cid->fd_bytes;
if ( !FT_QALLOC( charstring, glyph_length ) )
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h
index cef96073ded4..51b16c75944b 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h
@@ -4,7 +4,7 @@
*
* OpenType Glyph Loader (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidload.c b/src/java.desktop/share/native/libfreetype/src/cid/cidload.c
index bb1bf13e2219..1a0e6b1561e0 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidload.c
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidload.c
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 font loader (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidload.h b/src/java.desktop/share/native/libfreetype/src/cid/cidload.h
index 659dd0e378ca..cef7d1c9a6a1 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidload.h
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidload.h
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 font loader (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c
index 634bbf2f135e..2d11609598b8 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c
@@ -4,7 +4,7 @@
*
* CID objects manager (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h
index 800268efa2f3..406646231278 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h
@@ -4,7 +4,7 @@
*
* CID objects manager (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c
index 4d1ba335960a..fb936bd48d9a 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 parser (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h
index 6ae2e542394c..555245230b92 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 parser (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c
index a3a587c57bfb..ab188776e2fd 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c
@@ -4,7 +4,7 @@
*
* CID driver interface (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h
index 55d0b8a0d9b5..a4ddccec8082 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h
@@ -4,7 +4,7 @@
*
* High-level CID driver interface (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h b/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h
index d40ebfab86df..22136310cdf7 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h
@@ -4,7 +4,7 @@
*
* CID token definitions (specification only).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c
index b813efde4eb3..1cc8ab29d46a 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c
@@ -4,7 +4,7 @@
*
* AFM parser (body).
*
- * Copyright (C) 2006-2025 by
+ * Copyright (C) 2006-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h
index add8597717d1..02a9617b8dc4 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h
@@ -4,7 +4,7 @@
*
* AFM parser (specification).
*
- * Copyright (C) 2006-2025 by
+ * Copyright (C) 2006-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c
index 17bdd23c7d46..908a81126153 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c
@@ -4,7 +4,7 @@
*
* PostScript CFF (Type 2) decoding routines (body).
*
- * Copyright (C) 2017-2025 by
+ * Copyright (C) 2017-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h
index e72ec043baaa..0836a642b2ff 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h
@@ -4,7 +4,7 @@
*
* PostScript CFF (Type 2) decoding routines (specification).
*
- * Copyright (C) 2017-2025 by
+ * Copyright (C) 2017-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h b/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h
index 0d7fe2b6121a..5766482d1b70 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h
@@ -4,7 +4,7 @@
*
* PS auxiliary module error codes (specification only).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c
index 942804190c52..2f9eb87484cb 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c
@@ -4,7 +4,7 @@
*
* FreeType auxiliary PostScript module implementation (body).
*
- * Copyright (C) 2000-2025 by
+ * Copyright (C) 2000-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h
index 4a5ebc1b6079..e7fa15c34b79 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h
@@ -4,7 +4,7 @@
*
* FreeType auxiliary PostScript module implementation (specification).
*
- * Copyright (C) 2000-2025 by
+ * Copyright (C) 2000-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c
index 4567d3f3c069..3a054cbbf6d8 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c
@@ -4,7 +4,7 @@
*
* Some convenience conversions (body).
*
- * Copyright (C) 2006-2025 by
+ * Copyright (C) 2006-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h
index 63735af411f2..fc123faea4d7 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h
@@ -4,7 +4,7 @@
*
* Some convenience conversions (specification).
*
- * Copyright (C) 2006-2025 by
+ * Copyright (C) 2006-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c
index 8159fd6ef159..5019f9925c1e 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c
@@ -4,7 +4,7 @@
*
* Auxiliary functions for PostScript fonts (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h
index 277aa1247c50..04205f891b17 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h
@@ -4,7 +4,7 @@
*
* Auxiliary functions for PostScript fonts (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c
index 66493b68123b..686ca7abdfa3 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c
@@ -4,7 +4,7 @@
*
* Type 1 character map support (body).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h
index 114bfbb04103..be66a0c7f6f4 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h
@@ -4,7 +4,7 @@
*
* Type 1 character map support (specification).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c
index c3fb343d4c9b..ece512412da9 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c
@@ -4,7 +4,7 @@
*
* PostScript Type 1 decoding routines (body).
*
- * Copyright (C) 2000-2025 by
+ * Copyright (C) 2000-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -458,6 +458,7 @@
FT_Bool large_int;
FT_Fixed seed;
+ FT_UInt len_buildchar;
T1_Hints_Funcs hinter;
#ifdef FT_DEBUG_LEVEL_TRACE
@@ -483,13 +484,16 @@
hinter = (T1_Hints_Funcs)builder->hints_funcs;
- /* a font that reads BuildCharArray without setting */
- /* its values first is buggy, but ... */
- FT_ASSERT( ( decoder->len_buildchar == 0 ) ==
- ( decoder->buildchar == NULL ) );
+ /* Cache `len_buildchar` locally so that a stray write to the */
+ /* decoder structure during charstring processing cannot bypass */
+ /* the bounds checks in callothersubr 19/24/25 handlers. */
+ len_buildchar = decoder->len_buildchar;
- if ( decoder->buildchar && decoder->len_buildchar > 0 )
- FT_ARRAY_ZERO( decoder->buildchar, decoder->len_buildchar );
+ FT_ASSERT( ( len_buildchar == 0 ) ==
+ ( decoder->buildchar == NULL ) );
+
+ if ( decoder->buildchar && len_buildchar > 0 )
+ FT_ARRAY_ZERO( decoder->buildchar, len_buildchar );
zone->base = charstring_base;
limit = zone->limit = charstring_base + charstring_len;
@@ -969,8 +973,8 @@
idx = Fix2Int( top[0] );
- if ( idx < 0 ||
- (FT_UInt)idx + blend->num_designs > decoder->len_buildchar )
+ if ( idx < 0 ||
+ (FT_UInt)idx + blend->num_designs > len_buildchar )
goto Unexpected_OtherSubr;
ft_memcpy( &decoder->buildchar[idx],
@@ -1037,7 +1041,7 @@
idx = Fix2UInt( top[1] );
- if ( idx >= decoder->len_buildchar )
+ if ( idx >= len_buildchar )
goto Unexpected_OtherSubr;
decoder->buildchar[idx] = top[0];
@@ -1058,7 +1062,7 @@
idx = Fix2UInt( top[0] );
- if ( idx >= decoder->len_buildchar )
+ if ( idx >= len_buildchar )
goto Unexpected_OtherSubr;
top[0] = decoder->buildchar[idx];
@@ -1204,14 +1208,14 @@
#ifdef FT_DEBUG_LEVEL_TRACE
- if ( decoder->len_buildchar > 0 )
+ if ( len_buildchar > 0 )
{
FT_UInt i;
FT_TRACE4(( "BuildCharArray = [ " ));
- for ( i = 0; i < decoder->len_buildchar; i++ )
+ for ( i = 0; i < len_buildchar; i++ )
FT_TRACE4(( "%ld ", decoder->buildchar[i] ));
FT_TRACE4(( "]\n" ));
@@ -1523,6 +1527,15 @@
goto Syntax_Error;
}
+ /* Ensure that popping an unknown 'othersubr' result does not */
+ /* push the stack pointer past the end of the stack array. */
+ if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings:"
+ " stack overflow in pop\n" ));
+ goto Syntax_Error;
+ }
+
unknown_othersubr_result_cnt--;
top++; /* `push' the operand to callothersubr onto the stack */
break;
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h
index 7b913f55dff7..1b5d5205a865 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h
@@ -4,7 +4,7 @@
*
* PostScript Type 1 decoding routines (specification).
*
- * Copyright (C) 2000-2025 by
+ * Copyright (C) 2000-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c
index e053dba17b24..f169fc3459df 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c
@@ -4,7 +4,7 @@
*
* PostScript hinting algorithm (body).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h
index f4aa85405598..95d41b49aaf0 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h
@@ -4,7 +4,7 @@
*
* PostScript hinting algorithm (specification).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c
index a772b66f3097..2e4efea068ce 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c
@@ -5,7 +5,7 @@
* PostScript hinter global hinting management (body).
* Inspired by the new auto-hinter module.
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h
index 555e99facb2d..0158b92ab9de 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h
@@ -4,7 +4,7 @@
*
* PostScript hinter global hinting management.
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c
index c9f4a94fe98a..f6b2e2df94c0 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c
@@ -4,7 +4,7 @@
*
* FreeType PostScript hinter module implementation (body).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h
index de9c398e9fb0..d68ef9a87369 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h
@@ -4,7 +4,7 @@
*
* PostScript hinter module interface (specification).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h
index 7076664ddde9..96bc3a31756f 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h
@@ -4,7 +4,7 @@
*
* PS Hinter error codes (specification only).
*
- * Copyright (C) 2003-2025 by
+ * Copyright (C) 2003-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c
index 13754313fbb2..f14c9c7cbda1 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c
@@ -4,7 +4,7 @@
*
* FreeType PostScript hints recorder (body).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h
index a79069f98d2f..0b644f5b9644 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h
@@ -4,7 +4,7 @@
*
* Postscript (Type1/Type2) hints recorder (specification).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c
index c5d71edad881..5409c61fafab 100644
--- a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c
+++ b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c
@@ -4,7 +4,7 @@
*
* psnames module implementation (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h
index 482fd0a36d18..7a619d83fb39 100644
--- a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h
+++ b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h
@@ -4,7 +4,7 @@
*
* High-level psnames module interface (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h b/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h
index 17987f9cd4f6..bef9e797c806 100644
--- a/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h
+++ b/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h
@@ -4,7 +4,7 @@
*
* PS names module error codes (specification only).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h b/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h
index 65ce6c0b47f1..8a32aac325f2 100644
--- a/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h
+++ b/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h
@@ -4,7 +4,7 @@
*
* PostScript glyph names.
*
- * Copyright (C) 2005-2025 by
+ * Copyright (C) 2005-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h b/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h
index 9d97223e94ee..cf96cd09ed5f 100644
--- a/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h
+++ b/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h
@@ -5,7 +5,7 @@
* Miscellaneous macros for stand-alone rasterizer (specification
* only).
*
- * Copyright (C) 2005-2025 by
+ * Copyright (C) 2005-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c
index 807d444e7aa4..4165800a1aac 100644
--- a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c
+++ b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c
@@ -4,7 +4,7 @@
*
* The FreeType glyph rasterizer (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -546,7 +546,7 @@
*
*/
- if ( High )
+ if ( High && ras.bTop + ras.bRight < 256 )
{
ras.precision_bits = 12;
ras.precision_step = 256;
@@ -1351,17 +1351,9 @@
/* this arc has no given direction, split it! */
Split_Conic( arc );
arc += 2;
+ continue;
}
- else if ( y1 == y3 )
- {
- /* this arc is flat, advance position */
- /* and pop it from the Bezier stack */
- arc -= 2;
-
- ras.lastX = x3;
- ras.lastY = y3;
- }
- else
+ else if ( y1 != y3 )
{
/* the arc is y-monotonous, either ascending or descending */
/* detect a change of direction */
@@ -1389,13 +1381,16 @@
if ( Bezier_Down( RAS_VARS 2, arc, Split_Conic,
ras.minY, ras.maxY ) )
goto Fail;
- arc -= 2;
-
- ras.lastX = x3;
- ras.lastY = y3;
}
- } while ( arc >= arcs );
+ ras.lastX = x3;
+ ras.lastY = y3;
+
+ if ( arc == arcs )
+ break;
+ arc -= 2;
+
+ } while ( 1 );
return SUCCESS;
@@ -1498,17 +1493,9 @@
/* this arc has no given direction, split it! */
Split_Cubic( arc );
arc += 3;
+ continue;
}
- else if ( y1 == y4 )
- {
- /* this arc is flat, advance position */
- /* and pop it from the Bezier stack */
- arc -= 3;
-
- ras.lastX = x4;
- ras.lastY = y4;
- }
- else
+ else if ( y1 != y4 )
{
state_bez = y1 < y4 ? Ascending_State : Descending_State;
@@ -1535,13 +1522,16 @@
if ( Bezier_Down( RAS_VARS 3, arc, Split_Cubic,
ras.minY, ras.maxY ) )
goto Fail;
- arc -= 3;
-
- ras.lastX = x4;
- ras.lastY = y4;
}
- } while ( arc >= arcs );
+ ras.lastX = x4;
+ ras.lastY = y4;
+
+ if ( arc == arcs )
+ break;
+ arc -= 3;
+
+ } while ( 1 );
return SUCCESS;
diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h
index 64499bf955bf..e20184ddc8ea 100644
--- a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h
+++ b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h
@@ -4,7 +4,7 @@
*
* The FreeType glyph rasterizer (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c
index 3fa008704e54..6b28cb0bf8d8 100644
--- a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c
+++ b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c
@@ -4,7 +4,7 @@
*
* The FreeType glyph rasterizer interface (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h
index d838a942b049..92249a0cb9f6 100644
--- a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h
+++ b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h
@@ -4,7 +4,7 @@
*
* The FreeType glyph rasterizer interface (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h b/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h
index 39d82a8051aa..744d179cd8c2 100644
--- a/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h
+++ b/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h
@@ -4,7 +4,7 @@
*
* monochrome renderer error codes (specification only).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c
index 24fb34555988..e588e6b380b4 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c
@@ -4,7 +4,7 @@
*
* PNG Bitmap glyph support.
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* Google, Inc.
* Written by Stuart Gill and Behdad Esfahbod.
*
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h
index c59199e60dfe..f187b639a113 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h
@@ -4,7 +4,7 @@
*
* PNG Bitmap glyph support.
*
- * Copyright (C) 2013-2025 by
+ * Copyright (C) 2013-2026 by
* Google, Inc.
* Written by Stuart Gill and Behdad Esfahbod.
*
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c
index 32291e23e368..4046b1a0cdbc 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c
@@ -4,7 +4,7 @@
*
* High-level SFNT driver interface (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h
index be4e33166c1c..e9eed184b7fd 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h
@@ -4,7 +4,7 @@
*
* High-level SFNT driver interface (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h
index 2da4ac776b07..05b259c1bfcb 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h
@@ -4,7 +4,7 @@
*
* SFNT error codes (specification only).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c
index 6af35787e85e..fc855cbb6b95 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c
@@ -4,7 +4,7 @@
*
* SFNT object management (base).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h
index 8c38b7279501..a27ad7064acc 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h
@@ -4,7 +4,7 @@
*
* SFNT object management (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c
index 015c7b78b4d6..b8a3030d9cb0 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c
@@ -4,7 +4,7 @@
*
* WOFF format management (base).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h
index df7ace5c2094..a563fcc682ae 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h
@@ -4,7 +4,7 @@
*
* WOFFF format management (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c
index 41c233597b8e..013e30fc520b 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c
@@ -4,7 +4,7 @@
*
* WOFF2 format management (base).
*
- * Copyright (C) 2019-2025 by
+ * Copyright (C) 2019-2026 by
* Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h
index 588761d0c8ea..e0296d82603e 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h
@@ -4,7 +4,7 @@
*
* WOFFF2 format management (specification).
*
- * Copyright (C) 2019-2025 by
+ * Copyright (C) 2019-2026 by
* Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c
index 91b02344224e..f5837e65e86d 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c
@@ -4,7 +4,7 @@
*
* TrueType character mapping table (cmap) support (body).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h
index 645e9e37e0c6..fdb34f525e3c 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h
@@ -4,7 +4,7 @@
*
* TrueType character mapping table (cmap) support (specification).
*
- * Copyright (C) 2002-2025 by
+ * Copyright (C) 2002-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h
index 65807bb7378a..c17ac5bba15d 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h
@@ -4,7 +4,7 @@
*
* TT CMAP classes definitions (specification only).
*
- * Copyright (C) 2009-2025 by
+ * Copyright (C) 2009-2026 by
* Oran Agra and Mickey Gabel.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c
index 7929b7aaf4c8..b22e279b3465 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c
@@ -4,7 +4,7 @@
*
* TrueType and OpenType colored glyph layer support (body).
*
- * Copyright (C) 2018-2025 by
+ * Copyright (C) 2018-2026 by
* David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg.
*
* Originally written by Shao Yu Zhang .
@@ -236,8 +236,10 @@
p1 = (FT_Byte*)( table + base_glyphs_offset_v1 );
num_base_glyphs_v1 = FT_PEEK_ULONG( p1 );
- if ( ( table_size - base_glyphs_offset_v1 ) / BASE_GLYPH_PAINT_RECORD_SIZE
- < num_base_glyphs_v1 )
+ /* Account for 4 byte numBaseGlyphPaintRecords at the beginning of */
+ /* the BaseGlyphPaintRecord array. */
+ if ( ( table_size - base_glyphs_offset_v1 - 4 ) /
+ BASE_GLYPH_PAINT_RECORD_SIZE < num_base_glyphs_v1 )
goto InvalidTable;
colr->num_base_glyphs_v1 = num_base_glyphs_v1;
@@ -451,20 +453,14 @@
FT_UInt *acolor_index,
FT_LayerIterator* iterator )
{
- Colr* colr = (Colr*)face->colr;
- BaseGlyphRecord glyph_record;
-
-
- if ( !colr )
- return 0;
-
- if ( !iterator->p )
+ if ( !iterator->p ) /* first call to function */
{
- FT_ULong offset;
+ Colr* colr = (Colr*)face->colr;
+ BaseGlyphRecord glyph_record;
- /* first call to function */
- iterator->layer = 0;
+ if ( !colr )
+ return 0;
if ( !find_base_glyph_record( colr->base_glyphs,
colr->num_base_glyphs,
@@ -472,21 +468,18 @@
&glyph_record ) )
return 0;
- if ( glyph_record.num_layers )
- iterator->num_layers = glyph_record.num_layers;
- else
- return 0;
-
- offset = LAYER_SIZE * glyph_record.first_layer_index;
- if ( offset + LAYER_SIZE * glyph_record.num_layers > colr->table_size )
+ if ( glyph_record.num_layers == 0 ||
+ glyph_record.first_layer_index + glyph_record.num_layers >
+ colr->num_layers )
return 0;
- iterator->p = colr->layers + offset;
+ iterator->num_layers = glyph_record.num_layers;
+ iterator->layer = 0;
+ iterator->p = colr->layers +
+ LAYER_SIZE * glyph_record.first_layer_index;
}
- if ( iterator->layer >= iterator->num_layers ||
- iterator->p < colr->layers ||
- iterator->p >= ( (FT_Byte*)colr->table + colr->table_size ) )
+ if ( iterator->layer >= iterator->num_layers )
return 0;
*aglyph_index = FT_NEXT_USHORT( iterator->p );
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h
index 3913acc74d59..c7bf1f2a4a78 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h
@@ -4,7 +4,7 @@
*
* TrueType and OpenType colored glyph layer support (specification).
*
- * Copyright (C) 2018-2025 by
+ * Copyright (C) 2018-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Originally written by Shao Yu Zhang .
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c
index 6d1208f6af24..04e2db1eab58 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c
@@ -4,7 +4,7 @@
*
* TrueType and OpenType color palette support (body).
*
- * Copyright (C) 2018-2025 by
+ * Copyright (C) 2018-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Originally written by Shao Yu Zhang .
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h
index a0b4c9d927fa..5c2e660e13dc 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h
@@ -4,7 +4,7 @@
*
* TrueType and OpenType color palette support (specification).
*
- * Copyright (C) 2018-2025 by
+ * Copyright (C) 2018-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Originally written by Shao Yu Zhang .
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c
index 76618b0d3bb7..65b249ff4cdb 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c
@@ -4,7 +4,7 @@
*
* Routines to parse and access the 'kern' table for kerning (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h
index e0075dce61d6..8cc912a79e53 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h
@@ -5,7 +5,7 @@
* Routines to parse and access the 'kern' table for kerning
* (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c
index 0c257ce4d314..e17d07a971ce 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c
@@ -5,7 +5,7 @@
* Load the basic TrueType tables, i.e., tables that can be either in
* TTF or OTF fonts (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h
index e3666c901b14..0a0aab24ce6c 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h
@@ -5,7 +5,7 @@
* Load the basic TrueType tables, i.e., tables that can be either in
* TTF or OTF fonts (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c
index 541d84474708..60dce87d841a 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c
@@ -4,7 +4,7 @@
*
* Load the metrics tables common to TTF and OTF fonts (body).
*
- * Copyright (C) 2006-2025 by
+ * Copyright (C) 2006-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h
index 1ee84507f153..618e04ffd29d 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h
@@ -4,7 +4,7 @@
*
* Load the metrics tables common to TTF and OTF fonts (specification).
*
- * Copyright (C) 2006-2025 by
+ * Copyright (C) 2006-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c
index 4246b6c8eff1..98603e115eab 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c
@@ -5,7 +5,7 @@
* PostScript name table processing for TrueType and OpenType fonts
* (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h
index a11b66968547..896118015e13 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h
@@ -5,7 +5,7 @@
* PostScript name table processing for TrueType and OpenType fonts
* (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c
index 34e45619817c..1655e40b6814 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c
@@ -4,7 +4,7 @@
*
* TrueType and OpenType embedded bitmap support (body).
*
- * Copyright (C) 2005-2025 by
+ * Copyright (C) 2005-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Copyright 2013 by Google, Inc.
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h
index 7427149d68f1..8fd452232640 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h
@@ -4,7 +4,7 @@
*
* TrueType and OpenType embedded bitmap support (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c
index 0f9e3889aabf..1c3779d9f34c 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c
@@ -4,7 +4,7 @@
*
* WOFF2 Font table tags (base).
*
- * Copyright (C) 2019-2025 by
+ * Copyright (C) 2019-2026 by
* Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h
index e223022962ea..200262d38639 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h
@@ -4,7 +4,7 @@
*
* WOFF2 Font table tags (specification).
*
- * Copyright (C) 2019-2025 by
+ * Copyright (C) 2019-2026 by
* Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c
index 3c387aea0ac1..0f7b63937d70 100644
--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c
+++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c
@@ -4,7 +4,7 @@
*
* A new `perfect' anti-aliasing renderer (body).
*
- * Copyright (C) 2000-2025 by
+ * Copyright (C) 2000-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h
index e463e5b3eb8f..99c7383e76e8 100644
--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h
+++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h
@@ -4,7 +4,7 @@
*
* FreeType smooth renderer declaration
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h
index 8d5068549faa..2f2276bd58c8 100644
--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h
+++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h
@@ -4,7 +4,7 @@
*
* smooth renderer error codes (specification only).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c
index 5a7a852a619a..7378e6adc46d 100644
--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c
+++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
*
* Anti-aliasing renderer interface (body).
*
- * Copyright (C) 2000-2025 by
+ * Copyright (C) 2000-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h
index f76708ae7010..56c7ac70b5c9 100644
--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h
+++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h
@@ -4,7 +4,7 @@
*
* Anti-aliasing renderer interface (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c
index 6369d83d6d5a..90d6e8105787 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c
@@ -4,7 +4,7 @@
*
* TrueType font driver implementation (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h
index 943eaae3482f..c00bba066e30 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h
@@ -4,7 +4,7 @@
*
* High-level TrueType driver interface (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h b/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h
index 631dbf5a80fc..1ae4b087ac8e 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h
@@ -4,7 +4,7 @@
*
* TrueType error codes (specification only).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c
index 4dd68ab10197..dcff7c3bb713 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c
@@ -4,7 +4,7 @@
*
* TrueType Glyph Loader (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -1185,9 +1185,7 @@
/* make room for phantom points */
- error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
- outline->n_points + 4,
- 0 );
+ error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader, 4, 0 );
if ( error )
return error;
@@ -1425,6 +1423,14 @@
FT_TRACE5(( " nesting level: %u\n", recurse_count ));
#endif
+ /* arbitrary recursion limit */
+ if ( recurse_count > 100 )
+ {
+ FT_TRACE4(( "load_truetype_glyph: recursion depth exceeded\n" ));
+ error = FT_THROW( Invalid_Composite );
+ goto Exit;
+ }
+
/* some fonts have an incorrect value of `maxComponentDepth' */
if ( recurse_count > face->max_profile.maxComponentDepth )
{
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h
index 39d6ae3664ca..3d6a762d1f7f 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h
@@ -4,7 +4,7 @@
*
* TrueType Glyph Loader (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c
index f8842795f14d..d392e9bc1c23 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c
@@ -4,7 +4,7 @@
*
* TrueType GX Font Variation loader
*
- * Copyright (C) 2004-2025 by
+ * Copyright (C) 2004-2026 by
* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h
index 568c8027bbf8..8a59c0cd6e60 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h
@@ -4,7 +4,7 @@
*
* TrueType GX Font Variation loader (specification)
*
- * Copyright (C) 2004-2025 by
+ * Copyright (C) 2004-2026 by
* David Turner, Robert Wilhelm, Werner Lemberg and George Williams.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c
index f46cc77fe5f0..f850bc418e7b 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c
@@ -4,7 +4,7 @@
*
* TrueType bytecode interpreter (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h
index 5cdc8f59f1a2..05ac831dfd13 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h
@@ -4,7 +4,7 @@
*
* TrueType bytecode interpreter (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c
index 2aedbd842c1c..dc897688584a 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c
@@ -4,7 +4,7 @@
*
* Objects manager (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -734,6 +734,10 @@
/* a `loca' table is not valid */
if ( face->glyf_len && FT_ERR_EQ( error, Table_Missing ) )
goto Exit;
+ /* if both `glyf' and `loca' tables are missing, */
+ /* we don't have a valid font file either */
+ if ( face->glyf_len == 0 && FT_ERR_EQ( error, Locations_Missing ) )
+ goto Bad_Format;
if ( error )
goto Exit;
}
@@ -1057,9 +1061,23 @@
exec->maxFunc = 0;
exec->maxIns = 0;
- /* XXX: We reserve a little more elements on the stack to deal */
- /* with broken fonts like arialbs, courbs, timesbs, etc. */
- exec->stackSize = maxp->maxStackElements + 32;
+ /* We reserve extra elements on the stack to deal with broken fonts. */
+ /* */
+ /* Some fonts (e.g., `Rubik-Italic.ttf`) have buggy hinting bytecode */
+ /* that pushes more values than `maxStackElements` declared in the */
+ /* 'maxp' table. For example, `Rubik-Italic.ttf`'s 'prep' program */
+ /* pushes 255 values but `maxStackElements` is only set to 153. */
+ /* */
+ /* To alleviate this situation we increase the value of */
+ /* `maxStackElements` based on a percentage of `maxStackElements`, */
+ /* with a minimum of 128 extra slots. This allows most broken fonts */
+ /* to work without completely disabling hinting, while adding only a */
+ /* small overhead for correctly authored fonts. */
+
+ /* Use 50% more than declared, with minimum safety margin of 128. */
+ exec->stackSize = maxp->maxStackElements +
+ FT_MAX( maxp->maxStackElements / 2, 128 );
+
exec->storeSize = maxp->maxStorage;
exec->cvtSize = face->cvt_size;
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h
index 28d6c7d855f8..9b2f412ac475 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
*
* Objects manager (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c
index 827454d85744..5b0a3944d6a7 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
*
* TrueType-specific tables loader (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h
index bb4d3c9cc557..ad0a9eb7a6d5 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h
@@ -4,7 +4,7 @@
*
* TrueType-specific tables loader (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c
index b1a0d23bed62..cc94a0d4a456 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c
@@ -4,7 +4,7 @@
*
* AFM support for Type 1 fonts (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h
index 92ff627dd0d9..f31c9d100f0a 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h
@@ -4,7 +4,7 @@
*
* AFM support for Type 1 fonts (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c
index 5ded7714021e..1d7a342708dd 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c
@@ -4,7 +4,7 @@
*
* Type 1 driver interface (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h
index 1cc3d24e7dd2..2869adab6e74 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h
@@ -4,7 +4,7 @@
*
* High-level Type 1 driver interface (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h b/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h
index 46bddbc30fd8..efe53be1f4cd 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h
@@ -4,7 +4,7 @@
*
* Type 1 error codes (specification only).
*
- * Copyright (C) 2001-2025 by
+ * Copyright (C) 2001-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c
index b9bc0b56ce88..dd9b6cd80fc2 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c
@@ -4,7 +4,7 @@
*
* Type 1 Glyph Loader (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h
index 6bedd132c5fb..b3de427a2f3d 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h
@@ -4,7 +4,7 @@
*
* Type 1 Glyph Loader (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1load.c b/src/java.desktop/share/native/libfreetype/src/type1/t1load.c
index 0f11445bef06..1d095f8ac1f8 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1load.c
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1load.c
@@ -4,7 +4,7 @@
*
* Type 1 font loader (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1load.h b/src/java.desktop/share/native/libfreetype/src/type1/t1load.h
index 2cd8241968d1..39d4b94e9dc8 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1load.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1load.h
@@ -4,7 +4,7 @@
*
* Type 1 font loader (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c
index 7f25208f875d..4ee0a591096b 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c
@@ -4,7 +4,7 @@
*
* Type 1 objects manager (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h
index 6c71977c154d..f152f630a86e 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h
@@ -4,7 +4,7 @@
*
* Type 1 objects manager (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c
index ef643e298f42..a9b8d18a6ff6 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c
@@ -4,7 +4,7 @@
*
* Type 1 parser (body).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h
index f4ad426e9e1d..ebd7c3fb3404 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h
@@ -4,7 +4,7 @@
*
* Type 1 parser (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h b/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h
index a526406a411a..745351a34c95 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h
@@ -4,7 +4,7 @@
*
* Type 1 tokenizer (specification).
*
- * Copyright (C) 1996-2025 by
+ * Copyright (C) 1996-2026 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh
index 011b5ad55206..37bb8a8f9458 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh
@@ -525,7 +525,13 @@ struct ColorLine
hb_paint_extend_t get_extend () const
{
- return (hb_paint_extend_t) (unsigned int) extend;
+ switch ((unsigned int) extend)
+ {
+ case Extend::EXTEND_REPEAT: return HB_PAINT_EXTEND_REPEAT;
+ case Extend::EXTEND_REFLECT: return HB_PAINT_EXTEND_REFLECT;
+ case Extend::EXTEND_PAD:
+ default: return HB_PAINT_EXTEND_PAD;
+ }
}
HB_INTERNAL static hb_paint_extend_t static_get_extend (hb_color_line_t *color_line,
@@ -1520,9 +1526,9 @@ struct PaintComposite
void paint_glyph (hb_paint_context_t *c) const
{
TRACE_PAINT (this);
- c->funcs->push_group (c->data);
+ c->funcs->push_group_for (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
c->recurse (this+backdrop);
- c->funcs->push_group (c->data);
+ c->funcs->push_group_for (c->data, (hb_paint_composite_mode_t) (int) mode);
c->recurse (this+src);
c->funcs->pop_group (c->data, (hb_paint_composite_mode_t) (int) mode);
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
@@ -1814,10 +1820,7 @@ struct ClipList
{
auto *rec = clips.as_array ().bsearch (gid);
if (rec)
- {
- rec->get_extents (extents, this, instancer);
- return true;
- }
+ return rec->get_extents (extents, this, instancer);
return false;
}
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh
index 71417fdf3cf1..f79e236bce91 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh
@@ -172,7 +172,7 @@ struct CPAL
bool has_data () const { return numPalettes; }
- unsigned int get_size () const
+ size_t get_size () const
{ return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); }
unsigned int get_palette_count () const { return numPalettes; }
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh
index b77486a43403..f6e6c5e3a9d8 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh
@@ -79,7 +79,7 @@ struct SBIXGlyph
struct SBIXStrike
{
- static unsigned int get_size (unsigned num_glyphs)
+ static size_t get_size (unsigned num_glyphs)
{ return min_size + num_glyphs * HBUINT32::static_size; }
bool sanitize (hb_sanitize_context_t *c) const
diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh
index 9249abf70758..a0fd2c88d0a4 100644
--- a/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh
+++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh
@@ -27,7 +27,12 @@
#include "../../../hb-open-type.hh"
#include "../../../hb-blob.hh"
+#include "../../../hb-limits.hh"
+#include "../../../hb-map.hh"
#include "../../../hb-paint.hh"
+#include "../../../hb-zlib.hh"
+#include
+#include
/*
* SVG -- SVG (Scalable Vector Graphics)
@@ -39,12 +44,62 @@
namespace OT {
+static inline hb_blob_t *
+hb_ot_svg_reference_normalized_blob (hb_blob_t *image,
+ const char **svg,
+ unsigned *len)
+{
+ hb_blob_t *blob = hb_blob_reference (image);
+ unsigned data_len = 0;
+ const char *data = hb_blob_get_data (blob, &data_len);
+
+ if (!data || !data_len)
+ goto fail;
+
+ if (hb_blob_is_gzip (data, data_len))
+ {
+ uint32_t expected_size = 0;
+ if (hb_gzip_get_uncompressed_size (data, data_len, &expected_size) &&
+ unlikely ((size_t) expected_size > (size_t) HB_SVG_MAX_DOCUMENT_SIZE))
+ goto fail;
+
+ hb_blob_t *uncompressed = hb_blob_decompress_gzip (blob,
+ HB_SVG_MAX_DOCUMENT_SIZE);
+ if (!uncompressed)
+ goto fail;
+
+ hb_blob_destroy (blob);
+ blob = uncompressed;
+ data = hb_blob_get_data (blob, &data_len);
+ if (!data || !data_len)
+ goto fail;
+ }
+
+ if (unlikely ((size_t) data_len > (size_t) HB_SVG_MAX_DOCUMENT_SIZE))
+ goto fail;
+
+ if (svg) *svg = data;
+ if (len) *len = data_len;
+ return blob;
+
+fail:
+ hb_blob_destroy (blob);
+ if (svg) *svg = nullptr;
+ if (len) *len = 0;
+ return nullptr;
+}
struct SVGDocumentIndexEntry
{
int cmp (hb_codepoint_t g) const
{ return g < startGlyphID ? -1 : g > endGlyphID ? 1 : 0; }
+ hb_codepoint_t get_start_glyph () const
+ { return startGlyphID; }
+
+ hb_codepoint_t get_end_glyph () const
+ { return endGlyphID; }
+
hb_blob_t *reference_blob (hb_blob_t *svg_blob, unsigned int index_offset) const
{
return hb_blob_create_sub_blob (svg_blob,
@@ -78,13 +133,50 @@ struct SVG
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_SVG;
+ struct svg_id_span_t
+ {
+ const char *p;
+ unsigned len;
+
+ bool operator == (const svg_id_span_t &o) const
+ {
+ return len == o.len && !memcmp (p, o.p, len);
+ }
+
+ uint32_t hash () const
+ {
+ uint32_t h = hb_hash (len);
+ for (unsigned i = 0; i < len; i++)
+ h = h * 33u + (unsigned char) p[i];
+ return h;
+ }
+ };
+
+ struct svg_defs_entry_t
+ {
+ svg_id_span_t id;
+ unsigned start;
+ unsigned end;
+ };
+
+ struct svg_doc_cache_t
+ {
+ hb_blob_t *blob = nullptr;
+ const char *svg = nullptr;
+ unsigned len = 0;
+ hb_vector_t defs_entries;
+ hb_codepoint_t start_glyph = HB_CODEPOINT_INVALID;
+ hb_codepoint_t end_glyph = HB_CODEPOINT_INVALID;
+ hb_vector_t> glyph_spans;
+ hb_hashmap_t> id_spans;
+ };
+
bool has_data () const { return svgDocEntries; }
struct accelerator_t
{
- accelerator_t (hb_face_t *face)
- { table = hb_sanitize_context_t ().reference_table