diff -Nru openjdk-17-17.0.4+8/debian/changelog openjdk-17-17.0.5+8/debian/changelog --- openjdk-17-17.0.4+8/debian/changelog 2022-07-22 08:57:45.000000000 +0000 +++ openjdk-17-17.0.5+8/debian/changelog 2022-10-24 16:44:41.000000000 +0000 @@ -1,14 +1,55 @@ -openjdk-17 (17.0.4+8-1~20.04) focal-security; urgency=medium +openjdk-17 (17.0.5+8-2ubuntu1~20.04) focal-security; urgency=medium - * OpenJDK 17.0.4 release, build 8. - * Addresses security issues: CVE-2022-34169, CVE-2022-21541, - CVE-2022-21540, CVE-2022-21549. + * Build 17.0.5+8 for Ubuntu 20.04 LTS. - -- Matthias Klose Fri, 22 Jul 2022 10:57:45 +0200 + -- Matthias Klose Mon, 24 Oct 2022 18:44:41 +0200 + +openjdk-17 (17.0.5+8-2ubuntu1) kinetic-security; urgency=medium + + * Handle jtreg package name for backports. + + -- Matthias Klose Mon, 24 Oct 2022 18:33:55 +0200 + +openjdk-17 (17.0.5+8-2) unstable; urgency=medium + + * Fix the binary-indep only build. + + -- Matthias Klose Wed, 19 Oct 2022 16:23:50 +0200 + +openjdk-17 (17.0.5+8-1) unstable; urgency=high + + * OpenJDK 17.0.5+8 (release). + * Security fixes + - JDK-8289366: Improve HTTP/2 client usage. + - JDK-8288508: Enhance ECDSA usage. + - JDK-8286918: Better HttpServer service. + - JDK-8287446: Enhance icon presentations. + - JDK-8286910: Improve JNDI lookups. + - JDK-8286511: Improve macro allocation. + - JDK-8286526: Improve NTLM support. + - JDK-8286533: Key X509 usages. + - JDK-8286077: Wider MultiByte conversions. + - JDK-8286519: Better memory handling. + - JDK-8285662: Better permission resolution. + - JDK-8282252: Improve BigInteger/Decimal validation. + * Build using GCC 12 in recent development distros. + + -- Matthias Klose Wed, 19 Oct 2022 06:59:58 +0200 openjdk-17 (17.0.4+8-1) unstable; urgency=high * OpenJDK 17.0.4+8 (release). + * Security fixes + - JDK-8272243: Improve DER parsing. + - JDK-8272249: Better properties of loaded Properties. + - JDK-8273056, JDK-8283875, CVE-2022-21549: java.util.random does not + correctly sample exponential or Gaussian distributions. + - JDK-8277608: Address IP Addressing. + - JDK-8281859, CVE-2022-21540: Improve class compilation. + - JDK-8281866, CVE-2022-21541: Enhance MethodHandle invocations. + - JDK-8283190: Improve MIDI processing. + - JDK-8284370: Improve zlib usage. + - JDK-8285407, CVE-2022-34169: Improve Xalan supports. * Disable the reproducible-copyright-headers patch. * Only try to re-run failed tests once instead of three times. diff -Nru openjdk-17-17.0.4+8/debian/rules openjdk-17-17.0.5+8/debian/rules --- openjdk-17-17.0.4+8/debian/rules 2022-07-22 08:57:45.000000000 +0000 +++ openjdk-17-17.0.5+8/debian/rules 2022-10-24 16:44:41.000000000 +0000 @@ -157,7 +157,13 @@ NJOBS = $(subst parallel=,,$(filter parallel=%,$(subst $(COMMA), ,$(DEB_BUILD_OPTIONS)))) endif -jtreg_pkg = jtreg6 +ifneq (,$(filter $(distrel), sid bookworm bullseye focal jammy kinetic)) + jtreg_pkg = jtreg6 +else ifneq (,$(filter $(distrel), sid bookworm bullseye)) + jtreg_pkg = jtreg +else + jtreg_pkg = +endif with_check = $(if $(findstring nocheck, $(DEB_BUILD_OPTIONS)),,yes) ifneq (,$(filter $(DEB_HOST_ARCH), alpha armel mipsel mips64el riscv64)) @@ -264,14 +270,18 @@ export CC = $(DEB_HOST_GNU_TYPE)-gcc-10 export CXX = $(DEB_HOST_GNU_TYPE)-g++-10 bd_gcc = g++-10 , -else +else ifneq (,$(filter $(distrel),jammy)) export CC = $(DEB_HOST_GNU_TYPE)-gcc-11 export CXX = $(DEB_HOST_GNU_TYPE)-g++-11 bd_gcc = g++-11 , +else + export CC = $(DEB_HOST_GNU_TYPE)-gcc-12 + export CXX = $(DEB_HOST_GNU_TYPE)-g++-12 + bd_gcc = g++-12 , endif -# GCC 11 only -ifeq (,$(findstring 11, $(bd_gcc))) +# GCC 11 and up +ifeq (,$(findstring 11 12, $(bd_gcc))) DEB_BUILD_MAINT_OPTIONS = optimize=-lto endif @@ -900,6 +910,7 @@ debian/tests/control: debian/tests/control.in debian/rules sed \ + -e 's/@jtreg_pkg@/$(jtreg_pkg)/g' \ -e 's/@min_jtreg_version@/$(min_jtreg_version)/g' \ $< > $@; @@ -1045,8 +1056,8 @@ ifeq ($(with_check),yes) jtreg_version="$$(dpkg-query -f '$${Version}\n' -W $(jtreg_pkg))"; \ if ! dpkg --compare-versions $(min_jtreg_version) le $$jtreg_version; then \ - echo "Error: testsuite requires jtreg $(min_jtreg_version) but $$jtreg_version is installed"; \ - echo "Please update the jtreg dependency and regenerate debian/control"; \ + echo "Error: testsuite requires $(jtreg_pkg) $(min_jtreg_version) but $$jtreg_version is installed"; \ + echo "Please update the $(jtreg_pkg) dependency and regenerate debian/control"; \ false; \ fi endif @@ -1756,10 +1767,10 @@ cp -a $$i $(d_doc)/usr/share/doc/$(p_jrehl)/; \ ln -sf ../$(p_jrehl)/$$b $(d_doc)/usr/share/doc/$(p_doc)/$$b; \ done - rm -v $(d_doc)/usr/share/doc/$(p_jrehl)/api/script-dir/{jquery-3.5.1.min.js,jquery-ui.min.css,jquery-ui.min.js} + rm -v $(d_doc)/usr/share/doc/$(p_jrehl)/api/script-dir/{jquery-3.6.0.min.js,jquery-ui.min.css,jquery-ui.min.js} dh_link -p$(p_doc) \ /usr/share/javascript/jquery-ui/jquery-ui.min.js \ - /usr/share/doc/$(p_jrehl)/api/script-dir/jquery-3.5.1.min.js \ + /usr/share/doc/$(p_jrehl)/api/script-dir/jquery-3.6.0.min.js \ /usr/share/javascript/jquery-ui/themes/base/jquery-ui.min.css \ /usr/share/doc/$(p_jrehl)/api/script-dir/jquery-ui.min.css \ /usr/share/javascript/jquery-ui/jquery-ui.min.js \ @@ -1871,7 +1882,7 @@ is_release = yes #is_release = git_project = jdk17u -git_tag = jdk-17.0.4+8 +git_tag = jdk-17.0.5+8 package_version = $(subst jdk-,,$(git_tag)) package_version = $(shell echo $(PKGVERSION) | sed 's/-[^-][^-]*$$//') ifneq ($(is_release),yes) diff -Nru openjdk-17-17.0.4+8/debian/tests/control openjdk-17-17.0.5+8/debian/tests/control --- openjdk-17-17.0.4+8/debian/tests/control 2022-07-22 08:57:45.000000000 +0000 +++ openjdk-17-17.0.5+8/debian/tests/control 2022-10-24 16:44:41.000000000 +0000 @@ -7,9 +7,9 @@ Restrictions: superficial #Tests: hotspot, jaxp, langtools -#Depends: @, default-jre-headless, jtreg:native (>= 6+1-0~), testng:native, build-essential +#Depends: @, default-jre-headless, jtreg6:native (>= 6+1-0~), testng:native, build-essential #Restrictions: allow-stderr, skippable, flaky #Tests: jdk -#Depends: @, default-jre-headless, jtreg:native (>= 6+1-0~), testng:native, build-essential, xfwm4:native, xvfb, dbus-x11 +#Depends: @, default-jre-headless, jtreg6:native (>= 6+1-0~), testng:native, build-essential, xfwm4:native, xvfb, dbus-x11 #Restrictions: allow-stderr, skippable, flaky diff -Nru openjdk-17-17.0.4+8/debian/tests/control.in openjdk-17-17.0.5+8/debian/tests/control.in --- openjdk-17-17.0.4+8/debian/tests/control.in 2022-07-20 17:10:26.000000000 +0000 +++ openjdk-17-17.0.5+8/debian/tests/control.in 2022-10-24 16:44:41.000000000 +0000 @@ -7,9 +7,9 @@ Restrictions: superficial #Tests: hotspot, jaxp, langtools -#Depends: @, default-jre-headless, jtreg:native (>= @min_jtreg_version@), testng:native, build-essential +#Depends: @, default-jre-headless, @jtreg_pkg@:native (>= @min_jtreg_version@), testng:native, build-essential #Restrictions: allow-stderr, skippable, flaky #Tests: jdk -#Depends: @, default-jre-headless, jtreg:native (>= @min_jtreg_version@), testng:native, build-essential, xfwm4:native, xvfb, dbus-x11 +#Depends: @, default-jre-headless, @jtreg_pkg@:native (>= @min_jtreg_version@), testng:native, build-essential, xfwm4:native, xvfb, dbus-x11 #Restrictions: allow-stderr, skippable, flaky diff -Nru openjdk-17-17.0.4+8/doc/building.html openjdk-17-17.0.5+8/doc/building.html --- openjdk-17-17.0.4+8/doc/building.html 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/doc/building.html 2022-10-10 13:07:22.000000000 +0000 @@ -195,7 +195,7 @@

Windows

Windows XP is not a supported platform, but all newer Windows should be able to build the JDK.

On Windows, it is important that you pay attention to the instructions in the Special Considerations.

-

Windows is the only non-POSIX OS supported by the JDK, and as such, requires some extra care. A POSIX support layer is required to build on Windows. Currently, the only supported such layers are Cygwin and Windows Subsystem for Linux (WSL). (Msys is no longer supported due to a too old bash; msys2 would likely be possible to support in a future version but that would require effort to implement.)

+

Windows is the only non-POSIX OS supported by the JDK, and as such, requires some extra care. A POSIX support layer is required to build on Windows. Currently, the only supported such layers are Cygwin, Windows Subsystem for Linux (WSL), and MSYS2. (MSYS is no longer supported due to an outdated bash; While OpenJDK can be built with MSYS2, support for it is still experimental, so build failures and unusual errors are not uncommon.)

Internally in the build system, all paths are represented as Unix-style paths, e.g. /cygdrive/c/git/jdk/Makefile rather than C:\git\jdk\Makefile. This rule also applies to input to the build system, e.g. in arguments to configure. So, use --with-msvcr-dll=/cygdrive/c/msvcr100.dll rather than --with-msvcr-dll=c:\msvcr100.dll. For details on this conversion, see the section on Fixpath.

Cygwin

A functioning Cygwin environment is required for building the JDK on Windows. If you have a 64-bit OS, we strongly recommend using the 64-bit version of Cygwin.

@@ -278,7 +278,7 @@ Windows -Microsoft Visual Studio 2019 update 16.7.2 +Microsoft Visual Studio 2022 update 17.1.0 @@ -297,7 +297,7 @@

It is advisable to keep an older version of Xcode for building the JDK when updating Xcode. This blog page has good suggestions on managing multiple Xcode versions. To use a specific version of Xcode, use xcode-select -s before running configure, or use --with-toolchain-path to point to the version of Xcode to use, e.g. configure --with-toolchain-path=/Applications/Xcode8.app/Contents/Developer/usr/bin

If you have recently (inadvertently) updated your OS and/or Xcode version, and the JDK can no longer be built, please see the section on Problems with the Build Environment, and Getting Help to find out if there are any recent, non-merged patches available for this update.

Microsoft Visual Studio

-

The minimum accepted version of Visual Studio is 2017. Older versions will not be accepted by configure and will not work. The maximum accepted version of Visual Studio is 2019.

+

For aarch64 machines running Windows the minimum accepted version is Visual Studio 2019 (16.8 or higher). For all other platforms the minimum accepted version of Visual Studio is 2017. Older versions will not be accepted by configure and will not work. For all platforms the maximum accepted version of Visual Studio is 2019.

If you have multiple versions of Visual Studio installed, configure will by default pick the latest. You can request a specific version to be used by setting --with-toolchain-version, e.g. --with-toolchain-version=2017.

If you have Visual Studio installed but configure fails to detect it, it may be because of spaces in path.

IBM XL C/C++

diff -Nru openjdk-17-17.0.4+8/doc/building.md openjdk-17-17.0.5+8/doc/building.md --- openjdk-17-17.0.4+8/doc/building.md 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/doc/building.md 2022-10-10 13:07:22.000000000 +0000 @@ -179,10 +179,10 @@ Windows is the only non-POSIX OS supported by the JDK, and as such, requires some extra care. A POSIX support layer is required to build on Windows. -Currently, the only supported such layers are Cygwin and Windows Subsystem for -Linux (WSL). (Msys is no longer supported due to a too old bash; msys2 would -likely be possible to support in a future version but that would require effort -to implement.) +Currently, the only supported such layers are Cygwin, Windows Subsystem for +Linux (WSL), and MSYS2. (MSYS is no longer supported due to an outdated bash; +While OpenJDK can be built with MSYS2, support for it is still experimental, so +build failures and unusual errors are not uncommon.) Internally in the build system, all paths are represented as Unix-style paths, e.g. `/cygdrive/c/git/jdk/Makefile` rather than `C:\git\jdk\Makefile`. This @@ -323,7 +323,7 @@ ------------------ ------------------------------------------------------- Linux gcc 10.2.0 macOS Apple Xcode 10.1 (using clang 10.0.0) - Windows Microsoft Visual Studio 2019 update 16.7.2 + Windows Microsoft Visual Studio 2022 update 17.1.0 All compilers are expected to be able to compile to the C99 language standard, as some C99 features are used in the source code. Microsoft Visual Studio diff -Nru openjdk-17-17.0.4+8/.jcheck/conf openjdk-17-17.0.5+8/.jcheck/conf --- openjdk-17-17.0.4+8/.jcheck/conf 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/.jcheck/conf 2022-10-10 13:07:22.000000000 +0000 @@ -1,7 +1,7 @@ [general] project=jdk-updates jbs=JDK -version=17.0.4 +version=17.0.5 [checks] error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists diff -Nru openjdk-17-17.0.4+8/make/autoconf/boot-jdk.m4 openjdk-17-17.0.5+8/make/autoconf/boot-jdk.m4 --- openjdk-17-17.0.4+8/make/autoconf/boot-jdk.m4 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/autoconf/boot-jdk.m4 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2022, 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 @@ -126,16 +126,18 @@ AC_DEFUN([BOOTJDK_CHECK_ARGUMENTS], [ if test "x$with_boot_jdk" != x; then - if test -d "$with_boot_jdk"; then - BOOT_JDK=$with_boot_jdk + BOOT_JDK_ARG="$with_boot_jdk" + UTIL_FIXUP_PATH(BOOT_JDK_ARG) + if test -d "$BOOT_JDK_ARG"; then + BOOT_JDK=$BOOT_JDK_ARG BOOT_JDK_FOUND=maybe - elif test -f "$with_boot_jdk"; then - case "$with_boot_jdk" in + elif test -f "$BOOT_JDK_ARG"; then + case "$BOOT_JDK_ARG" in *.tar.gz ) BOOT_JDK_SUPPORT_DIR=$CONFIGURESUPPORT_OUTPUTDIR/boot-jdk $RM -rf $BOOT_JDK_SUPPORT_DIR $MKDIR -p $BOOT_JDK_SUPPORT_DIR - $GUNZIP -c $with_boot_jdk | $TAR xf - -C $BOOT_JDK_SUPPORT_DIR + $GUNZIP -c $BOOT_JDK_ARG | $TAR xf - -C $BOOT_JDK_SUPPORT_DIR # Try to find javac to determine BOOT_JDK path BOOT_JDK_JAVAC_PATH=`$FIND $BOOT_JDK_SUPPORT_DIR | $GREP "/bin/javac"` diff -Nru openjdk-17-17.0.4+8/make/autoconf/flags-cflags.m4 openjdk-17-17.0.5+8/make/autoconf/flags-cflags.m4 --- openjdk-17-17.0.4+8/make/autoconf/flags-cflags.m4 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/autoconf/flags-cflags.m4 2022-10-10 13:07:22.000000000 +0000 @@ -116,6 +116,18 @@ CFLAGS_DEBUG_SYMBOLS="-g" ASFLAGS_DEBUG_SYMBOLS="-g" elif test "x$TOOLCHAIN_TYPE" = xclang; then + if test "x$ALLOW_ABSOLUTE_PATHS_IN_OUTPUT" = "xfalse"; then + # Check if compiler supports -fdebug-prefix-map. If so, use that to make + # the debug symbol paths resolve to paths relative to the workspace root. + workspace_root_trailing_slash="${WORKSPACE_ROOT%/}/" + DEBUG_PREFIX_CFLAGS="-fdebug-prefix-map=${workspace_root_trailing_slash}=" + FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [${DEBUG_PREFIX_CFLAGS}], + IF_FALSE: [ + DEBUG_PREFIX_CFLAGS= + ] + ) + fi + CFLAGS_DEBUG_SYMBOLS="-g" ASFLAGS_DEBUG_SYMBOLS="-g" elif test "x$TOOLCHAIN_TYPE" = xxlc; then @@ -458,9 +470,11 @@ ALWAYS_DEFINES_JVM="-D_REENTRANT" ALWAYS_DEFINES_JDK="-D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then - ALWAYS_DEFINES_JDK="-DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_DEPRECATE \ + # Access APIs for Windows 8 and above + # see https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 + ALWAYS_DEFINES_JDK="-DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0602 -D_CRT_SECURE_NO_DEPRECATE \ -D_CRT_NONSTDC_NO_DEPRECATE -DWIN32 -DIAL" - ALWAYS_DEFINES_JVM="-DNOMINMAX -DWIN32_LEAN_AND_MEAN" + ALWAYS_DEFINES_JVM="-DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0602" fi ############################################################################### diff -Nru openjdk-17-17.0.4+8/make/autoconf/lib-bundled.m4 openjdk-17-17.0.5+8/make/autoconf/lib-bundled.m4 --- openjdk-17-17.0.4+8/make/autoconf/lib-bundled.m4 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/autoconf/lib-bundled.m4 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2022, 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 @@ -217,6 +217,9 @@ LIBZ_LIBS="" if test "x$USE_EXTERNAL_LIBZ" = "xfalse"; then LIBZ_CFLAGS="$LIBZ_CFLAGS -I$TOPDIR/src/java.base/share/native/libzip/zlib" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + LIBZ_CFLAGS="$LIBZ_CFLAGS -DHAVE_UNISTD_H" + fi else LIBZ_LIBS="-lz" fi diff -Nru openjdk-17-17.0.4+8/make/autoconf/platform.m4 openjdk-17-17.0.5+8/make/autoconf/platform.m4 --- openjdk-17-17.0.4+8/make/autoconf/platform.m4 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/autoconf/platform.m4 2022-10-10 13:07:22.000000000 +0000 @@ -212,7 +212,7 @@ VAR_OS=windows VAR_OS_ENV=windows.wsl ;; - *msys*) + *msys* | *mingw*) VAR_OS=windows VAR_OS_ENV=windows.msys2 ;; diff -Nru openjdk-17-17.0.4+8/make/common/modules/LauncherCommon.gmk openjdk-17-17.0.5+8/make/common/modules/LauncherCommon.gmk --- openjdk-17-17.0.4+8/make/common/modules/LauncherCommon.gmk 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/common/modules/LauncherCommon.gmk 2022-10-10 13:07:22.000000000 +0000 @@ -44,6 +44,7 @@ LAUNCHER_SRC := $(TOPDIR)/src/java.base/share/native/launcher LAUNCHER_CFLAGS += -I$(TOPDIR)/src/java.base/share/native/launcher \ + -I$(TOPDIR)/src/java.desktop/share/native/include \ -I$(TOPDIR)/src/java.base/share/native/libjli \ -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli \ -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libjli \ @@ -196,9 +197,11 @@ ################################################################################ # Create man pages for jmod to pick up. There should be a one-to-one # relationship between executables and man pages (even if this is not always -# the case), so piggyback man page generation on the launcher compilation. +# the case), so piggyback man page generation on the launcher compilation. This +# file may be included from other places as well, so only process man pages +# when called from /Launcher.gmk. -ifeq ($(call isTargetOsType, unix), true) +ifeq ($(call isTargetOsType, unix)+$(MAKEFILE_PREFIX), true+Launcher) # Only build manpages on unix systems. # We assume all our man pages should reside in section 1. @@ -242,9 +245,9 @@ FILTER := $(PANDOC_TROFF_MANPAGE_FILTER), \ POST_PROCESS := $(MAN_POST_PROCESS), \ REPLACEMENTS := \ - @@COPYRIGHT_YEAR@@ => $(COPYRIGHT_YEAR) ; \ - @@VERSION_SHORT@@ => $(VERSION_SHORT) ; \ - @@VERSION_SPECIFICATION@@ => $(VERSION_SPECIFICATION), \ + @@COPYRIGHT_YEAR@@ => $(COPYRIGHT_YEAR) ; \ + @@VERSION_SHORT@@ => $(VERSION_SHORT) ; \ + @@VERSION_SPECIFICATION@@ => $(VERSION_SPECIFICATION), \ EXTRA_DEPS := $(PANDOC_TROFF_MANPAGE_FILTER) \ $(PANDOC_TROFF_MANPAGE_FILTER_SOURCE), \ )) diff -Nru openjdk-17-17.0.4+8/make/common/NativeCompilation.gmk openjdk-17-17.0.5+8/make/common/NativeCompilation.gmk --- openjdk-17-17.0.4+8/make/common/NativeCompilation.gmk 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/common/NativeCompilation.gmk 2022-10-10 13:07:22.000000000 +0000 @@ -359,9 +359,9 @@ $1_FLAGS := $(BASIC_ASFLAGS) $$($1_BASE_ASFLAGS) $1_COMPILER := $(AS) - # gcc assembly files must contain an appropriate relative .file + # gcc or clang assembly files must contain an appropriate relative .file # path for reproducible builds. - ifeq ($(TOOLCHAIN_TYPE), gcc) + ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), ) # If no absolute paths allowed, work out relative source file path # for assembly .file substitution, otherwise use full file path ifeq ($(ALLOW_ABSOLUTE_PATHS_IN_OUTPUT), false) @@ -403,8 +403,9 @@ $1_OBJ_DEPS := $$($1_SRC_FILE) $$($$($1_BASE)_COMPILE_VARDEPS_FILE) \ $$($$($1_BASE)_EXTRA_DEPS) $$($1_VARDEPS_FILE) $1_COMPILE_OPTIONS := $$($1_FLAGS) $(CC_OUT_OPTION)$$($1_OBJ) $$($1_SRC_FILE) - # For reproducible builds with gcc ensure random symbol generation is seeded deterministically - ifeq ($(TOOLCHAIN_TYPE), gcc) + # For reproducible builds with gcc and clang ensure random symbol generation is + # seeded deterministically + ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), ) ifeq ($$(ENABLE_REPRODUCIBLE_BUILD), true) $1_COMPILE_OPTIONS += -frandom-seed="$$($1_FILENAME)" endif diff -Nru openjdk-17-17.0.4+8/make/conf/github-actions.conf openjdk-17-17.0.5+8/make/conf/github-actions.conf --- openjdk-17-17.0.4+8/make/conf/github-actions.conf 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/make/conf/github-actions.conf 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,41 @@ +# +# Copyright (c) 2020, 2022, 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. +# + +# Versions and download locations for dependencies used by GitHub Actions (GHA) + +GTEST_VERSION=1.8.1 +JTREG_VERSION=6.1+2 + +LINUX_X64_BOOT_JDK_EXT=tar.gz +LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.2%2B8/OpenJDK17U-jdk_x64_linux_hotspot_17.0.2_8.tar.gz +LINUX_X64_BOOT_JDK_SHA256=288f34e3ba8a4838605636485d0365ce23e57d5f2f68997ac4c2e4c01967cd48 + +WINDOWS_X64_BOOT_JDK_EXT=zip +WINDOWS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.2%2B8/OpenJDK17U-jdk_x64_windows_hotspot_17.0.2_8.zip +WINDOWS_X64_BOOT_JDK_SHA256=d083479ca927dce2f586f779373d895e8bf668c632505740279390384edf03fa + +MACOS_X64_BOOT_JDK_EXT=tar.gz +MACOS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.2%2B8/OpenJDK17U-jdk_x64_mac_hotspot_17.0.2_8.tar.gz +MACOS_X64_BOOT_JDK_SHA256=3630e21a571b7180876bf08f85d0aac0bdbb3267b2ae9bd242f4933b21f9be32 diff -Nru openjdk-17-17.0.4+8/make/conf/jib-profiles.js openjdk-17-17.0.5+8/make/conf/jib-profiles.js --- openjdk-17-17.0.4+8/make/conf/jib-profiles.js 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/conf/jib-profiles.js 2022-10-10 13:07:22.000000000 +0000 @@ -1049,7 +1049,7 @@ var devkit_platform_revisions = { linux_x64: "gcc10.3.0-OL6.4+1.0", macosx: "Xcode12.4+1.0", - windows_x64: "VS2019-16.9.3+1.0", + windows_x64: "VS2022-17.1.0+1.0", linux_aarch64: "gcc10.3.0-OL7.6+1.0", linux_arm: "gcc8.2.0-Fedora27+1.0", linux_ppc64le: "gcc8.2.0-Fedora27+1.0", diff -Nru openjdk-17-17.0.4+8/make/conf/test-dependencies openjdk-17-17.0.5+8/make/conf/test-dependencies --- openjdk-17-17.0.4+8/make/conf/test-dependencies 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/conf/test-dependencies 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -# -# Copyright (c) 2020, 2022, 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. -# - -# Versions and download locations for dependencies used by pre-submit testing. - -BOOT_JDK_VERSION=17 -JTREG_VERSION=6 -JTREG_BUILD=1 -GTEST_VERSION=1.8.1 - -LINUX_X64_BOOT_JDK_FILENAME=openjdk-17.0.2_linux-x64_bin.tar.gz -LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.2%2B8/OpenJDK17U-jdk_x64_linux_hotspot_17.0.2_8.tar.gz -LINUX_X64_BOOT_JDK_SHA256=288f34e3ba8a4838605636485d0365ce23e57d5f2f68997ac4c2e4c01967cd48 - -WINDOWS_X64_BOOT_JDK_FILENAME=openjdk-17.0.2_windows-x64_bin.zip -WINDOWS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.2%2B8/OpenJDK17U-jdk_x64_windows_hotspot_17.0.2_8.zip -WINDOWS_X64_BOOT_JDK_SHA256=d083479ca927dce2f586f779373d895e8bf668c632505740279390384edf03fa - -MACOS_X64_BOOT_JDK_FILENAME=openjdk-17.0.2_macos-x64_bin.tar.gz -MACOS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.2%2B8/OpenJDK17U-jdk_x64_mac_hotspot_17.0.2_8.tar.gz -MACOS_X64_BOOT_JDK_SHA256=3630e21a571b7180876bf08f85d0aac0bdbb3267b2ae9bd242f4933b21f9be32 diff -Nru openjdk-17-17.0.4+8/make/conf/version-numbers.conf openjdk-17-17.0.5+8/make/conf/version-numbers.conf --- openjdk-17-17.0.4+8/make/conf/version-numbers.conf 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/conf/version-numbers.conf 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2022, 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,12 +28,12 @@ DEFAULT_VERSION_FEATURE=17 DEFAULT_VERSION_INTERIM=0 -DEFAULT_VERSION_UPDATE=4 +DEFAULT_VERSION_UPDATE=5 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2022-07-19 +DEFAULT_VERSION_DATE=2022-10-18 DEFAULT_VERSION_CLASSFILE_MAJOR=61 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 diff -Nru openjdk-17-17.0.4+8/make/data/currency/CurrencyData.properties openjdk-17-17.0.5+8/make/data/currency/CurrencyData.properties --- openjdk-17-17.0.4+8/make/data/currency/CurrencyData.properties 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/data/currency/CurrencyData.properties 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2022, 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 @@ -32,7 +32,7 @@ # Version of the currency code information in this class. # It is a serial number that accompanies with each amendment. -dataVersion=170 +dataVersion=172 # List of all valid ISO 4217 currency codes. # To ensure compatibility, do not remove codes. @@ -51,7 +51,7 @@ MTL470-MUR480-MVR462-MWK454-MXN484-MXV979-MYR458-MZM508-MZN943-NAD516-NGN566-\ NIO558-NLG528-NOK578-NPR524-NZD554-OMR512-PAB590-PEN604-PGK598-PHP608-\ PKR586-PLN985-PTE620-PYG600-QAR634-ROL642-RON946-RSD941-RUB643-RUR810-RWF646-SAR682-\ - SBD090-SCR690-SDD736-SDG938-SEK752-SGD702-SHP654-SIT705-SKK703-SLL694-SOS706-\ + SBD090-SCR690-SDD736-SDG938-SEK752-SGD702-SHP654-SIT705-SKK703-SLE925-SLL694-SOS706-\ SRD968-SRG740-SSP728-STD678-STN930-SVC222-SYP760-SZL748-THB764-TJS972-TMM795-TMT934-TND788-TOP776-\ TPE626-TRL792-TRY949-TTD780-TWD901-TZS834-UAH980-UGX800-USD840-USN997-USS998-UYI940-\ UYU858-UZS860-VEB862-VED926-VEF937-VES928-VND704-VUV548-WST882-XAF950-XAG961-XAU959-XBA955-\ @@ -317,6 +317,8 @@ KP=KPW # KOREA (THE REPUBLIC OF) KR=KRW +# KOSOVO - Not in ISO 3166/4217 +XK=EUR # KUWAIT KW=KWD # KYRGYZSTAN @@ -482,7 +484,7 @@ # SEYCHELLES SC=SCR # SIERRA LEONE -SL=SLL +SL=SLE # SINGAPORE SG=SGD # SLOVAKIA diff -Nru openjdk-17-17.0.4+8/make/data/tzdata/africa openjdk-17-17.0.5+8/make/data/tzdata/africa --- openjdk-17-17.0.4+8/make/data/tzdata/africa 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/data/tzdata/africa 2022-10-10 13:07:22.000000000 +0000 @@ -182,6 +182,7 @@ Link Africa/Abidjan Africa/Lome # Togo Link Africa/Abidjan Africa/Nouakchott # Mauritania Link Africa/Abidjan Africa/Ouagadougou # Burkina Faso +Link Africa/Abidjan Atlantic/Reykjavik # Iceland Link Africa/Abidjan Atlantic/St_Helena # St Helena # Djibouti @@ -192,7 +193,7 @@ # Egypt # Milne says Cairo used 2:05:08.9, the local mean time of the Abbasizeh -# observatory; round to nearest. Milne also says that the official time for +# observatory. Milne also says that the official time for # Egypt was mean noon at the Great Pyramid, 2:04:30.5, but apparently this # did not apply to Cairo, Alexandria, or Port Said. @@ -377,6 +378,7 @@ Rule Egypt 2014 only - Sep lastThu 24:00 0 - # Zone NAME STDOFF RULES FORMAT [UNTIL] + #STDOFF 2:05:08.9 Zone Africa/Cairo 2:05:09 - LMT 1900 Oct 2:00 Egypt EE%sT @@ -430,7 +432,7 @@ # At midnight on 30 June 1928 the clocks throughout Kenya was put forward # half an hour by the Alteration of Time Ordinance, 1928. # https://gazettes.africa/archive/ke/1928/ke-government-gazette-dated-1928-05-11-no-28.pdf -# [Ordinance No. 11 of 1928, The Offical Gazette, 1928-06-26, p 813] +# [Ordinance No. 11 of 1928, The Official Gazette, 1928-06-26, p 813] # https://books.google.com/books?id=2S0S6os32ZUC&pg=PA813 # # The 1928 ordinance was repealed by the Alteration of Time (repeal) Ordinance, @@ -1333,21 +1335,9 @@ Link Africa/Lagos Africa/Porto-Novo # Benin # Réunion -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Indian/Reunion 3:41:52 - LMT 1911 Jun # Saint-Denis - 4:00 - +04 +# See Asia/Dubai. # -# Scattered Islands (Îles Éparses) administered from Réunion are as follows. -# The following information about them is taken from -# Îles Éparses (, 1997-07-22, -# in French; no longer available as of 1999-08-17). -# We have no info about their time zone histories. -# -# Bassas da India - uninhabited -# Europa Island - inhabited from 1905 to 1910 by two families -# Glorioso Is - inhabited until at least 1958 -# Juan de Nova - uninhabited -# Tromelin - inhabited until at least 1958 +# The Crozet Islands also observe Réunion time; see the 'antarctica' file. # Rwanda # See Africa/Maputo. @@ -1379,9 +1369,10 @@ # From Michael Deckers (2018-12-30): # https://www.legis-palop.org/download.jsp?idFile=102818 # ... [The legal time of the country, which coincides with universal -# coordinated time, will be restituted at 2 o'clock on day 1 of January, 2019.] +# coordinated time, will be reinstituted at 2 o'clock on day 1 of January, 2019.] Zone Africa/Sao_Tome 0:26:56 - LMT 1884 + #STDOFF -0:36:44.68 -0:36:45 - LMT 1912 Jan 1 00:00u # Lisbon MT 0:00 - GMT 2018 Jan 1 01:00 1:00 - WAT 2019 Jan 1 02:00 @@ -1391,28 +1382,7 @@ # See Africa/Abidjan. # Seychelles - -# From P Chan (2020-11-27): -# Standard Time was adopted on 1907-01-01. -# -# Standard Time Ordinance (Chapter 237) -# The Laws of Seychelles in Force on the 31st December, 1971, Vol. 6, p 571 -# https://books.google.com/books?id=efE-AQAAIAAJ&pg=PA571 -# -# From Tim Parenti (2020-12-05): -# A footnote on https://books.google.com/books?id=DYdDAQAAMAAJ&pg=PA1689 -# confirms that Ordinance No. 9 of 1906 "was brought into force on the 1st -# January, 1907." - -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Indian/Mahe 3:41:48 - LMT 1907 Jan 1 # Victoria - 4:00 - +04 -# From Paul Eggert (2001-05-30): -# Aldabra, Farquhar, and Desroches, originally dependencies of the -# Seychelles, were transferred to the British Indian Ocean Territory -# in 1965 and returned to Seychelles control in 1976. We don't know -# whether this affected their time zone, so omit this for now. -# Possibly the islands were uninhabited. +# See Asia/Dubai. # Sierra Leone # See Africa/Abidjan. diff -Nru openjdk-17-17.0.4+8/make/data/tzdata/antarctica openjdk-17-17.0.5+8/make/data/tzdata/antarctica --- openjdk-17-17.0.4+8/make/data/tzdata/antarctica 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/data/tzdata/antarctica 2022-10-10 13:07:22.000000000 +0000 @@ -180,9 +180,7 @@ # St Paul Island - near Amsterdam, uninhabited # fishing stations operated variously 1819/1931 # -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Indian/Kerguelen 0 - -00 1950 # Port-aux-Français - 5:00 - +05 +# Kerguelen - see Indian/Maldives. # # year-round base in the main continent # Dumont d'Urville - see Pacific/Port_Moresby. @@ -265,31 +263,7 @@ # year-round from 1960/61 to 1992 # Vostok, since 1957-12-16, temporarily closed 1994-02/1994-11 -# From Craig Mundell (1994-12-15): -# http://quest.arc.nasa.gov/antarctica/QA/computers/Directions,Time,ZIP -# Vostok, which is one of the Russian stations, is set on the same -# time as Moscow, Russia. -# -# From Lee Hotz (2001-03-08): -# I queried the folks at Columbia who spent the summer at Vostok and this is -# what they had to say about time there: -# "in the US Camp (East Camp) we have been on New Zealand (McMurdo) -# time, which is 12 hours ahead of GMT. The Russian Station Vostok was -# 6 hours behind that (although only 2 miles away, i.e. 6 hours ahead -# of GMT). This is a time zone I think two hours east of Moscow. The -# natural time zone is in between the two: 8 hours ahead of GMT." -# -# From Paul Eggert (2001-05-04): -# This seems to be hopelessly confusing, so I asked Lee Hotz about it -# in person. He said that some Antarctic locations set their local -# time so that noon is the warmest part of the day, and that this -# changes during the year and does not necessarily correspond to mean -# solar noon. So the Vostok time might have been whatever the clocks -# happened to be during their visit. So we still don't really know what time -# it is at Vostok. But we'll guess +06. -# -Zone Antarctica/Vostok 0 - -00 1957 Dec 16 - 6:00 - +06 +# See Asia/Urumqi. # S Africa - year-round bases # Marion Island, -4653+03752 diff -Nru openjdk-17-17.0.4+8/make/data/tzdata/asia openjdk-17-17.0.5+8/make/data/tzdata/asia --- openjdk-17-17.0.4+8/make/data/tzdata/asia 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/data/tzdata/asia 2022-10-10 13:07:22.000000000 +0000 @@ -278,10 +278,7 @@ 6:00 - +06 # Brunei -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Asia/Brunei 7:39:40 - LMT 1926 Mar # Bandar Seri Begawan - 7:30 - +0730 1933 - 8:00 - +08 +# See Asia/Kuching. # Burma / Myanmar @@ -299,6 +296,7 @@ 6:30 - +0630 1942 May 9:00 - +09 1945 May 3 6:30 - +0630 +Link Asia/Yangon Indian/Cocos # Cambodia # See Asia/Bangkok. @@ -367,12 +365,9 @@ # in the city at the time for people who use different time standard to adjust # their clock to their preferred time. # -# a. For the 1940 May 31 spring forward, the essay claim that it was -# coordinared between the international settlement authority and the French -# concession authority and have gathered support from Hong Kong and Xiamen, -# that it would spring forward an hour from May 31 "midnight", and the essay -# claim "Hong Kong government implemented the spring forward in the same time -# on the same date as Shanghai". +# a. For the 1940 May 31 spring forward, the essay [says] ... "Hong +# Kong government implemented the spring forward in the same time on +# the same date as Shanghai". # # b. For the 1940 fall back, it was said that they initially intended to do # so on September 30 00:59 at night, however they postponed it to October 12 @@ -568,7 +563,7 @@ # Zhongyuan Time ("Central plain Time") UT +08 # Now part of Asia/Shanghai. # most of China -# Milne gives 8:05:43.2 for Xujiahui Observatory time; round to nearest. +# Milne gives 8:05:43.2 for Xujiahui Observatory time.... # Guo says Shanghai switched to UT +08 "from the end of the 19th century". # # Long-shu Time (probably as Long and Shu were two names of the area) UT +07 @@ -687,6 +682,7 @@ # Zone NAME STDOFF RULES FORMAT [UNTIL] # Beijing time, used throughout China; represented by Shanghai. + #STDOFF 8:05:43.2 Zone Asia/Shanghai 8:05:43 - LMT 1901 8:00 Shang C%sT 1949 May 28 8:00 PRC C%sT @@ -694,11 +690,12 @@ # / Wulumuqi. (Please use Asia/Shanghai if you prefer Beijing time.) Zone Asia/Urumqi 5:50:20 - LMT 1928 6:00 - +06 +Link Asia/Urumqi Antarctica/Vostok # Hong Kong -# Milne gives 7:36:41.7; round this. +# Milne gives 7:36:41.7. # From Lee Yiu Chung (2009-10-24): # I found there are some mistakes for the...DST rule for Hong @@ -882,7 +879,8 @@ Rule HK 1979 only - May 13 3:30 1:00 S Rule HK 1979 only - Oct 21 3:30 0 - # Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Asia/Hong_Kong 7:36:42 - LMT 1904 Oct 30 0:36:42 + #STDOFF 7:36:41.7 +Zone Asia/Hong_Kong 7:36:42 - LMT 1904 Oct 29 17:00u 8:00 - HKT 1941 Jun 15 3:00 8:00 1:00 HKST 1941 Oct 1 4:00 8:00 0:30 HKWT 1941 Dec 25 @@ -1357,7 +1355,7 @@ # # From Paul Eggert (2014-09-06): # The 1876 Report of the Secretary of the [US] Navy, p 306 says that Batavia -# civil time was 7:07:12.5; round to even for Jakarta. +# civil time was 7:07:12.5. # # From Gwillim Law (2001-05-28), overriding Shanks & Pottenger: # http://www.sumatera-inc.com/go_to_invest/about_indonesia.asp#standtime @@ -1393,10 +1391,11 @@ # # Zone NAME STDOFF RULES FORMAT [UNTIL] # Java, Sumatra + #STDOFF 7:07:12.5 Zone Asia/Jakarta 7:07:12 - LMT 1867 Aug 10 # Shanks & Pottenger say the next transition was at 1924 Jan 1 0:13, # but this must be a typo. - 7:07:12 - BMT 1923 Dec 31 23:47:12 # Batavia + 7:07:12 - BMT 1923 Dec 31 16:40u # Batavia 7:20 - +0720 1932 Nov 7:30 - +0730 1942 Mar 23 9:00 - +09 1945 Sep 23 @@ -1428,6 +1427,111 @@ # Iran +# From Roozbeh Pournader (2022-05-30): +# Here's an order from the Cabinet to the rest of the government to switch to +# Tehran time, which is mentioned to be already at +03:30: +# https://qavanin.ir/Law/TreeText/180138 +# Just in case that goes away, I also saved a copy at archive.org: +# https://web.archive.org/web/20220530111940/https://qavanin.ir/Law/TreeText/180138 +# Here's my translation: +# +# "Circular on Matching the Hours of Governmental and Official Circles +# in Provinces +# Approved 1314/03/22 [=1935-06-13] +# According to the ruling of the Honorable Cabinet, it is ordered that from +# now on in all internal provinces of the country, governmental and official +# circles set their time to match Tehran time (three hours and half before +# Greenwich).... +# +# I still haven't found out when Tehran itself switched to +03:30.... +# +# From Paul Eggert (2022-06-05): +# Although the above says Tehran was at +03:30 before 1935-06-13, we don't +# know when it switched to +03:30. For now, use 1935-06-13 as the switch date. +# Although most likely wrong, we have no better info. + +# From Roozbeh Pournader (2022-06-01): +# This is from Kayhan newspaper, one of the major Iranian newspapers, from +# March 20, 1978, page 2: +# +# "Pull the clocks 60 minutes forward +# As we informed before, from the fourth day of the month Farvardin of the +# new year [=1978-03-24], clocks will be pulled forward, and people's daily +# work and life program will start one hour earlier than the current program. +# On the 1st day of the month Farvardin of this year [=1977-03-21], they had +# pulled the clocks forward by one hour, but in the month of Mehr +# [=1977-09-23], the clocks were pulled back by 30 minutes. +# In this way, from the 4th day of the month Farvardin, clocks will be ahead +# of the previous years by one hour and a half. +# According to the new program, during the night of 4th of Farvardin, when +# the midnight, meaning 24 o'clock is announced, the hands of the clock must +# be pulled forward by one hour and thus consider midnight 1 o'clock in the +# forenoon." +# +# This implies that in September 1977, when the daylight savings time was +# done with, Iran didn't go back to +03:30, but immediately to +04:00. +# +# +# This is from the major Iranian newspaper Ettela'at, dated [1978-08-03]..., +# page 32. It looks like they decided to get the clocks back to +4:00 +# just in time for Ramadan that year: +# +# "Tomorrow Night, Pull the Clocks Back by One Hour +# At 1 o'clock in the forenoon of Saturday 14 Mordad [=1978-08-05], the +# clocks will be pulled one hour back and instead of 1 o'clock in the +# forenoon, Radio Iran will announce 24 o'clock. +# This decision was made in the Cabinet of Ministers meeting of 25 Tir +# [=1978-07-16], [...] +# At the beginning of the year 2537 [=March 1978: Iran was using a different +# year number for a few years then, based on the Coronation of Cyrus the +# Great], the country's official time was pulled forward by one hour and now +# the official time is one hour and a half ahead compared to last year, +# because in Farvardin of last year [=March 1977], the official time was +# pulled forward one hour and this continued until the second half of last +# year [=September 1977] until in the second half of last year the official +# time was pulled back half an hour and that half hour still remains." +# +# This matches the time of the true noon published in the newspapers, as they +# clearly go from +05:00 to +04:00 after that date (which happened during a +# long weekend in Iran). + +# From Roozbeh Pournader (2022-05-31): +# [Movahedi S. Cultural preconceptions of time: Can we use operational time +# to meddle in God's Time? Comp Stud Soc Hist. 1985;27(3):385-400] +# https://www.jstor.org/stable/178704 +# Here's the quotes from the paper: +# 1. '"Iran's official time keeper moved the clock one hour forward as from +# March 22, 1977 (Farvardin 2, 2536) to make maximum use of daylight and save +# in energy consumption. Thus Iran joined such other countries as Britain in +# observing what is known as 'daylight saving.' The proposal was originally +# put forward by the Ministry of Energy, in no way having any influence on +# observing religious ceremonies. Moving time one hour forward in summer +# means that at 11:00 o'clock on March 21, the official time was set as +# midnight March 22. Then September 24 will actually begin one hour later +# than the end of September 23 [...]." Iran's time base thus continued to be +# Greenwich Mean Time plus three and one-half hours (plus four and one-half +# hours in summer).' +# +# The article sources this from Iran Almanac and Book of Facts, 1977, Tehran: +# Echo of Iran, which is on Google Books at +# https://www.google.com/books/edition/Iran_Almanac_and_Book_of_Facts/9ybVAAAAMAAJ. +# (I confirmed it by searching for snippets.) +# +# 2. "After the fall of the shah, the revolutionary government returned to +# daylight-saving time (DST) on 26 May 1979." +# +# This seems to have been announced just one day in advance, on 25 May 1979. +# +# The change in 1977 clearly seems to be the first daylight savings effort in +# Iran. But the article doesn't mention what happened in 1978 (which was +# still during the shah's government), or how things continued in 1979 +# onwards (which was during the Islamic Republic). + +# From Francis Santoni (2022-06-01): +# for Iran and 1977 the effective change is only 20 October +# (UIT No. 143 17.XI.1977) and not 23 September (UIT No. 141 13.IX.1977). +# UIT is the Operational Bulletin of International Telecommunication Union. + # From Roozbeh Pournader (2003-03-15): # This is an English translation of what I just found (originally in Persian). # The Gregorian dates in brackets are mine: @@ -1462,65 +1566,12 @@ # leap year calculation involved. There has never been any serious # plan to change that law.... # -# From Paul Eggert (2018-11-30): -# Go with Shanks & Pottenger before Sept. 1991, and with Pournader thereafter. -# I used the following code in GNU Emacs 26.1 to generate the "Rule Iran" -# lines from 2008 through 2087. Emacs 26.1 uses Ed Reingold's -# cal-persia implementation of Birashk's approximation, which in the -# 2008-2087 range disagrees with the astronomical Persian calendar -# for Persian years 1404 (Gregorian 2025) and 1437 (Gregorian 2058), so -# the following code special-cases those years. See Table 15.1, page 264, of: -# Edward M. Reingold and Nachum Dershowitz, Calendrical Calculations: -# The Ultimate Edition, Cambridge University Press (2018). -# https://www.cambridge.org/fr/academic/subjects/computer-science/computing-general-interest/calendrical-calculations-ultimate-edition-4th-edition -# Page 258, footnote 2, of this book says there is some dispute over what will -# happen in 2091 (and some other years after that), so this code -# stops in 2087, as 2088 and 2089 agree with the "max" rule below. -# (cl-loop -# initially (require 'cal-persia) -# with first-persian-year = 1387 -# with last-persian-year = 1466 -# ;; Exceptional years in the above range, -# ;; from Reingold & Dershowitz Table 15.1, page 264: -# with exceptional-persian-years = '(1404 1437) -# with range-start = nil -# for persian-year from first-persian-year to last-persian-year -# do -# (let* -# ((exceptional-year-offset -# (if (member persian-year exceptional-persian-years) 1 0)) -# (beg-dst-absolute -# (+ (calendar-persian-to-absolute (list 1 1 persian-year)) -# exceptional-year-offset)) -# (end-dst-absolute -# (+ (calendar-persian-to-absolute (list 6 30 persian-year)) -# exceptional-year-offset)) -# (next-year-beg-dst-absolute -# (+ (calendar-persian-to-absolute (list 1 1 (1+ persian-year))) -# (if (member (1+ persian-year) exceptional-persian-years) 1 0))) -# (beg-dst (calendar-gregorian-from-absolute beg-dst-absolute)) -# (end-dst (calendar-gregorian-from-absolute end-dst-absolute)) -# (next-year-beg-dst (calendar-gregorian-from-absolute -# next-year-beg-dst-absolute)) -# (year (calendar-extract-year beg-dst)) -# (range-end (if range-start year "only"))) -# (setq range-start (or range-start year)) -# (when (or (/= (calendar-extract-day beg-dst) -# (calendar-extract-day next-year-beg-dst)) -# (= persian-year last-persian-year)) -# (insert -# (format -# "Rule\tIran\t%d\t%s\t-\t%s\t%2d\t24:00\t1:00\t-\n" -# range-start range-end -# (calendar-month-name (calendar-extract-month beg-dst) t) -# (calendar-extract-day beg-dst))) -# (insert -# (format -# "Rule\tIran\t%d\t%s\t-\t%s\t%2d\t24:00\t0\t-\n" -# range-start range-end -# (calendar-month-name (calendar-extract-month end-dst) t) -# (calendar-extract-day end-dst))) -# (setq range-start nil)))) +# From Paul Eggert (2022-06-30): +# Go with Pournader for 1935 through spring 1979, and for timestamps +# after August 1991; go with with Shanks & Pottenger for other timestamps. +# Go with Santoni's citation of the UIT for fall 1977, as 20 October 1977 +# is 28 Mehr 1356, consistent with the "Mehr" in Pournader's source. +# Assume that the UIT's "1930" is UTC, i.e., 24:00 local time. # # From Oscar van Vlijmen (2005-03-30), writing about future # discrepancies between cal-persia and the Iranian calendar: @@ -1554,10 +1605,23 @@ # be changed back to its previous state on the 24 hours of the # thirtieth day of Shahrivar. # +# From Ali Mirjamali (2022-05-10): +# Official IR News Agency announcement: irna.ir/xjJ3TT +# ... +# Highlights: DST will be cancelled for the next Iranian year 1402 +# (i.e 2023-March-21) and forthcoming years. +# # Rule NAME FROM TO - IN ON AT SAVE LETTER/S -Rule Iran 1978 1980 - Mar 20 24:00 1:00 - -Rule Iran 1978 only - Oct 20 24:00 0 - +# Work around a bug in zic 2022a and earlier. +Rule Iran 1910 only - Jan 1 00:00 0 - +# +Rule Iran 1977 only - Mar 21 23:00 1:00 - +Rule Iran 1977 only - Oct 20 24:00 0 - +Rule Iran 1978 only - Mar 24 24:00 1:00 - +Rule Iran 1978 only - Aug 5 01:00 0 - +Rule Iran 1979 only - May 26 24:00 1:00 - Rule Iran 1979 only - Sep 18 24:00 0 - +Rule Iran 1980 only - Mar 20 24:00 1:00 - Rule Iran 1980 only - Sep 22 24:00 0 - Rule Iran 1991 only - May 2 24:00 1:00 - Rule Iran 1992 1995 - Mar 21 24:00 1:00 - @@ -1588,85 +1652,13 @@ Rule Iran 2017 2019 - Sep 21 24:00 0 - Rule Iran 2020 only - Mar 20 24:00 1:00 - Rule Iran 2020 only - Sep 20 24:00 0 - -Rule Iran 2021 2023 - Mar 21 24:00 1:00 - -Rule Iran 2021 2023 - Sep 21 24:00 0 - -Rule Iran 2024 only - Mar 20 24:00 1:00 - -Rule Iran 2024 only - Sep 20 24:00 0 - -Rule Iran 2025 2027 - Mar 21 24:00 1:00 - -Rule Iran 2025 2027 - Sep 21 24:00 0 - -Rule Iran 2028 2029 - Mar 20 24:00 1:00 - -Rule Iran 2028 2029 - Sep 20 24:00 0 - -Rule Iran 2030 2031 - Mar 21 24:00 1:00 - -Rule Iran 2030 2031 - Sep 21 24:00 0 - -Rule Iran 2032 2033 - Mar 20 24:00 1:00 - -Rule Iran 2032 2033 - Sep 20 24:00 0 - -Rule Iran 2034 2035 - Mar 21 24:00 1:00 - -Rule Iran 2034 2035 - Sep 21 24:00 0 - -Rule Iran 2036 2037 - Mar 20 24:00 1:00 - -Rule Iran 2036 2037 - Sep 20 24:00 0 - -Rule Iran 2038 2039 - Mar 21 24:00 1:00 - -Rule Iran 2038 2039 - Sep 21 24:00 0 - -Rule Iran 2040 2041 - Mar 20 24:00 1:00 - -Rule Iran 2040 2041 - Sep 20 24:00 0 - -Rule Iran 2042 2043 - Mar 21 24:00 1:00 - -Rule Iran 2042 2043 - Sep 21 24:00 0 - -Rule Iran 2044 2045 - Mar 20 24:00 1:00 - -Rule Iran 2044 2045 - Sep 20 24:00 0 - -Rule Iran 2046 2047 - Mar 21 24:00 1:00 - -Rule Iran 2046 2047 - Sep 21 24:00 0 - -Rule Iran 2048 2049 - Mar 20 24:00 1:00 - -Rule Iran 2048 2049 - Sep 20 24:00 0 - -Rule Iran 2050 2051 - Mar 21 24:00 1:00 - -Rule Iran 2050 2051 - Sep 21 24:00 0 - -Rule Iran 2052 2053 - Mar 20 24:00 1:00 - -Rule Iran 2052 2053 - Sep 20 24:00 0 - -Rule Iran 2054 2055 - Mar 21 24:00 1:00 - -Rule Iran 2054 2055 - Sep 21 24:00 0 - -Rule Iran 2056 2057 - Mar 20 24:00 1:00 - -Rule Iran 2056 2057 - Sep 20 24:00 0 - -Rule Iran 2058 2059 - Mar 21 24:00 1:00 - -Rule Iran 2058 2059 - Sep 21 24:00 0 - -Rule Iran 2060 2062 - Mar 20 24:00 1:00 - -Rule Iran 2060 2062 - Sep 20 24:00 0 - -Rule Iran 2063 only - Mar 21 24:00 1:00 - -Rule Iran 2063 only - Sep 21 24:00 0 - -Rule Iran 2064 2066 - Mar 20 24:00 1:00 - -Rule Iran 2064 2066 - Sep 20 24:00 0 - -Rule Iran 2067 only - Mar 21 24:00 1:00 - -Rule Iran 2067 only - Sep 21 24:00 0 - -Rule Iran 2068 2070 - Mar 20 24:00 1:00 - -Rule Iran 2068 2070 - Sep 20 24:00 0 - -Rule Iran 2071 only - Mar 21 24:00 1:00 - -Rule Iran 2071 only - Sep 21 24:00 0 - -Rule Iran 2072 2074 - Mar 20 24:00 1:00 - -Rule Iran 2072 2074 - Sep 20 24:00 0 - -Rule Iran 2075 only - Mar 21 24:00 1:00 - -Rule Iran 2075 only - Sep 21 24:00 0 - -Rule Iran 2076 2078 - Mar 20 24:00 1:00 - -Rule Iran 2076 2078 - Sep 20 24:00 0 - -Rule Iran 2079 only - Mar 21 24:00 1:00 - -Rule Iran 2079 only - Sep 21 24:00 0 - -Rule Iran 2080 2082 - Mar 20 24:00 1:00 - -Rule Iran 2080 2082 - Sep 20 24:00 0 - -Rule Iran 2083 only - Mar 21 24:00 1:00 - -Rule Iran 2083 only - Sep 21 24:00 0 - -Rule Iran 2084 2086 - Mar 20 24:00 1:00 - -Rule Iran 2084 2086 - Sep 20 24:00 0 - -Rule Iran 2087 only - Mar 21 24:00 1:00 - -Rule Iran 2087 only - Sep 21 24:00 0 - -# -# The following rules are approximations starting in the year 2088. -# These are the best post-2088 approximations available, given the -# restrictions of a single rule using ordinary Gregorian dates. -# At some point this table will need to be extended, though quite -# possibly Iran will change the rules first. -Rule Iran 2088 max - Mar 20 24:00 1:00 - -Rule Iran 2088 max - Sep 20 24:00 0 - +Rule Iran 2021 2022 - Mar 21 24:00 1:00 - +Rule Iran 2021 2022 - Sep 21 24:00 0 - # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Asia/Tehran 3:25:44 - LMT 1916 - 3:25:44 - TMT 1946 # Tehran Mean Time - 3:30 - +0330 1977 Nov + 3:25:44 - TMT 1935 Jun 13 # Tehran Mean Time + 3:30 Iran +0330/+0430 1977 Oct 20 24:00 4:00 Iran +04/+05 1979 3:30 Iran +0330/+0430 @@ -2488,9 +2480,9 @@ # the third time belt (before 1930 this means +03). # From Alexander Konzurovski (2018-12-20): -# Qyzyolrda Region (Asia/Qyzylorda) is changing its time zone from -# UTC+6 to UTC+5 effective December 21st, 2018. The legal document is -# located here: http://adilet.zan.kz/rus/docs/P1800000817 (russian language). +# (Asia/Qyzylorda) is changing its time zone from UTC+6 to UTC+5 +# effective December 21st, 2018.... +# http://adilet.zan.kz/rus/docs/P1800000817 (russian language). # Zone NAME STDOFF RULES FORMAT [UNTIL] # @@ -2767,20 +2759,8 @@ Rule NBorneo 1935 1941 - Sep 14 0:00 0:20 - Rule NBorneo 1935 1941 - Dec 14 0:00 0 - # -# peninsular Malaysia -# taken from Mok Ly Yng (2003-10-30) -# https://web.archive.org/web/20190822231045/http://www.math.nus.edu.sg/~mathelmr/teaching/timezone.html -# This agrees with Singapore since 1905-06-01. -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Asia/Kuala_Lumpur 6:46:46 - LMT 1901 Jan 1 - 6:55:25 - SMT 1905 Jun 1 # Singapore M.T. - 7:00 - +07 1933 Jan 1 - 7:00 0:20 +0720 1936 Jan 1 - 7:20 - +0720 1941 Sep 1 - 7:30 - +0730 1942 Feb 16 - 9:00 - +09 1945 Sep 12 - 7:30 - +0730 1982 Jan 1 - 8:00 - +08 +# For peninsular Malaysia see Asia/Singapore. +# # Sabah & Sarawak # From Paul Eggert (2014-08-12): # The data entries here are mostly from Shanks & Pottenger, but the 1942, 1945 @@ -2791,12 +2771,14 @@ 8:00 NBorneo +08/+0820 1942 Feb 16 9:00 - +09 1945 Sep 12 8:00 - +08 +Link Asia/Kuching Asia/Brunei # Maldives # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Indian/Maldives 4:54:00 - LMT 1880 # Malé 4:54:00 - MMT 1960 # Malé Mean Time 5:00 - +05 +Link Indian/Maldives Indian/Kerguelen # Mongolia @@ -3631,6 +3613,7 @@ 9:00 - +09 1945 Sep 12 7:30 - +0730 1982 Jan 1 8:00 - +08 +Link Asia/Singapore Asia/Kuala_Lumpur # Spratly Is # no information @@ -3865,7 +3848,7 @@ Zone Asia/Dushanbe 4:35:12 - LMT 1924 May 2 5:00 - +05 1930 Jun 21 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00s - 5:00 1:00 +05/+06 1991 Sep 9 2:00s + 5:00 1:00 +06 1991 Sep 9 2:00s 5:00 - +05 # Thailand @@ -3875,6 +3858,7 @@ 7:00 - +07 Link Asia/Bangkok Asia/Phnom_Penh # Cambodia Link Asia/Bangkok Asia/Vientiane # Laos +Link Asia/Bangkok Indian/Christmas # Turkmenistan # From Shanks & Pottenger. @@ -3890,6 +3874,8 @@ Zone Asia/Dubai 3:41:12 - LMT 1920 4:00 - +04 Link Asia/Dubai Asia/Muscat # Oman +Link Asia/Dubai Indian/Mahe +Link Asia/Dubai Indian/Reunion # Uzbekistan # Byalokoz 1919 says Uzbekistan was 4:27:53. @@ -3901,7 +3887,8 @@ 6:00 - +06 1982 Apr 1 5:00 RussiaAsia +05/+06 1992 5:00 - +05 -# Milne says Tashkent was 4:37:10.8; round to nearest. +# Milne says Tashkent was 4:37:10.8. + #STDOFF 4:37:10.8 Zone Asia/Tashkent 4:37:11 - LMT 1924 May 2 5:00 - +05 1930 Jun 21 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00 @@ -3920,7 +3907,7 @@ # The English-language name of Vietnam's most populous city is "Ho Chi Minh # City"; use Ho_Chi_Minh below to avoid a name of more than 14 characters. -# From Paul Eggert (2014-10-21) after a heads-up from Trần Ngọc Quân: +# From Paul Eggert (2022-07-27) after a 2014 heads-up from Trần Ngọc Quân: # Trần Tiến Bình's authoritative book "Lịch Việt Nam: thế kỷ XX-XXI (1901-2100)" # (Nhà xuất bản Văn Hoá - Thông Tin, Hanoi, 2005), pp 49-50, # is quoted verbatim in: @@ -3932,8 +3919,8 @@ # The 1906 transition was effective July 1 and standardized Indochina to # Phù Liễn Observatory, legally 104° 17' 17" east of Paris. # It's unclear whether this meant legal Paris Mean Time (00:09:21) or -# the Paris Meridian (2° 20' 14.03" E); the former yields 07:06:30.1333... -# and the latter 07:06:29.333... so either way it rounds to 07:06:30, +# the Paris Meridian; for now guess the former and round the exact +# 07:06:30.1333... to 07:06:30.13 as the legal spec used 66 2/3 ms precision. # which is used below even though the modern-day Phù Liễn Observatory # is closer to 07:06:31. Abbreviate Phù Liễn Mean Time as PLMT. # @@ -3960,7 +3947,8 @@ # NXB Thuận Hoá, Huế, 1995. # Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Asia/Ho_Chi_Minh 7:06:40 - LMT 1906 Jul 1 + #STDOFF 7:06:30.13 +Zone Asia/Ho_Chi_Minh 7:06:30 - LMT 1906 Jul 1 7:06:30 - PLMT 1911 May 1 # Phù Liễn MT 7:00 - +07 1942 Dec 31 23:00 8:00 - +08 1945 Mar 14 23:00 diff -Nru openjdk-17-17.0.4+8/make/data/tzdata/australasia openjdk-17-17.0.5+8/make/data/tzdata/australasia --- openjdk-17-17.0.4+8/make/data/tzdata/australasia 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/data/tzdata/australasia 2022-10-10 13:07:22.000000000 +0000 @@ -275,16 +275,10 @@ 10:00 AT AE%sT # Christmas -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Indian/Christmas 7:02:52 - LMT 1895 Feb - 7:00 - +07 +# See Asia/Bangkok. # Cocos (Keeling) Is -# These islands were ruled by the Ross family from about 1830 to 1978. -# We don't know when standard time was introduced; for now, we guess 1900. -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Indian/Cocos 6:27:40 - LMT 1900 - 6:30 - +0630 +# See Asia/Yangon. # Fiji @@ -501,6 +495,11 @@ # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Pacific/Tarawa 11:32:04 - LMT 1901 # Bairiki 12:00 - +12 +Link Pacific/Tarawa Pacific/Funafuti +Link Pacific/Tarawa Pacific/Majuro +Link Pacific/Tarawa Pacific/Wake +Link Pacific/Tarawa Pacific/Wallis + Zone Pacific/Kanton 0 - -00 1937 Aug 31 -12:00 - -12 1979 Oct -11:00 - -11 1994 Dec 31 @@ -514,15 +513,8 @@ # See Pacific/Guam. # Marshall Is +# See Pacific/Tarawa for most locations. # Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Pacific/Majuro 11:24:48 - LMT 1901 - 11:00 - +11 1914 Oct - 9:00 - +09 1919 Feb 1 - 11:00 - +11 1937 - 10:00 - +10 1941 Apr 1 - 9:00 - +09 1944 Jan 30 - 11:00 - +11 1969 Oct - 12:00 - +12 Zone Pacific/Kwajalein 11:09:20 - LMT 1901 11:00 - +11 1937 10:00 - +10 1941 Apr 1 @@ -532,22 +524,9 @@ 12:00 - +12 # Micronesia +# For Chuuk and Yap see Pacific/Port_Moresby. +# For Pohnpei see Pacific/Guadalcanal. # Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Pacific/Chuuk -13:52:52 - LMT 1844 Dec 31 - 10:07:08 - LMT 1901 - 10:00 - +10 1914 Oct - 9:00 - +09 1919 Feb 1 - 10:00 - +10 1941 Apr 1 - 9:00 - +09 1945 Aug - 10:00 - +10 -Zone Pacific/Pohnpei -13:27:08 - LMT 1844 Dec 31 # Kolonia - 10:32:52 - LMT 1901 - 11:00 - +11 1914 Oct - 9:00 - +09 1919 Feb 1 - 11:00 - +11 1937 - 10:00 - +10 1941 Apr 1 - 9:00 - +09 1945 Aug - 11:00 - +11 Zone Pacific/Kosrae -13:08:04 - LMT 1844 Dec 31 10:51:56 - LMT 1901 11:00 - +11 1914 Oct @@ -617,12 +596,12 @@ Zone Pacific/Auckland 11:39:04 - LMT 1868 Nov 2 11:30 NZ NZ%sT 1946 Jan 1 12:00 NZ NZ%sT +Link Pacific/Auckland Antarctica/McMurdo + Zone Pacific/Chatham 12:13:48 - LMT 1868 Nov 2 12:15 - +1215 1946 Jan 1 12:45 Chatham +1245/+1345 -Link Pacific/Auckland Antarctica/McMurdo - # Auckland Is # uninhabited; Māori and Moriori, colonial settlers, pastoralists, sealers, # and scientific personnel have wintered @@ -681,7 +660,7 @@ # Niue -# See Pacific/Raratonga comments for 1952 transition. +# See Pacific/Rarotonga comments for 1952 transition. # # From Tim Parenti (2021-09-13): # Consecutive contemporaneous editions of The Air Almanac listed -11:20 for @@ -717,6 +696,7 @@ 9:48:32 - PMMT 1895 # Port Moresby Mean Time 10:00 - +10 Link Pacific/Port_Moresby Antarctica/DumontDUrville +Link Pacific/Port_Moresby Pacific/Chuuk # # From Paul Eggert (2014-10-13): # Base the Bougainville entry on the Arawa-Kieta region, which appears to have @@ -844,6 +824,7 @@ # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Pacific/Guadalcanal 10:39:48 - LMT 1912 Oct # Honiara 11:00 - +11 +Link Pacific/Guadalcanal Pacific/Pohnpei # Tokelau # @@ -884,9 +865,7 @@ 13:00 Tonga +13/+14 # Tuvalu -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Pacific/Funafuti 11:56:52 - LMT 1901 - 12:00 - +12 +# See Pacific/Tarawa. # US minor outlying islands @@ -945,9 +924,7 @@ # uninhabited since World War II; was probably like Pacific/Kiritimati # Wake -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Pacific/Wake 11:06:28 - LMT 1901 - 12:00 - +12 +# See Pacific/Tarawa. # Vanuatu @@ -986,9 +963,7 @@ 11:00 Vanuatu +11/+12 # Wallis and Futuna -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Pacific/Wallis 12:15:20 - LMT 1901 - 12:00 - +12 +# See Pacific/Tarawa. ############################################################################### @@ -1306,6 +1281,7 @@ # to have the extra hour of sunshine removed from their area." See: # Daylight saving coming to WA in 2019. Guardian Express. 2018-04-01. # https://www.communitynews.com.au/guardian-express/news/exclusive-daylight-savings-coming-wa-summer-2018/ +# [The article ends with "Today's date is April 1."] # Queensland @@ -1849,16 +1825,12 @@ # "In Marshall Islands, Friday is followed by Sunday", NY Times. 1993-08-22. # https://www.nytimes.com/1993/08/22/world/in-marshall-islands-friday-is-followed-by-sunday.html -# From Phake Nick (2018-10-27): -# ... pointed out that -# currently tzdata say Pacific/Kwajalein switched from GMT+11 to GMT-12 in -# 1969 October without explanation, however an 1993 article from NYT say it -# synchorized its day with US mainland about 40 years ago and thus the switch -# should occur at around 1950s instead. -# -# From Paul Eggert (2018-11-18): -# The NYT (actually, AP) article is vague and possibly wrong about this. -# The article says the earlier switch was "40 years ago when the United States +# From Paul Eggert (2022-03-31): +# Phake Nick (2018-10-27) noted 's +# citation of a 1993 AP article published in the New York Times saying +# Kwajalein synchronized its day with the US mainland about 40 years earlier. +# However the AP article is vague and possibly wrong about this. The article +# says the earlier switch was "about 40 years ago when the United States # Army established a missile test range here". However, the Kwajalein Test # Center was established on 1960-10-01 and was run by the US Navy. It was # transferred to the US Army on 1964-07-01. See "Seize the High Ground" @@ -1905,13 +1877,6 @@ # Like the Ladrones (see Guam commentary), assume the Spanish East Indies # kept American time until the Philippines switched at the end of 1844. -# Alan Eugene Davis writes (1996-03-16), -# "I am certain, having lived there for the past decade, that 'Truk' -# (now properly known as Chuuk) ... is in the time zone GMT+10." -# -# Shanks & Pottenger write that Truk switched from UT +10 to +11 -# on 1978-10-01; ignore this for now. - # From Paul Eggert (1999-10-29): # The Federated States of Micronesia Visitors Board writes in # The Federated States of Micronesia - Visitor Information (1999-01-26) @@ -2242,7 +2207,7 @@ # through the third Sunday in January at 03:00, like Fiji, for now. # From David Wade (2017-10-18): -# In August government was disolved by the King. The current prime minister +# In August government was dissolved by the King. The current prime minister # continued in office in care taker mode. It is easy to see that few # decisions will be made until elections 16th November. # @@ -2250,26 +2215,6 @@ # For now, guess that DST is discontinued. That's what the IATA is guessing. -# Wake - -# From Vernice Anderson, Personal Secretary to Philip Jessup, -# US Ambassador At Large (oral history interview, 1971-02-02): -# -# Saturday, the 14th [of October, 1950] - ... The time was all the -# more confusing at that point, because we had crossed the -# International Date Line, thus getting two Sundays. Furthermore, we -# discovered that Wake Island had two hours of daylight saving time -# making calculation of time in Washington difficult if not almost -# impossible. -# -# https://www.trumanlibrary.org/oralhist/andrsonv.htm - -# From Paul Eggert (2003-03-23): -# We have no other report of DST in Wake Island, so omit this info for now. - -# See also the commentary for Micronesia. - - ############################################################################### # The International Date Line diff -Nru openjdk-17-17.0.4+8/make/data/tzdata/backward openjdk-17-17.0.5+8/make/data/tzdata/backward --- openjdk-17-17.0.4+8/make/data/tzdata/backward 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/data/tzdata/backward 2022-10-10 13:07:22.000000000 +0000 @@ -27,10 +27,15 @@ # 2009-05-17 by Arthur David Olson. # This file provides links from old or merged timezone names to current ones. -# Many names changed in late 1993. Several of these names are +# Many names changed in late 1993, and many merged names moved here +# in the period from 2013 through 2022. Several of these names are # also present in the file 'backzone', which has data important only # for pre-1970 timestamps and so is out of scope for tzdb proper. +# Although this file is optional and tzdb will work if you omit it by +# building with 'make BACKWARD=', in practice downstream users +# typically use this file for backward compatibility. + # Link TARGET LINK-NAME Link Africa/Nairobi Africa/Asmera Link Africa/Abidjan Africa/Timbuktu @@ -71,7 +76,7 @@ Link Asia/Makassar Asia/Ujung_Pandang Link Asia/Ulaanbaatar Asia/Ulan_Bator Link Atlantic/Faroe Atlantic/Faeroe -Link Europe/Oslo Atlantic/Jan_Mayen +Link Europe/Berlin Atlantic/Jan_Mayen Link Australia/Sydney Australia/ACT Link Australia/Sydney Australia/Canberra Link Australia/Hobart Australia/Currie @@ -106,6 +111,7 @@ Link Europe/Dublin Eire Link Etc/UTC Etc/UCT Link Europe/London Europe/Belfast +Link Europe/Kyiv Europe/Kiev Link Europe/Chisinau Europe/Tiraspol Link Europe/London GB Link Europe/London GB-Eire @@ -114,7 +120,7 @@ Link Etc/GMT GMT0 Link Etc/GMT Greenwich Link Asia/Hong_Kong Hongkong -Link Atlantic/Reykjavik Iceland +Link Africa/Abidjan Iceland Link Asia/Tehran Iran Link Asia/Jerusalem Israel Link America/Jamaica Jamaica @@ -130,10 +136,10 @@ Link Asia/Shanghai PRC Link Pacific/Kanton Pacific/Enderbury Link Pacific/Honolulu Pacific/Johnston -Link Pacific/Pohnpei Pacific/Ponape +Link Pacific/Guadalcanal Pacific/Ponape Link Pacific/Pago_Pago Pacific/Samoa -Link Pacific/Chuuk Pacific/Truk -Link Pacific/Chuuk Pacific/Yap +Link Pacific/Port_Moresby Pacific/Truk +Link Pacific/Port_Moresby Pacific/Yap Link Europe/Warsaw Poland Link Europe/Lisbon Portugal Link Asia/Taipei ROC diff -Nru openjdk-17-17.0.4+8/make/data/tzdata/etcetera openjdk-17-17.0.5+8/make/data/tzdata/etcetera --- openjdk-17-17.0.4+8/make/data/tzdata/etcetera 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/data/tzdata/etcetera 2022-10-10 13:07:22.000000000 +0000 @@ -40,12 +40,16 @@ # behind GMT but uses the completely misleading abbreviation "GMT". Zone Etc/GMT 0 - GMT + +# The following zone is used by tzcode functions like gmtime, +# which load the "UTC" file to handle seconds properly. Zone Etc/UTC 0 - UTC # The following link uses older naming conventions, # but it belongs here, not in the file 'backward', -# as functions like gmtime load the "GMT" file to handle leap seconds properly. -# We want this to work even on installations that omit the other older names. +# as it is needed for tzcode releases through 2022a, +# where functions like gmtime load "GMT" instead of the "Etc/UTC". +# We want this to work even on installations that omit 'backward'. Link Etc/GMT GMT Link Etc/UTC Etc/Universal diff -Nru openjdk-17-17.0.4+8/make/data/tzdata/europe openjdk-17-17.0.5+8/make/data/tzdata/europe --- openjdk-17-17.0.4+8/make/data/tzdata/europe 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/data/tzdata/europe 2022-10-10 13:07:22.000000000 +0000 @@ -326,8 +326,7 @@ # UT-00:25:22 and cites the International Telegraph Bureau. As it is # not clear that there was any practical significance to the change # from UT-00:25:22 to UT-00:25:21.1 in civil timekeeping, omit this -# transition for now and just use the latter value, omitting its -# fraction since our format cannot represent fractions. +# transition for now and just use the latter value. # "Countess Markievicz ... claimed that the [1916] abolition of Dublin Mean Time # was among various actions undertaken by the 'English' government that @@ -523,7 +522,7 @@ # Use Europe/London for Jersey, Guernsey, and the Isle of Man. # Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Europe/London -0:01:15 - LMT 1847 Dec 1 0:00s +Zone Europe/London -0:01:15 - LMT 1847 Dec 1 0:00 GB-Eire %s 1968 Oct 27 1:00 - BST 1971 Oct 31 2:00u 0:00 GB-Eire %s 1996 @@ -561,7 +560,8 @@ Rule Eire 1996 max - Oct lastSun 1:00u -1:00 - # Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Europe/Dublin -0:25:00 - LMT 1880 Aug 2 + #STDOFF -0:25:21.1 +Zone Europe/Dublin -0:25:21 - LMT 1880 Aug 2 -0:25:21 - DMT 1916 May 21 2:00s -0:25:21 1:00 IST 1916 Oct 1 2:00s 0:00 GB-Eire %s 1921 Dec 6 # independence @@ -984,6 +984,8 @@ 1:00 C-Eur CE%sT 1944 Sep 3 1:00 Belgium CE%sT 1977 1:00 EU CE%sT +Link Europe/Brussels Europe/Amsterdam +Link Europe/Brussels Europe/Luxembourg # Bosnia and Herzegovina # See Europe/Belgrade. @@ -1046,62 +1048,12 @@ # End of rearguard section. 1:00 Czech CE%sT 1979 1:00 EU CE%sT -# Use Europe/Prague also for Slovakia. +Link Europe/Prague Europe/Bratislava + # Denmark, Faroe Islands, and Greenland +# For Denmark see Europe/Berlin. -# From Jesper Nørgaard Welen (2005-04-26): -# the law [introducing standard time] was in effect from 1894-01-01.... -# The page https://www.retsinformation.dk/eli/lta/1893/83 -# confirms this, and states that the law was put forth 1893-03-29. -# -# The EU [actually, EEC and Euratom] treaty with effect from 1973: -# https://www.retsinformation.dk/eli/lta/1972/21100 -# -# This provoked a new law from 1974 to make possible summer time changes -# in subsequent decrees with the law -# https://www.retsinformation.dk/eli/lta/1974/223 -# -# It seems however that no decree was set forward until 1980. I have -# not found any decree, but in another related law, the effecting DST -# changes are stated explicitly to be from 1980-04-06 at 02:00 to -# 1980-09-28 at 02:00. If this is true, this differs slightly from -# the EU rule in that DST runs to 02:00, not 03:00. We don't know -# when Denmark began using the EU rule correctly, but we have only -# confirmation of the 1980-time, so I presume it was correct in 1981: -# The law is about the management of the extra hour, concerning -# working hours reported and effect on obligatory-rest rules (which -# was suspended on that night): -# https://web.archive.org/web/20140104053304/https://www.retsinformation.dk/Forms/R0710.aspx?id=60267 - -# From Jesper Nørgaard Welen (2005-06-11): -# The Herning Folkeblad (1980-09-26) reported that the night between -# Saturday and Sunday the clock is set back from three to two. - -# From Paul Eggert (2005-06-11): -# Hence the "02:00" of the 1980 law refers to standard time, not -# wall-clock time, and so the EU rules were in effect in 1980. - -# Rule NAME FROM TO - IN ON AT SAVE LETTER/S -Rule Denmark 1916 only - May 14 23:00 1:00 S -Rule Denmark 1916 only - Sep 30 23:00 0 - -Rule Denmark 1940 only - May 15 0:00 1:00 S -Rule Denmark 1945 only - Apr 2 2:00s 1:00 S -Rule Denmark 1945 only - Aug 15 2:00s 0 - -Rule Denmark 1946 only - May 1 2:00s 1:00 S -Rule Denmark 1946 only - Sep 1 2:00s 0 - -Rule Denmark 1947 only - May 4 2:00s 1:00 S -Rule Denmark 1947 only - Aug 10 2:00s 0 - -Rule Denmark 1948 only - May 9 2:00s 1:00 S -Rule Denmark 1948 only - Aug 8 2:00s 0 - -# -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Europe/Copenhagen 0:50:20 - LMT 1890 - 0:50:20 - CMT 1894 Jan 1 # Copenhagen MT - 1:00 Denmark CE%sT 1942 Nov 2 2:00s - 1:00 C-Eur CE%sT 1945 Apr 2 2:00 - 1:00 Denmark CE%sT 1980 - 1:00 EU CE%sT Zone Atlantic/Faroe -0:27:04 - LMT 1908 Jan 11 # Tórshavn 0:00 - WET 1981 0:00 EU WE%sT @@ -1321,10 +1273,10 @@ Rule Finland 1981 1982 - Mar lastSun 2:00 1:00 S Rule Finland 1981 1982 - Sep lastSun 3:00 0 - -# Milne says Helsinki (Helsingfors) time was 1:39:49.2 (official document); -# round to nearest. +# Milne says Helsinki (Helsingfors) time was 1:39:49.2 (official document). # Zone NAME STDOFF RULES FORMAT [UNTIL] + #STDOFF 1:39:49.2 Zone Europe/Helsinki 1:39:49 - LMT 1878 May 31 1:39:49 - HMT 1921 May # Helsinki Mean Time 2:00 Finland EE%sT 1983 @@ -1471,6 +1423,7 @@ 0:00 France WE%sT 1945 Sep 16 3:00 1:00 France CE%sT 1977 1:00 EU CE%sT +Link Europe/Paris Europe/Monaco # Germany @@ -1514,21 +1467,11 @@ 1:00 SovietZone CE%sT 1946 1:00 Germany CE%sT 1980 1:00 EU CE%sT +Link Europe/Berlin Arctic/Longyearbyen +Link Europe/Berlin Europe/Copenhagen +Link Europe/Berlin Europe/Oslo +Link Europe/Berlin Europe/Stockholm -# From Tobias Conradi (2011-09-12): -# Büsingen , surrounded by the Swiss canton -# Schaffhausen, did not start observing DST in 1980 as the rest of DE -# (West Germany at that time) and DD (East Germany at that time) did. -# DD merged into DE, the area is currently covered by code DE in ISO 3166-1, -# which in turn is covered by the zone Europe/Berlin. -# -# Source for the time in Büsingen 1980: -# http://www.srf.ch/player/video?id=c012c029-03b7-4c2b-9164-aa5902cd58d3 - -# From Arthur David Olson (2012-03-03): -# Büsingen and Zurich have shared clocks since 1970. - -Link Europe/Zurich Europe/Busingen # Georgia # Please see the "asia" file for Asia/Tbilisi. @@ -1537,7 +1480,7 @@ # Gibraltar # Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Europe/Gibraltar -0:21:24 - LMT 1880 Aug 2 0:00s +Zone Europe/Gibraltar -0:21:24 - LMT 1880 Aug 2 0:00 GB-Eire %s 1957 Apr 14 2:00 1:00 - CET 1982 1:00 EU CE%sT @@ -1648,62 +1591,7 @@ 1:00 EU CE%sT # Iceland -# -# From Adam David (1993-11-06): -# The name of the timezone in Iceland for system / mail / news purposes is GMT. -# -# (1993-12-05): -# This material is paraphrased from the 1988 edition of the University of -# Iceland Almanak. -# -# From January 1st, 1908 the whole of Iceland was standardised at 1 hour -# behind GMT. Previously, local mean solar time was used in different parts -# of Iceland, the almanak had been based on Reykjavík mean solar time which -# was 1 hour and 28 minutes behind GMT. -# -# "first day of winter" referred to [below] means the first day of the 26 weeks -# of winter, according to the old icelandic calendar that dates back to the -# time the norsemen first settled Iceland. The first day of winter is always -# Saturday, but is not dependent on the Julian or Gregorian calendars. -# -# (1993-12-10): -# I have a reference from the Oxford Icelandic-English dictionary for the -# beginning of winter, which ties it to the ecclesiastical calendar (and thus -# to the julian/gregorian calendar) over the period in question. -# the winter begins on the Saturday next before St. Luke's day -# (old style), or on St. Luke's day, if a Saturday. -# St. Luke's day ought to be traceable from ecclesiastical sources. "old style" -# might be a reference to the Julian calendar as opposed to Gregorian, or it -# might mean something else (???). -# -# From Paul Eggert (2014-11-22): -# The information below is taken from the 1988 Almanak; see -# http://www.almanak.hi.is/klukkan.html -# -# Rule NAME FROM TO - IN ON AT SAVE LETTER/S -Rule Iceland 1917 1919 - Feb 19 23:00 1:00 - -Rule Iceland 1917 only - Oct 21 1:00 0 - -Rule Iceland 1918 1919 - Nov 16 1:00 0 - -Rule Iceland 1921 only - Mar 19 23:00 1:00 - -Rule Iceland 1921 only - Jun 23 1:00 0 - -Rule Iceland 1939 only - Apr 29 23:00 1:00 - -Rule Iceland 1939 only - Oct 29 2:00 0 - -Rule Iceland 1940 only - Feb 25 2:00 1:00 - -Rule Iceland 1940 1941 - Nov Sun>=2 1:00s 0 - -Rule Iceland 1941 1942 - Mar Sun>=2 1:00s 1:00 - -# 1943-1946 - first Sunday in March until first Sunday in winter -Rule Iceland 1943 1946 - Mar Sun>=1 1:00s 1:00 - -Rule Iceland 1942 1948 - Oct Sun>=22 1:00s 0 - -# 1947-1967 - first Sunday in April until first Sunday in winter -Rule Iceland 1947 1967 - Apr Sun>=1 1:00s 1:00 - -# 1949 and 1967 Oct transitions delayed by 1 week -Rule Iceland 1949 only - Oct 30 1:00s 0 - -Rule Iceland 1950 1966 - Oct Sun>=22 1:00s 0 - -Rule Iceland 1967 only - Oct 29 1:00s 0 - -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Atlantic/Reykjavik -1:28 - LMT 1908 - -1:00 Iceland -01/+00 1968 Apr 7 1:00s - 0:00 - GMT +# See Africa/Abidjan. # Italy # @@ -1819,19 +1707,19 @@ Rule Italy 1979 only - Sep 30 0:00s 0 - # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Europe/Rome 0:49:56 - LMT 1866 Dec 12 - 0:49:56 - RMT 1893 Oct 31 23:49:56 # Rome Mean + 0:49:56 - RMT 1893 Oct 31 23:00u # Rome Mean 1:00 Italy CE%sT 1943 Sep 10 1:00 C-Eur CE%sT 1944 Jun 4 1:00 Italy CE%sT 1980 1:00 EU CE%sT +Link Europe/Rome Europe/Vatican +Link Europe/Rome Europe/San_Marino + # Kosovo # See Europe/Belgrade. -Link Europe/Rome Europe/Vatican -Link Europe/Rome Europe/San_Marino - # Latvia # From Liene Kanepe (1998-09-17): @@ -1915,16 +1803,7 @@ 2:00 EU EE%sT # Liechtenstein - -# From Paul Eggert (2013-09-09): -# Shanks & Pottenger say Vaduz is like Zurich. - -# From Alois Treindl (2019-07-04): -# I was able to access the online archive of the Vaduz paper Vaterland ... -# I could confirm from the paper that Liechtenstein did in fact follow -# the same DST in 1941 and 1942 as Switzerland did. - -Link Europe/Zurich Europe/Vaduz +# See Europe/Zurich. # Lithuania @@ -1980,40 +1859,7 @@ 2:00 EU EE%sT # Luxembourg -# Whitman disagrees with most of these dates in minor ways; -# go with Shanks & Pottenger. -# Rule NAME FROM TO - IN ON AT SAVE LETTER/S -Rule Lux 1916 only - May 14 23:00 1:00 S -Rule Lux 1916 only - Oct 1 1:00 0 - -Rule Lux 1917 only - Apr 28 23:00 1:00 S -Rule Lux 1917 only - Sep 17 1:00 0 - -Rule Lux 1918 only - Apr Mon>=15 2:00s 1:00 S -Rule Lux 1918 only - Sep Mon>=15 2:00s 0 - -Rule Lux 1919 only - Mar 1 23:00 1:00 S -Rule Lux 1919 only - Oct 5 3:00 0 - -Rule Lux 1920 only - Feb 14 23:00 1:00 S -Rule Lux 1920 only - Oct 24 2:00 0 - -Rule Lux 1921 only - Mar 14 23:00 1:00 S -Rule Lux 1921 only - Oct 26 2:00 0 - -Rule Lux 1922 only - Mar 25 23:00 1:00 S -Rule Lux 1922 only - Oct Sun>=2 1:00 0 - -Rule Lux 1923 only - Apr 21 23:00 1:00 S -Rule Lux 1923 only - Oct Sun>=2 2:00 0 - -Rule Lux 1924 only - Mar 29 23:00 1:00 S -Rule Lux 1924 1928 - Oct Sun>=2 1:00 0 - -Rule Lux 1925 only - Apr 5 23:00 1:00 S -Rule Lux 1926 only - Apr 17 23:00 1:00 S -Rule Lux 1927 only - Apr 9 23:00 1:00 S -Rule Lux 1928 only - Apr 14 23:00 1:00 S -Rule Lux 1929 only - Apr 20 23:00 1:00 S -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Europe/Luxembourg 0:24:36 - LMT 1904 Jun - 1:00 Lux CE%sT 1918 Nov 25 - 0:00 Lux WE%sT 1929 Oct 6 2:00s - 0:00 Belgium WE%sT 1940 May 14 3:00 - 1:00 C-Eur WE%sT 1944 Sep 18 3:00 - 1:00 Belgium CE%sT 1977 - 1:00 EU CE%sT +# See Europe/Brussels. # North Macedonia # See Europe/Belgrade. @@ -2032,7 +1878,7 @@ Rule Malta 1975 1980 - Sep Sun>=15 2:00 0 - Rule Malta 1980 only - Mar 31 2:00 1:00 S # Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Europe/Malta 0:58:04 - LMT 1893 Nov 2 0:00s # Valletta +Zone Europe/Malta 0:58:04 - LMT 1893 Nov 2 # Valletta 1:00 Italy CE%sT 1973 Mar 31 1:00 Malta CE%sT 1981 1:00 EU CE%sT @@ -2114,126 +1960,16 @@ 2:00 Moldova EE%sT # Monaco -# -# From Michael Deckers (2020-06-12): -# In the "Journal de Monaco" of 1892-05-24, online at -# https://journaldemonaco.gouv.mc/var/jdm/storage/original/application/b1c67c12c5af11b41ea888fb048e4fe8.pdf -# we read: ... -# [In virtue of a Sovereign Ordinance of the May 13 of the current [year], -# legal time in the Principality will be set to, from the date of June 1, -# 1892 onwards, to the meridian of Paris, as in France.] -# In the "Journal de Monaco" of 1911-03-28, online at -# https://journaldemonaco.gouv.mc/var/jdm/storage/original/application/de74ffb7db53d4f599059fe8f0ed482a.pdf -# we read an ordinance of 1911-03-16: ... -# [Legal time in the Principality will be set, from the date of promulgation -# of the present ordinance, to legal time in France.... Consequently, legal -# time will be retarded by 9 minutes and 21 seconds.] -# -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Europe/Monaco 0:29:32 - LMT 1892 Jun 1 - 0:09:21 - PMT 1911 Mar 29 # Paris Mean Time - 0:00 France WE%sT 1945 Sep 16 3:00 - 1:00 France CE%sT 1977 - 1:00 EU CE%sT +# See Europe/Paris. # Montenegro # See Europe/Belgrade. # Netherlands - -# Howse writes that the Netherlands' railways used GMT between 1892 and 1940, -# but for other purposes the Netherlands used Amsterdam mean time. - -# However, Robert H. van Gent writes (2001-04-01): -# Howse's statement is only correct up to 1909. From 1909-05-01 (00:00:00 -# Amsterdam mean time) onwards, the whole of the Netherlands (including -# the Dutch railways) was required by law to observe Amsterdam mean time -# (19 minutes 32.13 seconds ahead of GMT). This had already been the -# common practice (except for the railways) for many decades but it was -# not until 1909 when the Dutch government finally defined this by law. -# On 1937-07-01 this was changed to 20 minutes (exactly) ahead of GMT and -# was generally known as Dutch Time ("Nederlandse Tijd"). -# -# (2001-04-08): -# 1892-05-01 was the date when the Dutch railways were by law required to -# observe GMT while the remainder of the Netherlands adhered to the common -# practice of following Amsterdam mean time. -# -# (2001-04-09): -# In 1835 the authorities of the province of North Holland requested the -# municipal authorities of the towns and cities in the province to observe -# Amsterdam mean time but I do not know in how many cases this request was -# actually followed. -# -# From 1852 onwards the Dutch telegraph offices were by law required to -# observe Amsterdam mean time. As the time signals from the observatory of -# Leiden were also distributed by the telegraph system, I assume that most -# places linked up with the telegraph (and railway) system automatically -# adopted Amsterdam mean time. -# -# Although the early Dutch railway companies initially observed a variety -# of times, most of them had adopted Amsterdam mean time by 1858 but it -# was not until 1866 when they were all required by law to observe -# Amsterdam mean time. - -# The data entries before 1945 are taken from -# https://www.staff.science.uu.nl/~gent0113/wettijd/wettijd.htm - -# From Paul Eggert (2021-05-09): -# I invented the abbreviations AMT for Amsterdam Mean Time and NST for -# Netherlands Summer Time, used in the Netherlands from 1835 to 1937. - -# Rule NAME FROM TO - IN ON AT SAVE LETTER/S -Rule Neth 1916 only - May 1 0:00 1:00 NST # Netherlands Summer Time -Rule Neth 1916 only - Oct 1 0:00 0 AMT # Amsterdam Mean Time -Rule Neth 1917 only - Apr 16 2:00s 1:00 NST -Rule Neth 1917 only - Sep 17 2:00s 0 AMT -Rule Neth 1918 1921 - Apr Mon>=1 2:00s 1:00 NST -Rule Neth 1918 1921 - Sep lastMon 2:00s 0 AMT -Rule Neth 1922 only - Mar lastSun 2:00s 1:00 NST -Rule Neth 1922 1936 - Oct Sun>=2 2:00s 0 AMT -Rule Neth 1923 only - Jun Fri>=1 2:00s 1:00 NST -Rule Neth 1924 only - Mar lastSun 2:00s 1:00 NST -Rule Neth 1925 only - Jun Fri>=1 2:00s 1:00 NST -# From 1926 through 1939 DST began 05-15, except that it was delayed by a week -# in years when 05-15 fell in the Pentecost weekend. -Rule Neth 1926 1931 - May 15 2:00s 1:00 NST -Rule Neth 1932 only - May 22 2:00s 1:00 NST -Rule Neth 1933 1936 - May 15 2:00s 1:00 NST -Rule Neth 1937 only - May 22 2:00s 1:00 NST -Rule Neth 1937 only - Jul 1 0:00 1:00 S -Rule Neth 1937 1939 - Oct Sun>=2 2:00s 0 - -Rule Neth 1938 1939 - May 15 2:00s 1:00 S -Rule Neth 1945 only - Apr 2 2:00s 1:00 S -Rule Neth 1945 only - Sep 16 2:00s 0 - -# -# Amsterdam Mean Time was +00:19:32.13, but the .13 is omitted -# below because the current format requires STDOFF to be an integer. -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Europe/Amsterdam 0:19:32 - LMT 1835 - 0:19:32 Neth %s 1937 Jul 1 - 0:20 Neth +0020/+0120 1940 May 16 0:00 - 1:00 C-Eur CE%sT 1945 Apr 2 2:00 - 1:00 Neth CE%sT 1977 - 1:00 EU CE%sT +# See Europe/Brussels. # Norway -# http://met.no/met/met_lex/q_u/sommertid.html (2004-01) agrees with Shanks & -# Pottenger. -# Rule NAME FROM TO - IN ON AT SAVE LETTER/S -Rule Norway 1916 only - May 22 1:00 1:00 S -Rule Norway 1916 only - Sep 30 0:00 0 - -Rule Norway 1945 only - Apr 2 2:00s 1:00 S -Rule Norway 1945 only - Oct 1 2:00s 0 - -Rule Norway 1959 1964 - Mar Sun>=15 2:00s 1:00 S -Rule Norway 1959 1965 - Sep Sun>=15 2:00s 0 - -Rule Norway 1965 only - Apr 25 2:00s 1:00 S -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Europe/Oslo 0:43:00 - LMT 1895 Jan 1 - 1:00 Norway CE%sT 1940 Aug 10 23:00 - 1:00 C-Eur CE%sT 1945 Apr 2 2:00 - 1:00 Norway CE%sT 1980 - 1:00 EU CE%sT +# See Europe/Berlin. # Svalbard & Jan Mayen @@ -2280,9 +2016,9 @@ # the German armed forces at the Svalbard weather station code-named # Haudegen did not surrender to the Allies until September 1945. # -# All these events predate our cutoff date of 1970, so use Europe/Oslo +# All these events predate our cutoff date of 1970, so use Europe/Berlin # for these regions. -Link Europe/Oslo Arctic/Longyearbyen + # Poland @@ -2336,7 +2072,6 @@ # According to a Portuguese decree (1911-05-26) # https://dre.pt/application/dir/pdf1sdip/1911/05/12500/23132313.pdf # Lisbon was at -0:36:44.68, but switched to GMT on 1912-01-01 at 00:00. -# Round the old offset to -0:36:45. This agrees with Willett.... # # From Michael Deckers (2018-02-15): # article 5 [of the 1911 decree; Deckers's translation] ...: @@ -2423,6 +2158,7 @@ Rule Port 1983 only - Mar lastSun 2:00s 1:00 S # # Zone NAME STDOFF RULES FORMAT [UNTIL] + #STDOFF -0:36:44.68 Zone Europe/Lisbon -0:36:45 - LMT 1884 -0:36:45 - LMT 1912 Jan 1 0:00u # Lisbon MT 0:00 Port WE%sT 1966 Apr 3 2:00 @@ -2431,9 +2167,13 @@ 0:00 W-Eur WE%sT 1992 Sep 27 1:00s 1:00 EU CE%sT 1996 Mar 31 1:00u 0:00 EU WE%sT -# This Zone can be simplified once we assume zic %z. Zone Atlantic/Azores -1:42:40 - LMT 1884 # Ponta Delgada -1:54:32 - HMT 1912 Jan 1 2:00u # Horta MT +# Vanguard section, for zic and other parsers that support %z. +# -2:00 Port %z 1966 Apr 3 2:00 +# -1:00 Port %z 1983 Sep 25 1:00s +# -1:00 W-Eur %z 1992 Sep 27 1:00s +# Rearguard section, for parsers lacking %z; see ziguard.awk. -2:00 Port -02/-01 1942 Apr 25 22:00s -2:00 Port +00 1942 Aug 15 22:00s -2:00 Port -02/-01 1943 Apr 17 22:00s @@ -2445,11 +2185,14 @@ -2:00 Port -02/-01 1966 Apr 3 2:00 -1:00 Port -01/+00 1983 Sep 25 1:00s -1:00 W-Eur -01/+00 1992 Sep 27 1:00s +# End of rearguard section. 0:00 EU WE%sT 1993 Mar 28 1:00u -1:00 EU -01/+00 -# This Zone can be simplified once we assume zic %z. Zone Atlantic/Madeira -1:07:36 - LMT 1884 # Funchal -1:07:36 - FMT 1912 Jan 1 1:00u # Funchal MT +# Vanguard section, for zic and other parsers that support %z. +# -1:00 Port %z 1966 Apr 3 2:00 +# Rearguard section, for parsers lacking %z; see ziguard.awk. -1:00 Port -01/+00 1942 Apr 25 22:00s -1:00 Port +01 1942 Aug 15 22:00s -1:00 Port -01/+00 1943 Apr 17 22:00s @@ -2459,6 +2202,7 @@ -1:00 Port -01/+00 1945 Apr 21 22:00s -1:00 Port +01 1945 Aug 25 22:00s -1:00 Port -01/+00 1966 Apr 3 2:00 +# End of rearguard section. 0:00 Port WE%sT 1983 Sep 25 1:00s 0:00 EU WE%sT @@ -2877,20 +2621,19 @@ 2:00 - EET 1992 Mar 20 # Central Crimea used Moscow time 1994/1997. # -# From Paul Eggert (2006-03-22): -# The _Economist_ (1994-05-28, p 45) reports that central Crimea switched -# from Kiev to Moscow time sometime after the January 1994 elections. +# From Paul Eggert (2022-07-21): +# The _Economist_ (1994-05-28, p 45) reported that central Crimea switched +# from Kyiv to Moscow time sometime after the January 1994 elections. # Shanks (1999) says "date of change uncertain", but implies that it happened # sometime between the 1994 DST switches. Shanks & Pottenger simply say # 1994-09-25 03:00, but that can't be right. For now, guess it -# changed in May. +# changed in May. This change evidently didn't last long; see below. 2:00 C-Eur EE%sT 1994 May -# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev. - 3:00 E-Eur MSK/MSD 1996 Mar 31 0:00s +# From IATA SSIM (1994/1997), which also said that Kerch is still like Kyiv. + 3:00 C-Eur MSK/MSD 1996 Mar 31 0:00s 3:00 1:00 MSD 1996 Oct 27 3:00s -# IATA SSIM (1997-09) says Crimea switched to EET/EEST. +# IATA SSIM (1997-09) said Crimea switched to EET/EEST. # Assume it happened in March by not changing the clocks. - 3:00 Russia MSK/MSD 1997 3:00 - MSK 1997 Mar lastSun 1:00u # From Alexander Krivenyshev (2014-03-17): # time change at 2:00 (2am) on March 30, 2014 @@ -3059,11 +2802,12 @@ # Note: Effective 2005-12-01, (59) Perm Oblast and (81) Komi-Permyak # Autonomous Okrug merged to form (90, RU-PER) Perm Krai. -# Milne says Yekaterinburg was 4:02:32.9; round to nearest. +# Milne says Yekaterinburg was 4:02:32.9. # Byalokoz 1919 says its provincial time was based on Perm, at 3:45:05. # Assume it switched on 1916-07-03, the time of the new standard. # The 1919 and 1930 transitions are from Shanks. + #STDOFF 4:02:32.9 Zone Asia/Yekaterinburg 4:02:33 - LMT 1916 Jul 3 3:45:05 - PMT 1919 Jul 15 4:00 4:00 - +04 1930 Jun 21 @@ -3375,8 +3119,8 @@ # 14-28 **** Tomponsky District # 14-30 **** Ust-Maysky District -# From Arthur David Olson (2012-05-09): -# Tomponskij and Ust'-Majskij switched from Vladivostok time to Yakutsk time +# From Arthur David Olson (2022-03-21): +# Tomponsky and Ust-Maysky switched from Vladivostok time to Yakutsk time # in 2011. # From Paul Eggert (2012-11-25): @@ -3501,8 +3245,8 @@ # Asia/Ust-Nera covers parts of (14, RU-SA) Sakha (Yakutia) Republic: # 14-22 **** Oymyakonsky District -# From Arthur David Olson (2012-05-09): -# Ojmyakonskij [and the Kuril Islands] switched from +# From Arthur David Olson (2022-03-21): +# Oymyakonsky and the Kuril Islands switched from # Magadan time to Vladivostok time in 2011. # # From Tim Parenti (2014-07-06), per Alexander Krivenyshev (2014-07-02): @@ -3576,7 +3320,7 @@ Link Europe/Belgrade Europe/Zagreb # Croatia # Slovakia -Link Europe/Prague Europe/Bratislava +# See Europe/Prague. # Slovenia # See Europe/Belgrade. @@ -3665,7 +3409,7 @@ Rule SpainAfrica 1978 only - Jun 1 0:00 1:00 S Rule SpainAfrica 1978 only - Aug 4 0:00 0 - # Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Europe/Madrid -0:14:44 - LMT 1900 Dec 31 23:45:16 +Zone Europe/Madrid -0:14:44 - LMT 1901 Jan 1 0:00u 0:00 Spain WE%sT 1940 Mar 16 23:00 1:00 Spain CE%sT 1979 1:00 EU CE%sT @@ -3687,61 +3431,7 @@ # Ignore this for now, as the Canaries are part of the EU. # Sweden - -# From Ivan Nilsson (2001-04-13), superseding Shanks & Pottenger: -# -# The law "Svensk författningssamling 1878, no 14" about standard time in 1879: -# From the beginning of 1879 (that is 01-01 00:00) the time for all -# places in the country is "the mean solar time for the meridian at -# three degrees, or twelve minutes of time, to the west of the -# meridian of the Observatory of Stockholm". The law is dated 1878-05-31. -# -# The observatory at that time had the meridian 18° 03' 30" -# eastern longitude = 01:12:14 in time. Less 12 minutes gives the -# national standard time as 01:00:14 ahead of GMT.... -# -# About the beginning of CET in Sweden. The lawtext ("Svensk -# författningssamling 1899, no 44") states, that "from the beginning -# of 1900... ... the same as the mean solar time for the meridian at -# the distance of one hour of time from the meridian of the English -# observatory at Greenwich, or at 12 minutes 14 seconds to the west -# from the meridian of the Observatory of Stockholm". The law is dated -# 1899-06-16. In short: At 1900-01-01 00:00:00 the new standard time -# in Sweden is 01:00:00 ahead of GMT. -# -# 1916: The lawtext ("Svensk författningssamling 1916, no 124") states -# that "1916-05-15 is considered to begin one hour earlier". It is -# pretty obvious that at 05-14 23:00 the clocks are set to 05-15 00:00.... -# Further the law says, that "1916-09-30 is considered to end one hour later". -# -# The laws regulating [DST] are available on the site of the Swedish -# Parliament beginning with 1985 - the laws regulating 1980/1984 are -# not available on the site (to my knowledge they are only available -# in Swedish): (type -# "sommartid" without the quotes in the field "Fritext" and then click -# the Sök-button). -# -# (2001-05-13): -# -# I have now found a newspaper stating that at 1916-10-01 01:00 -# summertime the church-clocks etc were set back one hour to show -# 1916-10-01 00:00 standard time. The article also reports that some -# people thought the switch to standard time would take place already -# at 1916-10-01 00:00 summer time, but they had to wait for another -# hour before the event took place. -# -# Source: The newspaper "Dagens Nyheter", 1916-10-01, page 7 upper left. - -# An extra-special abbreviation style is SET for Swedish Time (svensk -# normaltid) 1879-1899, 3° west of the Stockholm Observatory. - -# Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone Europe/Stockholm 1:12:12 - LMT 1879 Jan 1 - 1:00:14 - SET 1900 Jan 1 # Swedish Time - 1:00 - CET 1916 May 14 23:00 - 1:00 1:00 CEST 1916 Oct 1 1:00 - 1:00 - CET 1980 - 1:00 EU CE%sT +# See Europe/Berlin. # Switzerland # From Howse: @@ -3835,6 +3525,19 @@ # 1853-07-16, though it probably occurred at some other date in Zurich, and # legal civil time probably changed at still some other transition date. +# From Tobias Conradi (2011-09-12): +# Büsingen , surrounded by the Swiss canton +# Schaffhausen, did not start observing DST in 1980 as the rest of DE +# (West Germany at that time) and DD (East Germany at that time) did. +# DD merged into DE, the area is currently covered by code DE in ISO 3166-1, +# which in turn is covered by the zone Europe/Berlin. +# +# Source for the time in Büsingen 1980: +# http://www.srf.ch/player/video?id=c012c029-03b7-4c2b-9164-aa5902cd58d3 +# +# From Arthur David Olson (2012-03-03): +# Büsingen and Zurich have shared clocks since 1970. + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule Swiss 1941 1942 - May Mon>=1 1:00 1:00 S Rule Swiss 1941 1942 - Oct Mon>=1 2:00 0 - @@ -3843,6 +3546,9 @@ 0:29:46 - BMT 1894 Jun # Bern Mean Time 1:00 Swiss CE%sT 1981 1:00 EU CE%sT +Link Europe/Zurich Europe/Busingen +Link Europe/Zurich Europe/Vaduz + # Turkey @@ -4051,7 +3757,7 @@ # Ukraine # -# From Alois Triendl (2014-03-01): +# From Alois Treindl (2014-03-01): # REGULATION A N O V A on March 20, 1992 N 139 ... means that from # 1992 on, Ukraine had DST with begin time at 02:00 am, on last Sunday # in March, and end time 03:00 am, last Sunday in September.... @@ -4111,7 +3817,7 @@ # The law documents themselves are at # http://w1.c1.rada.gov.ua/pls/zweb_n/webproc4_1?id=&pf3511=41484 -# From Vladimir in Moscow via Alois Treindl re Kiev time 1991/2 (2014-02-28): +# From Vladimir in Moscow via Alois Treindl re Kyiv time 1991/2 (2014-02-28): # First in Ukraine they changed Time zone from UTC+3 to UTC+2 with DST: # 03 25 1990 02:00 -03.00 1 Time Zone 3 with DST # 07 01 1990 02:00 -02.00 1 Time Zone 2 with DST @@ -4139,23 +3845,23 @@ # * Ukrainian Government's Resolution of 20.03.1992, No. 139. # http://www.uazakon.com/documents/date_8u/pg_grcasa.htm -# From Paul Eggert (2018-10-03): +# From Paul Eggert (2022-04-12): # As is usual in tzdb, Ukrainian zones use the most common English spellings. -# For example, tzdb uses Europe/Kiev, as "Kiev" is the most common spelling in -# English for Ukraine's capital, even though it is certainly wrong as a -# transliteration of the Ukrainian "Київ". This is similar to tzdb's use of -# Europe/Prague, which is certainly wrong as a transliteration of the Czech -# "Praha". ("Kiev" came from old Slavic via Russian to English, and "Prague" -# came from old Slavic via French to English, so the two cases have something -# in common.) Admittedly English-language spelling of Ukrainian names is -# controversial, and some day "Kyiv" may become substantially more popular in -# English; in the meantime, stick with the traditional English "Kiev" as that -# means less disruption for our users. +# In particular, tzdb's name Europe/Kyiv uses the most common spelling in +# English for Ukraine's capital. Although tzdb's former name was Europe/Kiev, +# "Kyiv" is now more common due to widespread reporting of the current conflict. +# Conversely, tzdb continues to use the names Europe/Uzhgorod and +# Europe/Zaporozhye; this is similar to tzdb's use of Europe/Prague, which is +# certainly wrong as a transliteration of the Czech "Praha". +# English-language spelling of Ukrainian names is in flux, and +# some day "Uzhhorod" or "Zaporizhzhia" may become substantially more +# common in English; in the meantime, do not change these +# English spellings as that means less disruption for our users. # Zone NAME STDOFF RULES FORMAT [UNTIL] -# This represents most of Ukraine. See above for the spelling of "Kiev". -Zone Europe/Kiev 2:02:04 - LMT 1880 - 2:02:04 - KMT 1924 May 2 # Kiev Mean Time +# This represents most of Ukraine. See above for the spelling of "Kyiv". +Zone Europe/Kyiv 2:02:04 - LMT 1880 + 2:02:04 - KMT 1924 May 2 # Kyiv Mean Time 2:00 - EET 1930 Jun 21 3:00 - MSK 1941 Sep 20 1:00 C-Eur CE%sT 1943 Nov 6 @@ -4178,7 +3884,7 @@ 2:00 C-Eur EE%sT 1996 May 13 2:00 EU EE%sT # Zaporozh'ye and eastern Lugansk oblasts observed DST 1990/1991. -# "Zaporizhia" is the transliteration of the Ukrainian name, but +# "Zaporizhzhia" is the transliteration of the Ukrainian name, but # "Zaporozh'ye" is more common in English. Use the common English # spelling, except omit the apostrophe as it is not allowed in # portable Posix file names. diff -Nru openjdk-17-17.0.4+8/make/data/tzdata/leapseconds openjdk-17-17.0.5+8/make/data/tzdata/leapseconds --- openjdk-17-17.0.4+8/make/data/tzdata/leapseconds 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/data/tzdata/leapseconds 2022-10-10 13:07:22.000000000 +0000 @@ -95,11 +95,11 @@ # Any additional leap seconds will come after this. # This Expires line is commented out for now, # so that pre-2020a zic implementations do not reject this file. -#Expires 2022 Dec 28 00:00:00 +#Expires 2023 Jun 28 00:00:00 # POSIX timestamps for the data in this file: #updated 1467936000 (2016-07-08 00:00:00 UTC) -#expires 1672185600 (2022-12-28 00:00:00 UTC) +#expires 1687910400 (2023-06-28 00:00:00 UTC) -# Updated through IERS Bulletin C63 -# File expires on: 28 December 2022 +# Updated through IERS Bulletin C64 +# File expires on: 28 June 2023 diff -Nru openjdk-17-17.0.4+8/make/data/tzdata/northamerica openjdk-17-17.0.5+8/make/data/tzdata/northamerica --- openjdk-17-17.0.4+8/make/data/tzdata/northamerica 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/data/tzdata/northamerica 2022-10-10 13:07:22.000000000 +0000 @@ -367,8 +367,7 @@ # From Paul Eggert (2014-09-06): # Monthly Notices of the Royal Astronomical Society 44, 4 (1884-02-08), 208 # says that New York City Hall time was 3 minutes 58.4 seconds fast of -# Eastern time (i.e., -4:56:01.6) just before the 1883 switch. Round to the -# nearest second. +# Eastern time (i.e., -4:56:01.6) just before the 1883 switch. # Rule NAME FROM TO - IN ON AT SAVE LETTER Rule NYC 1920 only - Mar lastSun 2:00 1:00 D @@ -377,7 +376,8 @@ Rule NYC 1921 1954 - Sep lastSun 2:00 0 S Rule NYC 1955 1966 - Oct lastSun 2:00 0 S # Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone America/New_York -4:56:02 - LMT 1883 Nov 18 12:03:58 + #STDOFF -4:56:01.6 +Zone America/New_York -4:56:02 - LMT 1883 Nov 18 17:00u -5:00 US E%sT 1920 -5:00 NYC E%sT 1942 -5:00 US E%sT 1946 @@ -2841,7 +2841,7 @@ # Barbados -# For 1899 Milne gives -3:58:29.2; round that. +# For 1899 Milne gives -3:58:29.2. # From P Chan (2020-12-09 and 2020-12-11): # Standard time of GMT-4 was adopted in 1911. @@ -2885,6 +2885,7 @@ Rule Barb 1979 only - Sep 30 2:00 0 S Rule Barb 1980 only - Sep 25 2:00 0 S # Zone NAME STDOFF RULES FORMAT [UNTIL] + #STDOFF -3:58:29.2 Zone America/Barbados -3:58:29 - LMT 1911 Aug 28 # Bridgetown -4:00 Barb A%sT 1944 -4:00 Barb AST/-0330 1945 @@ -2945,10 +2946,10 @@ # Bermuda -# From Paul Eggert (2020-11-24): +# From Paul Eggert (2022-07-27): # For 1899 Milne gives -4:19:18.3 as the meridian of the clock tower, # Bermuda dockyard, Ireland I. This agrees with standard offset given in the -# Daylight Saving Act, 1917 cited below. Round that to the nearest second. +# Daylight Saving Act, 1917 cited below. # It is not known when this time became standard for Bermuda; guess 1890. # The transition to -04 was specified by: # 1930: The Time Zone Act, 1929 (1929: No. 39) [1929-11-08] @@ -3043,6 +3044,7 @@ Rule Bermuda 1956 only - Oct lastSun 2:00 0 S # Zone NAME STDOFF RULES FORMAT [UNTIL] + #STDOFF -4:19:18.3 Zone Atlantic/Bermuda -4:19:18 - LMT 1890 # Hamilton -4:19:18 Bermuda BMT/BST 1930 Jan 1 2:00 -4:00 Bermuda A%sT 1974 Apr 28 2:00 @@ -3057,7 +3059,7 @@ # Costa Rica -# Milne gives -5:36:13.3 as San José mean time; round to nearest. +# Milne gives -5:36:13.3 as San José mean time. # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule CR 1979 1980 - Feb lastSun 0:00 1:00 D @@ -3069,6 +3071,7 @@ Rule CR 1992 only - Mar 15 0:00 0 S # There are too many San Josés elsewhere, so we'll use 'Costa Rica'. # Zone NAME STDOFF RULES FORMAT [UNTIL] + #STDOFF -5:36:13.3 Zone America/Costa_Rica -5:36:13 - LMT 1890 # San José -5:36:13 - SJMT 1921 Jan 15 # San José Mean Time -6:00 CR C%sT @@ -3491,7 +3494,7 @@ # Jamaica # Shanks & Pottenger give -5:07:12, but Milne records -5:07:10.41 from an # unspecified official document, and says "This time is used throughout the -# island". Go with Milne. Round to the nearest second as required by zic. +# island". Go with Milne. # # Shanks & Pottenger give April 28 for the 1974 spring-forward transition, but # Lance Neita writes that Prime Minister Michael Manley decreed it January 5. @@ -3504,6 +3507,7 @@ # http://www.jamaicaobserver.com/columns/The-politician-in-all-of-us_17573647 # # Zone NAME STDOFF RULES FORMAT [UNTIL] + #STDOFF -5:07:10.41 Zone America/Jamaica -5:07:10 - LMT 1890 # Kingston -5:07:10 - KMT 1912 Feb # Kingston Mean Time -5:00 - EST 1974 @@ -3701,6 +3705,7 @@ # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone America/Grand_Turk -4:44:32 - LMT 1890 + #STDOFF -5:07:10.41 -5:07:10 - KMT 1912 Feb # Kingston Mean Time -5:00 - EST 1979 -5:00 US E%sT 2015 Mar 8 2:00 diff -Nru openjdk-17-17.0.4+8/make/data/tzdata/southamerica openjdk-17-17.0.5+8/make/data/tzdata/southamerica --- openjdk-17-17.0.4+8/make/data/tzdata/southamerica 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/data/tzdata/southamerica 2022-10-10 13:07:22.000000000 +0000 @@ -423,6 +423,7 @@ # # Buenos Aires (BA), Capital Federal (CF), Zone America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 Oct 31 + #STDOFF -4:16:48.25 -4:16:48 - CMT 1920 May # Córdoba Mean Time -4:00 - -04 1930 Dec -4:00 Arg -04/-03 1969 Oct 5 @@ -440,6 +441,7 @@ # - Santiago del Estero switched to -4:00 on 1991-04-01, # then to -3:00 on 1991-04-26. # + #STDOFF -4:16:48.25 Zone America/Argentina/Cordoba -4:16:48 - LMT 1894 Oct 31 -4:16:48 - CMT 1920 May -4:00 - -04 1930 Dec @@ -452,6 +454,7 @@ # # Salta (SA), La Pampa (LP), Neuquén (NQ), Rio Negro (RN) Zone America/Argentina/Salta -4:21:40 - LMT 1894 Oct 31 + #STDOFF -4:16:48.25 -4:16:48 - CMT 1920 May -4:00 - -04 1930 Dec -4:00 Arg -04/-03 1969 Oct 5 @@ -464,6 +467,7 @@ # # Tucumán (TM) Zone America/Argentina/Tucuman -4:20:52 - LMT 1894 Oct 31 + #STDOFF -4:16:48.25 -4:16:48 - CMT 1920 May -4:00 - -04 1930 Dec -4:00 Arg -04/-03 1969 Oct 5 @@ -477,6 +481,7 @@ # # La Rioja (LR) Zone America/Argentina/La_Rioja -4:27:24 - LMT 1894 Oct 31 + #STDOFF -4:16:48.25 -4:16:48 - CMT 1920 May -4:00 - -04 1930 Dec -4:00 Arg -04/-03 1969 Oct 5 @@ -491,6 +496,7 @@ # # San Juan (SJ) Zone America/Argentina/San_Juan -4:34:04 - LMT 1894 Oct 31 + #STDOFF -4:16:48.25 -4:16:48 - CMT 1920 May -4:00 - -04 1930 Dec -4:00 Arg -04/-03 1969 Oct 5 @@ -505,6 +511,7 @@ # # Jujuy (JY) Zone America/Argentina/Jujuy -4:21:12 - LMT 1894 Oct 31 + #STDOFF -4:16:48.25 -4:16:48 - CMT 1920 May -4:00 - -04 1930 Dec -4:00 Arg -04/-03 1969 Oct 5 @@ -520,6 +527,7 @@ # # Catamarca (CT), Chubut (CH) Zone America/Argentina/Catamarca -4:23:08 - LMT 1894 Oct 31 + #STDOFF -4:16:48.25 -4:16:48 - CMT 1920 May -4:00 - -04 1930 Dec -4:00 Arg -04/-03 1969 Oct 5 @@ -534,6 +542,7 @@ # # Mendoza (MZ) Zone America/Argentina/Mendoza -4:35:16 - LMT 1894 Oct 31 + #STDOFF -4:16:48.25 -4:16:48 - CMT 1920 May -4:00 - -04 1930 Dec -4:00 Arg -04/-03 1969 Oct 5 @@ -556,6 +565,7 @@ Rule SanLuis 2007 2008 - Oct Sun>=8 0:00 1:00 - Zone America/Argentina/San_Luis -4:25:24 - LMT 1894 Oct 31 + #STDOFF -4:16:48.25 -4:16:48 - CMT 1920 May -4:00 - -04 1930 Dec -4:00 Arg -04/-03 1969 Oct 5 @@ -574,6 +584,7 @@ # # Santa Cruz (SC) Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31 + #STDOFF -4:16:48.25 -4:16:48 - CMT 1920 May -4:00 - -04 1930 Dec -4:00 Arg -04/-03 1969 Oct 5 @@ -586,6 +597,7 @@ # # Tierra del Fuego, Antártida e Islas del Atlántico Sur (TF) Zone America/Argentina/Ushuaia -4:33:12 - LMT 1894 Oct 31 + #STDOFF -4:16:48.25 -4:16:48 - CMT 1920 May -4:00 - -04 1930 Dec -4:00 Arg -04/-03 1969 Oct 5 @@ -668,7 +680,7 @@ # From Rodrigo Severo (2004-10-04): # It's just the biannual change made necessary by the much hyped, supposedly -# modern Brazilian eletronic voting machines which, apparently, can't deal +# modern Brazilian ... voting machines which, apparently, can't deal # with a time change between the first and the second rounds of the elections. # From Steffen Thorsen (2007-09-20): @@ -1164,7 +1176,7 @@ # this is known to work for DST transitions starting in 2008 and # may well be true for earlier transitions. -# From Tim Parenti (2022-03-15): +# From Tim Parenti (2022-07-06): # For a brief period of roughly six weeks in 1946, DST was only observed on an # emergency basis in specific regions of central Chile; namely, "the national # territory between the provinces of Coquimbo and Concepción, inclusive". @@ -1182,7 +1194,14 @@ # Law Number 8,522, promulgated 1946-08-27, reunified Chilean clocks at their # new "Summer Time" of -04, reckoned as that of "the meridian of the # Astronomical Observatory of Lo Espejo, advanced by 42 minutes and 45 -# seconds". +# seconds". Although this law specified the new Summer Time to start on 1 +# September each year, a special "transitional article" started it a few days +# early, as soon as the law took effect. As the law was to take force "from +# the date of its publication in the 'Diario Oficial', which happened the +# following day, presume the change took place in Santiago and its environs +# from 24:00 -03 to 23:00 -04 on Wednesday 1946-08-28. Although this was a +# no-op for wall clocks in the north and south of the country, put their formal +# start to DST an hour later when they reached 24:00 -04. # https://www.diariooficial.interior.gob.cl/versiones-anteriores/do-h/19460828/#page/1 # After a brief "Winter Time" stint at -05 beginning 1947-04-01, Law Number # 8,777, promulgated 1947-05-17, established year-round -04 "from 23:00 on the @@ -1302,11 +1321,19 @@ # So we extend the new rules on Saturdays at 24:00 mainland time indefinitely. # From Juan Correa (2019-02-04): # http://www.diariooficial.interior.gob.cl/publicaciones/2018/11/23/42212/01/1498738.pdf -# From Paul Eggert (2019-09-01): -# The above says the Magallanes exception expires 2022-04-02 at 24:00, -# so in theory, they will revert to -04/-03 after that. -# For now, assume that they will not revert, -# since they have extended the expiration date once already. + +# From Juan Correa (2022-04-02): +# I found there was a decree published last Thursday that will keep +# Magallanes region to UTC -3 "indefinitely". The decree is available at +# https://www.diariooficial.interior.gob.cl/publicaciones/2022/03/31/43217-B/01/2108910.pdf + +# From Juan Correa (2022-08-09): +# the Internal Affairs Ministry (Ministerio del Interior) informed DST +# for America/Santiago will start on midnight of September 11th; +# and will end on April 1st, 2023. Magallanes region (America/Punta_Arenas) +# will keep UTC -3 "indefinitely"... This is because on September 4th +# we will have a voting whether to approve a new Constitution.... +# https://www.interior.gob.cl/noticias/2022/08/09/comunicado-el-proximo-sabado-10-de-septiembre-los-relojes-se-deben-adelantar-una-hora/ # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule Chile 1927 1931 - Sep 1 0:00 1:00 - @@ -1344,7 +1371,9 @@ Rule Chile 2016 2018 - May Sun>=9 3:00u 0 - Rule Chile 2016 2018 - Aug Sun>=9 4:00u 1:00 - Rule Chile 2019 max - Apr Sun>=2 3:00u 0 - -Rule Chile 2019 max - Sep Sun>=2 4:00u 1:00 - +Rule Chile 2019 2021 - Sep Sun>=2 4:00u 1:00 - +Rule Chile 2022 only - Sep Sun>=9 4:00u 1:00 - +Rule Chile 2023 max - Sep Sun>=2 4:00u 1:00 - # IATA SSIM anomalies: (1992-02) says 1992-03-14; # (1996-09) says 1998-03-08. Ignore these. # Zone NAME STDOFF RULES FORMAT [UNTIL] @@ -1357,9 +1386,9 @@ -5:00 Chile -05/-04 1932 Sep 1 -4:00 - -04 1942 Jun 1 -5:00 - -05 1942 Aug 1 - -4:00 - -04 1946 Jul 15 - -4:00 1:00 -03 1946 Sep 1 # central Chile - -4:00 - -04 1947 Apr 1 + -4:00 - -04 1946 Jul 14 24:00 + -4:00 1:00 -03 1946 Aug 28 24:00 # central CL + -5:00 1:00 -04 1947 Mar 31 24:00 -5:00 - -05 1947 May 21 23:00 -4:00 Chile -04/-03 Zone America/Punta_Arenas -4:43:40 - LMT 1890 @@ -1371,7 +1400,8 @@ -5:00 Chile -05/-04 1932 Sep 1 -4:00 - -04 1942 Jun 1 -5:00 - -05 1942 Aug 1 - -4:00 - -04 1947 Apr 1 + -4:00 - -04 1946 Aug 28 24:00 + -5:00 1:00 -04 1947 Mar 31 24:00 -5:00 - -05 1947 May 21 23:00 -4:00 Chile -04/-03 2016 Dec 4 -3:00 - -03 @@ -1405,13 +1435,14 @@ # Colombia -# Milne gives 4:56:16.4 for Bogotá time in 1899; round to nearest. He writes, +# Milne gives 4:56:16.4 for Bogotá time in 1899. He writes, # "A variation of fifteen minutes in the public clocks of Bogota is not rare." # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule CO 1992 only - May 3 0:00 1:00 - Rule CO 1993 only - Apr 4 0:00 0 - # Zone NAME STDOFF RULES FORMAT [UNTIL] + #STDOFF -4:56:16.4 Zone America/Bogota -4:56:16 - LMT 1884 Mar 13 -4:56:16 - BMT 1914 Nov 23 # Bogotá Mean Time -5:00 CO -05/-04 diff -Nru openjdk-17-17.0.4+8/make/data/tzdata/VERSION openjdk-17-17.0.5+8/make/data/tzdata/VERSION --- openjdk-17-17.0.4+8/make/data/tzdata/VERSION 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/data/tzdata/VERSION 2022-10-10 13:07:22.000000000 +0000 @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2022a +tzdata2022c diff -Nru openjdk-17-17.0.4+8/make/data/tzdata/zone.tab openjdk-17-17.0.5+8/make/data/tzdata/zone.tab --- openjdk-17-17.0.4+8/make/data/tzdata/zone.tab 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/data/tzdata/zone.tab 2022-10-10 13:07:22.000000000 +0000 @@ -153,7 +153,7 @@ CA +6227-11421 America/Yellowknife Mountain - NT (central) CA +682059-1334300 America/Inuvik Mountain - NT (west) CA +4906-11631 America/Creston MST - BC (Creston) -CA +5946-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John) +CA +5546-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John) CA +5848-12242 America/Fort_Nelson MST - BC (Ft Nelson) CA +6043-13503 America/Whitehorse MST - Yukon (east) CA +6404-13925 America/Dawson MST - Yukon (west) @@ -423,7 +423,7 @@ TV -0831+17913 Pacific/Funafuti TW +2503+12130 Asia/Taipei TZ -0648+03917 Africa/Dar_es_Salaam -UA +5026+03031 Europe/Kiev Ukraine (most areas) +UA +5026+03031 Europe/Kyiv Ukraine (most areas) UA +4837+02218 Europe/Uzhgorod Transcarpathia UA +4750+03510 Europe/Zaporozhye Zaporozhye and east Lugansk UG +0019+03225 Africa/Kampala diff -Nru openjdk-17-17.0.4+8/make/devkit/createWindowsDevkit2019.sh openjdk-17-17.0.5+8/make/devkit/createWindowsDevkit2019.sh --- openjdk-17-17.0.4+8/make/devkit/createWindowsDevkit2019.sh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/devkit/createWindowsDevkit2019.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,227 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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. -# - -# This script copies parts of a Visual Studio installation into a devkit -# suitable for building OpenJDK and OracleJDK. Needs to run in Cygwin or WSL. -# erik.joelsson@oracle.com - -VS_VERSION="2019" -VS_VERSION_NUM_NODOT="160" -VS_DLL_VERSION="140" -SDK_VERSION="10" -SDK_FULL_VERSION="10.0.17763.0" -MSVC_DIR="Microsoft.VC142.CRT" -MSVC_FULL_VERSION="14.12.27508" -REDIST_FULL_VERSION="14.20.27508" - -SCRIPT_DIR="$(cd "$(dirname $0)" > /dev/null && pwd)" -BUILD_DIR="${SCRIPT_DIR}/../../build/devkit" - -################################################################################ -# Prepare settings - -UNAME_SYSTEM=`uname -s` -UNAME_RELEASE=`uname -r` - -# Detect cygwin or WSL -IS_CYGWIN=`echo $UNAME_SYSTEM | grep -i CYGWIN` -IS_WSL=`echo $UNAME_RELEASE | grep Microsoft` -if test "x$IS_CYGWIN" != "x"; then - BUILD_ENV="cygwin" -elif test "x$IS_WSL" != "x"; then - BUILD_ENV="wsl" -else - echo "Unknown environment; only Cygwin and WSL are supported." - exit 1 -fi - -if test "x$BUILD_ENV" = "xcygwin"; then - WINDOWS_PATH_TO_UNIX_PATH="cygpath -u" -elif test "x$BUILD_ENV" = "xwsl"; then - WINDOWS_PATH_TO_UNIX_PATH="wslpath -u" -fi - -# Work around the insanely named ProgramFiles(x86) env variable -PROGRAMFILES_X86="$($WINDOWS_PATH_TO_UNIX_PATH "$(cmd.exe /c set | sed -n 's/^ProgramFiles(x86)=//p' | tr -d '\r')")" - -# Find Visual Studio installation dir -VSNNNCOMNTOOLS=`cmd.exe /c echo %VS${VS_VERSION_NUM_NODOT}COMNTOOLS% | tr -d '\r'` -if [ -d "$VSNNNCOMNTOOLS" ]; then - VS_INSTALL_DIR="$($WINDOWS_PATH_TO_UNIX_PATH "$VSNNNCOMNTOOLS/../..")" -else - VS_INSTALL_DIR="${PROGRAMFILES_X86}/Microsoft Visual Studio/2019" - VS_INSTALL_DIR="$(ls -d "${VS_INSTALL_DIR}/"{Community,Professional,Enterprise} 2>/dev/null | head -n1)" -fi -echo "VS_INSTALL_DIR: $VS_INSTALL_DIR" - -# Extract semantic version -POTENTIAL_INI_FILES="Common7/IDE/wdexpress.isolation.ini Common7/IDE/devenv.isolation.ini" -for f in $POTENTIAL_INI_FILES; do - if [ -f "$VS_INSTALL_DIR/$f" ]; then - VS_VERSION_SP="$(grep ^SemanticVersion= "$VS_INSTALL_DIR/$f")" - # Remove SemnaticVersion= - VS_VERSION_SP="${VS_VERSION_SP#*=}" - # Remove suffix of too detailed numbering starting with + - VS_VERSION_SP="${VS_VERSION_SP%+*}" - break - fi -done -if [ -z "$VS_VERSION_SP" ]; then - echo "Failed to find SP version" - exit 1 -fi -echo "Found Version SP: $VS_VERSION_SP" - -# Setup output dirs -DEVKIT_ROOT="${BUILD_DIR}/VS${VS_VERSION}-${VS_VERSION_SP}-devkit" -DEVKIT_BUNDLE="${DEVKIT_ROOT}.tar.gz" - -echo "Creating devkit in $DEVKIT_ROOT" - -MSVCR_DLL=${MSVC_DIR}/vcruntime${VS_DLL_VERSION}.dll -VCRUNTIME_1_DLL=${MSVC_DIR}/vcruntime${VS_DLL_VERSION}_1.dll -MSVCP_DLL=${MSVC_DIR}/msvcp${VS_DLL_VERSION}.dll - -################################################################################ -# Copy Visual Studio files - -TOOLS_VERSION="$(ls "$VS_INSTALL_DIR/VC/Tools/MSVC" | sort -r -n | head -n1)" -echo "Found Tools version: $TOOLS_VERSION" -VC_SUBDIR="VC/Tools/MSVC/$TOOLS_VERSION" -REDIST_VERSION="$(ls "$VS_INSTALL_DIR/VC/Redist/MSVC" | sort -r -n | head -n1)" -echo "Found Redist version: $REDIST_VERSION" -REDIST_SUBDIR="VC/Redist/MSVC/$REDIST_VERSION" -echo "Copying VC..." -rm -rf $DEVKIT_ROOT/VC -mkdir -p $DEVKIT_ROOT/VC/bin -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx64/arm64" $DEVKIT_ROOT/VC/bin/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx64/x64" $DEVKIT_ROOT/VC/bin/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx86/x86" $DEVKIT_ROOT/VC/bin/ -mkdir -p $DEVKIT_ROOT/VC/lib -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/lib/arm64" $DEVKIT_ROOT/VC/lib/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/lib/x64" $DEVKIT_ROOT/VC/lib/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/lib/x86" $DEVKIT_ROOT/VC/lib/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/include" $DEVKIT_ROOT/VC/ -mkdir -p $DEVKIT_ROOT/VC/atlmfc/lib -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/lib/arm64" $DEVKIT_ROOT/VC/atlmfc/lib/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/lib/x64" $DEVKIT_ROOT/VC/atlmfc/lib/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/lib/x86" $DEVKIT_ROOT/VC/atlmfc/lib/ -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/include" $DEVKIT_ROOT/VC/atlmfc/ -mkdir -p $DEVKIT_ROOT/VC/Auxiliary -cp -r "$VS_INSTALL_DIR/VC/Auxiliary/Build" $DEVKIT_ROOT/VC/Auxiliary/ -mkdir -p $DEVKIT_ROOT/VC/redist -cp -r "$VS_INSTALL_DIR/$REDIST_SUBDIR/arm64" $DEVKIT_ROOT/VC/redist/ -cp -r "$VS_INSTALL_DIR/$REDIST_SUBDIR/x64" $DEVKIT_ROOT/VC/redist/ -cp -r "$VS_INSTALL_DIR/$REDIST_SUBDIR/x86" $DEVKIT_ROOT/VC/redist/ - -# The redist runtime libs are needed to run the compiler but may not be -# installed on the machine where the devkit will be used. -cp $DEVKIT_ROOT/VC/redist/x86/$MSVCR_DLL $DEVKIT_ROOT/VC/bin/x86 -cp $DEVKIT_ROOT/VC/redist/x86/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/x86 -cp $DEVKIT_ROOT/VC/redist/x64/$MSVCR_DLL $DEVKIT_ROOT/VC/bin/x64 -cp $DEVKIT_ROOT/VC/redist/x64/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/x64 -cp $DEVKIT_ROOT/VC/redist/arm64/$MSVCR_DLL $DEVKIT_ROOT/VC/bin/arm64 -cp $DEVKIT_ROOT/VC/redist/arm64/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/arm64 - -################################################################################ -# Copy SDK files - -SDK_INSTALL_DIR="$PROGRAMFILES_X86/Windows Kits/$SDK_VERSION" -echo "SDK_INSTALL_DIR: $SDK_INSTALL_DIR" - -SDK_FULL_VERSION="$(ls "$SDK_INSTALL_DIR/bin" | sort -r -n | head -n1)" -echo "Found SDK version: $SDK_FULL_VERSION" -UCRT_VERSION="$(ls "$SDK_INSTALL_DIR/Redist" | grep $SDK_VERSION | sort -r -n | head -n1)" -echo "Found UCRT version: $UCRT_VERSION" -echo "Copying SDK..." -rm -rf $DEVKIT_ROOT/$SDK_VERSION -mkdir -p $DEVKIT_ROOT/$SDK_VERSION/bin -cp -r "$SDK_INSTALL_DIR/bin/$SDK_FULL_VERSION/x64" $DEVKIT_ROOT/$SDK_VERSION/bin/ -cp -r "$SDK_INSTALL_DIR/bin/$SDK_FULL_VERSION/x86" $DEVKIT_ROOT/$SDK_VERSION/bin/ -mkdir -p $DEVKIT_ROOT/$SDK_VERSION/lib -cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/um/arm64" $DEVKIT_ROOT/$SDK_VERSION/lib/ -cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/um/x64" $DEVKIT_ROOT/$SDK_VERSION/lib/ -cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/um/x86" $DEVKIT_ROOT/$SDK_VERSION/lib/ -cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/ucrt/arm64" $DEVKIT_ROOT/$SDK_VERSION/lib/ -cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/ucrt/x64" $DEVKIT_ROOT/$SDK_VERSION/lib/ -cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/ucrt/x86" $DEVKIT_ROOT/$SDK_VERSION/lib/ -mkdir -p $DEVKIT_ROOT/$SDK_VERSION/Redist -cp -r "$SDK_INSTALL_DIR/Redist/$UCRT_VERSION/ucrt" $DEVKIT_ROOT/$SDK_VERSION/Redist/ -mkdir -p $DEVKIT_ROOT/$SDK_VERSION/include -cp -r "$SDK_INSTALL_DIR/include/$SDK_FULL_VERSION/"* $DEVKIT_ROOT/$SDK_VERSION/include/ - -################################################################################ -# Generate devkit.info - -echo-info() { - echo "$1" >> $DEVKIT_ROOT/devkit.info -} - -echo "Generating devkit.info..." -rm -f $DEVKIT_ROOT/devkit.info -echo-info "# This file describes to configure how to interpret the contents of this devkit" -echo-info "DEVKIT_NAME=\"Microsoft Visual Studio $VS_VERSION $VS_VERSION_SP (devkit)\"" -echo-info "DEVKIT_VS_VERSION=\"$VS_VERSION\"" -echo-info "" -echo-info "DEVKIT_TOOLCHAIN_PATH_x86=\"\$DEVKIT_ROOT/VC/bin/x86:\$DEVKIT_ROOT/$SDK_VERSION/bin/x86\"" -echo-info "DEVKIT_VS_INCLUDE_x86=\"\$DEVKIT_ROOT/VC/include;\$DEVKIT_ROOT/VC/atlmfc/include;\$DEVKIT_ROOT/$SDK_VERSION/include/shared;\$DEVKIT_ROOT/$SDK_VERSION/include/ucrt;\$DEVKIT_ROOT/$SDK_VERSION/include/um;\$DEVKIT_ROOT/$SDK_VERSION/include/winrt\"" -echo-info "DEVKIT_VS_LIB_x86=\"\$DEVKIT_ROOT/VC/lib/x86;\$DEVKIT_ROOT/VC/atlmfc/lib/x86;\$DEVKIT_ROOT/$SDK_VERSION/lib/x86\"" -echo-info "DEVKIT_MSVCR_DLL_x86=\"\$DEVKIT_ROOT/VC/redist/x86/$MSVCR_DLL\"" -echo-info "DEVKIT_MSVCP_DLL_x86=\"\$DEVKIT_ROOT/VC/redist/x86/$MSVCP_DLL\"" -echo-info "DEVKIT_UCRT_DLL_DIR_x86=\"\$DEVKIT_ROOT/10/Redist/ucrt/DLLs/x86\"" -echo-info "" -echo-info "DEVKIT_TOOLCHAIN_PATH_x86_64=\"\$DEVKIT_ROOT/VC/bin/x64:\$DEVKIT_ROOT/$SDK_VERSION/bin/x64:\$DEVKIT_ROOT/$SDK_VERSION/bin/x86\"" -echo-info "DEVKIT_VS_INCLUDE_x86_64=\"\$DEVKIT_ROOT/VC/include;\$DEVKIT_ROOT/VC/atlmfc/include;\$DEVKIT_ROOT/$SDK_VERSION/include/shared;\$DEVKIT_ROOT/$SDK_VERSION/include/ucrt;\$DEVKIT_ROOT/$SDK_VERSION/include/um;\$DEVKIT_ROOT/$SDK_VERSION/include/winrt\"" -echo-info "DEVKIT_VS_LIB_x86_64=\"\$DEVKIT_ROOT/VC/lib/x64;\$DEVKIT_ROOT/VC/atlmfc/lib/x64;\$DEVKIT_ROOT/$SDK_VERSION/lib/x64\"" -echo-info "DEVKIT_MSVCR_DLL_x86_64=\"\$DEVKIT_ROOT/VC/redist/x64/$MSVCR_DLL\"" -echo-info "DEVKIT_VCRUNTIME_1_DLL_x86_64=\"\$DEVKIT_ROOT/VC/redist/x64/$VCRUNTIME_1_DLL\"" -echo-info "DEVKIT_MSVCP_DLL_x86_64=\"\$DEVKIT_ROOT/VC/redist/x64/$MSVCP_DLL\"" -echo-info "DEVKIT_UCRT_DLL_DIR_x86_64=\"\$DEVKIT_ROOT/10/Redist/ucrt/DLLs/x64\"" -echo-info "" -echo-info "DEVKIT_TOOLCHAIN_PATH_aarch64=\"\$DEVKIT_ROOT/VC/bin/arm64:\$DEVKIT_ROOT/$SDK_VERSION/bin/x64:\$DEVKIT_ROOT/$SDK_VERSION/bin/x86\"" -echo-info "DEVKIT_VS_INCLUDE_aarch64=\"\$DEVKIT_ROOT/VC/include;\$DEVKIT_ROOT/VC/atlmfc/include;\$DEVKIT_ROOT/$SDK_VERSION/include/shared;\$DEVKIT_ROOT/$SDK_VERSION/include/ucrt;\$DEVKIT_ROOT/$SDK_VERSION/include/um;\$DEVKIT_ROOT/$SDK_VERSION/include/winrt\"" -echo-info "DEVKIT_VS_LIB_aarch64=\"\$DEVKIT_ROOT/VC/lib/arm64;\$DEVKIT_ROOT/VC/atlmfc/lib/arm64;\$DEVKIT_ROOT/$SDK_VERSION/lib/arm64\"" -echo-info "DEVKIT_MSVCR_DLL_aarch64=\"\$DEVKIT_ROOT/VC/redist/arm64/$MSVCR_DLL\"" -echo-info "DEVKIT_VCRUNTIME_1_DLL_aarch64=\"\$DEVKIT_ROOT/VC/redist/arm64/$VCRUNTIME_1_DLL\"" -echo-info "DEVKIT_MSVCP_DLL_aarch64=\"\$DEVKIT_ROOT/VC/redist/arm64/$MSVCP_DLL\"" -echo-info "DEVKIT_UCRT_DLL_DIR_aarch64=\"\$DEVKIT_ROOT/10/Redist/ucrt/DLLs/arm64\"" -echo-info "" -echo-info "DEVKIT_TOOLS_VERSION=\"$TOOLS_VERSION\"" -echo-info "DEVKIT_REDIST_VERSION=\"$REDIST_VERSION\"" -echo-info "DEVKIT_SDK_VERSION=\"$SDK_FULL_VERSION\"" -echo-info "DEVKIT_UCRT_VERSION=\"$UCRT_VERSION\"" - -################################################################################ -# Copy this script - -echo "Copying this script..." -cp $0 $DEVKIT_ROOT/ - -################################################################################ -# Create bundle - -echo "Creating bundle: $DEVKIT_BUNDLE" -(cd "$DEVKIT_ROOT" && tar zcf "$DEVKIT_BUNDLE" .) diff -Nru openjdk-17-17.0.4+8/make/devkit/createWindowsDevkit.sh openjdk-17-17.0.5+8/make/devkit/createWindowsDevkit.sh --- openjdk-17-17.0.4+8/make/devkit/createWindowsDevkit.sh 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/make/devkit/createWindowsDevkit.sh 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,252 @@ +#!/bin/bash +# +# Copyright (c) 2015, 2022, 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. +# + +# This script copies parts of a Visual Studio installation into a devkit +# suitable for building OpenJDK and OracleJDK. Needs to run in Cygwin or WSL. +# erik.joelsson@oracle.com + +usage_and_exit() { + echo "Usage: createWindowsDevkit.sh <2019 | 2022>" + exit 1 +} + +if [ ! $# = 1 ]; then + usage_and_exit +fi + +VS_VERSION="$1" + +VS_DLL_VERSION="140" +SDK_VERSION="10" + +SCRIPT_DIR="$(cd "$(dirname $0)" > /dev/null && pwd)" +BUILD_DIR="${SCRIPT_DIR}/../../build/devkit" + +################################################################################ +# Prepare settings + +UNAME_SYSTEM=`uname -s` +UNAME_RELEASE=`uname -r` + +# Detect cygwin or WSL +IS_CYGWIN=`echo $UNAME_SYSTEM | grep -i CYGWIN` +IS_WSL=`echo $UNAME_RELEASE | grep Microsoft` +if test "x$IS_CYGWIN" != "x"; then + BUILD_ENV="cygwin" +elif test "x$IS_WSL" != "x"; then + BUILD_ENV="wsl" +else + echo "Unknown environment; only Cygwin and WSL are supported." + exit 1 +fi + +if test "x$BUILD_ENV" = "xcygwin"; then + WINDOWS_PATH_TO_UNIX_PATH="cygpath -u" +elif test "x$BUILD_ENV" = "xwsl"; then + WINDOWS_PATH_TO_UNIX_PATH="wslpath -u" +fi + +# Work around the insanely named ProgramFiles(x86) env variable +PROGRAMFILES_X86="$($WINDOWS_PATH_TO_UNIX_PATH "$(cmd.exe /c set | sed -n 's/^ProgramFiles(x86)=//p' | tr -d '\r')")" +PROGRAMFILES="$($WINDOWS_PATH_TO_UNIX_PATH "$PROGRAMFILES")" + +case $VS_VERSION in + 2019) + MSVC_PROGRAMFILES_DIR="${PROGRAMFILES_X86}" + MSVC_CRT_DIR="Microsoft.VC142.CRT" + VS_VERSION_NUM_NODOT="160" + ;; + + 2022) + MSVC_PROGRAMFILES_DIR="${PROGRAMFILES}" + MSVC_CRT_DIR="Microsoft.VC143.CRT" + VS_VERSION_NUM_NODOT="170" + ;; + *) + echo "Unexpected VS version: $VS_VERSION" + usage_and_exit + ;; +esac + + +# Find Visual Studio installation dir +VSNNNCOMNTOOLS=`cmd.exe /c echo %VS${VS_VERSION_NUM_NODOT}COMNTOOLS% | tr -d '\r'` +if [ -d "$VSNNNCOMNTOOLS" ]; then + VS_INSTALL_DIR="$($WINDOWS_PATH_TO_UNIX_PATH "$VSNNNCOMNTOOLS/../..")" +else + VS_INSTALL_DIR="${MSVC_PROGRAMFILES_DIR}/Microsoft Visual Studio/$VS_VERSION" + VS_INSTALL_DIR="$(ls -d "${VS_INSTALL_DIR}/"{Community,Professional,Enterprise} 2>/dev/null | head -n1)" +fi +echo "VS_INSTALL_DIR: $VS_INSTALL_DIR" + +# Extract semantic version +POTENTIAL_INI_FILES="Common7/IDE/wdexpress.isolation.ini Common7/IDE/devenv.isolation.ini" +for f in $POTENTIAL_INI_FILES; do + if [ -f "$VS_INSTALL_DIR/$f" ]; then + VS_VERSION_SP="$(grep ^SemanticVersion= "$VS_INSTALL_DIR/$f")" + # Remove SemnaticVersion= + VS_VERSION_SP="${VS_VERSION_SP#*=}" + # Remove suffix of too detailed numbering starting with + + VS_VERSION_SP="${VS_VERSION_SP%+*}" + break + fi +done +if [ -z "$VS_VERSION_SP" ]; then + echo "Failed to find SP version" + exit 1 +fi +echo "Found Version SP: $VS_VERSION_SP" + +# Setup output dirs +DEVKIT_ROOT="${BUILD_DIR}/VS${VS_VERSION}-${VS_VERSION_SP}-devkit" +DEVKIT_BUNDLE="${DEVKIT_ROOT}.tar.gz" + +echo "Creating devkit in $DEVKIT_ROOT" + +MSVCR_DLL=${MSVC_CRT_DIR}/vcruntime${VS_DLL_VERSION}.dll +VCRUNTIME_1_DLL=${MSVC_CRT_DIR}/vcruntime${VS_DLL_VERSION}_1.dll +MSVCP_DLL=${MSVC_CRT_DIR}/msvcp${VS_DLL_VERSION}.dll + +################################################################################ +# Copy Visual Studio files + +TOOLS_VERSION="$(ls "$VS_INSTALL_DIR/VC/Tools/MSVC" | sort -r -n | head -n1)" +echo "Found Tools version: $TOOLS_VERSION" +VC_SUBDIR="VC/Tools/MSVC/$TOOLS_VERSION" +REDIST_VERSION="$(ls "$VS_INSTALL_DIR/VC/Redist/MSVC" | sort -r -n | head -n1)" +echo "Found Redist version: $REDIST_VERSION" +REDIST_SUBDIR="VC/Redist/MSVC/$REDIST_VERSION" +echo "Copying VC..." +rm -rf $DEVKIT_ROOT/VC +mkdir -p $DEVKIT_ROOT/VC/bin +cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx64/arm64" $DEVKIT_ROOT/VC/bin/ +cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx64/x64" $DEVKIT_ROOT/VC/bin/ +cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx86/x86" $DEVKIT_ROOT/VC/bin/ +mkdir -p $DEVKIT_ROOT/VC/lib +cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/lib/arm64" $DEVKIT_ROOT/VC/lib/ +cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/lib/x64" $DEVKIT_ROOT/VC/lib/ +cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/lib/x86" $DEVKIT_ROOT/VC/lib/ +cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/include" $DEVKIT_ROOT/VC/ +mkdir -p $DEVKIT_ROOT/VC/atlmfc/lib +cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/lib/arm64" $DEVKIT_ROOT/VC/atlmfc/lib/ +cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/lib/x64" $DEVKIT_ROOT/VC/atlmfc/lib/ +cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/lib/x86" $DEVKIT_ROOT/VC/atlmfc/lib/ +cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/atlmfc/include" $DEVKIT_ROOT/VC/atlmfc/ +mkdir -p $DEVKIT_ROOT/VC/Auxiliary +cp -r "$VS_INSTALL_DIR/VC/Auxiliary/Build" $DEVKIT_ROOT/VC/Auxiliary/ +mkdir -p $DEVKIT_ROOT/VC/redist +cp -r "$VS_INSTALL_DIR/$REDIST_SUBDIR/arm64" $DEVKIT_ROOT/VC/redist/ +cp -r "$VS_INSTALL_DIR/$REDIST_SUBDIR/x64" $DEVKIT_ROOT/VC/redist/ +cp -r "$VS_INSTALL_DIR/$REDIST_SUBDIR/x86" $DEVKIT_ROOT/VC/redist/ + +# The redist runtime libs are needed to run the compiler but may not be +# installed on the machine where the devkit will be used. +cp $DEVKIT_ROOT/VC/redist/x86/$MSVCR_DLL $DEVKIT_ROOT/VC/bin/x86 +cp $DEVKIT_ROOT/VC/redist/x86/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/x86 +cp $DEVKIT_ROOT/VC/redist/x64/$MSVCR_DLL $DEVKIT_ROOT/VC/bin/x64 +cp $DEVKIT_ROOT/VC/redist/x64/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/x64 +cp $DEVKIT_ROOT/VC/redist/arm64/$MSVCR_DLL $DEVKIT_ROOT/VC/bin/arm64 +cp $DEVKIT_ROOT/VC/redist/arm64/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/arm64 + +################################################################################ +# Copy SDK files + +SDK_INSTALL_DIR="$PROGRAMFILES_X86/Windows Kits/$SDK_VERSION" +echo "SDK_INSTALL_DIR: $SDK_INSTALL_DIR" + +SDK_FULL_VERSION="$(ls "$SDK_INSTALL_DIR/bin" | sort -r -n | head -n1)" +echo "Found SDK version: $SDK_FULL_VERSION" +UCRT_VERSION="$(ls "$SDK_INSTALL_DIR/Redist" | grep $SDK_VERSION | sort -r -n | head -n1)" +echo "Found UCRT version: $UCRT_VERSION" +echo "Copying SDK..." +rm -rf $DEVKIT_ROOT/$SDK_VERSION +mkdir -p $DEVKIT_ROOT/$SDK_VERSION/bin +cp -r "$SDK_INSTALL_DIR/bin/$SDK_FULL_VERSION/x64" $DEVKIT_ROOT/$SDK_VERSION/bin/ +cp -r "$SDK_INSTALL_DIR/bin/$SDK_FULL_VERSION/x86" $DEVKIT_ROOT/$SDK_VERSION/bin/ +mkdir -p $DEVKIT_ROOT/$SDK_VERSION/lib +cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/um/arm64" $DEVKIT_ROOT/$SDK_VERSION/lib/ +cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/um/x64" $DEVKIT_ROOT/$SDK_VERSION/lib/ +cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/um/x86" $DEVKIT_ROOT/$SDK_VERSION/lib/ +cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/ucrt/arm64" $DEVKIT_ROOT/$SDK_VERSION/lib/ +cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/ucrt/x64" $DEVKIT_ROOT/$SDK_VERSION/lib/ +cp -r "$SDK_INSTALL_DIR/lib/$SDK_FULL_VERSION/ucrt/x86" $DEVKIT_ROOT/$SDK_VERSION/lib/ +mkdir -p $DEVKIT_ROOT/$SDK_VERSION/Redist +cp -r "$SDK_INSTALL_DIR/Redist/$UCRT_VERSION/ucrt" $DEVKIT_ROOT/$SDK_VERSION/Redist/ +mkdir -p $DEVKIT_ROOT/$SDK_VERSION/include +cp -r "$SDK_INSTALL_DIR/include/$SDK_FULL_VERSION/"* $DEVKIT_ROOT/$SDK_VERSION/include/ + +################################################################################ +# Generate devkit.info + +echo-info() { + echo "$1" >> $DEVKIT_ROOT/devkit.info +} + +echo "Generating devkit.info..." +rm -f $DEVKIT_ROOT/devkit.info +echo-info "# This file describes to configure how to interpret the contents of this devkit" +echo-info "DEVKIT_NAME=\"Microsoft Visual Studio $VS_VERSION $VS_VERSION_SP (devkit)\"" +echo-info "DEVKIT_VS_VERSION=\"$VS_VERSION\"" +echo-info "" +echo-info "DEVKIT_TOOLCHAIN_PATH_x86=\"\$DEVKIT_ROOT/VC/bin/x86:\$DEVKIT_ROOT/$SDK_VERSION/bin/x86\"" +echo-info "DEVKIT_VS_INCLUDE_x86=\"\$DEVKIT_ROOT/VC/include;\$DEVKIT_ROOT/VC/atlmfc/include;\$DEVKIT_ROOT/$SDK_VERSION/include/shared;\$DEVKIT_ROOT/$SDK_VERSION/include/ucrt;\$DEVKIT_ROOT/$SDK_VERSION/include/um;\$DEVKIT_ROOT/$SDK_VERSION/include/winrt\"" +echo-info "DEVKIT_VS_LIB_x86=\"\$DEVKIT_ROOT/VC/lib/x86;\$DEVKIT_ROOT/VC/atlmfc/lib/x86;\$DEVKIT_ROOT/$SDK_VERSION/lib/x86\"" +echo-info "DEVKIT_MSVCR_DLL_x86=\"\$DEVKIT_ROOT/VC/redist/x86/$MSVCR_DLL\"" +echo-info "DEVKIT_MSVCP_DLL_x86=\"\$DEVKIT_ROOT/VC/redist/x86/$MSVCP_DLL\"" +echo-info "DEVKIT_UCRT_DLL_DIR_x86=\"\$DEVKIT_ROOT/10/Redist/ucrt/DLLs/x86\"" +echo-info "" +echo-info "DEVKIT_TOOLCHAIN_PATH_x86_64=\"\$DEVKIT_ROOT/VC/bin/x64:\$DEVKIT_ROOT/$SDK_VERSION/bin/x64:\$DEVKIT_ROOT/$SDK_VERSION/bin/x86\"" +echo-info "DEVKIT_VS_INCLUDE_x86_64=\"\$DEVKIT_ROOT/VC/include;\$DEVKIT_ROOT/VC/atlmfc/include;\$DEVKIT_ROOT/$SDK_VERSION/include/shared;\$DEVKIT_ROOT/$SDK_VERSION/include/ucrt;\$DEVKIT_ROOT/$SDK_VERSION/include/um;\$DEVKIT_ROOT/$SDK_VERSION/include/winrt\"" +echo-info "DEVKIT_VS_LIB_x86_64=\"\$DEVKIT_ROOT/VC/lib/x64;\$DEVKIT_ROOT/VC/atlmfc/lib/x64;\$DEVKIT_ROOT/$SDK_VERSION/lib/x64\"" +echo-info "DEVKIT_MSVCR_DLL_x86_64=\"\$DEVKIT_ROOT/VC/redist/x64/$MSVCR_DLL\"" +echo-info "DEVKIT_VCRUNTIME_1_DLL_x86_64=\"\$DEVKIT_ROOT/VC/redist/x64/$VCRUNTIME_1_DLL\"" +echo-info "DEVKIT_MSVCP_DLL_x86_64=\"\$DEVKIT_ROOT/VC/redist/x64/$MSVCP_DLL\"" +echo-info "DEVKIT_UCRT_DLL_DIR_x86_64=\"\$DEVKIT_ROOT/10/Redist/ucrt/DLLs/x64\"" +echo-info "" +echo-info "DEVKIT_TOOLCHAIN_PATH_aarch64=\"\$DEVKIT_ROOT/VC/bin/arm64:\$DEVKIT_ROOT/$SDK_VERSION/bin/x64:\$DEVKIT_ROOT/$SDK_VERSION/bin/x86\"" +echo-info "DEVKIT_VS_INCLUDE_aarch64=\"\$DEVKIT_ROOT/VC/include;\$DEVKIT_ROOT/VC/atlmfc/include;\$DEVKIT_ROOT/$SDK_VERSION/include/shared;\$DEVKIT_ROOT/$SDK_VERSION/include/ucrt;\$DEVKIT_ROOT/$SDK_VERSION/include/um;\$DEVKIT_ROOT/$SDK_VERSION/include/winrt\"" +echo-info "DEVKIT_VS_LIB_aarch64=\"\$DEVKIT_ROOT/VC/lib/arm64;\$DEVKIT_ROOT/VC/atlmfc/lib/arm64;\$DEVKIT_ROOT/$SDK_VERSION/lib/arm64\"" +echo-info "DEVKIT_MSVCR_DLL_aarch64=\"\$DEVKIT_ROOT/VC/redist/arm64/$MSVCR_DLL\"" +echo-info "DEVKIT_VCRUNTIME_1_DLL_aarch64=\"\$DEVKIT_ROOT/VC/redist/arm64/$VCRUNTIME_1_DLL\"" +echo-info "DEVKIT_MSVCP_DLL_aarch64=\"\$DEVKIT_ROOT/VC/redist/arm64/$MSVCP_DLL\"" +echo-info "DEVKIT_UCRT_DLL_DIR_aarch64=\"\$DEVKIT_ROOT/10/Redist/ucrt/DLLs/arm64\"" +echo-info "" +echo-info "DEVKIT_TOOLS_VERSION=\"$TOOLS_VERSION\"" +echo-info "DEVKIT_REDIST_VERSION=\"$REDIST_VERSION\"" +echo-info "DEVKIT_SDK_VERSION=\"$SDK_FULL_VERSION\"" +echo-info "DEVKIT_UCRT_VERSION=\"$UCRT_VERSION\"" + +################################################################################ +# Copy this script + +echo "Copying this script..." +cp $0 $DEVKIT_ROOT/ + +################################################################################ +# Create bundle + +echo "Creating bundle: $DEVKIT_BUNDLE" +(cd "$DEVKIT_ROOT" && tar zcf "$DEVKIT_BUNDLE" .) diff -Nru openjdk-17-17.0.4+8/make/modules/java.base/lib/CoreLibraries.gmk openjdk-17-17.0.5+8/make/modules/java.base/lib/CoreLibraries.gmk --- openjdk-17-17.0.4+8/make/modules/java.base/lib/CoreLibraries.gmk 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/modules/java.base/lib/CoreLibraries.gmk 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2022, 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 @@ -135,6 +135,7 @@ $(LIBZ_CFLAGS), \ CFLAGS_unix := $(BUILD_LIBZIP_MMAP) -UDEBUG, \ DISABLED_WARNINGS_gcc := unused-function implicit-fallthrough, \ + DISABLED_WARNINGS_clang := format-nonliteral, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_unix := -ljvm -ljava $(LIBZ_LIBS), \ diff -Nru openjdk-17-17.0.4+8/make/modules/java.desktop/lib/Awt2dLibraries.gmk openjdk-17-17.0.5+8/make/modules/java.desktop/lib/Awt2dLibraries.gmk --- openjdk-17-17.0.4+8/make/modules/java.desktop/lib/Awt2dLibraries.gmk 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/modules/java.desktop/lib/Awt2dLibraries.gmk 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2022, 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 @@ -368,6 +368,7 @@ common/awt/debug \ common/font \ common/java2d/opengl \ + include \ # LIBAWT_HEADLESS_CFLAGS := $(CUPS_CFLAGS) $(FONTCONFIG_CFLAGS) $(X_CFLAGS) \ @@ -477,6 +478,7 @@ libawt/java2d \ libawt/java2d/pipe \ libawt/java2d/loops \ + include \ # LIBFONTMANAGER_CFLAGS += $(LIBFREETYPE_CFLAGS) @@ -656,6 +658,8 @@ common/awt/systemscale \ # + LIBSPLASHSCREEN_HEADER_DIRS += include + ifeq ($(USE_EXTERNAL_LIBGIF), false) LIBSPLASHSCREEN_HEADER_DIRS += libsplashscreen/giflib else @@ -680,6 +684,7 @@ ifeq ($(USE_EXTERNAL_LIBZ), false) LIBSPLASHSCREEN_EXTRA_SRC += java.base:libzip/zlib + LIBZ_DISABLED_WARNINGS_CLANG := format-nonliteral endif ifeq ($(call isTargetOs, macosx), true) @@ -749,7 +754,7 @@ maybe-uninitialized shift-negative-value implicit-fallthrough \ unused-function, \ DISABLED_WARNINGS_clang := incompatible-pointer-types sign-compare \ - deprecated-declarations, \ + deprecated-declarations null-pointer-subtraction $(LIBZ_DISABLED_WARNINGS_CLANG), \ DISABLED_WARNINGS_microsoft := 4018 4244 4267, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff -Nru openjdk-17-17.0.4+8/make/modules/jdk.jpackage/Lib.gmk openjdk-17-17.0.5+8/make/modules/jdk.jpackage/Lib.gmk --- openjdk-17-17.0.4+8/make/modules/jdk.jpackage/Lib.gmk 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/modules/jdk.jpackage/Lib.gmk 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2022, 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,6 +24,7 @@ # include LibCommon.gmk +include LauncherCommon.gmk ################################################################################ @@ -75,6 +76,8 @@ LIBS_macosx := $(LIBCXX) -framework Cocoa, \ LIBS_windows := $(LIBCXX), \ LIBS_linux := -ldl, \ + MANIFEST := $(JAVA_MANIFEST), \ + MANIFEST_VERSION := $(VERSION_NUMBER_FOUR_POSITIONS) \ )) JPACKAGE_TARGETS += $(BUILD_JPACKAGE_APPLAUNCHEREXE) @@ -92,9 +95,9 @@ JPACKAGE_LIBAPPLAUNCHER_INCLUDES := $(addprefix -I, $(JPACKAGE_LIBAPPLAUNCHER_SRC)) $(eval $(call SetupJdkLibrary, BUILD_JPACKAGE_LIBAPPLAUNCHER, \ - NAME := jpackageapplauncher, \ + NAME := jpackageapplauncheraux, \ OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \ - SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjpackageapplauncher, \ + SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjpackageapplauncheraux, \ SRC := $(JPACKAGE_LIBAPPLAUNCHER_SRC), \ EXCLUDE_FILES := LinuxLauncher.c LinuxPackage.c, \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ @@ -175,6 +178,8 @@ LDFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LDFLAGS), \ LIBS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LIBS), \ LIBS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LIBS_windows), \ + MANIFEST := $(JAVA_MANIFEST), \ + MANIFEST_VERSION := $(VERSION_NUMBER_FOUR_POSITIONS) \ )) JPACKAGE_TARGETS += $(BUILD_JPACKAGE_APPLAUNCHERWEXE) diff -Nru openjdk-17-17.0.4+8/make/scripts/fixpath.sh openjdk-17-17.0.5+8/make/scripts/fixpath.sh --- openjdk-17-17.0.4+8/make/scripts/fixpath.sh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/make/scripts/fixpath.sh 2022-10-10 13:07:22.000000000 +0000 @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2022, 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,6 +28,14 @@ # available, or extract values automatically from the environment if missing. # This is robust, but slower. function setup() { + + # Make regexp tests case insensitive + shopt -s nocasematch + # Prohibit msys2 from meddling with paths + export MSYS2_ARG_CONV_EXCL="*" + # Make sure WSL gets a copy of the path + export WSLENV=PATH/l + while getopts "e:p:r:t:c:qmi" opt; do case "$opt" in e) PATHTOOL="$OPTARG" ;; @@ -87,13 +95,6 @@ wintemp_win="$($CMD /q /c echo %TEMP% 2>/dev/null | tr -d \\n\\r)" WINTEMP="$($PATHTOOL -u "$wintemp_win")" fi - - # Make regexp tests case insensitive - shopt -s nocasematch - # Prohibit msys2 from meddling with paths - export MSYS2_ARG_CONV_EXCL="*" - # Make sure WSL gets a copy of the path - export WSLENV=PATH/l } # Cleanup handling @@ -299,6 +300,19 @@ if [[ $arg =~ ^([^/]*|-[^:=]*[:=]|.*file://|/[a-zA-Z:]{1,3}:?)($DRIVEPREFIX/)([a-z])(/[^/]+.*$) ]] ; then prefix="${BASH_REMATCH[1]}" winpath="${BASH_REMATCH[3]}:${BASH_REMATCH[4]}" + + # If the thing in its entirety points to an existing path, use that instead of thinking + # we have a prefix. This can only happen if the top-level directory has a single-letter name. + if [[ ${#prefix} -eq 2 && "${prefix:0:1}" == "/" ]]; then + possiblepath="${BASH_REMATCH[1]}/${BASH_REMATCH[3]}${BASH_REMATCH[4]}" + if [[ -e "$possiblepath" || -e "$(dirname $possiblepath)" || -e "$(echo $possiblepath | cut -d / -f 1-5)" ]] ; then + prefix= + drivepart="${possiblepath:1:1}" + pathpart="${possiblepath:2}" + winpath="$drivepart:$pathpart" + fi + fi + # Change slash to backslash (or vice versa if mixed mode) if [[ $MIXEDMODE != true ]]; then winpath="${winpath//'/'/'\'}" diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/aarch64/aarch64.ad openjdk-17-17.0.5+8/src/hotspot/cpu/aarch64/aarch64.ad --- openjdk-17-17.0.4+8/src/hotspot/cpu/aarch64/aarch64.ad 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/aarch64/aarch64.ad 2022-10-10 13:07:22.000000000 +0000 @@ -15060,10 +15060,10 @@ %{ match(Set cr (OverflowAddL op1 op2)); - format %{ "cmn $op1, $op2\t# overflow check long" %} + format %{ "adds zr, $op1, $op2\t# overflow check long" %} ins_cost(INSN_COST); ins_encode %{ - __ cmn($op1$$Register, $op2$$constant); + __ adds(zr, $op1$$Register, $op2$$constant); %} ins_pipe(icmp_reg_imm); diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/aarch64/frame_aarch64.cpp openjdk-17-17.0.5+8/src/hotspot/cpu/aarch64/frame_aarch64.cpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/aarch64/frame_aarch64.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/aarch64/frame_aarch64.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -350,13 +350,9 @@ assert(jfa->last_Java_sp() > sp(), "must be above this frame on stack"); // Since we are walking the stack now this nested anchor is obviously walkable // even if it wasn't when it was stacked. - if (!jfa->walkable()) { - // Capture _last_Java_pc (if needed) and mark anchor walkable. - jfa->capture_last_Java_pc(); - } + jfa->make_walkable(); map->clear(); assert(map->include_argument_oops(), "should be set by clear"); - vmassert(jfa->last_Java_pc() != NULL, "not walkable"); frame fr(jfa->last_Java_sp(), jfa->last_Java_fp(), jfa->last_Java_pc()); return fr; @@ -817,20 +813,14 @@ void frame::pd_ps() {} #endif -void JavaFrameAnchor::make_walkable(JavaThread* thread) { +void JavaFrameAnchor::make_walkable() { // last frame set? if (last_Java_sp() == NULL) return; // already walkable? if (walkable()) return; - vmassert(Thread::current() == (Thread*)thread, "not current thread"); vmassert(last_Java_sp() != NULL, "not called from Java code?"); vmassert(last_Java_pc() == NULL, "already walkable"); - capture_last_Java_pc(); + _last_Java_pc = (address)_last_Java_sp[-1]; vmassert(walkable(), "something went wrong"); } -void JavaFrameAnchor::capture_last_Java_pc() { - vmassert(_last_Java_sp != NULL, "no last frame set"); - vmassert(_last_Java_pc == NULL, "already walkable"); - _last_Java_pc = (address)_last_Java_sp[-1]; -} diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -144,10 +144,12 @@ inline bool frame::is_older(intptr_t* id) const { assert(this->id() != NULL && id != NULL, "NULL frame id"); return this->id() > id ; } - - inline intptr_t* frame::link() const { return (intptr_t*) *(intptr_t **)addr_at(link_offset); } +inline intptr_t* frame::link_or_null() const { + intptr_t** ptr = (intptr_t **)addr_at(link_offset); + return os::is_readable_pointer(ptr) ? *ptr : NULL; +} inline intptr_t* frame::unextended_sp() const { return _unextended_sp; } diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/aarch64/javaFrameAnchor_aarch64.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/aarch64/javaFrameAnchor_aarch64.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/aarch64/javaFrameAnchor_aarch64.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/aarch64/javaFrameAnchor_aarch64.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -65,8 +65,8 @@ } bool walkable(void) { return _last_Java_sp != NULL && _last_Java_pc != NULL; } - void make_walkable(JavaThread* thread); - void capture_last_Java_pc(void); + + void make_walkable(); intptr_t* last_Java_sp(void) const { return _last_Java_sp; } diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp openjdk-17-17.0.5+8/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -721,8 +721,23 @@ || entry.rspec().type() == relocInfo::static_call_type || entry.rspec().type() == relocInfo::virtual_call_type, "wrong reloc type"); + bool need_trampoline = far_branches(); + if (!need_trampoline && entry.rspec().type() == relocInfo::runtime_call_type && !CodeCache::contains(entry.target())) { + // If it is a runtime call of an address outside small CodeCache, + // we need to check whether it is in range. + address target = entry.target(); + assert(target < CodeCache::low_bound() || target >= CodeCache::high_bound(), "target is inside CodeCache"); + // Case 1: -------T-------L====CodeCache====H------- + // ^-------longest branch---| + // Case 2: -------L====CodeCache====H-------T------- + // |-------longest branch ---^ + address longest_branch_start = (target < CodeCache::low_bound()) ? CodeCache::high_bound() - NativeInstruction::instruction_size + : CodeCache::low_bound(); + need_trampoline = !reachable_from_branch_at(longest_branch_start, target); + } + // We need a trampoline if branches are far. - if (far_branches()) { + if (need_trampoline) { bool in_scratch_emit_size = false; #ifdef COMPILER2 // We don't want to emit a trampoline if C2 is generating dummy @@ -743,7 +758,7 @@ if (cbuf) cbuf->set_insts_mark(); relocate(entry.rspec()); - if (!far_branches()) { + if (!need_trampoline) { bl(entry.target()); } else { bl(pc()); @@ -2270,11 +2285,13 @@ // If a constant does not fit in an immediate field, generate some // number of MOV instructions and then perform the operation. -void MacroAssembler::wrap_add_sub_imm_insn(Register Rd, Register Rn, unsigned imm, +void MacroAssembler::wrap_add_sub_imm_insn(Register Rd, Register Rn, uint64_t imm, add_sub_imm_insn insn1, - add_sub_reg_insn insn2) { + add_sub_reg_insn insn2, + bool is32) { assert(Rd != zr, "Rd = zr and not setting flags?"); - if (operand_valid_for_add_sub_immediate((int)imm)) { + bool fits = operand_valid_for_add_sub_immediate(is32 ? (int32_t)imm : imm); + if (fits) { (this->*insn1)(Rd, Rn, imm); } else { if (uabs(imm) < (1 << 24)) { @@ -2282,7 +2299,7 @@ (this->*insn1)(Rd, Rd, imm & ((1 << 12)-1)); } else { assert_different_registers(Rd, Rn); - mov(Rd, (uint64_t)imm); + mov(Rd, imm); (this->*insn2)(Rd, Rn, Rd, LSL, 0); } } @@ -2290,15 +2307,17 @@ // Seperate vsn which sets the flags. Optimisations are more restricted // because we must set the flags correctly. -void MacroAssembler::wrap_adds_subs_imm_insn(Register Rd, Register Rn, unsigned imm, - add_sub_imm_insn insn1, - add_sub_reg_insn insn2) { - if (operand_valid_for_add_sub_immediate((int)imm)) { +void MacroAssembler::wrap_adds_subs_imm_insn(Register Rd, Register Rn, uint64_t imm, + add_sub_imm_insn insn1, + add_sub_reg_insn insn2, + bool is32) { + bool fits = operand_valid_for_add_sub_immediate(is32 ? (int32_t)imm : imm); + if (fits) { (this->*insn1)(Rd, Rn, imm); } else { assert_different_registers(Rd, Rn); assert(Rd != zr, "overflow in immediate operand"); - mov(Rd, (uint64_t)imm); + mov(Rd, imm); (this->*insn2)(Rd, Rn, Rd, LSL, 0); } } @@ -3342,7 +3361,7 @@ crc32x(crc, crc, tmp2); crc32x(crc, crc, tmp3); br(Assembler::GE, CRC_by32_loop); - cmn(len, 32); + cmn(len, (u1)32); br(Assembler::NE, CRC_less32); b(L_exit); @@ -3405,7 +3424,7 @@ sub(len, len, 64); add(buf, buf, 8); - cmn(len, 128); + cmn(len, (u1)128); br(Assembler::NE, CRC_less64); BIND(L_exit); mvnw(crc, crc); @@ -3639,7 +3658,7 @@ crc32cx(crc, crc, tmp2); crc32cx(crc, crc, tmp3); br(Assembler::GE, CRC_by32_loop); - cmn(len, 32); + cmn(len, (u1)32); br(Assembler::NE, CRC_less32); b(L_exit); @@ -3702,7 +3721,7 @@ sub(len, len, 64); add(buf, buf, 8); - cmn(len, 128); + cmn(len, (u1)128); br(Assembler::NE, CRC_less64); BIND(L_exit); } diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -206,8 +206,11 @@ inline void cmp(Register Rd, unsigned char imm8) { subs(zr, Rd, imm8); } inline void cmp(Register Rd, unsigned imm) = delete; - inline void cmnw(Register Rd, unsigned imm) { addsw(zr, Rd, imm); } - inline void cmn(Register Rd, unsigned imm) { adds(zr, Rd, imm); } + template + inline void cmnw(Register Rd, T imm) { addsw(zr, Rd, imm); } + + inline void cmn(Register Rd, unsigned char imm8) { adds(zr, Rd, imm8); } + inline void cmn(Register Rd, unsigned imm) = delete; void cset(Register Rd, Assembler::Condition cond) { csinc(Rd, zr, zr, ~cond); @@ -225,7 +228,7 @@ inline void movw(Register Rd, Register Rn) { if (Rd == sp || Rn == sp) { - addw(Rd, Rn, 0U); + Assembler::addw(Rd, Rn, 0U); } else { orrw(Rd, zr, Rn); } @@ -234,7 +237,7 @@ assert(Rd != r31_sp && Rn != r31_sp, "should be"); if (Rd == Rn) { } else if (Rd == sp || Rn == sp) { - add(Rd, Rn, 0U); + Assembler::add(Rd, Rn, 0U); } else { orr(Rd, zr, Rn); } @@ -1133,17 +1136,17 @@ // If a constant does not fit in an immediate field, generate some // number of MOV instructions and then perform the operation - void wrap_add_sub_imm_insn(Register Rd, Register Rn, unsigned imm, + void wrap_add_sub_imm_insn(Register Rd, Register Rn, uint64_t imm, add_sub_imm_insn insn1, - add_sub_reg_insn insn2); + add_sub_reg_insn insn2, bool is32); // Seperate vsn which sets the flags - void wrap_adds_subs_imm_insn(Register Rd, Register Rn, unsigned imm, - add_sub_imm_insn insn1, - add_sub_reg_insn insn2); - -#define WRAP(INSN) \ - void INSN(Register Rd, Register Rn, unsigned imm) { \ - wrap_add_sub_imm_insn(Rd, Rn, imm, &Assembler::INSN, &Assembler::INSN); \ + void wrap_adds_subs_imm_insn(Register Rd, Register Rn, uint64_t imm, + add_sub_imm_insn insn1, + add_sub_reg_insn insn2, bool is32); + +#define WRAP(INSN, is32) \ + void INSN(Register Rd, Register Rn, uint64_t imm) { \ + wrap_add_sub_imm_insn(Rd, Rn, imm, &Assembler::INSN, &Assembler::INSN, is32); \ } \ \ void INSN(Register Rd, Register Rn, Register Rm, \ @@ -1160,12 +1163,12 @@ Assembler::INSN(Rd, Rn, Rm, option, amount); \ } - WRAP(add) WRAP(addw) WRAP(sub) WRAP(subw) + WRAP(add, false) WRAP(addw, true) WRAP(sub, false) WRAP(subw, true) #undef WRAP -#define WRAP(INSN) \ - void INSN(Register Rd, Register Rn, unsigned imm) { \ - wrap_adds_subs_imm_insn(Rd, Rn, imm, &Assembler::INSN, &Assembler::INSN); \ +#define WRAP(INSN, is32) \ + void INSN(Register Rd, Register Rn, uint64_t imm) { \ + wrap_adds_subs_imm_insn(Rd, Rn, imm, &Assembler::INSN, &Assembler::INSN, is32); \ } \ \ void INSN(Register Rd, Register Rn, Register Rm, \ @@ -1182,7 +1185,7 @@ Assembler::INSN(Rd, Rn, Rm, option, amount); \ } - WRAP(adds) WRAP(addsw) WRAP(subs) WRAP(subsw) + WRAP(adds, false) WRAP(addsw, true) WRAP(subs, false) WRAP(subsw, true) void add(Register Rd, Register Rn, RegisterOrConstant increment); void addw(Register Rd, Register Rn, RegisterOrConstant increment); diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp openjdk-17-17.0.5+8/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -6619,7 +6619,7 @@ assert(is_even(framesize/2), "sp not 16-byte aligned"); // lr and fp are already in place - __ sub(sp, rfp, ((unsigned)framesize-4) << LogBytesPerInt); // prolog + __ sub(sp, rfp, ((uint64_t)framesize-4) << LogBytesPerInt); // prolog int frame_complete = __ pc() - start; diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/arm/frame_arm.inline.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/arm/frame_arm.inline.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/arm/frame_arm.inline.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/arm/frame_arm.inline.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -124,9 +124,13 @@ inline bool frame::is_older(intptr_t* id) const { assert(this->id() != NULL && id != NULL, "NULL frame id"); return this->id() > id ; } - inline intptr_t* frame::link() const { return (intptr_t*) *(intptr_t **)addr_at(link_offset); } +inline intptr_t* frame::link_or_null() const { + intptr_t** ptr = (intptr_t **)addr_at(link_offset); + return os::is_readable_pointer(ptr) ? *ptr : NULL; +} + inline intptr_t* frame::unextended_sp() const { return _unextended_sp; } // Return address: diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/arm/javaFrameAnchor_arm.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/arm/javaFrameAnchor_arm.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/arm/javaFrameAnchor_arm.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/arm/javaFrameAnchor_arm.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -65,7 +65,7 @@ // Always walkable bool walkable(void) { return true; } // Never any thing to do since we are always walkable and can find address of return addresses - void make_walkable(JavaThread* thread) { } + void make_walkable() { } intptr_t* last_Java_sp(void) const { return _last_Java_sp; } diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/ppc/frame_ppc.inline.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/ppc/frame_ppc.inline.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/ppc/frame_ppc.inline.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/ppc/frame_ppc.inline.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -117,6 +117,10 @@ return (intptr_t*)callers_abi()->callers_sp; } +inline intptr_t* frame::link_or_null() const { + return link(); +} + inline intptr_t* frame::real_fp() const { return fp(); } diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp openjdk-17-17.0.5+8/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1,6 +1,6 @@ /* * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021 SAP SE. All rights reserved. + * Copyright (c) 2021, 2022 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 @@ -400,36 +400,40 @@ #define __ _masm-> class ZSaveLiveRegisters { - - private: MacroAssembler* _masm; RegMask _reg_mask; Register _result_reg; + int _frame_size; public: ZSaveLiveRegisters(MacroAssembler *masm, ZLoadBarrierStubC2 *stub) : _masm(masm), _reg_mask(stub->live()), _result_reg(stub->ref()) { - const int total_regs_amount = iterate_over_register_mask(ACTION_SAVE); + const int register_save_size = iterate_over_register_mask(ACTION_COUNT_ONLY) * BytesPerWord; + _frame_size = align_up(register_save_size, frame::alignment_in_bytes) + + frame::abi_reg_args_size; __ save_LR_CR(R0); - __ push_frame_reg_args(total_regs_amount * BytesPerWord, R0); + __ push_frame(_frame_size, R0); + + iterate_over_register_mask(ACTION_SAVE, _frame_size); } ~ZSaveLiveRegisters() { - __ pop_frame(); - __ restore_LR_CR(R0); + iterate_over_register_mask(ACTION_RESTORE, _frame_size); - iterate_over_register_mask(ACTION_RESTORE); + __ addi(R1_SP, R1_SP, _frame_size); + __ restore_LR_CR(R0); } private: enum IterationAction : int { - ACTION_SAVE = 0, - ACTION_RESTORE = 1 + ACTION_SAVE, + ACTION_RESTORE, + ACTION_COUNT_ONLY }; - int iterate_over_register_mask(IterationAction action) { + int iterate_over_register_mask(IterationAction action, int offset = 0) { int reg_save_index = 0; RegMaskIterator live_regs_iterator(_reg_mask); @@ -454,11 +458,11 @@ reg_save_index++; if (action == ACTION_SAVE) { - _masm->std(std_reg, (intptr_t) -reg_save_index * BytesPerWord, R1_SP); + _masm->std(std_reg, offset - reg_save_index * BytesPerWord, R1_SP); } else if (action == ACTION_RESTORE) { - _masm->ld(std_reg, (intptr_t) -reg_save_index * BytesPerWord, R1_SP); + _masm->ld(std_reg, offset - reg_save_index * BytesPerWord, R1_SP); } else { - fatal("Sanity"); + assert(action == ACTION_COUNT_ONLY, "Sanity"); } } } else if (vm_reg->is_FloatRegister()) { @@ -467,19 +471,34 @@ reg_save_index++; if (action == ACTION_SAVE) { - _masm->stfd(fp_reg, (intptr_t) -reg_save_index * BytesPerWord, R1_SP); + _masm->stfd(fp_reg, offset - reg_save_index * BytesPerWord, R1_SP); } else if (action == ACTION_RESTORE) { - _masm->lfd(fp_reg, (intptr_t) -reg_save_index * BytesPerWord, R1_SP); + _masm->lfd(fp_reg, offset - reg_save_index * BytesPerWord, R1_SP); } else { - fatal("Sanity"); + assert(action == ACTION_COUNT_ONLY, "Sanity"); } } } else if (vm_reg->is_ConditionRegister()) { // NOP. Conditions registers are covered by save_LR_CR + } else if (vm_reg->is_VectorSRegister()) { + assert(SuperwordUseVSX, "or should not reach here"); + VectorSRegister vs_reg = vm_reg->as_VectorSRegister(); + if (vs_reg->encoding() >= VSR32->encoding() && vs_reg->encoding() <= VSR51->encoding()) { + reg_save_index += 2; + + Register spill_addr = R0; + if (action == ACTION_SAVE) { + _masm->addi(spill_addr, R1_SP, offset - reg_save_index * BytesPerWord); + _masm->stxvd2x(vs_reg, spill_addr); + } else if (action == ACTION_RESTORE) { + _masm->addi(spill_addr, R1_SP, offset - reg_save_index * BytesPerWord); + _masm->lxvd2x(vs_reg, spill_addr); + } else { + assert(action == ACTION_COUNT_ONLY, "Sanity"); + } + } } else { - if (vm_reg->is_VectorRegister()) { - fatal("Vector registers are unsupported. Found register %s", vm_reg->name()); - } else if (vm_reg->is_SpecialRegister()) { + if (vm_reg->is_SpecialRegister()) { fatal("Special registers are unsupported. Found register %s", vm_reg->name()); } else { fatal("Register type is not known"); @@ -495,7 +514,6 @@ #define __ _masm-> class ZSetupArguments { - private: MacroAssembler* const _masm; const Register _ref; const Address _ref_addr; diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/ppc/javaFrameAnchor_ppc.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/ppc/javaFrameAnchor_ppc.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/ppc/javaFrameAnchor_ppc.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/ppc/javaFrameAnchor_ppc.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -67,7 +67,7 @@ // Always walkable. bool walkable(void) { return true; } // Never any thing to do since we are always walkable and can find address of return addresses. - void make_walkable(JavaThread* thread) { } + void make_walkable() { } intptr_t* last_Java_sp(void) const { return _last_Java_sp; } diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/ppc/ppc.ad openjdk-17-17.0.5+8/src/hotspot/cpu/ppc/ppc.ad --- openjdk-17-17.0.4+8/src/hotspot/cpu/ppc/ppc.ad 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/ppc/ppc.ad 2022-10-10 13:07:22.000000000 +0000 @@ -1,6 +1,6 @@ // // Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. -// Copyright (c) 2012, 2021 SAP SE. All rights reserved. +// Copyright (c) 2012, 2022 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 @@ -257,70 +257,72 @@ // ---------------------------- // Vector-Scalar Registers // ---------------------------- - reg_def VSR0 ( SOC, SOC, Op_VecX, 0, NULL); - reg_def VSR1 ( SOC, SOC, Op_VecX, 1, NULL); - reg_def VSR2 ( SOC, SOC, Op_VecX, 2, NULL); - reg_def VSR3 ( SOC, SOC, Op_VecX, 3, NULL); - reg_def VSR4 ( SOC, SOC, Op_VecX, 4, NULL); - reg_def VSR5 ( SOC, SOC, Op_VecX, 5, NULL); - reg_def VSR6 ( SOC, SOC, Op_VecX, 6, NULL); - reg_def VSR7 ( SOC, SOC, Op_VecX, 7, NULL); - reg_def VSR8 ( SOC, SOC, Op_VecX, 8, NULL); - reg_def VSR9 ( SOC, SOC, Op_VecX, 9, NULL); - reg_def VSR10 ( SOC, SOC, Op_VecX, 10, NULL); - reg_def VSR11 ( SOC, SOC, Op_VecX, 11, NULL); - reg_def VSR12 ( SOC, SOC, Op_VecX, 12, NULL); - reg_def VSR13 ( SOC, SOC, Op_VecX, 13, NULL); - reg_def VSR14 ( SOC, SOC, Op_VecX, 14, NULL); - reg_def VSR15 ( SOC, SOC, Op_VecX, 15, NULL); - reg_def VSR16 ( SOC, SOC, Op_VecX, 16, NULL); - reg_def VSR17 ( SOC, SOC, Op_VecX, 17, NULL); - reg_def VSR18 ( SOC, SOC, Op_VecX, 18, NULL); - reg_def VSR19 ( SOC, SOC, Op_VecX, 19, NULL); - reg_def VSR20 ( SOC, SOC, Op_VecX, 20, NULL); - reg_def VSR21 ( SOC, SOC, Op_VecX, 21, NULL); - reg_def VSR22 ( SOC, SOC, Op_VecX, 22, NULL); - reg_def VSR23 ( SOC, SOC, Op_VecX, 23, NULL); - reg_def VSR24 ( SOC, SOC, Op_VecX, 24, NULL); - reg_def VSR25 ( SOC, SOC, Op_VecX, 25, NULL); - reg_def VSR26 ( SOC, SOC, Op_VecX, 26, NULL); - reg_def VSR27 ( SOC, SOC, Op_VecX, 27, NULL); - reg_def VSR28 ( SOC, SOC, Op_VecX, 28, NULL); - reg_def VSR29 ( SOC, SOC, Op_VecX, 29, NULL); - reg_def VSR30 ( SOC, SOC, Op_VecX, 30, NULL); - reg_def VSR31 ( SOC, SOC, Op_VecX, 31, NULL); - reg_def VSR32 ( SOC, SOC, Op_VecX, 32, NULL); - reg_def VSR33 ( SOC, SOC, Op_VecX, 33, NULL); - reg_def VSR34 ( SOC, SOC, Op_VecX, 34, NULL); - reg_def VSR35 ( SOC, SOC, Op_VecX, 35, NULL); - reg_def VSR36 ( SOC, SOC, Op_VecX, 36, NULL); - reg_def VSR37 ( SOC, SOC, Op_VecX, 37, NULL); - reg_def VSR38 ( SOC, SOC, Op_VecX, 38, NULL); - reg_def VSR39 ( SOC, SOC, Op_VecX, 39, NULL); - reg_def VSR40 ( SOC, SOC, Op_VecX, 40, NULL); - reg_def VSR41 ( SOC, SOC, Op_VecX, 41, NULL); - reg_def VSR42 ( SOC, SOC, Op_VecX, 42, NULL); - reg_def VSR43 ( SOC, SOC, Op_VecX, 43, NULL); - reg_def VSR44 ( SOC, SOC, Op_VecX, 44, NULL); - reg_def VSR45 ( SOC, SOC, Op_VecX, 45, NULL); - reg_def VSR46 ( SOC, SOC, Op_VecX, 46, NULL); - reg_def VSR47 ( SOC, SOC, Op_VecX, 47, NULL); - reg_def VSR48 ( SOC, SOC, Op_VecX, 48, NULL); - reg_def VSR49 ( SOC, SOC, Op_VecX, 49, NULL); - reg_def VSR50 ( SOC, SOC, Op_VecX, 50, NULL); - reg_def VSR51 ( SOC, SOC, Op_VecX, 51, NULL); - reg_def VSR52 ( SOC, SOC, Op_VecX, 52, NULL); - reg_def VSR53 ( SOC, SOC, Op_VecX, 53, NULL); - reg_def VSR54 ( SOC, SOC, Op_VecX, 54, NULL); - reg_def VSR55 ( SOC, SOC, Op_VecX, 55, NULL); - reg_def VSR56 ( SOC, SOC, Op_VecX, 56, NULL); - reg_def VSR57 ( SOC, SOC, Op_VecX, 57, NULL); - reg_def VSR58 ( SOC, SOC, Op_VecX, 58, NULL); - reg_def VSR59 ( SOC, SOC, Op_VecX, 59, NULL); - reg_def VSR60 ( SOC, SOC, Op_VecX, 60, NULL); - reg_def VSR61 ( SOC, SOC, Op_VecX, 61, NULL); - reg_def VSR62 ( SOC, SOC, Op_VecX, 62, NULL); - reg_def VSR63 ( SOC, SOC, Op_VecX, 63, NULL); + // 1st 32 VSRs are aliases for the FPRs which are already defined above. + reg_def VSR0 ( SOC, SOC, Op_VecX, 0, VMRegImpl::Bad()); + reg_def VSR1 ( SOC, SOC, Op_VecX, 1, VMRegImpl::Bad()); + reg_def VSR2 ( SOC, SOC, Op_VecX, 2, VMRegImpl::Bad()); + reg_def VSR3 ( SOC, SOC, Op_VecX, 3, VMRegImpl::Bad()); + reg_def VSR4 ( SOC, SOC, Op_VecX, 4, VMRegImpl::Bad()); + reg_def VSR5 ( SOC, SOC, Op_VecX, 5, VMRegImpl::Bad()); + reg_def VSR6 ( SOC, SOC, Op_VecX, 6, VMRegImpl::Bad()); + reg_def VSR7 ( SOC, SOC, Op_VecX, 7, VMRegImpl::Bad()); + reg_def VSR8 ( SOC, SOC, Op_VecX, 8, VMRegImpl::Bad()); + reg_def VSR9 ( SOC, SOC, Op_VecX, 9, VMRegImpl::Bad()); + reg_def VSR10 ( SOC, SOC, Op_VecX, 10, VMRegImpl::Bad()); + reg_def VSR11 ( SOC, SOC, Op_VecX, 11, VMRegImpl::Bad()); + reg_def VSR12 ( SOC, SOC, Op_VecX, 12, VMRegImpl::Bad()); + reg_def VSR13 ( SOC, SOC, Op_VecX, 13, VMRegImpl::Bad()); + reg_def VSR14 ( SOC, SOE, Op_VecX, 14, VMRegImpl::Bad()); + reg_def VSR15 ( SOC, SOE, Op_VecX, 15, VMRegImpl::Bad()); + reg_def VSR16 ( SOC, SOE, Op_VecX, 16, VMRegImpl::Bad()); + reg_def VSR17 ( SOC, SOE, Op_VecX, 17, VMRegImpl::Bad()); + reg_def VSR18 ( SOC, SOE, Op_VecX, 18, VMRegImpl::Bad()); + reg_def VSR19 ( SOC, SOE, Op_VecX, 19, VMRegImpl::Bad()); + reg_def VSR20 ( SOC, SOE, Op_VecX, 20, VMRegImpl::Bad()); + reg_def VSR21 ( SOC, SOE, Op_VecX, 21, VMRegImpl::Bad()); + reg_def VSR22 ( SOC, SOE, Op_VecX, 22, VMRegImpl::Bad()); + reg_def VSR23 ( SOC, SOE, Op_VecX, 23, VMRegImpl::Bad()); + reg_def VSR24 ( SOC, SOE, Op_VecX, 24, VMRegImpl::Bad()); + reg_def VSR25 ( SOC, SOE, Op_VecX, 25, VMRegImpl::Bad()); + reg_def VSR26 ( SOC, SOE, Op_VecX, 26, VMRegImpl::Bad()); + reg_def VSR27 ( SOC, SOE, Op_VecX, 27, VMRegImpl::Bad()); + reg_def VSR28 ( SOC, SOE, Op_VecX, 28, VMRegImpl::Bad()); + reg_def VSR29 ( SOC, SOE, Op_VecX, 29, VMRegImpl::Bad()); + reg_def VSR30 ( SOC, SOE, Op_VecX, 30, VMRegImpl::Bad()); + reg_def VSR31 ( SOC, SOE, Op_VecX, 31, VMRegImpl::Bad()); + // 2nd 32 VSRs are aliases for the VRs which are only defined here. + reg_def VSR32 ( SOC, SOC, Op_VecX, 32, VSR32->as_VMReg()); + reg_def VSR33 ( SOC, SOC, Op_VecX, 33, VSR33->as_VMReg()); + reg_def VSR34 ( SOC, SOC, Op_VecX, 34, VSR34->as_VMReg()); + reg_def VSR35 ( SOC, SOC, Op_VecX, 35, VSR35->as_VMReg()); + reg_def VSR36 ( SOC, SOC, Op_VecX, 36, VSR36->as_VMReg()); + reg_def VSR37 ( SOC, SOC, Op_VecX, 37, VSR37->as_VMReg()); + reg_def VSR38 ( SOC, SOC, Op_VecX, 38, VSR38->as_VMReg()); + reg_def VSR39 ( SOC, SOC, Op_VecX, 39, VSR39->as_VMReg()); + reg_def VSR40 ( SOC, SOC, Op_VecX, 40, VSR40->as_VMReg()); + reg_def VSR41 ( SOC, SOC, Op_VecX, 41, VSR41->as_VMReg()); + reg_def VSR42 ( SOC, SOC, Op_VecX, 42, VSR42->as_VMReg()); + reg_def VSR43 ( SOC, SOC, Op_VecX, 43, VSR43->as_VMReg()); + reg_def VSR44 ( SOC, SOC, Op_VecX, 44, VSR44->as_VMReg()); + reg_def VSR45 ( SOC, SOC, Op_VecX, 45, VSR45->as_VMReg()); + reg_def VSR46 ( SOC, SOC, Op_VecX, 46, VSR46->as_VMReg()); + reg_def VSR47 ( SOC, SOC, Op_VecX, 47, VSR47->as_VMReg()); + reg_def VSR48 ( SOC, SOC, Op_VecX, 48, VSR48->as_VMReg()); + reg_def VSR49 ( SOC, SOC, Op_VecX, 49, VSR49->as_VMReg()); + reg_def VSR50 ( SOC, SOC, Op_VecX, 50, VSR50->as_VMReg()); + reg_def VSR51 ( SOC, SOC, Op_VecX, 51, VSR51->as_VMReg()); + reg_def VSR52 ( SOC, SOE, Op_VecX, 52, VSR52->as_VMReg()); + reg_def VSR53 ( SOC, SOE, Op_VecX, 53, VSR53->as_VMReg()); + reg_def VSR54 ( SOC, SOE, Op_VecX, 54, VSR54->as_VMReg()); + reg_def VSR55 ( SOC, SOE, Op_VecX, 55, VSR55->as_VMReg()); + reg_def VSR56 ( SOC, SOE, Op_VecX, 56, VSR56->as_VMReg()); + reg_def VSR57 ( SOC, SOE, Op_VecX, 57, VSR57->as_VMReg()); + reg_def VSR58 ( SOC, SOE, Op_VecX, 58, VSR58->as_VMReg()); + reg_def VSR59 ( SOC, SOE, Op_VecX, 59, VSR59->as_VMReg()); + reg_def VSR60 ( SOC, SOE, Op_VecX, 60, VSR60->as_VMReg()); + reg_def VSR61 ( SOC, SOE, Op_VecX, 61, VSR61->as_VMReg()); + reg_def VSR62 ( SOC, SOE, Op_VecX, 62, VSR62->as_VMReg()); + reg_def VSR63 ( SOC, SOE, Op_VecX, 63, VSR63->as_VMReg()); // ---------------------------- // Specify priority of register selection within phases of register diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/ppc/register_ppc.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/ppc/register_ppc.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/ppc/register_ppc.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/ppc/register_ppc.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2018 SAP SE. All rights reserved. + * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022 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 @@ -69,7 +69,11 @@ // v14-v19 Volatile scratch registers // v20-v31 Non-volatile registers // vrsave Non-volatile 32-bit register - +// +// ---------------------------------------------- +// On processors with VSX feature: +// vs0-31 Alias for f0-f31 (64 bit, see above) +// vs32-63 Alias for v0-31 (128 bit, see above) // Use Register as shortcut class RegisterImpl; diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/ppc/vmreg_ppc.cpp openjdk-17-17.0.5+8/src/hotspot/cpu/ppc/vmreg_ppc.cpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/ppc/vmreg_ppc.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/ppc/vmreg_ppc.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1,6 +1,6 @@ /* * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2020 SAP SE. All rights reserved. + * Copyright (c) 2012, 2022 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 @@ -44,8 +44,14 @@ if (reg->encoding() < FloatRegisterImpl::number_of_registers-1) freg = freg->successor(); } - for ( ; i < ConcreteRegisterImpl::number_of_registers; i++) { - regName[i] = "NON-GPR-FPR"; + + VectorSRegister vsreg = ::as_VectorSRegister(0); + for ( ; i < ConcreteRegisterImpl::max_vsr; ) { + regName[i++] = vsreg->name(); + } + + for ( ; i < ConcreteRegisterImpl::number_of_registers; ) { + regName[i++] = "NON-GPR-FPR-VSR"; } } diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/ppc/vmreg_ppc.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/ppc/vmreg_ppc.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/ppc/vmreg_ppc.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/ppc/vmreg_ppc.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2021 SAP SE. All rights reserved. + * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022 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,7 +35,7 @@ value() < ConcreteRegisterImpl::max_fpr; } -inline bool is_VectorRegister() { +inline bool is_VectorSRegister() { return value() >= ConcreteRegisterImpl::max_fpr && value() < ConcreteRegisterImpl::max_vsr; } @@ -60,6 +60,11 @@ return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) >> 1); } +inline VectorSRegister as_VectorSRegister() { + assert(is_VectorSRegister(), "must be"); + return ::as_VectorSRegister(value() - ConcreteRegisterImpl::max_fpr); +} + inline bool is_concrete() { assert(is_reg(), "must be"); return is_even(value()); diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/s390/frame_s390.inline.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/s390/frame_s390.inline.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/s390/frame_s390.inline.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/s390/frame_s390.inline.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -155,6 +155,10 @@ return (intptr_t*) callers_abi()->callers_sp; } +inline intptr_t* frame::link_or_null() const { + return link(); +} + inline intptr_t** frame::interpreter_frame_locals_addr() const { return (intptr_t**) &(ijava_state()->locals); } diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/s390/javaFrameAnchor_s390.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/s390/javaFrameAnchor_s390.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/s390/javaFrameAnchor_s390.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/s390/javaFrameAnchor_s390.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -72,7 +72,7 @@ // We don't have to flush registers, so the stack is always walkable. inline bool walkable(void) { return true; } - inline void make_walkable(JavaThread* thread) { } + inline void make_walkable() { } public: diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/x86/frame_x86.cpp openjdk-17-17.0.5+8/src/hotspot/cpu/x86/frame_x86.cpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/x86/frame_x86.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/x86/frame_x86.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -341,13 +341,9 @@ assert(jfa->last_Java_sp() > sp(), "must be above this frame on stack"); // Since we are walking the stack now this nested anchor is obviously walkable // even if it wasn't when it was stacked. - if (!jfa->walkable()) { - // Capture _last_Java_pc (if needed) and mark anchor walkable. - jfa->capture_last_Java_pc(); - } + jfa->make_walkable(); map->clear(); assert(map->include_argument_oops(), "should be set by clear"); - vmassert(jfa->last_Java_pc() != NULL, "not walkable"); frame fr(jfa->last_Java_sp(), jfa->last_Java_fp(), jfa->last_Java_pc()); return fr; @@ -377,13 +373,9 @@ assert(jfa->last_Java_sp() > sp(), "must be above this frame on stack"); // Since we are walking the stack now this nested anchor is obviously walkable // even if it wasn't when it was stacked. - if (!jfa->walkable()) { - // Capture _last_Java_pc (if needed) and mark anchor walkable. - jfa->capture_last_Java_pc(); - } + jfa->make_walkable(); map->clear(); assert(map->include_argument_oops(), "should be set by clear"); - vmassert(jfa->last_Java_pc() != NULL, "not walkable"); frame fr(jfa->last_Java_sp(), jfa->last_Java_fp(), jfa->last_Java_pc()); return fr; @@ -721,20 +713,12 @@ void frame::pd_ps() {} #endif -void JavaFrameAnchor::make_walkable(JavaThread* thread) { +void JavaFrameAnchor::make_walkable() { // last frame set? if (last_Java_sp() == NULL) return; // already walkable? if (walkable()) return; - vmassert(Thread::current() == (Thread*)thread, "not current thread"); - vmassert(last_Java_sp() != NULL, "not called from Java code?"); vmassert(last_Java_pc() == NULL, "already walkable"); - capture_last_Java_pc(); - vmassert(walkable(), "something went wrong"); -} - -void JavaFrameAnchor::capture_last_Java_pc() { - vmassert(_last_Java_sp != NULL, "no last frame set"); - vmassert(_last_Java_pc == NULL, "already walkable"); _last_Java_pc = (address)_last_Java_sp[-1]; + vmassert(walkable(), "something went wrong"); } diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/x86/frame_x86.inline.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/x86/frame_x86.inline.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/x86/frame_x86.inline.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/x86/frame_x86.inline.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -138,10 +138,13 @@ inline bool frame::is_older(intptr_t* id) const { assert(this->id() != NULL && id != NULL, "NULL frame id"); return this->id() > id ; } - - inline intptr_t* frame::link() const { return (intptr_t*) *(intptr_t **)addr_at(link_offset); } +inline intptr_t* frame::link_or_null() const { + intptr_t** ptr = (intptr_t **)addr_at(link_offset); + return os::is_readable_pointer(ptr) ? *ptr : NULL; +} + inline intptr_t* frame::unextended_sp() const { return _unextended_sp; } // Return address: diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/x86/interp_masm_x86.cpp openjdk-17-17.0.5+8/src/hotspot/cpu/x86/interp_masm_x86.cpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/x86/interp_masm_x86.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/x86/interp_masm_x86.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1123,7 +1123,7 @@ bind(loop); // check if current entry is used - cmpptr(Address(rmon, BasicObjectLock::obj_offset_in_bytes()), (int32_t) NULL); + cmpptr(Address(rmon, BasicObjectLock::obj_offset_in_bytes()), (int32_t) NULL_WORD); jcc(Assembler::notEqual, exception); addptr(rmon, entry_size); // otherwise advance to next entry diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/x86/interpreterRT_x86_64.cpp openjdk-17-17.0.5+8/src/hotspot/cpu/x86/interpreterRT_x86_64.cpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/x86/interpreterRT_x86_64.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/x86/interpreterRT_x86_64.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -348,10 +348,10 @@ intptr_t *from_addr = (intptr_t*)(_from + Interpreter::local_offset_in_bytes(0)); _from -= Interpreter::stackElementSize; if (_num_args < Argument::n_int_register_parameters_c-1) { - *_reg_args++ = (*from_addr == 0) ? NULL : (intptr_t) from_addr; + *_reg_args++ = (*from_addr == 0) ? NULL_WORD : (intptr_t) from_addr; _num_args++; } else { - *_to++ = (*from_addr == 0) ? NULL : (intptr_t) from_addr; + *_to++ = (*from_addr == 0) ? NULL_WORD : (intptr_t) from_addr; } } @@ -443,10 +443,10 @@ _from -= Interpreter::stackElementSize; if (_num_int_args < Argument::n_int_register_parameters_c-1) { - *_int_args++ = (*from_addr == 0) ? NULL : (intptr_t)from_addr; + *_int_args++ = (*from_addr == 0) ? NULL_WORD : (intptr_t)from_addr; _num_int_args++; } else { - *_to++ = (*from_addr == 0) ? NULL : (intptr_t) from_addr; + *_to++ = (*from_addr == 0) ? NULL_WORD : (intptr_t) from_addr; } } diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/x86/javaFrameAnchor_x86.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/x86/javaFrameAnchor_x86.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/x86/javaFrameAnchor_x86.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/x86/javaFrameAnchor_x86.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -63,8 +63,7 @@ } bool walkable(void) { return _last_Java_sp != NULL && _last_Java_pc != NULL; } - void make_walkable(JavaThread* thread); - void capture_last_Java_pc(void); + void make_walkable(); intptr_t* last_Java_sp(void) const { return _last_Java_sp; } diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/x86/macroAssembler_x86.cpp openjdk-17-17.0.5+8/src/hotspot/cpu/x86/macroAssembler_x86.cpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/x86/macroAssembler_x86.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/x86/macroAssembler_x86.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -5269,10 +5269,28 @@ int vector64_count = (cnt & (~0x7)) >> 3; cnt = cnt & 0x7; + const int fill64_per_loop = 4; + const int max_unrolled_fill64 = 8; // 64 byte initialization loop. vpxor(xtmp, xtmp, xtmp, use64byteVector ? AVX_512bit : AVX_256bit); - for (int i = 0; i < vector64_count; i++) { + int start64 = 0; + if (vector64_count > max_unrolled_fill64) { + Label LOOP; + Register index = rtmp; + + start64 = vector64_count - (vector64_count % fill64_per_loop); + + movl(index, 0); + BIND(LOOP); + for (int i = 0; i < fill64_per_loop; i++) { + fill64(Address(base, index, Address::times_1, i * 64), xtmp, use64byteVector); + } + addl(index, fill64_per_loop * 64); + cmpl(index, start64 * 64); + jccb(Assembler::less, LOOP); + } + for (int i = start64; i < vector64_count; i++) { fill64_avx(base, i * 64, xtmp, use64byteVector); } @@ -8459,23 +8477,29 @@ evmovdqu(type[shift], mask, Address(dst, disp), xmm, Assembler::AVX_256bit); } +void MacroAssembler::fill32(Address dst, XMMRegister xmm) { + assert(MaxVectorSize >= 32, "vector length should be >= 32"); + vmovdqu(dst, xmm); +} void MacroAssembler::fill32_avx(Register dst, int disp, XMMRegister xmm) { - assert(MaxVectorSize >= 32, "vector length should be >= 32"); - vmovdqu(Address(dst, disp), xmm); + fill32(Address(dst, disp), xmm); } -void MacroAssembler::fill64_avx(Register dst, int disp, XMMRegister xmm, bool use64byteVector) { +void MacroAssembler::fill64(Address dst, XMMRegister xmm, bool use64byteVector) { assert(MaxVectorSize >= 32, "vector length should be >= 32"); - BasicType type[] = {T_BYTE, T_SHORT, T_INT, T_LONG}; if (!use64byteVector) { - fill32_avx(dst, disp, xmm); - fill32_avx(dst, disp + 32, xmm); + fill32(dst, xmm); + fill32(dst.plus_disp(32), xmm); } else { - evmovdquq(Address(dst, disp), xmm, Assembler::AVX_512bit); + evmovdquq(dst, xmm, Assembler::AVX_512bit); } } +void MacroAssembler::fill64_avx(Register dst, int disp, XMMRegister xmm, bool use64byteVector) { + fill64(Address(dst, disp), xmm, use64byteVector); +} + #endif //COMPILER2_OR_JVMCI diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/x86/macroAssembler_x86.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/x86/macroAssembler_x86.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/x86/macroAssembler_x86.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/x86/macroAssembler_x86.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -1860,8 +1860,12 @@ XMMRegister xmm, KRegister mask, Register length, Register temp); + void fill32(Address dst, XMMRegister xmm); + void fill32_avx(Register dst, int disp, XMMRegister xmm); + void fill64(Address dst, XMMRegister xmm, bool use64byteVector = false); + void fill64_avx(Register dst, int dis, XMMRegister xmm, bool use64byteVector = false); #ifdef _LP64 diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp openjdk-17-17.0.5+8/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -150,8 +150,8 @@ }; public: - static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors); - static void restore_live_registers(MacroAssembler* masm, bool restore_vectors = false); + static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_wide_vectors); + static void restore_live_registers(MacroAssembler* masm, bool restore_wide_vectors = false); // Offsets into the register save area // Used by deoptimization when it is managing result register @@ -168,19 +168,19 @@ static void restore_result_registers(MacroAssembler* masm); }; -OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) { +OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_wide_vectors) { int off = 0; int num_xmm_regs = XMMRegisterImpl::number_of_registers; if (UseAVX < 3) { num_xmm_regs = num_xmm_regs/2; } #if COMPILER2_OR_JVMCI - if (save_vectors && UseAVX == 0) { - save_vectors = false; // vectors larger than 16 byte long are supported only with AVX + if (save_wide_vectors && UseAVX == 0) { + save_wide_vectors = false; // vectors larger than 16 byte long are supported only with AVX } - assert(!save_vectors || MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); + assert(!save_wide_vectors || MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); #else - save_vectors = false; // vectors are generated only by C2 and JVMCI + save_wide_vectors = false; // vectors are generated only by C2 and JVMCI #endif // Always make the frame size 16-byte aligned, both vector and non vector stacks are always allocated @@ -201,7 +201,7 @@ __ push_CPU_state(); // Push a multiple of 16 bytes // push cpu state handles this on EVEX enabled targets - if (save_vectors) { + if (save_wide_vectors) { // Save upper half of YMM registers(0..15) int base_addr = XSAVE_AREA_YMM_BEGIN; for (int n = 0; n < 16; n++) { @@ -230,11 +230,12 @@ } } else { if (VM_Version::supports_evex()) { - // Save upper bank of ZMM registers(16..31) for double/float usage + // Save upper bank of XMM registers(16..31) for scalar or 16-byte vector usage int base_addr = XSAVE_AREA_UPPERBANK; off = 0; + int vector_len = VM_Version::supports_avx512vl() ? Assembler::AVX_128bit : Assembler::AVX_512bit; for (int n = 16; n < num_xmm_regs; n++) { - __ movsd(Address(rsp, base_addr+(off++*64)), as_XMMRegister(n)); + __ evmovdqul(Address(rsp, base_addr+(off++*64)), as_XMMRegister(n), vector_len); } #if COMPILER2_OR_JVMCI base_addr = XSAVE_AREA_OPMASK_BEGIN; @@ -298,7 +299,7 @@ } #if COMPILER2_OR_JVMCI - if (save_vectors) { + if (save_wide_vectors) { // Save upper half of YMM registers(0..15) off = ymm0_off; delta = ymm1_off - ymm0_off; @@ -361,7 +362,7 @@ return map; } -void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) { +void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_wide_vectors) { int num_xmm_regs = XMMRegisterImpl::number_of_registers; if (UseAVX < 3) { num_xmm_regs = num_xmm_regs/2; @@ -372,18 +373,18 @@ } #if COMPILER2_OR_JVMCI - if (restore_vectors) { + if (restore_wide_vectors) { assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX"); assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); } #else - assert(!restore_vectors, "vectors are generated only by C2"); + assert(!restore_wide_vectors, "vectors are generated only by C2"); #endif __ vzeroupper(); // On EVEX enabled targets everything is handled in pop fpu state - if (restore_vectors) { + if (restore_wide_vectors) { // Restore upper half of YMM registers (0..15) int base_addr = XSAVE_AREA_YMM_BEGIN; for (int n = 0; n < 16; n++) { @@ -412,11 +413,12 @@ } } else { if (VM_Version::supports_evex()) { - // Restore upper bank of ZMM registers(16..31) for double/float usage + // Restore upper bank of XMM registers(16..31) for scalar or 16-byte vector usage int base_addr = XSAVE_AREA_UPPERBANK; int off = 0; + int vector_len = VM_Version::supports_avx512vl() ? Assembler::AVX_128bit : Assembler::AVX_512bit; for (int n = 16; n < num_xmm_regs; n++) { - __ movsd(as_XMMRegister(n), Address(rsp, base_addr+(off++*64))); + __ evmovdqul(as_XMMRegister(n), Address(rsp, base_addr+(off++*64)), vector_len); } #if COMPILER2_OR_JVMCI base_addr = XSAVE_AREA_OPMASK_BEGIN; @@ -2501,7 +2503,7 @@ // Prolog for non exception case! // Save everything in sight. - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_vectors*/ true); + map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_wide_vectors*/ true); // Normal deoptimization. Save exec mode for unpack_frames. __ movl(r14, Deoptimization::Unpack_deopt); // callee-saved @@ -2519,7 +2521,7 @@ // return address is the pc describes what bci to do re-execute at // No need to update map as each call to save_live_registers will produce identical oopmap - (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_vectors*/ true); + (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_wide_vectors*/ true); __ movl(r14, Deoptimization::Unpack_reexecute); // callee-saved __ jmp(cont); @@ -2538,7 +2540,7 @@ uncommon_trap_offset = __ pc() - start; // Save everything in sight. - RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_vectors*/ true); + RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_wide_vectors*/ true); // fetch_unroll_info needs to call last_java_frame() __ set_last_Java_frame(noreg, noreg, NULL); @@ -2585,7 +2587,7 @@ __ push(0); // Save everything in sight. - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_vectors*/ true); + map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_wide_vectors*/ true); // Now it is safe to overwrite any register @@ -3016,7 +3018,7 @@ address call_pc = NULL; int frame_size_in_words; bool cause_return = (poll_type == POLL_AT_RETURN); - bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP); + bool save_wide_vectors = (poll_type == POLL_AT_VECTOR_LOOP); if (UseRTMLocking) { // Abort RTM transaction before calling runtime @@ -3031,7 +3033,7 @@ } // Save registers, fpu state, and flags - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_vectors); + map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_wide_vectors); // The following is basically a call_VM. However, we need the precise // address of the call in order to generate an oopmap. Hence, we do all the @@ -3070,7 +3072,7 @@ // Exception pending - RegisterSaver::restore_live_registers(masm, save_vectors); + RegisterSaver::restore_live_registers(masm, save_wide_vectors); __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); @@ -3143,7 +3145,7 @@ __ bind(no_adjust); // Normal exit, restore registers and exit. - RegisterSaver::restore_live_registers(masm, save_vectors); + RegisterSaver::restore_live_registers(masm, save_wide_vectors); __ ret(0); #ifdef ASSERT @@ -3183,7 +3185,7 @@ int start = __ offset(); // No need to save vector registers since they are caller-saved anyway. - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_vectors*/ false); + map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_wide_vectors*/ false); int frame_complete = __ offset(); diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp openjdk-17-17.0.5+8/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -517,7 +517,7 @@ // make sure this code is only executed if there is a pending exception { Label L; - __ cmpptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t) NULL); + __ cmpptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t) NULL_WORD); __ jcc(Assembler::notEqual, L); __ stop("StubRoutines::forward exception: no pending exception (1)"); __ bind(L); diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/zero/frame_zero.inline.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/zero/frame_zero.inline.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/zero/frame_zero.inline.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/zero/frame_zero.inline.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -82,6 +82,11 @@ return NULL; } +inline intptr_t* frame::link_or_null() const { + ShouldNotCallThis(); + return NULL; +} + inline interpreterState frame::get_interpreterState() const { return zero_interpreterframe()->interpreter_state(); } diff -Nru openjdk-17-17.0.4+8/src/hotspot/cpu/zero/javaFrameAnchor_zero.hpp openjdk-17-17.0.5+8/src/hotspot/cpu/zero/javaFrameAnchor_zero.hpp --- openjdk-17-17.0.4+8/src/hotspot/cpu/zero/javaFrameAnchor_zero.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/cpu/zero/javaFrameAnchor_zero.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -73,7 +73,7 @@ return true; } - void make_walkable(JavaThread* thread) { + void make_walkable() { // nothing to do } diff -Nru openjdk-17-17.0.4+8/src/hotspot/os/aix/os_aix.cpp openjdk-17-17.0.5+8/src/hotspot/os/aix/os_aix.cpp --- openjdk-17-17.0.4+8/src/hotspot/os/aix/os_aix.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/os/aix/os_aix.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1161,7 +1161,7 @@ // RTLD_LAZY is currently not implemented. The dl is loaded immediately with all its dependants. void * result= ::dlopen(filename, RTLD_LAZY); if (result != NULL) { - Events::log(NULL, "Loaded shared library %s", filename); + Events::log_dll_message(NULL, "Loaded shared library %s", filename); // Reload dll cache. Don't do this in signal handling. LoadedLibraries::reload(); log_info(os)("shared library load of %s was successful", filename); @@ -1176,21 +1176,12 @@ snprintf(ebuf, ebuflen - 1, "%s, LIBPATH=%s, LD_LIBRARY_PATH=%s : %s", filename, ::getenv("LIBPATH"), ::getenv("LD_LIBRARY_PATH"), error_report); } - Events::log(NULL, "Loading shared library %s failed, %s", filename, error_report); + Events::log_dll_message(NULL, "Loading shared library %s failed, %s", filename, error_report); log_info(os)("shared library load of %s failed, %s", filename, error_report); } return NULL; } -void* os::dll_lookup(void* handle, const char* name) { - void* res = dlsym(handle, name); - return res; -} - -void* os::get_default_process_handle() { - return (void*)::dlopen(NULL, RTLD_LAZY); -} - void os::print_dll_info(outputStream *st) { st->print_cr("Dynamic libraries:"); LoadedLibraries::print(st); @@ -2209,13 +2200,6 @@ return addr; } -// Sleep forever; naked call to OS-specific sleep; use with CAUTION -void os::infinite_sleep() { - while (true) { // sleep forever ... - ::sleep(100); // ... 100 seconds at a time - } -} - // Used to convert frequent JVM_Yield() to nops bool os::dont_yield() { return DontYieldALot; @@ -2551,47 +2535,6 @@ f(value, method, args, thread); } -void os::print_statistics() { -} - -bool os::message_box(const char* title, const char* message) { - int i; - fdStream err(defaultStream::error_fd()); - for (i = 0; i < 78; i++) err.print_raw("="); - err.cr(); - err.print_raw_cr(title); - for (i = 0; i < 78; i++) err.print_raw("-"); - err.cr(); - err.print_raw_cr(message); - for (i = 0; i < 78; i++) err.print_raw("="); - err.cr(); - - char buf[16]; - // Prevent process from exiting upon "read error" without consuming all CPU - while (::read(0, buf, sizeof(buf)) <= 0) { ::sleep(100); } - - return buf[0] == 'y' || buf[0] == 'Y'; -} - -// Is a (classpath) directory empty? -bool os::dir_is_empty(const char* path) { - DIR *dir = NULL; - struct dirent *ptr; - - dir = opendir(path); - if (dir == NULL) return true; - - /* Scan the directory */ - bool result = true; - while (result && (ptr = readdir(dir)) != NULL) { - if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) { - result = false; - } - } - closedir(dir); - return result; -} - // This code originates from JDK's sysOpen and open64_w // from src/solaris/hpi/src/system_md.c diff -Nru openjdk-17-17.0.4+8/src/hotspot/os/bsd/os_bsd.cpp openjdk-17-17.0.5+8/src/hotspot/os/bsd/os_bsd.cpp --- openjdk-17-17.0.4+8/src/hotspot/os/bsd/os_bsd.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/os/bsd/os_bsd.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1050,7 +1050,7 @@ void * result= ::dlopen(filename, RTLD_LAZY); if (result != NULL) { - Events::log(NULL, "Loaded shared library %s", filename); + Events::log_dll_message(NULL, "Loaded shared library %s", filename); // Successful loading log_info(os)("shared library load of %s was successful", filename); return result; @@ -1065,7 +1065,7 @@ ::strncpy(ebuf, error_report, ebuflen-1); ebuf[ebuflen-1]='\0'; } - Events::log(NULL, "Loading shared library %s failed, %s", filename, error_report); + Events::log_dll_message(NULL, "Loading shared library %s failed, %s", filename, error_report); log_info(os)("shared library load of %s failed, %s", filename, error_report); return NULL; @@ -1079,7 +1079,7 @@ log_info(os)("attempting shared library load of %s", filename); void * result= ::dlopen(filename, RTLD_LAZY); if (result != NULL) { - Events::log(NULL, "Loaded shared library %s", filename); + Events::log_dll_message(NULL, "Loaded shared library %s", filename); // Successful loading log_info(os)("shared library load of %s was successful", filename); return result; @@ -1096,7 +1096,7 @@ ::strncpy(ebuf, error_report, ebuflen-1); ebuf[ebuflen-1]='\0'; } - Events::log(NULL, "Loading shared library %s failed, %s", filename, error_report); + Events::log_dll_message(NULL, "Loading shared library %s failed, %s", filename, error_report); log_info(os)("shared library load of %s failed, %s", filename, error_report); int diag_msg_max_length=ebuflen-strlen(ebuf); @@ -1256,22 +1256,6 @@ } #endif // !__APPLE__ -void* os::get_default_process_handle() { -#ifdef __APPLE__ - // MacOS X needs to use RTLD_FIRST instead of RTLD_LAZY - // to avoid finding unexpected symbols on second (or later) - // loads of a library. - return (void*)::dlopen(NULL, RTLD_FIRST); -#else - return (void*)::dlopen(NULL, RTLD_LAZY); -#endif -} - -// XXX: Do we need a lock around this as per Linux? -void* os::dll_lookup(void* handle, const char* name) { - return dlsym(handle, name); -} - int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) { outputStream * out = (outputStream *) param; out->print_cr(INTPTR_FORMAT " \t%s", (intptr_t)base_address, name); @@ -1874,13 +1858,6 @@ return NULL; } -// Sleep forever; naked call to OS-specific sleep; use with CAUTION -void os::infinite_sleep() { - while (true) { // sleep forever ... - ::sleep(100); // ... 100 seconds at a time - } -} - // Used to convert frequent JVM_Yield() to nops bool os::dont_yield() { return DontYieldALot; @@ -2259,28 +2236,6 @@ f(value, method, args, thread); } -void os::print_statistics() { -} - -bool os::message_box(const char* title, const char* message) { - int i; - fdStream err(defaultStream::error_fd()); - for (i = 0; i < 78; i++) err.print_raw("="); - err.cr(); - err.print_raw_cr(title); - for (i = 0; i < 78; i++) err.print_raw("-"); - err.cr(); - err.print_raw_cr(message); - for (i = 0; i < 78; i++) err.print_raw("="); - err.cr(); - - char buf[16]; - // Prevent process from exiting upon "read error" without consuming all CPU - while (::read(0, buf, sizeof(buf)) <= 0) { ::sleep(100); } - - return buf[0] == 'y' || buf[0] == 'Y'; -} - static inline struct timespec get_mtime(const char* filename) { struct stat st; int ret = os::stat(filename, &st); @@ -2302,25 +2257,6 @@ return diff; } -// Is a (classpath) directory empty? -bool os::dir_is_empty(const char* path) { - DIR *dir = NULL; - struct dirent *ptr; - - dir = opendir(path); - if (dir == NULL) return true; - - // Scan the directory - bool result = true; - while (result && (ptr = readdir(dir)) != NULL) { - if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) { - result = false; - } - } - closedir(dir); - return result; -} - // This code originates from JDK's sysOpen and open64_w // from src/solaris/hpi/src/system_md.c diff -Nru openjdk-17-17.0.4+8/src/hotspot/os/linux/cgroupSubsystem_linux.cpp openjdk-17-17.0.5+8/src/hotspot/os/linux/cgroupSubsystem_linux.cpp --- openjdk-17-17.0.4+8/src/hotspot/os/linux/cgroupSubsystem_linux.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/os/linux/cgroupSubsystem_linux.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -260,7 +260,13 @@ } } if (is_cgroupsV2) { + // On some systems we have mixed cgroups v1 and cgroups v2 controllers (e.g. freezer on cg1 and + // all relevant controllers on cg2). Only set the cgroup path when we see a hierarchy id of 0. + if (hierarchy_id != 0) { + continue; + } for (int i = 0; i < CG_INFO_LENGTH; i++) { + assert(cg_infos[i]._cgroup_path == NULL, "cgroup path must only be set once"); cg_infos[i]._cgroup_path = os::strdup(cgroup_path); } } @@ -495,7 +501,10 @@ cpu_count = limit_count = os::Linux::active_processor_count(); int quota = cpu_quota(); int period = cpu_period(); - int share = cpu_shares(); + + // It's not a good idea to use cpu_shares() to limit the number + // of CPUs used by the JVM. See JDK-8281181. + int share = UseContainerCpuShares ? cpu_shares() : -1; if (quota > -1 && period > 0) { quota_count = ceilf((float)quota / (float)period); diff -Nru openjdk-17-17.0.4+8/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp openjdk-17-17.0.5+8/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp --- openjdk-17-17.0.4+8/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -136,19 +136,39 @@ const char* matchline = "hierarchical_memsw_limit"; const char* format = "%s " JULONG_FORMAT; GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", matchline, - "Hierarchical Memory and Swap Limit is : " JULONG_FORMAT, format, hier_memlimit) - if (hier_memlimit >= _unlimited_memory) { + "Hierarchical Memory and Swap Limit is : " JULONG_FORMAT, format, hier_memswlimit) + if (hier_memswlimit >= _unlimited_memory) { log_trace(os, container)("Hierarchical Memory and Swap Limit is: Unlimited"); } else { - return (jlong)hier_memlimit; + jlong swappiness = read_mem_swappiness(); + if (swappiness == 0) { + const char* matchmemline = "hierarchical_memory_limit"; + GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", matchmemline, + "Hierarchical Memory Limit is : " JULONG_FORMAT, format, hier_memlimit) + log_trace(os, container)("Memory and Swap Limit has been reset to " JULONG_FORMAT " because swappiness is 0", hier_memlimit); + return (jlong)hier_memlimit; + } + return (jlong)hier_memswlimit; } } return (jlong)-1; } else { + jlong swappiness = read_mem_swappiness(); + if (swappiness == 0) { + jlong memlimit = read_memory_limit_in_bytes(); + log_trace(os, container)("Memory and Swap Limit has been reset to " JULONG_FORMAT " because swappiness is 0", memlimit); + return memlimit; + } return (jlong)memswlimit; } } +jlong CgroupV1Subsystem::read_mem_swappiness() { + GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.swappiness", + "Swappiness is: " JULONG_FORMAT, JULONG_FORMAT, swappiness); + return swappiness; +} + jlong CgroupV1Subsystem::memory_soft_limit_in_bytes() { GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.soft_limit_in_bytes", "Memory Soft Limit is: " JULONG_FORMAT, JULONG_FORMAT, memsoftlimit); diff -Nru openjdk-17-17.0.4+8/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp openjdk-17-17.0.5+8/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp --- openjdk-17-17.0.4+8/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -108,6 +108,8 @@ char * pids_max_val(); + jlong read_mem_swappiness(); + public: CgroupV1Subsystem(CgroupV1Controller* cpuset, CgroupV1Controller* cpu, diff -Nru openjdk-17-17.0.4+8/src/hotspot/os/linux/globals_linux.hpp openjdk-17-17.0.5+8/src/hotspot/os/linux/globals_linux.hpp --- openjdk-17-17.0.4+8/src/hotspot/os/linux/globals_linux.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/os/linux/globals_linux.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -59,6 +59,10 @@ product(bool, UseContainerSupport, true, \ "Enable detection and runtime container configuration support") \ \ + product(bool, UseContainerCpuShares, false, \ + "Include CPU shares in the CPU availability" \ + " calculation.") \ + \ product(bool, PreferContainerQuotaForCPUCount, true, \ "Calculate the container CPU availability based on the value" \ " of quotas (if set), when true. Otherwise, use the CPU" \ diff -Nru openjdk-17-17.0.4+8/src/hotspot/os/linux/os_linux.cpp openjdk-17-17.0.5+8/src/hotspot/os/linux/os_linux.cpp --- openjdk-17-17.0.4+8/src/hotspot/os/linux/os_linux.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/os/linux/os_linux.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1818,10 +1818,10 @@ ::strncpy(ebuf, error_report, ebuflen-1); ebuf[ebuflen-1]='\0'; } - Events::log(NULL, "Loading shared library %s failed, %s", filename, error_report); + Events::log_dll_message(NULL, "Loading shared library %s failed, %s", filename, error_report); log_info(os)("shared library load of %s failed, %s", filename, error_report); } else { - Events::log(NULL, "Loaded shared library %s", filename); + Events::log_dll_message(NULL, "Loaded shared library %s", filename); log_info(os)("shared library load of %s was successful", filename); } return result; @@ -1857,13 +1857,16 @@ return result; } -void* os::dll_lookup(void* handle, const char* name) { - void* res = dlsym(handle, name); - return res; -} - -void* os::get_default_process_handle() { - return (void*)::dlopen(NULL, RTLD_LAZY); +const char* os::Linux::dll_path(void* lib) { + struct link_map *lmap; + const char* l_path = NULL; + assert(lib != NULL, "dll_path parameter must not be NULL"); + + int res_dli = ::dlinfo(lib, RTLD_DI_LINKMAP, &lmap); + if (res_dli == 0) { + l_path = lmap->l_name; + } + return l_path; } static bool _print_ascii_file(const char* filename, outputStream* st, const char* hdr = NULL) { @@ -4251,13 +4254,6 @@ return NULL; } -// Sleep forever; naked call to OS-specific sleep; use with CAUTION -void os::infinite_sleep() { - while (true) { // sleep forever ... - ::sleep(100); // ... 100 seconds at a time - } -} - // Used to convert frequent JVM_Yield() to nops bool os::dont_yield() { return DontYieldALot; @@ -4685,7 +4681,8 @@ // dynamic check - see 6515172 for details. // If anything goes wrong we fallback to returning the number of online // processors - which can be greater than the number available to the process. -int os::Linux::active_processor_count() { +static int get_active_processor_count() { + // Note: keep this function, with its CPU_xx macros, *outside* the os namespace (see JDK-8289477). cpu_set_t cpus; // can represent at most 1024 (CPU_SETSIZE) processors cpu_set_t* cpus_p = &cpus; int cpus_size = sizeof(cpu_set_t); @@ -4757,6 +4754,10 @@ return cpu_count; } +int os::Linux::active_processor_count() { + return get_active_processor_count(); +} + // Determine the active processor count from one of // three different sources: // @@ -4904,47 +4905,6 @@ f(value, method, args, thread); } -void os::print_statistics() { -} - -bool os::message_box(const char* title, const char* message) { - int i; - fdStream err(defaultStream::error_fd()); - for (i = 0; i < 78; i++) err.print_raw("="); - err.cr(); - err.print_raw_cr(title); - for (i = 0; i < 78; i++) err.print_raw("-"); - err.cr(); - err.print_raw_cr(message); - for (i = 0; i < 78; i++) err.print_raw("="); - err.cr(); - - char buf[16]; - // Prevent process from exiting upon "read error" without consuming all CPU - while (::read(0, buf, sizeof(buf)) <= 0) { ::sleep(100); } - - return buf[0] == 'y' || buf[0] == 'Y'; -} - -// Is a (classpath) directory empty? -bool os::dir_is_empty(const char* path) { - DIR *dir = NULL; - struct dirent *ptr; - - dir = opendir(path); - if (dir == NULL) return true; - - // Scan the directory - bool result = true; - while (result && (ptr = readdir(dir)) != NULL) { - if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) { - result = false; - } - } - closedir(dir); - return result; -} - // This code originates from JDK's sysOpen and open64_w // from src/solaris/hpi/src/system_md.c diff -Nru openjdk-17-17.0.4+8/src/hotspot/os/linux/os_linux.hpp openjdk-17-17.0.5+8/src/hotspot/os/linux/os_linux.hpp --- openjdk-17-17.0.4+8/src/hotspot/os/linux/os_linux.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/os/linux/os_linux.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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 @@ -120,6 +120,7 @@ static bool _stack_is_executable; static void *dlopen_helper(const char *name, char *ebuf, int ebuflen); static void *dll_load_in_vmthread(const char *name, char *ebuf, int ebuflen); + static const char *dll_path(void* lib); static void init_thread_fpu_state(); static int get_fpu_control_word(); diff -Nru openjdk-17-17.0.4+8/src/hotspot/os/posix/os_posix.cpp openjdk-17-17.0.5+8/src/hotspot/os/posix/os_posix.cpp --- openjdk-17-17.0.4+8/src/hotspot/os/posix/os_posix.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/os/posix/os_posix.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -45,6 +45,7 @@ #include "runtime/orderAccess.hpp" #include "runtime/perfMemory.hpp" #include "utilities/align.hpp" +#include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/formatBuffer.hpp" #include "utilities/macros.hpp" @@ -236,6 +237,25 @@ return fd; } +// Is a (classpath) directory empty? +bool os::dir_is_empty(const char* path) { + DIR *dir = NULL; + struct dirent *ptr; + + dir = ::opendir(path); + if (dir == NULL) return true; + + // Scan the directory + bool result = true; + while (result && (ptr = ::readdir(dir)) != NULL) { + if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) { + result = false; + } + } + ::closedir(dir); + return result; +} + static char* reserve_mmapped_memory(size_t bytes, char* requested_addr) { char * addr; int flags = MAP_PRIVATE NOT_AIX( | MAP_NORESERVE ) | MAP_ANONYMOUS; @@ -633,8 +653,42 @@ #endif } +void* os::get_default_process_handle() { +#ifdef __APPLE__ + // MacOS X needs to use RTLD_FIRST instead of RTLD_LAZY + // to avoid finding unexpected symbols on second (or later) + // loads of a library. + return (void*)::dlopen(NULL, RTLD_FIRST); +#else + return (void*)::dlopen(NULL, RTLD_LAZY); +#endif +} + +void* os::dll_lookup(void* handle, const char* name) { + return dlsym(handle, name); +} + void os::dll_unload(void *lib) { - ::dlclose(lib); + const char* l_path = LINUX_ONLY(os::Linux::dll_path(lib)) + NOT_LINUX(""); + if (l_path == NULL) l_path = ""; + int res = ::dlclose(lib); + + if (res == 0) { + Events::log_dll_message(NULL, "Unloaded shared library \"%s\" [" INTPTR_FORMAT "]", + l_path, p2i(lib)); + log_info(os)("Unloaded shared library \"%s\" [" INTPTR_FORMAT "]", l_path, p2i(lib)); + } else { + const char* error_report = ::dlerror(); + if (error_report == NULL) { + error_report = "dlerror returned no error description"; + } + + Events::log_dll_message(NULL, "Attempt to unload shared library \"%s\" [" INTPTR_FORMAT "] failed, %s", + l_path, p2i(lib), error_report); + log_info(os)("Attempt to unload shared library \"%s\" [" INTPTR_FORMAT "] failed, %s", + l_path, p2i(lib), error_report); + } } jlong os::lseek(int fd, jlong offset, int whence) { @@ -771,6 +825,12 @@ return agent_entry_name; } +// Sleep forever; naked call to OS-specific sleep; use with CAUTION +void os::infinite_sleep() { + while (true) { // sleep forever ... + ::sleep(100); // ... 100 seconds at a time + } +} void os::naked_short_nanosleep(jlong ns) { struct timespec req; @@ -1936,6 +1996,25 @@ } } +bool os::message_box(const char* title, const char* message) { + int i; + fdStream err(defaultStream::error_fd()); + for (i = 0; i < 78; i++) err.print_raw("="); + err.cr(); + err.print_raw_cr(title); + for (i = 0; i < 78; i++) err.print_raw("-"); + err.cr(); + err.print_raw_cr(message); + for (i = 0; i < 78; i++) err.print_raw("="); + err.cr(); + + char buf[16]; + // Prevent process from exiting upon "read error" without consuming all CPU + while (::read(0, buf, sizeof(buf)) <= 0) { ::sleep(100); } + + return buf[0] == 'y' || buf[0] == 'Y'; +} + //////////////////////////////////////////////////////////////////////////////// // runtime exit support diff -Nru openjdk-17-17.0.4+8/src/hotspot/os/windows/os_windows.cpp openjdk-17-17.0.5+8/src/hotspot/os/windows/os_windows.cpp --- openjdk-17-17.0.4+8/src/hotspot/os/windows/os_windows.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/os/windows/os_windows.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -22,8 +22,7 @@ * */ -// Must be at least Windows Vista or Server 2008 to use InitOnceExecuteOnce -#define _WIN32_WINNT 0x0600 +// API level must be at least Windows Vista or Server 2008 to use InitOnceExecuteOnce // no precompiled headers #include "jvm.h" @@ -1255,7 +1254,18 @@ const char* os::dll_file_extension() { return ".dll"; } void os::dll_unload(void *lib) { - ::FreeLibrary((HMODULE)lib); + char name[MAX_PATH]; + if (::GetModuleFileName((HMODULE)lib, name, sizeof(name)) == 0) { + snprintf(name, MAX_PATH, ""); + } + if (::FreeLibrary((HMODULE)lib)) { + Events::log_dll_message(NULL, "Unloaded dll \"%s\" [" INTPTR_FORMAT "]", name, p2i(lib)); + log_info(os)("Unloaded dll \"%s\" [" INTPTR_FORMAT "]", name, p2i(lib)); + } else { + const DWORD errcode = ::GetLastError(); + Events::log_dll_message(NULL, "Attempt to unload dll \"%s\" [" INTPTR_FORMAT "] failed (error code %d)", name, p2i(lib), errcode); + log_info(os)("Attempt to unload dll \"%s\" [" INTPTR_FORMAT "] failed (error code %d)", name, p2i(lib), errcode); + } } void* os::dll_lookup(void *lib, const char *name) { @@ -1526,7 +1536,7 @@ void * result = LoadLibrary(name); if (result != NULL) { - Events::log(NULL, "Loaded shared library %s", name); + Events::log_dll_message(NULL, "Loaded shared library %s", name); // Recalculate pdb search path if a DLL was loaded successfully. SymbolEngine::recalc_search_path(); log_info(os)("shared library load of %s was successful", name); @@ -1537,7 +1547,7 @@ // It may or may not be overwritten below (in the for loop and just above) lasterror(ebuf, (size_t) ebuflen); ebuf[ebuflen - 1] = '\0'; - Events::log(NULL, "Loading shared library %s failed, error code %lu", name, errcode); + Events::log_dll_message(NULL, "Loading shared library %s failed, error code %lu", name, errcode); log_info(os)("shared library load of %s failed, error code %lu", name, errcode); if (errcode == ERROR_MOD_NOT_FOUND) { @@ -3453,9 +3463,6 @@ return pd_release_memory(base, bytes); } -void os::print_statistics() { -} - static void warn_fail_commit_memory(char* addr, size_t bytes, bool exec) { int err = os::get_last_error(); char buf[256]; diff -Nru openjdk-17-17.0.4+8/src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp openjdk-17-17.0.5+8/src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp --- openjdk-17-17.0.4+8/src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/os_cpu/aix_ppc/thread_aix_ppc.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -30,7 +30,7 @@ frame JavaThread::pd_last_frame() { assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); - intptr_t* sp = last_Java_sp(); + intptr_t* sp = Atomic::load_acquire(&_anchor._last_Java_sp); address pc = _anchor.last_Java_pc(); // Last_Java_pc ist not set, if we come here from compiled code. diff -Nru openjdk-17-17.0.4+8/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp openjdk-17-17.0.5+8/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp --- openjdk-17-17.0.4+8/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/os_cpu/linux_ppc/thread_linux_ppc.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -31,7 +31,7 @@ frame JavaThread::pd_last_frame() { assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); - intptr_t* sp = last_Java_sp(); + intptr_t* sp = Atomic::load_acquire(&_anchor._last_Java_sp); address pc = _anchor.last_Java_pc(); // Last_Java_pc ist not set, if we come here from compiled code. diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/c1/c1_GraphBuilder.cpp openjdk-17-17.0.5+8/src/hotspot/share/c1/c1_GraphBuilder.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/c1/c1_GraphBuilder.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/c1/c1_GraphBuilder.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -213,8 +213,10 @@ } void BlockListBuilder::handle_jsr(BlockBegin* current, int sr_bci, int next_bci) { - // start a new block after jsr-bytecode and link this block into cfg - make_block_at(next_bci, current); + if (next_bci < method()->code_size()) { + // start a new block after jsr-bytecode and link this block into cfg + make_block_at(next_bci, current); + } // start a new block at the subroutine entry at mark it with special flag BlockBegin* sr_block = make_block_at(sr_bci, current); @@ -234,6 +236,8 @@ // branch target and a modification of the successor lists. const BitMap& bci_block_start = method()->bci_block_start(); + int end_bci = method()->code_size(); + ciBytecodeStream s(method()); while (s.next() != ciBytecodeStream::EOBC()) { int cur_bci = s.cur_bci(); @@ -304,7 +308,9 @@ case Bytecodes::_if_acmpne: // fall through case Bytecodes::_ifnull: // fall through case Bytecodes::_ifnonnull: - make_block_at(s.next_bci(), current); + if (s.next_bci() < end_bci) { + make_block_at(s.next_bci(), current); + } make_block_at(s.get_dest(), current); current = NULL; break; @@ -4045,20 +4051,28 @@ const int args_base = state()->stack_size() - callee->arg_size(); ValueType* type = state()->stack_at(args_base)->type(); if (type->is_constant()) { - ciMethod* target = type->as_ObjectType()->constant_value()->as_method_handle()->get_vmtarget(); - // We don't do CHA here so only inline static and statically bindable methods. - if (target->is_static() || target->can_be_statically_bound()) { - if (ciMethod::is_consistent_info(callee, target)) { - Bytecodes::Code bc = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual; - ignore_return = ignore_return || (callee->return_type()->is_void() && !target->return_type()->is_void()); - if (try_inline(target, /*holder_known*/ !callee->is_static(), ignore_return, bc)) { - return true; + ciObject* mh = type->as_ObjectType()->constant_value(); + if (mh->is_method_handle()) { + ciMethod* target = mh->as_method_handle()->get_vmtarget(); + + // We don't do CHA here so only inline static and statically bindable methods. + if (target->is_static() || target->can_be_statically_bound()) { + if (ciMethod::is_consistent_info(callee, target)) { + Bytecodes::Code bc = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual; + ignore_return = ignore_return || (callee->return_type()->is_void() && !target->return_type()->is_void()); + if (try_inline(target, /*holder_known*/ !callee->is_static(), ignore_return, bc)) { + return true; + } + } else { + print_inlining(target, "signatures mismatch", /*success*/ false); } } else { - print_inlining(target, "signatures mismatch", /*success*/ false); + assert(false, "no inlining through MH::invokeBasic"); // missing optimization opportunity due to suboptimal LF shape + print_inlining(target, "not static or statically bindable", /*success*/ false); } } else { - print_inlining(target, "not static or statically bindable", /*success*/ false); + assert(mh->is_null_object(), "not a null"); + print_inlining(callee, "receiver is always null", /*success*/ false); } } else { print_inlining(callee, "receiver not constant", /*success*/ false); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/c1/c1_LIRGenerator.cpp openjdk-17-17.0.5+8/src/hotspot/share/c1/c1_LIRGenerator.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/c1/c1_LIRGenerator.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/c1/c1_LIRGenerator.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1311,20 +1311,27 @@ info = state_for(x); } - LabelObj* L_not_prim = new LabelObj(); - LabelObj* L_done = new LabelObj(); + // While reading off the universal constant mirror is less efficient than doing + // another branch and returning the constant answer, this branchless code runs into + // much less risk of confusion for C1 register allocator. The choice of the universe + // object here is correct as long as it returns the same modifiers we would expect + // from the primitive class itself. See spec for Class.getModifiers that provides + // the typed array klasses with similar modifiers as their component types. + Klass* univ_klass_obj = Universe::byteArrayKlassObj(); + assert(univ_klass_obj->modifier_flags() == (JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC), "Sanity"); + LIR_Opr prim_klass = LIR_OprFact::metadataConst(univ_klass_obj); + + LIR_Opr recv_klass = new_register(T_METADATA); + __ move(new LIR_Address(receiver.result(), java_lang_Class::klass_offset(), T_ADDRESS), recv_klass, info); + + // Check if this is a Java mirror of primitive type, and select the appropriate klass. LIR_Opr klass = new_register(T_METADATA); - // Checking if it's a java mirror of primitive type - __ move(new LIR_Address(receiver.result(), java_lang_Class::klass_offset(), T_ADDRESS), klass, info); - __ cmp(lir_cond_notEqual, klass, LIR_OprFact::metadataConst(0)); - __ branch(lir_cond_notEqual, L_not_prim->label()); - __ move(LIR_OprFact::intConst(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC), result); - __ branch(lir_cond_always, L_done->label()); + __ cmp(lir_cond_equal, recv_klass, LIR_OprFact::metadataConst(0)); + __ cmove(lir_cond_equal, prim_klass, recv_klass, klass, T_ADDRESS); - __ branch_destination(L_not_prim->label()); + // Get the answer. __ move(new LIR_Address(klass, in_bytes(Klass::modifier_flags_offset()), T_INT), result); - __ branch_destination(L_done->label()); } // Example: Thread.currentThread() diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/c1/c1_LIR.hpp openjdk-17-17.0.5+8/src/hotspot/share/c1/c1_LIR.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/c1/c1_LIR.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/c1/c1_LIR.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -231,13 +231,13 @@ , is_xmm_bits = 1 , last_use_bits = 1 , is_fpu_stack_offset_bits = 1 // used in assertion checking on x86 for FPU stack slot allocation - , non_data_bits = pointer_bits + kind_bits + type_bits + size_bits + destroys_bits + virtual_bits + , non_data_bits = kind_bits + type_bits + size_bits + destroys_bits + virtual_bits + is_xmm_bits + last_use_bits + is_fpu_stack_offset_bits , data_bits = BitsPerInt - non_data_bits , reg_bits = data_bits / 2 // for two registers in one value encoding }; - enum OprShift { + enum OprShift : uintptr_t { kind_shift = 0 , type_shift = kind_shift + kind_bits , size_shift = type_shift + type_bits @@ -270,7 +270,7 @@ , no_type_mask = (int)(~(type_mask | last_use_mask | is_fpu_stack_offset_mask)) }; - uintptr_t data() const { return value() >> data_shift; } + uint32_t data() const { return (uint32_t)value() >> data_shift; } int lo_reg_half() const { return data() & lower_reg_mask; } int hi_reg_half() const { return (data() >> reg_bits) & lower_reg_mask; } OprKind kind_field() const { return (OprKind)(value() & kind_mask); } @@ -281,7 +281,9 @@ public: enum { vreg_base = ConcreteRegisterImpl::number_of_registers, - vreg_max = (1 << data_bits) - 1 + data_max = (1 << data_bits) - 1, // max unsigned value for data bit field + vreg_limit = 10000, // choose a reasonable limit, + vreg_max = MIN2(vreg_limit, data_max) // and make sure if fits in the bit field }; static inline LIR_Opr illegalOpr(); @@ -736,7 +738,6 @@ res->validate_type(); assert(res->vreg_number() == index, "conversion check"); assert(index >= LIR_OprDesc::vreg_base, "must start at vreg_base"); - assert(index <= (max_jint >> LIR_OprDesc::data_shift), "index is too big"); // old-style calculation; check if old and new method are equal LIR_OprDesc::OprType t = as_OprType(type); @@ -815,7 +816,7 @@ #ifdef ASSERT assert(index >= 0, "index must be positive"); - assert(index <= (max_jint >> LIR_OprDesc::data_shift), "index is too big"); + assert(index == (int)res->data(), "conversion check"); LIR_Opr old_res = (LIR_Opr)(intptr_t)((index << LIR_OprDesc::data_shift) | LIR_OprDesc::stack_value | @@ -2314,7 +2315,7 @@ typedef enum { inputMode, firstMode = inputMode, tempMode, outputMode, numModes, invalidMode = -1 } OprMode; enum { - maxNumberOfOperands = 20, + maxNumberOfOperands = 21, maxNumberOfInfos = 4 }; diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/ci/ciInstanceKlass.cpp openjdk-17-17.0.5+8/src/hotspot/share/ci/ciInstanceKlass.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/ci/ciInstanceKlass.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/ci/ciInstanceKlass.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -638,8 +638,10 @@ ciInstanceKlass* ciInstanceKlass::implementor() { ciInstanceKlass* impl = _implementor; if (impl == NULL) { - // Go into the VM to fetch the implementor. - { + if (is_shared()) { + impl = this; // assume a well-known interface never has a unique implementor + } else { + // Go into the VM to fetch the implementor. VM_ENTRY_MARK; MutexLocker ml(Compile_lock); Klass* k = get_instanceKlass()->implementor(); @@ -653,9 +655,7 @@ } } // Memoize this result. - if (!is_shared()) { - _implementor = impl; - } + _implementor = impl; } return impl; } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/ci/ciMethodBlocks.cpp openjdk-17-17.0.5+8/src/hotspot/share/ci/ciMethodBlocks.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/ci/ciMethodBlocks.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/ci/ciMethodBlocks.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,12 +33,13 @@ ciBlock *ciMethodBlocks::block_containing(int bci) { + assert(bci >= 0 && bci < _code_size, "valid bytecode range"); ciBlock *blk = _bci_to_block[bci]; return blk; } bool ciMethodBlocks::is_block_start(int bci) { - assert(bci >=0 && bci < _code_size, "valid bytecode range"); + assert(bci >= 0 && bci < _code_size, "valid bytecode range"); ciBlock *b = _bci_to_block[bci]; assert(b != NULL, "must have block for bytecode"); return b->start_bci() == bci; @@ -146,7 +147,9 @@ case Bytecodes::_ifnonnull : { cur_block->set_control_bci(bci); - ciBlock *fall_through = make_block_at(s.next_bci()); + if (s.next_bci() < limit_bci) { + ciBlock *fall_through = make_block_at(s.next_bci()); + } int dest_bci = s.get_dest(); ciBlock *dest = make_block_at(dest_bci); break; @@ -166,7 +169,9 @@ case Bytecodes::_jsr : { cur_block->set_control_bci(bci); - ciBlock *ret = make_block_at(s.next_bci()); + if (s.next_bci() < limit_bci) { + ciBlock *ret = make_block_at(s.next_bci()); + } int dest_bci = s.get_dest(); ciBlock *dest = make_block_at(dest_bci); break; @@ -224,7 +229,9 @@ case Bytecodes::_jsr_w : { cur_block->set_control_bci(bci); - ciBlock *ret = make_block_at(s.next_bci()); + if (s.next_bci() < limit_bci) { + ciBlock *ret = make_block_at(s.next_bci()); + } int dest_bci = s.get_far_dest(); ciBlock *dest = make_block_at(dest_bci); break; diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/classfile/classLoaderData.cpp openjdk-17-17.0.5+8/src/hotspot/share/classfile/classLoaderData.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/classfile/classLoaderData.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/classfile/classLoaderData.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -968,11 +968,13 @@ out->print_cr(" - keep alive %d", _keep_alive); out->print (" - claim "); switch(_claim) { - case _claim_none: out->print_cr("none"); break; - case _claim_finalizable:out->print_cr("finalizable"); break; - case _claim_strong: out->print_cr("strong"); break; - case _claim_other: out->print_cr("other"); break; - default: ShouldNotReachHere(); + case _claim_none: out->print_cr("none"); break; + case _claim_finalizable: out->print_cr("finalizable"); break; + case _claim_strong: out->print_cr("strong"); break; + case _claim_other: out->print_cr("other"); break; + case _claim_other | _claim_finalizable: out->print_cr("other and finalizable"); break; + case _claim_other | _claim_strong: out->print_cr("other and strong"); break; + default: ShouldNotReachHere(); } out->print_cr(" - handles %d", _handles.count()); out->print_cr(" - dependency count %d", _dependency_count); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/classfile/verifier.cpp openjdk-17-17.0.5+8/src/hotspot/share/classfile/verifier.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/classfile/verifier.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/classfile/verifier.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -2947,15 +2947,15 @@ _klass, ref_class, method_name, method_sig, true)) { // It's protected access, check if stack object is // assignable to current class. - bool is_assignable = current_type().is_assignable_from( - stack_object_type, this, true, CHECK_VERIFY(this)); - if (!is_assignable) { - if (ref_class_type.name() == vmSymbols::java_lang_Object() - && stack_object_type.is_array() - && method_name == vmSymbols::clone_name()) { - // Special case: arrays pretend to implement public Object - // clone(). - } else { + if (ref_class_type.name() == vmSymbols::java_lang_Object() + && stack_object_type.is_array() + && method_name == vmSymbols::clone_name()) { + // Special case: arrays pretend to implement public Object + // clone(). + } else { + bool is_assignable = current_type().is_assignable_from( + stack_object_type, this, true, CHECK_VERIFY(this)); + if (!is_assignable) { verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx(), TypeOrigin::implicit(current_type())), diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/code/codeCache.cpp openjdk-17-17.0.5+8/src/hotspot/share/code/codeCache.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/code/codeCache.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/code/codeCache.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -630,14 +630,23 @@ return contains((void *)nm); } +static bool is_in_asgct() { + Thread* current_thread = Thread::current_or_null_safe(); + return current_thread != NULL && current_thread->is_Java_thread() && current_thread->as_Java_thread()->in_asgct(); +} + // This method is safe to call without holding the CodeCache_lock, as long as a dead CodeBlob is not // looked up (i.e., one that has been marked for deletion). It only depends on the _segmap to contain // valid indices, which it will always do, as long as the CodeBlob is not in the process of being recycled. CodeBlob* CodeCache::find_blob(void* start) { CodeBlob* result = find_blob_unsafe(start); // We could potentially look up non_entrant methods - guarantee(result == NULL || !result->is_zombie() || result->is_locked_by_vm() || VMError::is_error_reported(), "unsafe access to zombie method"); - return result; + bool is_zombie = result != NULL && result->is_zombie(); + bool is_result_safe = !is_zombie || result->is_locked_by_vm() || VMError::is_error_reported(); + guarantee(is_result_safe || is_in_asgct(), "unsafe access to zombie method"); + // When in ASGCT the previous gurantee will pass for a zombie method but we still don't want that code blob returned in order + // to minimize the chance of accessing dead memory + return is_result_safe ? result : NULL; } // Lookup that does not fail if you lookup a zombie method (if you call this, be sure to know diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/compiler/compilationPolicy.cpp openjdk-17-17.0.5+8/src/hotspot/share/compiler/compilationPolicy.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/compiler/compilationPolicy.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/compiler/compilationPolicy.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -191,7 +191,7 @@ // Simple methods are as good being compiled with C1 as C2. // Determine if a given method is such a case. -bool CompilationPolicy::is_trivial(Method* method) { +bool CompilationPolicy::is_trivial(const methodHandle& method) { if (method->is_accessor() || method->is_constant_getter()) { return true; @@ -245,7 +245,7 @@ } } - static bool apply(int i, int b, CompLevel cur_level, const methodHandle& method) { + static bool apply(const methodHandle& method, CompLevel cur_level, int i, int b) { double k = 1; switch(cur_level) { case CompLevel_none: @@ -285,7 +285,7 @@ } } - static bool apply(int i, int b, CompLevel cur_level, const methodHandle& method) { + static bool apply(const methodHandle& method, CompLevel cur_level, int i, int b) { double k = 1; switch(cur_level) { case CompLevel_none: @@ -596,7 +596,7 @@ } // Set carry flags on the counters if necessary -void CompilationPolicy::handle_counter_overflow(Method* method) { +void CompilationPolicy::handle_counter_overflow(const methodHandle& method) { MethodCounters *mcs = method->method_counters(); if (mcs != NULL) { mcs->invocation_counter()->set_carry_on_overflow(); @@ -619,21 +619,25 @@ // Iterate through the queue and find a method with a maximum rate. for (CompileTask* task = compile_queue->first(); task != NULL;) { CompileTask* next_task = task->next(); - Method* method = task->method(); // If a method was unloaded or has been stale for some time, remove it from the queue. // Blocking tasks and tasks submitted from whitebox API don't become stale - if (task->is_unloaded() || (task->can_become_stale() && is_stale(t, TieredCompileTaskTimeout, method) && !is_old(method))) { - if (!task->is_unloaded()) { - if (PrintTieredEvents) { - print_event(REMOVE_FROM_QUEUE, method, method, task->osr_bci(), (CompLevel) task->comp_level()); - } - method->clear_queued_for_compilation(); + if (task->is_unloaded()) { + compile_queue->remove_and_mark_stale(task); + task = next_task; + continue; + } + Method* method = task->method(); + methodHandle mh(Thread::current(), method); + if (task->can_become_stale() && is_stale(t, TieredCompileTaskTimeout, mh) && !is_old(mh)) { + if (PrintTieredEvents) { + print_event(REMOVE_FROM_QUEUE, method, method, task->osr_bci(), (CompLevel) task->comp_level()); } + method->clear_queued_for_compilation(); compile_queue->remove_and_mark_stale(task); task = next_task; continue; } - update_rate(t, method); + update_rate(t, mh); if (max_task == NULL || compare_methods(method, max_method)) { // Select a method with the highest rate max_task = task; @@ -711,9 +715,9 @@ return NULL; } - handle_counter_overflow(method()); + handle_counter_overflow(method); if (method() != inlinee()) { - handle_counter_overflow(inlinee()); + handle_counter_overflow(inlinee); } if (bci == InvocationEntryBci) { @@ -792,43 +796,43 @@ print_event(COMPILE, mh(), mh(), bci, level); } int hot_count = (bci == InvocationEntryBci) ? mh->invocation_count() : mh->backedge_count(); - update_rate(nanos_to_millis(os::javaTimeNanos()), mh()); + update_rate(nanos_to_millis(os::javaTimeNanos()), mh); CompileBroker::compile_method(mh, bci, level, mh, hot_count, CompileTask::Reason_Tiered, THREAD); } } // update_rate() is called from select_task() while holding a compile queue lock. -void CompilationPolicy::update_rate(jlong t, Method* m) { +void CompilationPolicy::update_rate(jlong t, const methodHandle& method) { // Skip update if counters are absent. // Can't allocate them since we are holding compile queue lock. - if (m->method_counters() == NULL) return; + if (method->method_counters() == NULL) return; - if (is_old(m)) { + if (is_old(method)) { // We don't remove old methods from the queue, // so we can just zero the rate. - m->set_rate(0); + method->set_rate(0); return; } // We don't update the rate if we've just came out of a safepoint. // delta_s is the time since last safepoint in milliseconds. jlong delta_s = t - SafepointTracing::end_of_last_safepoint_ms(); - jlong delta_t = t - (m->prev_time() != 0 ? m->prev_time() : start_time()); // milliseconds since the last measurement + jlong delta_t = t - (method->prev_time() != 0 ? method->prev_time() : start_time()); // milliseconds since the last measurement // How many events were there since the last time? - int event_count = m->invocation_count() + m->backedge_count(); - int delta_e = event_count - m->prev_event_count(); + int event_count = method->invocation_count() + method->backedge_count(); + int delta_e = event_count - method->prev_event_count(); // We should be running for at least 1ms. if (delta_s >= TieredRateUpdateMinTime) { // And we must've taken the previous point at least 1ms before. if (delta_t >= TieredRateUpdateMinTime && delta_e > 0) { - m->set_prev_time(t); - m->set_prev_event_count(event_count); - m->set_rate((float)delta_e / (float)delta_t); // Rate is events per millisecond + method->set_prev_time(t); + method->set_prev_event_count(event_count); + method->set_rate((float)delta_e / (float)delta_t); // Rate is events per millisecond } else { if (delta_t > TieredRateUpdateMaxTime && delta_e == 0) { // If nothing happened for 25ms, zero the rate. Don't modify prev values. - m->set_rate(0); + method->set_rate(0); } } } @@ -836,12 +840,12 @@ // Check if this method has been stale for a given number of milliseconds. // See select_task(). -bool CompilationPolicy::is_stale(jlong t, jlong timeout, Method* m) { +bool CompilationPolicy::is_stale(jlong t, jlong timeout, const methodHandle& method) { jlong delta_s = t - SafepointTracing::end_of_last_safepoint_ms(); - jlong delta_t = t - m->prev_time(); + jlong delta_t = t - method->prev_time(); if (delta_t > timeout && delta_s > timeout) { - int event_count = m->invocation_count() + m->backedge_count(); - int delta_e = event_count - m->prev_event_count(); + int event_count = method->invocation_count() + method->backedge_count(); + int delta_e = event_count - method->prev_event_count(); // Return true if there were no events. return delta_e == 0; } @@ -850,13 +854,16 @@ // We don't remove old methods from the compile queue even if they have // very low activity. See select_task(). -bool CompilationPolicy::is_old(Method* method) { - return method->invocation_count() > 50000 || method->backedge_count() > 500000; +bool CompilationPolicy::is_old(const methodHandle& method) { + int i = method->invocation_count(); + int b = method->backedge_count(); + double k = TieredOldPercentage / 100.0; + + return CallPredicate::apply_scaled(method, CompLevel_none, i, b, k) || LoopPredicate::apply_scaled(method, CompLevel_none, i, b, k); } double CompilationPolicy::weight(Method* method) { - return (double)(method->rate() + 1) * - (method->invocation_count() + 1) * (method->backedge_count() + 1); + return (double)(method->rate() + 1) * (method->invocation_count() + 1) * (method->backedge_count() + 1); } // Apply heuristics and return true if x should be compiled before y @@ -905,13 +912,16 @@ if (cur_level != CompLevel_none || force_comp_at_level_simple(method) || CompilationModeFlag::quick_only() || !ProfileInterpreter) { return false; } + if (is_old(method)) { + return true; + } int i = method->invocation_count(); int b = method->backedge_count(); double k = Tier0ProfilingStartPercentage / 100.0; // If the top level compiler is not keeping up, delay profiling. if (CompileBroker::queue_size(CompLevel_full_optimization) <= Tier0Delay * compiler_count(CompLevel_full_optimization)) { - return CallPredicate::apply_scaled(method, CompLevel_full_profile, i, b, k) || LoopPredicate::apply_scaled(method, CompLevel_full_profile, i, b, k); + return CallPredicate::apply_scaled(method, CompLevel_none, i, b, k) || LoopPredicate::apply_scaled(method, CompLevel_none, i, b, k); } return false; } @@ -1001,7 +1011,7 @@ if (force_comp_at_level_simple(method)) { next_level = CompLevel_simple; } else { - if (is_trivial(method())) { + if (is_trivial(method)) { next_level = CompilationModeFlag::disable_intermediate() ? CompLevel_full_optimization : CompLevel_simple; } else { switch(cur_level) { @@ -1010,7 +1020,7 @@ // If we were at full profile level, would we switch to full opt? if (common(method, CompLevel_full_profile, disable_feedback) == CompLevel_full_optimization) { next_level = CompLevel_full_optimization; - } else if (!CompilationModeFlag::disable_intermediate() && Predicate::apply(i, b, cur_level, method)) { + } else if (!CompilationModeFlag::disable_intermediate() && Predicate::apply(method, cur_level, i, b)) { // C1-generated fully profiled code is about 30% slower than the limited profile // code that has only invocation and backedge counters. The observation is that // if C2 queue is large enough we can spend too much time in the fully profiled code @@ -1036,7 +1046,7 @@ if (mdo->would_profile()) { if (disable_feedback || (CompileBroker::queue_size(CompLevel_full_optimization) <= Tier3DelayOff * compiler_count(CompLevel_full_optimization) && - Predicate::apply(i, b, cur_level, method))) { + Predicate::apply(method, cur_level, i, b))) { next_level = CompLevel_full_profile; } } else { @@ -1046,7 +1056,7 @@ // If there is no MDO we need to profile if (disable_feedback || (CompileBroker::queue_size(CompLevel_full_optimization) <= Tier3DelayOff * compiler_count(CompLevel_full_optimization) && - Predicate::apply(i, b, cur_level, method))) { + Predicate::apply(method, cur_level, i, b))) { next_level = CompLevel_full_profile; } } @@ -1059,7 +1069,7 @@ if (mdo->would_profile() || CompilationModeFlag::disable_intermediate()) { int mdo_i = mdo->invocation_count_delta(); int mdo_b = mdo->backedge_count_delta(); - if (Predicate::apply(mdo_i, mdo_b, cur_level, method)) { + if (Predicate::apply(method, cur_level, mdo_i, mdo_b)) { next_level = CompLevel_full_optimization; } } else { @@ -1079,7 +1089,7 @@ // Determine if a method should be compiled with a normal entry point at a different level. CompLevel CompilationPolicy::call_event(const methodHandle& method, CompLevel cur_level, Thread* thread) { CompLevel osr_level = MIN2((CompLevel) method->highest_osr_comp_level(), common(method, cur_level, true)); - CompLevel next_level = common(method, cur_level); + CompLevel next_level = common(method, cur_level, is_old(method)); // If OSR method level is greater than the regular method level, the levels should be // equalized by raising the regular method level in order to avoid OSRs during each diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/compiler/compilationPolicy.hpp openjdk-17-17.0.5+8/src/hotspot/share/compiler/compilationPolicy.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/compiler/compilationPolicy.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/compiler/compilationPolicy.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -169,7 +169,7 @@ static double _increase_threshold_at_ratio; // Set carry flags in the counters (in Method* and MDO). - inline static void handle_counter_overflow(Method* method); + inline static void handle_counter_overflow(const methodHandle& method); // Verify that a level is consistent with the compilation mode static bool verify_level(CompLevel level); // Clamp the request level according to various constraints. @@ -188,17 +188,17 @@ // Has a method been long around? // We don't remove old methods from the compile queue even if they have // very low activity (see select_task()). - inline static bool is_old(Method* method); + inline static bool is_old(const methodHandle& method); // Was a given method inactive for a given number of milliseconds. // If it is, we would remove it from the queue (see select_task()). - inline static bool is_stale(jlong t, jlong timeout, Method* m); + inline static bool is_stale(jlong t, jlong timeout, const methodHandle& method); // Compute the weight of the method for the compilation scheduling inline static double weight(Method* method); // Apply heuristics and return true if x should be compiled before y inline static bool compare_methods(Method* x, Method* y); // Compute event rate for a given method. The rate is the number of event (invocations + backedges) // per millisecond. - inline static void update_rate(jlong t, Method* m); + inline static void update_rate(jlong t, const methodHandle& method); // Compute threshold scaling coefficient inline static double threshold_scale(CompLevel level, int feedback_k); // If a method is old enough and is still in the interpreter we would want to @@ -219,7 +219,7 @@ static void compile(const methodHandle& mh, int bci, CompLevel level, TRAPS); // Simple methods are as good being compiled with C1 as C2. // This function tells if it's such a function. - inline static bool is_trivial(Method* method); + inline static bool is_trivial(const methodHandle& method); // Force method to be compiled at CompLevel_simple? inline static bool force_comp_at_level_simple(const methodHandle& method); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/compiler/compileBroker.cpp openjdk-17-17.0.5+8/src/hotspot/share/compiler/compileBroker.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/compiler/compileBroker.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/compiler/compileBroker.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -2319,8 +2319,9 @@ /* Repeat compilation without installing code for profiling purposes */ int repeat_compilation_count = directive->RepeatCompilationOption; while (repeat_compilation_count > 0) { + ResourceMark rm(thread); task->print_ul("NO CODE INSTALLED"); - comp->compile_method(&ci_env, target, osr_bci, false , directive); + comp->compile_method(&ci_env, target, osr_bci, false, directive); repeat_compilation_count--; } } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/compiler/compilerDefinitions.cpp openjdk-17-17.0.5+8/src/hotspot/share/compiler/compilerDefinitions.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/compiler/compilerDefinitions.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/compiler/compilerDefinitions.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -267,12 +267,11 @@ FLAG_SET_ERGO(Tier0BackedgeNotifyFreqLog, MAX2(10, osr_threshold_log)); } // Adjust the tiered policy flags to approximate the legacy behavior. - if (CompilerConfig::is_c1_only()) { - FLAG_SET_ERGO(Tier3InvocationThreshold, threshold); - FLAG_SET_ERGO(Tier3MinInvocationThreshold, threshold); - FLAG_SET_ERGO(Tier3CompileThreshold, threshold); - FLAG_SET_ERGO(Tier3BackEdgeThreshold, osr_threshold); - } else { + FLAG_SET_ERGO(Tier3InvocationThreshold, threshold); + FLAG_SET_ERGO(Tier3MinInvocationThreshold, threshold); + FLAG_SET_ERGO(Tier3CompileThreshold, threshold); + FLAG_SET_ERGO(Tier3BackEdgeThreshold, osr_threshold); + if (CompilerConfig::is_c2_or_jvmci_compiler_only()) { FLAG_SET_ERGO(Tier4InvocationThreshold, threshold); FLAG_SET_ERGO(Tier4MinInvocationThreshold, threshold); FLAG_SET_ERGO(Tier4CompileThreshold, threshold); @@ -339,6 +338,20 @@ if (FLAG_IS_DEFAULT(Tier4BackEdgeThreshold)) { FLAG_SET_DEFAULT(Tier4BackEdgeThreshold, 15000); } + + if (FLAG_IS_DEFAULT(Tier3InvocationThreshold)) { + FLAG_SET_DEFAULT(Tier3InvocationThreshold, Tier4InvocationThreshold); + } + if (FLAG_IS_DEFAULT(Tier3MinInvocationThreshold)) { + FLAG_SET_DEFAULT(Tier3MinInvocationThreshold, Tier4MinInvocationThreshold); + } + if (FLAG_IS_DEFAULT(Tier3CompileThreshold)) { + FLAG_SET_DEFAULT(Tier3CompileThreshold, Tier4CompileThreshold); + } + if (FLAG_IS_DEFAULT(Tier3BackEdgeThreshold)) { + FLAG_SET_DEFAULT(Tier3BackEdgeThreshold, Tier4BackEdgeThreshold); + } + } // Scale tiered compilation thresholds. diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/compiler/compiler_globals.hpp openjdk-17-17.0.5+8/src/hotspot/share/compiler/compiler_globals.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/compiler/compiler_globals.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/compiler/compiler_globals.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -213,6 +213,12 @@ "do not start profiling in the interpreter") \ range(0, max_jint) \ \ + product(intx, TieredOldPercentage, 1000, DIAGNOSTIC, \ + "Percentage over tier 3 thresholds after which a method is " \ + "considered old (turns off parts of prioritization based on " \ + "compile queue length)") \ + range(0, max_jint) \ + \ product(intx, Tier3DelayOn, 5, \ "If C2 queue size grows over this amount per compiler thread " \ "stop compiling at tier 3 and start compiling at tier 2") \ @@ -244,8 +250,7 @@ \ product(intx, Tier0ProfilingStartPercentage, 200, \ "Start profiling in interpreter if the counters exceed the " \ - "specified percentage of tier 3 thresholds (tier 4 thresholds " \ - "with CompilationMode=high-only|high-only-quick-internal)") \ + "specified percentage of tier 3 thresholds") \ range(0, max_jint) \ \ product(uintx, IncreaseFirstTierCompileThresholdAt, 50, \ diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/compiler/methodLiveness.cpp openjdk-17-17.0.5+8/src/hotspot/share/compiler/methodLiveness.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/compiler/methodLiveness.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/compiler/methodLiveness.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -164,10 +164,11 @@ case Bytecodes::_ifnull: case Bytecodes::_ifnonnull: // Two way branch. Set predecessors at each destination. - dest = _block_map->at(bytes.next_bci()); - assert(dest != NULL, "must be a block immediately following this one."); - dest->add_normal_predecessor(current_block); - + if (bytes.next_bci() < method_len) { + dest = _block_map->at(bytes.next_bci()); + assert(dest != NULL, "must be a block immediately following this one."); + dest->add_normal_predecessor(current_block); + } dest = _block_map->at(bytes.get_dest()); assert(dest != NULL, "branch desination must start a block."); dest->add_normal_predecessor(current_block); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp openjdk-17-17.0.5+8/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -91,19 +91,19 @@ MemNode::MemOrd mo = access.mem_node_mo(); Node* store; + BasicType bt = access.type(); if (access.is_parse_access()) { C2ParseAccess& parse_access = static_cast(access); GraphKit* kit = parse_access.kit(); - if (access.type() == T_DOUBLE) { + if (bt == T_DOUBLE) { Node* new_val = kit->dstore_rounding(val.node()); val.set_node(new_val); } - store = kit->store_to_memory(kit->control(), access.addr().node(), val.node(), access.type(), - access.addr().type(), mo, requires_atomic_access, unaligned, mismatched, unsafe); + store = kit->store_to_memory(kit->control(), access.addr().node(), val.node(), bt, + access.addr().type(), mo, requires_atomic_access, unaligned, mismatched, unsafe); } else { - assert(!requires_atomic_access, "not yet supported"); assert(access.is_opt_access(), "either parse or opt access"); C2OptAccess& opt_access = static_cast(access); Node* ctl = opt_access.ctl(); @@ -113,7 +113,7 @@ int alias = gvn.C->get_alias_index(adr_type); Node* mem = mm->memory_at(alias); - StoreNode* st = StoreNode::make(gvn, ctl, mem, access.addr().node(), adr_type, val.node(), access.type(), mo); + StoreNode* st = StoreNode::make(gvn, ctl, mem, access.addr().node(), adr_type, val.node(), bt, mo, requires_atomic_access); if (unaligned) { st->set_unaligned_access(); } @@ -156,12 +156,11 @@ Node* control = control_dependent ? kit->control() : NULL; if (immutable) { - assert(!requires_atomic_access, "can't ensure atomicity"); Compile* C = Compile::current(); Node* mem = kit->immutable_memory(); load = LoadNode::make(kit->gvn(), control, mem, adr, - adr_type, val_type, access.type(), mo, dep, unaligned, - mismatched, unsafe, access.barrier_data()); + adr_type, val_type, access.type(), mo, dep, requires_atomic_access, + unaligned, mismatched, unsafe, access.barrier_data()); load = kit->gvn().transform(load); } else { load = kit->make_load(control, adr, val_type, access.type(), adr_type, mo, @@ -169,15 +168,14 @@ access.barrier_data()); } } else { - assert(!requires_atomic_access, "not yet supported"); assert(access.is_opt_access(), "either parse or opt access"); C2OptAccess& opt_access = static_cast(access); Node* control = control_dependent ? opt_access.ctl() : NULL; MergeMemNode* mm = opt_access.mem(); PhaseGVN& gvn = opt_access.gvn(); Node* mem = mm->memory_at(gvn.C->get_alias_index(adr_type)); - load = LoadNode::make(gvn, control, mem, adr, adr_type, val_type, access.type(), mo, - dep, unaligned, mismatched, unsafe, access.barrier_data()); + load = LoadNode::make(gvn, control, mem, adr, adr_type, val_type, access.type(), mo, dep, + requires_atomic_access, unaligned, mismatched, unsafe, access.barrier_data()); load = gvn.transform(load); } access.set_raw_access(load); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp openjdk-17-17.0.5+8/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -205,7 +205,7 @@ // Note: We don't need a keep-alive-barrier here. We already enqueue any loaded reference for SATB anyway, // because it must be the previous value. - res = load_reference_barrier(decorators, res, reinterpret_cast(NULL)); + res = load_reference_barrier(decorators, res, static_cast(nullptr)); satb_enqueue(res); return res; } @@ -216,7 +216,7 @@ oop previous = RawAccess<>::oop_atomic_xchg(addr, new_value); // Note: We don't need a keep-alive-barrier here. We already enqueue any loaded reference for SATB anyway, // because it must be the previous value. - previous = load_reference_barrier(decorators, previous, reinterpret_cast(NULL)); + previous = load_reference_barrier(decorators, previous, static_cast(nullptr)); satb_enqueue(previous); return previous; } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/gc/z/zReferenceProcessor.cpp openjdk-17-17.0.5+8/src/hotspot/share/gc/z/zReferenceProcessor.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/gc/z/zReferenceProcessor.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/gc/z/zReferenceProcessor.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -59,7 +59,7 @@ default: ShouldNotReachHere(); - return NULL; + return "Unknown"; } } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/jfr/jfr.cpp openjdk-17-17.0.5+8/src/hotspot/share/jfr/jfr.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/jfr/jfr.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/jfr/jfr.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -92,8 +92,8 @@ return t != NULL && t->jfr_thread_local()->is_excluded(); } -void Jfr::on_vm_shutdown(bool exception_handler) { - if (JfrRecorder::is_recording()) { +void Jfr::on_vm_shutdown(bool exception_handler, bool halt) { + if (!halt && JfrRecorder::is_recording()) { JfrEmergencyDump::on_vm_shutdown(exception_handler); } } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/jfr/jfr.hpp openjdk-17-17.0.5+8/src/hotspot/share/jfr/jfr.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/jfr/jfr.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/jfr/jfr.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -48,7 +48,7 @@ static void on_unloading_classes(); static void on_thread_start(Thread* thread); static void on_thread_exit(Thread* thread); - static void on_vm_shutdown(bool exception_handler = false); + static void on_vm_shutdown(bool exception_handler = false, bool halt = false); static bool on_flight_recorder_option(const JavaVMOption** option, char* delimiter); static bool on_start_flight_recording_option(const JavaVMOption** option, char* delimiter); static void on_vm_error_report(outputStream* st); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp openjdk-17-17.0.5+8/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -2590,6 +2590,49 @@ } } +C2V_VMENTRY(void, setThreadLocalObject, (JNIEnv* env, jobject, jint id, jobject value)) + requireInHotSpot("setThreadLocalObject", JVMCI_CHECK); + if (id == 0) { + thread->set_jvmci_reserved_oop0(JNIHandles::resolve(value)); + return; + } + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + err_msg("%d is not a valid thread local id", id)); +} + +C2V_VMENTRY_NULL(jobject, getThreadLocalObject, (JNIEnv* env, jobject, jint id)) + requireInHotSpot("getThreadLocalObject", JVMCI_CHECK_NULL); + if (id == 0) { + return JNIHandles::make_local(thread->get_jvmci_reserved_oop0()); + } + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), + err_msg("%d is not a valid thread local id", id)); +} + +C2V_VMENTRY(void, setThreadLocalLong, (JNIEnv* env, jobject, jint id, jlong value)) + requireInHotSpot("setThreadLocalLong", JVMCI_CHECK); + if (id == 0) { + thread->set_jvmci_reserved0(value); + } else if (id == 1) { + thread->set_jvmci_reserved1(value); + } else { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + err_msg("%d is not a valid thread local id", id)); + } +} + +C2V_VMENTRY_0(jlong, getThreadLocalLong, (JNIEnv* env, jobject, jint id)) + requireInHotSpot("getThreadLocalLong", JVMCI_CHECK_0); + if (id == 0) { + return thread->get_jvmci_reserved0(); + } else if (id == 1) { + return thread->get_jvmci_reserved1(); + } else { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), + err_msg("%d is not a valid thread local id", id)); + } +} + #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f)) @@ -2731,6 +2774,10 @@ {CC "addFailedSpeculation", CC "(J[B)Z", FN_PTR(addFailedSpeculation)}, {CC "callSystemExit", CC "(I)V", FN_PTR(callSystemExit)}, {CC "ticksNow", CC "()J", FN_PTR(ticksNow)}, + {CC "getThreadLocalObject", CC "(I)" OBJECT, FN_PTR(getThreadLocalObject)}, + {CC "setThreadLocalObject", CC "(I" OBJECT ")V", FN_PTR(setThreadLocalObject)}, + {CC "getThreadLocalLong", CC "(I)J", FN_PTR(getThreadLocalLong)}, + {CC "setThreadLocalLong", CC "(IJ)V", FN_PTR(setThreadLocalLong)}, {CC "registerCompilerPhase", CC "(" STRING ")I", FN_PTR(registerCompilerPhase)}, {CC "notifyCompilerPhaseEvent", CC "(JIII)V", FN_PTR(notifyCompilerPhaseEvent)}, {CC "notifyCompilerInliningEvent", CC "(I" HS_RESOLVED_METHOD HS_RESOLVED_METHOD "ZLjava/lang/String;I)V", FN_PTR(notifyCompilerInliningEvent)}, diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/jvmci/vmStructs_jvmci.cpp openjdk-17-17.0.5+8/src/hotspot/share/jvmci/vmStructs_jvmci.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/jvmci/vmStructs_jvmci.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/jvmci/vmStructs_jvmci.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -183,8 +183,8 @@ nonstatic_field(JavaThread, _pending_failed_speculation, jlong) \ nonstatic_field(JavaThread, _pending_transfer_to_interpreter, bool) \ nonstatic_field(JavaThread, _jvmci_counters, jlong*) \ - nonstatic_field(JavaThread, _jvmci_reserved0, intptr_t*) \ - nonstatic_field(JavaThread, _jvmci_reserved1, intptr_t*) \ + nonstatic_field(JavaThread, _jvmci_reserved0, jlong) \ + nonstatic_field(JavaThread, _jvmci_reserved1, jlong) \ nonstatic_field(JavaThread, _jvmci_reserved_oop0, oop) \ nonstatic_field(JavaThread, _should_post_on_exceptions_flag, int) \ nonstatic_field(JavaThread, _jni_environment, JNIEnv) \ diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/oops/access.hpp openjdk-17-17.0.5+8/src/hotspot/share/oops/access.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/oops/access.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/oops/access.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -295,8 +295,8 @@ static inline void arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, arrayOop dst_obj, size_t dst_offset_in_bytes, size_t length) { - AccessT::arraycopy(src_obj, src_offset_in_bytes, reinterpret_cast(NULL), - dst_obj, dst_offset_in_bytes, reinterpret_cast(NULL), + AccessT::arraycopy(src_obj, src_offset_in_bytes, static_cast(nullptr), + dst_obj, dst_offset_in_bytes, static_cast(nullptr), length); } @@ -304,7 +304,7 @@ static inline void arraycopy_to_native(arrayOop src_obj, size_t src_offset_in_bytes, T* dst, size_t length) { - AccessT::arraycopy(src_obj, src_offset_in_bytes, reinterpret_cast(NULL), + AccessT::arraycopy(src_obj, src_offset_in_bytes, static_cast(nullptr), NULL, 0, dst, length); } @@ -314,15 +314,15 @@ arrayOop dst_obj, size_t dst_offset_in_bytes, size_t length) { AccessT::arraycopy(NULL, 0, src, - dst_obj, dst_offset_in_bytes, reinterpret_cast(NULL), + dst_obj, dst_offset_in_bytes, static_cast(nullptr), length); } static inline bool oop_arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, arrayOop dst_obj, size_t dst_offset_in_bytes, size_t length) { - return AccessT::oop_arraycopy(src_obj, src_offset_in_bytes, reinterpret_cast(NULL), - dst_obj, dst_offset_in_bytes, reinterpret_cast(NULL), + return AccessT::oop_arraycopy(src_obj, src_offset_in_bytes, static_cast(nullptr), + dst_obj, dst_offset_in_bytes, static_cast(nullptr), length); } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/oops/methodData.cpp openjdk-17-17.0.5+8/src/hotspot/share/oops/methodData.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/oops/methodData.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/oops/methodData.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1242,7 +1242,9 @@ int extra_size = extra_data_count * DataLayout::compute_size_in_bytes(0); // Let's zero the space for the extra data - Copy::zero_to_bytes(((address)_data) + data_size, extra_size); + if (extra_size > 0) { + Copy::zero_to_bytes(((address)_data) + data_size, extra_size); + } // Add a cell to record information about modified arguments. // Set up _args_modified array after traps cells so that diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/callGenerator.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/callGenerator.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/callGenerator.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/callGenerator.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1115,22 +1115,29 @@ Node* receiver = kit.argument(0); if (receiver->Opcode() == Op_ConP) { input_not_const = false; - const TypeOopPtr* oop_ptr = receiver->bottom_type()->is_oopptr(); - ciMethod* target = oop_ptr->const_oop()->as_method_handle()->get_vmtarget(); - const int vtable_index = Method::invalid_vtable_index; + const TypeOopPtr* recv_toop = receiver->bottom_type()->isa_oopptr(); + if (recv_toop != NULL) { + ciMethod* target = recv_toop->const_oop()->as_method_handle()->get_vmtarget(); + const int vtable_index = Method::invalid_vtable_index; - if (!ciMethod::is_consistent_info(callee, target)) { + if (!ciMethod::is_consistent_info(callee, target)) { + print_inlining_failure(C, callee, jvms->depth() - 1, jvms->bci(), + "signatures mismatch"); + return NULL; + } + + CallGenerator *cg = C->call_generator(target, vtable_index, + false /* call_does_dispatch */, + jvms, + allow_inline, + PROB_ALWAYS); + return cg; + } else { + assert(receiver->bottom_type() == TypePtr::NULL_PTR, "not a null: %s", + Type::str(receiver->bottom_type())); print_inlining_failure(C, callee, jvms->depth() - 1, jvms->bci(), - "signatures mismatch"); - return NULL; + "receiver is always null"); } - - CallGenerator* cg = C->call_generator(target, vtable_index, - false /* call_does_dispatch */, - jvms, - allow_inline, - PROB_ALWAYS); - return cg; } else { print_inlining_failure(C, callee, jvms->depth() - 1, jvms->bci(), "receiver not constant"); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/callnode.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/callnode.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/callnode.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/callnode.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1654,7 +1654,6 @@ init_req( KlassNode , klass_node); init_req( InitialTest , initial_test); init_req( ALength , topnode); - init_req( ValidLengthTest , topnode); C->add_macro_node(this); } @@ -1687,6 +1686,54 @@ return mark_node; } +//============================================================================= +Node* AllocateArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { + if (remove_dead_region(phase, can_reshape)) return this; + // Don't bother trying to transform a dead node + if (in(0) && in(0)->is_top()) return NULL; + + const Type* type = phase->type(Ideal_length()); + if (type->isa_int() && type->is_int()->_hi < 0) { + if (can_reshape) { + PhaseIterGVN *igvn = phase->is_IterGVN(); + // Unreachable fall through path (negative array length), + // the allocation can only throw so disconnect it. + Node* proj = proj_out_or_null(TypeFunc::Control); + Node* catchproj = NULL; + if (proj != NULL) { + for (DUIterator_Fast imax, i = proj->fast_outs(imax); i < imax; i++) { + Node *cn = proj->fast_out(i); + if (cn->is_Catch()) { + catchproj = cn->as_Multi()->proj_out_or_null(CatchProjNode::fall_through_index); + break; + } + } + } + if (catchproj != NULL && catchproj->outcnt() > 0 && + (catchproj->outcnt() > 1 || + catchproj->unique_out()->Opcode() != Op_Halt)) { + assert(catchproj->is_CatchProj(), "must be a CatchProjNode"); + Node* nproj = catchproj->clone(); + igvn->register_new_node_with_optimizer(nproj); + + Node *frame = new ParmNode( phase->C->start(), TypeFunc::FramePtr ); + frame = phase->transform(frame); + // Halt & Catch Fire + Node* halt = new HaltNode(nproj, frame, "unexpected negative array length"); + phase->C->root()->add_req(halt); + phase->transform(halt); + + igvn->replace_node(catchproj, phase->C->top()); + return this; + } + } else { + // Can't correct it during regular GVN so register for IGVN + phase->C->record_for_igvn(this); + } + } + return NULL; +} + // Retrieve the length from the AllocateArrayNode. Narrow the type with a // CastII, if appropriate. If we are not allowed to create new nodes, and // a CastII is appropriate, return NULL. @@ -1711,13 +1758,16 @@ "narrow type must be narrower than length type"); // Return NULL if new nodes are not allowed - if (!allow_new_nodes) return NULL; + if (!allow_new_nodes) { + return NULL; + } // Create a cast which is control dependent on the initialization to // propagate the fact that the array length must be positive. InitializeNode* init = initialization(); - assert(init != NULL, "initialization not found"); - length = new CastIINode(length, narrow_length_type); - length->set_req(TypeFunc::Control, init->proj_out_or_null(TypeFunc::Control)); + if (init != NULL) { + length = new CastIINode(length, narrow_length_type); + length->set_req(TypeFunc::Control, init->proj_out_or_null(TypeFunc::Control)); + } } } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/callnode.hpp openjdk-17-17.0.5+8/src/hotspot/share/opto/callnode.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/callnode.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/callnode.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -913,7 +913,6 @@ KlassNode, // type (maybe dynamic) of the obj. InitialTest, // slow-path test (may be constant) ALength, // array length (or TOP if none) - ValidLengthTest, ParmLimit }; @@ -923,7 +922,6 @@ fields[KlassNode] = TypeInstPtr::NOTNULL; fields[InitialTest] = TypeInt::BOOL; fields[ALength] = t; // length (can be a bad length) - fields[ValidLengthTest] = TypeInt::BOOL; const TypeTuple *domain = TypeTuple::make(ParmLimit, fields); @@ -1018,16 +1016,18 @@ // class AllocateArrayNode : public AllocateNode { public: - AllocateArrayNode(Compile* C, const TypeFunc* atype, Node* ctrl, Node* mem, Node* abio, Node* size, Node* klass_node, - Node* initial_test, Node* count_val, Node* valid_length_test) + AllocateArrayNode(Compile* C, const TypeFunc *atype, Node *ctrl, Node *mem, Node *abio, + Node* size, Node* klass_node, Node* initial_test, + Node* count_val + ) : AllocateNode(C, atype, ctrl, mem, abio, size, klass_node, initial_test) { init_class_id(Class_AllocateArray); set_req(AllocateNode::ALength, count_val); - set_req(AllocateNode::ValidLengthTest, valid_length_test); } virtual int Opcode() const; + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); // Dig the length operand out of a array allocation site. Node* Ideal_length() { diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/cfgnode.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/cfgnode.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/cfgnode.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/cfgnode.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -314,7 +314,7 @@ } //------------------------------is_unreachable_region-------------------------- -// Find if the Region node is reachable from the root. +// Check if the RegionNode is part of an unsafe loop and unreachable from root. bool RegionNode::is_unreachable_region(const PhaseGVN* phase) { Node* top = phase->C->top(); assert(req() == 2 || (req() == 3 && in(1) != NULL && in(2) == top), "sanity check arguments"); @@ -373,7 +373,7 @@ VectorSet visited; // Mark all control nodes reachable from root outputs - Node *n = (Node*)phase->C->root(); + Node* n = (Node*)phase->C->root(); nstack.push(n); visited.set(n->_idx); while (nstack.size() != 0) { @@ -475,7 +475,7 @@ // Remove TOP or NULL input paths. If only 1 input path remains, this Region // degrades to a copy. - bool add_to_worklist = false; + bool add_to_worklist = true; bool modified = false; int cnt = 0; // Count of values merging DEBUG_ONLY( int cnt_orig = req(); ) // Save original inputs count @@ -501,7 +501,7 @@ } } if( phase->type(n) == Type::TOP ) { - set_req(i, NULL); // Ignore TOP inputs + set_req_X(i, NULL, phase); // Ignore TOP inputs modified = true; i--; continue; @@ -532,7 +532,8 @@ } } } - add_to_worklist = true; + add_to_worklist = false; + phase->is_IterGVN()->add_users_to_worklist(this); i--; } } @@ -547,45 +548,51 @@ if ((this->is_Loop() && (del_it == LoopNode::EntryControl || (del_it == 0 && is_unreachable_region(phase)))) || (!this->is_Loop() && has_phis && is_unreachable_region(phase))) { - // Yes, the region will be removed during the next step below. - // Cut the backedge input and remove phis since no data paths left. - // We don't cut outputs to other nodes here since we need to put them - // on the worklist. - PhaseIterGVN *igvn = phase->is_IterGVN(); - if (in(1)->outcnt() == 1) { - igvn->_worklist.push(in(1)); - } - del_req(1); - cnt = 0; - assert( req() == 1, "no more inputs expected" ); - uint max = outcnt(); - bool progress = true; - Node *top = phase->C->top(); - DUIterator j; - while(progress) { - progress = false; - for (j = outs(); has_out(j); j++) { - Node *n = out(j); - if( n->is_Phi() ) { - assert(n->in(0) == this, ""); - assert( n->req() == 2 && n->in(1) != NULL, "Only one data input expected" ); - // Break dead loop data path. - // Eagerly replace phis with top to avoid regionless phis. - igvn->replace_node(n, top); - if( max != outcnt() ) { - progress = true; - j = refresh_out_pos(j); - max = outcnt(); + // This region and therefore all nodes on the input control path(s) are unreachable + // from root. To avoid incomplete removal of unreachable subgraphs, walk up the CFG + // and aggressively replace all nodes by top. + PhaseIterGVN* igvn = phase->is_IterGVN(); + Node* top = phase->C->top(); + ResourceMark rm; + Node_List nstack; + VectorSet visited; + nstack.push(this); + visited.set(_idx); + while (nstack.size() != 0) { + Node* n = nstack.pop(); + for (uint i = 0; i < n->req(); ++i) { + Node* m = n->in(i); + assert(m != (Node*)phase->C->root(), "Should be unreachable from root"); + if (m != NULL && m->is_CFG() && !visited.test_set(m->_idx)) { + nstack.push(m); + } + } + if (n->is_Region()) { + // Eagerly replace phis with top to avoid regionless phis. + n->set_req(0, NULL); + bool progress = true; + uint max = n->outcnt(); + DUIterator j; + while (progress) { + progress = false; + for (j = n->outs(); n->has_out(j); j++) { + Node* u = n->out(j); + if (u->is_Phi()) { + igvn->replace_node(u, top); + if (max != n->outcnt()) { + progress = true; + j = n->refresh_out_pos(j); + max = n->outcnt(); + } + } } } } + igvn->replace_node(n, top); } - add_to_worklist = true; + return NULL; } } - if (add_to_worklist) { - phase->is_IterGVN()->add_users_to_worklist(this); // Revisit collapsed Phis - } if( cnt <= 1 ) { // Only 1 path in? set_req(0, NULL); // Null control input for region copy @@ -629,8 +636,9 @@ assert(parent_ctrl != NULL, "Region is a copy of some non-null control"); assert(parent_ctrl != this, "Close dead loop"); } - if (!add_to_worklist) + if (add_to_worklist) { igvn->add_users_to_worklist(this); // Check for further allowed opts + } for (DUIterator_Last imin, i = last_outs(imin); i >= imin; --i) { Node* n = last_out(i); igvn->hash_delete(n); // Remove from worklist before modifying edges @@ -2131,7 +2139,7 @@ doit = false; break; } - if (in(i)->in(AddPNode::Offset) != base) { + if (in(i)->in(AddPNode::Base) != base) { base = NULL; } if (in(i)->in(AddPNode::Offset) != offset) { @@ -2631,17 +2639,6 @@ // Rethrows always throw exceptions, never return if (call->entry_point() == OptoRuntime::rethrow_stub()) { f[CatchProjNode::fall_through_index] = Type::TOP; - } else if (call->is_AllocateArray()) { - Node* klass_node = call->in(AllocateNode::KlassNode); - Node* length = call->in(AllocateNode::ALength); - const Type* length_type = phase->type(length); - const Type* klass_type = phase->type(klass_node); - Node* valid_length_test = call->in(AllocateNode::ValidLengthTest); - const Type* valid_length_test_t = phase->type(valid_length_test); - if (length_type == Type::TOP || klass_type == Type::TOP || valid_length_test_t == Type::TOP || - valid_length_test_t->is_int()->is_con(0)) { - f[CatchProjNode::fall_through_index] = Type::TOP; - } } else if( call->req() > TypeFunc::Parms ) { const Type *arg0 = phase->type( call->in(TypeFunc::Parms) ); // Check for null receiver to virtual or interface calls diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/chaitin.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/chaitin.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/chaitin.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/chaitin.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1700,6 +1700,19 @@ if( cisc->oper_input_base() > 1 && mach->oper_input_base() <= 1 ) { assert( cisc->oper_input_base() == 2, "Only adding one edge"); cisc->ins_req(1,src); // Requires a memory edge + } else { + // There is no space reserved for a memory edge before the inputs for + // instructions which have "stackSlotX" parameter instead of "memory". + // For example, "MoveF2I_stack_reg". We always need a memory edge from + // src to cisc, else we might schedule cisc before src, loading from a + // spill location before storing the spill. On some platforms, we land + // in this else case because mach->oper_input_base() > 1, i.e. we have + // multiple inputs. In some rare cases there are even multiple memory + // operands, before and after spilling. + // (e.g. spilling "addFPR24_reg_mem" to "addFPR24_mem_cisc") + // In either case, there is no space in the inputs for the memory edge + // so we add an additional precedence / memory edge. + cisc->add_prec(src); } block->map_node(cisc, j); // Insert into basic block n->subsume_by(cisc, C); // Correct graph diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/compile.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/compile.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/compile.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/compile.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -2015,10 +2015,8 @@ bool Compile::optimize_loops(PhaseIterGVN& igvn, LoopOptsMode mode) { if (_loop_opts_cnt > 0) { - debug_only( int cnt = 0; ); while (major_progress() && (_loop_opts_cnt > 0)) { TracePhase tp("idealLoop", &timers[_t_idealLoop]); - assert( cnt++ < 40, "infinite cycle in loop optimization" ); PhaseIdealLoop::optimize(igvn, mode); _loop_opts_cnt--; if (failing()) return false; @@ -3519,7 +3517,7 @@ n->set_req(MemBarNode::Precedent, top()); while (wq.size() > 0) { Node* m = wq.pop(); - if (m->outcnt() == 0) { + if (m->outcnt() == 0 && m != top()) { for (uint j = 0; j < m->req(); j++) { Node* in = m->in(j); if (in != NULL) { @@ -3740,7 +3738,7 @@ // 'fall-thru' path, so expected kids is 1 less. if (n->is_PCTable() && n->in(0) && n->in(0)->in(0)) { if (n->in(0)->in(0)->is_Call()) { - CallNode* call = n->in(0)->in(0)->as_Call(); + CallNode *call = n->in(0)->in(0)->as_Call(); if (call->entry_point() == OptoRuntime::rethrow_stub()) { required_outcnt--; // Rethrow always has 1 less kid } else if (call->req() > TypeFunc::Parms && @@ -3749,25 +3747,22 @@ // detected that the virtual call will always result in a null // pointer exception. The fall-through projection of this CatchNode // will not be populated. - Node* arg0 = call->in(TypeFunc::Parms); + Node *arg0 = call->in(TypeFunc::Parms); if (arg0->is_Type() && arg0->as_Type()->type()->higher_equal(TypePtr::NULL_PTR)) { required_outcnt--; } - } else if (call->entry_point() == OptoRuntime::new_array_Java() || - call->entry_point() == OptoRuntime::new_array_nozero_Java()) { - // Check for illegal array length. In such case, the optimizer has + } else if (call->entry_point() == OptoRuntime::new_array_Java() && + call->req() > TypeFunc::Parms+1 && + call->is_CallStaticJava()) { + // Check for negative array length. In such case, the optimizer has // detected that the allocation attempt will always result in an // exception. There is no fall-through projection of this CatchNode . - assert(call->is_CallStaticJava(), "static call expected"); - assert(call->req() == call->jvms()->endoff() + 1, "missing extra input"); - Node* valid_length_test = call->in(call->req()-1); - call->del_req(call->req()-1); - if (valid_length_test->find_int_con(1) == 0) { + Node *arg1 = call->in(TypeFunc::Parms+1); + if (arg1->is_Type() && + arg1->as_Type()->type()->join(TypeInt::POS)->empty()) { required_outcnt--; } - assert(n->outcnt() == required_outcnt, "malformed control flow"); - continue; } } } @@ -3776,14 +3771,6 @@ record_method_not_compilable("malformed control flow"); return true; // Not all targets reachable! } - } else if (n->is_PCTable() && n->in(0) && n->in(0)->in(0) && n->in(0)->in(0)->is_Call()) { - CallNode* call = n->in(0)->in(0)->as_Call(); - if (call->entry_point() == OptoRuntime::new_array_Java() || - call->entry_point() == OptoRuntime::new_array_nozero_Java()) { - assert(call->is_CallStaticJava(), "static call expected"); - assert(call->req() == call->jvms()->endoff() + 1, "missing extra input"); - call->del_req(call->req()-1); // valid length test useless now - } } // Check that I actually visited all kids. Unreached kids // must be infinite loops. diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/graphKit.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/graphKit.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/graphKit.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/graphKit.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1537,14 +1537,7 @@ const TypePtr* adr_type = NULL; // debug-mode-only argument debug_only(adr_type = C->get_adr_type(adr_idx)); Node* mem = memory(adr_idx); - Node* ld; - if (require_atomic_access && bt == T_LONG) { - ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency, unaligned, mismatched, unsafe, barrier_data); - } else if (require_atomic_access && bt == T_DOUBLE) { - ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency, unaligned, mismatched, unsafe, barrier_data); - } else { - ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency, unaligned, mismatched, unsafe, barrier_data); - } + Node* ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency, require_atomic_access, unaligned, mismatched, unsafe, barrier_data); ld = _gvn.transform(ld); if (((bt == T_OBJECT) && C->do_escape_analysis()) || C->eliminate_boxing()) { // Improve graph before escape analysis and boxing elimination. @@ -1564,14 +1557,7 @@ const TypePtr* adr_type = NULL; debug_only(adr_type = C->get_adr_type(adr_idx)); Node *mem = memory(adr_idx); - Node* st; - if (require_atomic_access && bt == T_LONG) { - st = StoreLNode::make_atomic(ctl, mem, adr, adr_type, val, mo); - } else if (require_atomic_access && bt == T_DOUBLE) { - st = StoreDNode::make_atomic(ctl, mem, adr, adr_type, val, mo); - } else { - st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo); - } + Node* st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo, require_atomic_access); if (unaligned) { st->as_Store()->set_unaligned_access(); } @@ -2744,9 +2730,7 @@ // Make a catch node with just two handlers: fall-through and catch-all Node* i_o = _gvn.transform( new ProjNode(call, TypeFunc::I_O, separate_io_proj) ); Node* catc = _gvn.transform( new CatchNode(control(), i_o, 2) ); - Node* norm = new CatchProjNode(catc, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci); - _gvn.set_type_bottom(norm); - C->record_for_igvn(norm); + Node* norm = _gvn.transform( new CatchProjNode(catc, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci) ); Node* excp = _gvn.transform( new CatchProjNode(catc, CatchProjNode::catch_all_index, CatchProjNode::no_handler_bci) ); { PreserveJVMState pjvms(this); @@ -3985,28 +3969,20 @@ initial_slow_test = initial_slow_test->as_Bool()->as_int_value(&_gvn); } - const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type(); - Node* valid_length_test = _gvn.intcon(1); - if (ary_type->klass()->is_array_klass()) { - BasicType bt = ary_type->klass()->as_array_klass()->element_type()->basic_type(); - jint max = TypeAryPtr::max_array_length(bt); - Node* valid_length_cmp = _gvn.transform(new CmpUNode(length, intcon(max))); - valid_length_test = _gvn.transform(new BoolNode(valid_length_cmp, BoolTest::le)); - } - // Create the AllocateArrayNode and its result projections AllocateArrayNode* alloc = new AllocateArrayNode(C, AllocateArrayNode::alloc_type(TypeInt::INT), control(), mem, i_o(), size, klass_node, initial_slow_test, - length, valid_length_test); + length); // Cast to correct type. Note that the klass_node may be constant or not, // and in the latter case the actual array type will be inexact also. // (This happens via a non-constant argument to inline_native_newArray.) // In any case, the value of klass_node provides the desired array type. const TypeInt* length_type = _gvn.find_int_type(length); + const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type(); if (ary_type->isa_aryptr() && length_type != NULL) { // Try to get a better type than POS for the size ary_type = ary_type->is_aryptr()->cast_to_size(length_type); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/idealKit.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/idealKit.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/idealKit.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/idealKit.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -358,12 +358,7 @@ const TypePtr* adr_type = NULL; // debug-mode-only argument debug_only(adr_type = C->get_adr_type(adr_idx)); Node* mem = memory(adr_idx); - Node* ld; - if (require_atomic_access && bt == T_LONG) { - ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo); - } else { - ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo); - } + Node* ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, LoadNode::DependsOnlyOnTest, require_atomic_access); return transform(ld); } @@ -375,12 +370,7 @@ const TypePtr* adr_type = NULL; debug_only(adr_type = C->get_adr_type(adr_idx)); Node *mem = memory(adr_idx); - Node* st; - if (require_atomic_access && bt == T_LONG) { - st = StoreLNode::make_atomic(ctl, mem, adr, adr_type, val, mo); - } else { - st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo); - } + Node* st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo, require_atomic_access); if (mismatched) { st->as_Store()->set_mismatched_access(); } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/ifg.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/ifg.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/ifg.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/ifg.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -37,6 +37,8 @@ #include "opto/memnode.hpp" #include "opto/opcodes.hpp" +#include + PhaseIFG::PhaseIFG( Arena *arena ) : Phase(Interference_Graph), _arena(arena) { } @@ -784,7 +786,7 @@ assert(int_pressure.current_pressure() == count_int_pressure(liveout), "the int pressure is incorrect"); assert(float_pressure.current_pressure() == count_float_pressure(liveout), "the float pressure is incorrect"); } - assert(lrg._area >= 0.0, "negative spill area" ); + assert(lrg._area >= 0.0, "unexpected spill area value %g (rounding mode %x)", lrg._area, fegetround()); } } @@ -895,7 +897,7 @@ if (g_isfinite(cost)) { lrg._area -= cost; } - assert(lrg._area >= 0.0, "negative spill area" ); + assert(lrg._area >= 0.0, "unexpected spill area value %g (rounding mode %x)", lrg._area, fegetround()); assign_high_score_to_immediate_copies(block, n, lrg, location + 1, last_inst); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/lcm.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/lcm.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/lcm.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/lcm.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -488,9 +488,12 @@ //------------------------------select----------------------------------------- -// Select a nice fellow from the worklist to schedule next. If there is only -// one choice, then use it. Projections take top priority for correctness -// reasons - if I see a projection, then it is next. There are a number of +// Select a nice fellow from the worklist to schedule next. If there is only one +// choice, then use it. CreateEx nodes that are initially ready must start their +// blocks and are given the highest priority, by being placed at the beginning +// of the worklist. Next after initially-ready CreateEx nodes are projections, +// which must follow their parents, and CreateEx nodes with local input +// dependencies. Next are constants and CheckCastPP nodes. There are a number of // other special cases, for instructions that consume condition codes, et al. // These are chosen immediately. Some instructions are required to immediately // precede the last instruction in the block, and these are taken last. Of the @@ -528,15 +531,28 @@ Node *n = worklist[i]; // Get Node on worklist int iop = n->is_Mach() ? n->as_Mach()->ideal_Opcode() : 0; - if( n->is_Proj() || // Projections always win - n->Opcode()== Op_Con || // So does constant 'Top' - iop == Op_CreateEx || // Create-exception must start block - iop == Op_CheckCastPP - ) { + if (iop == Op_CreateEx || n->is_Proj()) { + // CreateEx nodes that are initially ready must start the block (after Phi + // and Parm nodes which are pre-scheduled) and get top priority. This is + // currently enforced by placing them at the beginning of the initial + // worklist and selecting them eagerly here. After these, projections and + // other CreateEx nodes are selected with equal priority. worklist.map(i,worklist.pop()); return n; } + if (n->Opcode() == Op_Con || iop == Op_CheckCastPP) { + // Constants and CheckCastPP nodes have higher priority than the rest of + // the nodes tested below. Record as current winner, but keep looking for + // higher-priority nodes in the worklist. + choice = 4; + // Latency and score are only used to break ties among low-priority nodes. + latency = 0; + score = 0; + idx = i; + continue; + } + // Final call in a block must be adjacent to 'catch' Node *e = block->end(); if( e->is_Catch() && e->in(0)->in(0) == n ) @@ -555,7 +571,7 @@ } } - uint n_choice = 2; + uint n_choice = 2; // See if this instruction is consumed by a branch. If so, then (as the // branch is the last instruction in the basic block) force it to the @@ -1060,8 +1076,8 @@ // ties in scheduling by worklist order. delay.push(m); } else if (m->is_Mach() && m->as_Mach()->ideal_Opcode() == Op_CreateEx) { - // Force the CreateEx to the top of the list so it's processed - // first and ends up at the start of the block. + // Place CreateEx nodes that are initially ready at the beginning of the + // worklist so they are selected first and scheduled at the block start. worklist.insert(0, m); } else { worklist.push(m); // Then on to worklist! diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/loopnode.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/loopnode.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/loopnode.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/loopnode.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -3409,6 +3409,17 @@ return 0; } +#ifdef ASSERT +bool IdealLoopTree::has_reduction_nodes() const { + for (uint i = 0; i < _body.size(); i++) { + if (_body[i]->is_reduction()) { + return true; + } + } + return false; +} +#endif // ASSERT + #ifndef PRODUCT //------------------------------dump_head-------------------------------------- // Dump 1 liner for loop header info diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/loopnode.hpp openjdk-17-17.0.5+8/src/hotspot/share/opto/loopnode.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/loopnode.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/loopnode.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -777,6 +777,11 @@ void remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase); +#ifdef ASSERT + // Tell whether the body contains nodes marked as reductions. + bool has_reduction_nodes() const; +#endif // ASSERT + #ifndef PRODUCT void dump_head() const; // Dump loop head only void dump() const; // Dump this loop recursively diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/loopopts.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/loopopts.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/loopopts.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/loopopts.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -334,9 +334,11 @@ // We allow the special case of AddP's with no local inputs. // This allows us to split-up address expressions. if (m->is_AddP() && - get_ctrl(m->in(2)) != n_ctrl && - get_ctrl(m->in(3)) != n_ctrl) { - // Move the AddP up to dominating point + get_ctrl(m->in(AddPNode::Base)) != n_ctrl && + get_ctrl(m->in(AddPNode::Address)) != n_ctrl && + get_ctrl(m->in(AddPNode::Offset)) != n_ctrl) { + // Move the AddP up to the dominating point. That's fine because control of m's inputs + // must dominate get_ctrl(m) == n_ctrl and we just checked that the input controls are != n_ctrl. Node* c = find_non_split_ctrl(idom(n_ctrl)); if (c->is_OuterStripMinedLoop()) { c->as_Loop()->verify_strip_mined(1); @@ -1603,6 +1605,8 @@ } } +// Compute the early control of a node by following its inputs until we reach +// nodes that are pinned. Then compute the LCA of the control of all pinned nodes. Node* PhaseIdealLoop::compute_early_ctrl(Node* n, Node* n_ctrl) { Node* early_ctrl = NULL; ResourceMark rm; @@ -1618,17 +1622,14 @@ } else { for (uint j = 0; j < m->req(); j++) { Node* in = m->in(j); - if (in == NULL) { - continue; + if (in != NULL) { + wq.push(in); } - wq.push(in); } } if (c != NULL) { - assert(is_dominator(c, n_ctrl), ""); - if (early_ctrl == NULL) { - early_ctrl = c; - } else if (is_dominator(early_ctrl, c)) { + assert(is_dominator(c, n_ctrl), "control input must dominate current control"); + if (early_ctrl == NULL || is_dominator(early_ctrl, c)) { early_ctrl = c; } } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/loopPredicate.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/loopPredicate.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/loopPredicate.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/loopPredicate.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -26,6 +26,7 @@ #include "opto/loopnode.hpp" #include "opto/addnode.hpp" #include "opto/callnode.hpp" +#include "opto/castnode.hpp" #include "opto/connode.hpp" #include "opto/convertnode.hpp" #include "opto/loopnode.hpp" @@ -1392,6 +1393,10 @@ register_new_node(max_value, new_proj); max_value = new AddINode(opaque_init, max_value); register_new_node(max_value, new_proj); + // init + (current stride - initial stride) is within the loop so narrow its type by leveraging the type of the iv Phi + max_value = new CastIINode(max_value, loop->_head->as_CountedLoop()->phi()->bottom_type()); + register_new_node(max_value, predicate_proj); + bol = rc_predicate(loop, new_proj, scale, offset, max_value, limit, stride, rng, (stride > 0) != (scale > 0), overflow, negate); opaque_bol = new Opaque4Node(C, bol, _igvn.intcon(1)); C->add_skeleton_predicate_opaq(opaque_bol); @@ -1399,6 +1404,7 @@ new_proj = create_new_if_for_predicate(predicate_proj, NULL, reason, overflow ? Op_If : iff->Opcode()); _igvn.replace_input_of(new_proj->in(0), 1, opaque_bol); assert(max_value->outcnt() > 0, "should be used"); + assert(skeleton_predicate_has_opaque(new_proj->in(0)->as_If()), "unexpected"); return new_proj; } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/loopTransform.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/loopTransform.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/loopTransform.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/loopTransform.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1311,19 +1311,23 @@ op == Op_OrL || op == Op_RShiftL || op == Op_LShiftL || + op == Op_LShiftI || op == Op_AddL || op == Op_AddI || op == Op_MulL || op == Op_MulI || op == Op_SubL || op == Op_SubI || - op == Op_ConvI2L); + op == Op_ConvI2L || + op == Op_CastII); } bool PhaseIdealLoop::skeleton_predicate_has_opaque(IfNode* iff) { ResourceMark rm; Unique_Node_List wq; wq.push(iff->in(1)->in(1)); + uint init = 0; + uint stride = 0; for (uint i = 0; i < wq.size(); i++) { Node* n = wq.at(i); int op = n->Opcode(); @@ -1336,11 +1340,39 @@ } continue; } - if (n->is_Opaque1()) { - return true; + if (n->Opcode() == Op_OpaqueLoopInit) { + init++; + } else if (n->Opcode() == Op_OpaqueLoopStride) { + stride++; } } - return false; +#ifdef ASSERT + wq.clear(); + wq.push(iff->in(1)->in(1)); + uint verif_init = 0; + uint verif_stride = 0; + for (uint i = 0; i < wq.size(); i++) { + Node* n = wq.at(i); + int op = n->Opcode(); + if (!n->is_CFG()) { + if (n->Opcode() == Op_OpaqueLoopInit) { + verif_init++; + } else if (n->Opcode() == Op_OpaqueLoopStride) { + verif_stride++; + } else { + for (uint j = 1; j < n->req(); j++) { + Node* m = n->in(j); + if (m != NULL) { + wq.push(m); + } + } + } + } + } + assert(init == verif_init && stride == verif_stride, "missed opaque node"); +#endif + assert(stride == 0 || init != 0, "init should be there every time stride is"); + return init != 0; } // Clone the skeleton predicate bool for a main or unswitched loop: @@ -1557,6 +1589,15 @@ set_idom(new_pre_exit, pre_end, dd_main_head); set_loop(new_pre_exit, outer_loop->_parent); + if (peel_only) { + // Nodes in the peeled iteration that were marked as reductions within the + // original loop might not be reductions within their new outer loop. + for (uint i = 0; i < loop->_body.size(); i++) { + Node* n = old_new[loop->_body[i]->_idx]; + n->remove_flag(Node::Flag_is_reduction); + } + } + // Step B2: Build a zero-trip guard for the main-loop. After leaving the // pre-loop, the main-loop may not execute at all. Later in life this // zero-trip guard will become the minimum-trip guard when we unroll @@ -2156,6 +2197,20 @@ new_limit = new CMoveINode(adj_bool, adj_limit, adj_max, TypeInt::INT); } register_new_node(new_limit, ctrl); + if (loop_head->unrolled_count() == 1) { + // The Opaque2 node created above (in the case of the first unrolling) hides the type of the loop limit. + // As a result, if the iv Phi constant folds (because it captured the iteration range), the exit test won't + // constant fold and the graph contains a broken counted loop. + const Type* new_limit_t; + if (stride_con > 0) { + new_limit_t = TypeInt::make(min_jint, limit_type->_hi, limit_type->_widen); + } else { + assert(stride_con < 0, "stride can't be 0"); + new_limit_t = TypeInt::make(limit_type->_lo, max_jint, limit_type->_widen); + } + new_limit = new CastIINode(new_limit, new_limit_t); + register_new_node(new_limit, ctrl); + } } assert(new_limit != NULL, ""); @@ -2816,6 +2871,9 @@ register_new_node(max_value, predicate_proj); max_value = new AddINode(opaque_init, max_value); register_new_node(max_value, predicate_proj); + // init + (current stride - initial stride) is within the loop so narrow its type by leveraging the type of the iv Phi + max_value = new CastIINode(max_value, loop->_head->as_CountedLoop()->phi()->bottom_type()); + register_new_node(max_value, predicate_proj); predicate_proj = add_range_check_predicate(loop, cl, predicate_proj, scale_con, int_offset, int_limit, stride_con, max_value); assert(skeleton_predicate_has_opaque(predicate_proj->in(0)->as_If()), "unexpected"); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/macroArrayCopy.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/macroArrayCopy.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/macroArrayCopy.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/macroArrayCopy.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1017,7 +1017,7 @@ Node* sval = transform_later( LoadNode::make(_igvn, *ctrl, (*mem)->memory_at(s_alias_idx), sptr, s_adr_type, TypeInt::INT, T_INT, MemNode::unordered, LoadNode::DependsOnlyOnTest, - false /*unaligned*/, is_mismatched)); + false /*require_atomic_access*/, false /*unaligned*/, is_mismatched)); Node* st = transform_later( StoreNode::make(_igvn, *ctrl, (*mem)->memory_at(d_alias_idx), dptr, adr_type, sval, T_INT, MemNode::unordered)); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/macro.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/macro.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/macro.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/macro.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1208,8 +1208,7 @@ AllocateNode* alloc, // allocation node to be expanded Node* length, // array length for an array allocation const TypeFunc* slow_call_type, // Type of slow call - address slow_call_address, // Address of slow call - Node* valid_length_test // whether length is valid or not + address slow_call_address // Address of slow call ) { Node* ctrl = alloc->in(TypeFunc::Control); @@ -1395,12 +1394,6 @@ // Copy debug information and adjust JVMState information, then replace // allocate node with the call call->copy_call_debug_info(&_igvn, alloc); - // For array allocations, copy the valid length check to the call node so Compile::final_graph_reshaping() can verify - // that the call has the expected number of CatchProj nodes (in case the allocation always fails and the fallthrough - // path dies). - if (valid_length_test != NULL) { - call->add_req(valid_length_test); - } if (expand_fast_path) { call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON. } else { @@ -1882,12 +1875,11 @@ void PhaseMacroExpand::expand_allocate(AllocateNode *alloc) { expand_allocate_common(alloc, NULL, OptoRuntime::new_instance_Type(), - OptoRuntime::new_instance_Java(), NULL); + OptoRuntime::new_instance_Java()); } void PhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) { Node* length = alloc->in(AllocateNode::ALength); - Node* valid_length_test = alloc->in(AllocateNode::ValidLengthTest); InitializeNode* init = alloc->initialization(); Node* klass_node = alloc->in(AllocateNode::KlassNode); ciKlass* k = _igvn.type(klass_node)->is_klassptr()->klass(); @@ -1902,7 +1894,7 @@ } expand_allocate_common(alloc, length, OptoRuntime::new_array_Type(), - slow_call_address, valid_length_test); + slow_call_address); } //-------------------mark_eliminated_box---------------------------------- diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/macro.hpp openjdk-17-17.0.5+8/src/hotspot/share/opto/macro.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/macro.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/macro.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -92,8 +92,8 @@ void expand_allocate_common(AllocateNode* alloc, Node* length, const TypeFunc* slow_call_type, - address slow_call_address, - Node* valid_length_test); + address slow_call_address); + void yank_initalize_node(InitializeNode* node); void yank_alloc_node(AllocateNode* alloc); Node *value_from_mem(Node *mem, Node *ctl, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, AllocateNode *alloc); Node *value_from_mem_phi(Node *mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, AllocateNode *alloc, Node_Stack *value_phis, int level); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/memnode.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/memnode.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/memnode.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/memnode.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -861,8 +861,8 @@ //----------------------------LoadNode::make----------------------------------- // Polymorphic factory method: -Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo, - ControlDependency control_dependency, bool unaligned, bool mismatched, bool unsafe, uint8_t barrier_data) { +Node* LoadNode::make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, BasicType bt, MemOrd mo, + ControlDependency control_dependency, bool require_atomic_access, bool unaligned, bool mismatched, bool unsafe, uint8_t barrier_data) { Compile* C = gvn.C; // sanity check the alias category against the created node type @@ -884,9 +884,9 @@ case T_INT: load = new LoadINode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency); break; case T_CHAR: load = new LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency); break; case T_SHORT: load = new LoadSNode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency); break; - case T_LONG: load = new LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency); break; + case T_LONG: load = new LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency, require_atomic_access); break; case T_FLOAT: load = new LoadFNode (ctl, mem, adr, adr_type, rt, mo, control_dependency); break; - case T_DOUBLE: load = new LoadDNode (ctl, mem, adr, adr_type, rt, mo, control_dependency); break; + case T_DOUBLE: load = new LoadDNode (ctl, mem, adr, adr_type, rt, mo, control_dependency, require_atomic_access); break; case T_ADDRESS: load = new LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(), mo, control_dependency); break; case T_OBJECT: #ifdef _LP64 @@ -922,42 +922,6 @@ return load; } -LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, - ControlDependency control_dependency, bool unaligned, bool mismatched, bool unsafe, uint8_t barrier_data) { - bool require_atomic = true; - LoadLNode* load = new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency, require_atomic); - if (unaligned) { - load->set_unaligned_access(); - } - if (mismatched) { - load->set_mismatched_access(); - } - if (unsafe) { - load->set_unsafe_access(); - } - load->set_barrier_data(barrier_data); - return load; -} - -LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, - ControlDependency control_dependency, bool unaligned, bool mismatched, bool unsafe, uint8_t barrier_data) { - bool require_atomic = true; - LoadDNode* load = new LoadDNode(ctl, mem, adr, adr_type, rt, mo, control_dependency, require_atomic); - if (unaligned) { - load->set_unaligned_access(); - } - if (mismatched) { - load->set_mismatched_access(); - } - if (unsafe) { - load->set_unsafe_access(); - } - load->set_barrier_data(barrier_data); - return load; -} - - - //------------------------------hash------------------------------------------- uint LoadNode::hash() const { // unroll addition of interesting fields @@ -1288,7 +1252,7 @@ } return LoadNode::make(gvn, in(MemNode::Control), in(MemNode::Memory), in(MemNode::Address), raw_adr_type(), rt, bt, _mo, _control_dependency, - is_unaligned_access(), is_mismatched_access()); + false /*require_atomic_access*/, is_unaligned_access(), is_mismatched_access()); } // Construct an equivalent signed load. @@ -1308,7 +1272,7 @@ } return LoadNode::make(gvn, in(MemNode::Control), in(MemNode::Memory), in(MemNode::Address), raw_adr_type(), rt, bt, _mo, _control_dependency, - is_unaligned_access(), is_mismatched_access()); + false /*require_atomic_access*/, is_unaligned_access(), is_mismatched_access()); } bool LoadNode::has_reinterpret_variant(const Type* rt) { @@ -1331,9 +1295,12 @@ if (raw_type == NULL) { is_mismatched = true; // conservatively match all non-raw accesses as mismatched } + const int op = Opcode(); + bool require_atomic_access = (op == Op_LoadL && ((LoadLNode*)this)->require_atomic_access()) || + (op == Op_LoadD && ((LoadDNode*)this)->require_atomic_access()); return LoadNode::make(gvn, in(MemNode::Control), in(MemNode::Memory), in(MemNode::Address), raw_adr_type(), rt, bt, _mo, _control_dependency, - is_unaligned_access(), is_mismatched); + require_atomic_access, is_unaligned_access(), is_mismatched); } bool StoreNode::has_reinterpret_variant(const Type* vt) { @@ -1351,7 +1318,11 @@ Node* StoreNode::convert_to_reinterpret_store(PhaseGVN& gvn, Node* val, const Type* vt) { BasicType bt = vt->basic_type(); assert(has_reinterpret_variant(vt), "no reinterpret variant: %s %s", Name(), type2name(bt)); - StoreNode* st = StoreNode::make(gvn, in(MemNode::Control), in(MemNode::Memory), in(MemNode::Address), raw_adr_type(), val, bt, _mo); + const int op = Opcode(); + bool require_atomic_access = (op == Op_StoreL && ((StoreLNode*)this)->require_atomic_access()) || + (op == Op_StoreD && ((StoreDNode*)this)->require_atomic_access()); + StoreNode* st = StoreNode::make(gvn, in(MemNode::Control), in(MemNode::Memory), in(MemNode::Address), + raw_adr_type(), val, bt, _mo, require_atomic_access); bool is_mismatched = is_mismatched_access(); const TypeRawPtr* raw_type = gvn.type(in(MemNode::Memory))->isa_rawptr(); @@ -2588,7 +2559,7 @@ //============================================================================= //---------------------------StoreNode::make----------------------------------- // Polymorphic factory method: -StoreNode* StoreNode::make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt, MemOrd mo) { +StoreNode* StoreNode::make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt, MemOrd mo, bool require_atomic_access) { assert((mo == unordered || mo == release), "unexpected"); Compile* C = gvn.C; assert(C->get_alias_index(adr_type) != Compile::AliasIdxRaw || @@ -2600,9 +2571,9 @@ case T_INT: return new StoreINode(ctl, mem, adr, adr_type, val, mo); case T_CHAR: case T_SHORT: return new StoreCNode(ctl, mem, adr, adr_type, val, mo); - case T_LONG: return new StoreLNode(ctl, mem, adr, adr_type, val, mo); + case T_LONG: return new StoreLNode(ctl, mem, adr, adr_type, val, mo, require_atomic_access); case T_FLOAT: return new StoreFNode(ctl, mem, adr, adr_type, val, mo); - case T_DOUBLE: return new StoreDNode(ctl, mem, adr, adr_type, val, mo); + case T_DOUBLE: return new StoreDNode(ctl, mem, adr, adr_type, val, mo, require_atomic_access); case T_METADATA: case T_ADDRESS: case T_OBJECT: @@ -2626,17 +2597,6 @@ } } -StoreLNode* StoreLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo) { - bool require_atomic = true; - return new StoreLNode(ctl, mem, adr, adr_type, val, mo, require_atomic); -} - -StoreDNode* StoreDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo) { - bool require_atomic = true; - return new StoreDNode(ctl, mem, adr, adr_type, val, mo, require_atomic); -} - - //--------------------------bottom_type---------------------------------------- const Type *StoreNode::bottom_type() const { return Type::MEMORY; @@ -3118,7 +3078,7 @@ // Clearing a short array is faster with stores Node *ClearArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Already know this is a large node, do not try to ideal it - if (!IdealizeClearArrayNode || _is_large) return NULL; + if (_is_large) return NULL; const int unit = BytesPerLong; const TypeX* t = phase->type(in(2))->isa_intptr_t(); @@ -3139,6 +3099,7 @@ } else if (size > 2 && Matcher::match_rule_supported_vector(Op_ClearArray, 4, T_LONG)) { return NULL; } + if (!IdealizeClearArrayNode) return NULL; Node *mem = in(1); if( phase->type(mem)==Type::TOP ) return NULL; Node *adr = in(3); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/memnode.hpp openjdk-17-17.0.5+8/src/hotspot/share/opto/memnode.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/memnode.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/memnode.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -226,10 +226,10 @@ } // Polymorphic factory method: - static Node* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr, - const TypePtr* at, const Type *rt, BasicType bt, + static Node* make(PhaseGVN& gvn, Node* c, Node* mem, Node* adr, + const TypePtr* at, const Type* rt, BasicType bt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, - bool unaligned = false, bool mismatched = false, bool unsafe = false, + bool require_atomic_access = false, bool unaligned = false, bool mismatched = false, bool unsafe = false, uint8_t barrier_data = 0); virtual uint hash() const; // Check the type @@ -415,9 +415,7 @@ virtual int store_Opcode() const { return Op_StoreL; } virtual BasicType memory_type() const { return T_LONG; } bool require_atomic_access() const { return _require_atomic_access; } - static LoadLNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, - const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, - bool unaligned = false, bool mismatched = false, bool unsafe = false, uint8_t barrier_data = 0); + #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { LoadNode::dump_spec(st); @@ -467,9 +465,7 @@ virtual int store_Opcode() const { return Op_StoreD; } virtual BasicType memory_type() const { return T_DOUBLE; } bool require_atomic_access() const { return _require_atomic_access; } - static LoadDNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, - const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, - bool unaligned = false, bool mismatched = false, bool unsafe = false, uint8_t barrier_data = 0); + #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { LoadNode::dump_spec(st); @@ -610,8 +606,9 @@ // procedure must indicate that the store requires `release' // semantics, if the stored value is an object reference that might // point to a new object and may become externally visible. - static StoreNode* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr, - const TypePtr* at, Node *val, BasicType bt, MemOrd mo); + static StoreNode* make(PhaseGVN& gvn, Node* c, Node* mem, Node* adr, + const TypePtr* at, Node* val, BasicType bt, + MemOrd mo, bool require_atomic_access = false); virtual uint hash() const; // Check the type @@ -692,7 +689,7 @@ virtual int Opcode() const; virtual BasicType memory_type() const { return T_LONG; } bool require_atomic_access() const { return _require_atomic_access; } - static StoreLNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo); + #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { StoreNode::dump_spec(st); @@ -728,7 +725,7 @@ virtual int Opcode() const; virtual BasicType memory_type() const { return T_DOUBLE; } bool require_atomic_access() const { return _require_atomic_access; } - static StoreDNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo); + #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { StoreNode::dump_spec(st); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/split_if.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/split_if.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/split_if.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/split_if.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -128,8 +128,8 @@ } } else { // We might see an Opaque1 from a loop limit check here - assert(use->is_If() || use->is_CMove() || use->Opcode() == Op_Opaque1 || use->is_AllocateArray(), "unexpected node type"); - Node *use_c = (use->is_If() || use->is_AllocateArray()) ? use->in(0) : get_ctrl(use); + assert(use->is_If() || use->is_CMove() || use->Opcode() == Op_Opaque1, "unexpected node type"); + Node *use_c = use->is_If() ? use->in(0) : get_ctrl(use); if (use_c == blk1 || use_c == blk2) { assert(use->is_CMove(), "unexpected node type"); continue; @@ -166,15 +166,14 @@ --j; } else { // We might see an Opaque1 from a loop limit check here - assert(u->is_If() || u->is_CMove() || u->Opcode() == Op_Opaque1 || u->is_AllocateArray(), "unexpected node type"); - assert(u->is_AllocateArray() || u->in(1) == bol, ""); - assert(!u->is_AllocateArray() || u->in(AllocateNode::ValidLengthTest) == bol, "wrong input to AllocateArray"); + assert(u->is_If() || u->is_CMove() || u->Opcode() == Op_Opaque1, "unexpected node type"); + assert(u->in(1) == bol, ""); // Get control block of either the CMove or the If input - Node *u_ctrl = (u->is_If() || u->is_AllocateArray()) ? u->in(0) : get_ctrl(u); + Node *u_ctrl = u->is_If() ? u->in(0) : get_ctrl(u); assert((u_ctrl != blk1 && u_ctrl != blk2) || u->is_CMove(), "won't converge"); Node *x = bol->clone(); register_new_node(x, u_ctrl); - _igvn.replace_input_of(u, u->is_AllocateArray() ? AllocateNode::ValidLengthTest : 1, x); + _igvn.replace_input_of(u, 1, x); --j; } } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/subnode.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/subnode.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/subnode.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/subnode.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -733,11 +733,10 @@ int w = MAX2(r0->_widen, r1->_widen); // _widen does not matter here const TypeInt* tr1 = TypeInt::make(lo_tr1, hi_tr1, w); const TypeInt* tr2 = TypeInt::make(lo_tr2, hi_tr2, w); - const Type* cmp1 = sub(tr1, t2); - const Type* cmp2 = sub(tr2, t2); - if (cmp1 == cmp2) { - return cmp1; // Hit! - } + const TypeInt* cmp1 = sub(tr1, t2)->is_int(); + const TypeInt* cmp2 = sub(tr2, t2)->is_int(); + // compute union, so that cmp handles all possible results from the two cases + return cmp1->meet(cmp2); } } } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/opto/superword.cpp openjdk-17-17.0.5+8/src/hotspot/share/opto/superword.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/opto/superword.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/opto/superword.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -2408,6 +2408,11 @@ return false; } + // Check that the loop to be vectorized does not have inconsistent reduction + // information, which would likely lead to a miscompilation. + assert(!lpt()->has_reduction_nodes() || cl->is_reduction_loop(), + "non-reduction loop contains reduction nodes"); + #ifndef PRODUCT if (TraceLoopOpts) { tty->print("SuperWord::output "); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/prims/forte.cpp openjdk-17-17.0.5+8/src/hotspot/share/prims/forte.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/prims/forte.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/prims/forte.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -552,6 +552,9 @@ return; } + // !important! make sure all to call thread->set_in_asgct(false) before every return + thread->set_in_asgct(true); + switch (thread->thread_state()) { case _thread_new: case _thread_uninitialized: @@ -609,6 +612,7 @@ trace->num_frames = ticks_unknown_state; // -7 break; } + thread->set_in_asgct(false); } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/prims/jvm.cpp openjdk-17-17.0.5+8/src/hotspot/share/prims/jvm.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/prims/jvm.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/prims/jvm.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -436,7 +436,7 @@ JVM_ENTRY_NO_ENV(void, JVM_Halt(jint code)) - before_exit(thread); + before_exit(thread, true); vm_exit(code); JVM_END diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/prims/jvmtiExport.cpp openjdk-17-17.0.5+8/src/hotspot/share/prims/jvmtiExport.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/prims/jvmtiExport.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/prims/jvmtiExport.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -169,7 +169,7 @@ thread->set_active_handles(new_handles); #endif assert(thread == JavaThread::current(), "thread must be current!"); - thread->frame_anchor()->make_walkable(thread); + thread->frame_anchor()->make_walkable(); }; ~JvmtiEventMark() { diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/prims/jvmtiRedefineClasses.cpp openjdk-17-17.0.5+8/src/hotspot/share/prims/jvmtiRedefineClasses.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/prims/jvmtiRedefineClasses.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/prims/jvmtiRedefineClasses.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1856,14 +1856,15 @@ if (old_cp->has_dynamic_constant()) { scratch_cp->set_has_dynamic_constant(); } - // Copy attributes from scratch_cp to merge_cp - merge_cp->copy_fields(scratch_cp()); log_info(redefine, class, constantpool)("merge_cp_len=%d, index_map_len=%d", merge_cp_length, _index_map_count); if (_index_map_count == 0) { // there is nothing to map between the new and merged constant pools + // Copy attributes from scratch_cp to merge_cp + merge_cp->copy_fields(scratch_cp()); + if (old_cp->length() == scratch_cp->length()) { // The old and new constant pools are the same length and the // index map is empty. This means that the three constant pools @@ -1917,6 +1918,9 @@ return JVMTI_ERROR_INTERNAL; } + // Copy attributes from scratch_cp to merge_cp (should be done after rewrite_cp_refs()) + merge_cp->copy_fields(scratch_cp()); + // Replace the new constant pool with a shrunken copy of the // merged constant pool so now the rewritten bytecodes have // valid references; the previous new constant pool will get @@ -3507,10 +3511,9 @@ } // end rewrite_cp_refs_in_verification_type_info() -// Change the constant pool associated with klass scratch_class to -// scratch_cp. If shrink is true, then scratch_cp_length elements -// are copied from scratch_cp to a smaller constant pool and the -// smaller constant pool is associated with scratch_class. +// Change the constant pool associated with klass scratch_class to scratch_cp. +// scratch_cp_length elements are copied from scratch_cp to a smaller constant pool +// and the smaller constant pool is associated with scratch_class. void VM_RedefineClasses::set_new_constant_pool( ClassLoaderData* loader_data, InstanceKlass* scratch_class, constantPoolHandle scratch_cp, @@ -4374,10 +4377,6 @@ // Leave arrays of jmethodIDs and itable index cache unchanged - // Copy the "source file name" attribute from new class version - the_class->set_source_file_name_index( - scratch_class->source_file_name_index()); - // Copy the "source debug extension" attribute from new class version the_class->set_source_debug_extension( scratch_class->source_debug_extension(), diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/runtime/arguments.cpp openjdk-17-17.0.5+8/src/hotspot/share/runtime/arguments.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/runtime/arguments.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/runtime/arguments.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -53,7 +53,7 @@ #include "runtime/safepointMechanism.hpp" #include "runtime/vm_version.hpp" #include "services/management.hpp" -#include "services/memTracker.hpp" +#include "services/nmtCommon.hpp" #include "utilities/align.hpp" #include "utilities/defaultStream.hpp" #include "utilities/macros.hpp" @@ -1985,17 +1985,6 @@ status = false; } - if (PrintNMTStatistics) { -#if INCLUDE_NMT - if (MemTracker::tracking_level() == NMT_off) { -#endif // INCLUDE_NMT - warning("PrintNMTStatistics is disabled, because native memory tracking is not enabled"); - PrintNMTStatistics = false; -#if INCLUDE_NMT - } -#endif - } - status = CompilerConfig::check_args_consistency(status); #if INCLUDE_JVMCI if (status && EnableJVMCI) { @@ -3718,29 +3707,6 @@ JVMFlag::printFlags(tty, false); vm_exit(0); } - if (match_option(option, "-XX:NativeMemoryTracking", &tail)) { -#if INCLUDE_NMT - // The launcher did not setup nmt environment variable properly. - if (!MemTracker::check_launcher_nmt_support(tail)) { - warning("Native Memory Tracking did not setup properly, using wrong launcher?"); - } - - // Verify if nmt option is valid. - if (MemTracker::verify_nmt_option()) { - // Late initialization, still in single-threaded mode. - if (MemTracker::tracking_level() >= NMT_summary) { - MemTracker::init(); - } - } else { - vm_exit_during_initialization("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL); - } - continue; -#else - jio_fprintf(defaultStream::error_stream(), - "Native Memory Tracking is not supported in this VM\n"); - return JNI_ERR; -#endif - } #ifndef PRODUCT if (match_option(option, "-XX:+PrintFlagsWithComments")) { @@ -3992,6 +3958,26 @@ no_shared_spaces("CDS Disabled"); #endif // INCLUDE_CDS +#if INCLUDE_NMT + // Verify NMT arguments + const NMT_TrackingLevel lvl = NMTUtil::parse_tracking_level(NativeMemoryTracking); + if (lvl == NMT_unknown) { + jio_fprintf(defaultStream::error_stream(), + "Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL); + return JNI_ERR; + } + if (PrintNMTStatistics && lvl == NMT_off) { + warning("PrintNMTStatistics is disabled, because native memory tracking is not enabled"); + FLAG_SET_DEFAULT(PrintNMTStatistics, false); + } +#else + if (!FLAG_IS_DEFAULT(NativeMemoryTracking) || PrintNMTStatistics) { + warning("Native Memory Tracking is not supported in this VM"); + FLAG_SET_DEFAULT(NativeMemoryTracking, "off"); + FLAG_SET_DEFAULT(PrintNMTStatistics, false); + } +#endif // INCLUDE_NMT + if (TraceDependencies && VerifyDependencies) { if (!FLAG_IS_DEFAULT(TraceDependencies)) { warning("TraceDependencies results may be inflated by VerifyDependencies"); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/runtime/frame.hpp openjdk-17-17.0.5+8/src/hotspot/share/runtime/frame.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/runtime/frame.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/runtime/frame.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -202,8 +202,12 @@ public: // Link (i.e., the pointer to the previous frame) + // might crash if the frame has no parent intptr_t* link() const; + // Link (i.e., the pointer to the previous frame) or null if the link cannot be accessed + intptr_t* link_or_null() const; + // Return address address sender_pc() const; diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/runtime/interfaceSupport.inline.hpp openjdk-17-17.0.5+8/src/hotspot/share/runtime/interfaceSupport.inline.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/runtime/interfaceSupport.inline.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/runtime/interfaceSupport.inline.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -138,7 +138,7 @@ _original_state(thread->thread_state()) { if (thread->has_last_Java_frame()) { - thread->frame_anchor()->make_walkable(thread); + thread->frame_anchor()->make_walkable(); } thread->set_thread_state(_thread_in_vm); @@ -209,7 +209,7 @@ // we call known native code using this wrapper holding locks. _thread->check_possible_safepoint(); // Once we are in native vm expects stack to be walkable - _thread->frame_anchor()->make_walkable(_thread); + _thread->frame_anchor()->make_walkable(); OrderAccess::storestore(); // Keep thread_state change and make_walkable() separate. _thread->set_thread_state(_thread_in_native); } @@ -222,7 +222,7 @@ // We are leaving the VM at this point and going directly to native code. // Block, if we are in the middle of a safepoint synchronization. assert(!thread->owns_locks(), "must release all locks when leaving VM"); - thread->frame_anchor()->make_walkable(thread); + thread->frame_anchor()->make_walkable(); trans(_thread_in_vm, _thread_in_native); // Check for pending. async. exceptions or suspends. if (_thread->has_special_runtime_exit_condition()) _thread->handle_special_runtime_exit_condition(false); @@ -250,7 +250,7 @@ assert(thread->thread_state() == _thread_in_vm, "coming from wrong thread state"); thread->check_possible_safepoint(); // Once we are blocked vm expects stack to be walkable - thread->frame_anchor()->make_walkable(thread); + thread->frame_anchor()->make_walkable(); OrderAccess::storestore(); // Keep thread_state change and make_walkable() separate. thread->set_thread_state(_thread_blocked); } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/runtime/java.cpp openjdk-17-17.0.5+8/src/hotspot/share/runtime/java.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/runtime/java.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/runtime/java.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -244,7 +244,6 @@ Deoptimization::print_statistics(); SharedRuntime::print_statistics(); #endif //COMPILER1 - os::print_statistics(); } if (PrintLockStatistics || PrintPreciseBiasedLockingStatistics || PrintPreciseRTMLockingStatistics) { @@ -404,7 +403,7 @@ // Note: before_exit() can be executed only once, if more than one threads // are trying to shutdown the VM at the same time, only one thread // can run before_exit() and all other threads must wait. -void before_exit(JavaThread* thread) { +void before_exit(JavaThread* thread, bool halt) { #define BEFORE_EXIT_NOT_RUN 0 #define BEFORE_EXIT_RUNNING 1 #define BEFORE_EXIT_DONE 2 @@ -451,7 +450,7 @@ event.commit(); } - JFR_ONLY(Jfr::on_vm_shutdown();) + JFR_ONLY(Jfr::on_vm_shutdown(false, halt);) // Stop the WatcherThread. We do this before disenrolling various // PeriodicTasks to reduce the likelihood of races. @@ -612,7 +611,7 @@ JavaThread* jt = thread->as_Java_thread(); // Must always be walkable or have no last_Java_frame when in // thread_in_native - jt->frame_anchor()->make_walkable(jt); + jt->frame_anchor()->make_walkable(); jt->set_thread_state(_thread_in_native); } } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/runtime/java.hpp openjdk-17-17.0.5+8/src/hotspot/share/runtime/java.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/runtime/java.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/runtime/java.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -33,7 +33,7 @@ class Symbol; // Execute code before all handles are released and thread is killed; prologue to vm_exit -extern void before_exit(JavaThread * thread); +extern void before_exit(JavaThread * thread, bool halt = false); // Forced VM exit (i.e, internal error or JVM_Exit) extern void vm_exit(int code); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/runtime/objectMonitor.cpp openjdk-17-17.0.5+8/src/hotspot/share/runtime/objectMonitor.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/runtime/objectMonitor.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/runtime/objectMonitor.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -668,7 +668,7 @@ } else { // We report NULL instead of DEFLATER_MARKER here because is_busy() // ignores DEFLATER_MARKER values. - ss->print("owner=" INTPTR_FORMAT, NULL); + ss->print("owner=" INTPTR_FORMAT, NULL_WORD); } ss->print(", cxq=" INTPTR_FORMAT ", EntryList=" INTPTR_FORMAT, p2i(_cxq), p2i(_EntryList)); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/runtime/os.cpp openjdk-17-17.0.5+8/src/hotspot/share/runtime/os.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/runtime/os.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/runtime/os.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -64,6 +64,7 @@ #include "services/attachListener.hpp" #include "services/mallocTracker.hpp" #include "services/memTracker.hpp" +#include "services/nmtPreInit.hpp" #include "services/nmtCommon.hpp" #include "services/threadService.hpp" #include "utilities/align.hpp" @@ -681,6 +682,15 @@ NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); +#if INCLUDE_NMT + { + void* rc = NULL; + if (NMTPreInit::handle_malloc(&rc, size)) { + return rc; + } + } +#endif + // Since os::malloc can be called when the libjvm.{dll,so} is // first loaded and we don't have a thread yet we must accept NULL also here. assert(!os::ThreadCrashProtection::is_crash_protected(Thread::current_or_null()), @@ -696,6 +706,11 @@ NMT_TrackingLevel level = MemTracker::tracking_level(); size_t nmt_header_size = MemTracker::malloc_header_size(level); + // Check for overflow. + if (size + nmt_header_size < size) { + return NULL; + } + #ifndef ASSERT const size_t alloc_size = size + nmt_header_size; #else @@ -740,6 +755,15 @@ void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { +#if INCLUDE_NMT + { + void* rc = NULL; + if (NMTPreInit::handle_realloc(&rc, memblock, size)) { + return rc; + } + } +#endif + // For the test flag -XX:MallocMaxTestWords if (has_reached_max_malloc_test_peak(size)) { return NULL; @@ -790,6 +814,13 @@ // handles NULL pointers void os::free(void *memblock) { + +#if INCLUDE_NMT + if (NMTPreInit::handle_free(memblock)) { + return; + } +#endif + NOT_PRODUCT(inc_stat_counter(&num_frees, 1)); #ifdef ASSERT if (memblock == NULL) return; @@ -1255,34 +1286,34 @@ st->print_cr(INTPTR_FORMAT " is an unknown value", p2i(addr)); } +bool is_pointer_bad(intptr_t* ptr) { + return !is_aligned(ptr, sizeof(uintptr_t)) || !os::is_readable_pointer(ptr); +} + // Looks like all platforms can use the same function to check if C // stack is walkable beyond current frame. +// Returns true if this is not the case, i.e. the frame is possibly +// the first C frame on the stack. bool os::is_first_C_frame(frame* fr) { #ifdef _WINDOWS return true; // native stack isn't walkable on windows this way. #endif - // Load up sp, fp, sender sp and sender fp, check for reasonable values. // Check usp first, because if that's bad the other accessors may fault // on some architectures. Ditto ufp second, etc. - uintptr_t fp_align_mask = (uintptr_t)(sizeof(address)-1); - // sp on amd can be 32 bit aligned. - uintptr_t sp_align_mask = (uintptr_t)(sizeof(int)-1); - uintptr_t usp = (uintptr_t)fr->sp(); - if ((usp & sp_align_mask) != 0) return true; + if (is_pointer_bad(fr->sp())) return true; uintptr_t ufp = (uintptr_t)fr->fp(); - if ((ufp & fp_align_mask) != 0) return true; + if (is_pointer_bad(fr->fp())) return true; uintptr_t old_sp = (uintptr_t)fr->sender_sp(); - if ((old_sp & sp_align_mask) != 0) return true; - if (old_sp == 0 || old_sp == (uintptr_t)-1) return true; + if ((uintptr_t)fr->sender_sp() == (uintptr_t)-1 || is_pointer_bad(fr->sender_sp())) return true; - uintptr_t old_fp = (uintptr_t)fr->link(); - if ((old_fp & fp_align_mask) != 0) return true; - if (old_fp == 0 || old_fp == (uintptr_t)-1 || old_fp == ufp) return true; + uintptr_t old_fp = (uintptr_t)fr->link_or_null(); + if (old_fp == 0 || old_fp == (uintptr_t)-1 || old_fp == ufp || + is_pointer_bad(fr->link_or_null())) return true; // stack grows downwards; if old_fp is below current fp or if the stack // frame is too large, either the stack is corrupted or fp is not saved @@ -1294,7 +1325,6 @@ return false; } - // Set up the boot classpath. char* os::format_boot_path(const char* format_string, diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/runtime/safefetch.inline.hpp openjdk-17-17.0.5+8/src/hotspot/share/runtime/safefetch.inline.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/runtime/safefetch.inline.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/runtime/safefetch.inline.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -54,10 +54,20 @@ // returns true if SafeFetch32 and SafeFetchN can be used safely (stubroutines are already generated) inline bool CanUseSafeFetch32() { +#if defined (__APPLE__) && defined(AARCH64) + if (Thread::current_or_null_safe() == NULL) { // workaround for JDK-8282475 + return false; + } +#endif // __APPLE__ && AARCH64 return StubRoutines::SafeFetch32_stub() ? true : false; } inline bool CanUseSafeFetchN() { +#if defined (__APPLE__) && defined(AARCH64) + if (Thread::current_or_null_safe() == NULL) { + return false; + } +#endif // __APPLE__ && AARCH64 return StubRoutines::SafeFetchN_stub() ? true : false; } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/runtime/safepoint.cpp openjdk-17-17.0.5+8/src/hotspot/share/runtime/safepoint.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/runtime/safepoint.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/runtime/safepoint.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -705,7 +705,7 @@ } JavaThreadState state = thread->thread_state(); - thread->frame_anchor()->make_walkable(thread); + thread->frame_anchor()->make_walkable(); uint64_t safepoint_id = SafepointSynchronize::safepoint_counter(); // Check that we have a valid thread_state at this point diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/runtime/thread.cpp openjdk-17-17.0.5+8/src/hotspot/share/runtime/thread.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/runtime/thread.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/runtime/thread.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -374,10 +374,10 @@ // Perform common initialization actions - register_thread_stack_with_NMT(); - MACOS_AARCH64_ONLY(this->init_wx()); + register_thread_stack_with_NMT(); + JFR_ONLY(Jfr::on_thread_start(this);) log_debug(os, thread)("Thread " UINTX_FORMAT " stack dimensions: " @@ -1014,6 +1014,7 @@ JavaThread::JavaThread() : // Initialize fields + _in_asgct(false), _on_thread_list(false), DEBUG_ONLY(_java_call_counter(0) COMMA) _entry_point(nullptr), @@ -1057,8 +1058,8 @@ _pending_failed_speculation(0), _jvmci{nullptr}, _jvmci_counters(nullptr), - _jvmci_reserved0(nullptr), - _jvmci_reserved1(nullptr), + _jvmci_reserved0(0), + _jvmci_reserved1(0), _jvmci_reserved_oop0(nullptr), #endif // INCLUDE_JVMCI @@ -1701,7 +1702,7 @@ void JavaThread::handle_special_runtime_exit_condition(bool check_asyncs) { if (is_obj_deopt_suspend()) { - frame_anchor()->make_walkable(this); + frame_anchor()->make_walkable(); wait_for_object_deoptimization(); } @@ -2768,6 +2769,11 @@ jint parse_result = Arguments::parse(args); if (parse_result != JNI_OK) return parse_result; +#if INCLUDE_NMT + // Initialize NMT right after argument parsing to keep the pre-NMT-init window small. + MemTracker::initialize(); +#endif // INCLUDE_NMT + os::init_before_ergo(); jint ergo_result = Arguments::apply_ergo(); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/runtime/thread.hpp openjdk-17-17.0.5+8/src/hotspot/share/runtime/thread.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/runtime/thread.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/runtime/thread.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -692,6 +692,7 @@ friend class ThreadsSMRSupport; // to access _threadObj for exiting_threads_oops_do friend class HandshakeState; private: + bool _in_asgct; // Is set when this JavaThread is handling ASGCT call bool _on_thread_list; // Is set when this JavaThread is added to the Threads list OopHandle _threadObj; // The Java level thread object @@ -957,8 +958,8 @@ jlong* _jvmci_counters; // Fast thread locals for use by JVMCI - intptr_t* _jvmci_reserved0; - intptr_t* _jvmci_reserved1; + jlong _jvmci_reserved0; + jlong _jvmci_reserved1; oop _jvmci_reserved_oop0; public: @@ -969,6 +970,30 @@ static bool resize_all_jvmci_counters(int new_size); + void set_jvmci_reserved_oop0(oop value) { + _jvmci_reserved_oop0 = value; + } + + oop get_jvmci_reserved_oop0() { + return _jvmci_reserved_oop0; + } + + void set_jvmci_reserved0(jlong value) { + _jvmci_reserved0 = value; + } + + jlong get_jvmci_reserved0() { + return _jvmci_reserved0; + } + + void set_jvmci_reserved1(jlong value) { + _jvmci_reserved1 = value; + } + + jlong get_jvmci_reserved1() { + return _jvmci_reserved1; + } + private: #endif // INCLUDE_JVMCI @@ -1391,7 +1416,7 @@ public: // Accessing frames frame last_frame() { - _anchor.make_walkable(this); + _anchor.make_walkable(); return pd_last_frame(); } javaVFrame* last_java_vframe(RegisterMap* reg_map); @@ -1589,6 +1614,10 @@ static OopStorage* thread_oop_storage(); static void verify_cross_modify_fence_failure(JavaThread *thread) PRODUCT_RETURN; + + // AsyncGetCallTrace support + inline bool in_asgct(void) {return _in_asgct;} + inline void set_in_asgct(bool value) {_in_asgct = value;} }; // Inline implementation of JavaThread::current diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/services/memTracker.cpp openjdk-17-17.0.5+8/src/hotspot/share/services/memTracker.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/services/memTracker.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/services/memTracker.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -23,8 +23,11 @@ */ #include "precompiled.hpp" #include "jvm.h" +#include "logging/log.hpp" +#include "logging/logStream.hpp" #include "memory/metaspaceUtils.hpp" #include "runtime/atomic.hpp" +#include "runtime/globals.hpp" #include "runtime/orderAccess.hpp" #include "runtime/vmThread.hpp" #include "runtime/vmOperations.hpp" @@ -32,6 +35,8 @@ #include "services/memReporter.hpp" #include "services/mallocTracker.inline.hpp" #include "services/memTracker.hpp" +#include "services/nmtCommon.hpp" +#include "services/nmtPreInit.hpp" #include "services/threadStackTracker.hpp" #include "utilities/debug.hpp" #include "utilities/defaultStream.hpp" @@ -45,79 +50,44 @@ NMT_TrackingLevel MemTracker::_cmdline_tracking_level = NMT_unknown; MemBaseline MemTracker::_baseline; -bool MemTracker::_is_nmt_env_valid = true; -static const size_t buffer_size = 64; +void MemTracker::initialize() { + bool rc = true; + assert(_tracking_level == NMT_unknown, "only call once"); + + NMT_TrackingLevel level = NMTUtil::parse_tracking_level(NativeMemoryTracking); + // Should have been validated before in arguments.cpp + assert(level == NMT_off || level == NMT_summary || level == NMT_detail, + "Invalid setting for NativeMemoryTracking (%s)", NativeMemoryTracking); -NMT_TrackingLevel MemTracker::init_tracking_level() { // Memory type is encoded into tracking header as a byte field, // make sure that we don't overflow it. STATIC_ASSERT(mt_number_of_types <= max_jubyte); - char nmt_env_variable[buffer_size]; - jio_snprintf(nmt_env_variable, sizeof(nmt_env_variable), "NMT_LEVEL_%d", os::current_process_id()); - const char* nmt_env_value; -#ifdef _WINDOWS - // Read the NMT environment variable from the PEB instead of the CRT - char value[buffer_size]; - nmt_env_value = GetEnvironmentVariable(nmt_env_variable, value, (DWORD)sizeof(value)) != 0 ? value : NULL; -#else - nmt_env_value = ::getenv(nmt_env_variable); -#endif - NMT_TrackingLevel level = NMT_off; - if (nmt_env_value != NULL) { - if (strcmp(nmt_env_value, "summary") == 0) { - level = NMT_summary; - } else if (strcmp(nmt_env_value, "detail") == 0) { - level = NMT_detail; - } else if (strcmp(nmt_env_value, "off") != 0) { - // The value of the environment variable is invalid - _is_nmt_env_valid = false; - } - // Remove the environment variable to avoid leaking to child processes - os::unsetenv(nmt_env_variable); - } - - if (!MallocTracker::initialize(level) || - !VirtualMemoryTracker::initialize(level)) { - level = NMT_off; - } - return level; -} - -void MemTracker::init() { - NMT_TrackingLevel level = tracking_level(); - if (level >= NMT_summary) { - if (!VirtualMemoryTracker::late_initialize(level) || - !ThreadStackTracker::late_initialize(level)) { - shutdown(); + if (level > NMT_off) { + if (!MallocTracker::initialize(level) || + !VirtualMemoryTracker::initialize(level) || + !ThreadStackTracker::initialize(level)) { + assert(false, "NMT initialization failed"); + level = NMT_off; + log_warning(nmt)("NMT initialization failed. NMT disabled."); return; } } -} -bool MemTracker::check_launcher_nmt_support(const char* value) { - if (strcmp(value, "=detail") == 0) { - if (MemTracker::tracking_level() != NMT_detail) { - return false; - } - } else if (strcmp(value, "=summary") == 0) { - if (MemTracker::tracking_level() != NMT_summary) { - return false; - } - } else if (strcmp(value, "=off") == 0) { - if (MemTracker::tracking_level() != NMT_off) { - return false; - } - } else { - _is_nmt_env_valid = false; - } + NMTPreInit::pre_to_post(); - return true; -} + _tracking_level = _cmdline_tracking_level = level; -bool MemTracker::verify_nmt_option() { - return _is_nmt_env_valid; + // Log state right after NMT initialization + if (log_is_enabled(Info, nmt)) { + LogTarget(Info, nmt) lt; + LogStream ls(lt); + ls.print_cr("NMT initialized: %s", NMTUtil::tracking_level_to_string(_tracking_level)); + ls.print_cr("Preinit state: "); + NMTPreInit::print_state(&ls); + ls.cr(); + } } void* MemTracker::malloc_base(void* memblock) { @@ -174,6 +144,8 @@ void MemTracker::error_report(outputStream* output) { if (tracking_level() >= NMT_summary) { report(true, output, MemReporterBase::default_scale); // just print summary for error case. + output->print("Preinit state:"); + NMTPreInit::print_state(output); } } @@ -214,9 +186,14 @@ void MemTracker::tuning_statistics(outputStream* out) { // NMT statistics out->print_cr("Native Memory Tracking Statistics:"); + out->print_cr("State: %s", NMTUtil::tracking_level_to_string(_tracking_level)); out->print_cr("Malloc allocation site table size: %d", MallocSiteTable::hash_buckets()); out->print_cr(" Tracking stack depth: %d", NMT_TrackingStackDepth); NOT_PRODUCT(out->print_cr("Peak concurrent access: %d", MallocSiteTable::access_peak_count());) out->cr(); MallocSiteTable::print_tuning_statistics(out); + out->cr(); + out->print_cr("Preinit state:"); + NMTPreInit::print_state(out); + out->cr(); } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/services/memTracker.hpp openjdk-17-17.0.5+8/src/hotspot/share/services/memTracker.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/services/memTracker.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/services/memTracker.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -115,42 +115,33 @@ class MemTracker : AllStatic { friend class VirtualMemoryTrackerTest; + // Helper; asserts that we are in post-NMT-init phase + static void assert_post_init() { + assert(is_initialized(), "NMT not yet initialized."); + } + public: + + // Initializes NMT to whatever -XX:NativeMemoryTracking says. + // - Can only be called once. + // - NativeMemoryTracking must be validated beforehand. + static void initialize(); + + // Returns true if NMT had been initialized. + static bool is_initialized() { + return _tracking_level != NMT_unknown; + } + static inline NMT_TrackingLevel tracking_level() { - if (_tracking_level == NMT_unknown) { - // No fencing is needed here, since JVM is in single-threaded - // mode. - _tracking_level = init_tracking_level(); - _cmdline_tracking_level = _tracking_level; - } return _tracking_level; } - // A late initialization, for the stuff(s) can not be - // done in init_tracking_level(), which can NOT malloc - // any memory. - static void init(); - - // Shutdown native memory tracking + // Shutdown native memory tracking. + // This transitions the tracking level: + // summary -> minimal + // detail -> minimal static void shutdown(); - // Verify native memory tracking command line option. - // This check allows JVM to detect if compatible launcher - // is used. - // If an incompatible launcher is used, NMT may not be - // able to start, even it is enabled by command line option. - // A warning message should be given if it is encountered. - static bool check_launcher_nmt_support(const char* value); - - // This method checks native memory tracking environment - // variable value passed by launcher. - // Launcher only obligated to pass native memory tracking - // option value, but not obligated to validate the value, - // and launcher has option to discard native memory tracking - // option from the command line once it sets up the environment - // variable, so NMT has to catch the bad value here. - static bool verify_nmt_option(); - // Transition the tracking level to specified level static bool transition_to(NMT_TrackingLevel level); @@ -207,8 +198,12 @@ MallocTracker::record_arena_size_change(diff, flag); } + // Note: virtual memory operations should only ever be called after NMT initialization + // (we do not do any reservations before that). + static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag = mtNone) { + assert_post_init(); if (tracking_level() < NMT_summary) return; if (addr != NULL) { ThreadCritical tc; @@ -220,6 +215,7 @@ static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag = mtNone) { + assert_post_init(); if (tracking_level() < NMT_summary) return; if (addr != NULL) { ThreadCritical tc; @@ -231,6 +227,7 @@ static inline void record_virtual_memory_commit(void* addr, size_t size, const NativeCallStack& stack) { + assert_post_init(); if (tracking_level() < NMT_summary) return; if (addr != NULL) { ThreadCritical tc; @@ -246,6 +243,7 @@ // The two new memory regions will be both registered under stack and // memory flags of the original region. static inline void record_virtual_memory_split_reserved(void* addr, size_t size, size_t split) { + assert_post_init(); if (tracking_level() < NMT_summary) return; if (addr != NULL) { ThreadCritical tc; @@ -256,6 +254,7 @@ } static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) { + assert_post_init(); if (tracking_level() < NMT_summary) return; if (addr != NULL) { ThreadCritical tc; @@ -265,6 +264,7 @@ } static void record_thread_stack(void* addr, size_t size) { + assert_post_init(); if (tracking_level() < NMT_summary) return; if (addr != NULL) { ThreadStackTracker::new_thread_stack((address)addr, size, CALLER_PC); @@ -272,6 +272,7 @@ } static inline void release_thread_stack(void* addr, size_t size) { + assert_post_init(); if (tracking_level() < NMT_summary) return; if (addr != NULL) { ThreadStackTracker::delete_thread_stack((address)addr, size); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/services/nmtCommon.cpp openjdk-17-17.0.5+8/src/hotspot/share/services/nmtCommon.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/services/nmtCommon.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/services/nmtCommon.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -60,3 +60,27 @@ return K; } +const char* NMTUtil::tracking_level_to_string(NMT_TrackingLevel lvl) { + switch(lvl) { + case NMT_unknown: return "unknown"; break; + case NMT_off: return "off"; break; + case NMT_minimal: return "minimal"; break; + case NMT_summary: return "summary"; break; + case NMT_detail: return "detail"; break; + default: return "invalid"; break; + } +} + +// Returns the parsed level; NMT_unknown if string is invalid +NMT_TrackingLevel NMTUtil::parse_tracking_level(const char* s) { + if (s != NULL) { + if (strcmp(s, "summary") == 0) { + return NMT_summary; + } else if (strcmp(s, "detail") == 0) { + return NMT_detail; + } else if (strcmp(s, "off") == 0) { + return NMT_off; + } + } + return NMT_unknown; +} diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/services/nmtCommon.hpp openjdk-17-17.0.5+8/src/hotspot/share/services/nmtCommon.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/services/nmtCommon.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/services/nmtCommon.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -32,12 +32,52 @@ #define CALC_OBJ_SIZE_IN_TYPE(obj, type) (align_up(sizeof(obj), sizeof(type))/sizeof(type)) // Native memory tracking level +// +// The meaning of the different states: +// +// "unknown": pre-init phase (before parsing NMT arguments) +// +// "off": after initialization - NMT confirmed off. +// - nothing is tracked +// - no malloc headers are used +// +// "minimal": after shutdown - NMT had been on at some point but has been switched off +// - nothing is tracked +// - malloc headers are allocated but not initialized not used +// +// "summary": after initialization with NativeMemoryTracking=summary - NMT in summary mode +// - category summaries per tag are tracked +// - thread stacks are tracked +// - malloc headers are used +// - malloc call site table is allocated and used +// +// "detail": after initialization with NativeMemoryTracking=detail - NMT in detail mode +// - category summaries per tag are tracked +// - malloc details per call site are tracked +// - virtual memory mapping info is tracked +// - thread stacks are tracked +// - malloc headers are used +// - malloc call site table is allocated and used +// +// Valid state transitions: +// +// unknown ----> off +// | +// |--> summary -- +// | | +// |--> detail --+--> minimal +// + + +// Please keep relation of numerical values! +// unknown < off < minimal < summary < detail +// enum NMT_TrackingLevel { - NMT_unknown = 0xFF, - NMT_off = 0x00, - NMT_minimal = 0x01, - NMT_summary = 0x02, - NMT_detail = 0x03 + NMT_unknown = 0, + NMT_off = 1, + NMT_minimal = 2, + NMT_summary = 3, + NMT_detail = 4 }; // Number of stack frames to capture. This is a @@ -83,6 +123,14 @@ static size_t amount_in_scale(size_t amount, size_t scale) { return (amount + scale / 2) / scale; } + + // Parses the tracking level from a string. Returns NMT_unknown if + // string is not a valid level. + static NMT_TrackingLevel parse_tracking_level(const char* s); + + // Returns textual representation of a tracking level. + static const char* tracking_level_to_string(NMT_TrackingLevel level); + private: static const char* _memory_type_names[mt_number_of_types]; }; diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/services/nmtPreInit.cpp openjdk-17-17.0.5+8/src/hotspot/share/services/nmtPreInit.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/services/nmtPreInit.cpp 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/services/nmtPreInit.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2021 SAP SE. All rights reserved. + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "runtime/os.hpp" +#include "services/nmtPreInit.hpp" +#include "utilities/align.hpp" +#include "utilities/debug.hpp" +#include "utilities/ostream.hpp" +#include "utilities/globalDefinitions.hpp" + +#if INCLUDE_NMT + +// Obviously we cannot use os::malloc for any dynamic allocation during pre-NMT-init, so we must use +// raw malloc; to make this very clear, wrap them. +static void* raw_malloc(size_t s) { return ::malloc(s); } +static void* raw_realloc(void* old, size_t s) { return ::realloc(old, s); } +static void raw_free(void* p) { ::free(p); } + +// We must ensure that the start of the payload area of the nmt lookup table nodes is malloc-aligned +static const size_t malloc_alignment = 2 * sizeof(void*); // could we use max_align_t? +STATIC_ASSERT(is_aligned(sizeof(NMTPreInitAllocation), malloc_alignment)); + +// --------- NMTPreInitAllocation -------------- + +NMTPreInitAllocation* NMTPreInitAllocation::do_alloc(size_t payload_size) { + const size_t outer_size = sizeof(NMTPreInitAllocation) + payload_size; + void* p = raw_malloc(outer_size); + NMTPreInitAllocation* a = new(p) NMTPreInitAllocation(payload_size); + return a; +} + +NMTPreInitAllocation* NMTPreInitAllocation::do_reallocate(NMTPreInitAllocation* old, size_t new_payload_size) { + assert(old->next == NULL, "unhang from map first"); + // We just reallocate the old block, header and all. + const size_t new_outer_size = sizeof(NMTPreInitAllocation) + new_payload_size; + void* p = raw_realloc(old, new_outer_size); + // re-stamp header with new size + NMTPreInitAllocation* a = new(p) NMTPreInitAllocation(new_payload_size); + return a; +} + +void NMTPreInitAllocation::do_free(NMTPreInitAllocation* p) { + assert(p->next == NULL, "unhang from map first"); + raw_free(p); +} + +// --------- NMTPreInitAllocationTable -------------- + +NMTPreInitAllocationTable::NMTPreInitAllocationTable() { + ::memset(_entries, 0, sizeof(_entries)); +} + +// print a string describing the current state +void NMTPreInitAllocationTable::print_state(outputStream* st) const { + // Collect some statistics and print them + int num_entries = 0; + int num_primary_entries = 0; + int longest_chain = 0; + size_t sum_bytes = 0; + for (int i = 0; i < table_size; i++) { + int chain_len = 0; + for (NMTPreInitAllocation* a = _entries[i]; a != NULL; a = a->next) { + chain_len++; + sum_bytes += a->size; + } + if (chain_len > 0) { + num_primary_entries++; + } + num_entries += chain_len; + longest_chain = MAX2(chain_len, longest_chain); + } + st->print("entries: %d (primary: %d, empties: %d), sum bytes: " SIZE_FORMAT + ", longest chain length: %d", + num_entries, num_primary_entries, table_size - num_primary_entries, + sum_bytes, longest_chain); +} + +#ifdef ASSERT +void NMTPreInitAllocationTable::print_map(outputStream* st) const { + for (int i = 0; i < table_size; i++) { + st->print("[%d]: ", i); + for (NMTPreInitAllocation* a = _entries[i]; a != NULL; a = a->next) { + st->print( PTR_FORMAT "(" SIZE_FORMAT ") ", p2i(a->payload()), a->size); + } + st->cr(); + } +} + +void NMTPreInitAllocationTable::verify() const { + // This verifies the buildup of the lookup table, including the load and the chain lengths. + // We should see chain lens of 0-1 under normal conditions. Under artificial conditions + // (20000 VM args) we should see maybe 6-7. From a certain length on we can be sure something + // is broken. + const int longest_acceptable_chain_len = 30; + int num_chains_too_long = 0; + for (index_t i = 0; i < table_size; i++) { + int len = 0; + for (const NMTPreInitAllocation* a = _entries[i]; a != NULL; a = a->next) { + index_t i2 = index_for_key(a->payload()); + assert(i2 == i, "wrong hash"); + assert(a->size > 0, "wrong size"); + len++; + // very paranoid: search for dups + bool found = false; + for (const NMTPreInitAllocation* a2 = _entries[i]; a2 != NULL; a2 = a2->next) { + if (a == a2) { + assert(!found, "dup!"); + found = true; + } + } + } + if (len > longest_acceptable_chain_len) { + num_chains_too_long++; + } + } + if (num_chains_too_long > 0) { + assert(false, "NMT preinit lookup table degenerated (%d/%d chains longer than %d)", + num_chains_too_long, table_size, longest_acceptable_chain_len); + } +} +#endif // ASSERT + +// --------- NMTPreinit -------------- + +NMTPreInitAllocationTable* NMTPreInit::_table = NULL; +bool NMTPreInit::_nmt_was_initialized = false; + +// Some statistics +unsigned NMTPreInit::_num_mallocs_pre = 0; +unsigned NMTPreInit::_num_reallocs_pre = 0; +unsigned NMTPreInit::_num_frees_pre = 0; + +void NMTPreInit::create_table() { + assert(_table == NULL, "just once"); + void* p = raw_malloc(sizeof(NMTPreInitAllocationTable)); + _table = new(p) NMTPreInitAllocationTable(); +} + +// Allocate with os::malloc (hidden to prevent having to include os.hpp) +void* NMTPreInit::do_os_malloc(size_t size) { + return os::malloc(size, mtNMT); +} + +// Switches from NMT pre-init state to NMT post-init state; +// in post-init, no modifications to the lookup table are possible. +void NMTPreInit::pre_to_post() { + assert(_nmt_was_initialized == false, "just once"); + _nmt_was_initialized = true; + DEBUG_ONLY(verify();) +} + +#ifdef ASSERT +void NMTPreInit::verify() { + if (_table != NULL) { + _table->verify(); + } + assert(_num_reallocs_pre <= _num_mallocs_pre && + _num_frees_pre <= _num_mallocs_pre, "stats are off"); +} +#endif // ASSERT + +void NMTPreInit::print_state(outputStream* st) { + if (_table != NULL) { + _table->print_state(st); + st->cr(); + } + st->print_cr("pre-init mallocs: %u, pre-init reallocs: %u, pre-init frees: %u", + _num_mallocs_pre, _num_reallocs_pre, _num_frees_pre); +} + +#endif // INCLUDE_NMT diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/services/nmtPreInit.hpp openjdk-17-17.0.5+8/src/hotspot/share/services/nmtPreInit.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/services/nmtPreInit.hpp 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/services/nmtPreInit.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2021 SAP SE. All rights reserved. + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_SERVICES_NMT_PREINIT_HPP +#define SHARE_SERVICES_NMT_PREINIT_HPP + +#include "memory/allStatic.hpp" +#ifdef ASSERT +#include "runtime/atomic.hpp" +#endif +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +#if INCLUDE_NMT + +class outputStream; + +// NMTPreInit is the solution to a specific problem: +// +// NMT tracks C-heap allocations (os::malloc and friends). Those can happen at all VM life stages, +// including very early during the dynamic C++ initialization of the hotspot, and in CreateJavaVM +// before argument parsing. +// +// However, before the VM parses NMT arguments, we do not know whether NMT is enabled or not. Can we +// just ignore early allocations? If the only problem were statistical correctness, sure: footprint-wise +// they are not really relevant. +// +// But there is one big problem: NMT uses malloc headers to keep meta information of malloced blocks. +// We have to consider those in os::free() when calling free(3). +// +// So: +// 1) NMT off: +// a) pre-NMT-init allocations have no header +// b) post-NMT-init allocations have no header +// 2) NMT on: +// a) pre-NMT-init allocations have no header +// b) post-NMT-init allocations do have a header +// +// The problem is that inside os::free(p), we only get an opaque void* p; we do not know if p had been +// allocated in (a) or (b) phase. Therefore, we do not know if p is preceded by an NMT header which we +// would need to subtract from the pointer before calling free(3). There is no safe way to "guess" here +// without risking C-heap corruption. +// +// To solve this, we need a way to quickly determine, at os::free(p), whether p was a pre-NMT-init +// allocation. There are several ways to do this, see discussion under JDK-8256844. +// +// One of the easiest and most elegant ways is to store early allocation pointers in a lookup table. +// This is what NMTPreInit does. +// +////////////////////////////////////////////////////////////////////////// +// +// VM initialization wrt NMT: +// +//--------------------------------------------------------------- +//-> launcher dlopen's libjvm ^ +// -> dynamic C++ initialization | +// of libjvm | +// | +//-> launcher starts new thread (maybe) NMT pre-init phase : store allocated pointers in lookup table +// | +//-> launcher invokes CreateJavaVM | +// -> VM initialization before arg parsing | +// -> VM argument parsing v +// -> NMT initialization ------------------------------------- +// ^ +// ... | +// -> VM life... NMT post-init phase : lookup table is read-only; use it in os::free() and os::realloc(). +// ... | +// v +//---------------------------------------------------------------- +// +////////////////////////////////////////////////////////////////////////// +// +// Notes: +// - The VM will malloc() and realloc() several thousand times before NMT initialization. +// Starting with a lot of arguments increases this number since argument parsing strdups +// around a lot. +// - However, *surviving* allocations (allocations not freed immediately) are much rarer: +// typically only about 300-500. Again, mainly depending on the number of VM args. +// - There are a few cases of pre-to-post-init reallocs where pre-init allocations get +// reallocated after NMT initialization. Those we need to handle with special care (see +// NMTPreInit::handle_realloc()). Because of them we need to store allocation size with +// every pre-init allocation. + +// For the lookup table, design considerations are: +// - lookup speed is paramount since lookup is done for every os::free() call. +// - insert/delete speed only matters for VM startup - after NMT initialization the lookup +// table is readonly +// - memory consumption of the lookup table matters since we always pay for it, NMT on or off. +// - Obviously, nothing here can use *os::malloc*. Any dynamic allocations - if they cannot +// be avoided - should use raw malloc(3). +// +// We use a basic open hashmap, dimensioned generously - hash collisions should be very rare. +// The table is customized for holding malloced pointers. One main point of this map is that we do +// not allocate memory for the nodes themselves. Instead we piggy-back on the user allocation: +// the hashmap entry structure precedes, as a header, the malloced block. That way we avoid extra +// allocations just to hold the map nodes. This keeps runtime/memory overhead as small as possible. + +struct NMTPreInitAllocation { + NMTPreInitAllocation* next; + const size_t size; // (inner) payload size without header + // <-- USER ALLOCATION (PAYLOAD) STARTS HERE --> + + NMTPreInitAllocation(size_t size) : next(NULL), size(size) {}; + + // Returns start of the user data area + void* payload() { return this + 1; } + const void* payload() const { return this + 1; } + + // These functions do raw-malloc/realloc/free a C-heap block of given payload size, + // preceded with a NMTPreInitAllocation header. + static NMTPreInitAllocation* do_alloc(size_t payload_size); + static NMTPreInitAllocation* do_reallocate(NMTPreInitAllocation* old, size_t new_payload_size); + static void do_free(NMTPreInitAllocation* p); +}; + +class NMTPreInitAllocationTable { + + // Table_size: keep table size a prime and the hash function simple; this + // seems to give a good distribution for malloced pointers on all our libc variants. + // 8000ish is really plenty: normal VM runs have ~500 pre-init allocations to hold, + // VMs with insanely long command lines maybe ~700-1000. Which gives us an expected + // load factor of ~.1. Hash collisions should be very rare. + // ~8000 entries cost us ~64K for this table (64-bit), which is acceptable. + static const int table_size = 7919; + + NMTPreInitAllocation* _entries[table_size]; + + typedef int index_t; + const index_t invalid_index = -1; + + static unsigned calculate_hash(const void* p) { + uintptr_t tmp = p2i(p); + unsigned hash = (unsigned)tmp + LP64_ONLY( ^ (unsigned)(tmp >> 32)); + return hash; + } + + static index_t index_for_key(const void* p) { + const unsigned hash = calculate_hash(p); + return hash % table_size; + } + + const NMTPreInitAllocation* const * find_entry(const void* p) const { + return const_cast(this)->find_entry(p); + } + + NMTPreInitAllocation** find_entry(const void* p) { + const unsigned index = index_for_key(p); + NMTPreInitAllocation** aa = (&(_entries[index])); + while ((*aa) != NULL && (*aa)->payload() != p) { + aa = &((*aa)->next); + } + assert((*aa) == NULL || p == (*aa)->payload(), + "retrieve mismatch " PTR_FORMAT " vs " PTR_FORMAT ".", + p2i(p), p2i((*aa)->payload())); + return aa; + } + +public: + + NMTPreInitAllocationTable(); + + // Adds an entry to the table + void add(NMTPreInitAllocation* a) { + void* payload = a->payload(); + const unsigned index = index_for_key(payload); + assert(a->next == NULL, "entry already in table?"); + a->next = _entries[index]; // add to front + _entries[index] = a; // of list + assert(find(payload) == a, "add: reverse lookup error?"); + } + + // Find - but does not remove - an entry in this map. + // Returns NULL if not found. + const NMTPreInitAllocation* find(const void* p) const { + return *(find_entry(p)); + } + + // Find and removes an entry from the table. Asserts if not found. + NMTPreInitAllocation* find_and_remove(void* p) { + NMTPreInitAllocation** aa = find_entry(p); + assert((*aa) != NULL, "Entry not found: " PTR_FORMAT, p2i(p)); + NMTPreInitAllocation* a = (*aa); + (*aa) = (*aa)->next; // remove from its list + DEBUG_ONLY(a->next = NULL;) // mark as removed + return a; + } + + void print_state(outputStream* st) const; + DEBUG_ONLY(void print_map(outputStream* st) const;) + DEBUG_ONLY(void verify() const;) +}; + +// NMTPreInit is the outside interface to all of NMT preinit handling. +class NMTPreInit : public AllStatic { + + static NMTPreInitAllocationTable* _table; + static bool _nmt_was_initialized; + + // Some statistics + static unsigned _num_mallocs_pre; // Number of pre-init mallocs + static unsigned _num_reallocs_pre; // Number of pre-init reallocs + static unsigned _num_frees_pre; // Number of pre-init frees + + static void create_table(); + + static void add_to_map(NMTPreInitAllocation* a) { + assert(!_nmt_was_initialized, "lookup map cannot be modified after NMT initialization"); + // Only on add, we create the table on demand. Only needed on add, since everything should start + // with a call to os::malloc(). + if (_table == NULL) { + create_table(); + } + return _table->add(a); + } + + static const NMTPreInitAllocation* find_in_map(void* p) { + assert(_table != NULL, "stray allocation?"); + return _table->find(p); + } + + static NMTPreInitAllocation* find_and_remove_in_map(void* p) { + assert(!_nmt_was_initialized, "lookup map cannot be modified after NMT initialization"); + assert(_table != NULL, "stray allocation?"); + return _table->find_and_remove(p); + } + + // Just a wrapper for os::malloc to avoid including os.hpp here. + static void* do_os_malloc(size_t size); + +public: + + // Switches from NMT pre-init state to NMT post-init state; + // in post-init, no modifications to the lookup table are possible. + static void pre_to_post(); + + // Returns true if we are still in pre-init phase, false if post-init + static bool in_preinit_phase() { return _nmt_was_initialized == false; } + + // Called from os::malloc. + // Returns true if allocation was handled here; in that case, + // *rc contains the return address. + static bool handle_malloc(void** rc, size_t size) { + size = MAX2((size_t)1, size); // malloc(0) + if (!_nmt_was_initialized) { + // pre-NMT-init: + // Allocate entry and add address to lookup table + NMTPreInitAllocation* a = NMTPreInitAllocation::do_alloc(size); + add_to_map(a); + (*rc) = a->payload(); + _num_mallocs_pre++; + return true; + } + return false; + } + + // Called from os::realloc. + // Returns true if reallocation was handled here; in that case, + // *rc contains the return address. + static bool handle_realloc(void** rc, void* old_p, size_t new_size) { + if (old_p == NULL) { // realloc(NULL, n) + return handle_malloc(rc, new_size); + } + new_size = MAX2((size_t)1, new_size); // realloc(.., 0) + if (!_nmt_was_initialized) { + // pre-NMT-init: + // - the address must already be in the lookup table + // - find the old entry, remove from table, reallocate, add to table + NMTPreInitAllocation* a = find_and_remove_in_map(old_p); + a = NMTPreInitAllocation::do_reallocate(a, new_size); + add_to_map(a); + (*rc) = a->payload(); + _num_reallocs_pre++; + return true; + } else { + // post-NMT-init: + // If the old block was allocated during pre-NMT-init, we must relocate it: the + // new block must be allocated with "normal" os::malloc. + // We do this by: + // - look up (but not remove! lu table is read-only here.) the old entry + // - allocate new memory via os::malloc() + // - manually copy the old content over + // - return the new memory + // - The lu table is readonly so we keep the old address in the table. And we leave + // the old block allocated too, to prevent the libc from returning the same address + // and confusing us. + const NMTPreInitAllocation* a = find_in_map(old_p); + if (a != NULL) { // this was originally a pre-init allocation + void* p_new = do_os_malloc(new_size); + ::memcpy(p_new, a->payload(), MIN2(a->size, new_size)); + (*rc) = p_new; + return true; + } + } + return false; + } + + // Called from os::free. + // Returns true if free was handled here. + static bool handle_free(void* p) { + if (p == NULL) { // free(NULL) + return true; + } + if (!_nmt_was_initialized) { + // pre-NMT-init: + // - the allocation must be in the hash map, since all allocations went through + // NMTPreInit::handle_malloc() + // - find the old entry, unhang from map, free it + NMTPreInitAllocation* a = find_and_remove_in_map(p); + NMTPreInitAllocation::do_free(a); + _num_frees_pre++; + return true; + } else { + // post-NMT-init: + // - look up (but not remove! lu table is read-only here.) the entry + // - if found, we do nothing: the lu table is readonly, so we keep the old address + // in the table. We leave the block allocated to prevent the libc from returning + // the same address and confusing us. + // - if not found, we let regular os::free() handle this pointer + if (find_in_map(p) != NULL) { + return true; + } + } + return false; + } + + static void print_state(outputStream* st); + static void print_map(outputStream* st); + DEBUG_ONLY(static void verify();) +}; + +#endif // INCLUDE_NMT + +#endif // SHARE_SERVICES_NMT_PREINIT_HPP + diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/services/threadStackTracker.cpp openjdk-17-17.0.5+8/src/hotspot/share/services/threadStackTracker.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/services/threadStackTracker.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/services/threadStackTracker.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -33,7 +33,7 @@ volatile size_t ThreadStackTracker::_thread_count = 0; SortedLinkedList* ThreadStackTracker::_simple_thread_stacks = NULL; -bool ThreadStackTracker::late_initialize(NMT_TrackingLevel level) { +bool ThreadStackTracker::initialize(NMT_TrackingLevel level) { if (level == NMT_detail && !track_as_vm()) { _simple_thread_stacks = new (std::nothrow, ResourceObj::C_HEAP, mtNMT) SortedLinkedList(); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/services/threadStackTracker.hpp openjdk-17-17.0.5+8/src/hotspot/share/services/threadStackTracker.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/services/threadStackTracker.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/services/threadStackTracker.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -71,8 +71,7 @@ static int compare_thread_stack_base(const SimpleThreadStackSite& s1, const SimpleThreadStackSite& s2); static SortedLinkedList* _simple_thread_stacks; public: - // Late phase initialization - static bool late_initialize(NMT_TrackingLevel level); + static bool initialize(NMT_TrackingLevel level); static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to); static void new_thread_stack(void* base, size_t size, const NativeCallStack& stack); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/services/virtualMemoryTracker.cpp openjdk-17-17.0.5+8/src/hotspot/share/services/virtualMemoryTracker.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/services/virtualMemoryTracker.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/services/virtualMemoryTracker.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -320,14 +320,9 @@ } bool VirtualMemoryTracker::initialize(NMT_TrackingLevel level) { + assert(_reserved_regions == NULL, "only call once"); if (level >= NMT_summary) { VirtualMemorySummary::initialize(); - } - return true; -} - -bool VirtualMemoryTracker::late_initialize(NMT_TrackingLevel level) { - if (level >= NMT_summary) { _reserved_regions = new (std::nothrow, ResourceObj::C_HEAP, mtNMT) SortedLinkedList(); return (_reserved_regions != NULL); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/services/virtualMemoryTracker.hpp openjdk-17-17.0.5+8/src/hotspot/share/services/virtualMemoryTracker.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/services/virtualMemoryTracker.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/services/virtualMemoryTracker.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -371,9 +371,6 @@ public: static bool initialize(NMT_TrackingLevel level); - // Late phase initialization - static bool late_initialize(NMT_TrackingLevel level); - static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag = mtNone); static bool add_committed_region (address base_addr, size_t size, const NativeCallStack& stack); diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/utilities/bitMap.cpp openjdk-17-17.0.5+8/src/hotspot/share/utilities/bitMap.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/utilities/bitMap.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/utilities/bitMap.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -232,10 +232,10 @@ // With a valid range (beg <= end), this test ensures that end != 0, as // required by inverted_bit_mask_for_range. Also avoids an unnecessary write. if (beg != end) { - bm_word_t* pw = word_addr(beg); - bm_word_t w = *pw; - bm_word_t mr = inverted_bit_mask_for_range(beg, end); - bm_word_t nw = value ? (w | ~mr) : (w & mr); + volatile bm_word_t* pw = word_addr(beg); + bm_word_t w = Atomic::load(pw); + bm_word_t mr = inverted_bit_mask_for_range(beg, end); + bm_word_t nw = value ? (w | ~mr) : (w & mr); while (true) { bm_word_t res = Atomic::cmpxchg(pw, w, nw); if (res == w) break; diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/utilities/events.cpp openjdk-17-17.0.5+8/src/hotspot/share/utilities/events.cpp --- openjdk-17-17.0.4+8/src/hotspot/share/utilities/events.cpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/utilities/events.cpp 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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,6 +40,7 @@ StringEventLog* Events::_redefinitions = NULL; UnloadingEventLog* Events::_class_unloading = NULL; StringEventLog* Events::_deopt_messages = NULL; +StringEventLog* Events::_dll_messages = NULL; EventLog::EventLog() { // This normally done during bootstrap when we're only single @@ -97,6 +98,7 @@ _redefinitions = new StringEventLog("Classes redefined", "redef"); _class_unloading = new UnloadingEventLog("Classes unloaded", "unload"); _deopt_messages = new StringEventLog("Deoptimization events", "deopt"); + _dll_messages = new StringEventLog("Dll operation events", "dll"); } } diff -Nru openjdk-17-17.0.4+8/src/hotspot/share/utilities/events.hpp openjdk-17-17.0.5+8/src/hotspot/share/utilities/events.hpp --- openjdk-17-17.0.4+8/src/hotspot/share/utilities/events.hpp 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/hotspot/share/utilities/events.hpp 2022-10-10 13:07:22.000000000 +0000 @@ -230,6 +230,9 @@ // Deoptization related messages static StringEventLog* _deopt_messages; + // dynamic lib related messages + static StringEventLog* _dll_messages; + // Redefinition related messages static StringEventLog* _redefinitions; @@ -262,6 +265,8 @@ static void log_deopt_message(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3); + static void log_dll_message(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3); + // Register default loggers static void init(); }; @@ -322,6 +327,15 @@ va_end(ap); } } + +inline void Events::log_dll_message(Thread* thread, const char* format, ...) { + if (LogEvents && _dll_messages != NULL) { + va_list ap; + va_start(ap, format); + _dll_messages->logv(thread, format, ap); + va_end(ap); + } +} template inline void EventLogBase::print_log_on(outputStream* out, int max) { diff -Nru openjdk-17-17.0.4+8/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemFactory.java openjdk-17-17.0.5+8/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemFactory.java --- openjdk-17-17.0.4+8/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemFactory.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemFactory.java 2022-10-10 13:07:22.000000000 +0000 @@ -36,6 +36,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Objects; import java.util.function.Consumer; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -87,7 +88,10 @@ } catch (UncheckedIOException e) { return null; } + return create(optResult); + } + public static CgroupMetrics create(Optional optResult) { if (optResult.isEmpty()) { return null; } @@ -110,9 +114,9 @@ Map infos = result.getInfos(); if (result.isCgroupV2()) { // For unified it doesn't matter which controller we pick. - CgroupInfo anyController = infos.get(MEMORY_CTRL); - CgroupSubsystem subsystem = CgroupV2Subsystem.getInstance(anyController); - return subsystem != null ? new CgroupMetrics(subsystem) : null; + CgroupInfo anyController = infos.values().iterator().next(); + CgroupSubsystem subsystem = CgroupV2Subsystem.getInstance(Objects.requireNonNull(anyController)); + return new CgroupMetrics(subsystem); } else { CgroupV1Subsystem subsystem = CgroupV1Subsystem.getInstance(infos); return subsystem != null ? new CgroupV1MetricsImpl(subsystem) : null; @@ -145,6 +149,10 @@ } CgroupInfo info = CgroupInfo.fromCgroupsLine(line); switch (info.getName()) { + // Only the following controllers are important to Java. All + // other controllers (such as freezer) are ignored and + // are not considered in the checks below for + // anyCgroupsV1Controller/anyCgroupsV2Controller. case CPU_CTRL: infos.put(CPU_CTRL, info); break; case CPUACCT_CTRL: infos.put(CPUACCT_CTRL, info); break; case CPUSET_CTRL: infos.put(CPUSET_CTRL, info); break; @@ -222,6 +230,12 @@ */ private static void setCgroupV2Path(Map infos, String[] tokens) { + String name = tokens[1]; + if (!name.equals("")) { + // This must be a v1 controller that we have ignored (e.g., freezer) + assert infos.get(name) == null; + return; + } int hierarchyId = Integer.parseInt(tokens[0]); String cgroupPath = tokens[2]; for (CgroupInfo info: infos.values()) { diff -Nru openjdk-17-17.0.4+8/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java openjdk-17-17.0.5+8/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java --- openjdk-17-17.0.4+8/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java 2022-10-10 13:07:22.000000000 +0000 @@ -150,8 +150,9 @@ } private static boolean getSwapEnabled(CgroupV1MemorySubSystemController controller) { - long retval = getLongValue(controller, "memory.memsw.limit_in_bytes"); - return retval > 0; + long memswBytes = getLongValue(controller, "memory.memsw.limit_in_bytes"); + long swappiness = getLongValue(controller, "memory.swappiness"); + return (memswBytes > 0 && swappiness > 0); } diff -Nru openjdk-17-17.0.4+8/src/java.base/macosx/classes/jdk/internal/loader/ClassLoaderHelper.java openjdk-17-17.0.5+8/src/java.base/macosx/classes/jdk/internal/loader/ClassLoaderHelper.java --- openjdk-17-17.0.4+8/src/java.base/macosx/classes/jdk/internal/loader/ClassLoaderHelper.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/macosx/classes/jdk/internal/loader/ClassLoaderHelper.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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,8 @@ try { major = Integer.parseInt(i < 0 ? osVersion : osVersion.substring(0, i)); } catch (NumberFormatException e) {} - hasDynamicLoaderCache = major >= 11; + // SDK 10.15 and earlier always reports 10.16 instead of 11.x.x + hasDynamicLoaderCache = major >= 11 || osVersion.equals("10.16"); } private ClassLoaderHelper() {} diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java openjdk-17-17.0.5+8/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -344,6 +344,8 @@ } else { // Array too short, pad it w/ leading 0s if (secret.length < expectedLen) { + Arrays.fill(sharedSecret, offset, + offset + (expectedLen - secret.length), (byte)0); System.arraycopy(secret, 0, sharedSecret, offset + (expectedLen - secret.length), secret.length); diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/com/sun/security/ntlm/Client.java openjdk-17-17.0.5+8/src/java.base/share/classes/com/sun/security/ntlm/Client.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/com/sun/security/ntlm/Client.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/com/sun/security/ntlm/Client.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2022, 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 @@ -117,9 +117,10 @@ * {@code nonce} is null for NTLM v1. */ public byte[] type3(byte[] type2, byte[] nonce) throws NTLMException { - if (type2 == null || (v != Version.NTLM && nonce == null)) { + if (type2 == null || (v != Version.NTLM && nonce == null) || + (nonce != null && nonce.length != 8)) { throw new NTLMException(NTLMException.PROTOCOL, - "type2 and nonce cannot be null"); + "type2 cannot be null, and nonce must be 8-byte long"); } debug("NTLM Client: Type 2 received\n"); debug(type2); diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/com/sun/security/ntlm/NTLMException.java openjdk-17-17.0.5+8/src/java.base/share/classes/com/sun/security/ntlm/NTLMException.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/com/sun/security/ntlm/NTLMException.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/com/sun/security/ntlm/NTLMException.java 2022-10-10 13:07:22.000000000 +0000 @@ -65,6 +65,11 @@ */ public static final int PROTOCOL = 6; + /** + * If an invalid input is provided. + */ + public static final int INVALID_INPUT = 7; + private int errorCode; /** diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/com/sun/security/ntlm/NTLM.java openjdk-17-17.0.5+8/src/java.base/share/classes/com/sun/security/ntlm/NTLM.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/com/sun/security/ntlm/NTLM.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/com/sun/security/ntlm/NTLM.java 2022-10-10 13:07:22.000000000 +0000 @@ -226,23 +226,27 @@ System.arraycopy(data, 0, internal, offset, data.length); } - void writeSecurityBuffer(int offset, byte[] data) { + void writeSecurityBuffer(int offset, byte[] data) throws NTLMException { if (data == null) { - writeShort(offset+4, current); + writeInt(offset+4, current); } else { int len = data.length; + if (len > 65535) { + throw new NTLMException(NTLMException.INVALID_INPUT, + "Invalid data length " + len); + } if (current + len > internal.length) { internal = Arrays.copyOf(internal, current + len + 256); } writeShort(offset, len); writeShort(offset+2, len); - writeShort(offset+4, current); + writeInt(offset+4, current); System.arraycopy(data, 0, internal, current, len); current += len; } } - void writeSecurityBuffer(int offset, String str, boolean unicode) { + void writeSecurityBuffer(int offset, String str, boolean unicode) throws NTLMException { writeSecurityBuffer(offset, str == null ? null : str.getBytes( unicode ? StandardCharsets.UTF_16LE : StandardCharsets.ISO_8859_1)); diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/com/sun/security/ntlm/Server.java openjdk-17-17.0.5+8/src/java.base/share/classes/com/sun/security/ntlm/Server.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/com/sun/security/ntlm/Server.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/com/sun/security/ntlm/Server.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2022, 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 @@ -85,9 +85,9 @@ * {@code nonce} is null. */ public byte[] type2(byte[] type1, byte[] nonce) throws NTLMException { - if (nonce == null) { + if (nonce == null || nonce.length != 8) { throw new NTLMException(NTLMException.PROTOCOL, - "nonce cannot be null"); + "nonce must be 8-byte long"); } debug("NTLM Server: Type 1 received\n"); if (type1 != null) debug(type1); diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java openjdk-17-17.0.5+8/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java 2022-10-10 13:07:22.000000000 +0000 @@ -282,8 +282,8 @@ * registers the lambda proxy class for including into the CDS archive. */ private Class spinInnerClass() throws LambdaConversionException { - // CDS does not handle disableEagerInitialization. - if (!disableEagerInitialization) { + // CDS does not handle disableEagerInitialization or useImplMethodHandle + if (!disableEagerInitialization && !useImplMethodHandle) { // include lambda proxy class in CDS archive at dump time if (CDS.isDumpingArchive()) { Class innerClass = generateInnerClass(); diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/java/math/BigDecimal.java openjdk-17-17.0.5+8/src/java.base/share/classes/java/math/BigDecimal.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/java/math/BigDecimal.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/java/math/BigDecimal.java 2022-10-10 13:07:22.000000000 +0000 @@ -31,6 +31,10 @@ import static java.math.BigInteger.LONG_MASK; import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.ObjectStreamException; +import java.io.StreamCorruptedException; import java.util.Arrays; import java.util.Objects; @@ -1059,6 +1063,15 @@ } /** + * Accept no subclasses. + */ + private static BigInteger toStrictBigInteger(BigInteger val) { + return (val.getClass() == BigInteger.class) ? + val : + new BigInteger(val.toByteArray().clone()); + } + + /** * Translates a {@code BigInteger} into a {@code BigDecimal}. * The scale of the {@code BigDecimal} is zero. * @@ -1067,8 +1080,8 @@ */ public BigDecimal(BigInteger val) { scale = 0; - intVal = val; - intCompact = compactValFor(val); + intVal = toStrictBigInteger(val); + intCompact = compactValFor(intVal); } /** @@ -1082,7 +1095,7 @@ * @since 1.5 */ public BigDecimal(BigInteger val, MathContext mc) { - this(val,0,mc); + this(toStrictBigInteger(val), 0, mc); } /** @@ -1096,8 +1109,8 @@ */ public BigDecimal(BigInteger unscaledVal, int scale) { // Negative scales are now allowed - this.intVal = unscaledVal; - this.intCompact = compactValFor(unscaledVal); + this.intVal = toStrictBigInteger(unscaledVal); + this.intCompact = compactValFor(this.intVal); this.scale = scale; } @@ -1115,6 +1128,7 @@ * @since 1.5 */ public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) { + unscaledVal = toStrictBigInteger(unscaledVal); long compactVal = compactValFor(unscaledVal); int mcp = mc.precision; int prec = 0; @@ -4257,9 +4271,13 @@ = unsafe.objectFieldOffset(BigDecimal.class, "intCompact"); private static final long intValOffset = unsafe.objectFieldOffset(BigDecimal.class, "intVal"); + private static final long scaleOffset + = unsafe.objectFieldOffset(BigDecimal.class, "scale"); - static void setIntCompact(BigDecimal bd, long val) { - unsafe.putLong(bd, intCompactOffset, val); + static void setIntValAndScale(BigDecimal bd, BigInteger intVal, int scale) { + unsafe.putReference(bd, intValOffset, intVal); + unsafe.putInt(bd, scaleOffset, scale); + unsafe.putLong(bd, intCompactOffset, compactValFor(intVal)); } static void setIntValVolatile(BigDecimal bd, BigInteger val) { @@ -4278,15 +4296,30 @@ @java.io.Serial private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { - // Read in all fields - s.defaultReadObject(); - // validate possibly bad fields - if (intVal == null) { - String message = "BigDecimal: null intVal in stream"; - throw new java.io.StreamCorruptedException(message); - // [all values of scale are now allowed] + // prepare to read the fields + ObjectInputStream.GetField fields = s.readFields(); + BigInteger serialIntVal = (BigInteger) fields.get("intVal", null); + + // Validate field data + if (serialIntVal == null) { + throw new StreamCorruptedException("Null or missing intVal in BigDecimal stream"); } - UnsafeHolder.setIntCompact(this, compactValFor(intVal)); + // Validate provenance of serialIntVal object + serialIntVal = toStrictBigInteger(serialIntVal); + + // Any integer value is valid for scale + int serialScale = fields.get("scale", 0); + + UnsafeHolder.setIntValAndScale(this, serialIntVal, serialScale); + } + + /** + * Serialization without data not supported for this class. + */ + @java.io.Serial + private void readObjectNoData() + throws ObjectStreamException { + throw new InvalidObjectException("Deserialized BigDecimal objects need data"); } /** diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/java/math/BigInteger.java openjdk-17-17.0.5+8/src/java.base/share/classes/java/math/BigInteger.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/java/math/BigInteger.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/java/math/BigInteger.java 2022-10-10 13:07:22.000000000 +0000 @@ -30,9 +30,11 @@ package java.math; import java.io.IOException; +import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamField; +import java.io.ObjectStreamException; import java.util.Arrays; import java.util.Objects; import java.util.Random; @@ -4706,17 +4708,21 @@ // prepare to read the alternate persistent fields ObjectInputStream.GetField fields = s.readFields(); - // Read the alternate persistent fields that we care about - int sign = fields.get("signum", -2); - byte[] magnitude = (byte[])fields.get("magnitude", null); + // Read and validate the alternate persistent fields that we + // care about, signum and magnitude - // Validate signum + // Read and validate signum + int sign = fields.get("signum", -2); if (sign < -1 || sign > 1) { String message = "BigInteger: Invalid signum value"; if (fields.defaulted("signum")) message = "BigInteger: Signum not present in stream"; throw new java.io.StreamCorruptedException(message); } + + // Read and validate magnitude + byte[] magnitude = (byte[])fields.get("magnitude", null); + magnitude = magnitude.clone(); // defensive copy int[] mag = stripLeadingZeroBytes(magnitude, 0, magnitude.length); if ((mag.length == 0) != (sign == 0)) { String message = "BigInteger: signum-magnitude mismatch"; @@ -4725,18 +4731,24 @@ throw new java.io.StreamCorruptedException(message); } + // Equivalent to checkRange() on mag local without assigning + // this.mag field + if (mag.length > MAX_MAG_LENGTH || + (mag.length == MAX_MAG_LENGTH && mag[0] < 0)) { + throw new java.io.StreamCorruptedException("BigInteger: Out of the supported range"); + } + // Commit final fields via Unsafe - UnsafeHolder.putSign(this, sign); + UnsafeHolder.putSignAndMag(this, sign, mag); + } - // Calculate mag field from magnitude and discard magnitude - UnsafeHolder.putMag(this, mag); - if (mag.length >= MAX_MAG_LENGTH) { - try { - checkRange(); - } catch (ArithmeticException e) { - throw new java.io.StreamCorruptedException("BigInteger: Out of the supported range"); - } - } + /** + * Serialization without data not supported for this class. + */ + @java.io.Serial + private void readObjectNoData() + throws ObjectStreamException { + throw new InvalidObjectException("Deserialized BigInteger objects need data"); } // Support for resetting final fields while deserializing @@ -4748,11 +4760,8 @@ private static final long magOffset = unsafe.objectFieldOffset(BigInteger.class, "mag"); - static void putSign(BigInteger bi, int sign) { + static void putSignAndMag(BigInteger bi, int sign, int[] magnitude) { unsafe.putInt(bi, signumOffset, sign); - } - - static void putMag(BigInteger bi, int[] magnitude) { unsafe.putReference(bi, magOffset, magnitude); } } diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/java/net/doc-files/net-properties.html openjdk-17-17.0.5+8/src/java.base/share/classes/java/net/doc-files/net-properties.html --- openjdk-17-17.0.4+8/src/java.base/share/classes/java/net/doc-files/net-properties.html 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/java/net/doc-files/net-properties.html 2022-10-10 13:07:22.000000000 +0000 @@ -176,6 +176,16 @@ If HTTP keepalive is enabled (see above) this value determines the maximum number of idle connections that will be simultaneously kept alive, per destination.

+
  • {@systemProperty http.keepAlive.time.server} and + {@systemProperty http.keepAlive.time.proxy}

    +

    These properties modify the behavior of the HTTP keepalive cache in the case + where the server (or proxy) has not specified a keepalive time. If the + property is set in this case, then idle connections will be closed after the + specified number of seconds. If the property is set, and the server does + specify a keepalive time in a "Keep-Alive" response header, then the time specified + by the server is used. If the property is not set and also the server + does not specify a keepalive time, then connections are kept alive for an + implementation defined time, assuming {@code http.keepAlive} is {@code true}.

  • {@systemProperty http.maxRedirects} (default: {@code 20})
    This integer value determines the maximum number, for a given request, of HTTP redirects that will be automatically followed by the diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/java/security/UnresolvedPermission.java openjdk-17-17.0.5+8/src/java.base/share/classes/java/security/UnresolvedPermission.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/java/security/UnresolvedPermission.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/java/security/UnresolvedPermission.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -153,7 +153,7 @@ * Each chain is ordered bottom-to-top (i.e., with the signer certificate * first and the (root) certificate authority last). The signer * certificates are copied from the array. Subsequent changes to - * the array will not affect this UnsolvedPermission. + * the array will not affect this UnresolvedPermission. */ public UnresolvedPermission(String type, String name, @@ -165,59 +165,63 @@ if (type == null) throw new NullPointerException("type can't be null"); + // Perform a defensive copy and reassign certs if we have a non-null + // reference + if (certs != null) { + certs = certs.clone(); + } + this.type = type; this.name = name; this.actions = actions; + if (certs != null) { // Extract the signer certs from the list of certificates. - for (int i=0; i signerCerts = - new ArrayList<>(); - i = 0; - while (i < certs.length) { - signerCerts.add(certs[i]); - while (((i+1) < certs.length) && - ((X509Certificate)certs[i]).getIssuerX500Principal().equals( - ((X509Certificate)certs[i+1]).getSubjectX500Principal())) { - i++; - } - i++; - } - this.certs = - new java.security.cert.Certificate[signerCerts.size()]; - signerCerts.toArray(this.certs); + i++; + } + if (count == certs.length) { + // All the certs are signer certs, so we store the entire + // array. No further processing is needed. + this.certs = certs; + return; + } + + // extract the signer certs + ArrayList signerCerts = + new ArrayList<>(); + i = 0; + while (i < certs.length) { + signerCerts.add(certs[i]); + while (((i + 1) < certs.length) && + ((X509Certificate)certs[i]).getIssuerX500Principal().equals( + ((X509Certificate)certs[i + 1]).getSubjectX500Principal())) { + i++; } + i++; } + this.certs = + new java.security.cert.Certificate[signerCerts.size()]; + signerCerts.toArray(this.certs); } } @@ -310,6 +314,7 @@ * * @return false. */ + @Override public boolean implies(Permission p) { return false; } @@ -330,6 +335,7 @@ * type (class) name, permission name, actions, and * certificates as this object. */ + @Override public boolean equals(Object obj) { if (obj == this) return true; @@ -402,7 +408,7 @@ * * @return a hash code value for this object. */ - + @Override public int hashCode() { int hash = type.hashCode(); if (name != null) @@ -422,6 +428,7 @@ * * @return the empty string "". */ + @Override public String getActions() { return ""; @@ -489,6 +496,7 @@ * * @return information about this UnresolvedPermission. */ + @Override public String toString() { return "(unresolved " + type + " " + name + " " + actions + ")"; } @@ -500,7 +508,7 @@ * @return a new PermissionCollection object suitable for * storing UnresolvedPermissions. */ - + @Override public PermissionCollection newPermissionCollection() { return new UnresolvedPermissionCollection(); } diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java openjdk-17-17.0.5+8/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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 @@ -645,7 +645,7 @@ if (origin < bound) { r = r * (bound - origin) + origin; if (r >= bound) // may need to correct a rounding problem - r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1); + r = Math.nextAfter(bound, origin); } return r; } @@ -677,7 +677,7 @@ double r = rng.nextDouble(); r = r * bound; if (r >= bound) // may need to correct a rounding problem - r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1); + r = Math.nextDown(bound); return r; } diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/module-info.java openjdk-17-17.0.5+8/src/java.base/share/classes/module-info.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/module-info.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/module-info.java 2022-10-10 13:07:22.000000000 +0000 @@ -319,7 +319,8 @@ jdk.crypto.ec, jdk.security.auth; exports sun.security.provider.certpath to - java.naming; + java.naming, + jdk.jartool; exports sun.security.rsa to jdk.crypto.cryptoki; exports sun.security.timestamp to diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/net/www/http/HttpClient.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/net/www/http/HttpClient.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/net/www/http/HttpClient.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/net/www/http/HttpClient.java 2022-10-10 13:07:22.000000000 +0000 @@ -122,13 +122,13 @@ recomputing the value of keepingAlive */ int keepAliveConnections = -1; /* number of keep-alives left */ - /**Idle timeout value, in milliseconds. Zero means infinity, - * iff keepingAlive=true. - * Unfortunately, we can't always believe this one. If I'm connected - * through a Netscape proxy to a server that sent me a keep-alive - * time of 15 sec, the proxy unilaterally terminates my connection - * after 5 sec. So we have to hard code our effective timeout to - * 4 sec for the case where we're using a proxy. *SIGH* + /* + * The timeout if specified by the server. Following values possible + * 0: the server specified no keep alive headers + * -1: the server provided "Connection: keep-alive" but did not specify a + * a particular time in a "Keep-Alive:" headers + * Positive values are the number of seconds specified by the server + * in a "Keep-Alive" header */ int keepAliveTimeout = 0; @@ -235,7 +235,6 @@ return keepAliveProp; } - public String getSpnegoCBT() { return spnegoCBT; } @@ -898,7 +897,7 @@ responses.findValue("Keep-Alive")); /* default should be larger in case of proxy */ keepAliveConnections = p.findInt("max", usingProxy?50:5); - keepAliveTimeout = p.findInt("timeout", usingProxy?60:5); + keepAliveTimeout = p.findInt("timeout", -1); } } else if (b[7] != '0') { /* @@ -1151,6 +1150,10 @@ } } + public boolean getUsingProxy() { + return usingProxy; + } + /** * @return the proxy port being used for this client. Meaningless * if getProxyHostUsed() gives null. diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/net/www/http/KeepAliveCache.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/net/www/http/KeepAliveCache.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/net/www/http/KeepAliveCache.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/net/www/http/KeepAliveCache.java 2022-10-10 13:07:22.000000000 +0000 @@ -41,6 +41,8 @@ import jdk.internal.misc.InnocuousThread; import sun.security.action.GetIntegerAction; +import sun.net.www.protocol.http.HttpURLConnection; +import sun.util.logging.PlatformLogger; /** * A class that implements a cache of idle Http connections for keep-alive @@ -54,6 +56,32 @@ @java.io.Serial private static final long serialVersionUID = -2937172892064557949L; + // Keep alive time set according to priority specified here: + // 1. If server specifies a time with a Keep-Alive header + // 2. If user specifies a time with system property below + // 3. Default values which depend on proxy vs server and whether + // a Connection: keep-alive header was sent by server + + // name suffixed with "server" or "proxy" + private static final String keepAliveProp = "http.keepAlive.time."; + + private static final int userKeepAliveServer; + private static final int userKeepAliveProxy; + + static final PlatformLogger logger = HttpURLConnection.getHttpLogger(); + + @SuppressWarnings("removal") + static int getUserKeepAliveSeconds(String type) { + int v = AccessController.doPrivileged( + new GetIntegerAction(keepAliveProp+type, -1)).intValue(); + return v < -1 ? -1 : v; + } + + static { + userKeepAliveServer = getUserKeepAliveSeconds("server"); + userKeepAliveProxy = getUserKeepAliveSeconds("proxy"); + } + /* maximum # keep-alive connections to maintain at once * This should be 2 by the HTTP spec, but because we don't support pipe-lining * a larger value is more appropriate. So we now set a default of 5, and the value @@ -126,10 +154,29 @@ if (v == null) { int keepAliveTimeout = http.getKeepAliveTimeout(); - v = new ClientVector(keepAliveTimeout > 0 ? - keepAliveTimeout * 1000 : LIFETIME); - v.put(http); - super.put(key, v); + if (keepAliveTimeout == 0) { + keepAliveTimeout = getUserKeepAlive(http.getUsingProxy()); + if (keepAliveTimeout == -1) { + // same default for server and proxy + keepAliveTimeout = 5; + } + } else if (keepAliveTimeout == -1) { + keepAliveTimeout = getUserKeepAlive(http.getUsingProxy()); + if (keepAliveTimeout == -1) { + // different default for server and proxy + keepAliveTimeout = http.getUsingProxy() ? 60 : 5; + } + } + // at this point keepAliveTimeout is the number of seconds to keep + // alive, which could be 0, if the user specified 0 for the property + assert keepAliveTimeout >= 0; + if (keepAliveTimeout == 0) { + http.closeServer(); + } else { + v = new ClientVector(keepAliveTimeout * 1000); + v.put(http); + super.put(key, v); + } } else { v.put(http); } @@ -138,6 +185,11 @@ } } + // returns the keep alive set by user in system property or -1 if not set + private static int getUserKeepAlive(boolean isProxy) { + return isProxy ? userKeepAliveProxy : userKeepAliveServer; + } + /* remove an obsolete HttpClient from its VectorCache */ public void remove(HttpClient h, Object obj) { cacheLock.lock(); @@ -276,6 +328,11 @@ e.hc.closeServer(); } else { hc = e.hc; + if (KeepAliveCache.logger.isLoggable(PlatformLogger.Level.FINEST)) { + String msg = "cached HttpClient was idle for " + + Long.toString(currentTime - e.idleStartTime); + KeepAliveCache.logger.finest(msg); + } } } while ((hc == null) && (!isEmpty())); return hc; diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java 2022-10-10 13:07:22.000000000 +0000 @@ -76,10 +76,12 @@ /** * A map containing the algorithms in this SignerInfo. This is used to * avoid checking algorithms to see if they are disabled more than once. - * The key is the AlgorithmId of the algorithm, and the value is the name of - * the field or attribute. + * The key is the AlgorithmId of the algorithm, and the value is a record + * containing the name of the field or attribute and whether the key + * should also be checked (ex: if it is a signature algorithm). */ - private Map algorithms = new HashMap<>(); + private record AlgorithmInfo(String field, boolean checkKey) {} + private Map algorithms = new HashMap<>(); public SignerInfo(X500Name issuerName, BigInteger serial, @@ -350,7 +352,8 @@ } String digestAlgName = digestAlgorithmId.getName(); - algorithms.put(digestAlgorithmId, "SignerInfo digestAlgorithm field"); + algorithms.put(digestAlgorithmId, + new AlgorithmInfo("SignerInfo digestAlgorithm field", false)); byte[] dataSigned; @@ -428,7 +431,8 @@ new AlgorithmId(ObjectIdentifier.of(oid), digestEncryptionAlgorithmId.getParameters()); algorithms.put(sigAlgId, - "SignerInfo digestEncryptionAlgorithm field"); + new AlgorithmInfo( + "SignerInfo digestEncryptionAlgorithm field", true)); } X509Certificate cert = getCertificate(block); @@ -685,7 +689,8 @@ throws NoSuchAlgorithmException, SignatureException { AlgorithmId digestAlgId = token.getHashAlgorithm(); - algorithms.put(digestAlgId, "TimestampToken digestAlgorithm field"); + algorithms.put(digestAlgId, + new AlgorithmInfo("TimestampToken digestAlgorithm field", false)); MessageDigest md = MessageDigest.getInstance(digestAlgId.getName()); @@ -742,18 +747,19 @@ */ public static Set verifyAlgorithms(SignerInfo[] infos, JarConstraintsParameters params, String name) throws SignatureException { - Map algorithms = new HashMap<>(); + Map algorithms = new HashMap<>(); for (SignerInfo info : infos) { algorithms.putAll(info.algorithms); } Set enabledAlgorithms = new HashSet<>(); try { - for (Map.Entry algorithm : algorithms.entrySet()) { - params.setExtendedExceptionMsg(name, algorithm.getValue()); - AlgorithmId algId = algorithm.getKey(); + for (var algEntry : algorithms.entrySet()) { + AlgorithmInfo info = algEntry.getValue(); + params.setExtendedExceptionMsg(name, info.field()); + AlgorithmId algId = algEntry.getKey(); JAR_DISABLED_CHECK.permits(algId.getName(), - algId.getParameters(), params); + algId.getParameters(), params, info.checkKey()); enabledAlgorithms.add(algId.getName()); } } catch (CertPathValidatorException e) { diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2021, 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 @@ -38,7 +38,6 @@ import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; import java.security.cert.Certificate; -import java.security.cert.X509CRL; import java.security.cert.X509Certificate; import java.security.cert.PKIXCertPathChecker; import java.security.cert.TrustAnchor; @@ -57,7 +56,6 @@ import sun.security.validator.Validator; import sun.security.x509.AlgorithmId; import sun.security.x509.X509CertImpl; -import sun.security.x509.X509CRLImpl; /** * A {@code PKIXCertPathChecker} implementation to check whether a @@ -131,7 +129,7 @@ * certificate * @param constraints the algorithm constraints (or null) * @param date the date specified by the PKIXParameters date, or the - * JAR timestamp if jar files are being validated and the + * timestamp if JAR files are being validated and the * JAR is timestamped. May be null if no timestamp or * PKIXParameter date is set. * @param variant the Validator variant of the operation. A null value @@ -160,17 +158,19 @@ /** * Create a new {@code AlgorithmChecker} with the given {@code TrustAnchor}, - * {@code PKIXParameter} date, and {@code varient} + * {@code PKIXParameter} date, and {@code variant}. * * @param anchor the trust anchor selected to validate the target * certificate - * @param pkixdate Date the constraints are checked against. The value is - * either the PKIXParameters date or null for the current date. + * @param date the date specified by the PKIXParameters date, or the + * timestamp if JAR files are being validated and the + * JAR is timestamped. May be null if no timestamp or + * PKIXParameter date is set. * @param variant the Validator variant of the operation. A null value * passed will set it to Validator.GENERIC. */ - public AlgorithmChecker(TrustAnchor anchor, Date pkixdate, String variant) { - this(anchor, certPathDefaultConstraints, pkixdate, variant); + public AlgorithmChecker(TrustAnchor anchor, Date date, String variant) { + this(anchor, certPathDefaultConstraints, date, variant); } @Override @@ -283,13 +283,13 @@ // Check against local constraints if it is DisabledAlgorithmConstraints if (constraints instanceof DisabledAlgorithmConstraints) { ((DisabledAlgorithmConstraints)constraints).permits(currSigAlg, - currSigAlgParams, cp); + currSigAlgParams, cp, true); // DisabledAlgorithmsConstraints does not check primitives, so key // additional key check. } else { // Perform the default constraints checking anyway. - certPathDefaultConstraints.permits(currSigAlg, currSigAlgParams, cp); + certPathDefaultConstraints.permits(currSigAlg, currSigAlgParams, cp, true); // Call locally set constraints to check key with primitives. if (!constraints.permits(primitives, currPubKey)) { throw new CertPathValidatorException( @@ -379,29 +379,6 @@ * Check the signature algorithm with the specified public key. * * @param key the public key to verify the CRL signature - * @param crl the target CRL - * @param variant the Validator variant of the operation. A null value - * passed will set it to Validator.GENERIC. - * @param anchor the trust anchor selected to validate the CRL issuer - */ - static void check(PublicKey key, X509CRL crl, String variant, - TrustAnchor anchor) throws CertPathValidatorException { - - X509CRLImpl x509CRLImpl = null; - try { - x509CRLImpl = X509CRLImpl.toImpl(crl); - } catch (CRLException ce) { - throw new CertPathValidatorException(ce); - } - - AlgorithmId algorithmId = x509CRLImpl.getSigAlgId(); - check(key, algorithmId, variant, anchor); - } - - /** - * Check the signature algorithm with the specified public key. - * - * @param key the public key to verify the CRL signature * @param algorithmId signature algorithm Algorithm ID * @param variant the Validator variant of the operation. A null * value passed will set it to Validator.GENERIC. @@ -412,7 +389,7 @@ certPathDefaultConstraints.permits(algorithmId.getName(), algorithmId.getParameters(), - new CertPathConstraintsParameters(key, variant, anchor)); + new CertPathConstraintsParameters(key, variant, anchor), true); } } diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/provider/certpath/CertPathConstraintsParameters.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/provider/certpath/CertPathConstraintsParameters.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/provider/certpath/CertPathConstraintsParameters.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/provider/certpath/CertPathConstraintsParameters.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, 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 @@ * constraints specified in the jdk.certpath.disabledAlgorithms security * property. */ -class CertPathConstraintsParameters implements ConstraintsParameters { +public class CertPathConstraintsParameters implements ConstraintsParameters { // The public key of the certificate private final Key key; // The certificate's trust anchor which will be checked against the @@ -103,7 +103,7 @@ @Override public String toString() { StringBuilder sb = new StringBuilder("[\n"); - sb.append("\n Variant: ").append(variant); + sb.append(" Variant: ").append(variant); if (anchor != null) { sb.append("\n Anchor: ").append(anchor); } diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java 2022-10-10 13:07:22.000000000 +0000 @@ -691,7 +691,8 @@ // check the crl signature algorithm try { - AlgorithmChecker.check(prevKey, crl, variant, anchor); + AlgorithmChecker.check(prevKey, crlImpl.getSigAlgId(), + variant, anchor); } catch (CertPathValidatorException cpve) { if (debug != null) { debug.println("CRL signature algorithm check failed: " + cpve); diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, 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 @@ -176,8 +176,8 @@ List certPathCheckers = new ArrayList<>(); // add standard checkers that we will be using certPathCheckers.add(untrustedChecker); - certPathCheckers.add(new AlgorithmChecker(anchor, null, params.date(), - params.variant())); + certPathCheckers.add(new AlgorithmChecker(anchor, null, + params.timestamp(), params.variant())); certPathCheckers.add(new KeyChecker(certPathLen, params.targetCertConstraints())); certPathCheckers.add(new ConstraintsChecker(certPathLen)); diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/provider/certpath/PKIX.java 2022-10-10 13:07:22.000000000 +0000 @@ -88,6 +88,7 @@ private Set anchors; private List certs; private Timestamp timestamp; + private Date timestampDate; private String variant = Validator.VAR_GENERIC; ValidatorParams(CertPath cp, PKIXParameters params) @@ -154,10 +155,20 @@ stores = params.getCertStores(); return stores; } + // The date() param is used when enforcing the validity period + // of certificates and when checking the time period of revocation data. + // The main difference between the date() and timestamp() method is + // that the date() method only uses the timestamp (if specified) + // for certificates in a code signer's chain. Date date() { if (!gotDate) { - // use timestamp if checking signed code that is - // timestamped, otherwise use date parameter + // Use timestamp if checking signed code that is + // timestamped, otherwise use date parameter. + // Note that TSA server certificates do not use the + // timestamp, which means that an expired TSA certificate + // is considered a validation failure. This policy means + // that signed and timestamped code is valid until the TSA + // certificate expires (assuming all other checks are valid). if (timestamp != null && (variant.equals(Validator.VAR_CODE_SIGNING) || variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING))) { @@ -210,6 +221,17 @@ String variant() { return variant; } + // The timestamp() param is passed as the date param when creating an + // AlgorithmChecker. An AlgorithmChecker always uses the timestamp + // if specified in order to enforce the denyAfter constraint. + Date timestamp() { + // return timestamp date if set, otherwise use date parameter + if (timestampDate == null) { + timestampDate = (timestamp != null) + ? timestamp.getTimestamp() : date(); + } + return timestampDate; + } } static class BuilderParams extends ValidatorParams { diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, 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 @@ -344,7 +344,7 @@ // add the algorithm checker checkers.add(new AlgorithmChecker(builder.trustAnchor, - buildParams.date(), buildParams.variant())); + buildParams.timestamp(), buildParams.variant())); BasicChecker basicChecker = null; if (nextState.keyParamsNeeded()) { diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ -164,7 +164,7 @@ this.conContext = conContext; this.sslConfig = (SSLConfiguration)conContext.sslConfig.clone(); - this.algorithmConstraints = new SSLAlgorithmConstraints( + this.algorithmConstraints = SSLAlgorithmConstraints.wrap( sslConfig.userSpecifiedAlgorithmConstraints); this.activeProtocols = getActiveProtocols(sslConfig.enabledProtocols, sslConfig.enabledCipherSuites, algorithmConstraints); diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2022, 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 @@ -57,46 +57,98 @@ // the default algorithm constraints static final AlgorithmConstraints DEFAULT = - new SSLAlgorithmConstraints(null); + new SSLAlgorithmConstraints(null, true); // the default SSL only algorithm constraints static final AlgorithmConstraints DEFAULT_SSL_ONLY = - new SSLAlgorithmConstraints((SSLSocket)null, false); + new SSLAlgorithmConstraints(null, false); - SSLAlgorithmConstraints(AlgorithmConstraints userSpecifiedConstraints) { - this.userSpecifiedConstraints = userSpecifiedConstraints; - this.peerSpecifiedConstraints = null; - this.enabledX509DisabledAlgConstraints = true; + private SSLAlgorithmConstraints(AlgorithmConstraints userSpecifiedConstraints, + boolean enabledX509DisabledAlgConstraints) { + this(userSpecifiedConstraints, null, enabledX509DisabledAlgConstraints); } - SSLAlgorithmConstraints(SSLSocket socket, + private SSLAlgorithmConstraints( + AlgorithmConstraints userSpecifiedConstraints, + SupportedSignatureAlgorithmConstraints peerSpecifiedConstraints, boolean withDefaultCertPathConstraints) { - this.userSpecifiedConstraints = getUserSpecifiedConstraints(socket); - this.peerSpecifiedConstraints = null; + this.userSpecifiedConstraints = userSpecifiedConstraints; + this.peerSpecifiedConstraints = peerSpecifiedConstraints; this.enabledX509DisabledAlgConstraints = withDefaultCertPathConstraints; } - SSLAlgorithmConstraints(SSLEngine engine, + /** + * Returns a SSLAlgorithmConstraints instance that checks the provided + * {@code userSpecifiedConstraints} in addition to standard checks. + * Returns a singleton instance if parameter is null or DEFAULT. + * @param userSpecifiedConstraints additional constraints to check + * @return a SSLAlgorithmConstraints instance + */ + static AlgorithmConstraints wrap(AlgorithmConstraints userSpecifiedConstraints) { + return wrap(userSpecifiedConstraints, true); + } + + private static AlgorithmConstraints wrap( + AlgorithmConstraints userSpecifiedConstraints, boolean withDefaultCertPathConstraints) { - this.userSpecifiedConstraints = getUserSpecifiedConstraints(engine); - this.peerSpecifiedConstraints = null; - this.enabledX509DisabledAlgConstraints = withDefaultCertPathConstraints; + if (nullIfDefault(userSpecifiedConstraints) == null) { + return withDefaultCertPathConstraints ? DEFAULT : DEFAULT_SSL_ONLY; + } + return new SSLAlgorithmConstraints(userSpecifiedConstraints, + withDefaultCertPathConstraints); + } + + /** + * Returns a SSLAlgorithmConstraints instance that checks the constraints + * configured for the given {@code socket} in addition to standard checks. + * Returns a singleton instance if the constraints are null or DEFAULT. + * @param socket socket with configured constraints + * @return a SSLAlgorithmConstraints instance + */ + static AlgorithmConstraints forSocket(SSLSocket socket, + boolean withDefaultCertPathConstraints) { + AlgorithmConstraints userSpecifiedConstraints = + getUserSpecifiedConstraints(socket); + return wrap(userSpecifiedConstraints, withDefaultCertPathConstraints); } - SSLAlgorithmConstraints(SSLSocket socket, String[] supportedAlgorithms, + static SSLAlgorithmConstraints forSocket( + SSLSocket socket, + String[] supportedAlgorithms, boolean withDefaultCertPathConstraints) { - this.userSpecifiedConstraints = getUserSpecifiedConstraints(socket); - this.peerSpecifiedConstraints = - new SupportedSignatureAlgorithmConstraints(supportedAlgorithms); - this.enabledX509DisabledAlgConstraints = withDefaultCertPathConstraints; + return new SSLAlgorithmConstraints( + nullIfDefault(getUserSpecifiedConstraints(socket)), + new SupportedSignatureAlgorithmConstraints(supportedAlgorithms), + withDefaultCertPathConstraints); + } + + /** + * Returns a SSLAlgorithmConstraints instance that checks the constraints + * configured for the given {@code engine} in addition to standard checks. + * Returns a singleton instance if the constraints are null or DEFAULT. + * @param engine engine with configured constraints + * @return a SSLAlgorithmConstraints instance + */ + static AlgorithmConstraints forEngine(SSLEngine engine, + boolean withDefaultCertPathConstraints) { + AlgorithmConstraints userSpecifiedConstraints = + getUserSpecifiedConstraints(engine); + return wrap(userSpecifiedConstraints, withDefaultCertPathConstraints); } - SSLAlgorithmConstraints(SSLEngine engine, String[] supportedAlgorithms, + static SSLAlgorithmConstraints forEngine( + SSLEngine engine, + String[] supportedAlgorithms, boolean withDefaultCertPathConstraints) { - this.userSpecifiedConstraints = getUserSpecifiedConstraints(engine); - this.peerSpecifiedConstraints = - new SupportedSignatureAlgorithmConstraints(supportedAlgorithms); - this.enabledX509DisabledAlgConstraints = withDefaultCertPathConstraints; + return new SSLAlgorithmConstraints( + nullIfDefault(getUserSpecifiedConstraints(engine)), + new SupportedSignatureAlgorithmConstraints(supportedAlgorithms), + withDefaultCertPathConstraints); + } + + private static AlgorithmConstraints nullIfDefault( + AlgorithmConstraints constraints) { + return constraints == DEFAULT ? null : constraints; } private static AlgorithmConstraints getUserSpecifiedConstraints( diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java 2022-10-10 13:07:22.000000000 +0000 @@ -1485,14 +1485,14 @@ String[] peerSupportedSignAlgs = extSession.getLocalSupportedSignatureAlgorithms(); - constraints = new SSLAlgorithmConstraints( + constraints = SSLAlgorithmConstraints.forSocket( sslSocket, peerSupportedSignAlgs, true); } else { constraints = - new SSLAlgorithmConstraints(sslSocket, true); + SSLAlgorithmConstraints.forSocket(sslSocket, true); } } else { - constraints = new SSLAlgorithmConstraints(sslSocket, true); + constraints = SSLAlgorithmConstraints.forSocket(sslSocket, true); } checkAlgorithmConstraints(chain, constraints, checkClientTrusted); @@ -1525,14 +1525,14 @@ String[] peerSupportedSignAlgs = extSession.getLocalSupportedSignatureAlgorithms(); - constraints = new SSLAlgorithmConstraints( + constraints = SSLAlgorithmConstraints.forEngine( engine, peerSupportedSignAlgs, true); } else { constraints = - new SSLAlgorithmConstraints(engine, true); + SSLAlgorithmConstraints.forEngine(engine, true); } } else { - constraints = new SSLAlgorithmConstraints(engine, true); + constraints = SSLAlgorithmConstraints.forEngine(engine, true); } checkAlgorithmConstraints(chain, constraints, checkClientTrusted); diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, 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 @@ -199,15 +199,15 @@ extSession.getPeerSupportedSignatureAlgorithms(); } - return new SSLAlgorithmConstraints( + return SSLAlgorithmConstraints.forSocket( sslSocket, peerSupportedSignAlgs, true); } } - return new SSLAlgorithmConstraints(sslSocket, true); + return SSLAlgorithmConstraints.forSocket(sslSocket, true); } - return new SSLAlgorithmConstraints((SSLSocket)null, true); + return SSLAlgorithmConstraints.DEFAULT; } // Gets algorithm constraints of the engine. @@ -225,13 +225,13 @@ extSession.getPeerSupportedSignatureAlgorithms(); } - return new SSLAlgorithmConstraints( + return SSLAlgorithmConstraints.forEngine( engine, peerSupportedSignAlgs, true); } } } - return new SSLAlgorithmConstraints(engine, true); + return SSLAlgorithmConstraints.forEngine(engine, true); } // we construct the alias we return to JSSE as seen in the code below diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java 2022-10-10 13:07:22.000000000 +0000 @@ -216,10 +216,10 @@ String[] localSupportedSignAlgs = extSession.getLocalSupportedSignatureAlgorithms(); - constraints = new SSLAlgorithmConstraints( + constraints = SSLAlgorithmConstraints.forSocket( sslSocket, localSupportedSignAlgs, false); } else { - constraints = new SSLAlgorithmConstraints(sslSocket, false); + constraints = SSLAlgorithmConstraints.forSocket(sslSocket, false); } // Grab any stapled OCSP responses for use in validation @@ -270,10 +270,10 @@ String[] localSupportedSignAlgs = extSession.getLocalSupportedSignatureAlgorithms(); - constraints = new SSLAlgorithmConstraints( + constraints = SSLAlgorithmConstraints.forEngine( engine, localSupportedSignAlgs, false); } else { - constraints = new SSLAlgorithmConstraints(engine, false); + constraints = SSLAlgorithmConstraints.forEngine(engine, false); } // Grab any stapled OCSP responses for use in validation diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java 2022-10-10 13:07:22.000000000 +0000 @@ -91,7 +91,11 @@ public static boolean isWindowsKeyStore(String storetype) { return storetype != null && (storetype.equalsIgnoreCase("Windows-MY") - || storetype.equalsIgnoreCase("Windows-ROOT")); + || storetype.equalsIgnoreCase("Windows-ROOT") + || storetype.equalsIgnoreCase("Windows-MY-CURRENTUSER") + || storetype.equalsIgnoreCase("Windows-ROOT-CURRENTUSER") + || storetype.equalsIgnoreCase("Windows-MY-LOCALMACHINE") + || storetype.equalsIgnoreCase("Windows-ROOT-LOCALMACHINE")); } /** @@ -102,6 +106,14 @@ return "Windows-MY"; } else if(storetype.equalsIgnoreCase("Windows-ROOT")) { return "Windows-ROOT"; + } else if(storetype.equalsIgnoreCase("Windows-MY-CURRENTUSER")) { + return "Windows-MY-CURRENTUSER"; + } else if(storetype.equalsIgnoreCase("Windows-ROOT-CURRENTUSER")) { + return "Windows-ROOT-CURRENTUSER"; + } else if(storetype.equalsIgnoreCase("Windows-MY-LOCALMACHINE")) { + return "Windows-MY-LOCALMACHINE"; + } else if(storetype.equalsIgnoreCase("Windows-ROOT-LOCALMACHINE")) { + return "Windows-ROOT-LOCALMACHINE"; } else { return storetype.toUpperCase(Locale.ENGLISH); } diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java 2022-10-10 13:07:22.000000000 +0000 @@ -27,6 +27,7 @@ import sun.security.validator.Validator; +import java.lang.ref.SoftReference; import java.security.AlgorithmParameters; import java.security.CryptoPrimitive; import java.security.Key; @@ -39,7 +40,6 @@ import java.security.spec.MGF1ParameterSpec; import java.security.spec.NamedParameterSpec; import java.security.spec.PSSParameterSpec; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -53,6 +53,7 @@ import java.util.Collection; import java.util.StringTokenizer; import java.util.TimeZone; +import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; import java.util.regex.Matcher; @@ -100,6 +101,8 @@ private final Set disabledAlgorithms; private final Constraints algorithmConstraints; + private volatile SoftReference> cacheRef = + new SoftReference<>(null); public static DisabledAlgorithmConstraints certPathConstraints() { return CertPathHolder.CONSTRAINTS; @@ -156,8 +159,11 @@ throw new IllegalArgumentException("The primitives cannot be null" + " or empty."); } + if (algorithm == null || algorithm.isEmpty()) { + throw new IllegalArgumentException("No algorithm name specified"); + } - if (!checkAlgorithm(disabledAlgorithms, algorithm, decomposer)) { + if (!cachedCheckAlgorithm(algorithm)) { return false; } @@ -193,16 +199,16 @@ } public final void permits(String algorithm, AlgorithmParameters ap, - ConstraintsParameters cp) throws CertPathValidatorException { - - permits(algorithm, cp); + ConstraintsParameters cp, boolean checkKey) + throws CertPathValidatorException { + permits(algorithm, cp, checkKey); if (ap != null) { permits(ap, cp); } } private void permits(AlgorithmParameters ap, ConstraintsParameters cp) - throws CertPathValidatorException { + throws CertPathValidatorException { switch (ap.getAlgorithm().toUpperCase(Locale.ENGLISH)) { case "RSASSA-PSS": @@ -220,13 +226,13 @@ PSSParameterSpec pssParams = ap.getParameterSpec(PSSParameterSpec.class); String digestAlg = pssParams.getDigestAlgorithm(); - permits(digestAlg, cp); + permits(digestAlg, cp, false); AlgorithmParameterSpec mgfParams = pssParams.getMGFParameters(); if (mgfParams instanceof MGF1ParameterSpec) { String mgfDigestAlg = ((MGF1ParameterSpec)mgfParams).getDigestAlgorithm(); if (!mgfDigestAlg.equalsIgnoreCase(digestAlg)) { - permits(mgfDigestAlg, cp); + permits(mgfDigestAlg, cp, false); } } } catch (InvalidParameterSpecException ipse) { @@ -234,22 +240,24 @@ } } - public final void permits(String algorithm, ConstraintsParameters cp) - throws CertPathValidatorException { + public final void permits(String algorithm, ConstraintsParameters cp, + boolean checkKey) throws CertPathValidatorException { - // Check if named curves in the key are disabled. - for (Key key : cp.getKeys()) { - for (String curve : getNamedCurveFromKey(key)) { - if (!checkAlgorithm(disabledAlgorithms, curve, decomposer)) { - throw new CertPathValidatorException( + if (checkKey) { + // Check if named curves in the key are disabled. + for (Key key : cp.getKeys()) { + for (String curve : getNamedCurveFromKey(key)) { + if (!cachedCheckAlgorithm(curve)) { + throw new CertPathValidatorException( "Algorithm constraints check failed on disabled " + "algorithm: " + curve, null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); + } } } } - algorithmConstraints.permits(algorithm, cp); + algorithmConstraints.permits(algorithm, cp, checkKey); } private static List getNamedCurveFromKey(Key key) { @@ -487,8 +495,8 @@ return true; } - public void permits(String algorithm, ConstraintsParameters cp) - throws CertPathValidatorException { + public void permits(String algorithm, ConstraintsParameters cp, + boolean checkKey) throws CertPathValidatorException { if (debug != null) { debug.println("Constraints.permits(): " + algorithm + ", " @@ -502,8 +510,10 @@ algorithms.add(algorithm); } - for (Key key : cp.getKeys()) { - algorithms.add(key.getAlgorithm()); + if (checkKey) { + for (Key key : cp.getKeys()) { + algorithms.add(key.getAlgorithm()); + } } // Check all applicable constraints @@ -513,6 +523,9 @@ continue; } for (Constraint constraint : list) { + if (!checkKey && constraint instanceof KeySizeConstraint) { + continue; + } constraint.permits(cp); } } @@ -688,8 +701,6 @@ */ private static class DenyAfterConstraint extends Constraint { private Date denyAfterDate; - private static final SimpleDateFormat dateFormat = - new SimpleDateFormat("EEE, MMM d HH:mm:ss z yyyy"); DenyAfterConstraint(String algo, int year, int month, int day) { Calendar c; @@ -723,7 +734,7 @@ denyAfterDate = c.getTime(); if (debug != null) { debug.println("DenyAfterConstraint date set to: " + - dateFormat.format(denyAfterDate)); + denyAfterDate); } } @@ -754,8 +765,8 @@ throw new CertPathValidatorException( "denyAfter constraint check failed: " + algorithm + " used with Constraint date: " + - dateFormat.format(denyAfterDate) + "; params date: " + - dateFormat.format(currentDate) + cp.extendedExceptionMsg(), + denyAfterDate + "; params date: " + + currentDate + cp.extendedExceptionMsg(), null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } } @@ -961,6 +972,25 @@ } } + private boolean cachedCheckAlgorithm(String algorithm) { + Map cache; + if ((cache = cacheRef.get()) == null) { + synchronized (this) { + if ((cache = cacheRef.get()) == null) { + cache = new ConcurrentHashMap<>(); + cacheRef = new SoftReference<>(cache); + } + } + } + Boolean result = cache.get(algorithm); + if (result != null) { + return result; + } + result = checkAlgorithm(disabledAlgorithms, algorithm, decomposer); + cache.put(algorithm, result); + return result; + } + /* * This constraint is used for the complete disabling of the algorithm. */ diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/util/ECUtil.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/util/ECUtil.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/util/ECUtil.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/util/ECUtil.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2022, 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 @@ -310,5 +310,40 @@ } } + // Partial Public key validation as described in NIST SP 800-186 Appendix D.1.1.1. + // The extra step in the full validation (described in Appendix D.1.1.2) is implemented + // as sun.security.ec.ECOperations#checkOrder inside the jdk.crypto.ec module. + public static void validatePublicKey(ECPoint point, ECParameterSpec spec) + throws InvalidKeyException { + BigInteger p; + if (spec.getCurve().getField() instanceof ECFieldFp f) { + p = f.getP(); + } else { + throw new InvalidKeyException("Only curves over prime fields are supported"); + } + + // 1. If Q is the point at infinity, output REJECT + if (point.equals(ECPoint.POINT_INFINITY)) { + throw new InvalidKeyException("Public point is at infinity"); + } + // 2. Verify that x and y are integers in the interval [0, p-1]. Output REJECT if verification fails. + BigInteger x = point.getAffineX(); + if (x.signum() < 0 || x.compareTo(p) >= 0) { + throw new InvalidKeyException("Public point x is not in the interval [0, p-1]"); + } + BigInteger y = point.getAffineY(); + if (y.signum() < 0 || y.compareTo(p) >= 0) { + throw new InvalidKeyException("Public point y is not in the interval [0, p-1]"); + } + // 3. Verify that (x, y) is a point on the W_a,b by checking that (x, y) satisfies the defining + // equation y^2 = x^3 + a x + b where computations are carried out in GF(p). Output REJECT + // if verification fails. + BigInteger left = y.modPow(BigInteger.TWO, p); + BigInteger right = x.pow(3).add(spec.getCurve().getA().multiply(x)).add(spec.getCurve().getB()).mod(p); + if (!left.equals(right)) { + throw new InvalidKeyException("Public point is not on the curve"); + } + } + private ECUtil() {} } diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/util/JarConstraintsParameters.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/util/JarConstraintsParameters.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/util/JarConstraintsParameters.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/util/JarConstraintsParameters.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, 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 @@ -50,9 +50,9 @@ private boolean anchorIsJdkCASet; // The timestamp of the signed JAR file, if timestamped private Date timestamp; - // The keys of the signers + // The keys of the signers and TSA private final Set keys; - // The certs in the signers' chains that are issued by the trust anchor + // The certs in the signers and TSA chain that are issued by the trust anchor private final Set certsIssuedByAnchor; // The extended exception message private String message; @@ -73,7 +73,7 @@ // used for checking if the signer's certificate chains back to a // JDK root CA for (CodeSigner signer : signers) { - init(signer.getSignerCertPath()); + addToCertsAndKeys(signer.getSignerCertPath()); Timestamp timestamp = signer.getTimestamp(); if (timestamp == null) { // this means one of the signers doesn't have a timestamp @@ -82,7 +82,7 @@ skipTimestamp = true; } else { // add the key and last cert of TSA too - init(timestamp.getSignerCertPath()); + addToCertsAndKeys(timestamp.getSignerCertPath()); if (!skipTimestamp) { Date timestampDate = timestamp.getTimestamp(); if (latestTimestamp == null) { @@ -98,11 +98,22 @@ this.timestamp = latestTimestamp; } - // extract last certificate and key from chain - private void init(CertPath cp) { + public JarConstraintsParameters(List chain, Date timestamp) { + this.keys = new HashSet<>(); + this.certsIssuedByAnchor = new HashSet<>(); + addToCertsAndKeys(chain); + this.timestamp = timestamp; + } + + // extract last certificate and signer's public key from chain + private void addToCertsAndKeys(CertPath cp) { @SuppressWarnings("unchecked") List chain = (List)cp.getCertificates(); + addToCertsAndKeys(chain); + } + + private void addToCertsAndKeys(List chain) { if (!chain.isEmpty()) { this.certsIssuedByAnchor.add(chain.get(chain.size() - 1)); this.keys.add(chain.get(0).getPublicKey()); @@ -162,13 +173,13 @@ @Override public String extendedExceptionMsg() { - return message; + return message == null ? "." : message; } @Override public String toString() { StringBuilder sb = new StringBuilder("[\n"); - sb.append("\n Variant: ").append(getVariant()); + sb.append(" Variant: ").append(getVariant()); sb.append("\n Certs Issued by Anchor:"); for (X509Certificate cert : certsIssuedByAnchor) { sb.append("\n Cert Issuer: ") diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java 2022-10-10 13:07:22.000000000 +0000 @@ -295,7 +295,7 @@ params.setExtendedExceptionMsg(JarFile.MANIFEST_NAME, name + " entry"); DisabledAlgorithmConstraints.jarConstraints() - .permits(algorithm, params); + .permits(algorithm, params, false); return true; } catch (GeneralSecurityException e) { if (debug != null) { diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java 2022-10-10 13:07:22.000000000 +0000 @@ -383,7 +383,7 @@ try { params.setExtendedExceptionMsg(name + ".SF", key + " attribute"); DisabledAlgorithmConstraints - .jarConstraints().permits(algorithm, params); + .jarConstraints().permits(algorithm, params, false); } catch (GeneralSecurityException e) { permittedAlgs.put(algorithm, Boolean.FALSE); permittedAlgs.put(key.toUpperCase(), Boolean.FALSE); diff -Nru openjdk-17-17.0.4+8/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties openjdk-17-17.0.5+8/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties --- openjdk-17-17.0.4+8/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2022, 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 @@ -221,6 +221,7 @@ SHP=SHP SIT=SIT SKK=SKK +SLE=SLE SLL=SLL SOS=SOS SRD=SRD @@ -445,6 +446,7 @@ shp=Saint Helena Pound sit=Slovenian Tolar skk=Slovak Koruna +sle=Sierra Leonean Leone sll=Sierra Leonean Leone sos=Somali Shilling srd=Surinamese Dollar diff -Nru openjdk-17-17.0.4+8/src/java.base/share/conf/security/java.security openjdk-17-17.0.5+8/src/java.base/share/conf/security/java.security --- openjdk-17-17.0.4+8/src/java.base/share/conf/security/java.security 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/conf/security/java.security 2022-10-10 13:07:22.000000000 +0000 @@ -558,7 +558,7 @@ # can be included in the disabledAlgorithms properties. These properties are # to help manage common actions easier across multiple disabledAlgorithm # properties. -# There is one defined security property: jdk.disabled.NamedCurves +# There is one defined security property: jdk.disabled.namedCurves # See the property for more specific details. # # @@ -634,7 +634,8 @@ # # jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \ - RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224 + RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224, \ + SHA1 usage SignedJAR & denyAfter 2019-01-01 # # Legacy algorithms for certification path (CertPath) processing and @@ -698,7 +699,7 @@ # See "jdk.certpath.disabledAlgorithms" for syntax descriptions. # jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ - DSA keySize < 1024 + DSA keySize < 1024, SHA1 denyAfter 2019-01-01 # # Algorithm restrictions for Secure Socket Layer/Transport Layer Security diff -Nru openjdk-17-17.0.4+8/src/java.base/share/native/libjava/sizecalc.h openjdk-17-17.0.5+8/src/java.base/share/native/libjava/sizecalc.h --- openjdk-17-17.0.4+8/src/java.base/share/native/libjava/sizecalc.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/native/libjava/sizecalc.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2013, 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. - */ - -#ifndef SIZECALC_H -#define SIZECALC_H - -/* - * A machinery for safe calculation of sizes used when allocating memory. - * - * All size checks are performed against the SIZE_MAX (the maximum value for - * size_t). All numerical arguments as well as the result of calculation must - * be non-negative integers less than or equal to SIZE_MAX, otherwise the - * calculated size is considered unsafe. - * - * If the SIZECALC_ALLOC_THROWING_BAD_ALLOC macro is defined, then _ALLOC_ - * helper macros throw the std::bad_alloc instead of returning NULL. - */ - -#include /* SIZE_MAX for C99+ */ -/* http://stackoverflow.com/questions/3472311/what-is-a-portable-method-to-find-the-maximum-value-of-size-t */ -#ifndef SIZE_MAX -#define SIZE_MAX ((size_t)-1) -#endif - -#define IS_SAFE_SIZE_T(x) ((x) >= 0 && (unsigned long long)(x) <= SIZE_MAX) - -#define IS_SAFE_SIZE_MUL(m, n) \ - (IS_SAFE_SIZE_T(m) && IS_SAFE_SIZE_T(n) && ((m) == 0 || (n) == 0 || (size_t)(n) <= (SIZE_MAX / (size_t)(m)))) - -#define IS_SAFE_SIZE_ADD(a, b) \ - (IS_SAFE_SIZE_T(a) && IS_SAFE_SIZE_T(b) && (size_t)(b) <= (SIZE_MAX - (size_t)(a))) - - - -/* Helper macros */ - -#ifdef SIZECALC_ALLOC_THROWING_BAD_ALLOC -#define FAILURE_RESULT throw std::bad_alloc() -#else -#define FAILURE_RESULT NULL -#endif - -/* - * A helper macro to safely allocate an array of size m*n. - * Example usage: - * int* p = (int*)SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(int), n); - * if (!p) throw OutOfMemory; - * // Use the allocated array... - */ -#define SAFE_SIZE_ARRAY_ALLOC(func, m, n) \ - (IS_SAFE_SIZE_MUL((m), (n)) ? ((func)((m) * (n))) : FAILURE_RESULT) - -#define SAFE_SIZE_ARRAY_REALLOC(func, p, m, n) \ - (IS_SAFE_SIZE_MUL((m), (n)) ? ((func)((p), (m) * (n))) : FAILURE_RESULT) - -/* - * A helper macro to safely allocate an array of type 'type' with 'n' items - * using the C++ new[] operator. - * Example usage: - * MyClass* p = SAFE_SIZE_NEW_ARRAY(MyClass, n); - * // Use the pointer. - * This macro throws the std::bad_alloc C++ exception to indicate - * a failure. - * NOTE: if 'n' is calculated, the calling code is responsible for using the - * IS_SAFE_... macros to check if the calculations are safe. - */ -#define SAFE_SIZE_NEW_ARRAY(type, n) \ - (IS_SAFE_SIZE_MUL(sizeof(type), (n)) ? (new type[(n)]) : throw std::bad_alloc()) - -#define SAFE_SIZE_NEW_ARRAY2(type, n, m) \ - (IS_SAFE_SIZE_MUL((m), (n)) && IS_SAFE_SIZE_MUL(sizeof(type), (n) * (m)) ? \ - (new type[(n) * (m)]) : throw std::bad_alloc()) - -/* - * Checks if a data structure of size (a + m*n) can be safely allocated - * w/o producing an integer overflow when calculating its size. - */ -#define IS_SAFE_STRUCT_SIZE(a, m, n) \ - ( \ - IS_SAFE_SIZE_MUL((m), (n)) && IS_SAFE_SIZE_ADD((m) * (n), (a)) \ - ) - -/* - * A helper macro for implementing safe memory allocation for a data structure - * of size (a + m * n). - * Example usage: - * void * p = SAFE_SIZE_ALLOC(malloc, header, num, itemSize); - * if (!p) throw OutOfMemory; - * // Use the allocated memory... - */ -#define SAFE_SIZE_STRUCT_ALLOC(func, a, m, n) \ - (IS_SAFE_STRUCT_SIZE((a), (m), (n)) ? ((func)((a) + (m) * (n))) : FAILURE_RESULT) - - -#endif /* SIZECALC_H */ - diff -Nru openjdk-17-17.0.4+8/src/java.base/share/native/libjli/java.c openjdk-17-17.0.5+8/src/java.base/share/native/libjli/java.c --- openjdk-17-17.0.4+8/src/java.base/share/native/libjli/java.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/native/libjli/java.c 2022-10-10 13:07:22.000000000 +0000 @@ -108,7 +108,6 @@ static void SetClassPath(const char *s); static void SetMainModule(const char *s); static void SelectVersion(int argc, char **argv, char **main_class); -static void SetJvmEnvironment(int argc, char **argv); static jboolean ParseArguments(int *pargc, char ***pargv, int *pmode, char **pwhat, int *pret, const char *jrepath); @@ -284,9 +283,6 @@ jvmpath, sizeof(jvmpath), jvmcfg, sizeof(jvmcfg)); - /* Set env. Must be done before LoadJavaVM. */ - SetJvmEnvironment(argc, argv); - ifn.CreateJavaVM = 0; ifn.GetDefaultJavaVMInitArgs = 0; @@ -798,84 +794,6 @@ return jvmtype; } -/* - * This method must be called before the VM is loaded, primarily - * used to parse and set any VM related options or env variables. - * This function is non-destructive leaving the argument list intact. - */ -static void -SetJvmEnvironment(int argc, char **argv) { - - static const char* NMT_Env_Name = "NMT_LEVEL_"; - const char* NMT_Arg_Name = IsJavaArgs() ? "-J-XX:NativeMemoryTracking=" : "-XX:NativeMemoryTracking="; - int i; - /* process only the launcher arguments */ - for (i = 0; i < argc; i++) { - char *arg = argv[i]; - /* - * Java launcher (!IsJavaArgs()): - * Since this must be a VM flag we stop processing once we see - * an argument the launcher would not have processed beyond (such - * as -version or -h), or an argument that indicates the following - * arguments are for the application (i.e. the main class name, or - * the -jar argument). - * Other launchers (IsJavaArgs()): - * All arguments have to be scanned to see if it is a -J argument. - */ - if (!IsJavaArgs() && i > 0) { - char *prev = argv[i - 1]; - // skip non-dash arg preceded by class path specifiers - if (*arg != '-' && IsWhiteSpaceOption(prev)) { - continue; - } - - if (*arg != '-' || isTerminalOpt(arg)) { - return; - } - } - /* - * The following case checks for "-XX:NativeMemoryTracking=value". - * If value is non null, an environmental variable set to this value - * will be created to be used by the JVM. - * The argument is passed to the JVM, which will check validity. - * The JVM is responsible for removing the env variable. - */ - if (JLI_StrCCmp(arg, NMT_Arg_Name) == 0) { - int retval; - // get what follows this parameter, include "=" - size_t pnlen = JLI_StrLen(NMT_Arg_Name); - if (JLI_StrLen(arg) > pnlen) { - char* value = arg + pnlen; - size_t pbuflen = pnlen + JLI_StrLen(value) + 10; // 10 max pid digits - - /* - * ensures that malloc successful - * DONT JLI_MemFree() pbuf. JLI_PutEnv() uses system call - * that could store the address. - */ - char * pbuf = (char*)JLI_MemAlloc(pbuflen); - - JLI_Snprintf(pbuf, pbuflen, "%s%d=%s", NMT_Env_Name, JLI_GetPid(), value); - retval = JLI_PutEnv(pbuf); - if (JLI_IsTraceLauncher()) { - char* envName; - char* envBuf; - - // ensures that malloc successful - envName = (char*)JLI_MemAlloc(pbuflen); - JLI_Snprintf(envName, pbuflen, "%s%d", NMT_Env_Name, JLI_GetPid()); - - printf("TRACER_MARKER: NativeMemoryTracking: env var is %s\n",envName); - printf("TRACER_MARKER: NativeMemoryTracking: putenv arg %s\n",pbuf); - envBuf = getenv(envName); - printf("TRACER_MARKER: NativeMemoryTracking: got value %s\n",envBuf); - free(envName); - } - } - } - } -} - /* copied from HotSpot function "atomll()" */ static int parse_size(const char *s, jlong *result) { diff -Nru openjdk-17-17.0.4+8/src/java.base/share/native/libjli/jli_util.h openjdk-17-17.0.5+8/src/java.base/share/native/libjli/jli_util.h --- openjdk-17-17.0.4+8/src/java.base/share/native/libjli/jli_util.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/share/native/libjli/jli_util.h 2022-10-10 13:07:22.000000000 +0000 @@ -93,8 +93,6 @@ JNIEXPORT void JNICALL JLI_CmdToArgs(char *cmdline); #define JLI_Lseek _lseeki64 -#define JLI_PutEnv _putenv -#define JLI_GetPid _getpid #else /* NIXES */ #include #include @@ -102,8 +100,6 @@ #define JLI_StrNCaseCmp(p1, p2, p3) strncasecmp((p1), (p2), (p3)) #define JLI_Snprintf snprintf #define JLI_Open open -#define JLI_PutEnv putenv -#define JLI_GetPid getpid #ifdef __linux__ #define _LARGFILE64_SOURCE #define JLI_Lseek lseek64 diff -Nru openjdk-17-17.0.4+8/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java openjdk-17-17.0.5+8/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java --- openjdk-17-17.0.4+8/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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 @@ -32,9 +32,8 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.net.UnixDomainSocketAddress; -import java.net.StandardProtocolFamily; import java.net.StandardSocketOptions; +import java.net.UnixDomainSocketAddress; import java.nio.*; import java.nio.channels.*; import java.nio.file.Files; @@ -46,6 +45,7 @@ import java.security.SecureRandom; import java.util.Random; +import static java.net.StandardProtocolFamily.UNIX; /** * A simple Pipe implementation based on a socket connection. @@ -69,12 +69,14 @@ { private final SelectorProvider sp; + private final boolean preferUnixDomain; private IOException ioe; SourceChannelImpl source; SinkChannelImpl sink; - private Initializer(SelectorProvider sp) { + private Initializer(SelectorProvider sp, boolean preferUnixDomain) { this.sp = sp; + this.preferUnixDomain = preferUnixDomain; } @Override @@ -122,7 +124,7 @@ // Bind ServerSocketChannel to a port on the loopback // address if (ssc == null || !ssc.isOpen()) { - ssc = createListener(); + ssc = createListener(preferUnixDomain); sa = ssc.getLocalAddress(); } @@ -164,9 +166,8 @@ try { if (ssc != null) ssc.close(); - if (sa instanceof UnixDomainSocketAddress) { - Path path = ((UnixDomainSocketAddress) sa).getPath(); - Files.deleteIfExists(path); + if (sa instanceof UnixDomainSocketAddress uaddr) { + Files.deleteIfExists(uaddr.getPath()); } } catch (IOException e2) {} } @@ -175,22 +176,24 @@ } /** - * Creates a Pipe implementation that supports buffering. + * Creates a (TCP) Pipe implementation that supports buffering. */ PipeImpl(SelectorProvider sp) throws IOException { - this(sp, true); + this(sp, true, false); } /** - * Creates Pipe implementation that supports optionally buffering. + * Creates Pipe implementation that supports optionally buffering + * and is TCP by default, but if Unix domain is supported and + * preferAfUnix is true, then Unix domain sockets are used. * - * @implNote The pipe uses Unix domain sockets where possible. It uses a - * loopback connection on older editions of Windows. When buffering is - * disabled then it sets TCP_NODELAY on the sink channel. + * @param preferAfUnix use Unix domain sockets if supported + * + * @param buffering if false set TCP_NODELAY on TCP sockets */ @SuppressWarnings("removal") - PipeImpl(SelectorProvider sp, boolean buffering) throws IOException { - Initializer initializer = new Initializer(sp); + PipeImpl(SelectorProvider sp, boolean preferAfUnix, boolean buffering) throws IOException { + Initializer initializer = new Initializer(sp, preferAfUnix); try { AccessController.doPrivileged(initializer); SinkChannelImpl sink = initializer.sink; @@ -212,18 +215,14 @@ return sink; } - private static volatile boolean noUnixDomainSockets; - - private static ServerSocketChannel createListener() throws IOException { + private static ServerSocketChannel createListener(boolean preferUnixDomain) throws IOException { ServerSocketChannel listener = null; - if (!noUnixDomainSockets) { + if (preferUnixDomain && UnixDomainSockets.isSupported()) { try { - listener = ServerSocketChannel.open(StandardProtocolFamily.UNIX); - return listener.bind(null); - } catch (UnsupportedOperationException | IOException e) { - // IOException is most likely to be caused by the temporary directory - // name being too long. Possibly should log this. - noUnixDomainSockets = true; + listener = ServerSocketChannel.open(UNIX); + listener.bind(null); + return listener; + } catch (IOException | UnsupportedOperationException e) { if (listener != null) listener.close(); } diff -Nru openjdk-17-17.0.4+8/src/java.base/windows/classes/sun/nio/ch/WEPollSelectorImpl.java openjdk-17-17.0.5+8/src/java.base/windows/classes/sun/nio/ch/WEPollSelectorImpl.java --- openjdk-17-17.0.4+8/src/java.base/windows/classes/sun/nio/ch/WEPollSelectorImpl.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/windows/classes/sun/nio/ch/WEPollSelectorImpl.java 2022-10-10 13:07:22.000000000 +0000 @@ -75,7 +75,7 @@ // wakeup support try { - this.pipe = new PipeImpl(sp, /*buffering*/ false); + this.pipe = new PipeImpl(sp, /* AF_UNIX */ true, /*buffering*/ false); } catch (IOException ioe) { WEPoll.freePollArray(pollArrayAddress); WEPoll.close(eph); diff -Nru openjdk-17-17.0.4+8/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java openjdk-17-17.0.5+8/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java --- openjdk-17-17.0.4+8/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java 2022-10-10 13:07:22.000000000 +0000 @@ -139,7 +139,7 @@ WindowsSelectorImpl(SelectorProvider sp) throws IOException { super(sp); pollWrapper = new PollArrayWrapper(INIT_CAP); - wakeupPipe = new PipeImpl(sp, false); + wakeupPipe = new PipeImpl(sp, /* AF_UNIX */ true, /*buffering*/ false); wakeupSourceFd = ((SelChImpl)wakeupPipe.source()).getFDVal(); wakeupSinkFd = ((SelChImpl)wakeupPipe.sink()).getFDVal(); pollWrapper.addWakeupSocket(wakeupSourceFd, 0); diff -Nru openjdk-17-17.0.4+8/src/java.base/windows/native/libjava/java_props_md.c openjdk-17-17.0.5+8/src/java.base/windows/native/libjava/java_props_md.c --- openjdk-17-17.0.4+8/src/java.base/windows/native/libjava/java_props_md.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/windows/native/libjava/java_props_md.c 2022-10-10 13:07:22.000000000 +0000 @@ -23,11 +23,6 @@ * questions. */ -/* Access APIs for Windows Vista and above */ -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0601 -#endif - #include "jni.h" #include "jni_util.h" @@ -63,19 +58,19 @@ static char * getEncodingInternal(LCID lcid) { - int codepage; + int codepage = 0; char * ret = malloc(16); if (ret == NULL) { return NULL; } - if (GetLocaleInfo(lcid, + if (lcid == 0) { // for sun.jnu.encoding + codepage = GetACP(); + _itoa_s(codepage, ret + 2, 14, 10); + } else if (GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, - ret+2, 14) == 0) { - codepage = 1252; - strcpy(ret+2, "1252"); - } else { - codepage = atoi(ret+2); + ret + 2, 14) != 0) { + codepage = atoi(ret + 2); } switch (codepage) { @@ -660,7 +655,6 @@ * (which is a Windows LCID value), */ LCID userDefaultLCID = GetUserDefaultLCID(); - LCID systemDefaultLCID = GetSystemDefaultLCID(); LANGID userDefaultUILang = GetUserDefaultUILanguage(); LCID userDefaultUILCID = MAKELCID(userDefaultUILang, SORTIDFROMLCID(userDefaultLCID)); @@ -693,7 +687,10 @@ &sprops.display_variant, &display_encoding); - sprops.sun_jnu_encoding = getEncodingInternal(systemDefaultLCID); + sprops.sun_jnu_encoding = getEncodingInternal(0); + if (sprops.sun_jnu_encoding == NULL) { + sprops.sun_jnu_encoding = "UTF-8"; + } if (LANGIDFROMLCID(userDefaultLCID) == 0x0c04 && majorVersion == 6) { // MS claims "Vista has built-in support for HKSCS-2004. // All of the HKSCS-2004 characters have Unicode 4.1. diff -Nru openjdk-17-17.0.4+8/src/java.base/windows/native/libjava/WinCAPISeedGenerator.c openjdk-17-17.0.5+8/src/java.base/windows/native/libjava/WinCAPISeedGenerator.c --- openjdk-17-17.0.4+8/src/java.base/windows/native/libjava/WinCAPISeedGenerator.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/windows/native/libjava/WinCAPISeedGenerator.c 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,6 @@ * questions. */ -/* Need to define this to get CAPI functions included */ -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0400 -#endif - #include #include #include diff -Nru openjdk-17-17.0.4+8/src/java.base/windows/native/libjava/WinNTFileSystem_md.c openjdk-17-17.0.5+8/src/java.base/windows/native/libjava/WinNTFileSystem_md.c --- openjdk-17-17.0.4+8/src/java.base/windows/native/libjava/WinNTFileSystem_md.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.base/windows/native/libjava/WinNTFileSystem_md.c 2022-10-10 13:07:22.000000000 +0000 @@ -23,11 +23,6 @@ * questions. */ -/* Access APIs for WinXP and above */ -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif - #include #include #include diff -Nru openjdk-17-17.0.4+8/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java openjdk-17-17.0.5+8/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java --- openjdk-17-17.0.4+8/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java 2022-10-10 13:07:22.000000000 +0000 @@ -172,7 +172,8 @@ ((AccessibleState)oldValue) == AccessibleState.VISIBLE ) { menuClosed(ptr); } - } else if (thisRole == AccessibleRole.MENU_ITEM) { + } else if (thisRole == AccessibleRole.MENU_ITEM || + (thisRole == AccessibleRole.MENU)) { if ( newValue != null && ((AccessibleState)newValue) == AccessibleState.FOCUSED ) { menuItemSelected(ptr); @@ -200,7 +201,6 @@ } } - static Accessible getSwingAccessible(final Accessible a) { return (a instanceof CAccessible) ? ((CAccessible)a).accessible : a; } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.h openjdk-17-17.0.5+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.h --- openjdk-17-17.0.4+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.h 2022-10-10 13:07:22.000000000 +0000 @@ -83,6 +83,7 @@ - (NSView* _Nonnull)view; - (NSWindow* _Nonnull)window; - (id _Nonnull)parent; +- (CommonComponentAccessibility* _Nullable)typeSafeParent; - (NSString* _Nonnull)javaRole; - (BOOL)isMenu; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m openjdk-17-17.0.5+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m --- openjdk-17-17.0.4+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m 2022-10-10 13:07:22.000000000 +0000 @@ -95,7 +95,11 @@ return NO; } - return isChildSelected(env, ((CommonComponentAccessibility *)[self parent])->fAccessible, fIndex, fComponent); + CommonComponentAccessibility* parent = [self typeSafeParent]; + if (parent != nil) { + return isChildSelected(env, parent->fAccessible, fIndex, fComponent); + } + return NO; } - (BOOL)isSelectable:(JNIEnv *)env @@ -122,7 +126,7 @@ /* * Here we should keep all the mapping between the accessibility roles and implementing classes */ - rolesMap = [[NSMutableDictionary alloc] initWithCapacity:51]; + rolesMap = [[NSMutableDictionary alloc] initWithCapacity:50]; [rolesMap setObject:@"ButtonAccessibility" forKey:@"pushbutton"]; [rolesMap setObject:@"ImageAccessibility" forKey:@"icon"]; @@ -154,7 +158,6 @@ [rolesMap setObject:@"TableAccessibility" forKey:@"table"]; [rolesMap setObject:@"MenuBarAccessibility" forKey:@"menubar"]; [rolesMap setObject:@"MenuAccessibility" forKey:@"menu"]; - [rolesMap setObject:@"MenuItemAccessibility" forKey:@"menuitem"]; [rolesMap setObject:@"MenuAccessibility" forKey:@"popupmenu"]; [rolesMap setObject:@"ProgressIndicatorAccessibility" forKey:@"progressbar"]; @@ -182,7 +185,8 @@ [rolesMap setObject:IgnoreClassName forKey:@"viewport"]; [rolesMap setObject:IgnoreClassName forKey:@"window"]; - rowRolesMapForParent = [[NSMutableDictionary alloc] initWithCapacity:2]; + rowRolesMapForParent = [[NSMutableDictionary alloc] initWithCapacity:3]; + [rowRolesMapForParent setObject:@"MenuItemAccessibility" forKey:@"MenuAccessibility"]; [rowRolesMapForParent setObject:@"ListRowAccessibility" forKey:@"ListAccessibility"]; [rowRolesMapForParent setObject:@"OutlineRowAccessibility" forKey:@"OutlineAccessibility"]; @@ -708,6 +712,15 @@ return fParent; } +- (CommonComponentAccessibility *)typeSafeParent +{ + id parent = [self parent]; + if ([parent isKindOfClass:[CommonComponentAccessibility class]]) { + return (CommonComponentAccessibility*)parent; + } + return nil; +} + - (NSString *)javaRole { if(fJavaRole == nil) { @@ -792,7 +805,7 @@ (*env)->DeleteLocalRef(env, axComponent); point.y += size.height; - point.y = [[[[self view] window] screen] frame].size.height - point.y; + point.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - point.y; return NSMakeRect(point.x, point.y, size.width, size.height); } @@ -824,11 +837,13 @@ if (fNSRole == nil) { NSString *javaRole = [self javaRole]; fNSRole = [sRoles objectForKey:javaRole]; + CommonComponentAccessibility* parent = [self typeSafeParent]; // The sRoles NSMutableDictionary maps popupmenu to Mac's popup button. // JComboBox behavior currently relies on this. However this is not the // proper mapping for a JPopupMenu so fix that. if ( [javaRole isEqualToString:@"popupmenu"] && - ![[[self parent] javaRole] isEqualToString:@"combobox"] ) { + parent != nil && + ![[parent javaRole] isEqualToString:@"combobox"] ) { fNSRole = NSAccessibilityMenuRole; } if (fNSRole == nil) { @@ -990,7 +1005,7 @@ point.y += size.height; // Now make it into Cocoa screen coords. - point.y = [[[[self view] window] screen] frame].size.height - point.y; + point.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - point.y; return point; } @@ -1025,8 +1040,9 @@ // This may change when later fixing issues which currently // exist for combo boxes, but for now the following is only // for JPopupMenus, not for combobox menus. - id parent = [self parent]; + id parent = [self typeSafeParent]; if ( [[self javaRole] isEqualToString:@"popupmenu"] && + parent != nil && ![[parent javaRole] isEqualToString:@"combobox"] ) { NSArray *children = [CommonComponentAccessibility childrenOfParent:self @@ -1098,7 +1114,7 @@ "(Ljava/awt/Container;FF)Ljavax/accessibility/Accessible;", nil); // Make it into java screen coords - point.y = [[[[self view] window] screen] frame].size.height - point.y; + point.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - point.y; jobject jparent = fComponent; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m openjdk-17-17.0.5+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m --- openjdk-17-17.0.4+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m 2022-10-10 13:07:22.000000000 +0000 @@ -61,11 +61,14 @@ - (jobject)tabGroup { if (fTabGroupAxContext == NULL) { - JNIEnv* env = [ThreadUtilities getJNIEnv]; - jobject tabGroupAxContext = [(CommonComponentAccessibility *)[self parent] axContextWithEnv:env]; - fTabGroupAxContext = (*env)->NewWeakGlobalRef(env, tabGroupAxContext); - CHECK_EXCEPTION(); - (*env)->DeleteLocalRef(env, tabGroupAxContext); + CommonComponentAccessibility* parent = [self typeSafeParent]; + if (parent != nil) { + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject tabGroupAxContext = [parent axContextWithEnv:env]; + fTabGroupAxContext = (*env)->NewWeakGlobalRef(env, tabGroupAxContext); + CHECK_EXCEPTION(); + (*env)->DeleteLocalRef(env, tabGroupAxContext); + } } return fTabGroupAxContext; } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h openjdk-17-17.0.5+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h --- openjdk-17-17.0.4+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h 2022-10-10 13:07:22.000000000 +0000 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, JetBrains s.r.o.. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ @interface TableAccessibility : CommonComponentAccessibility { NSMutableDictionary *rowCache; + BOOL cacheValid; } - (BOOL)isAccessibleChildSelectedFromIndex:(int)index; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m openjdk-17-17.0.5+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m --- openjdk-17-17.0.4+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m 2022-10-10 13:07:22.000000000 +0000 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, JetBrains s.r.o.. 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 @@ -130,6 +130,15 @@ if (rowCache == nil) { int rowCount = [self accessibilityRowCount]; rowCache = [[NSMutableDictionary dictionaryWithCapacity:rowCount] retain]; + cacheValid = YES; + } + + if (!cacheValid) { + for (NSNumber *key in [rowCache allKeys]) { + [[rowCache objectForKey:key] release]; + [rowCache removeObjectForKey:key]; + } + cacheValid = YES; } id row = [rowCache objectForKey:[NSNumber numberWithUnsignedInteger:index]]; @@ -223,11 +232,7 @@ } - (void)clearCache { - for (NSNumber *key in [rowCache allKeys]) { - [[rowCache objectForKey:key] release]; - } - [rowCache release]; - rowCache = nil; + cacheValid = NO; } @end diff -Nru openjdk-17-17.0.4+8/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m openjdk-17-17.0.5+8/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m --- openjdk-17-17.0.4+8/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m 2022-10-10 13:07:22.000000000 +0000 @@ -296,6 +296,11 @@ CGKeyCode keyCode = GetCGKeyCode(javaKeyCode); CGEventRef event = CGEventCreateKeyboardEvent(source, keyCode, keyPressed); if (event != NULL) { + CGEventFlags flags = CGEventSourceFlagsState(kCGEventSourceStateHIDSystemState); + if ((flags & kCGEventFlagMaskSecondaryFn) != 0) { + flags ^= kCGEventFlagMaskSecondaryFn; + CGEventSetFlags(event, flags); + } CGEventPost(kCGHIDEventTap, event); CFRelease(event); } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m openjdk-17-17.0.5+8/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m --- openjdk-17-17.0.4+8/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m 2022-10-10 13:07:22.000000000 +0000 @@ -65,6 +65,10 @@ MTLVC_ADD_VERTEX(TX1, TY1, DX1, DY1, 0); \ } while (0) +// Next define should exactly match to the amount +// of MTLVC_ADD_VERTEX in MTLVC_ADD_TRIANGLES +#define VERTS_FOR_A_QUAD 6 + jboolean MTLVertexCache_InitVertexCache() { @@ -219,7 +223,11 @@ J2dTraceLn1(J2D_TRACE_INFO, "MTLVertexCache_AddMaskQuad: %d", maskCacheIndex); - if (maskCacheIndex >= MTLVC_MASK_CACHE_MAX_INDEX) + // MTLVC_ADD_TRIANGLES at the end of this function + // will place VERTS_FOR_A_QUAD vertexes to the vertex cache + // check free space and flush if needed. + if ((maskCacheIndex >= MTLVC_MASK_CACHE_MAX_INDEX) || + ((vertexCacheIndex + VERTS_FOR_A_QUAD) >= MTLVC_MAX_INDEX)) { J2dTraceLn2(J2D_TRACE_INFO, "maskCacheIndex = %d, vertexCacheIndex = %d", maskCacheIndex, vertexCacheIndex); MTLVertexCache_FlushVertexCache(mtlc); @@ -305,7 +313,9 @@ { J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_AddGlyphQuad"); - if (vertexCacheIndex >= MTLVC_MAX_INDEX) + // MTLVC_ADD_TRIANGLES adds VERTS_FOR_A_QUAD vertexes into Cache + // so need to check space for VERTS_FOR_A_QUAD elements + if ((vertexCacheIndex + VERTS_FOR_A_QUAD) >= MTLVC_MAX_INDEX) { J2dTraceLn2(J2D_TRACE_INFO, "maskCacheIndex = %d, vertexCacheIndex = %d", maskCacheIndex, vertexCacheIndex); MTLVertexCache_FlushGlyphVertexCache(); diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java openjdk-17-17.0.5+8/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java --- openjdk-17-17.0.4+8/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java 2022-10-10 13:07:22.000000000 +0000 @@ -962,7 +962,8 @@ this.clearCode = 1 << initCodeSize; this.eofCode = clearCode + 1; - int code, oldCode = 0; + final int NULL_CODE = -1; + int code, oldCode = NULL_CODE; int[] prefix = new int[4096]; byte[] suffix = new byte[4096]; @@ -985,6 +986,7 @@ codeMask = (1 << codeSize) - 1; code = getCode(codeSize, codeMask); + oldCode = NULL_CODE; if (code == eofCode) { // Inform IIOReadProgressListeners of end of image processImageComplete(); @@ -1007,24 +1009,21 @@ } } - if (tableIndex >= prefix.length) { - throw new IIOException("Code buffer limit reached," - + " no End of Image tag present, possibly data is corrupted. "); - } - - int ti = tableIndex; - int oc = oldCode; - - prefix[ti] = oc; - suffix[ti] = initial[newSuffixIndex]; - initial[ti] = initial[oc]; - length[ti] = length[oc] + 1; - - ++tableIndex; - if ((tableIndex == (1 << codeSize)) && - (tableIndex < 4096)) { - ++codeSize; - codeMask = (1 << codeSize) - 1; + if (NULL_CODE != oldCode && tableIndex < 4096) { + int ti = tableIndex; + int oc = oldCode; + + prefix[ti] = oc; + suffix[ti] = initial[newSuffixIndex]; + initial[ti] = initial[oc]; + length[ti] = length[oc] + 1; + + ++tableIndex; + if ((tableIndex == (1 << codeSize)) && + (tableIndex < 4096)) { + ++codeSize; + codeMask = (1 << codeSize) - 1; + } } } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java openjdk-17-17.0.5+8/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java --- openjdk-17-17.0.4+8/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, 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 @@ -341,44 +341,30 @@ } private void verify() throws ImageLayoutException { - - if (offset < 0 || offset >= dataArrayLength) { - throw new ImageLayoutException("Invalid image layout"); - } - + checkIndex(offset, dataArrayLength); if (nextPixelOffset != getBytesPerPixel(pixelType)) { throw new ImageLayoutException("Invalid image layout"); } int lastScanOffset = safeMult(nextRowOffset, (height - 1)); - int lastPixelOffset = safeMult(nextPixelOffset, (width -1 )); + long off = (long) offset + lastPixelOffset + lastScanOffset; - lastPixelOffset = safeAdd(lastPixelOffset, lastScanOffset); - - int off = safeAdd(offset, lastPixelOffset); - - if (off < 0 || off >= dataArrayLength) { - throw new ImageLayoutException("Invalid image layout"); - } + checkIndex(off, dataArrayLength); } - static int safeAdd(int a, int b) throws ImageLayoutException { - long res = a; - res += b; - if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) { + private static int checkIndex(long index, int length) + throws ImageLayoutException + { + if (index < 0 || index >= length) { throw new ImageLayoutException("Invalid image layout"); } - return (int)res; + return (int) index; } - static int safeMult(int a, int b) throws ImageLayoutException { - long res = a; - res *= b; - if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) { - throw new ImageLayoutException("Invalid image layout"); - } - return (int)res; + private static int safeMult(int a, int b) throws ImageLayoutException { + long res = (long) a * b; + return checkIndex(res, Integer.MAX_VALUE); } @SuppressWarnings("serial") // JDK-implementation class diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/legal/freetype.md openjdk-17-17.0.5+8/src/java.desktop/share/legal/freetype.md --- openjdk-17-17.0.4+8/src/java.desktop/share/legal/freetype.md 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/legal/freetype.md 2022-10-10 13:07:22.000000000 +0000 @@ -1,4 +1,4 @@ -## The FreeType Project: Freetype v2.12.0 +## The FreeType Project: Freetype v2.12.1 ### FreeType Notice diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/legal/harfbuzz.md openjdk-17-17.0.5+8/src/java.desktop/share/legal/harfbuzz.md --- openjdk-17-17.0.4+8/src/java.desktop/share/legal/harfbuzz.md 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/legal/harfbuzz.md 2022-10-10 13:07:22.000000000 +0000 @@ -1,4 +1,4 @@ -## Harfbuzz v2.8 +## Harfbuzz v4.4.1 ### Harfbuzz License diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/include/sizecalc.h openjdk-17-17.0.5+8/src/java.desktop/share/native/include/sizecalc.h --- openjdk-17-17.0.4+8/src/java.desktop/share/native/include/sizecalc.h 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/include/sizecalc.h 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2013, 2022, 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. + */ + +#ifndef SIZECALC_H +#define SIZECALC_H + +/* + * A machinery for safe calculation of sizes used when allocating memory. + * + * All size checks are performed against the SIZE_MAX (the maximum value for + * size_t). All numerical arguments as well as the result of calculation must + * be non-negative integers less than or equal to SIZE_MAX, otherwise the + * calculated size is considered unsafe. + * + * If the SIZECALC_ALLOC_THROWING_BAD_ALLOC macro is defined, then _ALLOC_ + * helper macros throw the std::bad_alloc instead of returning NULL. + */ + +#include /* SIZE_MAX for C99+ */ +/* http://stackoverflow.com/questions/3472311/what-is-a-portable-method-to-find-the-maximum-value-of-size-t */ +#ifndef SIZE_MAX +#define SIZE_MAX ((size_t)-1) +#endif + +#define IS_SAFE_SIZE_T(x) ((x) >= 0 && (unsigned long long)(x) <= SIZE_MAX) + +#define IS_MUL_OVERFLOW(m, n) \ + ((m) != 0 && (n) != 0 && (((size_t)((m)*(n))) != (((size_t)(m)) * ((size_t)(n))))) + +#define IS_SAFE_SIZE_MUL(m, n) \ + (IS_SAFE_SIZE_T(m) && IS_SAFE_SIZE_T(n) && \ + ((m) == 0 || (n) == 0 || (size_t)(n) <= (SIZE_MAX / (size_t)(m))) && \ + !IS_MUL_OVERFLOW(m, n)) + +#define IS_SAFE_SIZE_ADD(a, b) \ + (IS_SAFE_SIZE_T(a) && IS_SAFE_SIZE_T(b) && (size_t)(b) <= (SIZE_MAX - (size_t)(a))) + + + +/* Helper macros */ + +#ifdef SIZECALC_ALLOC_THROWING_BAD_ALLOC +#define FAILURE_RESULT throw std::bad_alloc() +#else +#define FAILURE_RESULT NULL +#endif + +/* + * A helper macro to safely allocate an array of size m*n. + * Example usage: + * int* p = (int*)SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(int), n); + * if (!p) throw OutOfMemory; + * // Use the allocated array... + */ +#define SAFE_SIZE_ARRAY_ALLOC(func, m, n) \ + (IS_SAFE_SIZE_MUL((m), (n)) ? ((func)((m) * (n))) : FAILURE_RESULT) + +#define SAFE_SIZE_ARRAY_REALLOC(func, p, m, n) \ + (IS_SAFE_SIZE_MUL((m), (n)) ? ((func)((p), (m) * (n))) : FAILURE_RESULT) + +/* + * A helper macro to safely allocate an array of type 'type' with 'n' items + * using the C++ new[] operator. + * Example usage: + * MyClass* p = SAFE_SIZE_NEW_ARRAY(MyClass, n); + * // Use the pointer. + * This macro throws the std::bad_alloc C++ exception to indicate + * a failure. + * NOTE: if 'n' is calculated, the calling code is responsible for using the + * IS_SAFE_... macros to check if the calculations are safe. + */ +#define SAFE_SIZE_NEW_ARRAY(type, n) \ + (IS_SAFE_SIZE_MUL(sizeof(type), (n)) ? (new type[(n)]) : throw std::bad_alloc()) + +#define SAFE_SIZE_NEW_ARRAY2(type, n, m) \ + (IS_SAFE_SIZE_MUL((m), (n)) && IS_SAFE_SIZE_MUL(sizeof(type), (n) * (m)) ? \ + (new type[(n) * (m)]) : throw std::bad_alloc()) + +/* + * Checks if a data structure of size (a + m*n) can be safely allocated + * w/o producing an integer overflow when calculating its size. + */ +#define IS_SAFE_STRUCT_SIZE(a, m, n) \ + ( \ + IS_SAFE_SIZE_MUL((m), (n)) && IS_SAFE_SIZE_ADD((m) * (n), (a)) \ + ) + +/* + * A helper macro for implementing safe memory allocation for a data structure + * of size (a + m * n). + * Example usage: + * void * p = SAFE_SIZE_ALLOC(malloc, header, num, itemSize); + * if (!p) throw OutOfMemory; + * // Use the allocated memory... + */ +#define SAFE_SIZE_STRUCT_ALLOC(func, a, m, n) \ + (IS_SAFE_STRUCT_SIZE((a), (m), (n)) ? ((func)((a) + (m) * (n))) : FAILURE_RESULT) + + +#endif /* SIZECALC_H */ + diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h 2022-10-10 13:07:22.000000000 +0000 @@ -4942,7 +4942,7 @@ */ #define FREETYPE_MAJOR 2 #define FREETYPE_MINOR 12 -#define FREETYPE_PATCH 0 +#define FREETYPE_PATCH 1 /************************************************************************** diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h 2022-10-10 13:07:22.000000000 +0000 @@ -528,14 +528,14 @@ * @fields: * num_color_stops :: * The number of color stops for the requested glyph index. Set by - * @FT_Get_Colorline_Stops. + * @FT_Get_Paint. * * current_color_stop :: * The current color stop. Set by @FT_Get_Colorline_Stops. * * p :: - * An opaque pointer into 'COLR' table data. The caller must set this - * to `NULL` before the first call of @FT_Get_Colorline_Stops. + * An opaque pointer into 'COLR' table data. Set by @FT_Get_Paint. + * Updated by @FT_Get_Colorline_Stops. * * @since: * 2.11 -- **currently experimental only!** There might be changes diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/base/ftmac.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/base/ftmac.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/base/ftmac.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/base/ftmac.c 2022-10-10 13:07:22.000000000 +0000 @@ -314,7 +314,7 @@ NULL, NULL, NULL ) ) return ( OSType ) 0; - return ((FInfo *)(info.finderInfo))->fdType; + return ( (FInfo *)( info.finderInfo ) )->fdType; } @@ -462,7 +462,7 @@ if ( ps_name_len != 0 ) { - ft_memcpy(ps_name, names[0] + 1, ps_name_len); + ft_memcpy( ps_name, names[0] + 1, ps_name_len ); ps_name[ps_name_len] = 0; } if ( style->indexes[face_index] > 1 && diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c 2022-10-10 13:07:22.000000000 +0000 @@ -402,17 +402,17 @@ FT_Long *result_offset ); - CONST_FT_RFORK_RULE_ARRAY_BEGIN(ft_raccess_guess_table, - ft_raccess_guess_rec) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_double, apple_double) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_single, apple_single) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_ufs_export, darwin_ufs_export) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_newvfs, darwin_newvfs) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_hfsplus, darwin_hfsplus) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(vfat, vfat) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_cap, linux_cap) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_double, linux_double) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_netatalk, linux_netatalk) + CONST_FT_RFORK_RULE_ARRAY_BEGIN( ft_raccess_guess_table, + ft_raccess_guess_rec ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( apple_double, apple_double ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( apple_single, apple_single ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_ufs_export, darwin_ufs_export ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_newvfs, darwin_newvfs ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_hfsplus, darwin_hfsplus ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( vfat, vfat ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_cap, linux_cap ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_double, linux_double ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_netatalk, linux_netatalk ) CONST_FT_RFORK_RULE_ARRAY_END diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c 2022-10-10 13:07:22.000000000 +0000 @@ -81,7 +81,7 @@ if ( char_code < 255 ) { - FT_UInt code = (FT_UInt)(char_code + 1); + FT_UInt code = (FT_UInt)( char_code + 1 ); for (;;) diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c 2022-10-10 13:07:22.000000000 +0000 @@ -75,7 +75,7 @@ #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { - CFF_Font cff = (CFF_Font)(face->extra.data); + CFF_Font cff = (CFF_Font)( face->extra.data ); return cff_index_access_element( &cff->charstrings_index, glyph_index, @@ -111,7 +111,7 @@ #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { - CFF_Font cff = (CFF_Font)(face->extra.data); + CFF_Font cff = (CFF_Font)( face->extra.data ); cff_index_forget_element( &cff->charstrings_index, pointer ); @@ -370,8 +370,8 @@ SFNT_Service sfnt; - if ( size->root.metrics.x_ppem < 1 || - size->root.metrics.y_ppem < 1 ) + if ( size && (size->root.metrics.x_ppem < 1 || + size->root.metrics.y_ppem < 1 ) ) { error = FT_THROW( Invalid_Size_Handle ); return error; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c 2022-10-10 13:07:22.000000000 +0000 @@ -248,7 +248,7 @@ else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { - CFF_Font cff = (CFF_Font)(face->extra.data); + CFF_Font cff = (CFF_Font)( face->extra.data ); bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar ); diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c 2022-10-10 13:07:22.000000000 +0000 @@ -535,11 +535,11 @@ if ( r & 1 ) { - *buffer = (FT_Byte)(*buffer + c); + *buffer = (FT_Byte)( *buffer + c ); buffer++; } else - *buffer = (FT_Byte)(c << 4); + *buffer = (FT_Byte)( c << 4 ); r++; } @@ -572,8 +572,8 @@ if ( p >= limit ) return 0; - if ( n > (FT_UInt)(limit - p) ) - n = (FT_UInt)(limit - p); + if ( n > (FT_UInt)( limit - p ) ) + n = (FT_UInt)( limit - p ); for ( r = 0; r < n; r++ ) { diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c 2022-10-10 13:07:22.000000000 +0000 @@ -518,7 +518,7 @@ if ( *cur == '<' ) /* <...> */ { - if ( cur + 1 < limit && *(cur + 1) == '<' ) /* << */ + if ( cur + 1 < limit && *( cur + 1 ) == '<' ) /* << */ { cur++; cur++; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c 2022-10-10 13:07:22.000000000 +0000 @@ -2269,7 +2269,7 @@ /* This is due to the fact that, in the vast majority of cases, */ /* the span length in bytes is relatively small. */ while ( --c2 > 0 ) - *(++target) = 0xFF; + *( ++target ) = 0xFF; target[1] |= f2; } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c 2022-10-10 13:07:22.000000000 +0000 @@ -367,7 +367,7 @@ } /* transform transparency to alpha */ - if ( png_get_valid(png, info, PNG_INFO_tRNS ) ) + if ( png_get_valid( png, info, PNG_INFO_tRNS ) ) png_set_tRNS_to_alpha( png ); if ( bitdepth == 16 ) @@ -387,7 +387,7 @@ png_set_filler( png, 0xFF, PNG_FILLER_AFTER ); /* recheck header after setting EXPAND options */ - png_read_update_info(png, info ); + png_read_update_info( png, info ); png_get_IHDR( png, info, &imgWidth, &imgHeight, &bitdepth, &color_type, &interlace, diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c 2022-10-10 13:07:22.000000000 +0000 @@ -1066,7 +1066,8 @@ */ if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC || face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX || - face->colr ) + face->colr || + face->svg ) flags |= FT_FACE_FLAG_COLOR; /* color glyphs */ if ( has_outline == TRUE ) diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c 2022-10-10 13:07:22.000000000 +0000 @@ -973,7 +973,7 @@ /* composite glyph */ FT_Bool have_instructions = FALSE; FT_UShort instruction_size = 0; - FT_ULong composite_size; + FT_ULong composite_size = 0; FT_ULong size_needed; FT_Byte* pointer = NULL; @@ -2104,7 +2104,7 @@ error = FT_THROW( Invalid_Table ); goto Exit; } - file_offset = ROUND4(woff2.metaOffset + woff2.metaLength); + file_offset = ROUND4( woff2.metaOffset + woff2.metaLength ); } if ( woff2.privOffset ) @@ -2114,7 +2114,7 @@ error = FT_THROW( Invalid_Table ); goto Exit; } - file_offset = ROUND4(woff2.privOffset + woff2.privLength); + file_offset = ROUND4( woff2.privOffset + woff2.privLength ); } if ( file_offset != ( ROUND4( woff2.length ) ) ) diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c 2022-10-10 13:07:22.000000000 +0000 @@ -465,7 +465,7 @@ if ( subheader ) { FT_Byte* p = subheader; - FT_UInt idx = (FT_UInt)(char_code & 0xFF); + FT_UInt idx = (FT_UInt)( char_code & 0xFF ); FT_UInt start, count; FT_Int delta; FT_UInt offset; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c 2022-10-10 13:07:22.000000000 +0000 @@ -1104,8 +1104,8 @@ for ( ; vec < limit; vec++, u++ ) { - vec->x = ( FT_MulFix( u->x, x_scale ) + 32 ) >> 6; - vec->y = ( FT_MulFix( u->y, y_scale ) + 32 ) >> 6; + vec->x = ADD_LONG( FT_MulFix( u->x, x_scale ), 32 ) >> 6; + vec->y = ADD_LONG( FT_MulFix( u->y, y_scale ), 32 ) >> 6; } } else @@ -1228,8 +1228,8 @@ p1 = gloader->base.outline.points + k; p2 = gloader->base.outline.points + l; - x = p1->x - p2->x; - y = p1->y - p2->y; + x = SUB_LONG( p1->x, p2->x ); + y = SUB_LONG( p1->y, p2->y ); } else { @@ -2255,7 +2255,7 @@ if ( loader->widthp ) glyph->metrics.horiAdvance = loader->widthp[glyph_index] * 64; else - glyph->metrics.horiAdvance = SUB_LONG(loader->pp2.x, loader->pp1.x); + glyph->metrics.horiAdvance = SUB_LONG( loader->pp2.x, loader->pp1.x ); /* set glyph dimensions */ glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin ); diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c 2022-10-10 13:07:22.000000000 +0000 @@ -516,14 +516,6 @@ exec->GS.round_state = 1; exec->GS.loop = 1; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - exec->iup_called = FALSE; -#endif -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - exec->iupx_called = FALSE; - exec->iupy_called = FALSE; -#endif - /* some glyphs leave something on the stack. so we clean it */ /* before a new execution. */ exec->top = 0; @@ -7847,6 +7839,15 @@ Compute_Funcs( exc ); Compute_Round( exc, (FT_Byte)exc->GS.round_state ); + /* These flags cancel execution of some opcodes after IUP is called */ +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + exc->iup_called = FALSE; +#endif +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + exc->iupx_called = FALSE; + exc->iupy_called = FALSE; +#endif + do { exc->opcode = exc->code[exc->IP]; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c 2022-10-10 13:07:22.000000000 +0000 @@ -203,7 +203,7 @@ kp->index1 = FT_Get_Char_Index( t1_face, p[0] ); kp->index2 = FT_Get_Char_Index( t1_face, p[1] ); - kp->x = (FT_Int)FT_PEEK_SHORT_LE(p + 2); + kp->x = (FT_Int)FT_PEEK_SHORT_LE( p + 2 ); kp->y = 0; kp++; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/type1/t1load.c openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/type1/t1load.c --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libfreetype/src/type1/t1load.c 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libfreetype/src/type1/t1load.c 2022-10-10 13:07:22.000000000 +0000 @@ -2057,9 +2057,9 @@ name_table->elements[n][len] = '\0'; /* record index of /.notdef */ - if ( *cur == '.' && + if ( *cur == '.' && ft_strcmp( ".notdef", - (const char*)(name_table->elements[n]) ) == 0 ) + (const char*)( name_table->elements[n] ) ) == 0 ) { notdef_index = n; notdef_found = 1; @@ -2331,8 +2331,8 @@ /* in valid Type 1 fonts we don't see `RD' or `-|' directly */ /* since those tokens are handled by parse_subrs and */ /* parse_charstrings */ - else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' && - have_integer ) + else if ( *cur == 'R' && cur + 6 < limit && *( cur + 1 ) == 'D' && + have_integer ) { FT_ULong s; FT_Byte* b; @@ -2344,8 +2344,8 @@ have_integer = 0; } - else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' && - have_integer ) + else if ( *cur == '-' && cur + 6 < limit && *( cur + 1 ) == '|' && + have_integer ) { FT_ULong s; FT_Byte* b; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/graph/graph.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/graph/graph.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/graph/graph.hh 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/graph/graph.hh 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,860 @@ +/* + * Copyright © 2022 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#ifndef GRAPH_GRAPH_HH +#define GRAPH_GRAPH_HH + +namespace graph { + +/** + * Represents a serialized table in the form of a graph. + * Provides methods for modifying and reordering the graph. + */ +struct graph_t +{ + struct vertex_t + { + hb_serialize_context_t::object_t obj; + int64_t distance = 0 ; + int64_t space = 0 ; + hb_vector_t parents; + unsigned start = 0; + unsigned end = 0; + unsigned priority = 0; + + friend void swap (vertex_t& a, vertex_t& b) + { + hb_swap (a.obj, b.obj); + hb_swap (a.distance, b.distance); + hb_swap (a.space, b.space); + hb_swap (a.parents, b.parents); + hb_swap (a.start, b.start); + hb_swap (a.end, b.end); + hb_swap (a.priority, b.priority); + } + + bool is_shared () const + { + return parents.length > 1; + } + + unsigned incoming_edges () const + { + return parents.length; + } + + void remove_parent (unsigned parent_index) + { + for (unsigned i = 0; i < parents.length; i++) + { + if (parents[i] != parent_index) continue; + parents.remove (i); + break; + } + } + + void remap_parents (const hb_vector_t& id_map) + { + for (unsigned i = 0; i < parents.length; i++) + parents[i] = id_map[parents[i]]; + } + + void remap_parent (unsigned old_index, unsigned new_index) + { + for (unsigned i = 0; i < parents.length; i++) + { + if (parents[i] == old_index) + parents[i] = new_index; + } + } + + bool is_leaf () const + { + return !obj.real_links.length && !obj.virtual_links.length; + } + + bool raise_priority () + { + if (has_max_priority ()) return false; + priority++; + return true; + } + + bool has_max_priority () const { + return priority >= 3; + } + + int64_t modified_distance (unsigned order) const + { + // TODO(garretrieger): once priority is high enough, should try + // setting distance = 0 which will force to sort immediately after + // it's parent where possible. + + int64_t modified_distance = + hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFFF); + if (has_max_priority ()) { + modified_distance = 0; + } + return (modified_distance << 18) | (0x003FFFF & order); + } + + int64_t distance_modifier () const + { + if (!priority) return 0; + int64_t table_size = obj.tail - obj.head; + + if (priority == 1) + return -table_size / 2; + + return -table_size; + } + }; + + /* + * A topological sorting of an object graph. Ordered + * in reverse serialization order (first object in the + * serialization is at the end of the list). This matches + * the 'packed' object stack used internally in the + * serializer + */ + template + graph_t (const T& objects) + : parents_invalid (true), + distance_invalid (true), + positions_invalid (true), + successful (true) + { + num_roots_for_space_.push (1); + bool removed_nil = false; + vertices_.alloc (objects.length); + vertices_scratch_.alloc (objects.length); + for (unsigned i = 0; i < objects.length; i++) + { + // TODO(grieger): check all links point to valid objects. + + // If this graph came from a serialization buffer object 0 is the + // nil object. We don't need it for our purposes here so drop it. + if (i == 0 && !objects[i]) + { + removed_nil = true; + continue; + } + + vertex_t* v = vertices_.push (); + if (check_success (!vertices_.in_error ())) + v->obj = *objects[i]; + if (!removed_nil) continue; + // Fix indices to account for removed nil object. + for (auto& l : v->obj.all_links_writer ()) { + l.objidx--; + } + } + } + + ~graph_t () + { + vertices_.fini (); + } + + bool in_error () const + { + return !successful || + vertices_.in_error () || + num_roots_for_space_.in_error (); + } + + const vertex_t& root () const + { + return vertices_[root_idx ()]; + } + + unsigned root_idx () const + { + // Object graphs are in reverse order, the first object is at the end + // of the vector. Since the graph is topologically sorted it's safe to + // assume the first object has no incoming edges. + return vertices_.length - 1; + } + + const hb_serialize_context_t::object_t& object(unsigned i) const + { + return vertices_[i].obj; + } + + /* + * Generates a new topological sorting of graph ordered by the shortest + * distance to each node. + */ + void sort_shortest_distance () + { + positions_invalid = true; + + if (vertices_.length <= 1) { + // Graph of 1 or less doesn't need sorting. + return; + } + + update_distances (); + + hb_priority_queue_t queue; + hb_vector_t &sorted_graph = vertices_scratch_; + if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return; + hb_vector_t id_map; + if (unlikely (!check_success (id_map.resize (vertices_.length)))) return; + + hb_vector_t removed_edges; + if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return; + update_parents (); + + queue.insert (root ().modified_distance (0), root_idx ()); + int new_id = root_idx (); + unsigned order = 1; + while (!queue.in_error () && !queue.is_empty ()) + { + unsigned next_id = queue.pop_minimum().second; + + hb_swap (sorted_graph[new_id], vertices_[next_id]); + const vertex_t& next = sorted_graph[new_id]; + + id_map[next_id] = new_id--; + + for (const auto& link : next.obj.all_links ()) { + removed_edges[link.objidx]++; + if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx])) + // Add the order that the links were encountered to the priority. + // This ensures that ties between priorities objects are broken in a consistent + // way. More specifically this is set up so that if a set of objects have the same + // distance they'll be added to the topological order in the order that they are + // referenced from the parent object. + queue.insert (vertices_[link.objidx].modified_distance (order++), + link.objidx); + } + } + + check_success (!queue.in_error ()); + check_success (!sorted_graph.in_error ()); + if (!check_success (new_id == -1)) + print_orphaned_nodes (); + + remap_all_obj_indices (id_map, &sorted_graph); + + hb_swap (vertices_, sorted_graph); + } + + /* + * Assign unique space numbers to each connected subgraph of 32 bit offset(s). + */ + bool assign_32bit_spaces () + { + unsigned root_index = root_idx (); + hb_set_t visited; + hb_set_t roots; + for (unsigned i = 0; i <= root_index; i++) + { + // Only real links can form 32 bit spaces + for (auto& l : vertices_[i].obj.real_links) + { + if (l.width == 4 && !l.is_signed) + { + roots.add (l.objidx); + find_subgraph (l.objidx, visited); + } + } + } + + // Mark everything not in the subgraphs of 32 bit roots as visited. + // This prevents 32 bit subgraphs from being connected via nodes not in the 32 bit subgraphs. + visited.invert (); + + if (!roots) return false; + + while (roots) + { + unsigned next = HB_SET_VALUE_INVALID; + if (unlikely (!check_success (!roots.in_error ()))) break; + if (!roots.next (&next)) break; + + hb_set_t connected_roots; + find_connected_nodes (next, roots, visited, connected_roots); + if (unlikely (!check_success (!connected_roots.in_error ()))) break; + + isolate_subgraph (connected_roots); + if (unlikely (!check_success (!connected_roots.in_error ()))) break; + + unsigned next_space = this->next_space (); + num_roots_for_space_.push (0); + for (unsigned root : connected_roots) + { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Subgraph %u gets space %u", root, next_space); + vertices_[root].space = next_space; + num_roots_for_space_[next_space] = num_roots_for_space_[next_space] + 1; + distance_invalid = true; + positions_invalid = true; + } + + // TODO(grieger): special case for GSUB/GPOS use extension promotions to move 16 bit space + // into the 32 bit space as needed, instead of using isolation. + } + + + + return true; + } + + /* + * Isolates the subgraph of nodes reachable from root. Any links to nodes in the subgraph + * that originate from outside of the subgraph will be removed by duplicating the linked to + * object. + * + * Indices stored in roots will be updated if any of the roots are duplicated to new indices. + */ + bool isolate_subgraph (hb_set_t& roots) + { + update_parents (); + hb_map_t subgraph; + + // incoming edges to root_idx should be all 32 bit in length so we don't need to de-dup these + // set the subgraph incoming edge count to match all of root_idx's incoming edges + hb_set_t parents; + for (unsigned root_idx : roots) + { + subgraph.set (root_idx, wide_parents (root_idx, parents)); + find_subgraph (root_idx, subgraph); + } + + unsigned original_root_idx = root_idx (); + hb_map_t index_map; + bool made_changes = false; + for (auto entry : subgraph.iter ()) + { + const auto& node = vertices_[entry.first]; + unsigned subgraph_incoming_edges = entry.second; + + if (subgraph_incoming_edges < node.incoming_edges ()) + { + // Only de-dup objects with incoming links from outside the subgraph. + made_changes = true; + duplicate_subgraph (entry.first, index_map); + } + } + + if (!made_changes) + return false; + + if (original_root_idx != root_idx () + && parents.has (original_root_idx)) + { + // If the root idx has changed since parents was determined, update root idx in parents + parents.add (root_idx ()); + parents.del (original_root_idx); + } + + auto new_subgraph = + + subgraph.keys () + | hb_map([&] (unsigned node_idx) { + const unsigned *v; + if (index_map.has (node_idx, &v)) return *v; + return node_idx; + }) + ; + + remap_obj_indices (index_map, new_subgraph); + remap_obj_indices (index_map, parents.iter (), true); + + // Update roots set with new indices as needed. + unsigned next = HB_SET_VALUE_INVALID; + while (roots.next (&next)) + { + const unsigned *v; + if (index_map.has (next, &v)) + { + roots.del (next); + roots.add (*v); + } + } + + return true; + } + + void find_subgraph (unsigned node_idx, hb_map_t& subgraph) + { + for (const auto& link : vertices_[node_idx].obj.all_links ()) + { + const unsigned *v; + if (subgraph.has (link.objidx, &v)) + { + subgraph.set (link.objidx, *v + 1); + continue; + } + subgraph.set (link.objidx, 1); + find_subgraph (link.objidx, subgraph); + } + } + + void find_subgraph (unsigned node_idx, hb_set_t& subgraph) + { + if (subgraph.has (node_idx)) return; + subgraph.add (node_idx); + for (const auto& link : vertices_[node_idx].obj.all_links ()) + find_subgraph (link.objidx, subgraph); + } + + /* + * duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign + * links. index_map is updated with mappings from old id to new id. If a duplication has already + * been performed for a given index, then it will be skipped. + */ + void duplicate_subgraph (unsigned node_idx, hb_map_t& index_map) + { + if (index_map.has (node_idx)) + return; + + index_map.set (node_idx, duplicate (node_idx)); + for (const auto& l : object (node_idx).all_links ()) { + duplicate_subgraph (l.objidx, index_map); + } + } + + /* + * Creates a copy of node_idx and returns it's new index. + */ + unsigned duplicate (unsigned node_idx) + { + positions_invalid = true; + distance_invalid = true; + + auto* clone = vertices_.push (); + auto& child = vertices_[node_idx]; + if (vertices_.in_error ()) { + return -1; + } + + clone->obj.head = child.obj.head; + clone->obj.tail = child.obj.tail; + clone->distance = child.distance; + clone->space = child.space; + clone->parents.reset (); + + unsigned clone_idx = vertices_.length - 2; + for (const auto& l : child.obj.real_links) + { + clone->obj.real_links.push (l); + vertices_[l.objidx].parents.push (clone_idx); + } + for (const auto& l : child.obj.virtual_links) + { + clone->obj.virtual_links.push (l); + vertices_[l.objidx].parents.push (clone_idx); + } + + check_success (!clone->obj.real_links.in_error ()); + check_success (!clone->obj.virtual_links.in_error ()); + + // The last object is the root of the graph, so swap back the root to the end. + // The root's obj idx does change, however since it's root nothing else refers to it. + // all other obj idx's will be unaffected. + hb_swap (vertices_[vertices_.length - 2], *clone); + + // Since the root moved, update the parents arrays of all children on the root. + for (const auto& l : root ().obj.all_links ()) + vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ()); + + return clone_idx; + } + + /* + * Creates a copy of child and re-assigns the link from + * parent to the clone. The copy is a shallow copy, objects + * linked from child are not duplicated. + */ + bool duplicate (unsigned parent_idx, unsigned child_idx) + { + update_parents (); + + unsigned links_to_child = 0; + for (const auto& l : vertices_[parent_idx].obj.all_links ()) + { + if (l.objidx == child_idx) links_to_child++; + } + + if (vertices_[child_idx].incoming_edges () <= links_to_child) + { + // Can't duplicate this node, doing so would orphan the original one as all remaining links + // to child are from parent. + DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %d => %d", + parent_idx, child_idx); + return false; + } + + DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d", + parent_idx, child_idx); + + unsigned clone_idx = duplicate (child_idx); + if (clone_idx == (unsigned) -1) return false; + // duplicate shifts the root node idx, so if parent_idx was root update it. + if (parent_idx == clone_idx) parent_idx++; + + auto& parent = vertices_[parent_idx]; + for (auto& l : parent.obj.all_links_writer ()) + { + if (l.objidx != child_idx) + continue; + + reassign_link (l, parent_idx, clone_idx); + } + + return true; + } + + /* + * Raises the sorting priority of all children. + */ + bool raise_childrens_priority (unsigned parent_idx) + { + DEBUG_MSG (SUBSET_REPACK, nullptr, " Raising priority of all children of %d", + parent_idx); + // This operation doesn't change ordering until a sort is run, so no need + // to invalidate positions. It does not change graph structure so no need + // to update distances or edge counts. + auto& parent = vertices_[parent_idx].obj; + bool made_change = false; + for (auto& l : parent.all_links_writer ()) + made_change |= vertices_[l.objidx].raise_priority (); + return made_change; + } + + void print_orphaned_nodes () + { + if (!DEBUG_ENABLED(SUBSET_REPACK)) return; + + DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected."); + parents_invalid = true; + update_parents(); + + for (unsigned i = 0; i < root_idx (); i++) + { + const auto& v = vertices_[i]; + if (!v.parents) + DEBUG_MSG (SUBSET_REPACK, nullptr, "Node %u is orphaned.", i); + } + } + + unsigned num_roots_for_space (unsigned space) const + { + return num_roots_for_space_[space]; + } + + unsigned next_space () const + { + return num_roots_for_space_.length; + } + + void move_to_new_space (const hb_set_t& indices) + { + num_roots_for_space_.push (0); + unsigned new_space = num_roots_for_space_.length - 1; + + for (unsigned index : indices) { + auto& node = vertices_[index]; + num_roots_for_space_[node.space] = num_roots_for_space_[node.space] - 1; + num_roots_for_space_[new_space] = num_roots_for_space_[new_space] + 1; + node.space = new_space; + distance_invalid = true; + positions_invalid = true; + } + } + + unsigned space_for (unsigned index, unsigned* root = nullptr) const + { + const auto& node = vertices_[index]; + if (node.space) + { + if (root != nullptr) + *root = index; + return node.space; + } + + if (!node.parents) + { + if (root) + *root = index; + return 0; + } + + return space_for (node.parents[0], root); + } + + void err_other_error () { this->successful = false; } + + size_t total_size_in_bytes () const { + size_t total_size = 0; + for (unsigned i = 0; i < vertices_.length; i++) { + size_t size = vertices_[i].obj.tail - vertices_[i].obj.head; + total_size += size; + } + return total_size; + } + + + private: + + /* + * Returns the numbers of incoming edges that are 32bits wide. + */ + unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const + { + unsigned count = 0; + hb_set_t visited; + for (unsigned p : vertices_[node_idx].parents) + { + if (visited.has (p)) continue; + visited.add (p); + + // Only real links can be wide + for (const auto& l : vertices_[p].obj.real_links) + { + if (l.objidx == node_idx && l.width == 4 && !l.is_signed) + { + count++; + parents.add (p); + } + } + } + return count; + } + + bool check_success (bool success) + { return this->successful && (success || ((void) err_other_error (), false)); } + + public: + /* + * Creates a map from objid to # of incoming edges. + */ + void update_parents () + { + if (!parents_invalid) return; + + for (unsigned i = 0; i < vertices_.length; i++) + vertices_[i].parents.reset (); + + for (unsigned p = 0; p < vertices_.length; p++) + { + for (auto& l : vertices_[p].obj.all_links ()) + { + vertices_[l.objidx].parents.push (p); + } + } + + parents_invalid = false; + } + + /* + * compute the serialized start and end positions for each vertex. + */ + void update_positions () + { + if (!positions_invalid) return; + + unsigned current_pos = 0; + for (int i = root_idx (); i >= 0; i--) + { + auto& v = vertices_[i]; + v.start = current_pos; + current_pos += v.obj.tail - v.obj.head; + v.end = current_pos; + } + + positions_invalid = false; + } + + /* + * Finds the distance to each object in the graph + * from the initial node. + */ + void update_distances () + { + if (!distance_invalid) return; + + // Uses Dijkstra's algorithm to find all of the shortest distances. + // https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm + // + // Implementation Note: + // Since our priority queue doesn't support fast priority decreases + // we instead just add new entries into the queue when a priority changes. + // Redundant ones are filtered out later on by the visited set. + // According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf + // for practical performance this is faster then using a more advanced queue + // (such as a fibonacci queue) with a fast decrease priority. + for (unsigned i = 0; i < vertices_.length; i++) + { + if (i == vertices_.length - 1) + vertices_[i].distance = 0; + else + vertices_[i].distance = hb_int_max (int64_t); + } + + hb_priority_queue_t queue; + queue.insert (0, vertices_.length - 1); + + hb_vector_t visited; + visited.resize (vertices_.length); + + while (!queue.in_error () && !queue.is_empty ()) + { + unsigned next_idx = queue.pop_minimum ().second; + if (visited[next_idx]) continue; + const auto& next = vertices_[next_idx]; + int64_t next_distance = vertices_[next_idx].distance; + visited[next_idx] = true; + + for (const auto& link : next.obj.all_links ()) + { + if (visited[link.objidx]) continue; + + const auto& child = vertices_[link.objidx].obj; + unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide + int64_t child_weight = (child.tail - child.head) + + ((int64_t) 1 << (link_width * 8)) * (vertices_[link.objidx].space + 1); + int64_t child_distance = next_distance + child_weight; + + if (child_distance < vertices_[link.objidx].distance) + { + vertices_[link.objidx].distance = child_distance; + queue.insert (child_distance, link.objidx); + } + } + } + + check_success (!queue.in_error ()); + if (!check_success (queue.is_empty ())) + { + print_orphaned_nodes (); + return; + } + + distance_invalid = false; + } + + private: + /* + * Updates a link in the graph to point to a different object. Corrects the + * parents vector on the previous and new child nodes. + */ + void reassign_link (hb_serialize_context_t::object_t::link_t& link, + unsigned parent_idx, + unsigned new_idx) + { + unsigned old_idx = link.objidx; + link.objidx = new_idx; + vertices_[old_idx].remove_parent (parent_idx); + vertices_[new_idx].parents.push (parent_idx); + } + + /* + * Updates all objidx's in all links using the provided mapping. Corrects incoming edge counts. + */ + template + void remap_obj_indices (const hb_map_t& id_map, + Iterator subgraph, + bool only_wide = false) + { + if (!id_map) return; + for (unsigned i : subgraph) + { + for (auto& link : vertices_[i].obj.all_links_writer ()) + { + const unsigned *v; + if (!id_map.has (link.objidx, &v)) continue; + if (only_wide && !(link.width == 4 && !link.is_signed)) continue; + + reassign_link (link, i, *v); + } + } + } + + /* + * Updates all objidx's in all links using the provided mapping. + */ + void remap_all_obj_indices (const hb_vector_t& id_map, + hb_vector_t* sorted_graph) const + { + for (unsigned i = 0; i < sorted_graph->length; i++) + { + (*sorted_graph)[i].remap_parents (id_map); + for (auto& link : (*sorted_graph)[i].obj.all_links_writer ()) + { + link.objidx = id_map[link.objidx]; + } + } + } + + /* + * Finds all nodes in targets that are reachable from start_idx, nodes in visited will be skipped. + * For this search the graph is treated as being undirected. + * + * Connected targets will be added to connected and removed from targets. All visited nodes + * will be added to visited. + */ + void find_connected_nodes (unsigned start_idx, + hb_set_t& targets, + hb_set_t& visited, + hb_set_t& connected) + { + if (unlikely (!check_success (!visited.in_error ()))) return; + if (visited.has (start_idx)) return; + visited.add (start_idx); + + if (targets.has (start_idx)) + { + targets.del (start_idx); + connected.add (start_idx); + } + + const auto& v = vertices_[start_idx]; + + // Graph is treated as undirected so search children and parents of start_idx + for (const auto& l : v.obj.all_links ()) + find_connected_nodes (l.objidx, targets, visited, connected); + + for (unsigned p : v.parents) + find_connected_nodes (p, targets, visited, connected); + } + + public: + // TODO(garretrieger): make private, will need to move most of offset overflow code into graph. + hb_vector_t vertices_; + hb_vector_t vertices_scratch_; + private: + bool parents_invalid; + bool distance_invalid; + bool positions_invalid; + bool successful; + hb_vector_t num_roots_for_space_; +}; + +} + +#endif // GRAPH_GRAPH_HH diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/graph/serialize.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/graph/serialize.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/graph/serialize.hh 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/graph/serialize.hh 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,249 @@ +/* + * Copyright © 2022 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger + */ + +#ifndef GRAPH_SERIALIZE_HH +#define GRAPH_SERIALIZE_HH + +namespace graph { + +struct overflow_record_t +{ + unsigned parent; + unsigned child; +}; + +inline +int64_t compute_offset ( + const graph_t& graph, + unsigned parent_idx, + const hb_serialize_context_t::object_t::link_t& link) +{ + const auto& parent = graph.vertices_[parent_idx]; + const auto& child = graph.vertices_[link.objidx]; + int64_t offset = 0; + switch ((hb_serialize_context_t::whence_t) link.whence) { + case hb_serialize_context_t::whence_t::Head: + offset = child.start - parent.start; break; + case hb_serialize_context_t::whence_t::Tail: + offset = child.start - parent.end; break; + case hb_serialize_context_t::whence_t::Absolute: + offset = child.start; break; + } + + assert (offset >= link.bias); + offset -= link.bias; + return offset; +} + +inline +bool is_valid_offset (int64_t offset, + const hb_serialize_context_t::object_t::link_t& link) +{ + if (unlikely (!link.width)) + // Virtual links can't overflow. + return link.is_signed || offset >= 0; + + if (link.is_signed) + { + if (link.width == 4) + return offset >= -((int64_t) 1 << 31) && offset < ((int64_t) 1 << 31); + else + return offset >= -(1 << 15) && offset < (1 << 15); + } + else + { + if (link.width == 4) + return offset >= 0 && offset < ((int64_t) 1 << 32); + else if (link.width == 3) + return offset >= 0 && offset < ((int32_t) 1 << 24); + else + return offset >= 0 && offset < (1 << 16); + } +} + +/* + * Will any offsets overflow on graph when it's serialized? + */ +inline bool +will_overflow (graph_t& graph, + hb_vector_t* overflows = nullptr) +{ + if (overflows) overflows->resize (0); + graph.update_positions (); + + const auto& vertices = graph.vertices_; + for (int parent_idx = vertices.length - 1; parent_idx >= 0; parent_idx--) + { + // Don't need to check virtual links for overflow + for (const auto& link : vertices[parent_idx].obj.real_links) + { + int64_t offset = compute_offset (graph, parent_idx, link); + if (is_valid_offset (offset, link)) + continue; + + if (!overflows) return true; + + overflow_record_t r; + r.parent = parent_idx; + r.child = link.objidx; + overflows->push (r); + } + } + + if (!overflows) return false; + return overflows->length; +} + +inline +void print_overflows (graph_t& graph, + const hb_vector_t& overflows) +{ + if (!DEBUG_ENABLED(SUBSET_REPACK)) return; + + graph.update_parents (); + int limit = 10; + for (const auto& o : overflows) + { + if (!limit--) break; + const auto& parent = graph.vertices_[o.parent]; + const auto& child = graph.vertices_[o.child]; + DEBUG_MSG (SUBSET_REPACK, nullptr, + " overflow from " + "%4d (%4d in, %4d out, space %2d) => " + "%4d (%4d in, %4d out, space %2d)", + o.parent, + parent.incoming_edges (), + parent.obj.real_links.length + parent.obj.virtual_links.length, + graph.space_for (o.parent), + o.child, + child.incoming_edges (), + child.obj.real_links.length + child.obj.virtual_links.length, + graph.space_for (o.child)); + } + if (overflows.length > 10) { + DEBUG_MSG (SUBSET_REPACK, nullptr, " ... plus %d more overflows.", overflows.length - 10); + } +} + +template inline void +serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link, + char* head, + hb_serialize_context_t* c) +{ + OT::Offset* offset = reinterpret_cast*> (head + link.position); + *offset = 0; + c->add_link (*offset, + // serializer has an extra nil object at the start of the + // object array. So all id's are +1 of what our id's are. + link.objidx + 1, + (hb_serialize_context_t::whence_t) link.whence, + link.bias); +} + +inline +void serialize_link (const hb_serialize_context_t::object_t::link_t& link, + char* head, + hb_serialize_context_t* c) +{ + switch (link.width) + { + case 0: + // Virtual links aren't serialized. + return; + case 4: + if (link.is_signed) + { + serialize_link_of_type (link, head, c); + } else { + serialize_link_of_type (link, head, c); + } + return; + case 2: + if (link.is_signed) + { + serialize_link_of_type (link, head, c); + } else { + serialize_link_of_type (link, head, c); + } + return; + case 3: + serialize_link_of_type (link, head, c); + return; + default: + // Unexpected link width. + assert (0); + } +} + +/* + * serialize graph into the provided serialization buffer. + */ +inline hb_blob_t* serialize (const graph_t& graph) +{ + hb_vector_t buffer; + size_t size = graph.total_size_in_bytes (); + if (!buffer.alloc (size)) { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer."); + return nullptr; + } + hb_serialize_context_t c((void *) buffer, size); + + c.start_serialize (); + const auto& vertices = graph.vertices_; + for (unsigned i = 0; i < vertices.length; i++) { + c.push (); + + size_t size = vertices[i].obj.tail - vertices[i].obj.head; + char* start = c.allocate_size (size); + if (!start) { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Buffer out of space."); + return nullptr; + } + + memcpy (start, vertices[i].obj.head, size); + + // Only real links needs to be serialized. + for (const auto& link : vertices[i].obj.real_links) + serialize_link (link, start, &c); + + // All duplications are already encoded in the graph, so don't + // enable sharing during packing. + c.pop_pack (false); + } + c.end_serialize (); + + if (c.in_error ()) { + DEBUG_MSG (SUBSET_REPACK, nullptr, "Error during serialization. Err flag: %d", + c.errors); + return nullptr; + } + + return c.copy_blob (); +} + +} // namespace graph + +#endif // GRAPH_SERIALIZE_HH diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-ankr-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-ankr-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-ankr-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-ankr-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -54,7 +54,7 @@ DEFINE_SIZE_STATIC (4); }; -typedef LArrayOf GlyphAnchors; +typedef Array32Of GlyphAnchors; struct ankr { @@ -64,7 +64,7 @@ unsigned int i, unsigned int num_glyphs) const { - const NNOffsetTo *offset = (this+lookupTable).get_value (glyph_id, num_glyphs); + const NNOffset16To *offset = (this+lookupTable).get_value (glyph_id, num_glyphs); if (!offset) return Null (Anchor); const GlyphAnchors &anchors = &(this+anchorData) + *offset; @@ -83,9 +83,9 @@ protected: HBUINT16 version; /* Version number (set to zero) */ HBUINT16 flags; /* Flags (currently unused; set to zero) */ - LOffsetTo>> + Offset32To>> lookupTable; /* Offset to the table's lookup table */ - LNNOffsetTo + NNOffset32To anchorData; /* Offset to the glyph data table */ public: diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-bsln-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-bsln-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-bsln-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-bsln-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -82,7 +82,7 @@ } protected: - HBGlyphID stdGlyph; /* The specific glyph index number in this + HBGlyphID16 stdGlyph; /* The specific glyph index number in this * font that is used to set the baseline values. * This is the standard glyph. * This glyph must contain a set of control points @@ -105,7 +105,7 @@ } protected: - HBGlyphID stdGlyph; /* ditto */ + HBGlyphID16 stdGlyph; /* ditto */ HBUINT16 ctlPoints[32]; /* ditto */ Lookup lookupTable; /* Lookup table that maps glyphs to their diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc 2022-10-10 13:07:22.000000000 +0000 @@ -55,6 +55,7 @@ buffer (buffer_), sanitizer (), ankr_table (&Null (AAT::ankr)), + gdef_table (face->table.GDEF->table), lookup_index (0) { sanitizer.init (blob); @@ -107,7 +108,7 @@ {HB_TAG ('f','r','a','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS}, {HB_TAG ('f','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT, (hb_aat_layout_feature_selector_t) 7}, {HB_TAG ('h','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7}, - {HB_TAG ('h','i','s','t'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF}, + {HB_TAG ('h','i','s','t'), (hb_aat_layout_feature_type_t) 40, (hb_aat_layout_feature_selector_t) 0, (hb_aat_layout_feature_selector_t) 1}, {HB_TAG ('h','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF}, {HB_TAG ('h','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF}, {HB_TAG ('h','n','g','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION, HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION}, @@ -169,6 +170,7 @@ {HB_TAG ('v','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF}, {HB_TAG ('v','p','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7}, {HB_TAG ('v','r','t','2'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF}, + {HB_TAG ('v','r','t','r'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, (hb_aat_layout_feature_selector_t) 2, (hb_aat_layout_feature_selector_t) 3}, {HB_TAG ('z','e','r','o'), HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF}, }; @@ -248,7 +250,9 @@ if (morx.has_data ()) { AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob); + if (!buffer->message (font, "start table morx")) return; morx.apply (&c); + (void) buffer->message (font, "end table morx"); return; } @@ -257,7 +261,9 @@ if (mort.has_data ()) { AAT::hb_aat_apply_context_t c (plan, font, buffer, mort_blob); + if (!buffer->message (font, "start table mort")) return; mort.apply (&c); + (void) buffer->message (font, "end table mort"); return; } } @@ -313,8 +319,10 @@ const AAT::kerx& kerx = *kerx_blob->as (); AAT::hb_aat_apply_context_t c (plan, font, buffer, kerx_blob); + if (!buffer->message (font, "start table kerx")) return; c.set_ankr_table (font->face->table.ankr.get ()); kerx.apply (&c); + (void) buffer->message (font, "end table kerx"); } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh 2022-10-10 13:07:22.000000000 +0000 @@ -30,6 +30,9 @@ #include "hb-aat-layout.hh" #include "hb-open-type.hh" +namespace OT { +struct GDEF; +}; namespace AAT { @@ -93,8 +96,8 @@ return_trace (c->check_struct (this) && value.sanitize (c, base)); } - HBGlyphID last; /* Last GlyphID in this segment */ - HBGlyphID first; /* First GlyphID in this segment */ + HBGlyphID16 last; /* Last GlyphID in this segment */ + HBGlyphID16 first; /* First GlyphID in this segment */ T value; /* The lookup value (only one) */ public: DEFINE_SIZE_STATIC (4 + T::static_size); @@ -159,12 +162,12 @@ TRACE_SANITIZE (this); return_trace (c->check_struct (this) && first <= last && - valuesZ.sanitize (c, base, last - first + 1, hb_forward (ds)...)); + valuesZ.sanitize (c, base, last - first + 1, std::forward (ds)...)); } - HBGlyphID last; /* Last GlyphID in this segment */ - HBGlyphID first; /* First GlyphID in this segment */ - NNOffsetTo> + HBGlyphID16 last; /* Last GlyphID in this segment */ + HBGlyphID16 first; /* First GlyphID in this segment */ + NNOffset16To> valuesZ; /* A 16-bit offset from the start of * the table to the data. */ public: @@ -222,7 +225,7 @@ return_trace (c->check_struct (this) && value.sanitize (c, base)); } - HBGlyphID glyph; /* Last GlyphID */ + HBGlyphID16 glyph; /* Last GlyphID */ T value; /* The lookup value (only one) */ public: DEFINE_SIZE_STATIC (2 + T::static_size); @@ -284,7 +287,7 @@ protected: HBUINT16 format; /* Format identifier--format = 8 */ - HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */ + HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */ HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last * glyph minus the value of firstGlyph plus 1). */ UnsizedArrayOf @@ -326,7 +329,7 @@ protected: HBUINT16 format; /* Format identifier--format = 8 */ HBUINT16 valueSize; /* Byte size of each value. */ - HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */ + HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */ HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last * glyph minus the value of firstGlyph plus 1). */ UnsizedArrayOf @@ -658,8 +661,8 @@ return_trace (c->check_struct (this) && classArray.sanitize (c)); } protected: - HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */ - ArrayOf classArray; /* The class codes (indexed by glyph index minus + HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */ + Array16Of classArray; /* The class codes (indexed by glyph index minus * firstGlyph). */ public: DEFINE_SIZE_ARRAY (4, classArray); @@ -678,7 +681,8 @@ const void *base, const T *array) { - return (offset - ((const char *) array - (const char *) base)) / T::static_size; + /* https://github.com/harfbuzz/harfbuzz/issues/2816 */ + return (offset - unsigned ((const char *) array - (const char *) base)) / T::static_size; } template static unsigned int byteOffsetToIndex (unsigned int offset, @@ -835,7 +839,7 @@ } if (!c->in_place) - buffer->swap_buffers (); + buffer->sync (); } public: @@ -862,6 +866,7 @@ hb_buffer_t *buffer; hb_sanitize_context_t sanitizer; const ankr *ankr_table; + const OT::GDEF *gdef_table; /* Unused. For debug tracing only. */ unsigned int lookup_index; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-feat-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-feat-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-feat-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-feat-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -144,7 +144,7 @@ protected: HBUINT16 feature; /* Feature type. */ HBUINT16 nSettings; /* The number of records in the setting name array. */ - LNNOffsetTo> + NNOffset32To> settingTableZ; /* Offset in bytes from the beginning of this table to * this feature's setting name array. The actual type of * record this offset refers to will depend on the diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-just-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-just-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-just-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-just-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -79,7 +79,7 @@ * to decompose before more frequent ones. The ligatures * on the line of text will decompose in increasing * value of this field. */ - ArrayOf + Array16Of decomposedglyphs; /* Number of 16-bit glyph indexes that follow; * the ligature will be decomposed into these glyphs. @@ -100,7 +100,7 @@ protected: ActionSubrecordHeader header; - HBGlyphID addGlyph; /* Glyph that should be added if the distance factor + HBGlyphID16 addGlyph; /* Glyph that should be added if the distance factor * is growing. */ public: @@ -121,11 +121,11 @@ HBFixed substThreshold; /* Distance growth factor (in ems) at which * this glyph is replaced and the growth factor * recalculated. */ - HBGlyphID addGlyph; /* Glyph to be added as kashida. If this value is + HBGlyphID16 addGlyph; /* Glyph to be added as kashida. If this value is * 0xFFFF, no extra glyph will be added. Note that * generally when a glyph is added, justification * will need to be redone. */ - HBGlyphID substGlyph; /* Glyph to be substituted for this glyph if the + HBGlyphID16 substGlyph; /* Glyph to be substituted for this glyph if the * growth factor equals or exceeds the value of * substThreshold. */ public: @@ -146,7 +146,7 @@ HBUINT32 variationAxis; /* The 4-byte tag identifying the ductile axis. * This would normally be 0x64756374 ('duct'), * but you may use any axis the font contains. */ - HBFixed minimumLimit; /* The lowest value for the ductility axis tha + HBFixed minimumLimit; /* The lowest value for the ductility axis that * still yields an acceptable appearance. Normally * this will be 1.0. */ HBFixed noStretchValue; /* This is the default value that corresponds to @@ -170,7 +170,7 @@ ActionSubrecordHeader header; HBUINT16 flags; /* Currently unused; set to 0. */ - HBGlyphID glyph; /* Glyph that should be added if the distance factor + HBGlyphID16 glyph; /* Glyph that should be added if the distance factor * is growing. */ public: DEFINE_SIZE_STATIC (10); @@ -310,7 +310,7 @@ DEFINE_SIZE_STATIC (24); }; -typedef OT::LArrayOf WidthDeltaCluster; +typedef OT::Array32Of WidthDeltaCluster; struct JustificationCategory { @@ -358,20 +358,20 @@ } protected: - OffsetTo + Offset16To justClassTable; /* Offset to the justification category state table. */ - OffsetTo + Offset16To wdcTable; /* Offset from start of justification table to start * of the subtable containing the width delta factors * for the glyphs in your font. * * The width delta clusters table. */ - OffsetTo + Offset16To pcTable; /* Offset from start of justification table to start * of postcompensation subtable (set to zero if none). * * The postcompensation subtable, if present in the font. */ - Lookup> + Lookup> lookupTable; /* Lookup table associating glyphs with width delta * clusters. See the description of Width Delta Clusters * table for details on how to interpret the lookup values. */ @@ -398,13 +398,13 @@ FixedVersion<>version; /* Version of the justification table * (0x00010000u for version 1.0). */ HBUINT16 format; /* Format of the justification table (set to 0). */ - OffsetTo + Offset16To horizData; /* Byte offset from the start of the justification table * to the header for tables that contain justification * information for horizontal text. * If you are not including this information, * store 0. */ - OffsetTo + Offset16To vertData; /* ditto, vertical */ public: diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -82,8 +82,8 @@ } protected: - HBGlyphID left; - HBGlyphID right; + HBGlyphID16 left; + HBGlyphID16 right; FWORD value; public: DEFINE_SIZE_STATIC (6); @@ -287,7 +287,7 @@ * in the 'kern' table example. */ if (v == -0x8000) { - o.attach_type() = ATTACH_TYPE_NONE; + o.attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_NONE; o.attach_chain() = 0; o.y_offset = 0; } @@ -310,7 +310,7 @@ /* CoreText doesn't do crossStream kerning in vertical. We do. */ if (v == -0x8000) { - o.attach_type() = ATTACH_TYPE_NONE; + o.attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_NONE; o.attach_chain() = 0; o.x_offset = 0; } @@ -567,7 +567,7 @@ } break; } - o.attach_type() = ATTACH_TYPE_MARK; + o.attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_MARK; o.attach_chain() = (int) mark - (int) buffer->idx; buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; } @@ -710,18 +710,18 @@ { struct Long { - LNNOffsetTo> rowIndexTable; - LNNOffsetTo> columnIndexTable; - LNNOffsetTo> array; + NNOffset32To> rowIndexTable; + NNOffset32To> columnIndexTable; + NNOffset32To> array; } l; struct Short { - LNNOffsetTo> rowIndexTable; - LNNOffsetTo> columnIndexTable; - LNNOffsetTo> array; + NNOffset32To> rowIndexTable; + NNOffset32To> columnIndexTable; + NNOffset32To> array; } s; } u; - LNNOffsetTo> vector; + NNOffset32To> vector; public: DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 24); }; @@ -775,11 +775,11 @@ unsigned int subtable_type = get_type (); TRACE_DISPATCH (this, subtable_type); switch (subtable_type) { - case 0: return_trace (c->dispatch (u.format0, hb_forward (ds)...)); - case 1: return_trace (c->dispatch (u.format1, hb_forward (ds)...)); - case 2: return_trace (c->dispatch (u.format2, hb_forward (ds)...)); - case 4: return_trace (c->dispatch (u.format4, hb_forward (ds)...)); - case 6: return_trace (c->dispatch (u.format6, hb_forward (ds)...)); + case 0: return_trace (c->dispatch (u.format0, std::forward (ds)...)); + case 1: return_trace (c->dispatch (u.format1, std::forward (ds)...)); + case 2: return_trace (c->dispatch (u.format2, std::forward (ds)...)); + case 4: return_trace (c->dispatch (u.format4, std::forward (ds)...)); + case 6: return_trace (c->dispatch (u.format6, std::forward (ds)...)); default: return_trace (c->default_return_value ()); } } @@ -901,7 +901,7 @@ unsigned int count = c->buffer->len; for (unsigned int i = 0; i < count; i++) { - pos[i].attach_type() = ATTACH_TYPE_CURSIVE; + pos[i].attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_CURSIVE; pos[i].attach_chain() = HB_DIRECTION_IS_FORWARD (c->buffer->props.direction) ? -1 : +1; /* We intentionally don't set HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT, * since there needs to be a non-zero attachment for post-positioning to diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -30,6 +30,7 @@ #include "hb-open-type.hh" #include "hb-aat-layout-common.hh" #include "hb-ot-layout-common.hh" +#include "hb-ot-layout-gdef-table.hh" #include "hb-aat-map.hh" /* @@ -122,7 +123,7 @@ bool reverse_l = 3 == (m >> 4); bool reverse_r = 3 == (m & 0x0F); - if (end - start >= l + r) + if (end - start >= l + r && end-start <= HB_MAX_CONTEXT_LENGTH) { buffer->merge_clusters (start, hb_min (buffer->idx + 1, buffer->len)); buffer->merge_clusters (start, end); @@ -215,7 +216,9 @@ hb_aat_apply_context_t *c_) : ret (false), c (c_), + gdef (*c->gdef_table), mark_set (false), + has_glyph_classes (gdef.has_glyph_classes ()), mark (0), table (table_), subs (table+table->substitutionTables) {} @@ -240,21 +243,21 @@ if (buffer->idx == buffer->len && !mark_set) return; - const HBGlyphID *replacement; + const HBGlyphID16 *replacement; replacement = nullptr; if (Types::extended) { if (entry.data.markIndex != 0xFFFF) { - const Lookup &lookup = subs[entry.data.markIndex]; + const Lookup &lookup = subs[entry.data.markIndex]; replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs); } } else { unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint; - const UnsizedArrayOf &subs_old = (const UnsizedArrayOf &) subs; + const UnsizedArrayOf &subs_old = (const UnsizedArrayOf &) subs; replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)]; if (!replacement->sanitize (&c->sanitizer) || !*replacement) replacement = nullptr; @@ -263,6 +266,9 @@ { buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len)); buffer->info[mark].codepoint = *replacement; + if (has_glyph_classes) + _hb_glyph_info_set_glyph_props (&buffer->info[mark], + gdef.get_glyph_props (*replacement)); ret = true; } @@ -272,14 +278,14 @@ { if (entry.data.currentIndex != 0xFFFF) { - const Lookup &lookup = subs[entry.data.currentIndex]; + const Lookup &lookup = subs[entry.data.currentIndex]; replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs); } } else { unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint; - const UnsizedArrayOf &subs_old = (const UnsizedArrayOf &) subs; + const UnsizedArrayOf &subs_old = (const UnsizedArrayOf &) subs; replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)]; if (!replacement->sanitize (&c->sanitizer) || !*replacement) replacement = nullptr; @@ -287,6 +293,9 @@ if (replacement) { buffer->info[idx].codepoint = *replacement; + if (has_glyph_classes) + _hb_glyph_info_set_glyph_props (&buffer->info[idx], + gdef.get_glyph_props (*replacement)); ret = true; } @@ -301,10 +310,12 @@ bool ret; private: hb_aat_apply_context_t *c; + const OT::GDEF &gdef; bool mark_set; + bool has_glyph_classes; unsigned int mark; const ContextualSubtable *table; - const UnsizedOffsetListOf, HBUINT, false> &subs; + const UnsizedListOfOffset16To, HBUINT, false> &subs; }; bool apply (hb_aat_apply_context_t *c) const @@ -348,7 +359,7 @@ protected: StateTable machine; - NNOffsetTo, HBUINT, false>, HBUINT> + NNOffsetTo, HBUINT, false>, HBUINT> substitutionTables; public: DEFINE_SIZE_STATIC (20); @@ -520,7 +531,7 @@ if (action & (LigActionStore | LigActionLast)) { ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ); - const HBGlyphID &ligatureData = ligature[ligature_idx]; + const HBGlyphID16 &ligatureData = ligature[ligature_idx]; if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break; hb_codepoint_t lig = ligatureData; @@ -554,7 +565,7 @@ const LigatureSubtable *table; const UnsizedArrayOf &ligAction; const UnsizedArrayOf &component; - const UnsizedArrayOf &ligature; + const UnsizedArrayOf &ligature; unsigned int match_length; unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; }; @@ -586,7 +597,7 @@ ligAction; /* Offset to the ligature action table. */ NNOffsetTo, HBUINT> component; /* Offset to the component table. */ - NNOffsetTo, HBUINT> + NNOffsetTo, HBUINT> ligature; /* Offset to the actual ligature lists. */ public: DEFINE_SIZE_STATIC (28); @@ -599,6 +610,9 @@ { TRACE_APPLY (this); + const OT::GDEF &gdef (*c->gdef_table); + bool has_glyph_classes = gdef.has_glyph_classes (); + bool ret = false; unsigned int num_glyphs = c->face->get_num_glyphs (); @@ -606,10 +620,13 @@ unsigned int count = c->buffer->len; for (unsigned int i = 0; i < count; i++) { - const HBGlyphID *replacement = substitute.get_value (info[i].codepoint, num_glyphs); + const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs); if (replacement) { info[i].codepoint = *replacement; + if (has_glyph_classes) + _hb_glyph_info_set_glyph_props (&info[i], + gdef.get_glyph_props (*replacement)); ret = true; } } @@ -624,7 +641,7 @@ } protected: - Lookup substitute; + Lookup substitute; public: DEFINE_SIZE_MIN (2); }; @@ -727,7 +744,7 @@ unsigned int count = (flags & MarkedInsertCount); if (unlikely ((buffer->max_ops -= count) <= 0)) return; unsigned int start = entry.data.markedInsertIndex; - const HBGlyphID *glyphs = &insertionAction[start]; + const HBGlyphID16 *glyphs = &insertionAction[start]; if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0; bool before = flags & MarkedInsertBefore; @@ -755,7 +772,7 @@ unsigned int count = (flags & CurrentInsertCount) >> 5; if (unlikely ((buffer->max_ops -= count) <= 0)) return; unsigned int start = entry.data.currentInsertIndex; - const HBGlyphID *glyphs = &insertionAction[start]; + const HBGlyphID16 *glyphs = &insertionAction[start]; if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0; bool before = flags & CurrentInsertBefore; @@ -793,7 +810,7 @@ private: hb_aat_apply_context_t *c; unsigned int mark; - const UnsizedArrayOf &insertionAction; + const UnsizedArrayOf &insertionAction; }; bool apply (hb_aat_apply_context_t *c) const @@ -819,7 +836,7 @@ protected: StateTable machine; - NNOffsetTo, HBUINT> + NNOffsetTo, HBUINT> insertionAction; /* Byte offset from stateHeader to the start of * the insertion glyph table. */ public: @@ -889,11 +906,11 @@ unsigned int subtable_type = get_type (); TRACE_DISPATCH (this, subtable_type); switch (subtable_type) { - case Rearrangement: return_trace (c->dispatch (u.rearrangement, hb_forward (ds)...)); - case Contextual: return_trace (c->dispatch (u.contextual, hb_forward (ds)...)); - case Ligature: return_trace (c->dispatch (u.ligature, hb_forward (ds)...)); - case Noncontextual: return_trace (c->dispatch (u.noncontextual, hb_forward (ds)...)); - case Insertion: return_trace (c->dispatch (u.insertion, hb_forward (ds)...)); + case Rearrangement: return_trace (c->dispatch (u.rearrangement, std::forward (ds)...)); + case Contextual: return_trace (c->dispatch (u.contextual, std::forward (ds)...)); + case Ligature: return_trace (c->dispatch (u.ligature, std::forward (ds)...)); + case Noncontextual: return_trace (c->dispatch (u.noncontextual, std::forward (ds)...)); + case Insertion: return_trace (c->dispatch (u.insertion, std::forward (ds)...)); default: return_trace (c->default_return_value ()); } } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-opbd-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-opbd-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-opbd-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-opbd-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -58,7 +58,7 @@ bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id, hb_glyph_extents_t *extents, const void *base) const { - const OffsetTo *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ()); + const Offset16To *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ()); if (!bounds_offset) return false; const OpticalBounds &bounds = base+*bounds_offset; @@ -79,7 +79,7 @@ } protected: - Lookup> + Lookup> lookupTable; /* Lookup table associating glyphs with the four * int16 values for the left-side, top-side, * right-side, and bottom-side optical bounds. */ @@ -92,7 +92,7 @@ bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id, hb_glyph_extents_t *extents, const void *base) const { - const OffsetTo *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ()); + const Offset16To *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ()); if (!bounds_offset) return false; const OpticalBounds &bounds = base+*bounds_offset; @@ -116,7 +116,7 @@ } protected: - Lookup> + Lookup> lookupTable; /* Lookup table associating glyphs with the four * int16 values for the left-side, top-side, * right-side, and bottom-side optical bounds. */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -66,7 +66,7 @@ NameID trackNameID; /* The 'name' table index for this track. * (a short word or phrase like "loose" * or "very tight") */ - NNOffsetTo> + NNOffset16To> valuesZ; /* Offset from start of tracking table to * per-size tracking values for this track. */ @@ -141,7 +141,7 @@ protected: HBUINT16 nTracks; /* Number of separate tracks included in this table. */ HBUINT16 nSizes; /* Number of point sizes included in this table. */ - LNNOffsetTo> + NNOffset32To> sizeTable; /* Offset from start of the tracking table to * Array[nSizes] of size values.. */ UnsizedArrayOf @@ -212,10 +212,10 @@ FixedVersion<>version; /* Version of the tracking table * (0x00010000u for version 1.0). */ HBUINT16 format; /* Format of the tracking table (set to 0). */ - OffsetTo + Offset16To horizData; /* Offset from start of tracking table to TrackData * for horizontal text (or 0 if none). */ - OffsetTo + Offset16To vertData; /* Offset from start of tracking table to TrackData * for vertical text (or 0 if none). */ HBUINT16 reserved; /* Reserved. Set to 0. */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-ltag-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-ltag-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-aat-ltag-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-aat-ltag-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -50,7 +50,7 @@ } protected: - NNOffsetTo> + NNOffset16To> tag; /* Offset from the start of the table to * the beginning of the string */ HBUINT16 length; /* String length (in bytes) */ @@ -80,7 +80,7 @@ protected: HBUINT32 version; /* Table version; currently 1 */ HBUINT32 flags; /* Table flags; currently none defined */ - LArrayOf + Array32Of tagRanges; /* Range for each tag's string */ public: DEFINE_SIZE_ARRAY (12, tagRanges); diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-algs.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-algs.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-algs.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-algs.hh 2022-10-10 13:07:22.000000000 +0000 @@ -34,6 +34,10 @@ #include "hb-null.hh" #include "hb-number.hh" +#include +#include +#include +#include /* * Flags @@ -55,7 +59,7 @@ static inline constexpr T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \ static inline constexpr T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \ static inline constexpr T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \ - static inline constexpr T operator ~ (T r) { return T (~(unsigned int) r); } \ + static inline constexpr unsigned operator ~ (T r) { return (~(unsigned) r); } \ static inline T& operator |= (T &l, T r) { l = l | r; return l; } \ static inline T& operator &= (T& l, T r) { l = l & r; return l; } \ static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \ @@ -125,7 +129,7 @@ template struct BEInt { - static_assert (!hb_is_signed (Type), ""); + static_assert (!std::is_signed::value, ""); public: BEInt () = default; constexpr BEInt (Type V) : v {uint8_t ((V >> 16) & 0xFF), @@ -146,10 +150,26 @@ uint8_t ((V >> 16) & 0xFF), uint8_t ((V >> 8) & 0xFF), uint8_t ((V ) & 0xFF)} {} - constexpr operator Type () const { return (v[0] << 24) - + (v[1] << 16) - + (v[2] << 8) - + (v[3] ); } + + struct __attribute__((packed)) packed_uint32_t { uint32_t v; }; + constexpr operator Type () const { +#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \ + defined(__BYTE_ORDER) && \ + (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN) + /* Spoon-feed the compiler a big-endian integer with alignment 1. + * https://github.com/harfbuzz/harfbuzz/pull/1398 */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + return __builtin_bswap32 (((packed_uint32_t *) this)->v); +#else /* __BYTE_ORDER == __BIG_ENDIAN */ + return ((packed_uint32_t *) this)->v; +#endif +#else + return (v[0] << 24) + + (v[1] << 16) + + (v[2] << 8) + + (v[3] ); +#endif + } private: uint8_t v[4]; }; @@ -179,7 +199,7 @@ { /* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */ template constexpr auto - operator () (T&& v) const HB_AUTO_RETURN ( hb_forward (v) ) + operator () (T&& v) const HB_AUTO_RETURN ( std::forward (v) ) } HB_FUNCOBJ (hb_identity); struct @@ -203,7 +223,7 @@ struct { template constexpr bool - operator () (T&& v) const { return bool (hb_forward (v)); } + operator () (T&& v) const { return bool (std::forward (v)); } } HB_FUNCOBJ (hb_bool); @@ -214,13 +234,19 @@ template constexpr auto impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ()) - template constexpr auto - impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN - ( - /* Knuth's multiplicative method: */ - (uint32_t) v * 2654435761u - ) + template constexpr uint32_t + impl (const hb::shared_ptr& v, hb_priority<1>) const + { + return v.get () ? v.get ()->hash () : 0; + } + template constexpr uint32_t + impl (const hb::unique_ptr& v, hb_priority<1>) const + { + return v.get () ? v.get ()->hash () : 0; + } + + template constexpr auto + impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash>{} (hb_deref (v))) public: @@ -237,26 +263,26 @@ /* Pointer-to-member-function. */ template auto impl (Appl&& a, hb_priority<2>, T &&v, Ts&&... ds) const HB_AUTO_RETURN - ((hb_deref (hb_forward (v)).*hb_forward (a)) (hb_forward (ds)...)) + ((hb_deref (std::forward (v)).*std::forward (a)) (std::forward (ds)...)) /* Pointer-to-member. */ template auto impl (Appl&& a, hb_priority<1>, T &&v) const HB_AUTO_RETURN - ((hb_deref (hb_forward (v))).*hb_forward (a)) + ((hb_deref (std::forward (v))).*std::forward (a)) /* Operator(). */ template auto impl (Appl&& a, hb_priority<0>, Ts&&... ds) const HB_AUTO_RETURN - (hb_deref (hb_forward (a)) (hb_forward (ds)...)) + (hb_deref (std::forward (a)) (std::forward (ds)...)) public: template auto operator () (Appl&& a, Ts&&... ds) const HB_AUTO_RETURN ( - impl (hb_forward (a), + impl (std::forward (a), hb_prioritize, - hb_forward (ds)...) + std::forward (ds)...) ) } HB_FUNCOBJ (hb_invoke); @@ -275,9 +301,9 @@ hb_declval (V), hb_declval (Ts)...)) { - return hb_invoke (hb_forward (a), - hb_forward (v), - hb_forward (ds)...); + return hb_invoke (std::forward (a), + std::forward (v), + std::forward (ds)...); } template (a), - hb_forward (d0), - hb_forward (v), - hb_forward (ds)...); + return hb_invoke (std::forward (a), + std::forward (d0), + std::forward (v), + std::forward (ds)...); } private: @@ -324,14 +350,14 @@ #define HB_PARTIALIZE(Pos) \ template \ decltype(auto) operator () (_T&& _v) const \ - { return hb_partial (this, hb_forward<_T> (_v)); } \ + { return hb_partial (this, std::forward<_T> (_v)); } \ static_assert (true, "") #else /* https://github.com/harfbuzz/harfbuzz/issues/1724 */ #define HB_PARTIALIZE(Pos) \ template \ auto operator () (_T&& _v) const HB_AUTO_RETURN \ - (hb_partial (+this, hb_forward<_T> (_v))) \ + (hb_partial (+this, std::forward<_T> (_v))) \ static_assert (true, "") #endif @@ -343,22 +369,22 @@ template auto impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN ( - hb_deref (hb_forward (p)).has (hb_forward (v)) + hb_deref (std::forward (p)).has (std::forward (v)) ) template auto impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN ( - hb_invoke (hb_forward (p), - hb_forward (v)) + hb_invoke (std::forward (p), + std::forward (v)) ) public: template auto operator () (Pred&& p, Val &&v) const HB_RETURN (bool, - impl (hb_forward (p), - hb_forward (v), + impl (std::forward (p), + std::forward (v), hb_prioritize) ) } @@ -371,22 +397,22 @@ template auto impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN ( - hb_has (hb_forward (p), - hb_forward (v)) + hb_has (std::forward (p), + std::forward (v)) ) template auto impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN ( - hb_forward (p) == hb_forward (v) + std::forward (p) == std::forward (v) ) public: template auto operator () (Pred&& p, Val &&v) const HB_RETURN (bool, - impl (hb_forward (p), - hb_forward (v), + impl (std::forward (p), + std::forward (v), hb_prioritize) ) } @@ -399,20 +425,20 @@ template auto impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN ( - hb_deref (hb_forward (f)).get (hb_forward (v)) + hb_deref (std::forward (f)).get (std::forward (v)) ) template auto impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN ( - hb_invoke (hb_forward (f), - hb_forward (v)) + hb_invoke (std::forward (f), + std::forward (v)) ) template auto impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN ( - hb_forward (f)[hb_forward (v)] + std::forward (f)[std::forward (v)] ) public: @@ -420,8 +446,8 @@ template auto operator () (Proj&& f, Val &&v) const HB_AUTO_RETURN ( - impl (hb_forward (f), - hb_forward (v), + impl (std::forward (f), + std::forward (v), hb_prioritize) ) } @@ -432,21 +458,27 @@ private: template auto + impl (T1&& v1, T2 &&v2, hb_priority<3>) const HB_AUTO_RETURN + ( + std::forward (v2).cmp (std::forward (v1)) == 0 + ) + + template auto impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN ( - hb_forward (v2).cmp (hb_forward (v1)) == 0 + std::forward (v1).cmp (std::forward (v2)) == 0 ) template auto impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN ( - hb_forward (v1).cmp (hb_forward (v2)) == 0 + std::forward (v1) == std::forward (v2) ) template auto impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN ( - hb_forward (v1) == hb_forward (v2) + std::forward (v2) == std::forward (v1) ) public: @@ -454,8 +486,8 @@ template auto operator () (T1&& v1, T2 &&v2) const HB_AUTO_RETURN ( - impl (hb_forward (v1), - hb_forward (v2), + impl (std::forward (v1), + std::forward (v2), hb_prioritize) ) } @@ -469,11 +501,15 @@ typedef T2 second_t; typedef hb_pair_t pair_t; + template ::value && + std::is_default_constructible::value)> + hb_pair_t () : first (), second () {} hb_pair_t (T1 a, T2 b) : first (a), second (b) {} template + hb_is_convertible (T2, Q2))> operator hb_pair_t () { return hb_pair_t (first, second); } hb_pair_t reverse () const @@ -515,24 +551,34 @@ { template constexpr auto operator () (T&& a, T2&& b) const HB_AUTO_RETURN - (a <= b ? hb_forward (a) : hb_forward (b)) + (a <= b ? std::forward (a) : std::forward (b)) } HB_FUNCOBJ (hb_min); struct { template constexpr auto operator () (T&& a, T2&& b) const HB_AUTO_RETURN - (a >= b ? hb_forward (a) : hb_forward (b)) + (a >= b ? std::forward (a) : std::forward (b)) } HB_FUNCOBJ (hb_max); struct { template constexpr auto operator () (T&& x, T2&& min, T3&& max) const HB_AUTO_RETURN - (hb_min (hb_max (hb_forward (x), hb_forward (min)), hb_forward (max))) + (hb_min (hb_max (std::forward (x), std::forward (min)), std::forward (max))) } HB_FUNCOBJ (hb_clamp); +struct +{ + template void + operator () (T& a, T& b) const + { + using std::swap; // allow ADL + swap (a, b); + } +} +HB_FUNCOBJ (hb_swap); /* * Bithacks. @@ -760,6 +806,14 @@ #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0]))) +static inline void * +hb_memcpy (void *__restrict dst, const void *__restrict src, size_t len) +{ + /* It's illegal to pass 0 as size to memcpy. */ + if (unlikely (!len)) return dst; + return memcpy (dst, src, len); +} + static inline int hb_memcmp (const void *a, const void *b, unsigned int len) { @@ -787,7 +841,7 @@ template static inline bool hb_in_range (T u, T lo, T hi) { - static_assert (!hb_is_signed::value, ""); + static_assert (!std::is_signed::value, ""); /* The casts below are important as if T is smaller than int, * the subtract results will become a signed int! */ @@ -803,6 +857,11 @@ { return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3); } +template static inline bool +hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3, T lo4, T hi4) +{ + return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3) || hb_in_range (u, lo4, hi4); +} /* @@ -849,7 +908,7 @@ #pragma GCC diagnostic ignored "-Wcast-align" V* p = (V*) (((const char *) base) + (mid * stride)); #pragma GCC diagnostic pop - int c = compar ((const void *) hb_addressof (key), (const void *) p, ds...); + int c = compar ((const void *) std::addressof (key), (const void *) p, ds...); if (c < 0) max = mid - 1; else if (c > 0) @@ -1151,30 +1210,48 @@ /* Operators. */ -struct hb_bitwise_and +struct { HB_PARTIALIZE(2); template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b) } HB_FUNCOBJ (hb_bitwise_and); -struct hb_bitwise_or +struct { HB_PARTIALIZE(2); template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b) } HB_FUNCOBJ (hb_bitwise_or); -struct hb_bitwise_xor +struct { HB_PARTIALIZE(2); template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b) } HB_FUNCOBJ (hb_bitwise_xor); -struct hb_bitwise_sub +struct +{ HB_PARTIALIZE(2); + template constexpr auto + operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a & b) +} +HB_FUNCOBJ (hb_bitwise_lt); +struct { HB_PARTIALIZE(2); template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b) } -HB_FUNCOBJ (hb_bitwise_sub); +HB_FUNCOBJ (hb_bitwise_gt); // aka sub +struct +{ HB_PARTIALIZE(2); + template constexpr auto + operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a | b) +} +HB_FUNCOBJ (hb_bitwise_le); +struct +{ HB_PARTIALIZE(2); + template constexpr auto + operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | ~b) +} +HB_FUNCOBJ (hb_bitwise_ge); struct { template constexpr auto @@ -1197,6 +1274,12 @@ struct { HB_PARTIALIZE(2); template constexpr auto + operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (b - a) +} +HB_FUNCOBJ (hb_rsub); +struct +{ HB_PARTIALIZE(2); + template constexpr auto operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b) } HB_FUNCOBJ (hb_mul); diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-array.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-array.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-array.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-array.hh 2022-10-10 13:07:22.000000000 +0000 @@ -36,20 +36,33 @@ template struct hb_sorted_array_t; +enum hb_not_found_t +{ + HB_NOT_FOUND_DONT_STORE, + HB_NOT_FOUND_STORE, + HB_NOT_FOUND_STORE_CLOSEST, +}; + + template struct hb_array_t : hb_iter_with_fallback_t, Type&> { /* * Constructors. */ - hb_array_t () : arrayZ (nullptr), length (0), backwards_length (0) {} - hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_), backwards_length (0) {} + hb_array_t () = default; + hb_array_t (const hb_array_t&) = default; + ~hb_array_t () = default; + hb_array_t& operator= (const hb_array_t&) = default; + hb_array_t& operator= (hb_array_t&&) = default; + + constexpr hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {} template - hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_), backwards_length (0) {} + constexpr hb_array_t (Type (&array_)[length_]) : hb_array_t (array_, length_) {} template - hb_array_t (const hb_array_t &o) : + constexpr hb_array_t (const hb_array_t &o) : hb_iter_with_fallback_t (), arrayZ (o.arrayZ), length (o.length), backwards_length (o.backwards_length) {} template arrayZ[i] : not_found; } template - bool lfind (const T &x, unsigned *pos = nullptr) const + bool lfind (const T &x, unsigned *pos = nullptr, + hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE, + unsigned int to_store = (unsigned int) -1) const { for (unsigned i = 0; i < length; ++i) if (hb_equal (x, this->arrayZ[i])) @@ -149,6 +164,22 @@ return true; } + if (pos) + { + switch (not_found) + { + case HB_NOT_FOUND_DONT_STORE: + break; + + case HB_NOT_FOUND_STORE: + *pos = to_store; + break; + + case HB_NOT_FOUND_STORE_CLOSEST: + *pos = length; + break; + } + } return false; } @@ -219,7 +250,7 @@ unsigned P = sizeof (Type), hb_enable_if (P == 1)> const T *as () const - { return length < hb_null_size (T) ? &Null (T) : reinterpret_cast (arrayZ); } + { return length < hb_min_size (T) ? &Null (T) : reinterpret_cast (arrayZ); } template = size; } - /* Only call if you allocated the underlying array using malloc() or similar. */ - void free () - { ::free ((void *) arrayZ); arrayZ = nullptr; length = 0; } + /* Only call if you allocated the underlying array using hb_malloc() or similar. */ + void fini () + { hb_free ((void *) arrayZ); arrayZ = nullptr; length = 0; } template hb_array_t copy (hb_serialize_context_t *c) const @@ -255,9 +286,9 @@ */ public: - Type *arrayZ; - unsigned int length; - unsigned int backwards_length; + Type *arrayZ = nullptr; + unsigned int length = 0; + unsigned int backwards_length = 0; }; template inline hb_array_t hb_array (T *array, unsigned int length) @@ -266,13 +297,6 @@ hb_array (T (&array_)[length_]) { return hb_array_t (array_); } -enum hb_bfind_not_found_t -{ - HB_BFIND_NOT_FOUND_DONT_STORE, - HB_BFIND_NOT_FOUND_STORE, - HB_BFIND_NOT_FOUND_STORE_CLOSEST, -}; - template struct hb_sorted_array_t : hb_iter_t, Type&>, @@ -283,14 +307,19 @@ static constexpr bool is_random_access_iterator = true; static constexpr bool is_sorted_iterator = true; - hb_sorted_array_t () : hb_array_t () {} - hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t (array_, length_) {} + hb_sorted_array_t () = default; + hb_sorted_array_t (const hb_sorted_array_t&) = default; + ~hb_sorted_array_t () = default; + hb_sorted_array_t& operator= (const hb_sorted_array_t&) = default; + hb_sorted_array_t& operator= (hb_sorted_array_t&&) = default; + + constexpr hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t (array_, length_) {} template - hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t (array_) {} + constexpr hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t (array_) {} template - hb_sorted_array_t (const hb_array_t &o) : + constexpr hb_sorted_array_t (const hb_array_t &o) : hb_iter_t (), hb_array_t (o) {} template arrayZ[i] : not_found; } - template + template const Type *bsearch (const T &x, const Type *not_found = nullptr) const { unsigned int i; @@ -323,7 +352,7 @@ } template bool bfind (const T &x, unsigned int *i = nullptr, - hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, + hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE, unsigned int to_store = (unsigned int) -1) const { unsigned pos; @@ -339,29 +368,30 @@ { switch (not_found) { - case HB_BFIND_NOT_FOUND_DONT_STORE: + case HB_NOT_FOUND_DONT_STORE: break; - case HB_BFIND_NOT_FOUND_STORE: + case HB_NOT_FOUND_STORE: *i = to_store; break; - case HB_BFIND_NOT_FOUND_STORE_CLOSEST: + case HB_NOT_FOUND_STORE_CLOSEST: *i = pos; break; } } return false; } - template - bool bsearch_impl (const T &x, unsigned *pos) const + template + bool bsearch_impl (const T &x, unsigned *pos, Ts... ds) const { return hb_bsearch_impl (pos, x, this->arrayZ, this->length, sizeof (Type), - _hb_cmp_method); + _hb_cmp_method, + ds...); } }; template inline hb_sorted_array_t @@ -372,7 +402,7 @@ { return hb_sorted_array_t (array_); } template -bool hb_array_t::operator == (const hb_array_t &o) const +inline bool hb_array_t::operator == (const hb_array_t &o) const { if (o.length != this->length) return false; for (unsigned int i = 0; i < this->length; i++) { @@ -380,8 +410,18 @@ } return true; } - -/* TODO Specialize opeator== for hb_bytes_t and hb_ubytes_t. */ +template <> +inline bool hb_array_t::operator == (const hb_array_t &o) const +{ + if (o.length != this->length) return false; + return 0 == hb_memcmp (arrayZ, o.arrayZ, length); +} +template <> +inline bool hb_array_t::operator == (const hb_array_t &o) const +{ + if (o.length != this->length) return false; + return 0 == hb_memcmp (arrayZ, o.arrayZ, length); +} template <> inline uint32_t hb_array_t::hash () const { @@ -390,7 +430,6 @@ current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u); return current; } - template <> inline uint32_t hb_array_t::hash () const { uint32_t current = 0; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh 2022-10-10 13:07:22.000000000 +0000 @@ -102,20 +102,12 @@ #define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N)) -#elif defined(HB_NO_MT) +#else /* defined(HB_NO_MT) */ #define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V)) - #define _hb_memory_barrier() do {} while (0) - #define hb_atomic_ptr_impl_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false) - -#else - -#error "Could not find any system to define atomic_int macros." -#error "Check hb-atomic.hh for possible resolutions." - #endif diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-bimap.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-bimap.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-bimap.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-bimap.hh 2022-10-10 13:07:22.000000000 +0000 @@ -33,42 +33,39 @@ /* Bi-directional map */ struct hb_bimap_t { - hb_bimap_t () { init (); } - ~hb_bimap_t () { fini (); } - - void init () - { - forw_map.init (); - back_map.init (); - } - - void fini () - { - forw_map.fini (); - back_map.fini (); - } - void reset () { forw_map.reset (); back_map.reset (); } + void resize (unsigned pop) + { + forw_map.resize (pop); + back_map.resize (pop); + } + bool in_error () const { return forw_map.in_error () || back_map.in_error (); } void set (hb_codepoint_t lhs, hb_codepoint_t rhs) { + if (in_error ()) return; if (unlikely (lhs == HB_MAP_VALUE_INVALID)) return; if (unlikely (rhs == HB_MAP_VALUE_INVALID)) { del (lhs); return; } + forw_map.set (lhs, rhs); + if (unlikely (in_error ())) return; + back_map.set (rhs, lhs); + if (unlikely (in_error ())) forw_map.del (lhs); } hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); } hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map.get (rhs); } hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); } - bool has (hb_codepoint_t lhs, hb_codepoint_t *vp = nullptr) const { return forw_map.has (lhs, vp); } + bool has (hb_codepoint_t lhs) const { return forw_map.has (lhs); } + void del (hb_codepoint_t lhs) { @@ -82,7 +79,7 @@ back_map.clear (); } - bool is_empty () const { return get_population () == 0; } + bool is_empty () const { return forw_map.is_empty (); } unsigned int get_population () const { return forw_map.get_population (); } @@ -94,14 +91,6 @@ /* Inremental bimap: only lhs is given, rhs is incrementally assigned */ struct hb_inc_bimap_t : hb_bimap_t { - hb_inc_bimap_t () { init (); } - - void init () - { - hb_bimap_t::init (); - next_value = 0; - } - /* Add a mapping from lhs to rhs with a unique value if lhs is unknown. * Return the rhs value as the result. */ @@ -160,7 +149,7 @@ } protected: - unsigned int next_value; + unsigned int next_value = 0; }; #endif /* HB_BIMAP_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-bit-page.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-bit-page.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-bit-page.hh 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-bit-page.hh 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,282 @@ +/* + * Copyright © 2012,2017 Google, Inc. + * Copyright © 2021 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_BIT_PAGE_HH +#define HB_BIT_PAGE_HH + +#include "hb.hh" + +struct hb_bit_page_t +{ + void init0 () { v.clear (); } + void init1 () { v.clear (0xFF); } + + constexpr unsigned len () const + { return ARRAY_LENGTH_CONST (v); } + + bool is_empty () const + { + for (unsigned i = 0; i < len (); i++) + if (v[i]) + return false; + return true; + } + uint32_t hash () const + { + uint32_t h = 0; + for (unsigned i = 0; i < len (); i++) + h = h * 31 + hb_hash (v[i]); + return h; + } + + void add (hb_codepoint_t g) { elt (g) |= mask (g); } + void del (hb_codepoint_t g) { elt (g) &= ~mask (g); } + void set (hb_codepoint_t g, bool v) { if (v) add (g); else del (g); } + bool get (hb_codepoint_t g) const { return elt (g) & mask (g); } + + void add_range (hb_codepoint_t a, hb_codepoint_t b) + { + elt_t *la = &elt (a); + elt_t *lb = &elt (b); + if (la == lb) + *la |= (mask (b) << 1) - mask(a); + else + { + *la |= ~(mask (a) - 1); + la++; + + memset (la, 0xff, (char *) lb - (char *) la); + + *lb |= ((mask (b) << 1) - 1); + } + } + void del_range (hb_codepoint_t a, hb_codepoint_t b) + { + elt_t *la = &elt (a); + elt_t *lb = &elt (b); + if (la == lb) + *la &= ~((mask (b) << 1) - mask(a)); + else + { + *la &= mask (a) - 1; + la++; + + memset (la, 0, (char *) lb - (char *) la); + + *lb &= ~((mask (b) << 1) - 1); + } + } + void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v) + { if (v) add_range (a, b); else del_range (a, b); } + + + // Writes out page values to the array p. Returns the number of values + // written. At most size codepoints will be written. + unsigned int write (uint32_t base, + unsigned int start_value, + hb_codepoint_t *p, + unsigned int size) const + { + unsigned int start_v = start_value >> ELT_BITS_LOG_2; + unsigned int start_bit = start_value & ELT_MASK; + unsigned int count = 0; + for (unsigned i = start_v; i < len () && count < size; i++) + { + elt_t bits = v[i]; + uint32_t v_base = base | (i << ELT_BITS_LOG_2); + for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++) + { + if ((elt_t(1) << j) & bits) { + *p++ = v_base | j; + count++; + } + } + start_bit = 0; + } + return count; + } + + // Writes out the values NOT in this page to the array p. Returns the + // number of values written. At most size codepoints will be written. + // Returns the number of codepoints written. next_value holds the next value + // that should be written (if not present in this page). This is used to fill + // any missing value gaps between this page and the previous page, if any. + // next_value is updated to one more than the last value present in this page. + unsigned int write_inverted (uint32_t base, + unsigned int start_value, + hb_codepoint_t *p, + unsigned int size, + hb_codepoint_t *next_value) const + { + unsigned int start_v = start_value >> ELT_BITS_LOG_2; + unsigned int start_bit = start_value & ELT_MASK; + unsigned int count = 0; + for (unsigned i = start_v; i < len () && count < size; i++) + { + elt_t bits = v[i]; + uint32_t v_offset = i << ELT_BITS_LOG_2; + for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++) + { + if ((elt_t(1) << j) & bits) + { + hb_codepoint_t value = base | v_offset | j; + // Emit all the missing values from next_value up to value - 1. + for (hb_codepoint_t k = *next_value; k < value && count < size; k++) + { + *p++ = k; + count++; + } + // Skip over this value; + *next_value = value + 1; + } + } + start_bit = 0; + } + return count; + } + + bool is_equal (const hb_bit_page_t &other) const + { + return 0 == hb_memcmp (&v, &other.v, sizeof (v)); + } + bool is_subset (const hb_bit_page_t &larger_page) const + { + for (unsigned i = 0; i < len (); i++) + if (~larger_page.v[i] & v[i]) + return false; + return true; + } + + unsigned int get_population () const + { + unsigned int pop = 0; + for (unsigned int i = 0; i < len (); i++) + pop += hb_popcount (v[i]); + return pop; + } + + bool next (hb_codepoint_t *codepoint) const + { + unsigned int m = (*codepoint + 1) & MASK; + if (!m) + { + *codepoint = INVALID; + return false; + } + unsigned int i = m / ELT_BITS; + unsigned int j = m & ELT_MASK; + + const elt_t vv = v[i] & ~((elt_t (1) << j) - 1); + for (const elt_t *p = &vv; i < len (); p = &v[++i]) + if (*p) + { + *codepoint = i * ELT_BITS + elt_get_min (*p); + return true; + } + + *codepoint = INVALID; + return false; + } + bool previous (hb_codepoint_t *codepoint) const + { + unsigned int m = (*codepoint - 1) & MASK; + if (m == MASK) + { + *codepoint = INVALID; + return false; + } + unsigned int i = m / ELT_BITS; + unsigned int j = m & ELT_MASK; + + /* Fancy mask to avoid shifting by elt_t bitsize, which is undefined. */ + const elt_t mask = j < 8 * sizeof (elt_t) - 1 ? + ((elt_t (1) << (j + 1)) - 1) : + (elt_t) -1; + const elt_t vv = v[i] & mask; + const elt_t *p = &vv; + while (true) + { + if (*p) + { + *codepoint = i * ELT_BITS + elt_get_max (*p); + return true; + } + if ((int) i <= 0) break; + p = &v[--i]; + } + + *codepoint = INVALID; + return false; + } + hb_codepoint_t get_min () const + { + for (unsigned int i = 0; i < len (); i++) + if (v[i]) + return i * ELT_BITS + elt_get_min (v[i]); + return INVALID; + } + hb_codepoint_t get_max () const + { + for (int i = len () - 1; i >= 0; i--) + if (v[i]) + return i * ELT_BITS + elt_get_max (v[i]); + return 0; + } + + static constexpr hb_codepoint_t INVALID = HB_SET_VALUE_INVALID; + + typedef unsigned long long elt_t; + static constexpr unsigned PAGE_BITS = 512; + static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, ""); + static constexpr unsigned PAGE_BITS_LOG_2 = 9; + static_assert (1 << PAGE_BITS_LOG_2 == PAGE_BITS, ""); + static constexpr unsigned PAGE_BITMASK = PAGE_BITS - 1; + + static unsigned int elt_get_min (const elt_t &elt) { return hb_ctz (elt); } + static unsigned int elt_get_max (const elt_t &elt) { return hb_bit_storage (elt) - 1; } + + typedef hb_vector_size_t vector_t; + + static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8; + static constexpr unsigned ELT_BITS_LOG_2 = 6; + static_assert (1 << ELT_BITS_LOG_2 == ELT_BITS, ""); + static constexpr unsigned ELT_MASK = ELT_BITS - 1; + + static constexpr unsigned BITS = sizeof (vector_t) * 8; + static constexpr unsigned MASK = BITS - 1; + static_assert ((unsigned) PAGE_BITS == (unsigned) BITS, ""); + + elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; } + const elt_t& elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; } + static constexpr elt_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); } + + vector_t v; +}; +static_assert (hb_bit_page_t::PAGE_BITS == sizeof (hb_bit_page_t) * 8, ""); + + +#endif /* HB_BIT_PAGE_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,953 @@ +/* + * Copyright © 2012,2017 Google, Inc. + * Copyright © 2021 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_BIT_SET_HH +#define HB_BIT_SET_HH + +#include "hb.hh" +#include "hb-bit-page.hh" +#include "hb-machinery.hh" + + +struct hb_bit_set_t +{ + hb_bit_set_t () = default; + ~hb_bit_set_t () = default; + + hb_bit_set_t (const hb_bit_set_t& other) : hb_bit_set_t () { set (other); } + hb_bit_set_t ( hb_bit_set_t&& other) : hb_bit_set_t () { hb_swap (*this, other); } + hb_bit_set_t& operator= (const hb_bit_set_t& other) { set (other); return *this; } + hb_bit_set_t& operator= (hb_bit_set_t&& other) { hb_swap (*this, other); return *this; } + friend void swap (hb_bit_set_t &a, hb_bit_set_t &b) + { + if (likely (!a.successful || !b.successful)) + return; + hb_swap (a.population, b.population); + hb_swap (a.last_page_lookup, b.last_page_lookup); + hb_swap (a.page_map, b.page_map); + hb_swap (a.pages, b.pages); + } + + void init () + { + successful = true; + population = 0; + last_page_lookup.set_relaxed (0); + page_map.init (); + pages.init (); + } + void fini () + { + page_map.fini (); + pages.fini (); + } + + using page_t = hb_bit_page_t; + struct page_map_t + { + int cmp (const page_map_t &o) const { return cmp (o.major); } + int cmp (uint32_t o_major) const { return (int) o_major - (int) major; } + + uint32_t major; + uint32_t index; + }; + + bool successful = true; /* Allocations successful */ + mutable unsigned int population = 0; + mutable hb_atomic_int_t last_page_lookup = 0; + hb_sorted_vector_t page_map; + hb_vector_t pages; + + void err () { if (successful) successful = false; } /* TODO Remove */ + bool in_error () const { return !successful; } + + bool resize (unsigned int count) + { + if (unlikely (!successful)) return false; + if (unlikely (!pages.resize (count) || !page_map.resize (count))) + { + pages.resize (page_map.length); + successful = false; + return false; + } + return true; + } + + void alloc (unsigned sz) + { + sz >>= (page_t::PAGE_BITS_LOG_2 - 1); + pages.alloc (sz); + page_map.alloc (sz); + } + + void reset () + { + successful = true; + clear (); + } + + void clear () + { + resize (0); + if (likely (successful)) + population = 0; + } + bool is_empty () const + { + unsigned int count = pages.length; + for (unsigned int i = 0; i < count; i++) + if (!pages[i].is_empty ()) + return false; + return true; + } + explicit operator bool () const { return !is_empty (); } + + uint32_t hash () const + { + uint32_t h = 0; + for (auto &map : page_map) + h = h * 31 + hb_hash (map.major) + hb_hash (pages[map.index]); + return h; + } + + private: + void dirty () { population = UINT_MAX; } + public: + + void add (hb_codepoint_t g) + { + if (unlikely (!successful)) return; + if (unlikely (g == INVALID)) return; + dirty (); + page_t *page = page_for (g, true); if (unlikely (!page)) return; + page->add (g); + } + bool add_range (hb_codepoint_t a, hb_codepoint_t b) + { + if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */ + if (unlikely (a > b || a == INVALID || b == INVALID)) return false; + dirty (); + unsigned int ma = get_major (a); + unsigned int mb = get_major (b); + if (ma == mb) + { + page_t *page = page_for (a, true); if (unlikely (!page)) return false; + page->add_range (a, b); + } + else + { + page_t *page = page_for (a, true); if (unlikely (!page)) return false; + page->add_range (a, major_start (ma + 1) - 1); + + for (unsigned int m = ma + 1; m < mb; m++) + { + page = page_for (major_start (m), true); if (unlikely (!page)) return false; + page->init1 (); + } + + page = page_for (b, true); if (unlikely (!page)) return false; + page->add_range (major_start (mb), b); + } + return true; + } + + template + void set_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { + if (unlikely (!successful)) return; + if (!count) return; + dirty (); + hb_codepoint_t g = *array; + while (count) + { + unsigned int m = get_major (g); + page_t *page = page_for (g, v); if (unlikely (v && !page)) return; + unsigned int start = major_start (m); + unsigned int end = major_start (m + 1); + do + { + if (v || page) /* The v check is to optimize out the page check if v is true. */ + page->set (g, v); + + array = &StructAtOffsetUnaligned (array, stride); + count--; + } + while (count && (g = *array, start <= g && g < end)); + } + } + + template + void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { set_array (true, array, count, stride); } + template + void add_array (const hb_array_t& arr) { add_array (&arr, arr.len ()); } + + template + void del_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { set_array (false, array, count, stride); } + template + void del_array (const hb_array_t& arr) { del_array (&arr, arr.len ()); } + + /* Might return false if array looks unsorted. + * Used for faster rejection of corrupt data. */ + template + bool set_sorted_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { + if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */ + if (unlikely (!count)) return true; + dirty (); + hb_codepoint_t g = *array; + hb_codepoint_t last_g = g; + while (count) + { + unsigned int m = get_major (g); + page_t *page = page_for (g, v); if (unlikely (v && !page)) return false; + unsigned int end = major_start (m + 1); + do + { + /* If we try harder we can change the following comparison to <=; + * Not sure if it's worth it. */ + if (g < last_g) return false; + last_g = g; + + if (v || page) /* The v check is to optimize out the page check if v is true. */ + page->add (g); + + array = &StructAtOffsetUnaligned (array, stride); + count--; + } + while (count && (g = *array, g < end)); + } + return true; + } + + template + bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { return set_sorted_array (true, array, count, stride); } + template + bool add_sorted_array (const hb_sorted_array_t& arr) { return add_sorted_array (&arr, arr.len ()); } + + template + bool del_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { return set_sorted_array (false, array, count, stride); } + template + bool del_sorted_array (const hb_sorted_array_t& arr) { return del_sorted_array (&arr, arr.len ()); } + + void del (hb_codepoint_t g) + { + if (unlikely (!successful)) return; + page_t *page = page_for (g); + if (!page) + return; + dirty (); + page->del (g); + } + + private: + void del_pages (int ds, int de) + { + if (ds <= de) + { + // Pre-allocate the workspace that compact() will need so we can bail on allocation failure + // before attempting to rewrite the page map. + hb_vector_t compact_workspace; + if (unlikely (!allocate_compact_workspace (compact_workspace))) return; + + unsigned int write_index = 0; + for (unsigned int i = 0; i < page_map.length; i++) + { + int m = (int) page_map[i].major; + if (m < ds || de < m) + page_map[write_index++] = page_map[i]; + } + compact (compact_workspace, write_index); + resize (write_index); + } + } + + + public: + void del_range (hb_codepoint_t a, hb_codepoint_t b) + { + if (unlikely (!successful)) return; + if (unlikely (a > b || a == INVALID)) return; + dirty (); + unsigned int ma = get_major (a); + unsigned int mb = get_major (b); + /* Delete pages from ds through de if ds <= de. */ + int ds = (a == major_start (ma))? (int) ma: (int) (ma + 1); + int de = (b + 1 == major_start (mb + 1))? (int) mb: ((int) mb - 1); + if (ds > de || (int) ma < ds) + { + page_t *page = page_for (a); + if (page) + { + if (ma == mb) + page->del_range (a, b); + else + page->del_range (a, major_start (ma + 1) - 1); + } + } + if (de < (int) mb && ma != mb) + { + page_t *page = page_for (b); + if (page) + page->del_range (major_start (mb), b); + } + del_pages (ds, de); + } + + bool get (hb_codepoint_t g) const + { + const page_t *page = page_for (g); + if (!page) + return false; + return page->get (g); + } + + /* Has interface. */ + static constexpr bool SENTINEL = false; + typedef bool value_t; + value_t operator [] (hb_codepoint_t k) const { return get (k); } + bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; } + /* Predicate. */ + bool operator () (hb_codepoint_t k) const { return has (k); } + + /* Sink interface. */ + hb_bit_set_t& operator << (hb_codepoint_t v) + { add (v); return *this; } + hb_bit_set_t& operator << (const hb_pair_t& range) + { add_range (range.first, range.second); return *this; } + + bool intersects (hb_codepoint_t first, hb_codepoint_t last) const + { + hb_codepoint_t c = first - 1; + return next (&c) && c <= last; + } + void set (const hb_bit_set_t &other) + { + if (unlikely (!successful)) return; + unsigned int count = other.pages.length; + if (unlikely (!resize (count))) + return; + population = other.population; + + page_map = other.page_map; + pages = other.pages; + } + + bool is_equal (const hb_bit_set_t &other) const + { + if (has_population () && other.has_population () && + population != other.population) + return false; + + unsigned int na = pages.length; + unsigned int nb = other.pages.length; + + unsigned int a = 0, b = 0; + for (; a < na && b < nb; ) + { + if (page_at (a).is_empty ()) { a++; continue; } + if (other.page_at (b).is_empty ()) { b++; continue; } + if (page_map[a].major != other.page_map[b].major || + !page_at (a).is_equal (other.page_at (b))) + return false; + a++; + b++; + } + for (; a < na; a++) + if (!page_at (a).is_empty ()) { return false; } + for (; b < nb; b++) + if (!other.page_at (b).is_empty ()) { return false; } + + return true; + } + + bool is_subset (const hb_bit_set_t &larger_set) const + { + if (has_population () && larger_set.has_population () && + population != larger_set.population) + return false; + + uint32_t spi = 0; + for (uint32_t lpi = 0; spi < page_map.length && lpi < larger_set.page_map.length; lpi++) + { + uint32_t spm = page_map[spi].major; + uint32_t lpm = larger_set.page_map[lpi].major; + auto sp = page_at (spi); + auto lp = larger_set.page_at (lpi); + + if (spm < lpm && !sp.is_empty ()) + return false; + + if (lpm < spm) + continue; + + if (!sp.is_subset (lp)) + return false; + + spi++; + } + + while (spi < page_map.length) + if (!page_at (spi++).is_empty ()) + return false; + + return true; + } + + private: + bool allocate_compact_workspace (hb_vector_t& workspace) + { + if (unlikely (!workspace.resize (pages.length))) + { + successful = false; + return false; + } + + return true; + } + + /* + * workspace should be a pre-sized vector allocated to hold at exactly pages.length + * elements. + */ + void compact (hb_vector_t& workspace, + unsigned int length) + { + assert(workspace.length == pages.length); + hb_vector_t& old_index_to_page_map_index = workspace; + + hb_fill (old_index_to_page_map_index.writer(), 0xFFFFFFFF); + for (unsigned i = 0; i < length; i++) + old_index_to_page_map_index[page_map[i].index] = i; + + compact_pages (old_index_to_page_map_index); + } + void compact_pages (const hb_vector_t& old_index_to_page_map_index) + { + unsigned int write_index = 0; + for (unsigned int i = 0; i < pages.length; i++) + { + if (old_index_to_page_map_index[i] == 0xFFFFFFFF) continue; + + if (write_index < i) + pages[write_index] = pages[i]; + + page_map[old_index_to_page_map_index[i]].index = write_index; + write_index++; + } + } + public: + + template + void process (const Op& op, const hb_bit_set_t &other) + { + const bool passthru_left = op (1, 0); + const bool passthru_right = op (0, 1); + + if (unlikely (!successful)) return; + + dirty (); + + unsigned int na = pages.length; + unsigned int nb = other.pages.length; + unsigned int next_page = na; + + unsigned int count = 0, newCount = 0; + unsigned int a = 0, b = 0; + unsigned int write_index = 0; + + // Pre-allocate the workspace that compact() will need so we can bail on allocation failure + // before attempting to rewrite the page map. + hb_vector_t compact_workspace; + if (!passthru_left && unlikely (!allocate_compact_workspace (compact_workspace))) return; + + for (; a < na && b < nb; ) + { + if (page_map[a].major == other.page_map[b].major) + { + if (!passthru_left) + { + // Move page_map entries that we're keeping from the left side set + // to the front of the page_map vector. This isn't necessary if + // passthru_left is set since no left side pages will be removed + // in that case. + if (write_index < a) + page_map[write_index] = page_map[a]; + write_index++; + } + + count++; + a++; + b++; + } + else if (page_map[a].major < other.page_map[b].major) + { + if (passthru_left) + count++; + a++; + } + else + { + if (passthru_right) + count++; + b++; + } + } + if (passthru_left) + count += na - a; + if (passthru_right) + count += nb - b; + + if (!passthru_left) + { + na = write_index; + next_page = write_index; + compact (compact_workspace, write_index); + } + + if (unlikely (!resize (count))) + return; + + newCount = count; + + /* Process in-place backward. */ + a = na; + b = nb; + for (; a && b; ) + { + if (page_map[a - 1].major == other.page_map[b - 1].major) + { + a--; + b--; + count--; + page_map[count] = page_map[a]; + page_at (count).v = op (page_at (a).v, other.page_at (b).v); + } + else if (page_map[a - 1].major > other.page_map[b - 1].major) + { + a--; + if (passthru_left) + { + count--; + page_map[count] = page_map[a]; + } + } + else + { + b--; + if (passthru_right) + { + count--; + page_map[count].major = other.page_map[b].major; + page_map[count].index = next_page++; + page_at (count).v = other.page_at (b).v; + } + } + } + if (passthru_left) + while (a) + { + a--; + count--; + page_map[count] = page_map [a]; + } + if (passthru_right) + while (b) + { + b--; + count--; + page_map[count].major = other.page_map[b].major; + page_map[count].index = next_page++; + page_at (count).v = other.page_at (b).v; + } + assert (!count); + resize (newCount); + } + + void union_ (const hb_bit_set_t &other) { process (hb_bitwise_or, other); } + void intersect (const hb_bit_set_t &other) { process (hb_bitwise_and, other); } + void subtract (const hb_bit_set_t &other) { process (hb_bitwise_gt, other); } + void symmetric_difference (const hb_bit_set_t &other) { process (hb_bitwise_xor, other); } + + bool next (hb_codepoint_t *codepoint) const + { + // TODO: this should be merged with prev() as both implementations + // are very similar. + if (unlikely (*codepoint == INVALID)) { + *codepoint = get_min (); + return *codepoint != INVALID; + } + + const auto* page_map_array = page_map.arrayZ; + unsigned int major = get_major (*codepoint); + unsigned int i = last_page_lookup.get_relaxed (); + + if (unlikely (i >= page_map.length || page_map_array[i].major != major)) + { + page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST); + if (i >= page_map.length) { + *codepoint = INVALID; + return false; + } + } + + const auto* pages_array = pages.arrayZ; + const page_map_t ¤t = page_map_array[i]; + if (likely (current.major == major)) + { + if (pages_array[current.index].next (codepoint)) + { + *codepoint += current.major * page_t::PAGE_BITS; + last_page_lookup.set_relaxed (i); + return true; + } + i++; + } + + for (; i < page_map.length; i++) + { + const page_map_t ¤t = page_map.arrayZ[i]; + hb_codepoint_t m = pages_array[current.index].get_min (); + if (m != INVALID) + { + *codepoint = current.major * page_t::PAGE_BITS + m; + last_page_lookup.set_relaxed (i); + return true; + } + } + last_page_lookup.set_relaxed (0); + *codepoint = INVALID; + return false; + } + bool previous (hb_codepoint_t *codepoint) const + { + if (unlikely (*codepoint == INVALID)) { + *codepoint = get_max (); + return *codepoint != INVALID; + } + + page_map_t map = {get_major (*codepoint), 0}; + unsigned int i; + page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST); + if (i < page_map.length && page_map[i].major == map.major) + { + if (pages[page_map[i].index].previous (codepoint)) + { + *codepoint += page_map[i].major * page_t::PAGE_BITS; + return true; + } + } + i--; + for (; (int) i >= 0; i--) + { + hb_codepoint_t m = pages[page_map[i].index].get_max (); + if (m != INVALID) + { + *codepoint = page_map[i].major * page_t::PAGE_BITS + m; + return true; + } + } + *codepoint = INVALID; + return false; + } + bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const + { + hb_codepoint_t i; + + i = *last; + if (!next (&i)) + { + *last = *first = INVALID; + return false; + } + + /* TODO Speed up. */ + *last = *first = i; + while (next (&i) && i == *last + 1) + (*last)++; + + return true; + } + bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const + { + hb_codepoint_t i; + + i = *first; + if (!previous (&i)) + { + *last = *first = INVALID; + return false; + } + + /* TODO Speed up. */ + *last = *first = i; + while (previous (&i) && i == *first - 1) + (*first)--; + + return true; + } + + unsigned int next_many (hb_codepoint_t codepoint, + hb_codepoint_t *out, + unsigned int size) const + { + // By default, start at the first bit of the first page of values. + unsigned int start_page = 0; + unsigned int start_page_value = 0; + if (unlikely (codepoint != INVALID)) + { + const auto* page_map_array = page_map.arrayZ; + unsigned int major = get_major (codepoint); + unsigned int i = last_page_lookup.get_relaxed (); + if (unlikely (i >= page_map.length || page_map_array[i].major != major)) + { + page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST); + if (i >= page_map.length) + return 0; // codepoint is greater than our max element. + } + start_page = i; + start_page_value = page_remainder (codepoint + 1); + if (unlikely (start_page_value == 0)) + { + // The export-after value was last in the page. Start on next page. + start_page++; + start_page_value = 0; + } + } + + unsigned int initial_size = size; + for (unsigned int i = start_page; i < page_map.length && size; i++) + { + uint32_t base = major_start (page_map[i].major); + unsigned int n = pages[page_map[i].index].write (base, start_page_value, out, size); + out += n; + size -= n; + start_page_value = 0; + } + return initial_size - size; + } + + unsigned int next_many_inverted (hb_codepoint_t codepoint, + hb_codepoint_t *out, + unsigned int size) const + { + unsigned int initial_size = size; + // By default, start at the first bit of the first page of values. + unsigned int start_page = 0; + unsigned int start_page_value = 0; + if (unlikely (codepoint != INVALID)) + { + const auto* page_map_array = page_map.arrayZ; + unsigned int major = get_major (codepoint); + unsigned int i = last_page_lookup.get_relaxed (); + if (unlikely (i >= page_map.length || page_map_array[i].major != major)) + { + page_map.bfind(major, &i, HB_NOT_FOUND_STORE_CLOSEST); + if (unlikely (i >= page_map.length)) + { + // codepoint is greater than our max element. + while (++codepoint != INVALID && size) + { + *out++ = codepoint; + size--; + } + return initial_size - size; + } + } + start_page = i; + start_page_value = page_remainder (codepoint + 1); + if (unlikely (start_page_value == 0)) + { + // The export-after value was last in the page. Start on next page. + start_page++; + start_page_value = 0; + } + } + + hb_codepoint_t next_value = codepoint + 1; + for (unsigned int i=start_page; i= 0; i--) + { + const auto& map = page_map[(unsigned) i]; + const auto& page = pages[map.index]; + + if (!page.is_empty ()) + return map.major * page_t::PAGE_BITS + page.get_max (); + } + return INVALID; + } + + static constexpr hb_codepoint_t INVALID = page_t::INVALID; + + /* + * Iterator implementation. + */ + struct iter_t : hb_iter_with_fallback_t + { + static constexpr bool is_sorted_iterator = true; + iter_t (const hb_bit_set_t &s_ = Null (hb_bit_set_t), + bool init = true) : s (&s_), v (INVALID), l(0) + { + if (init) + { + l = s->get_population () + 1; + __next__ (); + } + } + + typedef hb_codepoint_t __item_t__; + hb_codepoint_t __item__ () const { return v; } + bool __more__ () const { return v != INVALID; } + void __next__ () { s->next (&v); if (l) l--; } + void __prev__ () { s->previous (&v); } + unsigned __len__ () const { return l; } + iter_t end () const { return iter_t (*s, false); } + bool operator != (const iter_t& o) const + { return s != o.s || v != o.v; } + + protected: + const hb_bit_set_t *s; + hb_codepoint_t v; + unsigned l; + }; + iter_t iter () const { return iter_t (*this); } + operator iter_t () const { return iter (); } + + protected: + + page_t *page_for (hb_codepoint_t g, bool insert = false) + { + unsigned major = get_major (g); + + /* The extra page_map length is necessary; can't just rely on vector here, + * since the next check would be tricked because a null page also has + * major==0, which we can't distinguish from an actualy major==0 page... */ + unsigned i = last_page_lookup.get_relaxed (); + if (likely (i < page_map.length)) + { + auto &cached_page = page_map.arrayZ[i]; + if (cached_page.major == major) + return &pages[cached_page.index]; + } + + page_map_t map = {major, pages.length}; + if (!page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST)) + { + if (!insert) + return nullptr; + + if (unlikely (!resize (pages.length + 1))) + return nullptr; + + pages[map.index].init0 (); + memmove (page_map + i + 1, + page_map + i, + (page_map.length - 1 - i) * page_map.item_size); + page_map[i] = map; + } + + last_page_lookup.set_relaxed (i); + return &pages[page_map[i].index]; + } + const page_t *page_for (hb_codepoint_t g) const + { + unsigned major = get_major (g); + + /* The extra page_map length is necessary; can't just rely on vector here, + * since the next check would be tricked because a null page also has + * major==0, which we can't distinguish from an actualy major==0 page... */ + unsigned i = last_page_lookup.get_relaxed (); + if (likely (i < page_map.length)) + { + auto &cached_page = page_map.arrayZ[i]; + if (cached_page.major == major) + return &pages[cached_page.index]; + } + + page_map_t key = {major}; + if (!page_map.bfind (key, &i)) + return nullptr; + + last_page_lookup.set_relaxed (i); + return &pages[page_map[i].index]; + } + page_t &page_at (unsigned int i) { return pages[page_map[i].index]; } + const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; } + unsigned int get_major (hb_codepoint_t g) const { return g >> page_t::PAGE_BITS_LOG_2; } + unsigned int page_remainder (hb_codepoint_t g) const { return g & page_t::PAGE_BITMASK; } + hb_codepoint_t major_start (unsigned int major) const { return major << page_t::PAGE_BITS_LOG_2; } +}; + + +#endif /* HB_BIT_SET_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-bit-set-invertible.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-bit-set-invertible.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-bit-set-invertible.hh 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-bit-set-invertible.hh 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,375 @@ +/* + * Copyright © 2012,2017 Google, Inc. + * Copyright © 2021 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_BIT_SET_INVERTIBLE_HH +#define HB_BIT_SET_INVERTIBLE_HH + +#include "hb.hh" +#include "hb-bit-set.hh" + + +struct hb_bit_set_invertible_t +{ + hb_bit_set_t s; + bool inverted = false; + + hb_bit_set_invertible_t () = default; + hb_bit_set_invertible_t (const hb_bit_set_invertible_t& o) = default; + hb_bit_set_invertible_t (hb_bit_set_invertible_t&& other) : hb_bit_set_invertible_t () { hb_swap (*this, other); } + hb_bit_set_invertible_t& operator= (const hb_bit_set_invertible_t& o) = default; + hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& other) { hb_swap (*this, other); return *this; } + friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b) + { + if (likely (!a.s.successful || !b.s.successful)) + return; + hb_swap (a.inverted, b.inverted); + hb_swap (a.s, b.s); + } + + void init () { s.init (); inverted = false; } + void fini () { s.fini (); } + void err () { s.err (); } + bool in_error () const { return s.in_error (); } + explicit operator bool () const { return !is_empty (); } + + void alloc (unsigned sz) { s.alloc (sz); } + void reset () + { + s.reset (); + inverted = false; + } + void clear () + { + s.clear (); + if (likely (s.successful)) + inverted = false; + } + void invert () + { + if (likely (s.successful)) + inverted = !inverted; + } + + bool is_empty () const + { + hb_codepoint_t v = INVALID; + next (&v); + return v == INVALID; + } + uint32_t hash () const { return s.hash () ^ (uint32_t) inverted; } + + hb_codepoint_t get_min () const + { + hb_codepoint_t v = INVALID; + next (&v); + return v; + } + hb_codepoint_t get_max () const + { + hb_codepoint_t v = INVALID; + previous (&v); + return v; + } + unsigned int get_population () const + { return inverted ? INVALID - s.get_population () : s.get_population (); } + + + void add (hb_codepoint_t g) { unlikely (inverted) ? s.del (g) : s.add (g); } + bool add_range (hb_codepoint_t a, hb_codepoint_t b) + { return unlikely (inverted) ? ((void) s.del_range (a, b), true) : s.add_range (a, b); } + + template + void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { inverted ? s.del_array (array, count, stride) : s.add_array (array, count, stride); } + template + void add_array (const hb_array_t& arr) { add_array (&arr, arr.len ()); } + + /* Might return false if array looks unsorted. + * Used for faster rejection of corrupt data. */ + template + bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { return inverted ? s.del_sorted_array (array, count, stride) : s.add_sorted_array (array, count, stride); } + template + bool add_sorted_array (const hb_sorted_array_t& arr) { return add_sorted_array (&arr, arr.len ()); } + + void del (hb_codepoint_t g) { unlikely (inverted) ? s.add (g) : s.del (g); } + void del_range (hb_codepoint_t a, hb_codepoint_t b) + { unlikely (inverted) ? (void) s.add_range (a, b) : s.del_range (a, b); } + + bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; } + + /* Has interface. */ + static constexpr bool SENTINEL = false; + typedef bool value_t; + value_t operator [] (hb_codepoint_t k) const { return get (k); } + bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; } + /* Predicate. */ + bool operator () (hb_codepoint_t k) const { return has (k); } + + /* Sink interface. */ + hb_bit_set_invertible_t& operator << (hb_codepoint_t v) + { add (v); return *this; } + hb_bit_set_invertible_t& operator << (const hb_pair_t& range) + { add_range (range.first, range.second); return *this; } + + bool intersects (hb_codepoint_t first, hb_codepoint_t last) const + { + hb_codepoint_t c = first - 1; + return next (&c) && c <= last; + } + + void set (const hb_bit_set_invertible_t &other) + { + s.set (other.s); + if (likely (s.successful)) + inverted = other.inverted; + } + + bool is_equal (const hb_bit_set_invertible_t &other) const + { + if (likely (inverted == other.inverted)) + return s.is_equal (other.s); + else + { + /* TODO Add iter_ranges() and use here. */ + auto it1 = iter (); + auto it2 = other.iter (); + return hb_all (+ hb_zip (it1, it2) + | hb_map ([](hb_pair_t _) { return _.first == _.second; })); + } + } + + bool is_subset (const hb_bit_set_invertible_t &larger_set) const + { + if (unlikely (inverted != larger_set.inverted)) + return hb_all (hb_iter (s) | hb_map (larger_set.s)); + else + return unlikely (inverted) ? larger_set.s.is_subset (s) : s.is_subset (larger_set.s); + } + + protected: + template + void process (const Op& op, const hb_bit_set_invertible_t &other) + { s.process (op, other.s); } + public: + void union_ (const hb_bit_set_invertible_t &other) + { + if (likely (inverted == other.inverted)) + { + if (unlikely (inverted)) + process (hb_bitwise_and, other); + else + process (hb_bitwise_or, other); /* Main branch. */ + } + else + { + if (unlikely (inverted)) + process (hb_bitwise_gt, other); + else + process (hb_bitwise_lt, other); + } + if (likely (s.successful)) + inverted = inverted || other.inverted; + } + void intersect (const hb_bit_set_invertible_t &other) + { + if (likely (inverted == other.inverted)) + { + if (unlikely (inverted)) + process (hb_bitwise_or, other); + else + process (hb_bitwise_and, other); /* Main branch. */ + } + else + { + if (unlikely (inverted)) + process (hb_bitwise_lt, other); + else + process (hb_bitwise_gt, other); + } + if (likely (s.successful)) + inverted = inverted && other.inverted; + } + void subtract (const hb_bit_set_invertible_t &other) + { + if (likely (inverted == other.inverted)) + { + if (unlikely (inverted)) + process (hb_bitwise_lt, other); + else + process (hb_bitwise_gt, other); /* Main branch. */ + } + else + { + if (unlikely (inverted)) + process (hb_bitwise_or, other); + else + process (hb_bitwise_and, other); + } + if (likely (s.successful)) + inverted = inverted && !other.inverted; + } + void symmetric_difference (const hb_bit_set_invertible_t &other) + { + process (hb_bitwise_xor, other); + if (likely (s.successful)) + inverted = inverted ^ other.inverted; + } + + bool next (hb_codepoint_t *codepoint) const + { + if (likely (!inverted)) + return s.next (codepoint); + + auto old = *codepoint; + if (unlikely (old + 1 == INVALID)) + { + *codepoint = INVALID; + return false; + } + + auto v = old; + s.next (&v); + if (old + 1 < v) + { + *codepoint = old + 1; + return true; + } + + v = old; + s.next_range (&old, &v); + + *codepoint = v + 1; + return *codepoint != INVALID; + } + bool previous (hb_codepoint_t *codepoint) const + { + if (likely (!inverted)) + return s.previous (codepoint); + + auto old = *codepoint; + if (unlikely (old - 1 == INVALID)) + { + *codepoint = INVALID; + return false; + } + + auto v = old; + s.previous (&v); + + if (old - 1 > v || v == INVALID) + { + *codepoint = old - 1; + return true; + } + + v = old; + s.previous_range (&v, &old); + + *codepoint = v - 1; + return *codepoint != INVALID; + } + bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const + { + if (likely (!inverted)) + return s.next_range (first, last); + + if (!next (last)) + { + *last = *first = INVALID; + return false; + } + + *first = *last; + s.next (last); + --*last; + return true; + } + bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const + { + if (likely (!inverted)) + return s.previous_range (first, last); + + if (!previous (first)) + { + *last = *first = INVALID; + return false; + } + + *last = *first; + s.previous (first); + ++*first; + return true; + } + + unsigned int next_many (hb_codepoint_t codepoint, + hb_codepoint_t *out, + unsigned int size) const + { + return inverted ? s.next_many_inverted (codepoint, out, size) + : s.next_many (codepoint, out, size); + } + + static constexpr hb_codepoint_t INVALID = hb_bit_set_t::INVALID; + + /* + * Iterator implementation. + */ + struct iter_t : hb_iter_with_fallback_t + { + static constexpr bool is_sorted_iterator = true; + iter_t (const hb_bit_set_invertible_t &s_ = Null (hb_bit_set_invertible_t), + bool init = true) : s (&s_), v (INVALID), l(0) + { + if (init) + { + l = s->get_population () + 1; + __next__ (); + } + } + + typedef hb_codepoint_t __item_t__; + hb_codepoint_t __item__ () const { return v; } + bool __more__ () const { return v != INVALID; } + void __next__ () { s->next (&v); if (l) l--; } + void __prev__ () { s->previous (&v); } + unsigned __len__ () const { return l; } + iter_t end () const { return iter_t (*s, false); } + bool operator != (const iter_t& o) const + { return s != o.s || v != o.v; } + + protected: + const hb_bit_set_invertible_t *s; + hb_codepoint_t v; + unsigned l; + }; + iter_t iter () const { return iter_t (*this); } + operator iter_t () const { return iter (); } +}; + + +#endif /* HB_BIT_SET_INVERTIBLE_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-blob.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-blob.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-blob.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-blob.cc 2022-10-10 13:07:22.000000000 +0000 @@ -72,14 +72,52 @@ void *user_data, hb_destroy_func_t destroy) { + if (!length) + { + if (destroy) + destroy (user_data); + return hb_blob_get_empty (); + } + + hb_blob_t *blob = hb_blob_create_or_fail (data, length, mode, + user_data, destroy); + return likely (blob) ? blob : hb_blob_get_empty (); +} + +/** + * hb_blob_create_or_fail: (skip) + * @data: Pointer to blob data. + * @length: Length of @data in bytes. + * @mode: Memory mode for @data. + * @user_data: Data parameter to pass to @destroy. + * @destroy: (nullable): Callback to call when @data is not needed anymore. + * + * Creates a new "blob" object wrapping @data. The @mode parameter is used + * to negotiate ownership and lifecycle of @data. + * + * Note that this function returns a freshly-allocated empty blob even if @length + * is zero. This is in contrast to hb_blob_create(), which returns the singleton + * empty blob (as returned by hb_blob_get_empty()) if @length is zero. + * + * Return value: New blob, or %NULL if failed. Destroy with hb_blob_destroy(). + * + * Since: 2.8.2 + **/ +hb_blob_t * +hb_blob_create_or_fail (const char *data, + unsigned int length, + hb_memory_mode_t mode, + void *user_data, + hb_destroy_func_t destroy) +{ hb_blob_t *blob; - if (!length || - length >= 1u << 31 || - !(blob = hb_object_create ())) { + if (length >= 1u << 31 || + !(blob = hb_object_create ())) + { if (destroy) destroy (user_data); - return hb_blob_get_empty (); + return nullptr; } blob->data = data; @@ -91,9 +129,10 @@ if (blob->mode == HB_MEMORY_MODE_DUPLICATE) { blob->mode = HB_MEMORY_MODE_READONLY; - if (!blob->try_make_writable ()) { + if (!blob->try_make_writable ()) + { hb_blob_destroy (blob); - return hb_blob_get_empty (); + return nullptr; } } @@ -226,7 +265,7 @@ blob->fini_shallow (); - free (blob); + hb_free (blob); } /** @@ -330,7 +369,7 @@ * * Fetches the data from a blob. * - * Returns: (transfer none) (array length=length): the byte data of @blob. + * Returns: (nullable) (transfer none) (array length=length): the byte data of @blob. * * Since: 0.9.2 **/ @@ -452,7 +491,7 @@ char *new_data; - new_data = (char *) malloc (this->length); + new_data = (char *) hb_malloc (this->length); if (unlikely (!new_data)) return false; @@ -463,7 +502,7 @@ this->mode = HB_MEMORY_MODE_WRITABLE; this->data = new_data; this->user_data = new_data; - this->destroy = free; + this->destroy = hb_free; return true; } @@ -517,7 +556,7 @@ assert (0); // If we don't have mmap we shouldn't reach here #endif - free (file); + hb_free (file); } #endif @@ -528,15 +567,15 @@ size_t name_len = strlen (file_name); size_t len = name_len + sizeof (_PATH_RSRCFORKSPEC); - char *rsrc_name = (char *) malloc (len); + char *rsrc_name = (char *) hb_malloc (len); if (unlikely (!rsrc_name)) return -1; strncpy (rsrc_name, file_name, name_len); strncpy (rsrc_name + name_len, _PATH_RSRCFORKSPEC, - sizeof (_PATH_RSRCFORKSPEC) - 1); + sizeof (_PATH_RSRCFORKSPEC)); int fd = open (rsrc_name, O_RDONLY | O_BINARY, 0); - free (rsrc_name); + hb_free (rsrc_name); if (fd != -1) { @@ -561,18 +600,38 @@ * Creates a new blob containing the data from the * specified binary font file. * - * Returns: An #hb_blob_t pointer with the content of the file + * Returns: An #hb_blob_t pointer with the content of the file, + * or hb_blob_get_empty() if failed. * * Since: 1.7.7 **/ hb_blob_t * hb_blob_create_from_file (const char *file_name) { + hb_blob_t *blob = hb_blob_create_from_file_or_fail (file_name); + return likely (blob) ? blob : hb_blob_get_empty (); +} + +/** + * hb_blob_create_from_file_or_fail: + * @file_name: A font filename + * + * Creates a new blob containing the data from the + * specified binary font file. + * + * Returns: An #hb_blob_t pointer with the content of the file, + * or %NULL if failed. + * + * Since: 2.8.2 + **/ +hb_blob_t * +hb_blob_create_from_file_or_fail (const char *file_name) +{ /* Adopted from glib's gmappedfile.c with Matthias Clasen and Allison Lortie permission but changed a lot to suit our need. */ #if defined(HAVE_MMAP) && !defined(HB_NO_MMAP) - hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t)); - if (unlikely (!file)) return hb_blob_get_empty (); + hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t)); + if (unlikely (!file)) return nullptr; int fd = open (file_name, O_RDONLY | O_BINARY, 0); if (unlikely (fd == -1)) goto fail_without_close; @@ -601,22 +660,22 @@ close (fd); - return hb_blob_create (file->contents, file->length, - HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, - (hb_destroy_func_t) _hb_mapped_file_destroy); + return hb_blob_create_or_fail (file->contents, file->length, + HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, + (hb_destroy_func_t) _hb_mapped_file_destroy); fail: close (fd); fail_without_close: - free (file); + hb_free (file); #elif defined(_WIN32) && !defined(HB_NO_MMAP) - hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t)); - if (unlikely (!file)) return hb_blob_get_empty (); + hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t)); + if (unlikely (!file)) return nullptr; HANDLE fd; unsigned int size = strlen (file_name) + 1; - wchar_t * wchar_file_name = (wchar_t *) malloc (sizeof (wchar_t) * size); + wchar_t * wchar_file_name = (wchar_t *) hb_malloc (sizeof (wchar_t) * size); if (unlikely (!wchar_file_name)) goto fail_without_close; mbstowcs (wchar_file_name, file_name, size); #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) @@ -636,7 +695,7 @@ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, nullptr); #endif - free (wchar_file_name); + hb_free (wchar_file_name); if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close; @@ -661,22 +720,22 @@ if (unlikely (!file->contents)) goto fail; CloseHandle (fd); - return hb_blob_create (file->contents, file->length, - HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, - (hb_destroy_func_t) _hb_mapped_file_destroy); + return hb_blob_create_or_fail (file->contents, file->length, + HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, + (hb_destroy_func_t) _hb_mapped_file_destroy); fail: CloseHandle (fd); fail_without_close: - free (file); + hb_free (file); #endif /* The following tries to read a file without knowing its size beforehand It's used as a fallback for systems without mmap or to read from pipes */ unsigned long len = 0, allocated = BUFSIZ * 16; - char *data = (char *) malloc (allocated); - if (unlikely (!data)) return hb_blob_get_empty (); + char *data = (char *) hb_malloc (allocated); + if (unlikely (!data)) return nullptr; FILE *fp = fopen (file_name, "rb"); if (unlikely (!fp)) goto fread_fail_without_close; @@ -689,7 +748,7 @@ /* Don't allocate and go more than ~536MB, our mmap reader still can cover files like that but lets limit our fallback reader */ if (unlikely (allocated > (2 << 28))) goto fread_fail; - char *new_data = (char *) realloc (data, allocated); + char *new_data = (char *) hb_realloc (data, allocated); if (unlikely (!new_data)) goto fread_fail; data = new_data; } @@ -706,13 +765,13 @@ } fclose (fp); - return hb_blob_create (data, len, HB_MEMORY_MODE_WRITABLE, data, - (hb_destroy_func_t) free); + return hb_blob_create_or_fail (data, len, HB_MEMORY_MODE_WRITABLE, data, + (hb_destroy_func_t) hb_free); fread_fail: fclose (fp); fread_fail_without_close: - free (data); - return hb_blob_get_empty (); + hb_free (data); + return nullptr; } #endif /* !HB_NO_OPEN */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-blob.h openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-blob.h --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-blob.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-blob.h 2022-10-10 13:07:22.000000000 +0000 @@ -91,8 +91,18 @@ hb_destroy_func_t destroy); HB_EXTERN hb_blob_t * +hb_blob_create_or_fail (const char *data, + unsigned int length, + hb_memory_mode_t mode, + void *user_data, + hb_destroy_func_t destroy); + +HB_EXTERN hb_blob_t * hb_blob_create_from_file (const char *file_name); +HB_EXTERN hb_blob_t * +hb_blob_create_from_file_or_fail (const char *file_name); + /* Always creates with MEMORY_MODE_READONLY. * Even if the parent blob is writable, we don't * want the user of the sub-blob to be able to diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-blob.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-blob.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-blob.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-blob.hh 2022-10-10 13:07:22.000000000 +0000 @@ -88,7 +88,7 @@ const T * get () const { return b->as (); } hb_blob_t * get_blob () const { return b.get_raw (); } unsigned int get_length () const { return b.get ()->length; } - void destroy () { hb_blob_destroy (b.get ()); b = nullptr; } + void destroy () { hb_blob_destroy (b.get_raw ()); b = nullptr; } private: hb_nonnull_ptr_t b; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc 2022-10-10 13:07:22.000000000 +0000 @@ -81,12 +81,51 @@ unsigned int hb_segment_properties_hash (const hb_segment_properties_t *p) { - return (unsigned int) p->direction ^ - (unsigned int) p->script ^ + return ((unsigned int) p->direction * 31 + + (unsigned int) p->script) * 31 + (intptr_t) (p->language); } +/** + * hb_segment_properties_overlay: + * @p: #hb_segment_properties_t to fill in. + * @src: #hb_segment_properties_t to fill in from. + * + * Fills in missing fields of @p from @src in a considered manner. + * + * First, if @p does not have direction set, direction is copied from @src. + * + * Next, if @p and @src have the same direction (which can be unset), if @p + * does not have script set, script is copied from @src. + * + * Finally, if @p and @src have the same direction and script (which either + * can be unset), if @p does not have language set, language is copied from + * @src. + * + * Since: 3.3.0 + **/ +void +hb_segment_properties_overlay (hb_segment_properties_t *p, + const hb_segment_properties_t *src) +{ + if (unlikely (!p || !src)) + return; + + if (!p->direction) + p->direction = src->direction; + if (p->direction != src->direction) + return; + + if (!p->script) + p->script = src->script; + + if (p->script != src->script) + return; + + if (!p->language) + p->language = src->language; +} /* Here is how the buffer works internally: * @@ -96,14 +135,15 @@ * As an optimization, both info and out_info may point to the * same piece of memory, which is owned by info. This remains the * case as long as out_len doesn't exceed i at any time. - * In that case, swap_buffers() is no-op and the glyph operations operate - * mostly in-place. + * In that case, sync() is mostly no-op and the glyph operations + * operate mostly in-place. * * As soon as out_info gets longer than info, out_info is moved over - * to an alternate buffer (which we reuse the pos buffer for!), and its + * to an alternate buffer (which we reuse the pos buffer for), and its * current contents (out_len entries) are copied to the new place. - * This should all remain transparent to the user. swap_buffers() then - * switches info and out_info. + * + * This should all remain transparent to the user. sync() then + * switches info over to out_info and does housekeeping. */ @@ -136,8 +176,8 @@ if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0])))) goto done; - new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0])); - new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0])); + new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_allocated * sizeof (pos[0])); + new_info = (hb_glyph_info_t *) hb_realloc (info, new_allocated * sizeof (info[0])); done: if (unlikely (!new_pos || !new_info)) @@ -216,13 +256,27 @@ /* HarfBuzz-Internal API */ void +hb_buffer_t::similar (const hb_buffer_t &src) +{ + hb_unicode_funcs_destroy (unicode); + unicode = hb_unicode_funcs_reference (src.unicode); + flags = src.flags; + cluster_level = src.cluster_level; + replacement = src.invisible; + invisible = src.invisible; + not_found = src.not_found; +} + +void hb_buffer_t::reset () { hb_unicode_funcs_destroy (unicode); unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ()); flags = HB_BUFFER_FLAG_DEFAULT; + cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT; replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; invisible = 0; + not_found = 0; clear (); } @@ -230,12 +284,12 @@ void hb_buffer_t::clear () { + content_type = HB_BUFFER_CONTENT_TYPE_INVALID; hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT; props = default_props; - scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; - content_type = HB_BUFFER_CONTENT_TYPE_INVALID; successful = true; + shaping_failed = false; have_output = false; have_positions = false; @@ -244,15 +298,44 @@ out_len = 0; out_info = info; - serial = 0; - memset (context, 0, sizeof context); memset (context_len, 0, sizeof context_len); deallocate_var_all (); + serial = 0; + scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; } void +hb_buffer_t::enter () +{ + deallocate_var_all (); + serial = 0; + shaping_failed = false; + scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; + if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR))) + { + max_len = hb_max (len * HB_BUFFER_MAX_LEN_FACTOR, + (unsigned) HB_BUFFER_MAX_LEN_MIN); + } + if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR))) + { + max_ops = hb_max (len * HB_BUFFER_MAX_OPS_FACTOR, + (unsigned) HB_BUFFER_MAX_OPS_MIN); + } +} +void +hb_buffer_t::leave () +{ + max_len = HB_BUFFER_MAX_LEN_DEFAULT; + max_ops = HB_BUFFER_MAX_OPS_DEFAULT; + deallocate_var_all (); + serial = 0; + // Intentionally not reseting shaping_failed, such that it can be inspected. +} + + +void hb_buffer_t::add (hb_codepoint_t codepoint, unsigned int cluster) { @@ -282,21 +365,12 @@ void -hb_buffer_t::remove_output () -{ - have_output = false; - have_positions = false; - - out_len = 0; - out_info = info; -} - -void hb_buffer_t::clear_output () { have_output = true; have_positions = false; + idx = 0; out_len = 0; out_info = info; } @@ -314,31 +388,26 @@ } void -hb_buffer_t::swap_buffers () +hb_buffer_t::sync () { - if (unlikely (!successful)) return; + assert (have_output); assert (idx <= len); - if (unlikely (!next_glyphs (len - idx))) return; - assert (have_output); - have_output = false; + if (unlikely (!successful || !next_glyphs (len - idx))) + goto reset; if (out_info != info) { - hb_glyph_info_t *tmp; - tmp = info; + pos = (hb_glyph_position_t *) info; info = out_info; - out_info = tmp; - - pos = (hb_glyph_position_t *) out_info; } - - unsigned int tmp; - tmp = len; len = out_len; - out_len = tmp; +reset: + have_output = false; + out_len = 0; + out_info = info; idx = 0; } @@ -373,12 +442,11 @@ /* This will blow in our face if memory allocation fails later * in this same lookup... * - * We used to shift with extra 32 items, instead of the 0 below. + * We used to shift with extra 32 items. * But that would leave empty slots in the buffer in case of allocation - * failures. Setting to zero for now to avoid other problems (see - * comments in shift_forward(). This can cause O(N^2) behavior more - * severely than adding 32 empty slots can... */ - if (unlikely (idx < count && !shift_forward (count + 0))) return false; + * failures. See comments in shift_forward(). This can cause O(N^2) + * behavior more severely than adding 32 empty slots can... */ + if (unlikely (idx < count && !shift_forward (count - idx))) return false; assert (idx >= count); @@ -410,52 +478,6 @@ } void -hb_buffer_t::reverse_range (unsigned int start, - unsigned int end) -{ - if (end - start < 2) - return; - - hb_array_t (info, len).reverse (start, end); - - if (have_positions) { - hb_array_t (pos, len).reverse (start, end); - } -} - -void -hb_buffer_t::reverse () -{ - if (unlikely (!len)) - return; - - reverse_range (0, len); -} - -void -hb_buffer_t::reverse_clusters () -{ - unsigned int i, start, count, last_cluster; - - if (unlikely (!len)) - return; - - reverse (); - - count = len; - start = 0; - last_cluster = info[0].cluster; - for (i = 1; i < count; i++) { - if (last_cluster != info[i].cluster) { - reverse_range (start, i); - start = i; - last_cluster = info[i].cluster; - } - } - reverse_range (start, i); -} - -void hb_buffer_t::merge_clusters_impl (unsigned int start, unsigned int end) { @@ -523,7 +545,8 @@ /* The logic here is duplicated in hb_ot_hide_default_ignorables(). */ unsigned int cluster = info[idx].cluster; - if (idx + 1 < len && cluster == info[idx + 1].cluster) + if ((idx + 1 < len && cluster == info[idx + 1].cluster) || + (out_len && cluster == out_info[out_len - 1].cluster)) { /* Cluster survives; do nothing. */ goto done; @@ -554,32 +577,6 @@ } void -hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end) -{ - unsigned int cluster = UINT_MAX; - cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster); - _unsafe_to_break_set_mask (info, start, end, cluster); -} -void -hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end) -{ - if (!have_output) - { - unsafe_to_break_impl (start, end); - return; - } - - assert (start <= out_len); - assert (idx <= end); - - unsigned int cluster = UINT_MAX; - cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster); - cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster); - _unsafe_to_break_set_mask (out_info, start, out_len, cluster); - _unsafe_to_break_set_mask (info, idx, end, cluster); -} - -void hb_buffer_t::guess_segment_properties () { assert_unicode (); @@ -623,14 +620,15 @@ HB_BUFFER_CLUSTER_LEVEL_DEFAULT, HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, 0, /* invisible */ - HB_BUFFER_SCRATCH_FLAG_DEFAULT, - HB_BUFFER_MAX_LEN_DEFAULT, - HB_BUFFER_MAX_OPS_DEFAULT, + 0, /* not_found */ + HB_BUFFER_CONTENT_TYPE_INVALID, HB_SEGMENT_PROPERTIES_DEFAULT, + false, /* successful */ - true, /* have_output */ + true, /* shaping_failed */ + false, /* have_output */ true /* have_positions */ /* Zero is good enough for everything else. */ @@ -638,7 +636,7 @@ /** - * hb_buffer_create: (Xconstructor) + * hb_buffer_create: * * Creates a new #hb_buffer_t with all properties to defaults. * @@ -668,6 +666,46 @@ } /** + * hb_buffer_create_similar: + * @src: An #hb_buffer_t + * + * Creates a new #hb_buffer_t, similar to hb_buffer_create(). The only + * difference is that the buffer is configured similarly to @src. + * + * Return value: (transfer full): + * A newly allocated #hb_buffer_t, similar to hb_buffer_create(). + * + * Since: 3.3.0 + **/ +hb_buffer_t * +hb_buffer_create_similar (const hb_buffer_t *src) +{ + hb_buffer_t *buffer = hb_buffer_create (); + + buffer->similar (*src); + + return buffer; +} + +/** + * hb_buffer_reset: + * @buffer: An #hb_buffer_t + * + * Resets the buffer to its initial status, as if it was just newly created + * with hb_buffer_create(). + * + * Since: 0.9.2 + **/ +void +hb_buffer_reset (hb_buffer_t *buffer) +{ + if (unlikely (hb_object_is_immutable (buffer))) + return; + + buffer->reset (); +} + +/** * hb_buffer_get_empty: * * Fetches an empty #hb_buffer_t. @@ -717,14 +755,14 @@ hb_unicode_funcs_destroy (buffer->unicode); - free (buffer->info); - free (buffer->pos); + hb_free (buffer->info); + hb_free (buffer->pos); #ifndef HB_NO_BUFFER_MESSAGE if (buffer->message_destroy) buffer->message_destroy (buffer->message_data); #endif - free (buffer); + hb_free (buffer); } /** @@ -801,7 +839,7 @@ * Since: 0.9.5 **/ hb_buffer_content_type_t -hb_buffer_get_content_type (hb_buffer_t *buffer) +hb_buffer_get_content_type (const hb_buffer_t *buffer) { return buffer->content_type; } @@ -843,7 +881,7 @@ * Since: 0.9.2 **/ hb_unicode_funcs_t * -hb_buffer_get_unicode_funcs (hb_buffer_t *buffer) +hb_buffer_get_unicode_funcs (const hb_buffer_t *buffer) { return buffer->unicode; } @@ -886,7 +924,7 @@ * Since: 0.9.2 **/ hb_direction_t -hb_buffer_get_direction (hb_buffer_t *buffer) +hb_buffer_get_direction (const hb_buffer_t *buffer) { return buffer->props.direction; } @@ -930,7 +968,7 @@ * Since: 0.9.2 **/ hb_script_t -hb_buffer_get_script (hb_buffer_t *buffer) +hb_buffer_get_script (const hb_buffer_t *buffer) { return buffer->props.script; } @@ -974,7 +1012,7 @@ * Since: 0.9.2 **/ hb_language_t -hb_buffer_get_language (hb_buffer_t *buffer) +hb_buffer_get_language (const hb_buffer_t *buffer) { return buffer->props.language; } @@ -1010,7 +1048,7 @@ * Since: 0.9.7 **/ void -hb_buffer_get_segment_properties (hb_buffer_t *buffer, +hb_buffer_get_segment_properties (const hb_buffer_t *buffer, hb_segment_properties_t *props) { *props = buffer->props; @@ -1048,7 +1086,7 @@ * Since: 0.9.7 **/ hb_buffer_flags_t -hb_buffer_get_flags (hb_buffer_t *buffer) +hb_buffer_get_flags (const hb_buffer_t *buffer) { return buffer->flags; } @@ -1087,7 +1125,7 @@ * Since: 0.9.42 **/ hb_buffer_cluster_level_t -hb_buffer_get_cluster_level (hb_buffer_t *buffer) +hb_buffer_get_cluster_level (const hb_buffer_t *buffer) { return buffer->cluster_level; } @@ -1128,7 +1166,7 @@ * Since: 0.9.31 **/ hb_codepoint_t -hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer) +hb_buffer_get_replacement_codepoint (const hb_buffer_t *buffer) { return buffer->replacement; } @@ -1168,31 +1206,53 @@ * Since: 2.0.0 **/ hb_codepoint_t -hb_buffer_get_invisible_glyph (hb_buffer_t *buffer) +hb_buffer_get_invisible_glyph (const hb_buffer_t *buffer) { return buffer->invisible; } - /** - * hb_buffer_reset: + * hb_buffer_set_not_found_glyph: * @buffer: An #hb_buffer_t + * @not_found: the not-found #hb_codepoint_t * - * Resets the buffer to its initial status, as if it was just newly created - * with hb_buffer_create(). + * Sets the #hb_codepoint_t that replaces characters not found in + * the font during shaping. * - * Since: 0.9.2 + * The not-found glyph defaults to zero, sometimes knows as the + * ".notdef" glyph. This API allows for differentiating the two. + * + * Since: 3.1.0 **/ void -hb_buffer_reset (hb_buffer_t *buffer) +hb_buffer_set_not_found_glyph (hb_buffer_t *buffer, + hb_codepoint_t not_found) { if (unlikely (hb_object_is_immutable (buffer))) return; - buffer->reset (); + buffer->not_found = not_found; } /** + * hb_buffer_get_not_found_glyph: + * @buffer: An #hb_buffer_t + * + * See hb_buffer_set_not_found_glyph(). + * + * Return value: + * The @buffer not-found #hb_codepoint_t + * + * Since: 3.1.0 + **/ +hb_codepoint_t +hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer) +{ + return buffer->not_found; +} + + +/** * hb_buffer_clear_contents: * @buffer: An #hb_buffer_t * @@ -1326,7 +1386,7 @@ * Since: 0.9.2 **/ unsigned int -hb_buffer_get_length (hb_buffer_t *buffer) +hb_buffer_get_length (const hb_buffer_t *buffer) { return buffer->len; } @@ -1363,6 +1423,11 @@ * Returns @buffer glyph position array. Returned pointer * is valid as long as @buffer contents are not modified. * + * If buffer did not have positions before, the positions will be + * initialized to zeros, unless this function is called from + * within a buffer message callback (see hb_buffer_set_message_func()), + * in which case %NULL is returned. + * * Return value: (transfer none) (array length=length): * The @buffer glyph position array. * The value valid as long as buffer has not been modified. @@ -1373,12 +1438,17 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer, unsigned int *length) { - if (!buffer->have_positions) - buffer->clear_positions (); - if (length) *length = buffer->len; + if (!buffer->have_positions) + { + if (unlikely (buffer->message_depth)) + return nullptr; + + buffer->clear_positions (); + } + return (hb_glyph_position_t *) buffer->pos; } @@ -1724,7 +1794,7 @@ **/ HB_EXTERN void hb_buffer_append (hb_buffer_t *buffer, - hb_buffer_t *source, + const hb_buffer_t *source, unsigned int start, unsigned int end) { @@ -1757,9 +1827,33 @@ if (!buffer->have_positions && source->have_positions) buffer->clear_positions (); + hb_segment_properties_overlay (&buffer->props, &source->props); + memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0])); if (buffer->have_positions) memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0])); + + if (source->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE) + { + /* See similar logic in add_utf. */ + + /* pre-context */ + if (!orig_len && start + source->context_len[0] > 0) + { + buffer->clear_context (0); + while (start > 0 && buffer->context_len[0] < buffer->CONTEXT_LENGTH) + buffer->context[0][buffer->context_len[0]++] = source->info[--start].codepoint; + for (auto i = 0u; i < source->context_len[0] && buffer->context_len[0] < buffer->CONTEXT_LENGTH; i++) + buffer->context[0][buffer->context_len[0]++] = source->context[0][i]; + } + + /* post-context */ + buffer->clear_context (1); + while (end < source->len && buffer->context_len[1] < buffer->CONTEXT_LENGTH) + buffer->context[1][buffer->context_len[1]++] = source->info[end++].codepoint; + for (auto i = 0u; i < source->context_len[1] && buffer->context_len[1] < buffer->CONTEXT_LENGTH; i++) + buffer->context[1][buffer->context_len[1]++] = source->context[1][i]; + } } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh 2022-10-10 13:07:22.000000000 +0000 @@ -1,29 +1,30 @@ + #line 1 "hb-buffer-deserialize-json.rl" /* -* Copyright © 2013 Google, Inc. -* -* This is part of HarfBuzz, a text shaping library. -* -* Permission is hereby granted, without written agreement and without -* license or royalty fees, to use, copy, modify, and distribute this -* software and its documentation for any purpose, provided that the -* above copyright notice and the following two paragraphs appear in -* all copies of this software. -* -* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR -* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES -* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN -* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -* DAMAGE. -* -* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, -* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS -* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO -* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. -* -* Google Author(s): Behdad Esfahbod -*/ + * Copyright © 2013 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ #ifndef HB_BUFFER_DESERIALIZE_JSON_HH #define HB_BUFFER_DESERIALIZE_JSON_HH @@ -31,158 +32,446 @@ #include "hb.hh" -#line 35 "hb-buffer-deserialize-json.hh" +#line 36 "hb-buffer-deserialize-json.hh" static const unsigned char _deserialize_json_trans_keys[] = { - 1u, 0u, 0u, 18u, 0u, 2u, 10u, 15u, - 16u, 17u, 2u, 2u, 0u, 7u, 0u, 6u, - 5u, 6u, 0u, 19u, 0u, 19u, 0u, 19u, - 2u, 2u, 0u, 7u, 0u, 6u, 5u, 6u, - 0u, 19u, 0u, 19u, 14u, 14u, 2u, 2u, - 0u, 7u, 0u, 6u, 0u, 19u, 0u, 19u, - 16u, 17u, 2u, 2u, 0u, 7u, 0u, 6u, - 5u, 6u, 0u, 19u, 0u, 19u, 2u, 2u, - 0u, 7u, 0u, 6u, 5u, 6u, 0u, 19u, - 0u, 19u, 2u, 2u, 0u, 7u, 0u, 6u, - 2u, 8u, 0u, 19u, 2u, 8u, 0u, 19u, - 0u, 19u, 2u, 2u, 0u, 7u, 0u, 6u, - 0u, 19u, 0u, 9u, 0u, 18u, 1u, 0u, - 0u + 0u, 0u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, + 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, + 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, + 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, + 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, + 34u, 92u, 9u, 125u, 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, + 9u, 125u, 9u, 93u, 9u, 123u, 0u, 0u, 0 }; -static const signed char _deserialize_json_char_class[] = { - 0, 0, 0, 0, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, - 1, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 3, 4, 1, 1, 5, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 7, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 8, 9, 1, 1, 1, - 10, 1, 11, 12, 1, 1, 13, 1, - 1, 1, 1, 14, 1, 1, 1, 1, - 1, 1, 1, 1, 15, 1, 1, 16, - 17, 1, 18, 1, 19, 0 +static const char _deserialize_json_key_spans[] = { + 0, 115, 26, 21, 2, 1, 50, 49, + 10, 117, 117, 117, 1, 50, 49, 10, + 117, 117, 1, 1, 50, 49, 117, 117, + 2, 1, 50, 49, 10, 117, 117, 1, + 50, 49, 10, 117, 117, 1, 50, 49, + 59, 117, 59, 117, 117, 1, 50, 49, + 117, 85, 115, 0 }; static const short _deserialize_json_index_offsets[] = { - 0, 0, 19, 22, 28, 30, 31, 39, - 46, 48, 68, 88, 108, 109, 117, 124, - 126, 146, 166, 167, 168, 176, 183, 203, - 223, 225, 226, 234, 241, 243, 263, 283, - 284, 292, 299, 301, 321, 341, 342, 350, - 357, 364, 384, 391, 411, 431, 432, 440, - 447, 467, 477, 496, 0 + 0, 0, 116, 143, 165, 168, 170, 221, + 271, 282, 400, 518, 636, 638, 689, 739, + 750, 868, 986, 988, 990, 1041, 1091, 1209, + 1327, 1330, 1332, 1383, 1433, 1444, 1562, 1680, + 1682, 1733, 1783, 1794, 1912, 2030, 2032, 2083, + 2133, 2193, 2311, 2371, 2489, 2607, 2609, 2660, + 2710, 2828, 2914, 3030 }; -static const signed char _deserialize_json_indicies[] = { - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2, 3, 0, 4, 5, 6, - 7, 8, 0, 9, 10, 11, 12, 12, - 0, 0, 0, 0, 0, 0, 13, 13, - 0, 0, 0, 14, 15, 16, 18, 19, - 20, 0, 0, 21, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 22, 23, 0, 0, 3, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 24, - 20, 0, 0, 21, 0, 19, 19, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 22, 25, 25, 0, 0, - 0, 0, 0, 0, 26, 26, 0, 0, - 0, 27, 28, 29, 31, 32, 33, 0, - 0, 34, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 35, 33, 0, 0, 34, 0, 32, - 32, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 35, 36, 37, - 37, 0, 0, 0, 0, 0, 0, 38, - 38, 0, 0, 0, 0, 39, 40, 42, - 0, 0, 43, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 44, 42, 0, 0, 43, 0, - 45, 45, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 44, 46, - 47, 48, 48, 0, 0, 0, 0, 0, - 0, 49, 49, 0, 0, 0, 50, 51, - 52, 54, 55, 56, 0, 0, 57, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 58, 56, - 0, 0, 57, 0, 55, 55, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 58, 59, 59, 0, 0, 0, - 0, 0, 0, 60, 60, 0, 0, 0, - 61, 62, 63, 65, 66, 67, 0, 0, - 68, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 69, 67, 0, 0, 68, 0, 66, 66, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 69, 70, 70, 0, - 0, 0, 0, 0, 0, 71, 71, 0, - 72, 0, 0, 73, 74, 76, 75, 75, - 75, 75, 75, 77, 79, 0, 0, 80, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 81, - 75, 0, 0, 0, 0, 0, 75, 83, - 0, 0, 84, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 85, 83, 0, 0, 84, 0, - 87, 87, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 85, 88, - 88, 0, 0, 0, 0, 0, 0, 89, - 89, 0, 0, 0, 0, 90, 91, 83, - 0, 0, 84, 0, 93, 93, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 85, 94, 0, 0, 95, 0, - 0, 0, 0, 0, 96, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2, +static const char _deserialize_json_indicies[] = { + 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 1, 3, 3, 3, + 3, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 1, 4, 1, + 5, 1, 6, 7, 1, 1, 8, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 9, 1, 10, 11, + 1, 12, 1, 12, 12, 12, 12, 12, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 12, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 13, 1, 13, 13, + 13, 13, 13, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 13, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 14, 1, 1, 15, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 1, + 17, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 1, 19, 19, 19, 19, 19, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 19, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 20, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 21, + 1, 22, 22, 22, 22, 22, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 22, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 23, 1, 19, + 19, 19, 19, 19, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 19, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 20, 1, 1, 1, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 21, 1, 24, 1, 24, + 24, 24, 24, 24, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 24, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 25, 1, 25, 25, 25, 25, 25, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 25, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 26, 1, + 1, 27, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 1, 29, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 1, 31, + 31, 31, 31, 31, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 31, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 32, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 33, 1, 31, 31, 31, + 31, 31, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 31, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 32, 1, 1, 1, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 33, 1, 34, 1, 35, 1, 35, + 35, 35, 35, 35, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 35, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 36, 1, 36, 36, 36, 36, 36, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 36, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 37, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 1, 39, 39, 39, 39, + 39, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 39, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 40, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 41, 1, 39, 39, 39, 39, 39, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 39, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 40, 1, 1, + 1, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 41, 1, + 43, 44, 1, 45, 1, 45, 45, 45, + 45, 45, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 45, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 46, 1, + 46, 46, 46, 46, 46, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 46, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 47, 1, 1, 48, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 1, 50, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 1, 52, 52, 52, + 52, 52, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 52, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 53, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 54, 1, 52, 52, 52, 52, 52, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 52, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 53, 1, + 1, 1, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 54, + 1, 55, 1, 55, 55, 55, 55, 55, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 55, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 56, 1, 56, 56, + 56, 56, 56, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 56, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 57, 1, 1, 58, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 1, + 60, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 1, 62, 62, 62, 62, 62, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 62, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 63, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 64, + 1, 62, 62, 62, 62, 62, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 62, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 63, 1, 1, 1, + 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 64, 1, 65, + 1, 65, 65, 65, 65, 65, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 65, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 66, 1, 66, 66, 66, 66, + 66, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 66, 1, 67, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 68, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 1, 71, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 72, 70, 73, 73, 73, 73, 73, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 73, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 74, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 75, 1, + 70, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 70, 1, 76, 76, 76, 76, + 76, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 76, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 77, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 78, 1, 76, 76, 76, 76, 76, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 76, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 77, 1, 1, + 1, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 78, 1, + 80, 1, 80, 80, 80, 80, 80, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 80, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 81, 1, 81, 81, 81, + 81, 81, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 81, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 82, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 1, 76, + 76, 76, 76, 76, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 76, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 77, 1, 1, 1, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 78, 1, 85, 85, 85, + 85, 85, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 85, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 86, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 87, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 0 }; -static const signed char _deserialize_json_index_defaults[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 75, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 -}; - -static const signed char _deserialize_json_cond_targs[] = { - 0, 1, 2, 2, 3, 4, 18, 24, +static const char _deserialize_json_trans_targs[] = { + 1, 0, 2, 2, 3, 4, 18, 24, 37, 45, 5, 12, 6, 7, 8, 9, - 11, 8, 9, 11, 10, 2, 49, 10, - 49, 13, 14, 15, 16, 17, 15, 16, - 17, 10, 2, 49, 19, 20, 21, 22, - 23, 22, 10, 2, 49, 23, 25, 31, - 26, 27, 28, 29, 30, 28, 29, 30, - 10, 2, 49, 32, 33, 34, 35, 36, - 34, 35, 36, 10, 2, 49, 38, 39, - 40, 43, 44, 40, 41, 42, 41, 10, - 2, 49, 43, 10, 2, 49, 44, 44, - 46, 47, 43, 48, 48, 48, 49, 50, - 51, 0 + 11, 9, 11, 10, 2, 49, 10, 49, + 13, 14, 15, 16, 17, 16, 17, 10, + 2, 49, 19, 20, 21, 22, 23, 10, + 2, 49, 23, 25, 31, 26, 27, 28, + 29, 30, 29, 30, 10, 2, 49, 32, + 33, 34, 35, 36, 35, 36, 10, 2, + 49, 38, 39, 40, 43, 44, 40, 41, + 42, 10, 2, 49, 10, 2, 49, 44, + 46, 47, 43, 48, 48, 49, 50, 51 }; -static const signed char _deserialize_json_cond_actions[] = { +static const char _deserialize_json_trans_actions[] = { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, - 2, 0, 0, 0, 3, 3, 4, 0, - 5, 0, 0, 2, 2, 2, 0, 0, - 0, 6, 6, 7, 0, 0, 0, 2, - 2, 0, 8, 8, 9, 0, 0, 0, - 0, 0, 2, 2, 2, 0, 0, 0, - 10, 10, 11, 0, 0, 2, 2, 2, - 0, 0, 0, 12, 12, 13, 0, 0, - 2, 14, 14, 0, 15, 0, 0, 16, - 16, 17, 0, 18, 18, 19, 0, 15, - 0, 0, 20, 20, 0, 21, 0, 0, - 0, 0 + 2, 0, 0, 3, 3, 4, 0, 5, + 0, 0, 2, 2, 2, 0, 0, 6, + 6, 7, 0, 0, 0, 2, 2, 8, + 8, 9, 0, 0, 0, 0, 0, 2, + 2, 2, 0, 0, 10, 10, 11, 0, + 0, 2, 2, 2, 0, 0, 12, 12, + 13, 0, 0, 2, 14, 14, 0, 15, + 0, 16, 16, 17, 18, 18, 19, 15, + 0, 0, 20, 20, 21, 0, 0, 0 }; static const int deserialize_json_start = 1; @@ -197,411 +486,247 @@ static hb_bool_t _hb_buffer_deserialize_json (hb_buffer_t *buffer, -const char *buf, -unsigned int buf_len, -const char **end_ptr, -hb_font_t *font) + const char *buf, + unsigned int buf_len, + const char **end_ptr, + hb_font_t *font) { - const char *p = buf, *pe = buf + buf_len; - - /* Ensure we have positions. */ - (void) hb_buffer_get_glyph_positions (buffer, nullptr); + const char *p = buf, *pe = buf + buf_len; - while (p < pe && ISSPACE (*p)) - p++; - if (p < pe && *p == (buffer->len ? ',' : '[')) - { - *end_ptr = ++p; - } + /* Ensure we have positions. */ + (void) hb_buffer_get_glyph_positions (buffer, nullptr); - const char *tok = nullptr; - int cs; - hb_glyph_info_t info = {0}; - hb_glyph_position_t pos = {0}; + while (p < pe && ISSPACE (*p)) + p++; + if (p < pe && *p == (buffer->len ? ',' : '[')) + { + *end_ptr = ++p; + } + + const char *tok = nullptr; + int cs; + hb_glyph_info_t info = {0}; + hb_glyph_position_t pos = {0}; -#line 223 "hb-buffer-deserialize-json.hh" +#line 512 "hb-buffer-deserialize-json.hh" { - cs = (int)deserialize_json_start; + cs = deserialize_json_start; } -#line 228 "hb-buffer-deserialize-json.hh" +#line 517 "hb-buffer-deserialize-json.hh" { - unsigned int _trans = 0; - const unsigned char * _keys; - const signed char * _inds; - int _ic; - _resume: {} - if ( p == pe ) - goto _out; - _keys = ( _deserialize_json_trans_keys + ((cs<<1))); - _inds = ( _deserialize_json_indicies + (_deserialize_json_index_offsets[cs])); - - if ( ( (*( p))) <= 125 && ( (*( p))) >= 9 ) { - _ic = (int)_deserialize_json_char_class[(int)( (*( p))) - 9]; - if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) ) - _trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) )); - else - _trans = (unsigned int)_deserialize_json_index_defaults[cs]; - } - else { - _trans = (unsigned int)_deserialize_json_index_defaults[cs]; - } - - cs = (int)_deserialize_json_cond_targs[_trans]; - - if ( _deserialize_json_cond_actions[_trans] != 0 ) { - - switch ( _deserialize_json_cond_actions[_trans] ) { - case 1: { - { -#line 38 "hb-buffer-deserialize-json.rl" - - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); - } + int _slen; + int _trans; + const unsigned char *_keys; + const char *_inds; + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _keys = _deserialize_json_trans_keys + (cs<<1); + _inds = _deserialize_json_indicies + _deserialize_json_index_offsets[cs]; + + _slen = _deserialize_json_key_spans[cs]; + _trans = _inds[ _slen > 0 && _keys[0] <=(*p) && + (*p) <= _keys[1] ? + (*p) - _keys[0] : _slen ]; -#line 264 "hb-buffer-deserialize-json.hh" + cs = _deserialize_json_trans_targs[_trans]; + if ( _deserialize_json_trans_actions[_trans] == 0 ) + goto _again; - break; - } - case 5: { - { + switch ( _deserialize_json_trans_actions[_trans] ) { + case 1: +#line 38 "hb-buffer-deserialize-json.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} + break; + case 5: #line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 280 "hb-buffer-deserialize-json.hh" - - - break; - } - case 2: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 2: #line 51 "hb-buffer-deserialize-json.rl" - - tok = p; - } - -#line 292 "hb-buffer-deserialize-json.hh" - - - break; - } - case 15: { - { + { + tok = p; +} + break; + case 15: #line 55 "hb-buffer-deserialize-json.rl" - if (unlikely (!buffer->ensure_glyphs ())) return false; } - -#line 302 "hb-buffer-deserialize-json.hh" - - - break; - } - case 21: { - { + { if (unlikely (!buffer->ensure_glyphs ())) return false; } + break; + case 21: #line 56 "hb-buffer-deserialize-json.rl" - if (unlikely (!buffer->ensure_unicode ())) return false; } - -#line 312 "hb-buffer-deserialize-json.hh" - - - break; - } - case 16: { - { + { if (unlikely (!buffer->ensure_unicode ())) return false; } + break; + case 16: #line 58 "hb-buffer-deserialize-json.rl" - - /* TODO Unescape \" and \\ if found. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 328 "hb-buffer-deserialize-json.hh" - - - break; - } - case 18: { - { + { + /* TODO Unescape \" and \\ if found. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} + break; + case 18: #line 66 "hb-buffer-deserialize-json.rl" - if (!parse_uint (tok, p, &info.codepoint)) return false; } - -#line 338 "hb-buffer-deserialize-json.hh" - - - break; - } - case 8: { - { + { if (!parse_uint (tok, p, &info.codepoint)) return false; } + break; + case 8: #line 67 "hb-buffer-deserialize-json.rl" - if (!parse_uint (tok, p, &info.cluster )) return false; } - -#line 348 "hb-buffer-deserialize-json.hh" - - - break; - } - case 10: { - { + { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 10: #line 68 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.x_offset )) return false; } - -#line 358 "hb-buffer-deserialize-json.hh" - - - break; - } - case 12: { - { + { if (!parse_int (tok, p, &pos.x_offset )) return false; } + break; + case 12: #line 69 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.y_offset )) return false; } - -#line 368 "hb-buffer-deserialize-json.hh" - - - break; - } - case 3: { - { + { if (!parse_int (tok, p, &pos.y_offset )) return false; } + break; + case 3: #line 70 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.x_advance)) return false; } - -#line 378 "hb-buffer-deserialize-json.hh" - - - break; - } - case 6: { - { + { if (!parse_int (tok, p, &pos.x_advance)) return false; } + break; + case 6: #line 71 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.y_advance)) return false; } - -#line 388 "hb-buffer-deserialize-json.hh" - - - break; - } - case 14: { - { + { if (!parse_int (tok, p, &pos.y_advance)) return false; } + break; + case 14: #line 51 "hb-buffer-deserialize-json.rl" - - tok = p; - } - -#line 400 "hb-buffer-deserialize-json.hh" - - { + { + tok = p; +} #line 55 "hb-buffer-deserialize-json.rl" - if (unlikely (!buffer->ensure_glyphs ())) return false; } - -#line 406 "hb-buffer-deserialize-json.hh" - - - break; - } - case 20: { - { + { if (unlikely (!buffer->ensure_glyphs ())) return false; } + break; + case 20: #line 51 "hb-buffer-deserialize-json.rl" - - tok = p; - } - -#line 418 "hb-buffer-deserialize-json.hh" - - { + { + tok = p; +} #line 56 "hb-buffer-deserialize-json.rl" - if (unlikely (!buffer->ensure_unicode ())) return false; } - -#line 424 "hb-buffer-deserialize-json.hh" - - - break; - } - case 17: { - { + { if (unlikely (!buffer->ensure_unicode ())) return false; } + break; + case 17: #line 58 "hb-buffer-deserialize-json.rl" - - /* TODO Unescape \" and \\ if found. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 440 "hb-buffer-deserialize-json.hh" - - { + { + /* TODO Unescape \" and \\ if found. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} #line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 452 "hb-buffer-deserialize-json.hh" - - - break; - } - case 19: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 19: #line 66 "hb-buffer-deserialize-json.rl" - if (!parse_uint (tok, p, &info.codepoint)) return false; } - -#line 462 "hb-buffer-deserialize-json.hh" - - { + { if (!parse_uint (tok, p, &info.codepoint)) return false; } #line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 474 "hb-buffer-deserialize-json.hh" - - - break; - } - case 9: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 9: #line 67 "hb-buffer-deserialize-json.rl" - if (!parse_uint (tok, p, &info.cluster )) return false; } - -#line 484 "hb-buffer-deserialize-json.hh" - - { + { if (!parse_uint (tok, p, &info.cluster )) return false; } #line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 496 "hb-buffer-deserialize-json.hh" - - - break; - } - case 11: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: #line 68 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.x_offset )) return false; } - -#line 506 "hb-buffer-deserialize-json.hh" - - { + { if (!parse_int (tok, p, &pos.x_offset )) return false; } #line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 518 "hb-buffer-deserialize-json.hh" - - - break; - } - case 13: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 13: #line 69 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.y_offset )) return false; } - -#line 528 "hb-buffer-deserialize-json.hh" - - { + { if (!parse_int (tok, p, &pos.y_offset )) return false; } #line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 540 "hb-buffer-deserialize-json.hh" - - - break; - } - case 4: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 4: #line 70 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.x_advance)) return false; } - -#line 550 "hb-buffer-deserialize-json.hh" - - { + { if (!parse_int (tok, p, &pos.x_advance)) return false; } #line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 562 "hb-buffer-deserialize-json.hh" - - - break; - } - case 7: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 7: #line 71 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.y_advance)) return false; } - -#line 572 "hb-buffer-deserialize-json.hh" - - { + { if (!parse_int (tok, p, &pos.y_advance)) return false; } #line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 713 "hb-buffer-deserialize-json.hh" + } - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 584 "hb-buffer-deserialize-json.hh" - - - break; - } - } - - } - - if ( cs != 0 ) { - p += 1; - goto _resume; - } - _out: {} +_again: + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + _out: {} } #line 136 "hb-buffer-deserialize-json.rl" - *end_ptr = p; + *end_ptr = p; - return p == pe && *(p-1) != ']'; + return p == pe && *(p-1) != ']'; } #endif /* HB_BUFFER_DESERIALIZE_JSON_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-text.hh 2022-10-10 13:07:22.000000000 +0000 @@ -1,29 +1,30 @@ + #line 1 "hb-buffer-deserialize-text.rl" /* -* Copyright © 2013 Google, Inc. -* -* This is part of HarfBuzz, a text shaping library. -* -* Permission is hereby granted, without written agreement and without -* license or royalty fees, to use, copy, modify, and distribute this -* software and its documentation for any purpose, provided that the -* above copyright notice and the following two paragraphs appear in -* all copies of this software. -* -* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR -* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES -* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN -* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -* DAMAGE. -* -* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, -* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS -* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO -* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. -* -* Google Author(s): Behdad Esfahbod -*/ + * Copyright © 2013 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ #ifndef HB_BUFFER_DESERIALIZE_TEXT_HH #define HB_BUFFER_DESERIALIZE_TEXT_HH @@ -31,143 +32,366 @@ #include "hb.hh" -#line 35 "hb-buffer-deserialize-text.hh" +#line 36 "hb-buffer-deserialize-text.hh" static const unsigned char _deserialize_text_trans_keys[] = { - 1u, 0u, 0u, 13u, 12u, 12u, 2u, 2u, - 5u, 11u, 0u, 12u, 5u, 6u, 4u, 6u, - 5u, 6u, 5u, 6u, 4u, 6u, 5u, 6u, - 3u, 3u, 4u, 6u, 5u, 6u, 3u, 6u, - 2u, 16u, 4u, 6u, 5u, 6u, 0u, 16u, - 0u, 16u, 1u, 0u, 0u, 12u, 0u, 16u, - 0u, 16u, 0u, 16u, 0u, 16u, 0u, 16u, - 0u, 16u, 0u, 16u, 0u, 16u, 0u, 16u, - 0u, 16u, 0u, 16u, 0u, 16u, 0u, 16u, - 0u, 16u, 0u + 0u, 0u, 9u, 91u, 85u, 85u, 43u, 43u, 48u, 102u, 9u, 85u, 48u, 57u, 45u, 57u, + 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, + 43u, 124u, 45u, 57u, 48u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, 9u, 85u, 9u, 124u, + 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, + 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 0 +}; + +static const char _deserialize_text_key_spans[] = { + 0, 83, 1, 1, 55, 77, 10, 13, + 10, 10, 13, 10, 1, 13, 10, 14, + 82, 13, 10, 116, 116, 0, 77, 116, + 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116 }; -static const signed char _deserialize_text_char_class[] = { - 0, 0, 0, 0, 0, 1, 1, 1, +static const short _deserialize_text_index_offsets[] = { + 0, 0, 84, 86, 88, 144, 222, 233, + 247, 258, 269, 283, 294, 296, 310, 321, + 336, 419, 433, 444, 561, 678, 679, 757, + 874, 991, 1108, 1225, 1342, 1459, 1576, 1693, + 1810, 1927, 2044, 2161, 2278 +}; + +static const char _deserialize_text_indicies[] = { + 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 1, 4, 1, 5, + 1, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 1, 1, 1, 1, 1, + 1, 1, 6, 6, 6, 6, 6, 6, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 6, 6, 6, 6, 6, 6, + 1, 7, 7, 7, 7, 7, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 7, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 4, 1, 8, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 1, 10, 1, 1, 11, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 1, + 13, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 1, 15, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 1, 17, 1, + 1, 18, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 1, 20, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 1, 22, + 1, 23, 1, 1, 24, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 1, 26, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 1, 22, 1, 1, 1, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 1, 28, 28, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 28, 1, 1, 28, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 28, 28, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 28, 1, 29, 1, 1, 30, + 31, 31, 31, 31, 31, 31, 31, 31, + 31, 1, 32, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 1, 34, 34, 34, + 34, 34, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 34, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 1, 1, + 1, 36, 37, 1, 1, 35, 35, 35, + 35, 35, 35, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 35, 35, 35, + 35, 35, 35, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 38, 1, 39, 39, 39, 39, 39, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 39, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 40, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 41, 1, 1, + 7, 7, 7, 7, 7, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 7, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 4, 1, 42, 42, + 42, 42, 42, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 42, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 43, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 44, 1, 42, 42, 42, 42, 42, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 42, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 1, 1, 1, 1, + 43, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 44, 1, + 47, 47, 47, 47, 47, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 47, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 48, 1, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 49, 46, 46, 50, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 51, 52, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 53, 46, 54, 54, 54, + 54, 54, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 54, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 55, + 1, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 56, 28, 28, 57, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 58, 59, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 60, 28, 61, 61, 61, 61, 61, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 61, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 62, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 63, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 64, 1, 65, + 65, 65, 65, 65, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 65, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 40, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 66, 1, 67, 67, 67, 67, + 67, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 67, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 48, 1, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 49, 46, 46, 50, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 51, + 52, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 53, + 46, 68, 68, 68, 68, 68, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 68, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 69, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 70, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 43, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 71, 1, 72, 72, + 72, 72, 72, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 72, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 73, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 3, 4, 1, 1, 5, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 1, 1, 7, 8, 9, 1, 10, - 11, 11, 11, 11, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 12, 1, 1, 1, - 1, 1, 13, 14, 15, 1, 1, 1, - 11, 11, 11, 11, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 74, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 16, 0 + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 75, 1, 72, 72, 72, 72, 72, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 72, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 73, 1, 1, + 1, 1, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 74, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 75, 1, + 68, 68, 68, 68, 68, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 68, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 69, 1, 1, 1, 1, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 1, 1, 1, 1, 1, 1, 70, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 43, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 71, 1, 77, 77, 77, + 77, 77, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 77, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 78, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 79, 1, 77, 77, 77, 77, 77, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 77, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 78, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 79, 1, 61, + 61, 61, 61, 61, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 61, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 62, 1, 1, 1, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 63, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 64, 1, 0 }; -static const short _deserialize_text_index_offsets[] = { - 0, 0, 14, 15, 16, 23, 36, 38, - 41, 43, 45, 48, 50, 51, 54, 56, - 60, 75, 78, 80, 97, 114, 114, 127, - 144, 161, 178, 195, 212, 229, 246, 263, - 280, 297, 314, 331, 348, 0 +static const char _deserialize_text_trans_targs[] = { + 1, 0, 2, 25, 3, 4, 19, 5, + 23, 24, 8, 27, 36, 27, 36, 30, + 33, 11, 12, 15, 12, 15, 13, 14, + 31, 32, 31, 32, 26, 18, 34, 35, + 34, 35, 20, 19, 6, 21, 22, 20, + 21, 22, 20, 21, 22, 24, 26, 26, + 7, 9, 10, 16, 21, 29, 26, 7, + 9, 10, 16, 21, 29, 28, 17, 21, + 29, 28, 29, 29, 28, 7, 10, 29, + 28, 7, 21, 29, 33, 28, 21, 29 }; -static const signed char _deserialize_text_indicies[] = { - 1, 0, 0, 0, 0, 0, 0, 2, - 0, 0, 0, 0, 0, 3, 4, 6, - 7, 7, 0, 0, 0, 0, 7, 8, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 4, 10, 11, 13, 14, - 15, 17, 18, 20, 21, 23, 24, 25, - 27, 28, 29, 31, 32, 33, 35, 36, - 29, 0, 28, 28, 38, 38, 0, 0, - 0, 0, 38, 0, 38, 0, 0, 0, - 38, 38, 38, 40, 41, 42, 44, 45, - 47, 0, 0, 0, 0, 48, 48, 0, - 49, 50, 0, 48, 0, 0, 0, 0, - 51, 52, 0, 0, 0, 0, 0, 0, - 0, 0, 53, 0, 0, 0, 0, 0, - 0, 54, 8, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4, 56, - 0, 0, 0, 0, 0, 0, 0, 0, - 57, 0, 0, 0, 0, 0, 0, 58, - 56, 0, 0, 0, 0, 60, 60, 0, - 0, 57, 0, 0, 0, 0, 0, 0, - 58, 63, 62, 64, 0, 62, 62, 62, - 62, 65, 62, 66, 62, 62, 62, 67, - 68, 69, 71, 38, 72, 0, 38, 38, - 38, 38, 73, 38, 74, 38, 38, 38, - 37, 75, 76, 78, 0, 0, 79, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 80, 81, 82, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 53, 83, 84, 62, 64, - 0, 62, 62, 62, 62, 65, 62, 66, - 62, 62, 62, 67, 68, 69, 86, 0, - 87, 0, 0, 0, 0, 0, 0, 0, - 88, 0, 0, 0, 0, 57, 89, 91, - 0, 92, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 93, 94, - 91, 0, 92, 0, 0, 36, 36, 0, - 0, 0, 0, 0, 0, 0, 0, 93, - 94, 86, 0, 87, 0, 0, 97, 97, - 0, 0, 0, 88, 0, 0, 0, 0, - 57, 89, 99, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 100, 101, 99, 0, 0, 0, 0, - 45, 45, 0, 0, 0, 0, 0, 0, - 0, 0, 100, 101, 78, 0, 0, 79, - 0, 18, 18, 0, 0, 0, 0, 0, - 0, 0, 0, 80, 81, 0 +static const char _deserialize_text_trans_actions[] = { + 0, 0, 0, 0, 1, 0, 2, 0, + 2, 2, 3, 4, 4, 5, 5, 4, + 4, 3, 3, 3, 0, 0, 6, 3, + 4, 4, 5, 5, 5, 3, 4, 4, + 5, 5, 7, 8, 9, 7, 7, 0, + 0, 0, 10, 10, 10, 8, 12, 13, + 14, 14, 14, 15, 11, 11, 17, 18, + 18, 18, 0, 16, 16, 19, 20, 19, + 19, 0, 0, 13, 10, 21, 21, 10, + 22, 23, 22, 22, 5, 24, 24, 24 }; -static const signed char _deserialize_text_index_defaults[] = { +static const char _deserialize_text_eof_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 62, 38, 0, 0, 62, 0, 0, - 0, 0, 0, 0, 0, 0 -}; - -static const signed char _deserialize_text_cond_targs[] = { - 0, 1, 2, 25, 3, 3, 4, 19, - 5, 6, 23, 24, 7, 8, 27, 36, - 8, 27, 36, 9, 30, 33, 10, 11, - 12, 15, 11, 12, 15, 13, 13, 14, - 31, 32, 14, 31, 32, 16, 26, 17, - 18, 34, 35, 18, 34, 35, 19, 20, - 19, 6, 21, 22, 20, 21, 22, 23, - 20, 21, 22, 24, 24, 25, 26, 26, - 7, 9, 10, 16, 21, 29, 26, 26, - 7, 9, 10, 21, 29, 27, 28, 17, - 21, 29, 28, 29, 29, 30, 28, 7, - 10, 29, 31, 28, 7, 21, 29, 32, - 33, 33, 34, 28, 21, 29, 35, 36, - 0 -}; - -static const signed char _deserialize_text_cond_actions[] = { - 0, 0, 0, 0, 1, 0, 0, 2, - 0, 0, 2, 2, 0, 3, 4, 4, - 0, 5, 5, 0, 4, 4, 0, 3, - 3, 3, 0, 0, 0, 6, 0, 3, - 4, 4, 0, 5, 5, 0, 5, 0, - 3, 4, 4, 0, 5, 5, 7, 7, - 8, 9, 7, 7, 0, 0, 0, 10, - 10, 10, 10, 10, 8, 11, 12, 13, - 14, 14, 14, 15, 11, 11, 16, 17, - 18, 18, 18, 16, 16, 19, 19, 20, - 19, 19, 0, 0, 13, 10, 10, 21, - 21, 10, 22, 22, 23, 22, 22, 22, - 10, 5, 24, 24, 24, 24, 24, 19, - 0 -}; - -static const signed char _deserialize_text_eof_trans[] = { - 1, 2, 3, 6, 7, 9, 10, 13, - 17, 20, 23, 27, 28, 31, 35, 29, - 38, 40, 44, 47, 53, 54, 55, 56, - 60, 62, 71, 78, 83, 70, 86, 91, - 96, 97, 99, 103, 104, 0 + 0, 0, 0, 7, 0, 0, 0, 10, + 10, 11, 16, 19, 0, 11, 10, 22, + 22, 10, 24, 24, 19 }; static const int deserialize_text_start = 1; @@ -182,583 +406,448 @@ static hb_bool_t _hb_buffer_deserialize_text (hb_buffer_t *buffer, -const char *buf, -unsigned int buf_len, -const char **end_ptr, -hb_font_t *font) + const char *buf, + unsigned int buf_len, + const char **end_ptr, + hb_font_t *font) { - const char *p = buf, *pe = buf + buf_len; + const char *p = buf, *pe = buf + buf_len; - /* Ensure we have positions. */ - (void) hb_buffer_get_glyph_positions (buffer, nullptr); + /* Ensure we have positions. */ + (void) hb_buffer_get_glyph_positions (buffer, nullptr); - while (p < pe && ISSPACE (*p)) - p++; + while (p < pe && ISSPACE (*p)) + p++; - const char *eof = pe, *tok = nullptr; - int cs; - hb_glyph_info_t info = {0}; - hb_glyph_position_t pos = {0}; + const char *eof = pe, *tok = nullptr; + int cs; + hb_glyph_info_t info = {0}; + hb_glyph_position_t pos = {0}; -#line 204 "hb-buffer-deserialize-text.hh" +#line 428 "hb-buffer-deserialize-text.hh" { - cs = (int)deserialize_text_start; + cs = deserialize_text_start; } -#line 209 "hb-buffer-deserialize-text.hh" +#line 433 "hb-buffer-deserialize-text.hh" { - unsigned int _trans = 0; - const unsigned char * _keys; - const signed char * _inds; - int _ic; - _resume: {} - if ( p == pe && p != eof ) - goto _out; - if ( p == eof ) { - if ( _deserialize_text_eof_trans[cs] > 0 ) { - _trans = (unsigned int)_deserialize_text_eof_trans[cs] - 1; - } - } - else { - _keys = ( _deserialize_text_trans_keys + ((cs<<1))); - _inds = ( _deserialize_text_indicies + (_deserialize_text_index_offsets[cs])); - - if ( ( (*( p))) <= 124 && ( (*( p))) >= 9 ) { - _ic = (int)_deserialize_text_char_class[(int)( (*( p))) - 9]; - if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) ) - _trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) )); - else - _trans = (unsigned int)_deserialize_text_index_defaults[cs]; - } - else { - _trans = (unsigned int)_deserialize_text_index_defaults[cs]; - } - - } - cs = (int)_deserialize_text_cond_targs[_trans]; - - if ( _deserialize_text_cond_actions[_trans] != 0 ) { - - switch ( _deserialize_text_cond_actions[_trans] ) { - case 1: { - { -#line 38 "hb-buffer-deserialize-text.rl" - - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); - } + int _slen; + int _trans; + const unsigned char *_keys; + const char *_inds; + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _keys = _deserialize_text_trans_keys + (cs<<1); + _inds = _deserialize_text_indicies + _deserialize_text_index_offsets[cs]; + + _slen = _deserialize_text_key_spans[cs]; + _trans = _inds[ _slen > 0 && _keys[0] <=(*p) && + (*p) <= _keys[1] ? + (*p) - _keys[0] : _slen ]; -#line 252 "hb-buffer-deserialize-text.hh" + cs = _deserialize_text_trans_targs[_trans]; + if ( _deserialize_text_trans_actions[_trans] == 0 ) + goto _again; - break; - } - case 3: { - { + switch ( _deserialize_text_trans_actions[_trans] ) { + case 1: +#line 38 "hb-buffer-deserialize-text.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} + break; + case 3: #line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 264 "hb-buffer-deserialize-text.hh" - - - break; - } - case 5: { - { + { + tok = p; +} + break; + case 5: #line 55 "hb-buffer-deserialize-text.rl" - if (unlikely (!buffer->ensure_glyphs ())) return false; } - -#line 274 "hb-buffer-deserialize-text.hh" - - - break; - } - case 8: { - { + { if (unlikely (!buffer->ensure_glyphs ())) return false; } + break; + case 8: #line 56 "hb-buffer-deserialize-text.rl" - if (unlikely (!buffer->ensure_unicode ())) return false; } - -#line 284 "hb-buffer-deserialize-text.hh" - - - break; - } - case 18: { - { + { if (unlikely (!buffer->ensure_unicode ())) return false; } + break; + case 18: #line 58 "hb-buffer-deserialize-text.rl" - - /* TODO Unescape delimeters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 300 "hb-buffer-deserialize-text.hh" - - - break; - } - case 9: { - { + { + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} + break; + case 9: #line 66 "hb-buffer-deserialize-text.rl" - if (!parse_hex (tok, p, &info.codepoint )) return false; } - -#line 310 "hb-buffer-deserialize-text.hh" - - - break; - } - case 21: { - { + {if (!parse_hex (tok, p, &info.codepoint )) return false; } + break; + case 21: #line 68 "hb-buffer-deserialize-text.rl" - if (!parse_uint (tok, p, &info.cluster )) return false; } - -#line 320 "hb-buffer-deserialize-text.hh" - - - break; - } - case 6: { - { + { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 6: #line 69 "hb-buffer-deserialize-text.rl" - if (!parse_int (tok, p, &pos.x_offset )) return false; } - -#line 330 "hb-buffer-deserialize-text.hh" - - - break; - } - case 23: { - { + { if (!parse_int (tok, p, &pos.x_offset )) return false; } + break; + case 23: #line 70 "hb-buffer-deserialize-text.rl" - if (!parse_int (tok, p, &pos.y_offset )) return false; } - -#line 340 "hb-buffer-deserialize-text.hh" - - - break; - } - case 20: { - { + { if (!parse_int (tok, p, &pos.y_offset )) return false; } + break; + case 20: #line 71 "hb-buffer-deserialize-text.rl" - if (!parse_int (tok, p, &pos.x_advance)) return false; } - -#line 350 "hb-buffer-deserialize-text.hh" - - - break; - } - case 15: { - { + { if (!parse_int (tok, p, &pos.x_advance)) return false; } + break; + case 15: #line 38 "hb-buffer-deserialize-text.rl" - - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); - } - -#line 363 "hb-buffer-deserialize-text.hh" - - { + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} #line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 371 "hb-buffer-deserialize-text.hh" - - - break; - } - case 4: { - { + { + tok = p; +} + break; + case 4: #line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 383 "hb-buffer-deserialize-text.hh" - - { + { + tok = p; +} #line 55 "hb-buffer-deserialize-text.rl" - if (unlikely (!buffer->ensure_glyphs ())) return false; } - -#line 389 "hb-buffer-deserialize-text.hh" - - - break; - } - case 2: { - { + { if (unlikely (!buffer->ensure_glyphs ())) return false; } + break; + case 2: #line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 401 "hb-buffer-deserialize-text.hh" - - { + { + tok = p; +} #line 56 "hb-buffer-deserialize-text.rl" - if (unlikely (!buffer->ensure_unicode ())) return false; } - -#line 407 "hb-buffer-deserialize-text.hh" - - - break; - } - case 16: { - { + { if (unlikely (!buffer->ensure_unicode ())) return false; } + break; + case 16: #line 58 "hb-buffer-deserialize-text.rl" - - /* TODO Unescape delimeters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 423 "hb-buffer-deserialize-text.hh" - - { + { + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} #line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 435 "hb-buffer-deserialize-text.hh" - - - break; - } - case 7: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 7: #line 66 "hb-buffer-deserialize-text.rl" - if (!parse_hex (tok, p, &info.codepoint )) return false; } - -#line 445 "hb-buffer-deserialize-text.hh" - - { + {if (!parse_hex (tok, p, &info.codepoint )) return false; } #line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 457 "hb-buffer-deserialize-text.hh" - - - break; - } - case 10: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 10: #line 68 "hb-buffer-deserialize-text.rl" - if (!parse_uint (tok, p, &info.cluster )) return false; } - -#line 467 "hb-buffer-deserialize-text.hh" - - { + { if (!parse_uint (tok, p, &info.cluster )) return false; } #line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 479 "hb-buffer-deserialize-text.hh" - - - break; - } - case 22: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 22: #line 70 "hb-buffer-deserialize-text.rl" - if (!parse_int (tok, p, &pos.y_offset )) return false; } - -#line 489 "hb-buffer-deserialize-text.hh" - - { + { if (!parse_int (tok, p, &pos.y_offset )) return false; } #line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 501 "hb-buffer-deserialize-text.hh" - - - break; - } - case 19: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 19: #line 71 "hb-buffer-deserialize-text.rl" - if (!parse_int (tok, p, &pos.x_advance)) return false; } - -#line 511 "hb-buffer-deserialize-text.hh" - - { + { if (!parse_int (tok, p, &pos.x_advance)) return false; } #line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 523 "hb-buffer-deserialize-text.hh" - - - break; - } - case 24: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 24: #line 72 "hb-buffer-deserialize-text.rl" - if (!parse_int (tok, p, &pos.y_advance)) return false; } - -#line 533 "hb-buffer-deserialize-text.hh" - - { + { if (!parse_int (tok, p, &pos.y_advance)) return false; } #line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 545 "hb-buffer-deserialize-text.hh" - - - break; - } - case 12: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 12: #line 38 "hb-buffer-deserialize-text.rl" - - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); - } - -#line 558 "hb-buffer-deserialize-text.hh" - - { + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} #line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 566 "hb-buffer-deserialize-text.hh" - - { + { + tok = p; +} #line 55 "hb-buffer-deserialize-text.rl" - if (unlikely (!buffer->ensure_glyphs ())) return false; } - -#line 572 "hb-buffer-deserialize-text.hh" - - - break; - } - case 14: { - { + { if (unlikely (!buffer->ensure_glyphs ())) return false; } + break; + case 14: #line 38 "hb-buffer-deserialize-text.rl" - - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); - } - -#line 585 "hb-buffer-deserialize-text.hh" - - { + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} #line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 593 "hb-buffer-deserialize-text.hh" - - { + { + tok = p; +} #line 58 "hb-buffer-deserialize-text.rl" - - /* TODO Unescape delimeters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 605 "hb-buffer-deserialize-text.hh" - - - break; - } - case 17: { - { + { + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} + break; + case 17: #line 58 "hb-buffer-deserialize-text.rl" - - /* TODO Unescape delimeters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 621 "hb-buffer-deserialize-text.hh" - - { + { + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} #line 55 "hb-buffer-deserialize-text.rl" - if (unlikely (!buffer->ensure_glyphs ())) return false; } - -#line 627 "hb-buffer-deserialize-text.hh" - - { + { if (unlikely (!buffer->ensure_glyphs ())) return false; } #line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 639 "hb-buffer-deserialize-text.hh" - - - break; - } - case 11: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: #line 38 "hb-buffer-deserialize-text.rl" - - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); - } - -#line 652 "hb-buffer-deserialize-text.hh" - - { + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} #line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 660 "hb-buffer-deserialize-text.hh" - - { + { + tok = p; +} #line 58 "hb-buffer-deserialize-text.rl" - - /* TODO Unescape delimeters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 672 "hb-buffer-deserialize-text.hh" - - { + { + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} #line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 684 "hb-buffer-deserialize-text.hh" - - - break; - } - case 13: { - { + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 13: #line 38 "hb-buffer-deserialize-text.rl" - - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); - } - -#line 697 "hb-buffer-deserialize-text.hh" - - { + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} #line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 705 "hb-buffer-deserialize-text.hh" - - { + { + tok = p; +} #line 58 "hb-buffer-deserialize-text.rl" - - /* TODO Unescape delimeters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 717 "hb-buffer-deserialize-text.hh" - - { + { + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} #line 55 "hb-buffer-deserialize-text.rl" - if (unlikely (!buffer->ensure_glyphs ())) return false; } - -#line 723 "hb-buffer-deserialize-text.hh" - - { + { if (unlikely (!buffer->ensure_glyphs ())) return false; } #line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 722 "hb-buffer-deserialize-text.hh" + } - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 735 "hb-buffer-deserialize-text.hh" - - - break; - } - } - - } +_again: + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + if ( p == eof ) + { + switch ( _deserialize_text_eof_actions[cs] ) { + case 16: +#line 58 "hb-buffer-deserialize-text.rl" + { + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 7: +#line 66 "hb-buffer-deserialize-text.rl" + {if (!parse_hex (tok, p, &info.codepoint )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 10: +#line 68 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 22: +#line 70 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 19: +#line 71 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 24: +#line 72 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: +#line 38 "hb-buffer-deserialize-text.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} +#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; +} +#line 58 "hb-buffer-deserialize-text.rl" + { + /* TODO Unescape delimiters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 839 "hb-buffer-deserialize-text.hh" + } + } - if ( p == eof ) { - if ( cs >= 19 ) - goto _out; - } - else { - if ( cs != 0 ) { - p += 1; - goto _resume; - } - } - _out: {} + _out: {} } #line 138 "hb-buffer-deserialize-text.rl" - *end_ptr = p; + *end_ptr = p; - return p == pe && *(p-1) != ']'; + return p == pe && *(p-1) != ']'; } #endif /* HB_BUFFER_DESERIALIZE_TEXT_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.h openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.h --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.h 2022-10-10 13:07:22.000000000 +0000 @@ -76,18 +76,72 @@ * @HB_GLYPH_FLAG_UNSAFE_TO_BREAK: Indicates that if input text is broken at the * beginning of the cluster this glyph is part of, * then both sides need to be re-shaped, as the - * result might be different. On the flip side, - * it means that when this flag is not present, - * then it's safe to break the glyph-run at the - * beginning of this cluster, and the two sides - * represent the exact same result one would get - * if breaking input text at the beginning of - * this cluster and shaping the two sides - * separately. This can be used to optimize - * paragraph layout, by avoiding re-shaping - * of each line after line-breaking, or limiting - * the reshaping to a small piece around the - * breaking point only. + * result might be different. + * On the flip side, it means that when this + * flag is not present, then it is safe to break + * the glyph-run at the beginning of this + * cluster, and the two sides will represent the + * exact same result one would get if breaking + * input text at the beginning of this cluster + * and shaping the two sides separately. + * This can be used to optimize paragraph + * layout, by avoiding re-shaping of each line + * after line-breaking. + * @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT: Indicates that if input text is changed on one + * side of the beginning of the cluster this glyph + * is part of, then the shaping results for the + * other side might change. + * Note that the absence of this flag will NOT by + * itself mean that it IS safe to concat text. + * Only two pieces of text both of which clear of + * this flag can be concatenated safely. + * This can be used to optimize paragraph + * layout, by avoiding re-shaping of each line + * after line-breaking, by limiting the + * reshaping to a small piece around the + * breaking positin only, even if the breaking + * position carries the + * #HB_GLYPH_FLAG_UNSAFE_TO_BREAK or when + * hyphenation or other text transformation + * happens at line-break position, in the following + * way: + * 1. Iterate back from the line-break position + * until the first cluster start position that is + * NOT unsafe-to-concat, 2. shape the segment from + * there till the end of line, 3. check whether the + * resulting glyph-run also is clear of the + * unsafe-to-concat at its start-of-text position; + * if it is, just splice it into place and the line + * is shaped; If not, move on to a position further + * back that is clear of unsafe-to-concat and retry + * from there, and repeat. + * At the start of next line a similar algorithm can + * be implemented. That is: 1. Iterate forward from + * the line-break position until the first cluster + * start position that is NOT unsafe-to-concat, 2. + * shape the segment from beginning of the line to + * that position, 3. check whether the resulting + * glyph-run also is clear of the unsafe-to-concat + * at its end-of-text position; if it is, just splice + * it into place and the beginning is shaped; If not, + * move on to a position further forward that is clear + * of unsafe-to-concat and retry up to there, and repeat. + * A slight complication will arise in the + * implementation of the algorithm above, + * because while our buffer API has a way to + * return flags for position corresponding to + * start-of-text, there is currently no position + * corresponding to end-of-text. This limitation + * can be alleviated by shaping more text than needed + * and looking for unsafe-to-concat flag within text + * clusters. + * The #HB_GLYPH_FLAG_UNSAFE_TO_BREAK flag will + * always imply this flag. + * To use this flag, you must enable the buffer flag + * @HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT during + * shaping, otherwise the buffer flag will not be + * reliably produced. + * Since: 4.0.0 * @HB_GLYPH_FLAG_DEFINED: All the currently defined flags. * * Flags for #hb_glyph_info_t. @@ -96,8 +150,9 @@ */ typedef enum { /*< flags >*/ HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001, + HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002, - HB_GLYPH_FLAG_DEFINED = 0x00000001 /* OR of all defined flags */ + HB_GLYPH_FLAG_DEFINED = 0x00000003 /* OR of all defined flags */ } hb_glyph_flags_t; HB_EXTERN hb_glyph_flags_t @@ -170,6 +225,9 @@ HB_EXTERN unsigned int hb_segment_properties_hash (const hb_segment_properties_t *p); +HB_EXTERN void +hb_segment_properties_overlay (hb_segment_properties_t *p, + const hb_segment_properties_t *src); /** @@ -185,6 +243,13 @@ hb_buffer_create (void); HB_EXTERN hb_buffer_t * +hb_buffer_create_similar (const hb_buffer_t *src); + +HB_EXTERN void +hb_buffer_reset (hb_buffer_t *buffer); + + +HB_EXTERN hb_buffer_t * hb_buffer_get_empty (void); HB_EXTERN hb_buffer_t * @@ -224,7 +289,7 @@ hb_buffer_content_type_t content_type); HB_EXTERN hb_buffer_content_type_t -hb_buffer_get_content_type (hb_buffer_t *buffer); +hb_buffer_get_content_type (const hb_buffer_t *buffer); HB_EXTERN void @@ -232,21 +297,21 @@ hb_unicode_funcs_t *unicode_funcs); HB_EXTERN hb_unicode_funcs_t * -hb_buffer_get_unicode_funcs (hb_buffer_t *buffer); +hb_buffer_get_unicode_funcs (const hb_buffer_t *buffer); HB_EXTERN void hb_buffer_set_direction (hb_buffer_t *buffer, hb_direction_t direction); HB_EXTERN hb_direction_t -hb_buffer_get_direction (hb_buffer_t *buffer); +hb_buffer_get_direction (const hb_buffer_t *buffer); HB_EXTERN void hb_buffer_set_script (hb_buffer_t *buffer, hb_script_t script); HB_EXTERN hb_script_t -hb_buffer_get_script (hb_buffer_t *buffer); +hb_buffer_get_script (const hb_buffer_t *buffer); HB_EXTERN void hb_buffer_set_language (hb_buffer_t *buffer, @@ -254,14 +319,14 @@ HB_EXTERN hb_language_t -hb_buffer_get_language (hb_buffer_t *buffer); +hb_buffer_get_language (const hb_buffer_t *buffer); HB_EXTERN void hb_buffer_set_segment_properties (hb_buffer_t *buffer, const hb_segment_properties_t *props); HB_EXTERN void -hb_buffer_get_segment_properties (hb_buffer_t *buffer, +hb_buffer_get_segment_properties (const hb_buffer_t *buffer, hb_segment_properties_t *props); HB_EXTERN void @@ -295,7 +360,20 @@ * @HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE: * flag indicating that a dotted circle should * not be inserted in the rendering of incorrect - * character sequences (such at <0905 093E>). Since: 2.4 + * character sequences (such at <0905 093E>). Since: 2.4.0 + * @HB_BUFFER_FLAG_VERIFY: + * flag indicating that the hb_shape() call and its variants + * should perform various verification processes on the results + * of the shaping operation on the buffer. If the verification + * fails, then either a buffer message is sent, if a message + * handler is installed on the buffer, or a message is written + * to standard error. In either case, the shaping result might + * be modified to show the failed output. Since: 3.4.0 + * @HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT: + * flag indicating that the @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT + * glyph-flag should be produced by the shaper. By default + * it will not be produced since it incurs a cost. Since: 4.0.0 + * @HB_BUFFER_FLAG_DEFINED: All currently defined flags: Since: 4.4.0 * * Flags for #hb_buffer_t. * @@ -307,7 +385,11 @@ HB_BUFFER_FLAG_EOT = 0x00000002u, /* End-of-text */ HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u, HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x00000008u, - HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u + HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u, + HB_BUFFER_FLAG_VERIFY = 0x00000020u, + HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x00000040u, + + HB_BUFFER_FLAG_DEFINED = 0x0000007Fu } hb_buffer_flags_t; HB_EXTERN void @@ -315,7 +397,7 @@ hb_buffer_flags_t flags); HB_EXTERN hb_buffer_flags_t -hb_buffer_get_flags (hb_buffer_t *buffer); +hb_buffer_get_flags (const hb_buffer_t *buffer); /** * hb_buffer_cluster_level_t: @@ -357,7 +439,7 @@ hb_buffer_cluster_level_t cluster_level); HB_EXTERN hb_buffer_cluster_level_t -hb_buffer_get_cluster_level (hb_buffer_t *buffer); +hb_buffer_get_cluster_level (const hb_buffer_t *buffer); /** * HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT: @@ -374,18 +456,26 @@ hb_codepoint_t replacement); HB_EXTERN hb_codepoint_t -hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer); +hb_buffer_get_replacement_codepoint (const hb_buffer_t *buffer); HB_EXTERN void hb_buffer_set_invisible_glyph (hb_buffer_t *buffer, hb_codepoint_t invisible); HB_EXTERN hb_codepoint_t -hb_buffer_get_invisible_glyph (hb_buffer_t *buffer); - +hb_buffer_get_invisible_glyph (const hb_buffer_t *buffer); HB_EXTERN void -hb_buffer_reset (hb_buffer_t *buffer); +hb_buffer_set_not_found_glyph (hb_buffer_t *buffer, + hb_codepoint_t not_found); + +HB_EXTERN hb_codepoint_t +hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer); + + +/* + * Content API. + */ HB_EXTERN void hb_buffer_clear_contents (hb_buffer_t *buffer); @@ -453,7 +543,7 @@ HB_EXTERN void hb_buffer_append (hb_buffer_t *buffer, - hb_buffer_t *source, + const hb_buffer_t *source, unsigned int start, unsigned int end); @@ -462,7 +552,7 @@ unsigned int length); HB_EXTERN unsigned int -hb_buffer_get_length (hb_buffer_t *buffer); +hb_buffer_get_length (const hb_buffer_t *buffer); /* Getting glyphs out of the buffer */ @@ -496,6 +586,7 @@ * @HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS: serialize glyph flags. Since: 1.5.0 * @HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES: do not serialize glyph advances, * glyph offsets will reflect absolute glyph positions. Since: 1.8.0 + * @HB_BUFFER_SERIALIZE_FLAG_DEFINED: All currently defined flags. Since: 4.4.0 * * Flags that control what glyph information are serialized in hb_buffer_serialize_glyphs(). * @@ -508,7 +599,9 @@ HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u, HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u, HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS = 0x00000010u, - HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES = 0x00000020u + HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES = 0x00000020u, + + HB_BUFFER_SERIALIZE_FLAG_DEFINED = 0x0000003Fu } hb_buffer_serialize_flags_t; /** @@ -550,24 +643,24 @@ HB_EXTERN unsigned int hb_buffer_serialize_unicode (hb_buffer_t *buffer, - unsigned int start, - unsigned int end, - char *buf, - unsigned int buf_size, - unsigned int *buf_consumed, - hb_buffer_serialize_format_t format, - hb_buffer_serialize_flags_t flags); + unsigned int start, + unsigned int end, + char *buf, + unsigned int buf_size, + unsigned int *buf_consumed, + hb_buffer_serialize_format_t format, + hb_buffer_serialize_flags_t flags); HB_EXTERN unsigned int hb_buffer_serialize (hb_buffer_t *buffer, - unsigned int start, - unsigned int end, - char *buf, - unsigned int buf_size, - unsigned int *buf_consumed, - hb_font_t *font, - hb_buffer_serialize_format_t format, - hb_buffer_serialize_flags_t flags); + unsigned int start, + unsigned int end, + char *buf, + unsigned int buf_size, + unsigned int *buf_consumed, + hb_font_t *font, + hb_buffer_serialize_format_t format, + hb_buffer_serialize_flags_t flags); HB_EXTERN hb_bool_t hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, @@ -579,10 +672,10 @@ HB_EXTERN hb_bool_t hb_buffer_deserialize_unicode (hb_buffer_t *buffer, - const char *buf, - int buf_len, - const char **end_ptr, - hb_buffer_serialize_format_t format); + const char *buf, + int buf_len, + const char **end_ptr, + hb_buffer_serialize_format_t format); diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh 2022-10-10 13:07:22.000000000 +0000 @@ -57,6 +57,7 @@ static_assert ((sizeof (hb_glyph_info_t) == 20), ""); static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), ""); +HB_MARK_AS_FLAG_T (hb_glyph_flags_t); HB_MARK_AS_FLAG_T (hb_buffer_flags_t); HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t); HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t); @@ -67,14 +68,15 @@ HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u, HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u, HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u, - HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK = 0x00000010u, - HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000020u, - - /* Reserved for complex shapers' internal use. */ - HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u, - HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u, - HB_BUFFER_SCRATCH_FLAG_COMPLEX2 = 0x04000000u, - HB_BUFFER_SCRATCH_FLAG_COMPLEX3 = 0x08000000u, + HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000010u, + HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS = 0x00000020u, + HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE = 0x00000040u, + + /* Reserved for shapers' internal use. */ + HB_BUFFER_SCRATCH_FLAG_SHAPER0 = 0x01000000u, + HB_BUFFER_SCRATCH_FLAG_SHAPER1 = 0x02000000u, + HB_BUFFER_SCRATCH_FLAG_SHAPER2 = 0x04000000u, + HB_BUFFER_SCRATCH_FLAG_SHAPER3 = 0x08000000u, }; HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t); @@ -87,35 +89,38 @@ { hb_object_header_t header; - /* Information about how the text in the buffer should be treated */ + /* + * Information about how the text in the buffer should be treated. + */ + hb_unicode_funcs_t *unicode; /* Unicode functions */ hb_buffer_flags_t flags; /* BOT / EOT / etc. */ hb_buffer_cluster_level_t cluster_level; hb_codepoint_t replacement; /* U+FFFD or something else. */ hb_codepoint_t invisible; /* 0 or something else. */ - hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */ - unsigned int max_len; /* Maximum allowed len. */ - int max_ops; /* Maximum allowed operations. */ + hb_codepoint_t not_found; /* 0 or something else. */ + + /* + * Buffer contents + */ - /* Buffer contents */ hb_buffer_content_type_t content_type; hb_segment_properties_t props; /* Script, language, direction */ bool successful; /* Allocations successful */ + bool shaping_failed; /* Shaping failure */ bool have_output; /* Whether we have an output buffer going on */ bool have_positions; /* Whether we have positions */ unsigned int idx; /* Cursor into ->info and ->pos arrays */ unsigned int len; /* Length of ->info and ->pos arrays */ - unsigned int out_len; /* Length of ->out array if have_output */ + unsigned int out_len; /* Length of ->out_info array if have_output */ unsigned int allocated; /* Length of allocated arrays */ hb_glyph_info_t *info; hb_glyph_info_t *out_info; hb_glyph_position_t *pos; - unsigned int serial; - /* Text before / after the main buffer contents. * Always in Unicode, and ordered outward. * Index 0 is for "pre-context", 1 for "post-context". */ @@ -123,18 +128,32 @@ hb_codepoint_t context[2][CONTEXT_LENGTH]; unsigned int context_len[2]; - /* Debugging API */ + + /* + * Managed by enter / leave + */ + + uint8_t allocated_var_bits; + uint8_t serial; + hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */ + unsigned int max_len; /* Maximum allowed len. */ + int max_ops; /* Maximum allowed operations. */ + /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */ + + + /* + * Messaging callback + */ + #ifndef HB_NO_BUFFER_MESSAGE hb_buffer_message_func_t message_func; void *message_data; hb_destroy_func_t message_destroy; + unsigned message_depth; /* How deeply are we inside a message callback? */ +#else + static constexpr unsigned message_depth = 0u; #endif - /* Internal debugging. */ - /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */ -#ifndef HB_NDEBUG - uint8_t allocated_var_bits; -#endif /* Methods */ @@ -143,38 +162,40 @@ void allocate_var (unsigned int start, unsigned int count) { -#ifndef HB_NDEBUG unsigned int end = start + count; assert (end <= 8); unsigned int bits = (1u< (info, len).reverse (start, end); + if (have_positions) + hb_array_t (pos, len).reverse (start, end); + } + void reverse () { reverse_range (0, len); } + + template + void reverse_groups (const FuncType& group, + bool merge_clusters = false) + { + if (unlikely (!len)) + return; + + unsigned start = 0; + unsigned i; + for (i = 1; i < len; i++) + { + if (!group (info[i - 1], info[i])) + { + if (merge_clusters) + this->merge_clusters (start, i); + reverse_range (start, i); + start = i; + } + } + if (merge_clusters) + this->merge_clusters (start, i); + reverse_range (start, i); + + reverse (); + } + + template + unsigned group_end (unsigned start, const FuncType& group) const + { + while (++start < len && group (info[start - 1], info[start])) + ; + + return start; + } + + static bool _cluster_group_func (const hb_glyph_info_t& a, + const hb_glyph_info_t& b) + { return a.cluster == b.cluster; } + + void reverse_clusters () { reverse_groups (_cluster_group_func); } + HB_INTERNAL void guess_segment_properties (); - HB_INTERNAL void swap_buffers (); - HB_INTERNAL void remove_output (); + HB_INTERNAL void sync (); HB_INTERNAL void clear_output (); HB_INTERNAL void clear_positions (); @@ -320,15 +402,87 @@ /* Merge clusters for deleting current glyph, and skip it. */ HB_INTERNAL void delete_glyph (); - void unsafe_to_break (unsigned int start, - unsigned int end) + + /* Adds glyph flags in mask to infos with clusters between start and end. + * The start index will be from out-buffer if from_out_buffer is true. + * If interior is true, then the cluster having the minimum value is skipped. */ + void _set_glyph_flags (hb_mask_t mask, + unsigned start = 0, + unsigned end = (unsigned) -1, + bool interior = false, + bool from_out_buffer = false) { - if (end - start < 2) + end = hb_min (end, len); + + if (interior && !from_out_buffer && end - start < 2) return; - unsafe_to_break_impl (start, end); + + scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS; + + if (!from_out_buffer || !have_output) + { + if (!interior) + { + for (unsigned i = start; i < end; i++) + info[i].mask |= mask; + } + else + { + unsigned cluster = _infos_find_min_cluster (info, start, end); + _infos_set_glyph_flags (info, start, end, cluster, mask); + } + } + else + { + assert (start <= out_len); + assert (idx <= end); + + if (!interior) + { + for (unsigned i = start; i < out_len; i++) + out_info[i].mask |= mask; + for (unsigned i = idx; i < end; i++) + info[i].mask |= mask; + } + else + { + unsigned cluster = _infos_find_min_cluster (info, idx, end); + cluster = _infos_find_min_cluster (out_info, start, out_len, cluster); + + _infos_set_glyph_flags (out_info, start, out_len, cluster, mask); + _infos_set_glyph_flags (info, idx, end, cluster, mask); + } + } + } + + void unsafe_to_break (unsigned int start = 0, unsigned int end = -1) + { + _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, + start, end, + true); + } + void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1) + { + if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0)) + return; + _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, + start, end, + true); + } + void unsafe_to_break_from_outbuffer (unsigned int start = 0, unsigned int end = -1) + { + _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, + start, end, + true, true); + } + void unsafe_to_concat_from_outbuffer (unsigned int start = 0, unsigned int end = -1) + { + if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0)) + return; + _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, + start, end, + false, true); } - HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end); - HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end); /* Internal methods */ @@ -398,12 +552,18 @@ #ifdef HB_NO_BUFFER_MESSAGE return true; #else - if (!messaging ()) + if (likely (!messaging ())) return true; + + message_depth++; + va_list ap; va_start (ap, fmt); bool ret = message_impl (font, fmt, ap); va_end (ap); + + message_depth--; + return ret; #endif } @@ -413,75 +573,59 @@ set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0) { if (inf.cluster != cluster) - { - if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) - inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK; - else - inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK; - } + inf.mask = (inf.mask & ~HB_GLYPH_FLAG_DEFINED) | (mask & HB_GLYPH_FLAG_DEFINED); inf.cluster = cluster; } - - unsigned int - _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos, - unsigned int start, unsigned int end, - unsigned int cluster) const - { - for (unsigned int i = start; i < end; i++) - cluster = hb_min (cluster, infos[i].cluster); - return cluster; - } void - _unsafe_to_break_set_mask (hb_glyph_info_t *infos, - unsigned int start, unsigned int end, - unsigned int cluster) + _infos_set_glyph_flags (hb_glyph_info_t *infos, + unsigned int start, unsigned int end, + unsigned int cluster, + hb_mask_t mask) { for (unsigned int i = start; i < end; i++) if (cluster != infos[i].cluster) { - scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK; - infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS; + infos[i].mask |= mask; } } + static unsigned + _infos_find_min_cluster (const hb_glyph_info_t *infos, + unsigned start, unsigned end, + unsigned cluster = UINT_MAX) + { + for (unsigned int i = start; i < end; i++) + cluster = hb_min (cluster, infos[i].cluster); + return cluster; + } - void unsafe_to_break_all () { unsafe_to_break_impl (0, len); } - void safe_to_break_all () + void clear_glyph_flags (hb_mask_t mask = 0) { for (unsigned int i = 0; i < len; i++) - info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + info[i].mask = (info[i].mask & ~HB_GLYPH_FLAG_DEFINED) | (mask & HB_GLYPH_FLAG_DEFINED); } }; DECLARE_NULL_INSTANCE (hb_buffer_t); -/* Loop over clusters. Duplicated in foreach_syllable(). */ -#define foreach_cluster(buffer, start, end) \ +#define foreach_group(buffer, start, end, group_func) \ for (unsigned int \ _count = buffer->len, \ - start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \ + start = 0, end = _count ? buffer->group_end (0, group_func) : 0; \ start < _count; \ - start = end, end = _next_cluster (buffer, start)) + start = end, end = buffer->group_end (start, group_func)) -static inline unsigned int -_next_cluster (hb_buffer_t *buffer, unsigned int start) -{ - hb_glyph_info_t *info = buffer->info; - unsigned int count = buffer->len; - - unsigned int cluster = info[start].cluster; - while (++start < count && cluster == info[start].cluster) - ; - - return start; -} +#define foreach_cluster(buffer, start, end) \ + foreach_group (buffer, start, end, hb_buffer_t::_cluster_group_func) #define HB_BUFFER_XALLOCATE_VAR(b, func, var) \ b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \ sizeof (b->info[0].var)) -#define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ()) -#define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ()) -#define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ()) +#define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ()) +#define HB_BUFFER_TRY_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, try_allocate_var, var ()) +#define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ()) +#define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ()) #endif /* HB_BUFFER_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-serialize.cc 2022-10-10 13:07:22.000000000 +0000 @@ -31,7 +31,7 @@ #include "hb-buffer.hh" -static const char *serialize_formats[] = { +static const char *_hb_buffer_serialize_formats[] = { "text", "json", nullptr @@ -50,7 +50,7 @@ const char ** hb_buffer_serialize_list_formats () { - return serialize_formats; + return _hb_buffer_serialize_formats; } /** @@ -91,8 +91,8 @@ { switch ((unsigned) format) { - case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0]; - case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1]; + case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return _hb_buffer_serialize_formats[0]; + case HB_BUFFER_SERIALIZE_FORMAT_JSON: return _hb_buffer_serialize_formats[1]; default: case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return nullptr; } @@ -400,9 +400,9 @@ * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to * write serialized buffer into. * @buf_size: the size of @buf. - * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf. + * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of bytes written into @buf. * @font: (nullable): the #hb_font_t used to shape this buffer, needed to - * read glyph names and extents. If %NULL, and empty font will be used. + * read glyph names and extents. If %NULL, an empty font will be used. * @format: the #hb_buffer_serialize_format_t to use for formatting the output. * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties * to serialize. @@ -514,7 +514,7 @@ * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to * write serialized buffer into. * @buf_size: the size of @buf. - * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf. + * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of bytes written into @buf. * @format: the #hb_buffer_serialize_format_t to use for formatting the output. * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties * to serialize. @@ -637,9 +637,9 @@ * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to * write serialized buffer into. * @buf_size: the size of @buf. - * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf. + * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of bytes written into @buf. * @font: (nullable): the #hb_font_t used to shape this buffer, needed to - * read glyph names and extents. If %NULL, and empty font will be used. + * read glyph names and extents. If %NULL, an empty font will be used. * @format: the #hb_buffer_serialize_format_t to use for formatting the output. * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties * to serialize. diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,440 @@ +/* + * Copyright © 2022 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb.hh" + +#ifndef HB_NO_BUFFER_VERIFY + +#include "hb-buffer.hh" + + +#define BUFFER_VERIFY_ERROR "buffer verify error: " +static inline void +buffer_verify_error (hb_buffer_t *buffer, + hb_font_t *font, + const char *fmt, + ...) HB_PRINTF_FUNC(3, 4); + +static inline void +buffer_verify_error (hb_buffer_t *buffer, + hb_font_t *font, + const char *fmt, + ...) +{ + va_list ap; + va_start (ap, fmt); + if (buffer->messaging ()) + { + buffer->message_impl (font, fmt, ap); + } + else + { + fprintf (stderr, "harfbuzz "); + vfprintf (stderr, fmt, ap); + fprintf (stderr, "\n"); + } + va_end (ap); +} + +static bool +buffer_verify_monotone (hb_buffer_t *buffer, + hb_font_t *font) +{ + /* Check that clusters are monotone. */ + if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES || + buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) + { + bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer)); + + unsigned int num_glyphs; + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs); + + for (unsigned int i = 1; i < num_glyphs; i++) + if (info[i-1].cluster != info[i].cluster && + (info[i-1].cluster < info[i].cluster) != is_forward) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone."); + return false; + } + } + + return true; +} + +static bool +buffer_verify_unsafe_to_break (hb_buffer_t *buffer, + hb_buffer_t *text_buffer, + hb_font_t *font, + const hb_feature_t *features, + unsigned int num_features, + const char * const *shapers) +{ + if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES && + buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) + { + /* Cannot perform this check without monotone clusters. */ + return true; + } + + /* Check that breaking up shaping at safe-to-break is indeed safe. */ + + hb_buffer_t *fragment = hb_buffer_create_similar (buffer); + hb_buffer_set_flags (fragment, (hb_buffer_flags_t (hb_buffer_get_flags (fragment) & ~HB_BUFFER_FLAG_VERIFY))); + hb_buffer_t *reconstruction = hb_buffer_create_similar (buffer); + hb_buffer_set_flags (reconstruction, (hb_buffer_flags_t (hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY))); + + unsigned int num_glyphs; + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs); + + unsigned int num_chars; + hb_glyph_info_t *text = hb_buffer_get_glyph_infos (text_buffer, &num_chars); + + /* Chop text and shape fragments. */ + bool forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer)); + unsigned int start = 0; + unsigned int text_start = forward ? 0 : num_chars; + unsigned int text_end = text_start; + for (unsigned int end = 1; end < num_glyphs + 1; end++) + { + if (end < num_glyphs && + (info[end].cluster == info[end-1].cluster || + info[end-(forward?0:1)].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)) + continue; + + /* Shape segment corresponding to glyphs start..end. */ + if (end == num_glyphs) + { + if (forward) + text_end = num_chars; + else + text_start = 0; + } + else + { + if (forward) + { + unsigned int cluster = info[end].cluster; + while (text_end < num_chars && text[text_end].cluster < cluster) + text_end++; + } + else + { + unsigned int cluster = info[end - 1].cluster; + while (text_start && text[text_start - 1].cluster >= cluster) + text_start--; + } + } + assert (text_start < text_end); + + if (0) + printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end); + + hb_buffer_clear_contents (fragment); + + hb_buffer_flags_t flags = hb_buffer_get_flags (fragment); + if (0 < text_start) + flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT); + if (text_end < num_chars) + flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT); + hb_buffer_set_flags (fragment, flags); + + hb_buffer_append (fragment, text_buffer, text_start, text_end); + if (!hb_shape_full (font, fragment, features, num_features, shapers)) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); + hb_buffer_destroy (reconstruction); + hb_buffer_destroy (fragment); + return false; + } + else if (!fragment->successful || fragment->shaping_failed) + { + hb_buffer_destroy (reconstruction); + hb_buffer_destroy (fragment); + return true; + } + hb_buffer_append (reconstruction, fragment, 0, -1); + + start = end; + if (forward) + text_start = text_end; + else + text_end = text_start; + } + + bool ret = true; + hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); + if (diff) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed."); + ret = false; + + /* Return the reconstructed result instead so it can be inspected. */ + hb_buffer_set_length (buffer, 0); + hb_buffer_append (buffer, reconstruction, 0, -1); + } + + hb_buffer_destroy (reconstruction); + hb_buffer_destroy (fragment); + + return ret; +} + +static bool +buffer_verify_unsafe_to_concat (hb_buffer_t *buffer, + hb_buffer_t *text_buffer, + hb_font_t *font, + const hb_feature_t *features, + unsigned int num_features, + const char * const *shapers) +{ + if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES && + buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) + { + /* Cannot perform this check without monotone clusters. */ + return true; + } + + /* Check that shuffling up text before shaping at safe-to-concat points + * is indeed safe. */ + + /* This is what we do: + * + * 1. We shape text once. Then segment the text at all the safe-to-concat + * points; + * + * 2. Then we create two buffers, one containing all the even segments and + * one all the odd segments. + * + * 3. Because all these segments were safe-to-concat at both ends, we + * expect that concatenating them and shaping should NOT change the + * shaping results of each segment. As such, we expect that after + * shaping the two buffers, we still get cluster boundaries at the + * segment boundaries, and that those all are safe-to-concat points. + * Moreover, that there are NOT any safe-to-concat points within the + * segments. + * + * 4. Finally, we reconstruct the shaping results of the original text by + * simply interleaving the shaping results of the segments from the two + * buffers, and assert that the total shaping results is the same as + * the one from original buffer in step 1. + */ + + hb_buffer_t *fragments[2] {hb_buffer_create_similar (buffer), + hb_buffer_create_similar (buffer)}; + hb_buffer_set_flags (fragments[0], (hb_buffer_flags_t (hb_buffer_get_flags (fragments[0]) & ~HB_BUFFER_FLAG_VERIFY))); + hb_buffer_set_flags (fragments[1], (hb_buffer_flags_t (hb_buffer_get_flags (fragments[1]) & ~HB_BUFFER_FLAG_VERIFY))); + hb_buffer_t *reconstruction = hb_buffer_create_similar (buffer); + hb_buffer_set_flags (reconstruction, (hb_buffer_flags_t (hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY))); + hb_segment_properties_t props; + hb_buffer_get_segment_properties (buffer, &props); + hb_buffer_set_segment_properties (fragments[0], &props); + hb_buffer_set_segment_properties (fragments[1], &props); + hb_buffer_set_segment_properties (reconstruction, &props); + + unsigned num_glyphs; + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs); + + unsigned num_chars; + hb_glyph_info_t *text = hb_buffer_get_glyph_infos (text_buffer, &num_chars); + + bool forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer)); + + if (!forward) + hb_buffer_reverse (buffer); + + /* + * Split text into segments and collect into to fragment streams. + */ + { + unsigned fragment_idx = 0; + unsigned start = 0; + unsigned text_start = 0; + unsigned text_end = 0; + for (unsigned end = 1; end < num_glyphs + 1; end++) + { + if (end < num_glyphs && + (info[end].cluster == info[end-1].cluster || + info[end].mask & HB_GLYPH_FLAG_UNSAFE_TO_CONCAT)) + continue; + + /* Accumulate segment corresponding to glyphs start..end. */ + if (end == num_glyphs) + text_end = num_chars; + else + { + unsigned cluster = info[end].cluster; + while (text_end < num_chars && text[text_end].cluster < cluster) + text_end++; + } + assert (text_start < text_end); + + if (0) + printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end); + +#if 0 + hb_buffer_flags_t flags = hb_buffer_get_flags (fragment); + if (0 < text_start) + flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT); + if (text_end < num_chars) + flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT); + hb_buffer_set_flags (fragment, flags); +#endif + + hb_buffer_append (fragments[fragment_idx], text_buffer, text_start, text_end); + + start = end; + text_start = text_end; + fragment_idx = 1 - fragment_idx; + } + } + + bool ret = true; + hb_buffer_diff_flags_t diff; + + /* + * Shape the two fragment streams. + */ + if (!hb_shape_full (font, fragments[0], features, num_features, shapers)) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); + ret = false; + goto out; + } + else if (!fragments[0]->successful || fragments[0]->shaping_failed) + { + ret = true; + goto out; + } + if (!hb_shape_full (font, fragments[1], features, num_features, shapers)) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment."); + ret = false; + goto out; + } + else if (!fragments[1]->successful || fragments[1]->shaping_failed) + { + ret = true; + goto out; + } + + if (!forward) + { + hb_buffer_reverse (fragments[0]); + hb_buffer_reverse (fragments[1]); + } + + /* + * Reconstruct results. + */ + { + unsigned fragment_idx = 0; + unsigned fragment_start[2] {0, 0}; + unsigned fragment_num_glyphs[2]; + hb_glyph_info_t *fragment_info[2]; + for (unsigned i = 0; i < 2; i++) + fragment_info[i] = hb_buffer_get_glyph_infos (fragments[i], &fragment_num_glyphs[i]); + while (fragment_start[0] < fragment_num_glyphs[0] || + fragment_start[1] < fragment_num_glyphs[1]) + { + unsigned fragment_end = fragment_start[fragment_idx] + 1; + while (fragment_end < fragment_num_glyphs[fragment_idx] && + (fragment_info[fragment_idx][fragment_end].cluster == fragment_info[fragment_idx][fragment_end - 1].cluster || + fragment_info[fragment_idx][fragment_end].mask & HB_GLYPH_FLAG_UNSAFE_TO_CONCAT)) + fragment_end++; + + hb_buffer_append (reconstruction, fragments[fragment_idx], fragment_start[fragment_idx], fragment_end); + + fragment_start[fragment_idx] = fragment_end; + fragment_idx = 1 - fragment_idx; + } + } + + if (!forward) + { + hb_buffer_reverse (buffer); + hb_buffer_reverse (reconstruction); + } + + /* + * Diff results. + */ + diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); + if (diff) + { + buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed."); + ret = false; + + /* Return the reconstructed result instead so it can be inspected. */ + hb_buffer_set_length (buffer, 0); + hb_buffer_append (buffer, reconstruction, 0, -1); + } + + +out: + hb_buffer_destroy (reconstruction); + hb_buffer_destroy (fragments[0]); + hb_buffer_destroy (fragments[1]); + + return ret; +} + +bool +hb_buffer_t::verify (hb_buffer_t *text_buffer, + hb_font_t *font, + const hb_feature_t *features, + unsigned int num_features, + const char * const *shapers) +{ + bool ret = true; + if (!buffer_verify_monotone (this, font)) + ret = false; + if (!buffer_verify_unsafe_to_break (this, text_buffer, font, features, num_features, shapers)) + ret = false; + if ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) != 0 && + !buffer_verify_unsafe_to_concat (this, text_buffer, font, features, num_features, shapers)) + ret = false; + if (!ret) + { +#ifndef HB_NO_BUFFER_SERIALIZE + unsigned len = text_buffer->len; + hb_vector_t bytes; + if (likely (bytes.resize (len * 10 + 16))) + { + hb_buffer_serialize_unicode (text_buffer, + 0, len, + bytes.arrayZ, bytes.length, + &len, + HB_BUFFER_SERIALIZE_FORMAT_TEXT, + HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS); + buffer_verify_error (this, font, BUFFER_VERIFY_ERROR "text was: %s.", bytes.arrayZ); + } +#endif + } + return ret; +} + + +#endif diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-cache.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-cache.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-cache.hh 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-cache.hh 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,80 @@ +/* + * Copyright © 2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_CACHE_HH +#define HB_CACHE_HH + +#include "hb.hh" + + +/* Implements a lockfree cache for int->int functions. */ + +template +struct hb_cache_t +{ + static_assert ((key_bits >= cache_bits), ""); + static_assert ((key_bits + value_bits - cache_bits <= 8 * sizeof (hb_atomic_int_t)), ""); + static_assert (sizeof (hb_atomic_int_t) == sizeof (unsigned int), ""); + + void init () { clear (); } + void fini () {} + + void clear () + { + for (unsigned i = 0; i < ARRAY_LENGTH (values); i++) + values[i].set_relaxed (-1); + } + + bool get (unsigned int key, unsigned int *value) const + { + unsigned int k = key & ((1u<> value_bits) != (key >> cache_bits)) + return false; + *value = v & ((1u<> key_bits) || (value >> value_bits))) + return false; /* Overflows */ + unsigned int k = key & ((1u<>cache_bits)< hb_cmap_cache_t; +typedef hb_cache_t<16, 24, 8> hb_advance_cache_t; + + +#endif /* HB_CACHE_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-cff1-interp-cs.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-cff1-interp-cs.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-cff1-interp-cs.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-cff1-interp-cs.hh 2022-10-10 13:07:22.000000000 +0000 @@ -38,17 +38,15 @@ struct cff1_cs_interp_env_t : cs_interp_env_t { template - void init (const byte_str_t &str, ACC &acc, unsigned int fd) + cff1_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd) + : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs) { - SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs); processed_width = false; has_width = false; arg_start = 0; in_seac = false; } - void fini () { SUPER::fini (); } - void set_width (bool has_width_) { if (likely (!processed_width && (SUPER::argStack.get_count () > 0))) @@ -154,7 +152,7 @@ }; template -struct cff1_cs_interpreter_t : cs_interpreter_t {}; +using cff1_cs_interpreter_t = cs_interpreter_t; } /* namespace CFF */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh 2022-10-10 13:07:22.000000000 +0000 @@ -35,18 +35,6 @@ struct blend_arg_t : number_t { - void init () - { - number_t::init (); - deltas.init (); - } - - void fini () - { - number_t::fini (); - deltas.fini_deep (); - } - void set_int (int v) { reset_blends (); number_t::set_int (v); } void set_fixed (int32_t v) { reset_blends (); number_t::set_fixed (v); } void set_real (double v) { reset_blends (); number_t::set_real (v); } @@ -76,14 +64,14 @@ typedef interp_env_t BlendInterpEnv; typedef biased_subrs_t cff2_biased_subrs_t; -struct cff2_cs_interp_env_t : cs_interp_env_t +template +struct cff2_cs_interp_env_t : cs_interp_env_t { template - void init (const byte_str_t &str, ACC &acc, unsigned int fd, - const int *coords_=nullptr, unsigned int num_coords_=0) + cff2_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd, + const int *coords_=nullptr, unsigned int num_coords_=0) + : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs) { - SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs); - coords = coords_; num_coords = num_coords_; varStore = acc.varStore; @@ -112,18 +100,14 @@ return OpCode_return; } - const blend_arg_t& eval_arg (unsigned int i) + const ELEM& eval_arg (unsigned int i) { - blend_arg_t &arg = argStack[i]; - blend_arg (arg); - return arg; + return SUPER::argStack[i]; } - const blend_arg_t& pop_arg () + const ELEM& pop_arg () { - blend_arg_t &arg = argStack.pop (); - blend_arg (arg); - return arg; + return SUPER::argStack.pop (); } void process_blend () @@ -134,10 +118,10 @@ if (do_blend) { if (unlikely (!scalars.resize (region_count))) - set_error (); + SUPER::set_error (); else - varStore->varStore.get_scalars (get_ivs (), coords, num_coords, - &scalars[0], region_count); + varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords, + &scalars[0], region_count); } seen_blend = true; } @@ -145,10 +129,10 @@ void process_vsindex () { - unsigned int index = argStack.pop_uint (); + unsigned int index = SUPER::argStack.pop_uint (); if (unlikely (seen_vsindex () || seen_blend)) { - set_error (); + SUPER::set_error (); } else { @@ -163,22 +147,18 @@ void set_ivs (unsigned int ivs_) { ivs = ivs_; } bool seen_vsindex () const { return seen_vsindex_; } - protected: - void blend_arg (blend_arg_t &arg) + double blend_deltas (hb_array_t deltas) const { - if (do_blend && arg.blending ()) + double v = 0; + if (do_blend) { - if (likely (scalars.length == arg.deltas.length)) + if (likely (scalars.length == deltas.length)) { - double v = arg.to_real (); for (unsigned int i = 0; i < scalars.length; i++) - { - v += (double)scalars[i] * arg.deltas[i].to_real (); - } - arg.set_real (v); - arg.deltas.resize (0); + v += (double) scalars[i] * deltas[i].to_real (); } } + return v; } protected: @@ -192,22 +172,24 @@ bool seen_vsindex_; bool seen_blend; - typedef cs_interp_env_t SUPER; + typedef cs_interp_env_t SUPER; }; -template > -struct cff2_cs_opset_t : cs_opset_t +template , PARAM>> +struct cff2_cs_opset_t : cs_opset_t, PARAM, PATH> { - static void process_op (op_code_t op, cff2_cs_interp_env_t &env, PARAM& param) + static void process_op (op_code_t op, cff2_cs_interp_env_t &env, PARAM& param) { switch (op) { case OpCode_callsubr: case OpCode_callgsubr: - /* a subroutine number shoudln't be a blended value */ + /* a subroutine number shouldn't be a blended value */ +#if 0 if (unlikely (env.argStack.peek ().blending ())) { env.set_error (); break; } +#endif SUPER::process_op (op, env, param); break; @@ -216,11 +198,13 @@ break; case OpCode_vsindexcs: +#if 0 if (unlikely (env.argStack.peek ().blending ())) { env.set_error (); break; } +#endif OPSET::process_vsindex (env, param); break; @@ -229,7 +213,26 @@ } } - static void process_blend (cff2_cs_interp_env_t &env, PARAM& param) + template + static void process_arg_blend (cff2_cs_interp_env_t &env, + ELEM &arg, + const hb_array_t blends, + unsigned n, unsigned i) + { + arg.set_blends (n, i, blends.length, blends); + } + template + static void process_arg_blend (cff2_cs_interp_env_t &env, + ELEM &arg, + const hb_array_t blends, + unsigned n, unsigned i) + { + arg.set_real (arg.to_real () + env.blend_deltas (blends)); + } + + static void process_blend (cff2_cs_interp_env_t &env, PARAM& param) { unsigned int n, k; @@ -246,26 +249,26 @@ } for (unsigned int i = 0; i < n; i++) { - const hb_array_t blends = env.argStack.get_subarray (start + n + (i * k)); - env.argStack[start + i].set_blends (n, i, k, blends); + const hb_array_t blends = env.argStack.sub_array (start + n + (i * k), k); + process_arg_blend (env, env.argStack[start + i], blends, n, i); } /* pop off blend values leaving default values now adorned with blend values */ env.argStack.pop (k * n); } - static void process_vsindex (cff2_cs_interp_env_t &env, PARAM& param) + static void process_vsindex (cff2_cs_interp_env_t &env, PARAM& param) { env.process_vsindex (); env.clear_args (); } private: - typedef cs_opset_t SUPER; + typedef cs_opset_t, PARAM, PATH> SUPER; }; -template -struct cff2_cs_interpreter_t : cs_interpreter_t {}; +template +using cff2_cs_interpreter_t = cs_interpreter_t, OPSET, PARAM>; } /* namespace CFF */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-common.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-common.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-common.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-common.hh 2022-10-10 13:07:22.000000000 +0000 @@ -217,9 +217,6 @@ struct number_t { - void init () { set_real (0.0); } - void fini () {} - void set_int (int v) { value = v; } int to_int () const { return value; } @@ -245,12 +242,15 @@ } protected: - double value; + double value = 0.; }; /* byte string */ struct UnsizedByteStr : UnsizedArrayOf { + hb_ubytes_t as_ubytes (unsigned l) const + { return hb_ubytes_t ((const unsigned char *) this, l); } + // encode 2-byte int (Dict/CharString) or 4-byte int (Dict) template static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, V value) @@ -263,7 +263,7 @@ T *ip = c->allocate_size (T::static_size); if (unlikely (!ip)) return_trace (false); - return_trace (c->check_assign (*ip, value)); + return_trace (c->check_assign (*ip, value, HB_SERIALIZE_ERROR_INT_OVERFLOW)); } template @@ -277,33 +277,10 @@ /* Defining null_size allows a Null object may be created. Should be safe because: * A descendent struct Dict uses a Null pointer to indicate a missing table, * checked before access. - * byte_str_t, a wrapper struct pairing a byte pointer along with its length, always - * checks the length before access. A Null pointer is used as the initial pointer - * along with zero length by the default ctor. */ DEFINE_SIZE_MIN(0); }; -/* Holder of a section of byte string within a CFFIndex entry */ -struct byte_str_t : hb_ubytes_t -{ - byte_str_t () - : hb_ubytes_t () {} - byte_str_t (const UnsizedByteStr& s, unsigned int l) - : hb_ubytes_t ((const unsigned char*)&s, l) {} - byte_str_t (const unsigned char *s, unsigned int l) - : hb_ubytes_t (s, l) {} - byte_str_t (const hb_ubytes_t &ub) /* conversion from hb_ubytes_t */ - : hb_ubytes_t (ub) {} - - /* sub-string */ - byte_str_t sub_str (unsigned int offset, unsigned int len_) const - { return byte_str_t (hb_ubytes_t::sub_array (offset, len_)); } - - bool check_limit (unsigned int offset, unsigned int count) const - { return (offset + count <= length); } -}; - /* A byte string associated with the current offset and an error condition */ struct byte_str_ref_t { @@ -311,17 +288,17 @@ void init () { - str = byte_str_t (); + str = hb_ubytes_t (); offset = 0; error = false; } void fini () {} - byte_str_ref_t (const byte_str_t &str_, unsigned int offset_ = 0) + byte_str_ref_t (const hb_ubytes_t &str_, unsigned int offset_ = 0) : str (str_), offset (offset_), error (false) {} - void reset (const byte_str_t &str_, unsigned int offset_ = 0) + void reset (const hb_ubytes_t &str_, unsigned int offset_ = 0) { str = str_; offset = offset_; @@ -337,14 +314,14 @@ return str[offset + i]; } - /* Conversion to byte_str_t */ - operator byte_str_t () const { return str.sub_str (offset, str.length - offset); } + /* Conversion to hb_ubytes_t */ + operator hb_ubytes_t () const { return str.sub_array (offset, str.length - offset); } - byte_str_t sub_str (unsigned int offset_, unsigned int len_) const - { return str.sub_str (offset_, len_); } + hb_ubytes_t sub_array (unsigned int offset_, unsigned int len_) const + { return str.sub_array (offset_, len_); } bool avail (unsigned int count=1) const - { return (!in_error () && str.check_limit (offset, count)); } + { return (!in_error () && offset + count <= str.length); } void inc (unsigned int count=1) { if (likely (!in_error () && (offset <= str.length) && (offset + count <= str.length))) @@ -361,46 +338,39 @@ void set_error () { error = true; } bool in_error () const { return error; } - byte_str_t str; + hb_ubytes_t str; unsigned int offset; /* beginning of the sub-string within str */ protected: bool error; }; -typedef hb_vector_t byte_str_array_t; +using byte_str_array_t = hb_vector_t; /* stack */ template struct cff_stack_t { - void init () - { - error = false; - count = 0; - elements.init (); - elements.resize (kSizeLimit); - for (unsigned int i = 0; i < elements.length; i++) - elements[i].init (); - } - void fini () { elements.fini_deep (); } - ELEM& operator [] (unsigned int i) { - if (unlikely (i >= count)) set_error (); + if (unlikely (i >= count)) + { + set_error (); + return Crap (ELEM); + } return elements[i]; } void push (const ELEM &v) { - if (likely (count < elements.length)) + if (likely (count < LIMIT)) elements[count++] = v; else set_error (); } ELEM &push () { - if (likely (count < elements.length)) + if (likely (count < LIMIT)) return elements[count++]; else { @@ -429,7 +399,7 @@ const ELEM& peek () { - if (unlikely (count < 0)) + if (unlikely (count == 0)) { set_error (); return Null (ELEM); @@ -439,7 +409,7 @@ void unpop () { - if (likely (count < elements.length)) + if (likely (count < LIMIT)) count++; else set_error (); @@ -447,18 +417,19 @@ void clear () { count = 0; } - bool in_error () const { return (error || elements.in_error ()); } + bool in_error () const { return (error); } void set_error () { error = true; } unsigned int get_count () const { return count; } bool is_empty () const { return !count; } - static constexpr unsigned kSizeLimit = LIMIT; + hb_array_t sub_array (unsigned start, unsigned length) const + { return hb_array_t (elements).sub_array (start, length); } - protected: - bool error; - unsigned int count; - hb_vector_t elements; + private: + bool error = false; + unsigned int count = 0; + ELEM elements[LIMIT]; }; /* argument stack */ @@ -513,9 +484,6 @@ return true; } - hb_array_t get_subarray (unsigned int start) const - { return S::elements.sub_array (start); } - private: typedef cff_stack_t S; }; @@ -523,11 +491,8 @@ /* an operator prefixed by its operands in a byte string */ struct op_str_t { - void init () {} - void fini () {} - + hb_ubytes_t str; op_code_t op; - byte_str_t str; }; /* base of OP_SERIALIZER */ @@ -553,13 +518,18 @@ opStart = 0; values.init (); } - void fini () { values.fini_deep (); } + void fini () { values.fini (); } + + void alloc (unsigned n) + { + values.alloc (n); + } void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t ()) { VAL *val = values.push (); val->op = op; - val->str = str_ref.str.sub_str (opStart, str_ref.offset - opStart); + val->str = str_ref.str.sub_array (opStart, str_ref.offset - opStart); opStart = str_ref.offset; } @@ -567,14 +537,14 @@ { VAL *val = values.push (v); val->op = op; - val->str = str_ref.sub_str ( opStart, str_ref.offset - opStart); + val->str = str_ref.sub_array ( opStart, str_ref.offset - opStart); opStart = str_ref.offset; } bool has_op (op_code_t op) const { - for (unsigned int i = 0; i < get_count (); i++) - if (get_value (i).op == op) return true; + for (const auto& v : values) + if (v.op == op) return true; return false; } @@ -589,14 +559,11 @@ template struct interp_env_t { - void init (const byte_str_t &str_) + interp_env_t () {} + interp_env_t (const hb_ubytes_t &str_) { str_ref.reset (str_); - argStack.init (); - error = false; } - void fini () { argStack.fini (); } - bool in_error () const { return error || str_ref.in_error () || argStack.in_error (); } @@ -630,10 +597,10 @@ arg_stack_t argStack; protected: - bool error; + bool error = false; }; -typedef interp_env_t<> num_interp_env_t; +using num_interp_env_t = interp_env_t<>; template struct opset_t @@ -676,11 +643,8 @@ template struct interpreter_t { - ~interpreter_t() { fini (); } - - void fini () { env.fini (); } - - ENV env; + interpreter_t (ENV& env_) : env (env_) {} + ENV& env; }; } /* namespace CFF */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-cs-common.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-cs-common.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-cs-common.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-cs-common.hh 2022-10-10 13:07:22.000000000 +0000 @@ -79,10 +79,10 @@ unsigned int get_count () const { return subrs ? subrs->count : 0; } unsigned int get_bias () const { return bias; } - byte_str_t operator [] (unsigned int index) const + hb_ubytes_t operator [] (unsigned int index) const { if (unlikely (!subrs || index >= subrs->count)) - return Null (byte_str_t); + return hb_ubytes_t (); else return (*subrs)[index]; } @@ -94,12 +94,6 @@ struct point_t { - void init () - { - x.init (); - y.init (); - } - void set_int (int _x, int _y) { x.set_int (_x); @@ -118,26 +112,21 @@ template struct cs_interp_env_t : interp_env_t { - void init (const byte_str_t &str, const SUBRS *globalSubrs_, const SUBRS *localSubrs_) + cs_interp_env_t (const hb_ubytes_t &str, const SUBRS *globalSubrs_, const SUBRS *localSubrs_) : + interp_env_t (str) { - interp_env_t::init (str); - context.init (str, CSType_CharString); seen_moveto = true; seen_hintmask = false; hstem_count = 0; vstem_count = 0; hintmask_size = 0; - pt.init (); - callStack.init (); + pt.set_int (0, 0); globalSubrs.init (globalSubrs_); localSubrs.init (localSubrs_); } - void fini () + ~cs_interp_env_t () { - interp_env_t::fini (); - - callStack.fini (); globalSubrs.fini (); localSubrs.fini (); } @@ -841,7 +830,6 @@ if (likely (env.argStack.get_count () == 11)) { point_t d; - d.init (); for (unsigned int i = 0; i < 10; i += 2) d.move (env.eval_arg (i), env.eval_arg (i+1)); @@ -887,6 +875,8 @@ template struct cs_interpreter_t : interpreter_t { + cs_interpreter_t (ENV& env_) : interpreter_t (env_) {} + bool interpret (PARAM& param) { SUPER::env.set_endchar (false); diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-dict-common.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-dict-common.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-dict-common.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-dict-common.hh 2022-10-10 13:07:22.000000000 +0000 @@ -179,6 +179,8 @@ template struct dict_interpreter_t : interpreter_t { + dict_interpreter_t (ENV& env_) : interpreter_t (env_) {} + bool interpret (PARAM& param) { param.init (); diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-common.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-common.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-common.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-common.cc 2022-10-10 13:07:22.000000000 +0000 @@ -29,10 +29,31 @@ #include "hb.hh" #include "hb-machinery.hh" +#if !defined(HB_NO_SETLOCALE) && (!defined(HAVE_NEWLOCALE) || !defined(HAVE_USELOCALE)) +#define HB_NO_SETLOCALE 1 +#endif + +#ifndef HB_NO_SETLOCALE + #include +#ifdef HAVE_XLOCALE_H +#include // Needed on BSD/OS X for uselocale +#endif + +#ifdef WIN32 +#define hb_locale_t _locale_t +#else +#define hb_locale_t locale_t +#endif +#define hb_setlocale setlocale +#define hb_uselocale uselocale + +#else + +#define hb_locale_t void * +#define hb_setlocale(Category, Locale) "C" +#define hb_uselocale(Locale) ((hb_locale_t) 0) -#ifdef HB_NO_SETLOCALE -#define setlocale(Category, Locale) "C" #endif /** @@ -139,7 +160,7 @@ /* hb_direction_t */ -const char direction_strings[][4] = { +static const char direction_strings[][4] = { "ltr", "rtl", "ttb", @@ -257,13 +278,11 @@ bool operator == (const char *s) const { return lang_equal (lang, s); } - hb_language_item_t & operator = (const char *s) { - /* If a custom allocated is used calling strdup() pairs - badly with a call to the custom free() in fini() below. - Therefore don't call strdup(), implement its behavior. - */ + hb_language_item_t & operator = (const char *s) + { + /* We can't call strdup(), because we allow custom allocators. */ size_t len = strlen(s) + 1; - lang = (hb_language_t) malloc(len); + lang = (hb_language_t) hb_malloc(len); if (likely (lang)) { memcpy((unsigned char *) lang, s, len); @@ -274,16 +293,15 @@ return *this; } - void fini () { free ((void *) lang); } + void fini () { hb_free ((void *) lang); } }; -/* Thread-safe lock-free language list */ +/* Thread-safe lockfree language list */ static hb_atomic_ptr_t langs; -#if HB_USE_ATEXIT -static void +static inline void free_langs () { retry: @@ -294,11 +312,10 @@ while (first_lang) { hb_language_item_t *next = first_lang->next; first_lang->fini (); - free (first_lang); + hb_free (first_lang); first_lang = next; } } -#endif static hb_language_item_t * lang_find_or_insert (const char *key) @@ -311,28 +328,26 @@ return lang; /* Not found; allocate one. */ - hb_language_item_t *lang = (hb_language_item_t *) calloc (1, sizeof (hb_language_item_t)); + hb_language_item_t *lang = (hb_language_item_t *) hb_calloc (1, sizeof (hb_language_item_t)); if (unlikely (!lang)) return nullptr; lang->next = first_lang; *lang = key; if (unlikely (!lang->lang)) { - free (lang); + hb_free (lang); return nullptr; } if (unlikely (!langs.cmpexch (first_lang, lang))) { lang->fini (); - free (lang); + hb_free (lang); goto retry; } -#if HB_USE_ATEXIT if (!first_lang) - atexit (free_langs); /* First person registers atexit() callback. */ -#endif + hb_atexit (free_langs); /* First person registers atexit() callback. */ return lang; } @@ -419,7 +434,7 @@ hb_language_t language = default_language; if (unlikely (language == HB_LANGUAGE_INVALID)) { - language = hb_language_from_string (setlocale (LC_CTYPE, nullptr), -1); + language = hb_language_from_string (hb_setlocale (LC_CTYPE, nullptr), -1); (void) default_language.cmpexch (HB_LANGUAGE_INVALID, language); } @@ -601,6 +616,9 @@ case HB_SCRIPT_CHORASMIAN: case HB_SCRIPT_YEZIDI: + /* Unicode-14.0 additions */ + case HB_SCRIPT_OLD_UYGHUR: + return HB_DIRECTION_RTL; @@ -1042,6 +1060,47 @@ return false; } +#ifndef HB_NO_SETLOCALE + +static inline void free_static_C_locale (); + +static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t, + hb_C_locale_lazy_loader_t> +{ + static hb_locale_t create () + { + hb_locale_t l = newlocale (LC_ALL_MASK, "C", NULL); + if (!l) + return l; + + hb_atexit (free_static_C_locale); + + return l; + } + static void destroy (hb_locale_t l) + { + freelocale (l); + } + static hb_locale_t get_null () + { + return (hb_locale_t) 0; + } +} static_C_locale; + +static inline +void free_static_C_locale () +{ + static_C_locale.free_instance (); +} + +static hb_locale_t +get_C_locale () +{ + return static_C_locale.get_unconst (); +} + +#endif + /** * hb_variation_to_string: * @variation: an #hb_variation_t to convert @@ -1067,7 +1126,11 @@ while (len && s[len - 1] == ' ') len--; s[len++] = '='; + + hb_locale_t oldlocale HB_UNUSED; + oldlocale = hb_uselocale (get_C_locale ()); len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value)); + (void) hb_uselocale (oldlocale); assert (len < ARRAY_LENGTH (s)); len = hb_min (len, size - 1); diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-common.h openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-common.h --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-common.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-common.h 2022-10-10 13:07:22.000000000 +0000 @@ -130,6 +130,16 @@ int8_t i8[4]; } hb_var_int_t; +typedef union _hb_var_num_t { + float f; + uint32_t u32; + int32_t i32; + uint16_t u16[2]; + int16_t i16[2]; + uint8_t u8[4]; + int8_t i8[4]; +} hb_var_num_t; + /* hb_tag_t */ @@ -476,6 +486,12 @@ * @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7 * @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7 * @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7 + * @HB_SCRIPT_CYPRO_MINOAN: `Cpmn`, Since: 3.0.0 + * @HB_SCRIPT_OLD_UYGHUR: `Ougr`, Since: 3.0.0 + * @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0 + * @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0 + * @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0 + * @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0 * @HB_SCRIPT_INVALID: No script set * * Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding @@ -683,6 +699,20 @@ HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), /*13.0*/ HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), /*13.0*/ + /* + * Since 3.0.0 + */ + HB_SCRIPT_CYPRO_MINOAN = HB_TAG ('C','p','m','n'), /*14.0*/ + HB_SCRIPT_OLD_UYGHUR = HB_TAG ('O','u','g','r'), /*14.0*/ + HB_SCRIPT_TANGSA = HB_TAG ('T','n','s','a'), /*14.0*/ + HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/ + HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/ + + /* + * Since 3.4.0 + */ + HB_SCRIPT_MATH = HB_TAG ('Z','m','t','h'), + /* No script set. */ HB_SCRIPT_INVALID = HB_TAG_NONE, diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-config.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-config.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-config.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-config.hh 2022-10-10 13:07:22.000000000 +0000 @@ -55,6 +55,7 @@ #define HB_NO_ATEXIT #define HB_NO_BUFFER_MESSAGE #define HB_NO_BUFFER_SERIALIZE +#define HB_NO_BUFFER_VERIFY #define HB_NO_BITMAP #define HB_NO_CFF #define HB_NO_COLOR @@ -63,6 +64,7 @@ #define HB_NO_FACE_COLLECT_UNICODES #define HB_NO_GETENV #define HB_NO_HINTING +#define HB_NO_LANGUAGE_LONG #define HB_NO_LANGUAGE_PRIVATE_SUBTAG #define HB_NO_LAYOUT_FEATURE_PARAMS #define HB_NO_LAYOUT_COLLECT_GLYPHS @@ -84,8 +86,15 @@ #ifdef HB_MINI #define HB_NO_AAT #define HB_NO_LEGACY +#define HB_NO_BORING_EXPANSION #endif +#if defined(HAVE_CONFIG_OVERRIDE_H) || defined(HB_CONFIG_OVERRIDE_H) +#ifndef HB_CONFIG_OVERRIDE_H +#define HB_CONFIG_OVERRIDE_H "config-override.h" +#endif +#include HB_CONFIG_OVERRIDE_H +#endif /* Closure of options. */ @@ -117,7 +126,7 @@ #define HB_NO_CMAP_LEGACY_SUBTABLES #define HB_NO_FALLBACK_SHAPE #define HB_NO_OT_KERN -#define HB_NO_OT_LAYOUT_BLACKLIST +#define HB_NO_OT_LAYOUT_BLOCKLIST #define HB_NO_OT_SHAPE_FALLBACK #endif @@ -137,10 +146,10 @@ #endif #ifdef HB_NO_OT_SHAPE_FALLBACK -#define HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK -#define HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK -#define HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK -#define HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS +#define HB_NO_OT_SHAPER_ARABIC_FALLBACK +#define HB_NO_OT_SHAPER_HEBREW_FALLBACK +#define HB_NO_OT_SHAPER_THAI_FALLBACK +#define HB_NO_OT_SHAPER_VOWEL_CONSTRAINTS #endif #ifdef NDEBUG @@ -155,8 +164,8 @@ #endif #endif -#ifdef HAVE_CONFIG_OVERRIDE_H -#include "config-override.h" +#ifdef HB_OPTIMIZE_SIZE +#define HB_NO_OT_LAYOUT_LOOKUP_CACHE #endif diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-cplusplus.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-cplusplus.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-cplusplus.hh 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-cplusplus.hh 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,192 @@ +/* + * Copyright © 2022 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_CPLUSPLUS_HH +#define HB_CPLUSPLUS_HH + +#include "hb.h" + +HB_BEGIN_DECLS +HB_END_DECLS + +#ifdef __cplusplus + +#include +#include + +#if 0 +#if !(__cplusplus >= 201103L) +#error "HarfBuzz C++ helpers require C++11" +#endif +#endif + +namespace hb { + + +template +struct vtable; + +template +struct shared_ptr +{ + using element_type = T; + + using v = vtable; + + explicit shared_ptr (T *p = nullptr) : p (p) {} + shared_ptr (const shared_ptr &o) : p (v::reference (o.p)) {} + shared_ptr (shared_ptr &&o) : p (o.p) { o.p = nullptr; } + shared_ptr& operator = (const shared_ptr &o) { if (p != o.p) { destroy (); p = o.p; reference (); } return *this; } + shared_ptr& operator = (shared_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; } + ~shared_ptr () { v::destroy (p); p = nullptr; } + + T* get() const { return p; } + + void swap (shared_ptr &o) { std::swap (p, o.p); } + friend void swap (shared_ptr &a, shared_ptr &b) { std::swap (a.p, b.p); } + + operator T * () const { return p; } + T& operator * () const { return *get (); } + T* operator -> () const { return get (); } + operator bool () { return p; } + bool operator == (const shared_ptr &o) { return p == o.p; } + bool operator != (const shared_ptr &o) { return p != o.p; } + + static T* get_empty() { return v::get_empty (); } + T* reference() { return v::reference (p); } + void destroy() { v::destroy (p); } + void set_user_data (hb_user_data_key_t *key, + void *value, + hb_destroy_func_t destroy, + hb_bool_t replace) { v::set_user_data (p, key, value, destroy, replace); } + void * get_user_data (hb_user_data_key_t *key) { return v::get_user_data (p, key); } + + private: + T *p; +}; + +template struct is_shared_ptr : std::false_type {}; +template struct is_shared_ptr> : std::true_type {}; + +template +struct unique_ptr +{ + using element_type = T; + + using v = vtable; + + explicit unique_ptr (T *p = nullptr) : p (p) {} + unique_ptr (const unique_ptr &o) = delete; + unique_ptr (unique_ptr &&o) : p (o.p) { o.p = nullptr; } + unique_ptr& operator = (const unique_ptr &o) = delete; + unique_ptr& operator = (unique_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; } + ~unique_ptr () { v::destroy (p); p = nullptr; } + + T* get() const { return p; } + T* release () { T* v = p; p = nullptr; return v; } + + void swap (unique_ptr &o) { std::swap (p, o.p); } + friend void swap (unique_ptr &a, unique_ptr &b) { std::swap (a.p, b.p); } + + operator T * () const { return p; } + T& operator * () const { return *get (); } + T* operator -> () const { return get (); } + operator bool () { return p; } + + private: + T *p; +}; + +template struct is_unique_ptr : std::false_type {}; +template struct is_unique_ptr> : std::true_type {}; + +template +struct vtable_t +{ + static constexpr auto get_empty = _get_empty; + static constexpr auto reference = _reference; + static constexpr auto destroy = _destroy; + static constexpr auto set_user_data = _set_user_data; + static constexpr auto get_user_data = _get_user_data; +}; + +#define HB_DEFINE_VTABLE(name) \ + template<> \ + struct vtable \ + : vtable_t {} + +HB_DEFINE_VTABLE (buffer); +HB_DEFINE_VTABLE (blob); +HB_DEFINE_VTABLE (face); +HB_DEFINE_VTABLE (font); +HB_DEFINE_VTABLE (font_funcs); +HB_DEFINE_VTABLE (map); +HB_DEFINE_VTABLE (set); +HB_DEFINE_VTABLE (shape_plan); +HB_DEFINE_VTABLE (unicode_funcs); + +#undef HB_DEFINE_VTABLE + + +} // namespace hb + +template +struct std::hash> +{ + std::size_t operator()(const hb::shared_ptr& v) const noexcept + { + std::size_t h = std::hash{}(v.get ()); + return h; + } +}; + +template +struct std::hash> +{ + std::size_t operator()(const hb::unique_ptr& v) const noexcept + { + std::size_t h = std::hash{}(v.get ()); + return h; + } +}; + + +#endif /* __cplusplus */ + +#endif /* HB_CPLUSPLUS_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-debug.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-debug.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-debug.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-debug.hh 2022-10-10 13:07:22.000000000 +0000 @@ -302,16 +302,16 @@ { if (unlikely (returned)) { fprintf (stderr, "OUCH, double calls to return_trace(). This is a bug, please report.\n"); - return hb_forward (v); + return std::forward (v); } _hb_debug_msg (what, obj, func, true, plevel ? *plevel : 1, -1, "return %s (line %d)", - hb_printer_t().print (v), line); + hb_printer_t>().print (v), line); if (plevel) --*plevel; plevel = nullptr; returned = true; - return hb_forward (v); + return std::forward (v); } private: @@ -333,7 +333,7 @@ template T ret (T&& v, const char *func HB_UNUSED = nullptr, - unsigned int line HB_UNUSED = 0) { return hb_forward (v); } + unsigned int line HB_UNUSED = 0) { return std::forward (v); } }; /* For disabled tracing; optimize out everything. @@ -343,7 +343,7 @@ template T ret (T&& v, const char *func HB_UNUSED = nullptr, - unsigned int line HB_UNUSED = 0) { return hb_forward (v); } + unsigned int line HB_UNUSED = 0) { return std::forward (v); } }; #define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__) @@ -438,6 +438,10 @@ #define TRACE_SUBSET(this) hb_no_trace_t trace #endif +#ifndef HB_DEBUG_SUBSET_REPACK +#define HB_DEBUG_SUBSET_REPACK (HB_DEBUG+0) +#endif + #ifndef HB_DEBUG_DISPATCH #define HB_DEBUG_DISPATCH ( \ HB_DEBUG_APPLY + \ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h 2022-10-10 13:07:22.000000000 +0000 @@ -107,9 +107,6 @@ hb_font_get_glyph_func_t func, void *user_data, hb_destroy_func_t destroy); -HB_EXTERN HB_DEPRECATED void -hb_set_invert (hb_set_t *set); - /** * hb_unicode_eastasian_width_func_t: * @ufuncs: A Unicode-functions structure diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-dispatch.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-dispatch.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-dispatch.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-dispatch.hh 2022-10-10 13:07:22.000000000 +0000 @@ -50,7 +50,7 @@ bool may_dispatch (const T *obj HB_UNUSED, const F *format HB_UNUSED) { return true; } template return_t dispatch (const T &obj, Ts&&... ds) - { return obj.dispatch (thiz (), hb_forward (ds)...); } + { return obj.dispatch (thiz (), std::forward (ds)...); } static return_t no_dispatch_return_value () { return Context::default_return_value (); } static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; } unsigned debug_depth = 0; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-draw.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-draw.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-draw.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-draw.cc 2022-10-10 13:07:22.000000000 +0000 @@ -25,237 +25,338 @@ #include "hb.hh" #ifndef HB_NO_DRAW -#ifdef HB_EXPERIMENTAL_API #include "hb-draw.hh" -#include "hb-ot.h" -#include "hb-ot-glyf-table.hh" -#include "hb-ot-cff1-table.hh" -#include "hb-ot-cff2-table.hh" /** - * hb_draw_funcs_set_move_to_func: - * @funcs: draw functions object - * @move_to: move-to callback + * SECTION:hb-draw + * @title: hb-draw + * @short_description: Glyph drawing + * @include: hb.h * - * Sets move-to callback to the draw functions object. - * - * Since: EXPERIMENTAL + * Functions for drawing (extracting) glyph shapes. **/ -void -hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs, - hb_draw_move_to_func_t move_to) -{ - if (unlikely (hb_object_is_immutable (funcs))) return; - funcs->move_to = move_to; + +static void +hb_draw_move_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED, + hb_draw_state_t *st HB_UNUSED, + float to_x HB_UNUSED, float to_y HB_UNUSED, + void *user_data HB_UNUSED) {} + +static void +hb_draw_line_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED, + hb_draw_state_t *st HB_UNUSED, + float to_x HB_UNUSED, float to_y HB_UNUSED, + void *user_data HB_UNUSED) {} + +static void +hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float control_x, float control_y, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ +#define HB_ONE_THIRD 0.33333333f + dfuncs->emit_cubic_to (draw_data, *st, + (st->current_x + 2.f * control_x) * HB_ONE_THIRD, + (st->current_y + 2.f * control_y) * HB_ONE_THIRD, + (to_x + 2.f * control_x) * HB_ONE_THIRD, + (to_y + 2.f * control_y) * HB_ONE_THIRD, + to_x, to_y); +#undef HB_ONE_THIRD } +static void +hb_draw_cubic_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED, + hb_draw_state_t *st HB_UNUSED, + float control1_x HB_UNUSED, float control1_y HB_UNUSED, + float control2_x HB_UNUSED, float control2_y HB_UNUSED, + float to_x HB_UNUSED, float to_y HB_UNUSED, + void *user_data HB_UNUSED) {} + +static void +hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED, + hb_draw_state_t *st HB_UNUSED, + void *user_data HB_UNUSED) {} + + +#define HB_DRAW_FUNC_IMPLEMENT(name) \ + \ +void \ +hb_draw_funcs_set_##name##_func (hb_draw_funcs_t *dfuncs, \ + hb_draw_##name##_func_t func, \ + void *user_data, \ + hb_destroy_func_t destroy) \ +{ \ + if (hb_object_is_immutable (dfuncs)) \ + return; \ + \ + if (dfuncs->destroy && dfuncs->destroy->name) \ + dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name); \ + \ + if (user_data && !dfuncs->user_data) \ + { \ + dfuncs->user_data = (decltype (dfuncs->user_data)) hb_calloc (1, sizeof (*dfuncs->user_data)); \ + if (unlikely (!dfuncs->user_data)) \ + goto fail; \ + } \ + if (destroy && !dfuncs->destroy) \ + { \ + dfuncs->destroy = (decltype (dfuncs->destroy)) hb_calloc (1, sizeof (*dfuncs->destroy)); \ + if (unlikely (!dfuncs->destroy)) \ + goto fail; \ + } \ + \ + if (func) { \ + dfuncs->func.name = func; \ + if (dfuncs->user_data) \ + dfuncs->user_data->name = user_data; \ + if (dfuncs->destroy) \ + dfuncs->destroy->name = destroy; \ + } else { \ + dfuncs->func.name = hb_draw_##name##_nil; \ + if (dfuncs->user_data) \ + dfuncs->user_data->name = nullptr; \ + if (dfuncs->destroy) \ + dfuncs->destroy->name = nullptr; \ + } \ + \ +fail: \ + if (destroy) \ + destroy (user_data); \ +} + +HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_DRAW_FUNC_IMPLEMENT + /** - * hb_draw_funcs_set_line_to_func: - * @funcs: draw functions object - * @line_to: line-to callback + * hb_draw_funcs_create: + * + * Creates a new draw callbacks object. * - * Sets line-to callback to the draw functions object. + * Return value: (transfer full): + * A newly allocated #hb_draw_funcs_t with a reference count of 1. The initial + * reference count should be released with hb_draw_funcs_destroy when you are + * done using the #hb_draw_funcs_t. This function never returns %NULL. If + * memory cannot be allocated, a special singleton #hb_draw_funcs_t object will + * be returned. * - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ -void -hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs, - hb_draw_line_to_func_t line_to) +hb_draw_funcs_t * +hb_draw_funcs_create () { - if (unlikely (hb_object_is_immutable (funcs))) return; - funcs->line_to = line_to; + hb_draw_funcs_t *dfuncs; + if (unlikely (!(dfuncs = hb_object_create ()))) + return const_cast (&Null (hb_draw_funcs_t)); + + dfuncs->func = Null (hb_draw_funcs_t).func; + + return dfuncs; } +DEFINE_NULL_INSTANCE (hb_draw_funcs_t) = +{ + HB_OBJECT_HEADER_STATIC, + + { +#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_nil, + HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_DRAW_FUNC_IMPLEMENT + } +}; + + /** - * hb_draw_funcs_set_quadratic_to_func: - * @funcs: draw functions object - * @move_to: quadratic-to callback + * hb_draw_funcs_reference: (skip) + * @dfuncs: draw functions * - * Sets quadratic-to callback to the draw functions object. + * Increases the reference count on @dfuncs by one. This prevents @buffer from + * being destroyed until a matching call to hb_draw_funcs_destroy() is made. * - * Since: EXPERIMENTAL + * Return value: (transfer full): + * The referenced #hb_draw_funcs_t. + * + * Since: 4.0.0 **/ -void -hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs, - hb_draw_quadratic_to_func_t quadratic_to) +hb_draw_funcs_t * +hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs) { - if (unlikely (hb_object_is_immutable (funcs))) return; - funcs->quadratic_to = quadratic_to; - funcs->is_quadratic_to_set = true; + return hb_object_reference (dfuncs); } /** - * hb_draw_funcs_set_cubic_to_func: - * @funcs: draw functions - * @cubic_to: cubic-to callback + * hb_draw_funcs_destroy: (skip) + * @dfuncs: draw functions * - * Sets cubic-to callback to the draw functions object. + * Deallocate the @dfuncs. + * Decreases the reference count on @dfuncs by one. If the result is zero, then + * @dfuncs and all associated resources are freed. See hb_draw_funcs_reference(). * - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ void -hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs, - hb_draw_cubic_to_func_t cubic_to) +hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs) { - if (unlikely (hb_object_is_immutable (funcs))) return; - funcs->cubic_to = cubic_to; + if (!hb_object_destroy (dfuncs)) return; + + if (dfuncs->destroy) + { +#define HB_DRAW_FUNC_IMPLEMENT(name) \ + if (dfuncs->destroy->name) dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name); + HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_DRAW_FUNC_IMPLEMENT + } + + hb_free (dfuncs); } /** - * hb_draw_funcs_set_close_path_func: - * @funcs: draw functions object - * @close_path: close-path callback + * hb_draw_funcs_make_immutable: + * @dfuncs: draw functions * - * Sets close-path callback to the draw functions object. + * Makes @dfuncs object immutable. * - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ void -hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs, - hb_draw_close_path_func_t close_path) +hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs) { - if (unlikely (hb_object_is_immutable (funcs))) return; - funcs->close_path = close_path; -} - -static void -_move_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {} - -static void -_line_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {} - -static void -_quadratic_to_nil (hb_position_t control_x HB_UNUSED, hb_position_t control_y HB_UNUSED, - hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, - void *user_data HB_UNUSED) {} - -static void -_cubic_to_nil (hb_position_t control1_x HB_UNUSED, hb_position_t control1_y HB_UNUSED, - hb_position_t control2_x HB_UNUSED, hb_position_t control2_y HB_UNUSED, - hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, - void *user_data HB_UNUSED) {} + if (hb_object_is_immutable (dfuncs)) + return; -static void -_close_path_nil (void *user_data HB_UNUSED) {} + hb_object_make_immutable (dfuncs); +} /** - * hb_draw_funcs_create: + * hb_draw_funcs_is_immutable: + * @dfuncs: draw functions * - * Creates a new draw callbacks object. + * Checks whether @dfuncs is immutable. * - * Since: EXPERIMENTAL + * Return value: %true if @dfuncs is immutable, %false otherwise + * + * Since: 4.0.0 **/ -hb_draw_funcs_t * -hb_draw_funcs_create () +hb_bool_t +hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs) { - hb_draw_funcs_t *funcs; - if (unlikely (!(funcs = hb_object_create ()))) - return const_cast (&Null (hb_draw_funcs_t)); - - funcs->move_to = (hb_draw_move_to_func_t) _move_to_nil; - funcs->line_to = (hb_draw_line_to_func_t) _line_to_nil; - funcs->quadratic_to = (hb_draw_quadratic_to_func_t) _quadratic_to_nil; - funcs->is_quadratic_to_set = false; - funcs->cubic_to = (hb_draw_cubic_to_func_t) _cubic_to_nil; - funcs->close_path = (hb_draw_close_path_func_t) _close_path_nil; - return funcs; + return hb_object_is_immutable (dfuncs); } + /** - * hb_draw_funcs_reference: - * @funcs: draw functions + * hb_draw_move_to: + * @dfuncs: draw functions + * @draw_data: associated draw data passed by the caller + * @st: current draw state + * @to_x: X component of target point + * @to_y: Y component of target point * - * Add to callbacks object refcount. + * Perform a "move-to" draw operation. * - * Returns: The same object. - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ -hb_draw_funcs_t * -hb_draw_funcs_reference (hb_draw_funcs_t *funcs) +void +hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y) { - return hb_object_reference (funcs); + dfuncs->move_to (draw_data, *st, + to_x, to_y); } /** - * hb_draw_funcs_destroy: - * @funcs: draw functions + * hb_draw_line_to: + * @dfuncs: draw functions + * @draw_data: associated draw data passed by the caller + * @st: current draw state + * @to_x: X component of target point + * @to_y: Y component of target point * - * Decreases refcount of callbacks object and deletes the object if it reaches - * to zero. + * Perform a "line-to" draw operation. * - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ void -hb_draw_funcs_destroy (hb_draw_funcs_t *funcs) +hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y) { - if (!hb_object_destroy (funcs)) return; - - free (funcs); + dfuncs->line_to (draw_data, *st, + to_x, to_y); } /** - * hb_draw_funcs_make_immutable: - * @funcs: draw functions + * hb_draw_quadratic_to: + * @dfuncs: draw functions + * @draw_data: associated draw data passed by the caller + * @st: current draw state + * @control_x: X component of control point + * @control_y: Y component of control point + * @to_x: X component of target point + * @to_y: Y component of target point * - * Makes funcs object immutable. + * Perform a "quadratic-to" draw operation. * - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ void -hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs) -{ - if (hb_object_is_immutable (funcs)) - return; - - hb_object_make_immutable (funcs); +hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float control_x, float control_y, + float to_x, float to_y) +{ + dfuncs->quadratic_to (draw_data, *st, + control_x, control_y, + to_x, to_y); } /** - * hb_draw_funcs_is_immutable: - * @funcs: draw functions + * hb_draw_cubic_to: + * @dfuncs: draw functions + * @draw_data: associated draw data passed by the caller + * @st: current draw state + * @control1_x: X component of first control point + * @control1_y: Y component of first control point + * @control2_x: X component of second control point + * @control2_y: Y component of second control point + * @to_x: X component of target point + * @to_y: Y component of target point * - * Checks whether funcs is immutable. + * Perform a "cubic-to" draw operation. * - * Returns: If is immutable. - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ -hb_bool_t -hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs) +void +hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y) { - return hb_object_is_immutable (funcs); + dfuncs->cubic_to (draw_data, *st, + control1_x, control1_y, + control2_x, control2_y, + to_x, to_y); } /** - * hb_font_draw_glyph: - * @font: a font object - * @glyph: a glyph id - * @funcs: draw callbacks object - * @user_data: parameter you like be passed to the callbacks when are called + * hb_draw_close_path: + * @dfuncs: draw functions + * @draw_data: associated draw data passed by the caller + * @st: current draw state * - * Draw a glyph. + * Perform a "close-path" draw operation. * - * Returns: Whether the font had the glyph and the operation completed successfully. - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ -hb_bool_t -hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph, - const hb_draw_funcs_t *funcs, - void *user_data) -{ - if (unlikely (funcs == &Null (hb_draw_funcs_t) || - glyph >= font->face->get_num_glyphs ())) - return false; - - draw_helper_t draw_helper (funcs, user_data); - if (font->face->table.glyf->get_path (font, glyph, draw_helper)) return true; -#ifndef HB_NO_CFF - if (font->face->table.cff1->get_path (font, glyph, draw_helper)) return true; - if (font->face->table.cff2->get_path (font, glyph, draw_helper)) return true; -#endif - - return false; +void +hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st) +{ + dfuncs->close_path (draw_data, *st); } -#endif + #endif diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-draw.h openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-draw.h --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-draw.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-draw.h 2022-10-10 13:07:22.000000000 +0000 @@ -33,65 +33,292 @@ HB_BEGIN_DECLS -#ifdef HB_EXPERIMENTAL_API -typedef void (*hb_draw_move_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data); -typedef void (*hb_draw_line_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data); -typedef void (*hb_draw_quadratic_to_func_t) (hb_position_t control_x, hb_position_t control_y, - hb_position_t to_x, hb_position_t to_y, - void *user_data); -typedef void (*hb_draw_cubic_to_func_t) (hb_position_t control1_x, hb_position_t control1_y, - hb_position_t control2_x, hb_position_t control2_y, - hb_position_t to_x, hb_position_t to_y, - void *user_data); -typedef void (*hb_draw_close_path_func_t) (void *user_data); + +/** + * hb_draw_state_t + * @path_open: Whether there is an open path + * @path_start_x: X component of the start of current path + * @path_start_y: Y component of the start of current path + * @current_x: X component of current point + * @current_y: Y component of current point + * + * Current drawing state. + * + * Since: 4.0.0 + **/ +typedef struct hb_draw_state_t { + hb_bool_t path_open; + + float path_start_x; + float path_start_y; + + float current_x; + float current_y; + + /*< private >*/ + hb_var_num_t reserved1; + hb_var_num_t reserved2; + hb_var_num_t reserved3; + hb_var_num_t reserved4; + hb_var_num_t reserved5; + hb_var_num_t reserved6; + hb_var_num_t reserved7; +} hb_draw_state_t; + +/** + * HB_DRAW_STATE_DEFAULT: + * + * The default #hb_draw_state_t at the start of glyph drawing. + */ +#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}} + /** * hb_draw_funcs_t: * * Glyph draw callbacks. * - * _move_to, _line_to and _cubic_to calls are nessecary to be defined but we - * translate _quadratic_to calls to _cubic_to if the callback isn't defined. + * #hb_draw_move_to_func_t, #hb_draw_line_to_func_t and + * #hb_draw_cubic_to_func_t calls are necessary to be defined but we translate + * #hb_draw_quadratic_to_func_t calls to #hb_draw_cubic_to_func_t if the + * callback isn't defined. * - * Since: EXPERIMENTAL + * Since: 4.0.0 **/ + typedef struct hb_draw_funcs_t hb_draw_funcs_t; + +/** + * hb_draw_move_to_func_t: + * @dfuncs: draw functions object + * @draw_data: The data accompanying the draw functions + * @st: current draw state + * @to_x: X component of target point + * @to_y: Y component of target point + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_draw_funcs_t to perform a "move-to" draw + * operation. + * + * Since: 4.0.0 + * + **/ +typedef void (*hb_draw_move_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y, + void *user_data); + +/** + * hb_draw_line_to_func_t: + * @dfuncs: draw functions object + * @draw_data: The data accompanying the draw functions + * @st: current draw state + * @to_x: X component of target point + * @to_y: Y component of target point + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_draw_funcs_t to perform a "line-to" draw + * operation. + * + * Since: 4.0.0 + * + **/ +typedef void (*hb_draw_line_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y, + void *user_data); + +/** + * hb_draw_quadratic_to_func_t: + * @dfuncs: draw functions object + * @draw_data: The data accompanying the draw functions + * @st: current draw state + * @control_x: X component of control point + * @control_y: Y component of control point + * @to_x: X component of target point + * @to_y: Y component of target point + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_draw_funcs_t to perform a "quadratic-to" draw + * operation. + * + * Since: 4.0.0 + * + **/ +typedef void (*hb_draw_quadratic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float control_x, float control_y, + float to_x, float to_y, + void *user_data); + +/** + * hb_draw_cubic_to_func_t: + * @dfuncs: draw functions object + * @draw_data: The data accompanying the draw functions + * @st: current draw state + * @control1_x: X component of first control point + * @control1_y: Y component of first control point + * @control2_x: X component of second control point + * @control2_y: Y component of second control point + * @to_x: X component of target point + * @to_y: Y component of target point + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_draw_funcs_t to perform a "cubic-to" draw + * operation. + * + * Since: 4.0.0 + * + **/ +typedef void (*hb_draw_cubic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y, + void *user_data); + +/** + * hb_draw_close_path_func_t: + * @dfuncs: draw functions object + * @draw_data: The data accompanying the draw functions + * @st: current draw state + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_draw_funcs_t to perform a "close-path" draw + * operation. + * + * Since: 4.0.0 + * + **/ +typedef void (*hb_draw_close_path_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + void *user_data); + +/** + * hb_draw_funcs_set_move_to_func: + * @dfuncs: draw functions object + * @func: (closure user_data) (destroy destroy) (scope notified): move-to callback + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets move-to callback to the draw functions object. + * + * Since: 4.0.0 + **/ HB_EXTERN void -hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs, - hb_draw_move_to_func_t move_to); +hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *dfuncs, + hb_draw_move_to_func_t func, + void *user_data, hb_destroy_func_t destroy); +/** + * hb_draw_funcs_set_line_to_func: + * @dfuncs: draw functions object + * @func: (closure user_data) (destroy destroy) (scope notified): line-to callback + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets line-to callback to the draw functions object. + * + * Since: 4.0.0 + **/ HB_EXTERN void -hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs, - hb_draw_line_to_func_t line_to); +hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *dfuncs, + hb_draw_line_to_func_t func, + void *user_data, hb_destroy_func_t destroy); +/** + * hb_draw_funcs_set_quadratic_to_func: + * @dfuncs: draw functions object + * @func: (closure user_data) (destroy destroy) (scope notified): quadratic-to callback + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets quadratic-to callback to the draw functions object. + * + * Since: 4.0.0 + **/ HB_EXTERN void -hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs, - hb_draw_quadratic_to_func_t quadratic_to); +hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *dfuncs, + hb_draw_quadratic_to_func_t func, + void *user_data, hb_destroy_func_t destroy); +/** + * hb_draw_funcs_set_cubic_to_func: + * @dfuncs: draw functions + * @func: (closure user_data) (destroy destroy) (scope notified): cubic-to callback + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets cubic-to callback to the draw functions object. + * + * Since: 4.0.0 + **/ HB_EXTERN void -hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs, - hb_draw_cubic_to_func_t cubic_to); +hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *dfuncs, + hb_draw_cubic_to_func_t func, + void *user_data, hb_destroy_func_t destroy); +/** + * hb_draw_funcs_set_close_path_func: + * @dfuncs: draw functions object + * @func: (closure user_data) (destroy destroy) (scope notified): close-path callback + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets close-path callback to the draw functions object. + * + * Since: 4.0.0 + **/ HB_EXTERN void -hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs, - hb_draw_close_path_func_t close_path); +hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *dfuncs, + hb_draw_close_path_func_t func, + void *user_data, hb_destroy_func_t destroy); + HB_EXTERN hb_draw_funcs_t * hb_draw_funcs_create (void); HB_EXTERN hb_draw_funcs_t * -hb_draw_funcs_reference (hb_draw_funcs_t *funcs); +hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs); HB_EXTERN void -hb_draw_funcs_destroy (hb_draw_funcs_t *funcs); +hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs); HB_EXTERN void -hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs); +hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs); HB_EXTERN hb_bool_t -hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs); -#endif +hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs); + + +HB_EXTERN void +hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y); + +HB_EXTERN void +hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y); + +HB_EXTERN void +hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float control_x, float control_y, + float to_x, float to_y); + +HB_EXTERN void +hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y); + +HB_EXTERN void +hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data, + hb_draw_state_t *st); + HB_END_DECLS diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-draw.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-draw.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-draw.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-draw.hh 2022-10-10 13:07:22.000000000 +0000 @@ -27,113 +27,205 @@ #include "hb.hh" -#ifdef HB_EXPERIMENTAL_API -struct hb_draw_funcs_t -{ - hb_object_header_t header; - hb_draw_move_to_func_t move_to; - hb_draw_line_to_func_t line_to; - hb_draw_quadratic_to_func_t quadratic_to; - bool is_quadratic_to_set; - hb_draw_cubic_to_func_t cubic_to; - hb_draw_close_path_func_t close_path; -}; +/* + * hb_draw_funcs_t + */ + +#define HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS \ + HB_DRAW_FUNC_IMPLEMENT (move_to) \ + HB_DRAW_FUNC_IMPLEMENT (line_to) \ + HB_DRAW_FUNC_IMPLEMENT (quadratic_to) \ + HB_DRAW_FUNC_IMPLEMENT (cubic_to) \ + HB_DRAW_FUNC_IMPLEMENT (close_path) \ + /* ^--- Add new callbacks here */ -struct draw_helper_t +struct hb_draw_funcs_t { - draw_helper_t (const hb_draw_funcs_t *funcs_, void *user_data_) - { - funcs = funcs_; - user_data = user_data_; - path_open = false; - path_start_x = current_x = path_start_y = current_y = 0; - } - ~draw_helper_t () { end_path (); } - - void move_to (hb_position_t x, hb_position_t y) - { - if (path_open) end_path (); - current_x = path_start_x = x; - current_y = path_start_y = y; - } + hb_object_header_t header; - void line_to (hb_position_t x, hb_position_t y) - { - if (equal_to_current (x, y)) return; - if (!path_open) start_path (); - funcs->line_to (x, y, user_data); - current_x = x; - current_y = y; + struct { +#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_func_t name; + HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_DRAW_FUNC_IMPLEMENT + } func; + + struct { +#define HB_DRAW_FUNC_IMPLEMENT(name) void *name; + HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_DRAW_FUNC_IMPLEMENT + } *user_data; + + struct { +#define HB_DRAW_FUNC_IMPLEMENT(name) hb_destroy_func_t name; + HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_DRAW_FUNC_IMPLEMENT + } *destroy; + + void emit_move_to (void *draw_data, hb_draw_state_t &st, + float to_x, float to_y) + { func.move_to (this, draw_data, &st, + to_x, to_y, + !user_data ? nullptr : user_data->move_to); } + void emit_line_to (void *draw_data, hb_draw_state_t &st, + float to_x, float to_y) + { func.line_to (this, draw_data, &st, + to_x, to_y, + !user_data ? nullptr : user_data->line_to); } + void emit_quadratic_to (void *draw_data, hb_draw_state_t &st, + float control_x, float control_y, + float to_x, float to_y) + { func.quadratic_to (this, draw_data, &st, + control_x, control_y, + to_x, to_y, + !user_data ? nullptr : user_data->quadratic_to); } + void emit_cubic_to (void *draw_data, hb_draw_state_t &st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y) + { func.cubic_to (this, draw_data, &st, + control1_x, control1_y, + control2_x, control2_y, + to_x, to_y, + !user_data ? nullptr : user_data->cubic_to); } + void emit_close_path (void *draw_data, hb_draw_state_t &st) + { func.close_path (this, draw_data, &st, + !user_data ? nullptr : user_data->close_path); } + + + void move_to (void *draw_data, hb_draw_state_t &st, + float to_x, float to_y) + { + if (st.path_open) close_path (draw_data, st); + st.current_x = to_x; + st.current_y = to_y; + } + + void line_to (void *draw_data, hb_draw_state_t &st, + float to_x, float to_y) + { + if (!st.path_open) start_path (draw_data, st); + emit_line_to (draw_data, st, to_x, to_y); + st.current_x = to_x; + st.current_y = to_y; } void - quadratic_to (hb_position_t control_x, hb_position_t control_y, - hb_position_t to_x, hb_position_t to_y) - { - if (equal_to_current (control_x, control_y) && equal_to_current (to_x, to_y)) - return; - if (!path_open) start_path (); - if (funcs->is_quadratic_to_set) - funcs->quadratic_to (control_x, control_y, to_x, to_y, user_data); - else - funcs->cubic_to (roundf ((current_x + 2.f * control_x) / 3.f), - roundf ((current_y + 2.f * control_y) / 3.f), - roundf ((to_x + 2.f * control_x) / 3.f), - roundf ((to_y + 2.f * control_y) / 3.f), - to_x, to_y, user_data); - current_x = to_x; - current_y = to_y; + quadratic_to (void *draw_data, hb_draw_state_t &st, + float control_x, float control_y, + float to_x, float to_y) + { + if (!st.path_open) start_path (draw_data, st); + emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y); + st.current_x = to_x; + st.current_y = to_y; } void - cubic_to (hb_position_t control1_x, hb_position_t control1_y, - hb_position_t control2_x, hb_position_t control2_y, - hb_position_t to_x, hb_position_t to_y) - { - if (equal_to_current (control1_x, control1_y) && - equal_to_current (control2_x, control2_y) && - equal_to_current (to_x, to_y)) - return; - if (!path_open) start_path (); - funcs->cubic_to (control1_x, control1_y, control2_x, control2_y, to_x, to_y, user_data); - current_x = to_x; - current_y = to_y; + cubic_to (void *draw_data, hb_draw_state_t &st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y) + { + if (!st.path_open) start_path (draw_data, st); + emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y); + st.current_x = to_x; + st.current_y = to_y; } - void end_path () + void + close_path (void *draw_data, hb_draw_state_t &st) { - if (path_open) + if (st.path_open) { - if ((path_start_x != current_x) || (path_start_y != current_y)) - funcs->line_to (path_start_x, path_start_y, user_data); - funcs->close_path (user_data); + if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y)) + emit_line_to (draw_data, st, st.path_start_x, st.path_start_y); + emit_close_path (draw_data, st); } - path_open = false; - path_start_x = current_x = path_start_y = current_y = 0; + st.path_open = false; + st.path_start_x = st.current_x = st.path_start_y = st.current_y = 0; } protected: - bool equal_to_current (hb_position_t x, hb_position_t y) - { return current_x == x && current_y == y; } - void start_path () + void start_path (void *draw_data, hb_draw_state_t &st) { - if (path_open) end_path (); - path_open = true; - funcs->move_to (path_start_x, path_start_y, user_data); + assert (!st.path_open); + emit_move_to (draw_data, st, st.current_x, st.current_y); + st.path_open = true; + st.path_start_x = st.current_x; + st.path_start_y = st.current_y; } +}; +DECLARE_NULL_INSTANCE (hb_draw_funcs_t); - hb_position_t path_start_x; - hb_position_t path_start_y; - - hb_position_t current_x; - hb_position_t current_y; +struct hb_draw_session_t +{ + hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_ = 0.f) + : slant {slant_}, not_slanted {slant == 0.f}, + funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT + {} + + ~hb_draw_session_t () { close_path (); } + + void move_to (float to_x, float to_y) + { + if (likely (not_slanted)) + funcs->move_to (draw_data, st, + to_x, to_y); + else + funcs->move_to (draw_data, st, + to_x + to_y * slant, to_y); + } + void line_to (float to_x, float to_y) + { + if (likely (not_slanted)) + funcs->line_to (draw_data, st, + to_x, to_y); + else + funcs->line_to (draw_data, st, + to_x + to_y * slant, to_y); + } + void + quadratic_to (float control_x, float control_y, + float to_x, float to_y) + { + if (likely (not_slanted)) + funcs->quadratic_to (draw_data, st, + control_x, control_y, + to_x, to_y); + else + funcs->quadratic_to (draw_data, st, + control_x + control_y * slant, control_y, + to_x + to_y * slant, to_y); + } + void + cubic_to (float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y) + { + if (likely (not_slanted)) + funcs->cubic_to (draw_data, st, + control1_x, control1_y, + control2_x, control2_y, + to_x, to_y); + else + funcs->cubic_to (draw_data, st, + control1_x + control1_y * slant, control1_y, + control2_x + control2_y * slant, control2_y, + to_x + to_y * slant, to_y); + } + void close_path () + { + funcs->close_path (draw_data, st); + } - bool path_open; - const hb_draw_funcs_t *funcs; - void *user_data; + protected: + float slant; + bool not_slanted; + hb_draw_funcs_t *funcs; + void *draw_data; + hb_draw_state_t st; }; -#endif #endif /* HB_DRAW_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-face.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-face.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-face.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-face.cc 2022-10-10 13:07:22.000000000 +0000 @@ -33,6 +33,7 @@ #include "hb-open-file.hh" #include "hb-ot-face.hh" #include "hb-ot-cmap-table.hh" +#include "hb-map.hh" /** @@ -142,7 +143,7 @@ typedef struct hb_face_for_data_closure_t { hb_blob_t *blob; - unsigned int index; + uint16_t index; } hb_face_for_data_closure_t; static hb_face_for_data_closure_t * @@ -150,12 +151,12 @@ { hb_face_for_data_closure_t *closure; - closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t)); + closure = (hb_face_for_data_closure_t *) hb_calloc (1, sizeof (hb_face_for_data_closure_t)); if (unlikely (!closure)) return nullptr; closure->blob = blob; - closure->index = index; + closure->index = (uint16_t) (index & 0xFFFFu); return closure; } @@ -166,7 +167,7 @@ hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data; hb_blob_destroy (closure->blob); - free (closure); + hb_free (closure); } static hb_blob_t * @@ -189,14 +190,24 @@ } /** - * hb_face_create: (Xconstructor) + * hb_face_create: * @blob: #hb_blob_t to work upon * @index: The index of the face within @blob * * Constructs a new face object from the specified blob and - * a face index into that blob. This is used for blobs of - * file formats such as Dfont and TTC that can contain more - * than one face. + * a face index into that blob. + * + * The face index is used for blobs of file formats such as TTC and + * and DFont that can contain more than one face. Face indices within + * such collections are zero-based. + * + * Note: If the blob font format is not a collection, @index + * is ignored. Otherwise, only the lower 16-bits of @index are used. + * The unmodified @index can be accessed via hb_face_get_index(). + * + * Note: The high 16-bits of @index, if non-zero, are used by + * hb_font_create() to load named-instances in variable fonts. See + * hb_font_create() for details. * * Return value: (transfer full): The new face object * @@ -281,7 +292,7 @@ { hb_face_t::plan_node_t *next = node->next; hb_shape_plan_destroy (node->shape_plan); - free (node); + hb_free (node); node = next; } @@ -291,7 +302,7 @@ if (face->destroy) face->destroy (face->user_data); - free (face); + hb_free (face); } /** @@ -331,7 +342,7 @@ * Since: 0.9.2 **/ void * -hb_face_get_user_data (const hb_face_t *face, +hb_face_get_user_data (hb_face_t *face, hb_user_data_key_t *key) { return hb_object_get_user_data (face, key); @@ -419,7 +430,8 @@ * Assigns the specified face-index to @face. Fails if the * face is immutable. * - * Note: face indices within a collection are zero-based. + * Note: changing the index has no effect on the face itself + * This only changes the value returned by hb_face_get_index(). * * Since: 0.9.2 **/ @@ -623,26 +635,26 @@ struct hb_face_builder_data_t { - struct table_entry_t - { - int cmp (hb_tag_t t) const - { - if (t < tag) return -1; - if (t > tag) return -1; - return 0; - } - - hb_tag_t tag; - hb_blob_t *blob; - }; - - hb_vector_t tables; + hb_hashmap_t tables; }; +static int compare_entries (const void* pa, const void* pb) +{ + const auto& a = * (const hb_pair_t *) pa; + const auto& b = * (const hb_pair_t *) pb; + + /* Order by blob size first (smallest to largest) and then table tag */ + + if (a.second->length != b.second->length) + return a.second->length < b.second->length ? -1 : +1; + + return a.first < b.first ? -1 : a.first == b.first ? 0 : +1; +} + static hb_face_builder_data_t * _hb_face_builder_data_create () { - hb_face_builder_data_t *data = (hb_face_builder_data_t *) calloc (1, sizeof (hb_face_builder_data_t)); + hb_face_builder_data_t *data = (hb_face_builder_data_t *) hb_calloc (1, sizeof (hb_face_builder_data_t)); if (unlikely (!data)) return nullptr; @@ -656,25 +668,25 @@ { hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data; - for (unsigned int i = 0; i < data->tables.length; i++) - hb_blob_destroy (data->tables[i].blob); + for (hb_blob_t* b : data->tables.values()) + hb_blob_destroy (b); data->tables.fini (); - free (data); + hb_free (data); } static hb_blob_t * _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data) { - unsigned int table_count = data->tables.length; + unsigned int table_count = data->tables.get_population (); unsigned int face_length = table_count * 16 + 12; - for (unsigned int i = 0; i < table_count; i++) - face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables[i].blob)); + for (hb_blob_t* b : data->tables.values()) + face_length += hb_ceil_to_4 (hb_blob_get_length (b)); - char *buf = (char *) malloc (face_length); + char *buf = (char *) hb_malloc (face_length); if (unlikely (!buf)) return nullptr; @@ -682,20 +694,31 @@ c.propagate_error (data->tables); OT::OpenTypeFontFile *f = c.start_serialize (); - bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2')); + bool is_cff = (data->tables.has (HB_TAG ('C','F','F',' ')) + || data->tables.has (HB_TAG ('C','F','F','2'))); hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag; - bool ret = f->serialize_single (&c, sfnt_tag, data->tables.as_array ()); + // Sort the tags so that produced face is deterministic. + hb_vector_t> sorted_entries; + data->tables.iter () | hb_sink (sorted_entries); + if (unlikely (sorted_entries.in_error ())) + { + hb_free (buf); + return nullptr; + } + + sorted_entries.qsort (compare_entries); + bool ret = f->serialize_single (&c, sfnt_tag, + sorted_entries.iter()); c.end_serialize (); if (unlikely (!ret)) { - free (buf); + hb_free (buf); return nullptr; } - return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free); + return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, hb_free); } static hb_blob_t * @@ -706,11 +729,7 @@ if (!tag) return _hb_face_builder_data_reference_blob (data); - hb_face_builder_data_t::table_entry_t *entry = data->tables.lsearch (tag); - if (entry) - return hb_blob_reference (entry->blob); - - return nullptr; + return hb_blob_reference (data->tables[tag]); } @@ -750,17 +769,21 @@ hb_bool_t hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob) { + if (tag == HB_MAP_VALUE_INVALID) + return false; + if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy)) return false; hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data; - hb_face_builder_data_t::table_entry_t *entry = data->tables.push (); - if (unlikely (data->tables.in_error())) + hb_blob_t* previous = data->tables.get (tag); + if (!data->tables.set (tag, hb_blob_reference (blob))) + { + hb_blob_destroy (blob); return false; + } - entry->tag = tag; - entry->blob = hb_blob_reference (blob); - + hb_blob_destroy (previous); return true; } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-face.h openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-face.h --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-face.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-face.h 2022-10-10 13:07:22.000000000 +0000 @@ -96,7 +96,7 @@ hb_bool_t replace); HB_EXTERN void * -hb_face_get_user_data (const hb_face_t *face, +hb_face_get_user_data (hb_face_t *face, hb_user_data_key_t *key); HB_EXTERN void diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-fallback-shape.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-fallback-shape.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-fallback-shape.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-fallback-shape.cc 2022-10-10 13:07:22.000000000 +0000 @@ -117,7 +117,7 @@ if (HB_DIRECTION_IS_BACKWARD (direction)) hb_buffer_reverse (buffer); - buffer->safe_to_break_all (); + buffer->clear_glyph_flags (); return true; } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-font.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-font.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-font.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-font.cc 2022-10-10 13:07:22.000000000 +0000 @@ -29,6 +29,7 @@ #include "hb.hh" #include "hb-font.hh" +#include "hb-draw.hh" #include "hb-machinery.hh" #include "hb-ot.h" @@ -501,20 +502,142 @@ return font->parent->get_glyph_from_name (name, len, glyph); } -DEFINE_NULL_INSTANCE (hb_font_funcs_t) = +static void +hb_font_get_glyph_shape_nil (hb_font_t *font HB_UNUSED, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, + void *draw_data, + void *user_data HB_UNUSED) +{ +} + + +typedef struct hb_font_get_glyph_shape_default_adaptor_t { + hb_draw_funcs_t *draw_funcs; + void *draw_data; + float x_scale; + float y_scale; +} hb_font_get_glyph_shape_default_adaptor_t; + +static void +hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, + void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data; + float x_scale = adaptor->x_scale; + float y_scale = adaptor->y_scale; + + adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st, + x_scale * to_x, y_scale * to_y); +} + +static void +hb_draw_line_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data, + hb_draw_state_t *st, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data; + float x_scale = adaptor->x_scale; + float y_scale = adaptor->y_scale; + + st->current_x *= x_scale; + st->current_y *= y_scale; + + adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st, + x_scale * to_x, y_scale * to_y); +} + +static void +hb_draw_quadratic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data, + hb_draw_state_t *st, + float control_x, float control_y, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data; + float x_scale = adaptor->x_scale; + float y_scale = adaptor->y_scale; + + st->current_x *= x_scale; + st->current_y *= y_scale; + + adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st, + x_scale * control_x, y_scale * control_y, + x_scale * to_x, y_scale * to_y); +} + +static void +hb_draw_cubic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data, + hb_draw_state_t *st, + float control1_x, float control1_y, + float control2_x, float control2_y, + float to_x, float to_y, + void *user_data HB_UNUSED) +{ + hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data; + float x_scale = adaptor->x_scale; + float y_scale = adaptor->y_scale; + + st->current_x *= x_scale; + st->current_y *= y_scale; + + adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st, + x_scale * control1_x, y_scale * control1_y, + x_scale * control2_x, y_scale * control2_y, + x_scale * to_x, y_scale * to_y); +} + +static void +hb_draw_close_path_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data, + hb_draw_state_t *st, + void *user_data HB_UNUSED) { + hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data; + + adaptor->draw_funcs->emit_close_path (adaptor->draw_data, *st); +} + +static const hb_draw_funcs_t _hb_draw_funcs_default = { HB_OBJECT_HEADER_STATIC, { -#define HB_FONT_FUNC_IMPLEMENT(name) nullptr, - HB_FONT_FUNCS_IMPLEMENT_CALLBACKS -#undef HB_FONT_FUNC_IMPLEMENT - }, - { -#define HB_FONT_FUNC_IMPLEMENT(name) nullptr, - HB_FONT_FUNCS_IMPLEMENT_CALLBACKS -#undef HB_FONT_FUNC_IMPLEMENT - }, +#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_default, + HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_DRAW_FUNC_IMPLEMENT + } +}; + +static void +hb_font_get_glyph_shape_default (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, + void *draw_data, + void *user_data HB_UNUSED) +{ + hb_font_get_glyph_shape_default_adaptor_t adaptor = { + draw_funcs, + draw_data, + (float) font->x_scale / (float) font->parent->x_scale, + (float) font->y_scale / (float) font->parent->y_scale + }; + + font->parent->get_glyph_shape (glyph, + const_cast (&_hb_draw_funcs_default), + &adaptor); +} + +DEFINE_NULL_INSTANCE (hb_font_funcs_t) = +{ + HB_OBJECT_HEADER_STATIC, + + nullptr, + nullptr, { { #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil, @@ -527,16 +650,8 @@ static const hb_font_funcs_t _hb_font_funcs_default = { HB_OBJECT_HEADER_STATIC, - { -#define HB_FONT_FUNC_IMPLEMENT(name) nullptr, - HB_FONT_FUNCS_IMPLEMENT_CALLBACKS -#undef HB_FONT_FUNC_IMPLEMENT - }, - { -#define HB_FONT_FUNC_IMPLEMENT(name) nullptr, - HB_FONT_FUNCS_IMPLEMENT_CALLBACKS -#undef HB_FONT_FUNC_IMPLEMENT - }, + nullptr, + nullptr, { { #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_default, @@ -548,7 +663,7 @@ /** - * hb_font_funcs_create: (Xconstructor) + * hb_font_funcs_create: * * Creates a new #hb_font_funcs_t structure of font functions. * @@ -615,12 +730,18 @@ { if (!hb_object_destroy (ffuncs)) return; -#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \ - ffuncs->destroy.name (ffuncs->user_data.name); - HB_FONT_FUNCS_IMPLEMENT_CALLBACKS + if (ffuncs->destroy) + { +#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy->name) \ + ffuncs->destroy->name (!ffuncs->user_data ? nullptr : ffuncs->user_data->name); + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT + } + + hb_free (ffuncs->destroy); + hb_free (ffuncs->user_data); - free (ffuncs); + hb_free (ffuncs); } /** @@ -710,24 +831,50 @@ hb_destroy_func_t destroy) \ { \ if (hb_object_is_immutable (ffuncs)) \ + goto fail; \ + \ + if (!func) \ { \ if (destroy) \ destroy (user_data); \ - return; \ + destroy = nullptr; \ + user_data = nullptr; \ } \ \ - if (ffuncs->destroy.name) \ - ffuncs->destroy.name (ffuncs->user_data.name); \ + if (ffuncs->destroy && ffuncs->destroy->name) \ + ffuncs->destroy->name (!ffuncs->user_data ? nullptr : ffuncs->user_data->name); \ + \ + if (user_data && !ffuncs->user_data) \ + { \ + ffuncs->user_data = (decltype (ffuncs->user_data)) hb_calloc (1, sizeof (*ffuncs->user_data)); \ + if (unlikely (!ffuncs->user_data)) \ + goto fail; \ + } \ + if (destroy && !ffuncs->destroy) \ + { \ + ffuncs->destroy = (decltype (ffuncs->destroy)) hb_calloc (1, sizeof (*ffuncs->destroy)); \ + if (unlikely (!ffuncs->destroy)) \ + goto fail; \ + } \ \ if (func) { \ ffuncs->get.f.name = func; \ - ffuncs->user_data.name = user_data; \ - ffuncs->destroy.name = destroy; \ + if (ffuncs->user_data) \ + ffuncs->user_data->name = user_data; \ + if (ffuncs->destroy) \ + ffuncs->destroy->name = destroy; \ } else { \ ffuncs->get.f.name = hb_font_get_##name##_default; \ - ffuncs->user_data.name = nullptr; \ - ffuncs->destroy.name = nullptr; \ + if (ffuncs->user_data) \ + ffuncs->user_data->name = nullptr; \ + if (ffuncs->destroy) \ + ffuncs->destroy->name = nullptr; \ } \ + return; \ + \ +fail: \ + if (destroy) \ + destroy (user_data); \ } HB_FONT_FUNCS_IMPLEMENT_CALLBACKS @@ -1168,6 +1315,26 @@ return font->get_glyph_from_name (name, len, glyph); } +/** + * hb_font_get_glyph_shape: + * @font: #hb_font_t to work upon + * @glyph: : The glyph ID + * @dfuncs: #hb_draw_funcs_t to draw to + * @draw_data: User data to pass to draw callbacks + * + * Fetches the glyph shape that corresponds to a glyph in the specified @font. + * The shape is returned by way of calls to the callsbacks of the @dfuncs + * objects, with @draw_data passed to them. + * + * Since: 4.0.0 + **/ +void +hb_font_get_glyph_shape (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data) +{ + font->get_glyph_shape (glyph, dfuncs, draw_data); +} /* A bit higher-level, and with fallback */ @@ -1190,7 +1357,7 @@ hb_direction_t direction, hb_font_extents_t *extents) { - return font->get_extents_for_direction (direction, extents); + font->get_extents_for_direction (direction, extents); } /** * hb_font_get_glyph_advance_for_direction: @@ -1215,7 +1382,7 @@ hb_position_t *x, hb_position_t *y) { - return font->get_glyph_advance_for_direction (glyph, direction, x, y); + font->get_glyph_advance_for_direction (glyph, direction, x, y); } /** * hb_font_get_glyph_advances_for_direction: @@ -1472,11 +1639,18 @@ { HB_OBJECT_HEADER_STATIC, + 0, /* serial */ + 0, /* serial_coords */ + nullptr, /* parent */ const_cast (&_hb_Null_hb_face_t), 1000, /* x_scale */ 1000, /* y_scale */ + 0., /* slant */ + 0., /* slant_xy; */ + 1.f, /* x_multf */ + 1.f, /* y_multf */ 1<<16, /* x_mult */ 1<<16, /* y_mult */ @@ -1509,18 +1683,26 @@ font->face = hb_face_reference (face); font->klass = hb_font_funcs_get_empty (); font->data.init0 (font); - font->x_scale = font->y_scale = hb_face_get_upem (face); + font->x_scale = font->y_scale = face->get_upem (); + font->x_multf = font->y_multf = 1.f; font->x_mult = font->y_mult = 1 << 16; return font; } /** - * hb_font_create: (Xconstructor) + * hb_font_create: * @face: a face. * * Constructs a new font object from the specified face. * + * Note: If @face's index value (as passed to hb_face_create() + * has non-zero top 16-bits, those bits minus one are passed to + * hb_font_set_var_named_instance(), effectively loading a named-instance + * of a variable font, instead of the default-instance. This allows + * specifying which named-instance to load by default when creating the + * face. + * * Return value: (transfer full): The new font object * * Since: 0.9.2 @@ -1535,6 +1717,11 @@ hb_ot_font_set_funcs (font); #endif +#ifndef HB_NO_VAR + if (face && face->index >> 16) + hb_font_set_var_named_instance (font, (face->index >> 16) - 1); +#endif + return font; } @@ -1544,12 +1731,14 @@ float *design_coords, unsigned int coords_length) { - free (font->coords); - free (font->design_coords); + hb_free (font->coords); + hb_free (font->design_coords); font->coords = coords; font->design_coords = design_coords; font->num_coords = coords_length; + + font->mults_changed (); // Easiest to call this to drop cached data } /** @@ -1578,7 +1767,7 @@ font->x_scale = parent->x_scale; font->y_scale = parent->y_scale; - font->mults_changed (); + font->slant = parent->slant; font->x_ppem = parent->x_ppem; font->y_ppem = parent->y_ppem; font->ptem = parent->ptem; @@ -1586,8 +1775,8 @@ unsigned int num_coords = parent->num_coords; if (num_coords) { - int *coords = (int *) calloc (num_coords, sizeof (parent->coords[0])); - float *design_coords = (float *) calloc (num_coords, sizeof (parent->design_coords[0])); + int *coords = (int *) hb_calloc (num_coords, sizeof (parent->coords[0])); + float *design_coords = (float *) hb_calloc (num_coords, sizeof (parent->design_coords[0])); if (likely (coords && design_coords)) { memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0])); @@ -1596,11 +1785,13 @@ } else { - free (coords); - free (design_coords); + hb_free (coords); + hb_free (design_coords); } } + font->mults_changed (); + return font; } @@ -1659,10 +1850,10 @@ hb_face_destroy (font->face); hb_font_funcs_destroy (font->klass); - free (font->coords); - free (font->design_coords); + hb_free (font->coords); + hb_free (font->design_coords); - free (font); + hb_free (font); } /** @@ -1686,6 +1877,9 @@ hb_destroy_func_t destroy /* May be NULL. */, hb_bool_t replace) { + if (!hb_object_is_immutable (font)) + font->serial++; + return hb_object_set_user_data (font, key, data, destroy, replace); } @@ -1745,6 +1939,45 @@ } /** + * hb_font_get_serial: + * @font: #hb_font_t to work upon + * + * Returns the internal serial number of the font. The serial + * number is increased every time a setting on the font is + * changed, using a setter function. + * + * Return value: serial number + * + * Since: 4.4.0. + **/ +unsigned int +hb_font_get_serial (hb_font_t *font) +{ + return font->serial; +} + +/** + * hb_font_changed: + * @font: #hb_font_t to work upon + * + * Notifies the @font that underlying font data has changed. + * This has the effect of increasing the serial as returned + * by hb_font_get_serial(), which invalidates internal caches. + * + * Since: 4.4.0. + **/ +void +hb_font_changed (hb_font_t *font) +{ + if (hb_object_is_immutable (font)) + return; + + font->serial++; + + font->mults_changed (); +} + +/** * hb_font_set_parent: * @font: #hb_font_t to work upon * @parent: The parent font object to assign @@ -1760,6 +1993,11 @@ if (hb_object_is_immutable (font)) return; + if (parent == font->parent) + return; + + font->serial++; + if (!parent) parent = hb_font_get_empty (); @@ -1802,6 +2040,11 @@ if (hb_object_is_immutable (font)) return; + if (face == font->face) + return; + + font->serial++; + if (unlikely (!face)) face = hb_face_get_empty (); @@ -1856,6 +2099,8 @@ return; } + font->serial++; + if (font->destroy) font->destroy (font->user_data); @@ -1893,6 +2138,8 @@ return; } + font->serial++; + if (font->destroy) font->destroy (font->user_data); @@ -1919,6 +2166,11 @@ if (hb_object_is_immutable (font)) return; + if (font->x_scale == x_scale && font->y_scale == y_scale) + return; + + font->serial++; + font->x_scale = x_scale; font->y_scale = y_scale; font->mults_changed (); @@ -1961,6 +2213,11 @@ if (hb_object_is_immutable (font)) return; + if (font->x_ppem == x_ppem && font->y_ppem == y_ppem) + return; + + font->serial++; + font->x_ppem = x_ppem; font->y_ppem = y_ppem; } @@ -2003,6 +2260,11 @@ if (hb_object_is_immutable (font)) return; + if (font->ptem == ptem) + return; + + font->serial++; + font->ptem = ptem; } @@ -2015,7 +2277,7 @@ * * Return value: Point size. A value of zero means "not set." * - * Since: 0.9.2 + * Since: 1.6.0 **/ float hb_font_get_ptem (hb_font_t *font) @@ -2023,6 +2285,58 @@ return font->ptem; } +/** + * hb_font_set_synthetic_slant: + * @font: #hb_font_t to work upon + * @slant: synthetic slant value. + * + * Sets the "synthetic slant" of a font. By default is zero. + * Synthetic slant is the graphical skew applied to the font + * at rendering time. + * + * HarfBuzz needs to know this value to adjust shaping results, + * metrics, and style values to match the slanted rendering. + * + * Note: The glyph shape fetched via the + * hb_font_get_glyph_shape() is slanted to reflect this value + * as well. + * + * Note: The slant value is a ratio. For example, a + * 20% slant would be represented as a 0.2 value. + * + * Since: 3.3.0 + **/ +HB_EXTERN void +hb_font_set_synthetic_slant (hb_font_t *font, float slant) +{ + if (hb_object_is_immutable (font)) + return; + + if (font->slant == slant) + return; + + font->serial++; + + font->slant = slant; + font->mults_changed (); +} + +/** + * hb_font_get_synthetic_slant: + * @font: #hb_font_t to work upon + * + * Fetches the "synthetic slant" of a font. + * + * Return value: Synthetic slant. By default is zero. + * + * Since: 3.3.0 + **/ +HB_EXTERN float +hb_font_get_synthetic_slant (hb_font_t *font) +{ + return font->slant; +} + #ifndef HB_NO_VAR /* * Variations @@ -2036,6 +2350,10 @@ * * Applies a list of font-variation settings to a font. * + * Note that this overrides all existing variations set on @font. + * Axes not included in @variations will be effectively set to their + * default values. + * * Since: 1.4.2 */ void @@ -2046,35 +2364,38 @@ if (hb_object_is_immutable (font)) return; + font->serial_coords = ++font->serial; + if (!variations_length) { hb_font_set_var_coords_normalized (font, nullptr, 0); return; } - unsigned int coords_length = hb_ot_var_get_axis_count (font->face); + const OT::fvar &fvar = *font->face->table.fvar; + auto axes = fvar.get_axes (); + const unsigned coords_length = axes.length; - int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr; - float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr; + int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr; + float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr; if (unlikely (coords_length && !(normalized && design_coords))) { - free (normalized); - free (design_coords); + hb_free (normalized); + hb_free (design_coords); return; } - const OT::fvar &fvar = *font->face->table.fvar; for (unsigned int i = 0; i < variations_length; i++) { - hb_ot_var_axis_info_t info; - if (hb_ot_var_find_axis_info (font->face, variations[i].tag, &info) && - info.axis_index < coords_length) - { - float v = variations[i].value; - design_coords[info.axis_index] = v; - normalized[info.axis_index] = fvar.normalize_axis_value (info.axis_index, v); - } + const auto tag = variations[i].tag; + const auto v = variations[i].value; + for (unsigned axis_index = 0; axis_index < coords_length; axis_index++) + if (axes[axis_index].axisTag == tag) + { + design_coords[axis_index] = v; + normalized[axis_index] = fvar.normalize_axis_value (axis_index, v); + } } font->face->table.avar->map_coords (normalized, coords_length); @@ -2090,6 +2411,10 @@ * Applies a list of variation coordinates (in design-space units) * to a font. * + * Note that this overrides all existing variations set on @font. + * Axes not included in @coords will be effectively set to their + * default values. + * * Since: 1.4.2 */ void @@ -2100,13 +2425,15 @@ if (hb_object_is_immutable (font)) return; - int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr; - float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr; + font->serial_coords = ++font->serial; + + int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr; + float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr; if (unlikely (coords_length && !(normalized && design_coords))) { - free (normalized); - free (design_coords); + hb_free (normalized); + hb_free (design_coords); return; } @@ -2133,15 +2460,17 @@ if (hb_object_is_immutable (font)) return; + font->serial_coords = ++font->serial; + unsigned int coords_length = hb_ot_var_named_instance_get_design_coords (font->face, instance_index, nullptr, nullptr); - float *coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr; + float *coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr; if (unlikely (coords_length && !coords)) return; hb_ot_var_named_instance_get_design_coords (font->face, instance_index, &coords_length, coords); hb_font_set_var_coords_design (font, coords, coords_length); - free (coords); + hb_free (coords); } /** @@ -2153,6 +2482,10 @@ * Applies a list of variation coordinates (in normalized units) * to a font. * + * Note that this overrides all existing variations set on @font. + * Axes not included in @coords will be effectively set to their + * default values. + * * Note: Coordinates should be normalized to 2.14. * * Since: 1.4.2 @@ -2165,15 +2498,17 @@ if (hb_object_is_immutable (font)) return; - int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr; - int *unmapped = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr; - float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (design_coords[0])) : nullptr; + font->serial_coords = ++font->serial; + + int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr; + int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr; + float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (design_coords[0])) : nullptr; if (unlikely (coords_length && !(copy && unmapped && design_coords))) { - free (copy); - free (unmapped); - free (design_coords); + hb_free (copy); + hb_free (unmapped); + hb_free (design_coords); return; } @@ -2187,7 +2522,7 @@ font->face->table.avar->unmap_coords (unmapped, coords_length); for (unsigned int i = 0; i < coords_length; ++i) design_coords[i] = font->face->table.fvar->unnormalize_axis_value (i, unmapped[i]); - free (unmapped); + hb_free (unmapped); _hb_font_adopt_var_coords (font, copy, design_coords, coords_length); } @@ -2195,14 +2530,19 @@ /** * hb_font_get_var_coords_normalized: * @font: #hb_font_t to work upon - * @length: Number of coordinates retrieved + * @length: (out): Number of coordinates retrieved * * Fetches the list of normalized variation coordinates currently * set on a font. * + * Note that this returned array may only contain values for some + * (or none) of the axes; omitted axes effectively have zero values. + * * Return value is valid as long as variation coordinates of the font * are not modified. * + * Return value: coordinates array + * * Since: 1.4.2 */ const int * @@ -2215,18 +2555,24 @@ return font->coords; } -#ifdef HB_EXPERIMENTAL_API /** * hb_font_get_var_coords_design: * @font: #hb_font_t to work upon - * @length: (out): number of coordinates + * @length: (out): Number of coordinates retrieved + * + * Fetches the list of variation coordinates (in design-space units) currently + * set on a font. + * + * Note that this returned array may only contain values for some + * (or none) of the axes; omitted axes effectively have their default + * values. * * Return value is valid as long as variation coordinates of the font * are not modified. * * Return value: coordinates array * - * Since: EXPERIMENTAL + * Since: 3.3.0 */ const float * hb_font_get_var_coords_design (hb_font_t *font, @@ -2238,7 +2584,6 @@ return font->design_coords; } #endif -#endif #ifndef HB_DISABLE_DEPRECATED /* @@ -2267,7 +2612,7 @@ { typedef hb_trampoline_t trampoline_t; - trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t)); + trampoline_t *trampoline = (trampoline_t *) hb_calloc (1, sizeof (trampoline_t)); if (unlikely (!trampoline)) return nullptr; @@ -2296,7 +2641,7 @@ if (closure->destroy) closure->destroy (closure->user_data); - free (closure); + hb_free (closure); } typedef hb_trampoline_t hb_font_get_glyph_trampoline_t; @@ -2360,12 +2705,14 @@ return; } + /* Since we pass it to two destroying functions. */ + trampoline_reference (&trampoline->closure); + hb_font_funcs_set_nominal_glyph_func (ffuncs, hb_font_get_nominal_glyph_trampoline, trampoline, trampoline_destroy); - trampoline_reference (&trampoline->closure); hb_font_funcs_set_variation_glyph_func (ffuncs, hb_font_get_variation_glyph_trampoline, trampoline, diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-font.h openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-font.h --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-font.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-font.h 2022-10-10 13:07:22.000000000 +0000 @@ -511,6 +511,25 @@ hb_codepoint_t *glyph, void *user_data); +/** + * hb_font_get_glyph_shape_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @glyph: The glyph ID to query + * @draw_funcs: The draw functions to send the shape data to + * @draw_data: The data accompanying the draw functions + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. + * + * Since: 4.0.0 + * + **/ +typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data); + /* func setters */ @@ -770,6 +789,22 @@ hb_font_get_glyph_from_name_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_font_funcs_set_glyph_shape_func: + * @ffuncs: A font-function structure + * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets the implementation function for #hb_font_get_glyph_shape_func_t. + * + * Since: 4.0.0 + **/ +HB_EXTERN void +hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs, + hb_font_get_glyph_shape_func_t func, + void *user_data, hb_destroy_func_t destroy); + /* func dispatch */ HB_EXTERN hb_bool_t @@ -850,6 +885,11 @@ const char *name, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph); +HB_EXTERN void +hb_font_get_glyph_shape (hb_font_t *font, + hb_codepoint_t glyph, + hb_draw_funcs_t *dfuncs, void *draw_data); + /* high-level funcs, with fallback */ @@ -962,6 +1002,12 @@ HB_EXTERN hb_bool_t hb_font_is_immutable (hb_font_t *font); +HB_EXTERN unsigned int +hb_font_get_serial (hb_font_t *font); + +HB_EXTERN void +hb_font_changed (hb_font_t *font); + HB_EXTERN void hb_font_set_parent (hb_font_t *font, hb_font_t *parent); @@ -1024,6 +1070,12 @@ hb_font_get_ptem (hb_font_t *font); HB_EXTERN void +hb_font_set_synthetic_slant (hb_font_t *font, float slant); + +HB_EXTERN float +hb_font_get_synthetic_slant (hb_font_t *font); + +HB_EXTERN void hb_font_set_variations (hb_font_t *font, const hb_variation_t *variations, unsigned int variations_length); @@ -1033,11 +1085,9 @@ const float *coords, unsigned int coords_length); -#ifdef HB_EXPERIMENTAL_API HB_EXTERN const float * hb_font_get_var_coords_design (hb_font_t *font, unsigned int *length); -#endif HB_EXTERN void hb_font_set_var_coords_normalized (hb_font_t *font, @@ -1052,11 +1102,6 @@ hb_font_set_var_named_instance (hb_font_t *font, unsigned instance_index); -#ifdef HB_EXPERIMENTAL_API -HB_EXTERN hb_bool_t -hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph, - const hb_draw_funcs_t *funcs, void *user_data); -#endif HB_END_DECLS diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-font.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-font.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-font.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-font.hh 2022-10-10 13:07:22.000000000 +0000 @@ -57,6 +57,7 @@ HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \ HB_FONT_FUNC_IMPLEMENT (glyph_name) \ HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \ + HB_FONT_FUNC_IMPLEMENT (glyph_shape) \ /* ^--- Add new callbacks here */ struct hb_font_funcs_t @@ -67,13 +68,13 @@ #define HB_FONT_FUNC_IMPLEMENT(name) void *name; HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT - } user_data; + } *user_data; struct { #define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name; HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT - } destroy; + } *destroy; /* Don't access these directly. Call font->get_*() instead. */ union get_t { @@ -103,12 +104,18 @@ struct hb_font_t { hb_object_header_t header; + unsigned int serial; + unsigned int serial_coords; hb_font_t *parent; hb_face_t *face; int32_t x_scale; int32_t y_scale; + float slant; + float slant_xy; + float x_multf; + float y_multf; int64_t x_mult; int64_t y_mult; @@ -134,10 +141,12 @@ { return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; } hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); } hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); } - hb_position_t em_scalef_x (float v) { return em_scalef (v, x_scale); } - hb_position_t em_scalef_y (float v) { return em_scalef (v, y_scale); } - float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); } - float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); } + hb_position_t em_scalef_x (float v) { return em_multf (v, x_multf); } + hb_position_t em_scalef_y (float v) { return em_multf (v, y_multf); } + float em_fscale_x (int16_t v) { return em_fmult (v, x_multf); } + float em_fscale_y (int16_t v) { return em_fmult (v, y_multf); } + float em_fscalef_x (float v) { return em_fmultf (v, x_multf); } + float em_fscalef_y (float v) { return em_fmultf (v, y_multf); } hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) { return em_mult (v, dir_mult (direction)); } @@ -200,14 +209,14 @@ memset (extents, 0, sizeof (*extents)); return klass->get.f.font_h_extents (this, user_data, extents, - klass->user_data.font_h_extents); + !klass->user_data ? nullptr : klass->user_data->font_h_extents); } hb_bool_t get_font_v_extents (hb_font_extents_t *extents) { memset (extents, 0, sizeof (*extents)); return klass->get.f.font_v_extents (this, user_data, extents, - klass->user_data.font_v_extents); + !klass->user_data ? nullptr : klass->user_data->font_v_extents); } bool has_glyph (hb_codepoint_t unicode) @@ -217,12 +226,13 @@ } hb_bool_t get_nominal_glyph (hb_codepoint_t unicode, - hb_codepoint_t *glyph) + hb_codepoint_t *glyph, + hb_codepoint_t not_found = 0) { - *glyph = 0; + *glyph = not_found; return klass->get.f.nominal_glyph (this, user_data, unicode, glyph, - klass->user_data.nominal_glyph); + !klass->user_data ? nullptr : klass->user_data->nominal_glyph); } unsigned int get_nominal_glyphs (unsigned int count, const hb_codepoint_t *first_unicode, @@ -234,30 +244,31 @@ count, first_unicode, unicode_stride, first_glyph, glyph_stride, - klass->user_data.nominal_glyphs); + !klass->user_data ? nullptr : klass->user_data->nominal_glyphs); } hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, - hb_codepoint_t *glyph) + hb_codepoint_t *glyph, + hb_codepoint_t not_found = 0) { - *glyph = 0; + *glyph = not_found; return klass->get.f.variation_glyph (this, user_data, unicode, variation_selector, glyph, - klass->user_data.variation_glyph); + !klass->user_data ? nullptr : klass->user_data->variation_glyph); } hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) { return klass->get.f.glyph_h_advance (this, user_data, glyph, - klass->user_data.glyph_h_advance); + !klass->user_data ? nullptr : klass->user_data->glyph_h_advance); } hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) { return klass->get.f.glyph_v_advance (this, user_data, glyph, - klass->user_data.glyph_v_advance); + !klass->user_data ? nullptr : klass->user_data->glyph_v_advance); } void get_glyph_h_advances (unsigned int count, @@ -270,7 +281,7 @@ count, first_glyph, glyph_stride, first_advance, advance_stride, - klass->user_data.glyph_h_advances); + !klass->user_data ? nullptr : klass->user_data->glyph_h_advances); } void get_glyph_v_advances (unsigned int count, @@ -283,7 +294,7 @@ count, first_glyph, glyph_stride, first_advance, advance_stride, - klass->user_data.glyph_v_advances); + !klass->user_data ? nullptr : klass->user_data->glyph_v_advances); } hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, @@ -292,7 +303,7 @@ *x = *y = 0; return klass->get.f.glyph_h_origin (this, user_data, glyph, x, y, - klass->user_data.glyph_h_origin); + !klass->user_data ? nullptr : klass->user_data->glyph_h_origin); } hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph, @@ -301,7 +312,7 @@ *x = *y = 0; return klass->get.f.glyph_v_origin (this, user_data, glyph, x, y, - klass->user_data.glyph_v_origin); + !klass->user_data ? nullptr : klass->user_data->glyph_v_origin); } hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, @@ -312,7 +323,7 @@ #else return klass->get.f.glyph_h_kerning (this, user_data, left_glyph, right_glyph, - klass->user_data.glyph_h_kerning); + !klass->user_data ? nullptr : klass->user_data->glyph_h_kerning); #endif } @@ -324,7 +335,7 @@ #else return klass->get.f.glyph_v_kerning (this, user_data, top_glyph, bottom_glyph, - klass->user_data.glyph_v_kerning); + !klass->user_data ? nullptr : klass->user_data->glyph_v_kerning); #endif } @@ -335,7 +346,7 @@ return klass->get.f.glyph_extents (this, user_data, glyph, extents, - klass->user_data.glyph_extents); + !klass->user_data ? nullptr : klass->user_data->glyph_extents); } hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, @@ -345,7 +356,7 @@ return klass->get.f.glyph_contour_point (this, user_data, glyph, point_index, x, y, - klass->user_data.glyph_contour_point); + !klass->user_data ? nullptr : klass->user_data->glyph_contour_point); } hb_bool_t get_glyph_name (hb_codepoint_t glyph, @@ -355,7 +366,7 @@ return klass->get.f.glyph_name (this, user_data, glyph, name, size, - klass->user_data.glyph_name); + !klass->user_data ? nullptr : klass->user_data->glyph_name); } hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */ @@ -366,7 +377,16 @@ return klass->get.f.glyph_from_name (this, user_data, name, len, glyph, - klass->user_data.glyph_from_name); + !klass->user_data ? nullptr : klass->user_data->glyph_from_name); + } + + void get_glyph_shape (hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data) + { + klass->get.f.glyph_shape (this, user_data, + glyph, + draw_funcs, draw_data, + !klass->user_data ? nullptr : klass->user_data->glyph_shape); } @@ -428,7 +448,6 @@ { *x = get_glyph_h_advance (glyph) / 2; - /* TODO cache this somehow?! */ hb_font_extents_t extents; get_h_extents_with_fallback (&extents); *y = extents.ascender; @@ -612,19 +631,26 @@ void mults_changed () { - signed upem = face->get_upem (); - x_mult = ((int64_t) x_scale << 16) / upem; - y_mult = ((int64_t) y_scale << 16) / upem; + float upem = face->get_upem (); + x_multf = x_scale / upem; + y_multf = y_scale / upem; + bool x_neg = x_scale < 0; + x_mult = (x_neg ? -((int64_t) -x_scale << 16) : ((int64_t) x_scale << 16)) / upem; + bool y_neg = y_scale < 0; + y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem; + slant_xy = y_scale ? slant * x_scale / y_scale : 0.f; + + data.fini (); } hb_position_t em_mult (int16_t v, int64_t mult) - { - return (hb_position_t) ((v * mult) >> 16); - } - hb_position_t em_scalef (float v, int scale) - { return (hb_position_t) roundf (v * scale / face->get_upem ()); } - float em_fscale (int16_t v, int scale) - { return (float) v * scale / face->get_upem (); } + { return (hb_position_t) ((v * mult + 32768) >> 16); } + hb_position_t em_multf (float v, float mult) + { return (hb_position_t) roundf (em_fmultf (v, mult)); } + float em_fmultf (float v, float mult) + { return v * mult; } + float em_fmult (int16_t v, float mult) + { return (float) v * mult; } }; DECLARE_NULL_INSTANCE (hb_font_t); diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ft.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ft.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ft.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ft.cc 2022-10-10 13:07:22.000000000 +0000 @@ -33,12 +33,16 @@ #include "hb-ft.h" +#include "hb-draw.hh" #include "hb-font.hh" #include "hb-machinery.hh" #include "hb-cache.hh" +#include "hb-ot-os2-table.hh" +#include "hb-ot-shaper-arabic-pua.hh" #include FT_ADVANCES_H #include FT_MULTIPLE_MASTERS_H +#include FT_OUTLINE_H #include FT_TRUETYPE_TABLES_H @@ -78,20 +82,20 @@ struct hb_ft_font_t { - mutable hb_mutex_t lock; - FT_Face ft_face; int load_flags; bool symbol; /* Whether selected cmap is symbol cmap. */ bool unref; /* Whether to destroy ft_face when done. */ - mutable int cached_x_scale; + mutable hb_mutex_t lock; + FT_Face ft_face; + mutable unsigned cached_serial; mutable hb_advance_cache_t advance_cache; }; static hb_ft_font_t * _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref) { - hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t)); + hb_ft_font_t *ft_font = (hb_ft_font_t *) hb_calloc (1, sizeof (hb_ft_font_t)); if (unlikely (!ft_font)) return nullptr; ft_font->lock.init (); @@ -101,7 +105,7 @@ ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; - ft_font->cached_x_scale = 0; + ft_font->cached_serial = (unsigned) -1; ft_font->advance_cache.init (); return ft_font; @@ -125,9 +129,61 @@ ft_font->lock.fini (); - free (ft_font); + hb_free (ft_font); +} + + +/* hb_font changed, update FT_Face. */ +static void _hb_ft_hb_font_changed (hb_font_t *font, FT_Face ft_face) +{ + + FT_Set_Char_Size (ft_face, + abs (font->x_scale), abs (font->y_scale), + 0, 0); +#if 0 + font->x_ppem * 72 * 64 / font->x_scale, + font->y_ppem * 72 * 64 / font->y_scale); +#endif + if (font->x_scale < 0 || font->y_scale < 0) + { + FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0, + 0, font->y_scale < 0 ? -1 : +1}; + FT_Set_Transform (ft_face, &matrix, nullptr); + } + +#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR) + unsigned int num_coords; + const int *coords = hb_font_get_var_coords_normalized (font, &num_coords); + if (num_coords) + { + FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (num_coords, sizeof (FT_Fixed)); + if (ft_coords) + { + for (unsigned int i = 0; i < num_coords; i++) + ft_coords[i] = coords[i] * 4; + FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords); + hb_free (ft_coords); + } + } +#endif +} + +/* Check if hb_font changed, update FT_Face. */ +static inline bool +_hb_ft_hb_font_check_changed (hb_font_t *font, + const hb_ft_font_t *ft_font) +{ + if (font->serial != ft_font->cached_serial) + { + _hb_ft_hb_font_changed (font, ft_font->ft_face); + ft_font->advance_cache.clear (); + ft_font->cached_serial = font->serial; + return true; + } + return false; } + /** * hb_ft_font_set_load_flags: * @font: #hb_font_t to work upon @@ -179,7 +235,7 @@ } /** - * hb_ft_font_get_face: + * hb_ft_font_get_face: (skip) * @font: #hb_font_t to work upon * * Fetches the FT_Face associated with the specified #hb_font_t @@ -201,7 +257,7 @@ } /** - * hb_ft_font_lock_face: + * hb_ft_font_lock_face: (skip) * @font: #hb_font_t to work upon * * Gets the FT_Face associated with @font, This face will be kept around until @@ -244,7 +300,7 @@ static hb_bool_t -hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED, +hb_ft_get_nominal_glyph (hb_font_t *font, void *font_data, hb_codepoint_t unicode, hb_codepoint_t *glyph, @@ -256,14 +312,29 @@ if (unlikely (!g)) { - if (unlikely (ft_font->symbol) && unicode <= 0x00FFu) + if (unlikely (ft_font->symbol)) { - /* For symbol-encoded OpenType fonts, we duplicate the - * U+F000..F0FF range at U+0000..U+00FF. That's what - * Windows seems to do, and that's hinted about at: - * https://docs.microsoft.com/en-us/typography/opentype/spec/recom - * under "Non-Standard (Symbol) Fonts". */ - g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode); + switch ((unsigned) font->face->table.OS2->get_font_page ()) { + case OT::OS2::font_page_t::FONT_PAGE_NONE: + if (unicode <= 0x00FFu) + /* For symbol-encoded OpenType fonts, we duplicate the + * U+F000..F0FF range at U+0000..U+00FF. That's what + * Windows seems to do, and that's hinted about at: + * https://docs.microsoft.com/en-us/typography/opentype/spec/recom + * under "Non-Standard (Symbol) Fonts". */ + g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode); + break; +#ifndef HB_NO_OT_SHAPER_ARABIC_FALLBACK + case OT::OS2::font_page_t::FONT_PAGE_SIMP_ARABIC: + g = FT_Get_Char_Index (ft_font->ft_face, _hb_arabic_pua_simp_map (unicode)); + break; + case OT::OS2::font_page_t::FONT_PAGE_TRAD_ARABIC: + g = FT_Get_Char_Index (ft_font->ft_face, _hb_arabic_pua_trad_map (unicode)); + break; +#endif + default: + break; + } if (!g) return false; } @@ -335,12 +406,6 @@ int load_flags = ft_font->load_flags; int mult = font->x_scale < 0 ? -1 : +1; - if (font->x_scale != ft_font->cached_x_scale) - { - ft_font->advance_cache.clear (); - ft_font->cached_x_scale = font->x_scale; - } - for (unsigned int i = 0; i < count; i++) { FT_Fixed v = 0; @@ -361,6 +426,7 @@ } } +#ifndef HB_NO_VERTICAL static hb_position_t hb_ft_get_glyph_v_advance (hb_font_t *font, void *font_data, @@ -379,9 +445,12 @@ /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates * have a Y growing upward. Hence the extra negation. */ + return (-v + (1<<9)) >> 10; } +#endif +#ifndef HB_NO_VERTICAL static hb_bool_t hb_ft_get_glyph_v_origin (hb_font_t *font, void *font_data, @@ -409,6 +478,7 @@ return true; } +#endif #ifndef HB_NO_OT_SHAPE_FALLBACK static hb_position_t @@ -419,6 +489,7 @@ void *user_data HB_UNUSED) { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); FT_Vector kerningv; FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED; @@ -549,6 +620,7 @@ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; hb_lock_t lock (ft_font->lock); FT_Face ft_face = ft_font->ft_face; + metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale); metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale); metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender); @@ -561,25 +633,106 @@ return true; } -#if HB_USE_ATEXIT -static void free_static_ft_funcs (); +#ifndef HB_NO_DRAW + +static int +_hb_ft_move_to (const FT_Vector *to, + hb_draw_session_t *drawing) +{ + drawing->move_to (to->x, to->y); + return FT_Err_Ok; +} + +static int +_hb_ft_line_to (const FT_Vector *to, + hb_draw_session_t *drawing) +{ + drawing->line_to (to->x, to->y); + return FT_Err_Ok; +} + +static int +_hb_ft_conic_to (const FT_Vector *control, + const FT_Vector *to, + hb_draw_session_t *drawing) +{ + drawing->quadratic_to (control->x, control->y, + to->x, to->y); + return FT_Err_Ok; +} + +static int +_hb_ft_cubic_to (const FT_Vector *control1, + const FT_Vector *control2, + const FT_Vector *to, + hb_draw_session_t *drawing) +{ + drawing->cubic_to (control1->x, control1->y, + control2->x, control2->y, + to->x, to->y); + return FT_Err_Ok; +} + +static void +hb_ft_get_glyph_shape (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data HB_UNUSED) +{ + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + hb_lock_t lock (ft_font->lock); + FT_Face ft_face = ft_font->ft_face; + + _hb_ft_hb_font_check_changed (font, ft_font); + + if (unlikely (FT_Load_Glyph (ft_face, glyph, + FT_LOAD_NO_BITMAP | ft_font->load_flags))) + return; + + if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE) + return; + + const FT_Outline_Funcs outline_funcs = { + (FT_Outline_MoveToFunc) _hb_ft_move_to, + (FT_Outline_LineToFunc) _hb_ft_line_to, + (FT_Outline_ConicToFunc) _hb_ft_conic_to, + (FT_Outline_CubicToFunc) _hb_ft_cubic_to, + 0, /* shift */ + 0, /* delta */ + }; + + hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy); + + FT_Outline_Decompose (&ft_face->glyph->outline, + &outline_funcs, + &draw_session); +} #endif + +static inline void free_static_ft_funcs (); + static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t { static hb_font_funcs_t *create () { hb_font_funcs_t *funcs = hb_font_funcs_create (); - hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr); - //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr); hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr); hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ft_get_nominal_glyphs, nullptr, nullptr); hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr); + + hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr); hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr); - hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr); //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr); + +#ifndef HB_NO_VERTICAL + //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr); + hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr); hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr); +#endif + #ifndef HB_NO_OT_SHAPE_FALLBACK hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr); #endif @@ -589,23 +742,23 @@ hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr); hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr); +#ifndef HB_NO_DRAW + hb_font_funcs_set_glyph_shape_func (funcs, hb_ft_get_glyph_shape, nullptr, nullptr); +#endif + hb_font_funcs_make_immutable (funcs); -#if HB_USE_ATEXIT - atexit (free_static_ft_funcs); -#endif + hb_atexit (free_static_ft_funcs); return funcs; } } static_ft_funcs; -#if HB_USE_ATEXIT -static +static inline void free_static_ft_funcs () { static_ft_funcs.free_instance (); } -#endif static hb_font_funcs_t * _hb_ft_get_font_funcs () @@ -642,20 +795,20 @@ if (error) return nullptr; - buffer = (FT_Byte *) malloc (length); + buffer = (FT_Byte *) hb_malloc (length); if (!buffer) return nullptr; error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length); if (error) { - free (buffer); + hb_free (buffer); return nullptr; } return hb_blob_create ((const char *) buffer, length, HB_MEMORY_MODE_WRITABLE, - buffer, free); + buffer, hb_free); } /** @@ -846,8 +999,8 @@ FT_MM_Var *mm_var = nullptr; if (!FT_Get_MM_Var (ft_face, &mm_var)) { - FT_Fixed *ft_coords = (FT_Fixed *) calloc (mm_var->num_axis, sizeof (FT_Fixed)); - int *coords = (int *) calloc (mm_var->num_axis, sizeof (int)); + FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (mm_var->num_axis, sizeof (FT_Fixed)); + int *coords = (int *) hb_calloc (mm_var->num_axis, sizeof (int)); if (coords && ft_coords) { if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, ft_coords)) @@ -866,18 +1019,43 @@ hb_font_set_var_coords_normalized (font, nullptr, 0); } } - free (coords); - free (ft_coords); + hb_free (coords); + hb_free (ft_coords); #ifdef HAVE_FT_DONE_MM_VAR FT_Done_MM_Var (ft_face->glyph->library, mm_var); #else - free (mm_var); + hb_free (mm_var); #endif } #endif } /** + * hb_ft_hb_font_changed: + * @font: #hb_font_t to work upon + * + * Refreshes the state of the underlying FT_Face of @font when the hb_font_t + * @font has changed. + * This function should be called after changing the size or + * variation-axis settings on the @font. + * This call is fast if nothing has changed on @font. + * + * Return value: true if changed, false otherwise + * + * Since: 4.4.0 + **/ +hb_bool_t +hb_ft_hb_font_changed (hb_font_t *font) +{ + if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) + return false; + + hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data; + + return _hb_ft_hb_font_check_changed (font, ft_font); +} + +/** * hb_ft_font_create_referenced: * @ft_face: FT_Face to work upon * @@ -905,9 +1083,7 @@ return hb_ft_font_create (ft_face, _hb_ft_face_destroy); } -#if HB_USE_ATEXIT -static void free_static_ft_library (); -#endif +static inline void free_static_ft_library (); static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t, hb_ft_library_lazy_loader_t> @@ -918,9 +1094,7 @@ if (FT_Init_FreeType (&l)) return nullptr; -#if HB_USE_ATEXIT - atexit (free_static_ft_library); -#endif + hb_atexit (free_static_ft_library); return l; } @@ -934,13 +1108,11 @@ } } static_ft_library; -#if HB_USE_ATEXIT -static +static inline void free_static_ft_library () { static_ft_library.free_instance (); } -#endif static FT_Library get_ft_library () @@ -1001,35 +1173,7 @@ if (FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL)) FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE); - FT_Set_Char_Size (ft_face, - abs (font->x_scale), abs (font->y_scale), - 0, 0); -#if 0 - font->x_ppem * 72 * 64 / font->x_scale, - font->y_ppem * 72 * 64 / font->y_scale); -#endif - if (font->x_scale < 0 || font->y_scale < 0) - { - FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0, - 0, font->y_scale < 0 ? -1 : +1}; - FT_Set_Transform (ft_face, &matrix, nullptr); - } - -#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR) - unsigned int num_coords; - const int *coords = hb_font_get_var_coords_normalized (font, &num_coords); - if (num_coords) - { - FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed)); - if (ft_coords) - { - for (unsigned int i = 0; i < num_coords; i++) - ft_coords[i] = coords[i] * 4; - FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords); - free (ft_coords); - } - } -#endif + _hb_ft_hb_font_changed (font, ft_face); ft_face->generic.data = blob; ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ft.h openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ft.h --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ft.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ft.h 2022-10-10 13:07:22.000000000 +0000 @@ -122,10 +122,17 @@ HB_EXTERN int hb_ft_font_get_load_flags (hb_font_t *font); -/* Call when size or variations settings on underlying FT_Face change. */ +/* Call when size or variations settings on underlying FT_Face changed, + * and you want to update the hb_font_t from it. */ HB_EXTERN void hb_ft_font_changed (hb_font_t *font); +/* Call when size or variations settings on underlying hb_font_t may have + * changed, and you want to update the FT_Face from it. This call is fast + * if nothing changed on hb_font_t. Returns true if changed. */ +HB_EXTERN hb_bool_t +hb_ft_hb_font_changed (hb_font_t *font); + /* Makes an hb_font_t use FreeType internally to implement font functions. * Note: this internally creates an FT_Face. Use it when you create your * hb_face_t using hb_face_create(). */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb.hh 2022-10-10 13:07:22.000000000 +0000 @@ -29,7 +29,6 @@ #ifndef HB_HH #define HB_HH - #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC #ifdef _MSC_VER #pragma warning( disable: 4068 ) /* Unknown pragma */ @@ -62,8 +61,10 @@ /* Error. Should never happen. */ #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR +#pragma GCC diagnostic error "-Wbitwise-instead-of-logical" #pragma GCC diagnostic error "-Wcast-align" #pragma GCC diagnostic error "-Wcast-function-type" +#pragma GCC diagnostic error "-Wcomma" #pragma GCC diagnostic error "-Wdelete-non-virtual-dtor" #pragma GCC diagnostic error "-Wembedded-directive" #pragma GCC diagnostic error "-Wextra-semi-stmt" @@ -117,6 +118,9 @@ #pragma GCC diagnostic ignored "-Wshadow" // TODO fix #pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" // TODO fix #pragma GCC diagnostic ignored "-Wunused-parameter" // TODO fix +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic ignored "-Wunused-result" // TODO fix +#endif #endif /* Ignored intentionally. */ @@ -179,6 +183,9 @@ #include #include #include +#if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES) +# define _USE_MATH_DEFINES +#endif #include #include #include @@ -220,10 +227,15 @@ extern "C" void* hb_calloc_impl(size_t nmemb, size_t size); extern "C" void* hb_realloc_impl(void *ptr, size_t size); extern "C" void hb_free_impl(void *ptr); -#define malloc hb_malloc_impl -#define calloc hb_calloc_impl -#define realloc hb_realloc_impl -#define free hb_free_impl +#define hb_malloc hb_malloc_impl +#define hb_calloc hb_calloc_impl +#define hb_realloc hb_realloc_impl +#define hb_free hb_free_impl +#else +#define hb_malloc malloc +#define hb_calloc calloc +#define hb_realloc realloc +#define hb_free free #endif @@ -335,7 +347,6 @@ #else # define HB_NODISCARD #endif -#define hb_success_t HB_NODISCARD bool /* https://github.com/harfbuzz/harfbuzz/issues/1852 */ #if defined(__clang__) && !(defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__))) @@ -376,7 +387,7 @@ # define HB_NO_SETLOCALE # define HB_NO_ERRNO # endif -# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# elif !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) # ifndef HB_NO_GETENV # define HB_NO_GETENV # endif @@ -398,6 +409,9 @@ # define errno _hb_errno #endif +#define HB_STMT_START do +#define HB_STMT_END while (0) + #if defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT) /* atexit() is only safe to be called from shared libraries on certain * platforms. Whitelist. @@ -426,16 +440,25 @@ */ # define HB_USE_ATEXIT 1 # endif -#endif +#endif /* defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT) */ #ifdef HB_NO_ATEXIT # undef HB_USE_ATEXIT #endif #ifndef HB_USE_ATEXIT # define HB_USE_ATEXIT 0 #endif - -#define HB_STMT_START do -#define HB_STMT_END while (0) +#ifndef hb_atexit +#if !HB_USE_ATEXIT +# define hb_atexit(_) HB_STMT_START { if (0) (_) (); } HB_STMT_END +#else /* HB_USE_ATEXIT */ +# ifdef HAVE_ATEXIT +# define hb_atexit atexit +# else + template struct hb_atexit_t { ~hb_atexit_t () { function (); } }; +# define hb_atexit(f) static hb_atexit_t _hb_atexit_##__LINE__; +# endif +#endif +#endif /* Lets assert int types. Saves trouble down the road. */ static_assert ((sizeof (hb_codepoint_t) == 4), ""); @@ -447,6 +470,7 @@ /* Headers we include for everyone. Keep topologically sorted by dependency. * They express dependency amongst themselves, but no other file should include * them directly.*/ +#include "hb-cplusplus.hh" #include "hb-meta.hh" #include "hb-mutex.hh" #include "hb-number.hh" diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-iter.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-iter.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-iter.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-iter.hh 2022-10-10 13:07:22.000000000 +0000 @@ -43,17 +43,12 @@ * is writable, then the iterator returns lvalues, otherwise it * returns rvalues. * - * TODO Document more. - * - * If iterator implementation implements operator!=, then can be - * used in range-based for loop. That comes free if the iterator + * If iterator implementation implements operator!=, then it can be + * used in range-based for loop. That already happens if the iterator * is random-access. Otherwise, the range-based for loop incurs * one traversal to find end(), which can be avoided if written * as a while-style for loop, or if iterator implements a faster - * __end__() method. - * TODO When opting in for C++17, address this by changing return - * type of .end()? - */ + * __end__() method. */ /* * Base classes for iterators. @@ -75,10 +70,6 @@ iter_t* thiz () { return static_cast< iter_t *> (this); } public: - /* TODO: - * Port operators below to use hb_enable_if to sniff which method implements - * an operator and use it, and remove hb_iter_fallback_mixin_t completely. */ - /* Operators. */ iter_t iter () const { return *thiz(); } iter_t operator + () const { return *thiz(); } @@ -87,11 +78,10 @@ explicit operator bool () const { return thiz()->__more__ (); } unsigned len () const { return thiz()->__len__ (); } /* The following can only be enabled if item_t is reference type. Otherwise - * it will be returning pointer to temporary rvalue. - * TODO Use a wrapper return type to fix for non-reference type. */ + * it will be returning pointer to temporary rvalue. */ template - hb_remove_reference* operator -> () const { return hb_addressof (**thiz()); } + hb_enable_if (std::is_reference::value)> + hb_remove_reference* operator -> () const { return std::addressof (**thiz()); } item_t operator * () const { return thiz()->__item__ (); } item_t operator * () { return thiz()->__item__ (); } item_t operator [] (unsigned i) const { return thiz()->__item_at__ (i); } @@ -162,7 +152,7 @@ { template hb_iter_type operator () (T&& c) const - { return hb_deref (hb_forward (c)).iter (); } + { return hb_deref (std::forward (c)).iter (); } /* Specialization for C arrays. */ @@ -289,7 +279,7 @@ { private: template >))> + hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference))> static hb_true_type impl (hb_priority<2>); template static auto impl (hb_priority<1>) -> decltype (hb_declval (Iter2) >> hb_declval (Item &), hb_true_type ()); @@ -353,7 +343,7 @@ template static inline auto -operator | (Lhs&& lhs, Rhs&& rhs) HB_AUTO_RETURN (hb_forward (rhs) (hb_forward (lhs))) +operator | (Lhs&& lhs, Rhs&& rhs) HB_AUTO_RETURN (std::forward (rhs) (std::forward (lhs))) /* hb_map(), hb_filter(), hb_reduce() */ @@ -581,6 +571,91 @@ } HB_FUNCOBJ (hb_zip); +/* hb_concat() */ + +template +struct hb_concat_iter_t : + hb_iter_t, typename A::item_t> +{ + hb_concat_iter_t () {} + hb_concat_iter_t (A& a, B& b) : a (a), b (b) {} + hb_concat_iter_t (const A& a, const B& b) : a (a), b (b) {} + + + typedef typename A::item_t __item_t__; + static constexpr bool is_random_access_iterator = + A::is_random_access_iterator && + B::is_random_access_iterator; + static constexpr bool is_sorted_iterator = false; + + __item_t__ __item__ () const + { + if (!a) + return *b; + return *a; + } + + __item_t__ __item_at__ (unsigned i) const + { + unsigned a_len = a.len (); + if (i < a_len) + return a[i]; + return b[i - a_len]; + } + + bool __more__ () const { return bool (a) || bool (b); } + + unsigned __len__ () const { return a.len () + b.len (); } + + void __next__ () + { + if (a) + ++a; + else + ++b; + } + + void __forward__ (unsigned n) + { + if (!n) return; + if (!is_random_access_iterator) { + while (n-- && *this) { + (*this)++; + } + return; + } + + unsigned a_len = a.len (); + if (n > a_len) { + n -= a_len; + a.__forward__ (a_len); + b.__forward__ (n); + } else { + a.__forward__ (n); + } + } + + hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a.end (), b.end ()); } + bool operator != (const hb_concat_iter_t& o) const + { + return a != o.a + || b != o.b; + } + + private: + A a; + B b; +}; +struct +{ HB_PARTIALIZE(2); + template + hb_concat_iter_t, hb_iter_type> + operator () (A&& a, B&& b) const + { return hb_concat_iter_t, hb_iter_type> (hb_iter (a), hb_iter (b)); } +} +HB_FUNCOBJ (hb_concat); + /* hb_apply() */ template @@ -674,8 +749,8 @@ template auto inc (hb_type_identity s, hb_priority<1>) - -> hb_void_t (s), hb_declval ()))> - { v = hb_invoke (hb_forward (s), v); } + -> hb_void_t (s), hb_declval ()))> + { v = hb_invoke (std::forward (s), v); } void inc (S s, hb_priority<0>) @@ -874,7 +949,7 @@ Proj&& f = hb_identity) const { for (auto it = hb_iter (c); it; ++it) - if (!hb_match (hb_forward (p), hb_get (hb_forward (f), *it))) + if (!hb_match (std::forward (p), hb_get (std::forward (f), *it))) return false; return true; } @@ -891,7 +966,7 @@ Proj&& f = hb_identity) const { for (auto it = hb_iter (c); it; ++it) - if (hb_match (hb_forward (p), hb_get (hb_forward (f), *it))) + if (hb_match (std::forward (p), hb_get (std::forward (f), *it))) return true; return false; } @@ -908,7 +983,7 @@ Proj&& f = hb_identity) const { for (auto it = hb_iter (c); it; ++it) - if (hb_match (hb_forward (p), hb_get (hb_forward (f), *it))) + if (hb_match (std::forward (p), hb_get (std::forward (f), *it))) return false; return true; } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-kern.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-kern.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-kern.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-kern.hh 2022-10-10 13:07:22.000000000 +0000 @@ -49,6 +49,10 @@ hb_mask_t kern_mask, bool scale = true) const { + if (!buffer->message (font, "start kern")) + return; + + buffer->unsafe_to_concat (); OT::hb_ot_apply_context_t c (1, font, buffer); c.set_lookup_mask (kern_mask); c.set_lookup_props (OT::LookupFlag::IgnoreMarks); @@ -67,7 +71,8 @@ } skippy_iter.reset (idx, 1); - if (!skippy_iter.next ()) + unsigned unsafe_to; + if (!skippy_iter.next (&unsafe_to)) { idx++; continue; @@ -125,6 +130,8 @@ skip: idx = skippy_iter.idx; } + + (void) buffer->message (font, "end kern"); } const Driver &driver; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-machinery.hh 2022-10-10 13:07:22.000000000 +0000 @@ -176,7 +176,7 @@ void init0 () {} /* Init, when memory is already set to 0. No-op for us. */ void init () { instance.set_relaxed (nullptr); } - void fini () { do_destroy (instance.get ()); } + void fini () { do_destroy (instance.get ()); init (); } void free_instance () { @@ -194,7 +194,8 @@ } const Returned * operator -> () const { return get (); } - const Returned & operator * () const { return *get (); } + template + const U & operator * () const { return *get (); } explicit operator bool () const { return get_stored () != Funcs::get_null (); } template operator const C * () const { return get (); } @@ -242,22 +243,22 @@ static const Stored* get_null () { return &Null (Stored); } static Stored *create (Data *data) { - Stored *p = (Stored *) calloc (1, sizeof (Stored)); + Stored *p = (Stored *) hb_calloc (1, sizeof (Stored)); if (likely (p)) - p->init (data); + p = new (p) Stored (data); return p; } static Stored *create () { - Stored *p = (Stored *) calloc (1, sizeof (Stored)); + Stored *p = (Stored *) hb_calloc (1, sizeof (Stored)); if (likely (p)) - p->init (); + p = new (p) Stored (); return p; } static void destroy (Stored *p) { - p->fini (); - free (p); + p->~Stored (); + hb_free (p); } // private: @@ -272,14 +273,19 @@ hb_face_lazy_loader_t, hb_face_t, WheresFace> {}; -template +template struct hb_table_lazy_loader_t : hb_lazy_loader_t, + hb_table_lazy_loader_t, hb_face_t, WheresFace, hb_blob_t> { static hb_blob_t *create (hb_face_t *face) - { return hb_sanitize_context_t ().reference_table (face); } + { + auto c = hb_sanitize_context_t (); + if (core) + c.set_num_glyphs (0); // So we don't recurse ad infinitum... + return c.reference_table (face); + } static void destroy (hb_blob_t *p) { hb_blob_destroy (p); } static const hb_blob_t *get_null () diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-map.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-map.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-map.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-map.cc 2022-10-10 13:07:22.000000000 +0000 @@ -40,7 +40,7 @@ /** - * hb_map_create: (Xconstructor) + * hb_map_create: * * Creates a new, initially empty map. * @@ -109,7 +109,7 @@ map->fini_shallow (); - free (map); + hb_free (map); } /** @@ -172,6 +172,25 @@ return map->successful; } +/** + * hb_map_copy: + * @map: A map + * + * Allocate a copy of @map. + * + * Return value: Newly-allocated map. + * + * Since: 4.4.0 + **/ +hb_map_t * +hb_map_copy (const hb_map_t *map) +{ + hb_map_t *copy = hb_map_create (); + if (unlikely (!copy)) return nullptr; + copy->resize (map->population); + hb_copy (*map, *copy); + return copy; +} /** * hb_map_set: @@ -188,6 +207,7 @@ hb_codepoint_t key, hb_codepoint_t value) { + /* Immutable-safe. */ map->set (key, value); } @@ -220,6 +240,7 @@ hb_map_del (hb_map_t *map, hb_codepoint_t key) { + /* Immutable-safe. */ map->del (key); } @@ -253,9 +274,6 @@ void hb_map_clear (hb_map_t *map) { - if (unlikely (hb_object_is_immutable (map))) - return; - return map->clear (); } @@ -290,3 +308,40 @@ { return map->get_population (); } + +/** + * hb_map_is_equal: + * @map: A map + * @other: Another map + * + * Tests whether @map and @other are equal (contain the same + * elements). + * + * Return value: %true if the two maps are equal, %false otherwise. + * + * Since: 4.3.0 + **/ +hb_bool_t +hb_map_is_equal (const hb_map_t *map, + const hb_map_t *other) +{ + return map->is_equal (*other); +} + +/** + * hb_map_hash: + * @map: A map + * + * Creates a hash representing @map. + * + * Return value: + * A hash of @map. + * + * Since: 4.4.0 + **/ +HB_EXTERN unsigned int +hb_map_hash (const hb_map_t *map) +{ + return map->hash (); +} + diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-map.h openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-map.h --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-map.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-map.h 2022-10-10 13:07:22.000000000 +0000 @@ -82,6 +82,9 @@ HB_EXTERN hb_bool_t hb_map_allocation_successful (const hb_map_t *map); +HB_EXTERN hb_map_t * +hb_map_copy (const hb_map_t *map); + HB_EXTERN void hb_map_clear (hb_map_t *map); @@ -91,6 +94,13 @@ HB_EXTERN unsigned int hb_map_get_population (const hb_map_t *map); +HB_EXTERN hb_bool_t +hb_map_is_equal (const hb_map_t *map, + const hb_map_t *other); + +HB_EXTERN unsigned int +hb_map_hash (const hb_map_t *map); + HB_EXTERN void hb_map_set (hb_map_t *map, hb_codepoint_t key, diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-map.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-map.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-map.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-map.hh 2022-10-10 13:07:22.000000000 +0000 @@ -34,32 +34,76 @@ * hb_hashmap_t */ +extern HB_INTERNAL const hb_codepoint_t minus_1; + template + bool minus_one = false> struct hb_hashmap_t { - HB_DELETE_COPY_ASSIGN (hb_hashmap_t); hb_hashmap_t () { init (); } ~hb_hashmap_t () { fini (); } - static_assert (hb_is_integral (K) || hb_is_pointer (K), ""); - static_assert (hb_is_integral (V) || hb_is_pointer (V), ""); + hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (population); hb_copy (o, *this); } + hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); } + hb_hashmap_t& operator= (const hb_hashmap_t& o) { resize (population); hb_copy (o, *this); return *this; } + hb_hashmap_t& operator= (hb_hashmap_t&& o) { hb_swap (*this, o); return *this; } + + hb_hashmap_t (std::initializer_list> lst) : hb_hashmap_t () + { + for (auto&& item : lst) + set (item.first, item.second); + } + template + hb_hashmap_t (const Iterable &o) : hb_hashmap_t () + { + auto iter = hb_iter (o); + if (iter.is_random_access_iterator) + resize (hb_len (iter)); + hb_copy (iter, *this); + } struct item_t { K key; + uint32_t hash : 30; + uint32_t is_used_ : 1; + uint32_t is_tombstone_ : 1; V value; - uint32_t hash; - void clear () { key = kINVALID; value = vINVALID; hash = 0; } + bool is_used () const { return is_used_; } + void set_used (bool is_used) { is_used_ = is_used; } + bool is_tombstone () const { return is_tombstone_; } + void set_tombstone (bool is_tombstone) { is_tombstone_ = is_tombstone; } + bool is_real () const { return is_used_ && !is_tombstone_; } + + template + static inline const V& default_value () { return Null(V); }; + template + static inline const V& default_value () + { + static_assert (hb_is_same (V, hb_codepoint_t), ""); + return minus_1; + }; + + void clear () + { + new (std::addressof (key)) K (); + new (std::addressof (value)) V (); + hash = 0; + is_used_ = false; + is_tombstone_ = false; + } bool operator == (const K &o) { return hb_deref (key) == hb_deref (o); } bool operator == (const item_t &o) { return *this == o.key; } - bool is_unused () const { return key == kINVALID; } - bool is_tombstone () const { return key != kINVALID && value == vINVALID; } - bool is_real () const { return key != kINVALID && value != vINVALID; } hb_pair_t get_pair() const { return hb_pair_t (key, value); } + hb_pair_t get_pair_ref() const { return hb_pair_t (key, value); } + + uint32_t total_hash () const + { return (hash * 31) + hb_hash (value); } }; hb_object_header_t header; @@ -70,6 +114,16 @@ unsigned int prime; item_t *items; + friend void swap (hb_hashmap_t& a, hb_hashmap_t& b) + { + if (unlikely (!a.successful || !b.successful)) + return; + hb_swap (a.population, b.population); + hb_swap (a.occupancy, b.occupancy); + hb_swap (a.mask, b.mask); + hb_swap (a.prime, b.prime); + hb_swap (a.items, b.items); + } void init_shallow () { successful = true; @@ -85,8 +139,13 @@ } void fini_shallow () { - free (items); - items = nullptr; + if (likely (items)) { + unsigned size = mask + 1; + for (unsigned i = 0; i < size; i++) + items[i].~item_t (); + hb_free (items); + items = nullptr; + } population = occupancy = 0; } void fini () @@ -103,13 +162,13 @@ bool in_error () const { return !successful; } - bool resize () + bool resize (unsigned new_population = 0) { if (unlikely (!successful)) return false; - unsigned int power = hb_bit_storage (population * 2 + 8); + unsigned int power = hb_bit_storage (hb_max (population, new_population) * 2 + 8); unsigned int new_size = 1u << power; - item_t *new_items = (item_t *) malloc ((size_t) new_size * sizeof (item_t)); + item_t *new_items = (item_t *) hb_malloc ((size_t) new_size * sizeof (item_t)); if (unlikely (!new_items)) { successful = false; @@ -130,45 +189,62 @@ /* Insert back old items. */ if (old_items) for (unsigned int i = 0; i < old_size; i++) + { if (old_items[i].is_real ()) + { set_with_hash (old_items[i].key, old_items[i].hash, - old_items[i].value); + std::move (old_items[i].value)); + } + old_items[i].~item_t (); + } - free (old_items); + hb_free (old_items); return true; } - void set (K key, V value) - { - set_with_hash (key, hb_hash (key), value); - } + template + bool set (K key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward (value)); } - V get (K key) const + const V& get (K key) const { - if (unlikely (!items)) return vINVALID; + if (unlikely (!items)) return item_t::default_value (); unsigned int i = bucket_for (key); - return items[i].is_real () && items[i] == key ? items[i].value : vINVALID; + return items[i].is_real () && items[i] == key ? items[i].value : item_t::default_value (); } - void del (K key) { set (key, vINVALID); } + void del (K key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); } /* Has interface. */ - static constexpr V SENTINEL = vINVALID; - typedef V value_t; + typedef const V& value_t; value_t operator [] (K k) const { return get (k); } - bool has (K k, V *vp = nullptr) const + bool has (K key, const V **vp = nullptr) const { - V v = (*this)[k]; - if (vp) *vp = v; - return v != SENTINEL; + if (unlikely (!items)) + { + if (vp) *vp = &item_t::default_value (); + return false; + } + unsigned int i = bucket_for (key); + if (items[i].is_real () && items[i] == key) + { + if (vp) *vp = &items[i].value; + return true; + } + else + { + if (vp) *vp = &item_t::default_value (); + return false; + } } /* Projection. */ V operator () (K k) const { return get (k); } void clear () { + if (unlikely (!successful)) return; + if (items) for (auto &_ : hb_iter (items, mask + 1)) _.clear (); @@ -179,6 +255,28 @@ bool is_empty () const { return population == 0; } explicit operator bool () const { return !is_empty (); } + uint32_t hash () const + { + uint32_t h = 0; + for (const auto &item : + hb_array (items, mask ? mask + 1 : 0) + | hb_filter (&item_t::is_real)) + h ^= item.total_hash (); + return h; + } + + bool is_equal (const hb_hashmap_t &other) const + { + if (population != other.population) return false; + + for (auto pair : iter ()) + if (get (pair.first) != pair.second) + return false; + + return true; + } + bool operator == (const hb_hashmap_t &other) const { return is_equal (other); } + bool operator != (const hb_hashmap_t &other) const { return !is_equal (other); } + unsigned int get_population () const { return population; } /* @@ -190,6 +288,12 @@ | hb_filter (&item_t::is_real) | hb_map (&item_t::get_pair) ) + auto iter_ref () const HB_AUTO_RETURN + ( + + hb_array (items, mask ? mask + 1 : 0) + | hb_filter (&item_t::is_real) + | hb_map (&item_t::get_pair_ref) + ) auto keys () const HB_AUTO_RETURN ( + hb_array (items, mask ? mask + 1 : 0) @@ -211,43 +315,48 @@ protected: - void set_with_hash (K key, uint32_t hash, V value) + template + bool set_with_hash (K key, uint32_t hash, VV&& value, bool is_delete=false) { - if (unlikely (!successful)) return; - if (unlikely (key == kINVALID)) return; - if ((occupancy + occupancy / 2) >= mask && !resize ()) return; + if (unlikely (!successful)) return false; + if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false; unsigned int i = bucket_for_hash (key, hash); - if (value == vINVALID && items[i].key != key) - return; /* Trying to delete non-existent key. */ + if (is_delete && items[i].key != key) + return true; /* Trying to delete non-existent key. */ - if (!items[i].is_unused ()) + if (items[i].is_used ()) { occupancy--; - if (items[i].is_tombstone ()) + if (!items[i].is_tombstone ()) population--; } items[i].key = key; - items[i].value = value; + items[i].value = std::forward (value); items[i].hash = hash; + items[i].set_used (true); + items[i].set_tombstone (is_delete); occupancy++; - if (!items[i].is_tombstone ()) + if (!is_delete) population++; + + return true; } - unsigned int bucket_for (K key) const + unsigned int bucket_for (const K &key) const { return bucket_for_hash (key, hb_hash (key)); } - unsigned int bucket_for_hash (K key, uint32_t hash) const + unsigned int bucket_for_hash (const K &key, uint32_t hash) const { + hash &= 0x3FFFFFFF; // We only store lower 30bit of hash unsigned int i = hash % prime; unsigned int step = 0; unsigned int tombstone = (unsigned) -1; - while (!items[i].is_unused ()) + while (items[i].is_used ()) { if (items[i].hash == hash && items[i] == key) return i; @@ -316,8 +425,22 @@ struct hb_map_t : hb_hashmap_t {}; + true> +{ + using hashmap = hb_hashmap_t; + ~hb_map_t () = default; + hb_map_t () : hashmap () {} + hb_map_t (const hb_map_t &o) : hashmap ((hashmap &) o) {} + hb_map_t (hb_map_t &&o) : hashmap (std::move ((hashmap &) o)) {} + hb_map_t& operator= (const hb_map_t&) = default; + hb_map_t& operator= (hb_map_t&&) = default; + hb_map_t (std::initializer_list> lst) : hashmap (lst) {} + template + hb_map_t (const Iterable &o) : hashmap (o) {} +}; #endif /* HB_MAP_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-meta.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-meta.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-meta.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-meta.hh 2022-10-10 13:07:22.000000000 +0000 @@ -29,6 +29,10 @@ #include "hb.hh" +#include +#include +#include + /* * C++ template meta-programming & fundamentals used with them. @@ -82,33 +86,16 @@ template struct hb_type_identity_t { typedef T type; }; template using hb_type_identity = typename hb_type_identity_t::type; -struct -{ - template constexpr T* - operator () (T& arg) const - { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-align" - /* https://en.cppreference.com/w/cpp/memory/addressof */ - return reinterpret_cast ( - &const_cast ( - reinterpret_cast (arg))); -#pragma GCC diagnostic pop - } -} -HB_FUNCOBJ (hb_addressof); - template static inline T hb_declval (); #define hb_declval(T) (hb_declval ()) -template struct hb_match_const : hb_type_identity_t, hb_bool_constant{}; -template struct hb_match_const : hb_type_identity_t, hb_bool_constant {}; +template struct hb_match_const : hb_type_identity_t, hb_false_type {}; +template struct hb_match_const : hb_type_identity_t, hb_true_type {}; template using hb_remove_const = typename hb_match_const::type; -template using hb_add_const = const T; -#define hb_is_const(T) hb_match_const::value -template struct hb_match_reference : hb_type_identity_t, hb_bool_constant{}; -template struct hb_match_reference : hb_type_identity_t, hb_bool_constant {}; -template struct hb_match_reference : hb_type_identity_t, hb_bool_constant {}; + +template struct hb_match_reference : hb_type_identity_t, hb_false_type {}; +template struct hb_match_reference : hb_type_identity_t, hb_true_type {}; +template struct hb_match_reference : hb_type_identity_t, hb_true_type {}; template using hb_remove_reference = typename hb_match_reference::type; template auto _hb_try_add_lvalue_reference (hb_priority<1>) -> hb_type_identity; template auto _hb_try_add_lvalue_reference (hb_priority<0>) -> hb_type_identity; @@ -116,92 +103,39 @@ template auto _hb_try_add_rvalue_reference (hb_priority<1>) -> hb_type_identity; template auto _hb_try_add_rvalue_reference (hb_priority<0>) -> hb_type_identity; template using hb_add_rvalue_reference = decltype (_hb_try_add_rvalue_reference (hb_prioritize)); -#define hb_is_reference(T) hb_match_reference::value -template struct hb_match_pointer : hb_type_identity_t, hb_bool_constant{}; -template struct hb_match_pointer : hb_type_identity_t, hb_bool_constant {}; + +template struct hb_match_pointer : hb_type_identity_t, hb_false_type {}; +template struct hb_match_pointer : hb_type_identity_t, hb_true_type {}; template using hb_remove_pointer = typename hb_match_pointer::type; template auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity*>; template auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity; template using hb_add_pointer = decltype (_hb_try_add_pointer (hb_prioritize)); -#define hb_is_pointer(T) hb_match_pointer::value /* TODO Add feature-parity to std::decay. */ template using hb_decay = hb_remove_const>; - -template -struct _hb_conditional { typedef T type; }; -template -struct _hb_conditional { typedef F type; }; -template -using hb_conditional = typename _hb_conditional::type; - - -template -struct hb_is_convertible -{ - private: - static constexpr bool from_void = hb_is_same (void, hb_decay); - static constexpr bool to_void = hb_is_same (void, hb_decay ); - static constexpr bool either_void = from_void || to_void; - static constexpr bool both_void = from_void && to_void; - - static hb_true_type impl2 (hb_conditional); - - template - static auto impl (hb_priority<1>) -> decltype (impl2 (hb_declval (T))); - template - static hb_false_type impl (hb_priority<0>); - public: - static constexpr bool value = both_void || - (!either_void && - decltype (impl> (hb_prioritize))::value); -}; -#define hb_is_convertible(From,To) hb_is_convertible::value - -template -using hb_is_base_of = hb_is_convertible *, hb_decay *>; -#define hb_is_base_of(Base,Derived) hb_is_base_of::value +#define hb_is_convertible(From,To) std::is_convertible::value template using hb_is_cr_convertible = hb_bool_constant< hb_is_same (hb_decay, hb_decay) && - (!hb_is_const (From) || hb_is_const (To)) && - (!hb_is_reference (To) || hb_is_const (To) || hb_is_reference (To)) + (!std::is_const::value || std::is_const::value) && + (!std::is_reference::value || std::is_const::value || std::is_reference::value) >; #define hb_is_cr_convertible(From,To) hb_is_cr_convertible::value -/* std::move and std::forward */ - -template -static constexpr hb_remove_reference&& hb_move (T&& t) { return (hb_remove_reference&&) (t); } - -template -static constexpr T&& hb_forward (hb_remove_reference& t) { return (T&&) t; } -template -static constexpr T&& hb_forward (hb_remove_reference&& t) { return (T&&) t; } struct { template constexpr auto - operator () (T&& v) const HB_AUTO_RETURN (hb_forward (v)) + operator () (T&& v) const HB_AUTO_RETURN (std::forward (v)) template constexpr auto operator () (T *v) const HB_AUTO_RETURN (*v) } HB_FUNCOBJ (hb_deref); -struct -{ - template constexpr auto - operator () (T&& v) const HB_AUTO_RETURN (hb_forward (v)) - - template constexpr auto - operator () (T& v) const HB_AUTO_RETURN (hb_addressof (v)) -} -HB_FUNCOBJ (hb_ref); - template struct hb_reference_wrapper { @@ -215,7 +149,7 @@ template struct hb_reference_wrapper { - hb_reference_wrapper (T& v) : v (hb_addressof (v)) {} + hb_reference_wrapper (T& v) : v (std::addressof (v)) {} bool operator == (const hb_reference_wrapper& o) const { return v == o.v; } bool operator != (const hb_reference_wrapper& o) const { return v != o.v; } operator T& () const { return *v; } @@ -226,50 +160,6 @@ /* Type traits */ -template -using hb_is_integral = hb_bool_constant< - hb_is_same (hb_decay, char) || - hb_is_same (hb_decay, signed char) || - hb_is_same (hb_decay, unsigned char) || - hb_is_same (hb_decay, signed int) || - hb_is_same (hb_decay, unsigned int) || - hb_is_same (hb_decay, signed short) || - hb_is_same (hb_decay, unsigned short) || - hb_is_same (hb_decay, signed long) || - hb_is_same (hb_decay, unsigned long) || - hb_is_same (hb_decay, signed long long) || - hb_is_same (hb_decay, unsigned long long) || - false ->; -#define hb_is_integral(T) hb_is_integral::value -template -using hb_is_floating_point = hb_bool_constant< - hb_is_same (hb_decay, float) || - hb_is_same (hb_decay, double) || - hb_is_same (hb_decay, long double) || - false ->; -#define hb_is_floating_point(T) hb_is_floating_point::value -template -using hb_is_arithmetic = hb_bool_constant< - hb_is_integral (T) || - hb_is_floating_point (T) || - false ->; -#define hb_is_arithmetic(T) hb_is_arithmetic::value - - -template -using hb_is_signed = hb_conditional, - hb_false_type>; -#define hb_is_signed(T) hb_is_signed::value -template -using hb_is_unsigned = hb_conditional, - hb_false_type>; -#define hb_is_unsigned(T) hb_is_unsigned::value - template struct hb_int_min; template <> struct hb_int_min : hb_integral_constant {}; template <> struct hb_int_min : hb_integral_constant {}; @@ -282,6 +172,7 @@ template <> struct hb_int_min : hb_integral_constant {}; template <> struct hb_int_min : hb_integral_constant {}; template <> struct hb_int_min : hb_integral_constant {}; +template struct hb_int_min : hb_integral_constant {}; #define hb_int_min(T) hb_int_min::value template struct hb_int_max; template <> struct hb_int_max : hb_integral_constant {}; @@ -297,6 +188,19 @@ template <> struct hb_int_max : hb_integral_constant {}; #define hb_int_max(T) hb_int_max::value +#if defined(__GNUC__) && __GNUC__ < 5 +#define hb_is_trivially_copyable(T) __has_trivial_copy(T) +#define hb_is_trivially_copy_assignable(T) __has_trivial_assign(T) +#define hb_is_trivially_constructible(T) __has_trivial_constructor(T) +#define hb_is_trivially_copy_constructible(T) __has_trivial_copy_constructor(T) +#define hb_is_trivially_destructible(T) __has_trivial_destructor(T) +#else +#define hb_is_trivially_copyable(T) std::is_trivially_copyable::value +#define hb_is_trivially_copy_assignable(T) std::is_trivially_copy_assignable::value +#define hb_is_trivially_constructible(T) std::is_trivially_constructible::value +#define hb_is_trivially_copy_constructible(T) std::is_trivially_copy_constructible::value +#define hb_is_trivially_destructible(T) std::is_trivially_destructible::value +#endif /* Class traits. */ @@ -308,108 +212,6 @@ TypeName(const TypeName&) = delete; \ void operator=(const TypeName&) = delete -template -struct _hb_is_destructible : hb_false_type {}; -template -struct _hb_is_destructible> : hb_true_type {}; -template -using hb_is_destructible = _hb_is_destructible; -#define hb_is_destructible(T) hb_is_destructible::value - -template -struct _hb_is_constructible : hb_false_type {}; -template -struct _hb_is_constructible, Ts...> : hb_true_type {}; -template -using hb_is_constructible = _hb_is_constructible; -#define hb_is_constructible(...) hb_is_constructible<__VA_ARGS__>::value - -template -using hb_is_default_constructible = hb_is_constructible; -#define hb_is_default_constructible(T) hb_is_default_constructible::value - -template -using hb_is_copy_constructible = hb_is_constructible>>; -#define hb_is_copy_constructible(T) hb_is_copy_constructible::value - -template -using hb_is_move_constructible = hb_is_constructible>>; -#define hb_is_move_constructible(T) hb_is_move_constructible::value - -template -struct _hb_is_assignable : hb_false_type {}; -template -struct _hb_is_assignable> : hb_true_type {}; -template -using hb_is_assignable = _hb_is_assignable; -#define hb_is_assignable(T,U) hb_is_assignable::value - -template -using hb_is_copy_assignable = hb_is_assignable, - hb_add_lvalue_reference>>; -#define hb_is_copy_assignable(T) hb_is_copy_assignable::value - -template -using hb_is_move_assignable = hb_is_assignable, - hb_add_rvalue_reference>; -#define hb_is_move_assignable(T) hb_is_move_assignable::value - -/* Trivial versions. */ - -template union hb_trivial { T value; }; - -template -using hb_is_trivially_destructible= hb_is_destructible>; -#define hb_is_trivially_destructible(T) hb_is_trivially_destructible::value - -/* Don't know how to do the following. */ -//template -//using hb_is_trivially_constructible= hb_is_constructible, hb_trivial...>; -//#define hb_is_trivially_constructible(...) hb_is_trivially_constructible<__VA_ARGS__>::value - -template -using hb_is_trivially_default_constructible= hb_is_default_constructible>; -#define hb_is_trivially_default_constructible(T) hb_is_trivially_default_constructible::value - -template -using hb_is_trivially_copy_constructible= hb_is_copy_constructible>; -#define hb_is_trivially_copy_constructible(T) hb_is_trivially_copy_constructible::value - -template -using hb_is_trivially_move_constructible= hb_is_move_constructible>; -#define hb_is_trivially_move_constructible(T) hb_is_trivially_move_constructible::value - -/* Don't know how to do the following. */ -//template -//using hb_is_trivially_assignable= hb_is_assignable, hb_trivial>; -//#define hb_is_trivially_assignable(T,U) hb_is_trivially_assignable::value - -template -using hb_is_trivially_copy_assignable= hb_is_copy_assignable>; -#define hb_is_trivially_copy_assignable(T) hb_is_trivially_copy_assignable::value - -template -using hb_is_trivially_move_assignable= hb_is_move_assignable>; -#define hb_is_trivially_move_assignable(T) hb_is_trivially_move_assignable::value - -template -using hb_is_trivially_copyable= hb_bool_constant< - hb_is_trivially_destructible (T) && - (!hb_is_move_assignable (T) || hb_is_trivially_move_assignable (T)) && - (!hb_is_move_constructible (T) || hb_is_trivially_move_constructible (T)) && - (!hb_is_copy_assignable (T) || hb_is_trivially_copy_assignable (T)) && - (!hb_is_copy_constructible (T) || hb_is_trivially_copy_constructible (T)) && - true ->; -#define hb_is_trivially_copyable(T) hb_is_trivially_copyable::value - -template -using hb_is_trivial= hb_bool_constant< - hb_is_trivially_copyable (T) && - hb_is_trivially_default_constructible (T) ->; -#define hb_is_trivial(T) hb_is_trivial::value - /* hb_unwrap_type (T) * If T has no T::type, returns T. Otherwise calls itself on T::type recursively. */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-mutex.hh 2022-10-10 13:07:22.000000000 +0000 @@ -39,8 +39,7 @@ /* We need external help for these */ -#if defined(HB_MUTEX_IMPL_INIT) \ - && defined(hb_mutex_impl_init) \ +#if defined(hb_mutex_impl_init) \ && defined(hb_mutex_impl_lock) \ && defined(hb_mutex_impl_unlock) \ && defined(hb_mutex_impl_finish) @@ -48,21 +47,19 @@ /* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */ -#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__)) +#elif !defined(HB_NO_MT) && !defined(HB_MUTEX_IMPL_STD_MUTEX) && (defined(HAVE_PTHREAD) || defined(__APPLE__)) #include typedef pthread_mutex_t hb_mutex_impl_t; -#define HB_MUTEX_IMPL_INIT PTHREAD_MUTEX_INITIALIZER #define hb_mutex_impl_init(M) pthread_mutex_init (M, nullptr) #define hb_mutex_impl_lock(M) pthread_mutex_lock (M) #define hb_mutex_impl_unlock(M) pthread_mutex_unlock (M) #define hb_mutex_impl_finish(M) pthread_mutex_destroy (M) -#elif !defined(HB_NO_MT) && defined(_WIN32) +#elif !defined(HB_NO_MT) && !defined(HB_MUTEX_IMPL_STD_MUTEX) && defined(_WIN32) typedef CRITICAL_SECTION hb_mutex_impl_t; -#define HB_MUTEX_IMPL_INIT {0} #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #define hb_mutex_impl_init(M) InitializeCriticalSectionEx (M, 0, 0) #else @@ -73,34 +70,40 @@ #define hb_mutex_impl_finish(M) DeleteCriticalSection (M) -#elif defined(HB_NO_MT) +#elif !defined(HB_NO_MT) + +#include +typedef std::mutex hb_mutex_impl_t; +#define hb_mutex_impl_init(M) HB_STMT_START { new (M) hb_mutex_impl_t; } HB_STMT_END +#define hb_mutex_impl_lock(M) (M)->lock () +#define hb_mutex_impl_unlock(M) (M)->unlock () +#define hb_mutex_impl_finish(M) HB_STMT_START { (M)->~hb_mutex_impl_t(); } HB_STMT_END + + +#else /* defined(HB_NO_MT) */ typedef int hb_mutex_impl_t; -#define HB_MUTEX_IMPL_INIT 0 #define hb_mutex_impl_init(M) HB_STMT_START {} HB_STMT_END #define hb_mutex_impl_lock(M) HB_STMT_START {} HB_STMT_END #define hb_mutex_impl_unlock(M) HB_STMT_START {} HB_STMT_END #define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END -#else - -#error "Could not find any system to define mutex macros." -#error "Check hb-mutex.hh for possible resolutions." - #endif -#define HB_MUTEX_INIT {HB_MUTEX_IMPL_INIT} - struct hb_mutex_t { - hb_mutex_impl_t m; + /* Create space for, but do not initialize m. */ + alignas(hb_mutex_impl_t) char m[sizeof (hb_mutex_impl_t)]; - void init () { hb_mutex_impl_init (&m); } - void lock () { hb_mutex_impl_lock (&m); } - void unlock () { hb_mutex_impl_unlock (&m); } - void fini () { hb_mutex_impl_finish (&m); } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" + void init () { hb_mutex_impl_init ((hb_mutex_impl_t *) m); } + void lock () { hb_mutex_impl_lock ((hb_mutex_impl_t *) m); } + void unlock () { hb_mutex_impl_unlock ((hb_mutex_impl_t *) m); } + void fini () { hb_mutex_impl_finish ((hb_mutex_impl_t *) m); } +#pragma GCC diagnostic pop }; struct hb_lock_t diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-null.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-null.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-null.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-null.hh 2022-10-10 13:07:22.000000000 +0000 @@ -37,10 +37,13 @@ /* Global nul-content Null pool. Enlarge as necessary. */ -#define HB_NULL_POOL_SIZE 384 +#define HB_NULL_POOL_SIZE 448 -/* Use SFINAE to sniff whether T has min_size; in which case return T::null_size, - * otherwise return sizeof(T). */ +/* Use SFINAE to sniff whether T has min_size; in which case return the larger + * of sizeof(T) and T::null_size, otherwise return sizeof(T). + * + * The main purpose of this is to let structs communicate that they are not nullable, + * by defining min_size but *not* null_size. */ /* The hard way... * https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol @@ -49,8 +52,9 @@ template struct _hb_null_size : hb_integral_constant {}; template -struct _hb_null_size> : hb_integral_constant {}; - +struct _hb_null_size> + : hb_integral_constant T::null_size ? sizeof (T) : T::null_size)> {}; template using hb_null_size = _hb_null_size; #define hb_null_size(T) hb_null_size::value @@ -68,6 +72,14 @@ using hb_static_size = _hb_static_size; #define hb_static_size(T) hb_static_size::value +template +struct _hb_min_size : hb_integral_constant {}; +template +struct _hb_min_size> : hb_integral_constant {}; +template +using hb_min_size = _hb_min_size; +#define hb_min_size(T) hb_min_size::value + /* * Null() @@ -96,7 +108,7 @@ /* Specializations for arbitrary-content Null objects expressed in bytes. */ #define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \ } /* Close namespace. */ \ - extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]; \ + extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[hb_null_size (Namespace::Type)]; \ template <> \ struct Null { \ static Namespace::Type const & get_null () { \ @@ -106,7 +118,7 @@ namespace Namespace { \ static_assert (true, "") /* Require semicolon after. */ #define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \ - const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size] + const unsigned char _hb_Null_##Namespace##_##Type[hb_null_size (Namespace::Type)] /* Specializations for arbitrary-content Null objects expressed as struct initializer. */ #define DECLARE_NULL_INSTANCE(Type) \ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-object.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-object.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-object.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-object.hh 2022-10-10 13:07:22.000000000 +0000 @@ -53,7 +53,7 @@ item_t *replace_or_insert (T v, lock_t &l, bool replace) { l.lock (); - item_t *item = items.find (v); + item_t *item = items.lsearch (v); if (item) { if (replace) { item_t old = *item; @@ -76,7 +76,7 @@ void remove (T v, lock_t &l) { l.lock (); - item_t *item = items.find (v); + item_t *item = items.lsearch (v); if (item) { item_t old = *item; @@ -93,7 +93,7 @@ bool find (T v, item_t *i, lock_t &l) { l.lock (); - item_t *item = items.find (v); + item_t *item = items.lsearch (v); if (item) *i = *item; l.unlock (); @@ -140,8 +140,6 @@ * Reference-count. */ -#define HB_REFERENCE_COUNT_INIT {0} - struct hb_reference_count_t { mutable hb_atomic_int_t ref_count; @@ -197,6 +195,8 @@ hb_reference_count_t ref_count; mutable hb_atomic_int_t writable = 0; hb_atomic_ptr_t user_data; + + bool is_inert () const { return !ref_count.get_relaxed (); } }; #define HB_OBJECT_HEADER_STATIC {} @@ -217,7 +217,7 @@ template static inline Type *hb_object_create () { - Type *obj = (Type *) calloc (1, sizeof (Type)); + Type *obj = (Type *) hb_calloc (1, sizeof (Type)); if (unlikely (!obj)) return obj; @@ -234,11 +234,6 @@ obj->header.user_data.init (); } template -static inline bool hb_object_is_inert (const Type *obj) -{ - return unlikely (obj->header.ref_count.is_inert ()); -} -template static inline bool hb_object_is_valid (const Type *obj) { return likely (obj->header.ref_count.is_valid ()); @@ -257,7 +252,7 @@ static inline Type *hb_object_reference (Type *obj) { hb_object_trace (obj, HB_FUNC); - if (unlikely (!obj || hb_object_is_inert (obj))) + if (unlikely (!obj || obj->header.is_inert ())) return obj; assert (hb_object_is_valid (obj)); obj->header.ref_count.inc (); @@ -267,7 +262,7 @@ static inline bool hb_object_destroy (Type *obj) { hb_object_trace (obj, HB_FUNC); - if (unlikely (!obj || hb_object_is_inert (obj))) + if (unlikely (!obj || obj->header.is_inert ())) return false; assert (hb_object_is_valid (obj)); if (obj->header.ref_count.dec () != 1) @@ -284,7 +279,7 @@ if (user_data) { user_data->fini (); - free (user_data); + hb_free (user_data); user_data = nullptr; } } @@ -295,7 +290,7 @@ hb_destroy_func_t destroy, hb_bool_t replace) { - if (unlikely (!obj || hb_object_is_inert (obj))) + if (unlikely (!obj || obj->header.is_inert ())) return false; assert (hb_object_is_valid (obj)); @@ -303,14 +298,14 @@ hb_user_data_array_t *user_data = obj->header.user_data.get (); if (unlikely (!user_data)) { - user_data = (hb_user_data_array_t *) calloc (sizeof (hb_user_data_array_t), 1); + user_data = (hb_user_data_array_t *) hb_calloc (sizeof (hb_user_data_array_t), 1); if (unlikely (!user_data)) return false; user_data->init (); if (unlikely (!obj->header.user_data.cmpexch (nullptr, user_data))) { user_data->fini (); - free (user_data); + hb_free (user_data); goto retry; } } @@ -322,7 +317,7 @@ static inline void *hb_object_get_user_data (Type *obj, hb_user_data_key_t *key) { - if (unlikely (!obj || hb_object_is_inert (obj))) + if (unlikely (!obj || obj->header.is_inert ())) return nullptr; assert (hb_object_is_valid (obj)); hb_user_data_array_t *user_data = obj->header.user_data.get (); diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-open-file.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-open-file.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-open-file.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-open-file.hh 2022-10-10 13:07:22.000000000 +0000 @@ -35,7 +35,6 @@ namespace OT { - /* * * The OpenType Font File @@ -102,7 +101,13 @@ { Tag t; t = tag; - return tables.bfind (t, table_index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX); + /* Use lfind for small fonts; there are fonts that have unsorted table entries; + * those tend to work in other tools, so tolerate them. + * https://github.com/harfbuzz/harfbuzz/issues/3065 */ + if (tables.len < 16) + return tables.lfind (t, table_index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX); + else + return tables.bfind (t, table_index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX); } const TableRecord& get_table_by_tag (hb_tag_t tag) const { @@ -113,44 +118,53 @@ public: - template + template >::value))> bool serialize (hb_serialize_context_t *c, hb_tag_t sfnt_tag, - hb_array_t items) + Iterator it) { TRACE_SERIALIZE (this); /* Alloc 12 for the OTHeader. */ - if (unlikely (!c->extend_min (*this))) return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); /* Write sfntVersion (bytes 0..3). */ sfnt_version = sfnt_tag; /* Take space for numTables, searchRange, entrySelector, RangeShift * and the TableRecords themselves. */ - if (unlikely (!tables.serialize (c, items.length))) return_trace (false); + unsigned num_items = it.len (); + if (unlikely (!tables.serialize (c, num_items))) return_trace (false); const char *dir_end = (const char *) c->head; HBUINT32 *checksum_adjustment = nullptr; /* Write OffsetTables, alloc for and write actual table blobs. */ - for (unsigned int i = 0; i < tables.len; i++) + unsigned i = 0; + for (hb_pair_t entry : it) { - TableRecord &rec = tables.arrayZ[i]; - hb_blob_t *blob = items[i].blob; - rec.tag = items[i].tag; - rec.length = blob->length; - rec.offset.serialize (c, this); + hb_blob_t *blob = entry.second; + unsigned len = blob->length; /* Allocate room for the table and copy it. */ - char *start = (char *) c->allocate_size (rec.length); + char *start = (char *) c->allocate_size (len); if (unlikely (!start)) return false; - if (likely (rec.length)) - memcpy (start, blob->data, rec.length); + TableRecord &rec = tables.arrayZ[i]; + rec.tag = entry.first; + rec.length = len; + rec.offset = 0; + if (unlikely (!c->check_assign (rec.offset, + (unsigned) ((char *) start - (char *) this), + HB_SERIALIZE_ERROR_OFFSET_OVERFLOW))) + return_trace (false); + + if (likely (len)) + memcpy (start, blob->data, len); /* 4-byte alignment. */ c->align (4); const char *end = (const char *) c->head; - if (items[i].tag == HB_OT_TAG_head && + if (entry.first == HB_OT_TAG_head && (unsigned) (end - start) >= head::static_size) { head *h = (head *) start; @@ -159,6 +173,7 @@ } rec.checkSum.set_for_data (start, end - start); + i++; } tables.qsort (); @@ -170,7 +185,7 @@ /* The following line is a slower version of the following block. */ //checksum.set_for_data (this, (const char *) c->head - (const char *) this); checksum.set_for_data (this, dir_end - (const char *) this); - for (unsigned int i = 0; i < items.length; i++) + for (unsigned int i = 0; i < num_items; i++) { TableRecord &rec = tables.arrayZ[i]; checksum = checksum + rec.checkSum; @@ -218,7 +233,7 @@ Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ FixedVersion<>version; /* Version of the TTC Header (1.0), * 0x00010000u */ - LArrayOf> + Array32Of> table; /* Array of offsets to the OffsetTable for each font * from the beginning of the file */ public: @@ -295,7 +310,7 @@ HBINT16 nameOffset; /* Offset from beginning of resource name list * to resource name, -1 means there is none. */ HBUINT8 attrs; /* Resource attributes */ - NNOffsetTo, HBUINT24> + NNOffset24To> offset; /* Offset from beginning of data block to * data for this resource */ HBUINT32 reserved; /* Reserved for handle to resource */ @@ -330,7 +345,7 @@ protected: Tag tag; /* Resource type. */ HBUINT16 resCountM1; /* Number of resources minus 1. */ - NNOffsetTo> + NNOffset16To> resourcesZ; /* Offset from beginning of resource type list * to reference item list for this type. */ public: @@ -386,7 +401,7 @@ HBUINT32 reserved1; /* Reserved for handle to next resource map */ HBUINT16 resreved2; /* Reserved for file reference number */ HBUINT16 attrs; /* Resource fork attribute */ - NNOffsetTo> + NNOffset16To> typeList; /* Offset from beginning of map to * resource type list */ Offset16 nameList; /* Offset from beginning of map to @@ -418,10 +433,10 @@ } protected: - LNNOffsetTo> + NNOffset32To> data; /* Offset from beginning of resource fork * to resource data */ - LNNOffsetTo + NNOffset32To map; /* Offset from beginning of resource fork * to resource map */ HBUINT32 dataLen; /* Length of resource data */ @@ -477,14 +492,15 @@ } } - template + template >::value))> bool serialize_single (hb_serialize_context_t *c, hb_tag_t sfnt_tag, - hb_array_t items) + Iterator items) { TRACE_SERIALIZE (this); assert (sfnt_tag != TTCTag); - if (unlikely (!c->extend_min (*this))) return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); return_trace (u.fontFace.serialize (c, sfnt_tag, items)); } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh 2022-10-10 13:07:22.000000000 +0000 @@ -33,6 +33,7 @@ #include "hb-blob.hh" #include "hb-face.hh" #include "hb-machinery.hh" +#include "hb-meta.hh" #include "hb-subset.hh" @@ -64,7 +65,7 @@ IntType& operator = (Type i) { v = i; return *this; } /* For reason we define cast out operator for signed/unsigned, instead of Type, see: * https://github.com/harfbuzz/harfbuzz/pull/2875/commits/09836013995cab2b9f07577a179ad7b024130467 */ - operator hb_conditional () const { return v; } + operator typename std::conditional::value, signed, unsigned>::type () const { return v; } bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } bool operator != (const IntType &o) const { return !(*this == o); } @@ -86,7 +87,7 @@ return pb->cmp (*pa); } template ::value && sizeof (Type2) < sizeof (int) && sizeof (Type) < sizeof (int))> int cmp (Type2 a) const @@ -122,6 +123,15 @@ * Works for unsigned, but not signed, since we rely on compiler for sign-extension. */ typedef IntType HBUINT24; /* 24-bit unsigned integer. */ +/* 15-bit unsigned number; top bit used for extension. */ +struct HBUINT15 : HBUINT16 +{ + /* TODO Flesh out; actually mask top bit. */ + HBUINT15& operator = (uint16_t i ) { HBUINT16::operator= (i); return *this; } + public: + DEFINE_SIZE_STATIC (2); +}; + /* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */ typedef HBINT16 FWORD; @@ -182,9 +192,9 @@ }; /* Glyph index number, same as uint16 (length = 16 bits) */ -struct HBGlyphID : HBUINT16 +struct HBGlyphID16 : HBUINT16 { - HBGlyphID& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; } + HBGlyphID16& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; } }; /* Script/language-system/feature index */ @@ -196,6 +206,12 @@ typedef Index NameID; +struct VarIdx : HBUINT32 { + static constexpr unsigned NO_VARIATION = 0xFFFFFFFFu; + VarIdx& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; } +}; +DECLARE_NULL_NAMESPACE_BYTES (OT, VarIdx); + /* Offset, Null offset = 0 */ template struct Offset : Type @@ -206,18 +222,12 @@ bool is_null () const { return has_null && 0 == *this; } - void *serialize (hb_serialize_context_t *c, const void *base) - { - void *t = c->start_embed (); - c->check_assign (*this, (unsigned) ((char *) t - (char *) base)); - return t; - } - public: DEFINE_SIZE_STATIC (sizeof (Type)); }; typedef Offset Offset16; +typedef Offset Offset24; typedef Offset Offset32; @@ -287,7 +297,7 @@ static Type *get_crap () { return &Crap (Type); } }; -template +template struct OffsetTo : Offset { HB_DELETE_COPY_ASSIGN (OffsetTo); @@ -319,10 +329,6 @@ hb_enable_if (hb_is_convertible (Base, void *))> friend Type& operator + (OffsetTo &offset, Base &&base) { return offset ((void *) base); } - Type& serialize (hb_serialize_context_t *c, const void *base) - { - return * (Type *) Offset::serialize (c, base); - } template bool serialize_subset (hb_subset_context_t *c, const OffsetTo& src, @@ -336,7 +342,7 @@ s->push (); - bool ret = c->dispatch (src_base+src, hb_forward (ds)...); + bool ret = c->dispatch (src_base+src, std::forward (ds)...); if (ret || !has_null) s->add_link (*this, s->pop_pack ()); @@ -346,6 +352,23 @@ return ret; } + + template + bool serialize_serialize (hb_serialize_context_t *c, Ts&&... ds) + { + *this = 0; + + Type* obj = c->push (); + bool ret = obj->serialize (c, std::forward (ds)...); + + if (ret) + c->add_link (*this, c->pop_pack ()); + else + c->pop_discard (); + + return ret; + } + /* TODO: Somehow merge this with previous function into a serialize_dispatch(). */ /* Workaround clang bug: https://bugs.llvm.org/show_bug.cgi?id=23029 * Can't compile: whence = hb_serialize_context_t::Head followed by Ts&&... @@ -362,7 +385,7 @@ c->push (); - bool ret = c->copy (src_base+src, hb_forward (ds)...); + bool ret = c->copy (src_base+src, std::forward (ds)...); c->add_link (*this, c->pop_pack (), whence, dst_bias); @@ -378,7 +401,7 @@ TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); if (unlikely (this->is_null ())) return_trace (true); - if (unlikely (!c->check_range (base, *this))) return_trace (false); + if (unlikely ((const char *) base + (unsigned) *this < (const char *) base)) return_trace (false); return_trace (true); } @@ -388,7 +411,7 @@ TRACE_SANITIZE (this); return_trace (sanitize_shallow (c, base) && (this->is_null () || - c->dispatch (StructAtOffset (base, *this), hb_forward (ds)...) || + c->dispatch (StructAtOffset (base, *this), std::forward (ds)...) || neuter (c))); } @@ -401,12 +424,14 @@ DEFINE_SIZE_STATIC (sizeof (OffsetType)); }; /* Partial specializations. */ -template -using LOffsetTo = OffsetTo; -template -using NNOffsetTo = OffsetTo; -template -using LNNOffsetTo = LOffsetTo; +template using Offset16To = OffsetTo; +template using Offset24To = OffsetTo; +template using Offset32To = OffsetTo; + +template using NNOffsetTo = OffsetTo; +template using NNOffset16To = Offset16To; +template using NNOffset24To = Offset24To; +template using NNOffset32To = Offset32To; /* @@ -453,8 +478,10 @@ const Type &lsearch (unsigned int len, const T &x, const Type ¬_found = Null (Type)) const { return *as_array (len).lsearch (x, ¬_found); } template - bool lfind (unsigned int len, const T &x, unsigned *pos = nullptr) const - { return as_array (len).lfind (x, pos); } + bool lfind (unsigned int len, const T &x, unsigned int *i = nullptr, + hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE, + unsigned int to_store = (unsigned int) -1) const + { return as_array (len).lfind (x, i, not_found, to_store); } void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1) { as_array (len).qsort (start, end); } @@ -462,7 +489,7 @@ bool serialize (hb_serialize_context_t *c, unsigned int items_len) { TRACE_SERIALIZE (this); - if (unlikely (!c->extend (*this, items_len))) return_trace (false); + if (unlikely (!c->extend (this, items_len))) return_trace (false); return_trace (true); } template dispatch (arrayZ[i], hb_forward (ds)...))) + if (unlikely (!c->dispatch (arrayZ[i], std::forward (ds)...))) return_trace (false); return_trace (true); } @@ -513,11 +540,11 @@ /* Unsized array of offset's */ template -using UnsizedOffsetArrayOf = UnsizedArrayOf>; +using UnsizedArray16OfOffsetTo = UnsizedArrayOf>; /* Unsized array of offsets relative to the beginning of the array itself. */ template -struct UnsizedOffsetListOf : UnsizedOffsetArrayOf +struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo { const Type& operator [] (int i_) const { @@ -538,8 +565,8 @@ bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const { TRACE_SANITIZE (this); - return_trace ((UnsizedOffsetArrayOf - ::sanitize (c, count, this, hb_forward (ds)...))); + return_trace ((UnsizedArray16OfOffsetTo + ::sanitize (c, count, this, std::forward (ds)...))); } }; @@ -562,14 +589,14 @@ { return *as_array (len).bsearch (x, ¬_found); } template bool bfind (unsigned int len, const T &x, unsigned int *i = nullptr, - hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, + hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE, unsigned int to_store = (unsigned int) -1) const { return as_array (len).bfind (x, i, not_found, to_store); } }; /* An array with a number of elements. */ -template +template struct ArrayOf { typedef Type item_t; @@ -617,17 +644,32 @@ hb_array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) { return as_array ().sub_array (start_offset, count); } - hb_success_t serialize (hb_serialize_context_t *c, unsigned items_len) + template + Type &lsearch (const T &x, Type ¬_found = Crap (Type)) + { return *as_array ().lsearch (x, ¬_found); } + template + const Type &lsearch (const T &x, const Type ¬_found = Null (Type)) const + { return *as_array ().lsearch (x, ¬_found); } + template + bool lfind (const T &x, unsigned int *i = nullptr, + hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE, + unsigned int to_store = (unsigned int) -1) const + { return as_array ().lfind (x, i, not_found, to_store); } + + void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1) + { as_array ().qsort (start, end); } + + HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len) { TRACE_SERIALIZE (this); - if (unlikely (!c->extend_min (*this))) return_trace (false); - c->check_assign (len, items_len); - if (unlikely (!c->extend (*this))) return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); + c->check_assign (len, items_len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW); + if (unlikely (!c->extend (this))) return_trace (false); return_trace (true); } template - hb_success_t serialize (hb_serialize_context_t *c, Iterator items) + HB_NODISCARD bool serialize (hb_serialize_context_t *c, Iterator items) { TRACE_SERIALIZE (this); unsigned count = items.len (); @@ -643,7 +685,7 @@ { TRACE_SERIALIZE (this); len++; - if (unlikely (!len || !c->extend (*this))) + if (unlikely (!len || !c->extend (this))) { len--; return_trace (nullptr); @@ -656,7 +698,7 @@ TRACE_SERIALIZE (this); auto *out = c->start_embed (this); if (unlikely (!c->extend_min (out))) return_trace (nullptr); - c->check_assign (out->len, len); + c->check_assign (out->len, len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW); if (unlikely (!as_array ().copy (c))) return_trace (nullptr); return_trace (out); } @@ -666,27 +708,14 @@ { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); - if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true); + if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true); unsigned int count = len; for (unsigned int i = 0; i < count; i++) - if (unlikely (!c->dispatch (arrayZ[i], hb_forward (ds)...))) + if (unlikely (!c->dispatch (arrayZ[i], std::forward (ds)...))) return_trace (false); return_trace (true); } - template - Type &lsearch (const T &x, Type ¬_found = Crap (Type)) - { return *as_array ().lsearch (x, ¬_found); } - template - const Type &lsearch (const T &x, const Type ¬_found = Null (Type)) const - { return *as_array ().lsearch (x, ¬_found); } - template - bool lfind (const T &x, unsigned *pos = nullptr) const - { return as_array ().lfind (x, pos); } - - void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1) - { as_array ().qsort (start, end); } - bool sanitize_shallow (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -699,21 +728,18 @@ public: DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); }; -template -using LArrayOf = ArrayOf; +template using Array16Of = ArrayOf; +template using Array32Of = ArrayOf; using PString = ArrayOf; /* Array of Offset's */ -template -using OffsetArrayOf = ArrayOf>; -template -using LOffsetArrayOf = ArrayOf>; -template -using LOffsetLArrayOf = ArrayOf, HBUINT32>; +template using Array16OfOffset16To = ArrayOf, HBUINT16>; +template using Array16OfOffset32To = ArrayOf, HBUINT16>; +template using Array32OfOffset32To = ArrayOf, HBUINT32>; /* Array of offsets relative to the beginning of the array itself. */ template -struct OffsetListOf : OffsetArrayOf +struct List16OfOffset16To : Array16OfOffset16To { const Type& operator [] (int i_) const { @@ -731,7 +757,7 @@ bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - struct OffsetListOf *out = c->serializer->embed (*this); + struct List16OfOffset16To *out = c->serializer->embed (*this); if (unlikely (!out)) return_trace (false); unsigned int count = this->len; for (unsigned int i = 0; i < count; i++) @@ -743,7 +769,7 @@ bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); - return_trace (OffsetArrayOf::sanitize (c, this, hb_forward (ds)...)); + return_trace (Array16OfOffset16To::sanitize (c, this, std::forward (ds)...)); } }; @@ -786,9 +812,9 @@ bool serialize (hb_serialize_context_t *c, unsigned int items_len) { TRACE_SERIALIZE (this); - if (unlikely (!c->extend_min (*this))) return_trace (false); - c->check_assign (lenP1, items_len + 1); - if (unlikely (!c->extend (*this))) return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); + c->check_assign (lenP1, items_len + 1, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW); + if (unlikely (!c->extend (this))) return_trace (false); return_trace (true); } template dispatch (arrayZ[i], hb_forward (ds)...))) + if (unlikely (!c->dispatch (arrayZ[i], std::forward (ds)...))) return_trace (false); return_trace (true); } @@ -859,9 +885,10 @@ { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); + if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true); unsigned int count = lenM1 + 1; for (unsigned int i = 0; i < count; i++) - if (unlikely (!c->dispatch (arrayZ[i], hb_forward (ds)...))) + if (unlikely (!c->dispatch (arrayZ[i], std::forward (ds)...))) return_trace (false); return_trace (true); } @@ -882,7 +909,7 @@ }; /* An array with sorted elements. Supports binary searching. */ -template +template struct SortedArrayOf : ArrayOf { hb_sorted_array_t< Type> as_array () { return hb_sorted_array (this->arrayZ, this->len); } @@ -928,11 +955,14 @@ { return *as_array ().bsearch (x, ¬_found); } template bool bfind (const T &x, unsigned int *i = nullptr, - hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, + hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE, unsigned int to_store = (unsigned int) -1) const { return as_array ().bfind (x, i, not_found, to_store); } }; +template using SortedArray16Of = SortedArrayOf; +template using SortedArray32Of = SortedArrayOf; + /* * Binary-search arrays */ @@ -1041,10 +1071,10 @@ { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return_trace (false); - if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true); + if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true); unsigned int count = get_length (); for (unsigned int i = 0; i < count; i++) - if (unlikely (!(*this)[i].sanitize (c, hb_forward (ds)...))) + if (unlikely (!(*this)[i].sanitize (c, std::forward (ds)...))) return_trace (false); return_trace (true); } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.cc 2022-10-10 13:07:22.000000000 +0000 @@ -311,10 +311,8 @@ struct cff1_extents_param_t { - void init (const OT::cff1::accelerator_t *_cff) + cff1_extents_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff) { - path_open = false; - cff = _cff; bounds.init (); } @@ -322,7 +320,7 @@ void end_path () { path_open = false; } bool is_path_open () const { return path_open; } - bool path_open; + bool path_open = false; bounds_t bounds; const OT::cff1::accelerator_t *cff; @@ -395,12 +393,11 @@ if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false; unsigned int fd = cff->fdSelect->get_fd (glyph); - cff1_cs_interpreter_t interp; - const byte_str_t str = (*cff->charStrings)[glyph]; - interp.env.init (str, *cff, fd); - interp.env.set_in_seac (in_seac); - cff1_extents_param_t param; - param.init (cff); + const hb_ubytes_t str = (*cff->charStrings)[glyph]; + cff1_cs_interp_env_t env (str, *cff, fd); + env.set_in_seac (in_seac); + cff1_cs_interpreter_t interp (env); + cff1_extents_param_t param (cff); if (unlikely (!interp.interpret (param))) return false; bounds = param.bounds; return true; @@ -442,13 +439,12 @@ return true; } -#ifdef HB_EXPERIMENTAL_API struct cff1_path_param_t { cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_, - draw_helper_t &draw_helper_, point_t *delta_) + hb_draw_session_t &draw_session_, point_t *delta_) { - draw_helper = &draw_helper_; + draw_session = &draw_session_; cff = cff_; font = font_; delta = delta_; @@ -458,14 +454,14 @@ { point_t point = p; if (delta) point.move (*delta); - draw_helper->move_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ())); + draw_session->move_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ())); } void line_to (const point_t &p) { point_t point = p; if (delta) point.move (*delta); - draw_helper->line_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ())); + draw_session->line_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ())); } void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3) @@ -477,15 +473,15 @@ point2.move (*delta); point3.move (*delta); } - draw_helper->cubic_to (font->em_scalef_x (point1.x.to_real ()), font->em_scalef_y (point1.y.to_real ()), - font->em_scalef_x (point2.x.to_real ()), font->em_scalef_y (point2.y.to_real ()), - font->em_scalef_x (point3.x.to_real ()), font->em_scalef_y (point3.y.to_real ())); + draw_session->cubic_to (font->em_fscalef_x (point1.x.to_real ()), font->em_fscalef_y (point1.y.to_real ()), + font->em_fscalef_x (point2.x.to_real ()), font->em_fscalef_y (point2.y.to_real ()), + font->em_fscalef_x (point3.x.to_real ()), font->em_fscalef_y (point3.y.to_real ())); } - void end_path () { draw_helper->end_path (); } + void end_path () { draw_session->close_path (); } hb_font_t *font; - draw_helper_t *draw_helper; + hb_draw_session_t *draw_session; point_t *delta; const OT::cff1::accelerator_t *cff; @@ -513,7 +509,7 @@ }; static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph, - draw_helper_t &draw_helper, bool in_seac = false, point_t *delta = nullptr); + hb_draw_session_t &draw_session, bool in_seac = false, point_t *delta = nullptr); struct cff1_cs_opset_path_t : cff1_cs_opset_t { @@ -530,23 +526,23 @@ hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ()); if (unlikely (!(!env.in_seac && base && accent - && _get_path (param.cff, param.font, base, *param.draw_helper, true) - && _get_path (param.cff, param.font, accent, *param.draw_helper, true, &delta)))) + && _get_path (param.cff, param.font, base, *param.draw_session, true) + && _get_path (param.cff, param.font, accent, *param.draw_session, true, &delta)))) env.set_error (); } }; bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph, - draw_helper_t &draw_helper, bool in_seac, point_t *delta) + hb_draw_session_t &draw_session, bool in_seac, point_t *delta) { if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false; unsigned int fd = cff->fdSelect->get_fd (glyph); - cff1_cs_interpreter_t interp; - const byte_str_t str = (*cff->charStrings)[glyph]; - interp.env.init (str, *cff, fd); - interp.env.set_in_seac (in_seac); - cff1_path_param_t param (cff, font, draw_helper, delta); + const hb_ubytes_t str = (*cff->charStrings)[glyph]; + cff1_cs_interp_env_t env (str, *cff, fd); + env.set_in_seac (in_seac); + cff1_cs_interpreter_t interp (env); + cff1_path_param_t param (cff, font, draw_session, delta); if (unlikely (!interp.interpret (param))) return false; /* Let's end the path specially since it is called inside seac also */ @@ -555,31 +551,25 @@ return true; } -bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const +bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const { #ifdef HB_NO_OT_FONT_CFF /* XXX Remove check when this code moves to .hh file. */ return true; #endif - return _get_path (this, font, glyph, draw_helper); + return _get_path (this, font, glyph, draw_session); } -#endif struct get_seac_param_t { - void init (const OT::cff1::accelerator_t *_cff) - { - cff = _cff; - base = 0; - accent = 0; - } + get_seac_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff) {} bool has_seac () const { return base && accent; } const OT::cff1::accelerator_t *cff; - hb_codepoint_t base; - hb_codepoint_t accent; + hb_codepoint_t base = 0; + hb_codepoint_t accent = 0; }; struct cff1_cs_opset_seac_t : cff1_cs_opset_t @@ -600,11 +590,10 @@ if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false; unsigned int fd = fdSelect->get_fd (glyph); - cff1_cs_interpreter_t interp; - const byte_str_t str = (*charStrings)[glyph]; - interp.env.init (str, *this, fd); - get_seac_param_t param; - param.init (this); + const hb_ubytes_t str = (*charStrings)[glyph]; + cff1_cs_interp_env_t env (str, *this, fd); + cff1_cs_interpreter_t interp (env); + get_seac_param_t param (this); if (unlikely (!interp.interpret (param))) return false; if (param.has_seac ()) diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -187,7 +187,7 @@ const hb_vector_t& supp_codes) { TRACE_SERIALIZE (this); - Encoding *dest = c->extend_min (*this); + Encoding *dest = c->extend_min (this); if (unlikely (!dest)) return_trace (false); dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0); switch (format) { @@ -318,14 +318,21 @@ return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c)); } - hb_codepoint_t get_sid (hb_codepoint_t glyph) const + hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const { + if (unlikely (glyph >= num_glyphs)) return 0; if (glyph == 0) return 0; else return sids[glyph - 1]; } + void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const + { + for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++) + mapping->set (gid, sids[gid - 1]); + } + hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const { if (sid == 0) @@ -381,20 +388,38 @@ return_trace (true); } - hb_codepoint_t get_sid (hb_codepoint_t glyph) const + hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const { + if (unlikely (glyph >= num_glyphs)) return 0; if (glyph == 0) return 0; glyph--; for (unsigned int i = 0;; i++) { if (glyph <= ranges[i].nLeft) - return (hb_codepoint_t)ranges[i].first + glyph; + return (hb_codepoint_t) ranges[i].first + glyph; glyph -= (ranges[i].nLeft + 1); } return 0; } + void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const + { + hb_codepoint_t gid = 1; + if (gid >= num_glyphs) + return; + for (unsigned i = 0;; i++) + { + hb_codepoint_t sid = ranges[i].first; + unsigned count = ranges[i].nLeft + 1; + for (unsigned j = 0; j < count; j++) + mapping->set (gid++, sid++); + + if (gid >= num_glyphs) + break; + } + } + hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const { if (sid == 0) return 0; @@ -457,7 +482,7 @@ const hb_vector_t& sid_ranges) { TRACE_SERIALIZE (this); - Charset *dest = c->extend_min (*this); + Charset *dest = c->extend_min (this); if (unlikely (!dest)) return_trace (false); dest->format = format; switch (format) @@ -521,16 +546,26 @@ hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const { - if (unlikely (glyph >= num_glyphs)) return 0; switch (format) { - case 0: return u.format0.get_sid (glyph); - case 1: return u.format1.get_sid (glyph); - case 2: return u.format2.get_sid (glyph); + case 0: return u.format0.get_sid (glyph, num_glyphs); + case 1: return u.format1.get_sid (glyph, num_glyphs); + case 2: return u.format2.get_sid (glyph, num_glyphs); default:return 0; } } + void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const + { + switch (format) + { + case 0: u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return; + case 1: u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return; + case 2: u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return; + default:return; + } + } + hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const { switch (format) @@ -602,6 +637,8 @@ { cff1_top_dict_interp_env_t () : num_interp_env_t(), prev_offset(0), last_offset(0) {} + cff1_top_dict_interp_env_t (const hb_ubytes_t &bytes) + : num_interp_env_t(bytes), prev_offset(0), last_offset(0) {} unsigned int prev_offset; unsigned int last_offset; @@ -713,6 +750,7 @@ case OpCode_Notice: case OpCode_Copyright: case OpCode_FullName: + case OpCode_FontName: case OpCode_FamilyName: case OpCode_Weight: case OpCode_PostScript: @@ -1023,11 +1061,10 @@ { fini (); return; } { /* parse top dict */ - const byte_str_t topDictStr = (*topDictIndex)[0]; + const hb_ubytes_t topDictStr = (*topDictIndex)[0]; if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; } - cff1_top_dict_interpreter_t top_interp; - top_interp.env.init (topDictStr); - topDict.init (); + cff1_top_dict_interp_env_t env (topDictStr); + cff1_top_dict_interpreter_t top_interp (env); if (unlikely (!top_interp.interpret (topDict))) { fini (); return; } } @@ -1097,20 +1134,21 @@ { for (unsigned int i = 0; i < fdCount; i++) { - byte_str_t fontDictStr = (*fdArray)[i]; + hb_ubytes_t fontDictStr = (*fdArray)[i]; if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; } cff1_font_dict_values_t *font; - cff1_font_dict_interpreter_t font_interp; - font_interp.env.init (fontDictStr); + cff1_top_dict_interp_env_t env (fontDictStr); + cff1_font_dict_interpreter_t font_interp (env); font = fontDicts.push (); - if (unlikely (font == &Crap (cff1_font_dict_values_t))) { fini (); return; } + if (unlikely (fontDicts.in_error ())) { fini (); return; } + font->init (); if (unlikely (!font_interp.interpret (*font))) { fini (); return; } PRIVDICTVAL *priv = &privateDicts[i]; - const byte_str_t privDictStr (StructAtOffset (cff, font->privateDictInfo.offset), font->privateDictInfo.size); + const hb_ubytes_t privDictStr = StructAtOffset (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; } - dict_interpreter_t priv_interp; - priv_interp.env.init (privDictStr); + num_interp_env_t env2 (privDictStr); + dict_interpreter_t priv_interp (env2); priv->init (); if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; } @@ -1125,10 +1163,10 @@ cff1_top_dict_values_t *font = &topDict; PRIVDICTVAL *priv = &privateDicts[0]; - const byte_str_t privDictStr (StructAtOffset (cff, font->privateDictInfo.offset), font->privateDictInfo.size); + const hb_ubytes_t privDictStr = StructAtOffset (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; } - dict_interpreter_t priv_interp; - priv_interp.env.init (privDictStr); + num_interp_env_t env (privDictStr); + dict_interpreter_t priv_interp (env); priv->init (); if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; } @@ -1143,8 +1181,8 @@ { sc.end_processing (); topDict.fini (); - fontDicts.fini_deep (); - privateDicts.fini_deep (); + fontDicts.fini (); + privateDicts.fini (); hb_blob_destroy (blob); blob = nullptr; } @@ -1193,6 +1231,19 @@ } } + hb_map_t *create_glyph_to_sid_map () const + { + if (charset != &Null (Charset)) + { + hb_map_t *mapping = hb_map_create (); + mapping->set (0, 0); + charset->collect_glyph_to_sid_map (mapping, num_glyphs); + return mapping; + } + else + return nullptr; + } + hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const { if (charset != &Null (Charset)) @@ -1244,60 +1295,49 @@ } protected: - hb_blob_t *blob; + hb_blob_t *blob = nullptr; hb_sanitize_context_t sc; public: - const Encoding *encoding; - const Charset *charset; - const CFF1NameIndex *nameIndex; - const CFF1TopDictIndex *topDictIndex; - const CFF1StringIndex *stringIndex; - const CFF1Subrs *globalSubrs; - const CFF1CharStrings *charStrings; - const CFF1FDArray *fdArray; - const CFF1FDSelect *fdSelect; - unsigned int fdCount; + const Encoding *encoding = nullptr; + const Charset *charset = nullptr; + const CFF1NameIndex *nameIndex = nullptr; + const CFF1TopDictIndex *topDictIndex = nullptr; + const CFF1StringIndex *stringIndex = nullptr; + const CFF1Subrs *globalSubrs = nullptr; + const CFF1CharStrings *charStrings = nullptr; + const CFF1FDArray *fdArray = nullptr; + const CFF1FDSelect *fdSelect = nullptr; + unsigned int fdCount = 0; cff1_top_dict_values_t topDict; hb_vector_t fontDicts; hb_vector_t privateDicts; - unsigned int num_glyphs; + unsigned int num_glyphs = 0; }; struct accelerator_t : accelerator_templ_t { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { SUPER::init (face); + glyph_names.set_relaxed (nullptr); + if (!is_valid ()) return; if (is_CID ()) return; - /* fill glyph_names */ - for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) - { - hb_codepoint_t sid = glyph_to_sid (gid); - gname_t gname; - gname.sid = sid; - if (sid < cff1_std_strings_length) - gname.name = cff1_std_strings (sid); - else - { - byte_str_t ustr = (*stringIndex)[sid - cff1_std_strings_length]; - gname.name = hb_bytes_t ((const char*)ustr.arrayZ, ustr.length); - } - if (unlikely (!gname.name.arrayZ)) { fini (); return; } - glyph_names.push (gname); - } - glyph_names.qsort (); } - - void fini () + ~accelerator_t () { - glyph_names.fini (); + hb_sorted_vector_t *names = glyph_names.get_relaxed (); + if (names) + { + names->fini (); + hb_free (names); + } SUPER::fini (); } @@ -1305,9 +1345,9 @@ bool get_glyph_name (hb_codepoint_t glyph, char *buf, unsigned int buf_len) const { - if (!buf) return true; if (unlikely (!is_valid ())) return false; if (is_CID()) return false; + if (unlikely (!buf_len)) return true; hb_codepoint_t sid = glyph_to_sid (glyph); const char *str; size_t str_len; @@ -1319,7 +1359,7 @@ } else { - byte_str_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length]; + hb_ubytes_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length]; str = (const char *)ubyte_str.arrayZ; str_len = ubyte_str.length; } @@ -1333,11 +1373,53 @@ bool get_glyph_from_name (const char *name, int len, hb_codepoint_t *glyph) const { + if (unlikely (!is_valid ())) return false; + if (is_CID()) return false; if (len < 0) len = strlen (name); if (unlikely (!len)) return false; + retry: + hb_sorted_vector_t *names = glyph_names.get (); + if (unlikely (!names)) + { + names = (hb_sorted_vector_t *) hb_calloc (sizeof (hb_sorted_vector_t), 1); + if (likely (names)) + { + names->init (); + /* TODO */ + + /* fill glyph names */ + for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) + { + hb_codepoint_t sid = glyph_to_sid (gid); + gname_t gname; + gname.sid = sid; + if (sid < cff1_std_strings_length) + gname.name = cff1_std_strings (sid); + else + { + hb_ubytes_t ustr = (*stringIndex)[sid - cff1_std_strings_length]; + gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length); + } + if (unlikely (!gname.name.arrayZ)) + gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */ + names->push (gname); + } + names->qsort (); + } + if (unlikely (!glyph_names.cmpexch (nullptr, names))) + { + if (names) + { + names->fini (); + hb_free (names); + } + goto retry; + } + } + gname_t key = { hb_bytes_t (name, len), 0 }; - const gname_t *gname = glyph_names.bsearch (key); + const gname_t *gname = names ? names->bsearch (key) : nullptr; if (!gname) return false; hb_codepoint_t gid = sid_to_glyph (gname->sid); if (!gid && gname->sid) return false; @@ -1347,9 +1429,7 @@ HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; -#ifdef HB_EXPERIMENTAL_API - HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const; -#endif + HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; private: struct gname_t @@ -1361,7 +1441,7 @@ { const gname_t *a = (const gname_t *)a_; const gname_t *b = (const gname_t *)b_; - int minlen = hb_min (a->name.length, b->name.length); + unsigned minlen = hb_min (a->name.length, b->name.length); int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen); if (ret) return ret; return a->name.length - b->name.length; @@ -1370,7 +1450,7 @@ int cmp (const gname_t &a) const { return cmp (&a, this); } }; - hb_sorted_vector_t glyph_names; + mutable hb_atomic_ptr_t> glyph_names; typedef accelerator_templ_t SUPER; }; @@ -1390,14 +1470,17 @@ public: FixedVersion version; /* Version of CFF table. set to 0x0100u */ - OffsetTo nameIndex; /* headerSize = Offset to Name INDEX. */ + NNOffsetTo nameIndex; /* headerSize = Offset to Name INDEX. */ HBUINT8 offSize; /* offset size (unused?) */ public: DEFINE_SIZE_STATIC (4); }; -struct cff1_accelerator_t : cff1::accelerator_t {}; +struct cff1_accelerator_t : cff1::accelerator_t { + cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {} +}; + } /* namespace OT */ #endif /* HB_OT_CFF1_TABLE_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc 2022-10-10 13:07:22.000000000 +0000 @@ -36,9 +36,8 @@ struct cff2_extents_param_t { - void init () + cff2_extents_param_t () { - path_open = false; min_x.set_int (INT_MAX); min_y.set_int (INT_MAX); max_x.set_int (INT_MIN); @@ -57,22 +56,22 @@ if (pt.y > max_y) max_y = pt.y; } - bool path_open; + bool path_open = false; number_t min_x; number_t min_y; number_t max_x; number_t max_y; }; -struct cff2_path_procs_extents_t : path_procs_t +struct cff2_path_procs_extents_t : path_procs_t, cff2_extents_param_t> { - static void moveto (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt) + static void moveto (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt) { param.end_path (); env.moveto (pt); } - static void line (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1) + static void line (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1) { if (!param.is_path_open ()) { @@ -83,7 +82,7 @@ param.update_bounds (env.get_pt ()); } - static void curve (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) + static void curve (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) { if (!param.is_path_open ()) { @@ -98,7 +97,7 @@ } }; -struct cff2_cs_opset_extents_t : cff2_cs_opset_t {}; +struct cff2_cs_opset_extents_t : cff2_cs_opset_t {}; bool OT::cff2::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph, @@ -112,11 +111,10 @@ if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false; unsigned int fd = fdSelect->get_fd (glyph); - cff2_cs_interpreter_t interp; - const byte_str_t str = (*charStrings)[glyph]; - interp.env.init (str, *this, fd, font->coords, font->num_coords); + const hb_ubytes_t str = (*charStrings)[glyph]; + cff2_cs_interp_env_t env (str, *this, fd, font->coords, font->num_coords); + cff2_cs_interpreter_t interp (env); cff2_extents_param_t param; - param.init (); if (unlikely (!interp.interpret (param))) return false; if (param.min_x >= param.max_x) @@ -143,57 +141,56 @@ return true; } -#ifdef HB_EXPERIMENTAL_API struct cff2_path_param_t { - cff2_path_param_t (hb_font_t *font_, draw_helper_t &draw_helper_) + cff2_path_param_t (hb_font_t *font_, hb_draw_session_t &draw_session_) { - draw_helper = &draw_helper_; + draw_session = &draw_session_; font = font_; } void move_to (const point_t &p) - { draw_helper->move_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); } + { draw_session->move_to (font->em_fscalef_x (p.x.to_real ()), font->em_fscalef_y (p.y.to_real ())); } void line_to (const point_t &p) - { draw_helper->line_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); } + { draw_session->line_to (font->em_fscalef_x (p.x.to_real ()), font->em_fscalef_y (p.y.to_real ())); } void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3) { - draw_helper->cubic_to (font->em_scalef_x (p1.x.to_real ()), font->em_scalef_y (p1.y.to_real ()), - font->em_scalef_x (p2.x.to_real ()), font->em_scalef_y (p2.y.to_real ()), - font->em_scalef_x (p3.x.to_real ()), font->em_scalef_y (p3.y.to_real ())); + draw_session->cubic_to (font->em_fscalef_x (p1.x.to_real ()), font->em_fscalef_y (p1.y.to_real ()), + font->em_fscalef_x (p2.x.to_real ()), font->em_fscalef_y (p2.y.to_real ()), + font->em_fscalef_x (p3.x.to_real ()), font->em_fscalef_y (p3.y.to_real ())); } protected: - draw_helper_t *draw_helper; + hb_draw_session_t *draw_session; hb_font_t *font; }; -struct cff2_path_procs_path_t : path_procs_t +struct cff2_path_procs_path_t : path_procs_t, cff2_path_param_t> { - static void moveto (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt) + static void moveto (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt) { param.move_to (pt); env.moveto (pt); } - static void line (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1) + static void line (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1) { param.line_to (pt1); env.moveto (pt1); } - static void curve (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) + static void curve (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) { param.cubic_to (pt1, pt2, pt3); env.moveto (pt3); } }; -struct cff2_cs_opset_path_t : cff2_cs_opset_t {}; +struct cff2_cs_opset_path_t : cff2_cs_opset_t {}; -bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const +bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const { #ifdef HB_NO_OT_FONT_CFF /* XXX Remove check when this code moves to .hh file. */ @@ -203,13 +200,12 @@ if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false; unsigned int fd = fdSelect->get_fd (glyph); - cff2_cs_interpreter_t interp; - const byte_str_t str = (*charStrings)[glyph]; - interp.env.init (str, *this, fd, font->coords, font->num_coords); - cff2_path_param_t param (font, draw_helper); + const hb_ubytes_t str = (*charStrings)[glyph]; + cff2_cs_interp_env_t env (str, *this, fd, font->coords, font->num_coords); + cff2_cs_interpreter_t interp (env); + cff2_path_param_t param (font, draw_session); if (unlikely (!interp.interpret (param))) return false; return true; } -#endif #endif diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -247,12 +247,8 @@ struct cff2_priv_dict_interp_env_t : num_interp_env_t { - void init (const byte_str_t &str) - { - num_interp_env_t::init (str); - ivs = 0; - seen_vsindex = false; - } + cff2_priv_dict_interp_env_t (const hb_ubytes_t &str) : + num_interp_env_t (str) {} void process_vsindex () { @@ -267,8 +263,8 @@ void set_ivs (unsigned int ivs_) { ivs = ivs_; } protected: - unsigned int ivs; - bool seen_vsindex; + unsigned int ivs = 0; + bool seen_vsindex = false; }; struct cff2_private_dict_opset_t : dict_opset_t @@ -397,7 +393,7 @@ template struct accelerator_templ_t { - void init (hb_face_t *face) + accelerator_templ_t (hb_face_t *face) { topDict.init (); fontDicts.init (); @@ -412,15 +408,15 @@ const OT::cff2 *cff2 = this->blob->template as (); if (cff2 == &Null (OT::cff2)) - { fini (); return; } + goto fail; { /* parse top dict */ - byte_str_t topDictStr (cff2 + cff2->topDict, cff2->topDictSize); - if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; } - cff2_top_dict_interpreter_t top_interp; - top_interp.env.init (topDictStr); + hb_ubytes_t topDictStr = (cff2 + cff2->topDict).as_ubytes (cff2->topDictSize); + if (unlikely (!topDictStr.sanitize (&sc))) goto fail; + num_interp_env_t env (topDictStr); + cff2_top_dict_interpreter_t top_interp (env); topDict.init (); - if (unlikely (!top_interp.interpret (topDict))) { fini (); return; } + if (unlikely (!top_interp.interpret (topDict))) goto fail; } globalSubrs = &StructAtOffset (cff2, cff2->topDict + cff2->topDictSize); @@ -434,49 +430,55 @@ (globalSubrs == &Null (CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) || (fdArray == &Null (CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) || (((fdSelect != &Null (CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count))))) - { fini (); return; } + goto fail; num_glyphs = charStrings->count; if (num_glyphs != sc.get_num_glyphs ()) - { fini (); return; } + goto fail; fdCount = fdArray->count; if (!privateDicts.resize (fdCount)) - { fini (); return; } + goto fail; /* parse font dicts and gather private dicts */ for (unsigned int i = 0; i < fdCount; i++) { - const byte_str_t fontDictStr = (*fdArray)[i]; - if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; } + const hb_ubytes_t fontDictStr = (*fdArray)[i]; + if (unlikely (!fontDictStr.sanitize (&sc))) goto fail; cff2_font_dict_values_t *font; - cff2_font_dict_interpreter_t font_interp; - font_interp.env.init (fontDictStr); + num_interp_env_t env (fontDictStr); + cff2_font_dict_interpreter_t font_interp (env); font = fontDicts.push (); - if (unlikely (font == &Crap (cff2_font_dict_values_t))) { fini (); return; } + if (unlikely (font == &Crap (cff2_font_dict_values_t))) goto fail; font->init (); - if (unlikely (!font_interp.interpret (*font))) { fini (); return; } + if (unlikely (!font_interp.interpret (*font))) goto fail; - const byte_str_t privDictStr (StructAtOffsetOrNull (cff2, font->privateDictInfo.offset), font->privateDictInfo.size); - if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; } - dict_interpreter_t priv_interp; - priv_interp.env.init(privDictStr); + const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff2, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size); + if (unlikely (!privDictStr.sanitize (&sc))) goto fail; + cff2_priv_dict_interp_env_t env2 (privDictStr); + dict_interpreter_t priv_interp (env2); privateDicts[i].init (); - if (unlikely (!priv_interp.interpret (privateDicts[i]))) { fini (); return; } + if (unlikely (!priv_interp.interpret (privateDicts[i]))) goto fail; privateDicts[i].localSubrs = &StructAtOffsetOrNull (&privDictStr[0], privateDicts[i].subrsOffset); if (privateDicts[i].localSubrs != &Null (CFF2Subrs) && unlikely (!privateDicts[i].localSubrs->sanitize (&sc))) - { fini (); return; } + goto fail; } - } - void fini () + + return; + + fail: + _fini (); + } + ~accelerator_templ_t () { _fini (); } + void _fini () { sc.end_processing (); topDict.fini (); - fontDicts.fini_deep (); - privateDicts.fini_deep (); + fontDicts.fini (); + privateDicts.fini (); hb_blob_destroy (blob); blob = nullptr; } @@ -484,32 +486,32 @@ bool is_valid () const { return blob; } protected: - hb_blob_t *blob; + hb_blob_t *blob = nullptr; hb_sanitize_context_t sc; public: cff2_top_dict_values_t topDict; - const CFF2Subrs *globalSubrs; - const CFF2VariationStore *varStore; - const CFF2CharStrings *charStrings; - const CFF2FDArray *fdArray; - const CFF2FDSelect *fdSelect; - unsigned int fdCount; + const CFF2Subrs *globalSubrs = nullptr; + const CFF2VariationStore *varStore = nullptr; + const CFF2CharStrings *charStrings = nullptr; + const CFF2FDArray *fdArray = nullptr; + const CFF2FDSelect *fdSelect = nullptr; + unsigned int fdCount = 0; hb_vector_t fontDicts; hb_vector_t privateDicts; - unsigned int num_glyphs; + unsigned int num_glyphs = 0; }; struct accelerator_t : accelerator_templ_t { + accelerator_t (hb_face_t *face) : accelerator_templ_t (face) {} + HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; -#ifdef HB_EXPERIMENTAL_API - HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const; -#endif + HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; }; typedef accelerator_templ_t accelerator_subset_t; @@ -525,7 +527,10 @@ DEFINE_SIZE_STATIC (5); }; -struct cff2_accelerator_t : cff2::accelerator_t {}; +struct cff2_accelerator_t : cff2::accelerator_t { + cff2_accelerator_t (hb_face_t *face) : cff2::accelerator_t (face) {} +}; + } /* namespace OT */ #endif /* HB_OT_CFF2_TABLE_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff-common.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff-common.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff-common.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cff-common.hh 2022-10-10 13:07:22.000000000 +0000 @@ -46,51 +46,21 @@ static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offset) { return offset ? StructAtOffset (P, offset) : Null (Type); } -inline unsigned int calcOffSize (unsigned int dataSize) -{ - unsigned int size = 1; - unsigned int offset = dataSize + 1; - while (offset & ~0xFF) - { - size++; - offset >>= 8; - } - /* format does not support size > 4; caller should handle it as an error */ - return size; -} - struct code_pair_t { hb_codepoint_t code; hb_codepoint_t glyph; }; -typedef hb_vector_t str_buff_t; -struct str_buff_vec_t : hb_vector_t -{ - void fini () { SUPER::fini_deep (); } - - unsigned int total_size () const - { - unsigned int size = 0; - for (unsigned int i = 0; i < length; i++) - size += (*this)[i].length; - return size; - } - - private: - typedef hb_vector_t SUPER; -}; +using str_buff_t = hb_vector_t; +using str_buff_vec_t = hb_vector_t; /* CFF INDEX */ template struct CFFIndex { - static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count) - { return offSize * (count + 1); } - unsigned int offset_array_size () const - { return calculate_offset_array_size (offSize, count); } + { return offSize * (count + 1); } CFFIndex *copy (hb_serialize_context_t *c) const { @@ -102,55 +72,46 @@ return_trace (out); } - bool serialize (hb_serialize_context_t *c, const CFFIndex &src) - { - TRACE_SERIALIZE (this); - unsigned int size = src.get_size (); - CFFIndex *dest = c->allocate_size (size); - if (unlikely (!dest)) return_trace (false); - memcpy (dest, &src, size); - return_trace (true); - } - bool serialize (hb_serialize_context_t *c, unsigned int offSize_, const byte_str_array_t &byteArray) { TRACE_SERIALIZE (this); + if (byteArray.length == 0) { COUNT *dest = c->allocate_min (); if (unlikely (!dest)) return_trace (false); *dest = 0; + return_trace (true); } - else - { - /* serialize CFFIndex header */ - if (unlikely (!c->extend_min (*this))) return_trace (false); - this->count = byteArray.length; - this->offSize = offSize_; - if (unlikely (!c->allocate_size (offSize_ * (byteArray.length + 1)))) - return_trace (false); - /* serialize indices */ - unsigned int offset = 1; - unsigned int i = 0; - for (; i < byteArray.length; i++) - { - set_offset_at (i, offset); - offset += byteArray[i].get_size (); - } + /* serialize CFFIndex header */ + if (unlikely (!c->extend_min (this))) return_trace (false); + this->count = byteArray.length; + this->offSize = offSize_; + if (unlikely (!c->allocate_size (offSize_ * (byteArray.length + 1)))) + return_trace (false); + + /* serialize indices */ + unsigned int offset = 1; + unsigned int i = 0; + for (; i < byteArray.length; i++) + { set_offset_at (i, offset); + offset += byteArray[i].get_size (); + } + set_offset_at (i, offset); - /* serialize data */ - for (unsigned int i = 0; i < byteArray.length; i++) - { - const byte_str_t &bs = byteArray[i]; - unsigned char *dest = c->allocate_size (bs.length); - if (unlikely (!dest)) return_trace (false); - memcpy (dest, &bs[0], bs.length); - } + /* serialize data */ + for (unsigned int i = 0; i < byteArray.length; i++) + { + const hb_ubytes_t &bs = byteArray[i]; + unsigned char *dest = c->allocate_size (bs.length); + if (unlikely (!dest)) return_trace (false); + memcpy (dest, &bs[0], bs.length); } + return_trace (true); } @@ -162,7 +123,7 @@ byteArray.init (); byteArray.resize (buffArray.length); for (unsigned int i = 0; i < byteArray.length; i++) - byteArray[i] = byte_str_t (buffArray[i].arrayZ, buffArray[i].length); + byteArray[i] = hb_ubytes_t (buffArray[i].arrayZ, buffArray[i].length); bool result = this->serialize (c, offSize_, byteArray); byteArray.fini (); return result; @@ -174,18 +135,9 @@ Iterator it) { TRACE_SERIALIZE (this); - if (it.len () == 0) - { - COUNT *dest = c->allocate_min (); - if (unlikely (!dest)) return_trace (false); - *dest = 0; - } - else - { - serialize_header(c, + it | hb_map ([] (const byte_str_t &_) { return _.length; })); - for (const auto &_ : +it) - _.copy (c); - } + serialize_header(c, + it | hb_map ([] (const hb_ubytes_t &_) { return _.length; })); + for (const auto &_ : +it) + _.copy (c); return_trace (true); } @@ -198,7 +150,7 @@ { auto it = + hb_iter (buffArray) - | hb_map ([] (const str_buff_t &_) { return byte_str_t (_.arrayZ, _.length); }) + | hb_map ([] (const str_buff_t &_) { return hb_ubytes_t (_.arrayZ, _.length); }) ; return serialize (c, it); } @@ -211,13 +163,15 @@ TRACE_SERIALIZE (this); unsigned total = + it | hb_reduce (hb_add, 0); - unsigned off_size = calcOffSize (total); + unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8; /* serialize CFFIndex header */ - if (unlikely (!c->extend_min (*this))) return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); this->count = it.len (); + if (!this->count) return_trace (true); + if (unlikely (!c->extend (this->offSize))) return_trace (false); this->offSize = off_size; - if (unlikely (!c->allocate_size (off_size * (it.len () + 1)))) + if (unlikely (!c->allocate_size (off_size * (this->count + 1)))) return_trace (false); /* serialize indices */ @@ -235,6 +189,7 @@ void set_offset_at (unsigned int index, unsigned int offset) { + assert (index <= count); HBUINT8 *p = offsets + offSize * index + offSize; unsigned int size = offSize; for (; size; size--) @@ -245,11 +200,13 @@ } } + private: unsigned int offset_at (unsigned int index) const { assert (index <= count); - const HBUINT8 *p = offsets + offSize * index; + unsigned int size = offSize; + const HBUINT8 *p = offsets + size * index; unsigned int offset = 0; for (; size; size--) offset = (offset << 8) + *p++; @@ -258,72 +215,57 @@ unsigned int length_at (unsigned int index) const { - if (unlikely ((offset_at (index + 1) < offset_at (index)) || - (offset_at (index + 1) > offset_at (count)))) + unsigned offset0 = offset_at (index); + unsigned offset1 = offset_at (index + 1); + if (unlikely (offset1 < offset0 || offset1 > offset_at (count))) return 0; - return offset_at (index + 1) - offset_at (index); + return offset1 - offset0; } const unsigned char *data_base () const - { return (const unsigned char *) this + min_size + offset_array_size (); } - - unsigned int data_size () const { return HBINT8::static_size; } + { return (const unsigned char *) this + min_size + offSize.static_size + offset_array_size (); } + public: - byte_str_t operator [] (unsigned int index) const + hb_ubytes_t operator [] (unsigned int index) const { - if (unlikely (index >= count)) return Null (byte_str_t); - return byte_str_t (data_base () + offset_at (index) - 1, length_at (index)); + if (unlikely (index >= count)) return hb_ubytes_t (); + unsigned length = length_at (index); + if (unlikely (!length)) return hb_ubytes_t (); + return hb_ubytes_t (data_base () + offset_at (index) - 1, length); } unsigned int get_size () const { - if (this == &Null (CFFIndex)) return 0; - if (count > 0) - return min_size + offset_array_size () + (offset_at (count) - 1); - return count.static_size; /* empty CFFIndex contains count only */ + if (count) + return min_size + offSize.static_size + offset_array_size () + (offset_at (count) - 1); + return min_size; /* empty CFFIndex contains count only */ } bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely ((c->check_struct (this) && count == 0) || /* empty INDEX */ - (c->check_struct (this) && offSize >= 1 && offSize <= 4 && - c->check_array (offsets, offSize, count + 1) && - c->check_array ((const HBUINT8*) data_base (), 1, max_offset () - 1)))); - } - - protected: - unsigned int max_offset () const - { - unsigned int max = 0; - for (unsigned int i = 0; i < count + 1u; i++) - { - unsigned int off = offset_at (i); - if (off > max) max = off; - } - return max; + return_trace (likely (c->check_struct (this) && + (count == 0 || /* empty INDEX */ + (count < count + 1u && + c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 && + c->check_array (offsets, offSize, count + 1u) && + c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count) - 1))))); } public: COUNT count; /* Number of object data. Note there are (count+1) offsets */ + private: HBUINT8 offSize; /* The byte size of each offset in the offsets array. */ HBUINT8 offsets[HB_VAR_ARRAY]; /* The array of (count + 1) offsets into objects array (1-base). */ /* HBUINT8 data[HB_VAR_ARRAY]; Object data */ public: - DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets); + DEFINE_SIZE_MIN (COUNT::static_size); }; template struct CFFIndexOf : CFFIndex { - const byte_str_t operator [] (unsigned int index) const - { - if (likely (index < CFFIndex::count)) - return byte_str_t (CFFIndex::data_base () + CFFIndex::offset_at (index) - 1, CFFIndex::length_at (index)); - return Null (byte_str_t); - } - template bool serialize (hb_serialize_context_t *c, unsigned int offSize_, @@ -335,7 +277,7 @@ { TRACE_SERIALIZE (this); /* serialize CFFIndex header */ - if (unlikely (!c->extend_min (*this))) return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); this->count = dataArrayLen; this->offSize = offSize_; if (unlikely (!c->allocate_size (offSize_ * (dataArrayLen + 1)))) @@ -373,7 +315,7 @@ { TRACE_SERIALIZE (this); for (unsigned int i = 0; i < dictval.get_count (); i++) - if (unlikely (!opszr.serialize (c, dictval[i], hb_forward (ds)...))) + if (unlikely (!opszr.serialize (c, dictval[i], std::forward (ds)...))) return_trace (false); return_trace (true); diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -27,6 +27,8 @@ #ifndef HB_OT_CMAP_TABLE_HH #define HB_OT_CMAP_TABLE_HH +#include "hb-ot-os2-table.hh" +#include "hb-ot-shaper-arabic-pua.hh" #include "hb-open-type.hh" #include "hb-set.hh" @@ -44,11 +46,17 @@ bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const { hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0; - if (!gid) + if (unlikely (!gid)) return false; *glyph = gid; return true; } + + unsigned get_language () const + { + return language; + } + void collect_unicodes (hb_set_t *out) const { for (unsigned int i = 0; i < 256; i++) @@ -87,124 +95,200 @@ struct CmapSubtableFormat4 { + template - HBUINT16* serialize_endcode_array (hb_serialize_context_t *c, - Iterator it) + void to_ranges (Iterator it, Writer& range_writer) { - HBUINT16 *endCode = c->start_embed (); - hb_codepoint_t prev_endcp = 0xFFFF; + hb_codepoint_t start_cp = 0, prev_run_start_cp = 0, run_start_cp = 0, end_cp = 0, last_gid = 0; + int run_length = 0 , delta = 0, prev_delta = 0; - for (const auto& _ : +it) - { - if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first) - { - HBUINT16 end_code; - end_code = prev_endcp; - c->copy (end_code); - } - prev_endcp = _.first; - } + enum { + FIRST_SUB_RANGE, + FOLLOWING_SUB_RANGE, + } mode; + + while (it) { + // Start a new range + { + const auto& pair = *it; + start_cp = pair.first; + prev_run_start_cp = start_cp; + run_start_cp = start_cp; + end_cp = start_cp; + last_gid = pair.second; + run_length = 1; + prev_delta = 0; + } + + delta = last_gid - start_cp; + mode = FIRST_SUB_RANGE; + it++; + + while (it) { + // Process range + const auto& pair = *it; + hb_codepoint_t next_cp = pair.first; + hb_codepoint_t next_gid = pair.second; + if (next_cp != end_cp + 1) { + // Current range is over, stop processing. + break; + } - { - // last endCode - HBUINT16 endcode; - endcode = prev_endcp; - if (unlikely (!c->copy (endcode))) return nullptr; - // There must be a final entry with end_code == 0xFFFF. - if (prev_endcp != 0xFFFF) - { - HBUINT16 finalcode; - finalcode = 0xFFFF; - if (unlikely (!c->copy (finalcode))) return nullptr; - } - } + if (next_gid == last_gid + 1) { + // The current run continues. + end_cp = next_cp; + run_length++; + last_gid = next_gid; + it++; + continue; + } - return endCode; - } + // A new run is starting, decide if we want to commit the current run. + int split_cost = (mode == FIRST_SUB_RANGE) ? 8 : 16; + int run_cost = run_length * 2; + if (run_cost >= split_cost) { + commit_current_range(start_cp, + prev_run_start_cp, + run_start_cp, + end_cp, + delta, + prev_delta, + split_cost, + range_writer); + start_cp = next_cp; + } - template - HBUINT16* serialize_startcode_array (hb_serialize_context_t *c, - Iterator it) - { - HBUINT16 *startCode = c->start_embed (); - hb_codepoint_t prev_cp = 0xFFFF; + // Start the new run + mode = FOLLOWING_SUB_RANGE; + prev_run_start_cp = run_start_cp; + run_start_cp = next_cp; + end_cp = next_cp; + prev_delta = delta; + delta = next_gid - run_start_cp; + run_length = 1; + last_gid = next_gid; + it++; + } + + // Finalize range + commit_current_range (start_cp, + prev_run_start_cp, + run_start_cp, + end_cp, + delta, + prev_delta, + 8, + range_writer); + } + + if (likely (end_cp != 0xFFFF)) { + range_writer (0xFFFF, 0xFFFF, 1); + } + } - for (const auto& _ : +it) - { - if (prev_cp == 0xFFFF || prev_cp + 1u != _.first) - { - HBUINT16 start_code; - start_code = _.first; - c->copy (start_code); + /* + * Writes the current range as either one or two ranges depending on what is most efficient. + */ + template + void commit_current_range (hb_codepoint_t start, + hb_codepoint_t prev_run_start, + hb_codepoint_t run_start, + hb_codepoint_t end, + int run_delta, + int previous_run_delta, + int split_cost, + Writer& range_writer) { + bool should_split = false; + if (start < run_start && run_start < end) { + int run_cost = (end - run_start + 1) * 2; + if (run_cost >= split_cost) { + should_split = true; } + } - prev_cp = _.first; + // TODO(grieger): handle case where delta is legitimately 0, mark range offset array instead? + if (should_split) { + if (start == prev_run_start) + range_writer (start, run_start - 1, previous_run_delta); + else + range_writer (start, run_start - 1, 0); + range_writer (run_start, end, run_delta); + return; } - // There must be a final entry with end_code == 0xFFFF. - if (it.len () == 0 || prev_cp != 0xFFFF) - { - HBUINT16 finalcode; - finalcode = 0xFFFF; - if (unlikely (!c->copy (finalcode))) return nullptr; + + if (start == run_start) { + // Range is only a run + range_writer (start, end, run_delta); + return; } - return startCode; + // Write only a single non-run range. + range_writer (start, end, 0); } template - HBINT16* serialize_idDelta_array (hb_serialize_context_t *c, - Iterator it, - HBUINT16 *endCode, - HBUINT16 *startCode, - unsigned segcount) - { - unsigned i = 0; - hb_codepoint_t last_gid = 0, start_gid = 0, last_cp = 0xFFFF; - bool use_delta = true; - - HBINT16 *idDelta = c->start_embed (); - if ((char *)idDelta - (char *)startCode != (int) segcount * (int) HBINT16::static_size) - return nullptr; - - for (const auto& _ : +it) - { - if (_.first == startCode[i]) - { - use_delta = true; - start_gid = _.second; + unsigned serialize_find_segcount (Iterator it) { + struct Counter { + unsigned segcount = 0; + + void operator() (hb_codepoint_t start, + hb_codepoint_t end, + int delta) { + segcount++; } - else if (_.second != last_gid + 1) use_delta = false; + } counter; - if (_.first == endCode[i]) - { - HBINT16 delta; - if (use_delta) delta = (int)start_gid - (int)startCode[i]; - else delta = 0; - c->copy (delta); + to_ranges (+it, counter); + return counter.segcount; + } - i++; - } - last_gid = _.second; - last_cp = _.first; - } + template + bool serialize_start_end_delta_arrays (hb_serialize_context_t *c, + Iterator it, + int segcount) + { + struct Writer { + hb_serialize_context_t *serializer_; + HBUINT16* end_code_; + HBUINT16* start_code_; + HBINT16* id_delta_; + int index_; + + Writer(hb_serialize_context_t *serializer) + : serializer_(serializer), + end_code_(nullptr), + start_code_(nullptr), + id_delta_(nullptr), + index_ (0) {} + void operator() (hb_codepoint_t start, + hb_codepoint_t end, + int delta) { + start_code_[index_] = start; + end_code_[index_] = end; + id_delta_[index_] = delta; + index_++; + } + } writer(c); + + writer.end_code_ = c->allocate_size (HBUINT16::static_size * segcount); + c->allocate_size (2); // padding + writer.start_code_ = c->allocate_size (HBUINT16::static_size * segcount); + writer.id_delta_ = c->allocate_size (HBINT16::static_size * segcount); - if (it.len () == 0 || last_cp != 0xFFFF) - { - HBINT16 delta; - delta = 1; - if (unlikely (!c->copy (delta))) return nullptr; - } + if (unlikely (!writer.end_code_ || !writer.start_code_ || !writer.id_delta_)) return false; - return idDelta; + to_ranges (+it, writer); + return true; } template + hb_requires (hb_is_iterator (Iterator))> HBUINT16* serialize_rangeoffset_glyid (hb_serialize_context_t *c, Iterator it, HBUINT16 *endCode, @@ -212,29 +296,23 @@ HBINT16 *idDelta, unsigned segcount) { + hb_map_t cp_to_gid { it }; + HBUINT16 *idRangeOffset = c->allocate_size (HBUINT16::static_size * segcount); if (unlikely (!c->check_success (idRangeOffset))) return nullptr; if (unlikely ((char *)idRangeOffset - (char *)idDelta != (int) segcount * (int) HBINT16::static_size)) return nullptr; - + hb_range (segcount) - | hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; }) - | hb_apply ([&] (const unsigned i) - { - idRangeOffset[i] = 2 * (c->start_embed () - idRangeOffset - i); - - + it - | hb_filter ([&] (const hb_item_type _) { return _.first >= startCode[i] && _.first <= endCode[i]; }) - | hb_apply ([&] (const hb_item_type _) - { - HBUINT16 glyID; - glyID = _.second; - c->copy (glyID); - }) - ; - - - }) - ; + for (unsigned i : + hb_range (segcount) + | hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; })) + { + idRangeOffset[i] = 2 * (c->start_embed () - idRangeOffset - i); + for (hb_codepoint_t cp = startCode[i]; cp <= endCode[i]; cp++) + { + HBUINT16 gid; + gid = cp_to_gid[cp]; + c->copy (gid); + } + } return idRangeOffset; } @@ -250,33 +328,44 @@ { return _.first <= 0xFFFF; }) ; - if (format4_iter.len () == 0) return; + if (!format4_iter) return; unsigned table_initpos = c->length (); - if (unlikely (!c->extend_min (*this))) return; + if (unlikely (!c->extend_min (this))) return; this->format = 4; - //serialize endCode[] - HBUINT16 *endCode = serialize_endcode_array (c, format4_iter); - if (unlikely (!endCode)) return; - - unsigned segcount = (c->length () - min_size) / HBUINT16::static_size; - - // 2 bytes of padding. - if (unlikely (!c->allocate_size (HBUINT16::static_size))) return; // 2 bytes of padding. - - // serialize startCode[] - HBUINT16 *startCode = serialize_startcode_array (c, format4_iter); - if (unlikely (!startCode)) return; + hb_vector_t> cp_to_gid { + format4_iter + }; + + //serialize endCode[], startCode[], idDelta[] + HBUINT16* endCode = c->start_embed (); + unsigned segcount = serialize_find_segcount (cp_to_gid.iter()); + if (unlikely (!serialize_start_end_delta_arrays (c, cp_to_gid.iter(), segcount))) + return; - //serialize idDelta[] - HBINT16 *idDelta = serialize_idDelta_array (c, format4_iter, endCode, startCode, segcount); - if (unlikely (!idDelta)) return; + HBUINT16 *startCode = endCode + segcount + 1; + HBINT16 *idDelta = ((HBINT16*)startCode) + segcount; - HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount); + HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, + cp_to_gid.iter (), + endCode, + startCode, + idDelta, + segcount); if (unlikely (!c->check_success (idRangeOffset))) return; - if (unlikely (!c->check_assign(this->length, c->length () - table_initpos))) return; + this->length = c->length () - table_initpos; + if ((long long) this->length != (long long) c->length () - table_initpos) + { + // Length overflowed. Discard the current object before setting the error condition, otherwise + // discard is a noop which prevents the higher level code from reverting the serializer to the + // pre-error state in cmap4 overflow handling code. + c->pop_discard (); + c->err (HB_SERIALIZE_ERROR_INT_OVERFLOW); + return; + } + this->segCountX2 = segcount * 2; this->entrySelector = hb_max (1u, hb_bit_storage (segcount)) - 1; this->searchRange = 2 * (1u << this->entrySelector); @@ -285,11 +374,15 @@ : 0; } + unsigned get_language () const + { + return language; + } + struct accelerator_t { accelerator_t () {} accelerator_t (const CmapSubtableFormat4 *subtable) { init (subtable); } - ~accelerator_t () { fini (); } void init (const CmapSubtableFormat4 *subtable) { @@ -301,7 +394,6 @@ glyphIdArray = idRangeOffset + segCount; glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2; } - void fini () {} bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const { @@ -323,7 +415,7 @@ 2, _hb_cmp_method, this->segCount + 1); - if (!found) + if (unlikely (!found)) return false; unsigned int i = found - endCount; @@ -343,7 +435,7 @@ gid += this->idDelta[i]; } gid &= 0xFFFFu; - if (!gid) + if (unlikely (!gid)) return false; *glyph = gid; return true; @@ -362,14 +454,14 @@ hb_codepoint_t start = this->startCount[i]; hb_codepoint_t end = this->endCount[i]; unsigned int rangeOffset = this->idRangeOffset[i]; + out->add_range(start, end); if (rangeOffset == 0) { for (hb_codepoint_t codepoint = start; codepoint <= end; codepoint++) { hb_codepoint_t gid = (codepoint + this->idDelta[i]) & 0xFFFFu; if (unlikely (!gid)) - continue; - out->add (codepoint); + out->del(codepoint); } } else @@ -378,11 +470,13 @@ { unsigned int index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount; if (unlikely (index >= this->glyphIdArrayLength)) + { + out->del_range (codepoint, end); break; + } hb_codepoint_t gid = this->glyphIdArray[index]; if (unlikely (!gid)) - continue; - out->add (codepoint); + out->del(codepoint); } } } @@ -391,6 +485,8 @@ void collect_mapping (hb_set_t *unicodes, /* OUT */ hb_map_t *mapping /* OUT */) const { + // TODO(grieger): optimize similar to collect_unicodes + // (ie. use add_range()) unsigned count = this->segCount; if (count && this->startCount[count - 1] == 0xFFFFu) count--; /* Skip sentinel segment. */ @@ -542,11 +638,17 @@ { /* Rely on our implicit array bound-checking. */ hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode]; - if (!gid) + if (unlikely (!gid)) return false; *glyph = gid; return true; } + + unsigned get_language () const + { + return language; + } + void collect_unicodes (hb_set_t *out) const { hb_codepoint_t start = startCharCode; @@ -582,7 +684,7 @@ UINT length; /* Byte length of this subtable. */ UINT language; /* Ignore. */ UINT startCharCode; /* First character code covered. */ - ArrayOf + ArrayOf glyphIdArray; /* Array of glyph index values for character * codes in the range. */ public: @@ -590,7 +692,7 @@ }; struct CmapSubtableFormat6 : CmapSubtableTrimmed {}; -struct CmapSubtableFormat10 : CmapSubtableTrimmed {}; +struct CmapSubtableFormat10 : CmapSubtableTrimmed {}; template struct CmapSubtableLongSegmented @@ -600,12 +702,17 @@ bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const { hb_codepoint_t gid = T::group_get_glyph (groups.bsearch (codepoint), codepoint); - if (!gid) + if (unlikely (!gid)) return false; *glyph = gid; return true; } + unsigned get_language () const + { + return language; + } + void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const { for (unsigned int i = 0; i < this->groups.len; i++) @@ -625,7 +732,7 @@ if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs)) end = start + (hb_codepoint_t) num_glyphs - gid; - out->add_range (start, end); + out->add_range (start, hb_min (end, 0x10FFFFu)); } } @@ -633,11 +740,19 @@ hb_map_t *mapping, /* OUT */ unsigned num_glyphs) const { + hb_codepoint_t last_end = 0; for (unsigned i = 0; i < this->groups.len; i++) { hb_codepoint_t start = this->groups[i].startCharCode; hb_codepoint_t end = hb_min ((hb_codepoint_t) this->groups[i].endCharCode, (hb_codepoint_t) HB_UNICODE_MAX); + if (unlikely (start > end || start < last_end)) { + // Range is not in order and is invalid, skip it. + continue; + } + last_end = end; + + hb_codepoint_t gid = this->groups[i].glyphID; if (!gid) { @@ -670,7 +785,7 @@ HBUINT16 reserved; /* Reserved; set to 0. */ HBUINT32 length; /* Byte length of this subtable. */ HBUINT32 language; /* Ignore. */ - SortedArrayOf + SortedArray32Of groups; /* Groupings. */ public: DEFINE_SIZE_ARRAY (16, groups); @@ -689,16 +804,16 @@ void serialize (hb_serialize_context_t *c, Iterator it) { - if (it.len () == 0) return; + if (!it) return; unsigned table_initpos = c->length (); - if (unlikely (!c->extend_min (*this))) return; + if (unlikely (!c->extend_min (this))) return; - hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF; + hb_codepoint_t startCharCode = (hb_codepoint_t) -1, endCharCode = (hb_codepoint_t) -1; hb_codepoint_t glyphID = 0; for (const auto& _ : +it) { - if (startCharCode == 0xFFFF) + if (startCharCode == (hb_codepoint_t) -1) { startCharCode = _.first; endCharCode = _.first; @@ -729,7 +844,7 @@ this->format = 12; this->reserved = 0; this->length = c->length () - table_initpos; - this->groups.len = (this->length - min_size)/CmapSubtableLongGroup::static_size; + this->groups.len = (this->length - min_size) / CmapSubtableLongGroup::static_size; } static size_t get_sub_table_size (const hb_sorted_vector_t &groups_data) @@ -784,7 +899,7 @@ DEFINE_SIZE_STATIC (4); }; -struct DefaultUVS : SortedArrayOf +struct DefaultUVS : SortedArray32Of { void collect_unicodes (hb_set_t *out) const { @@ -794,7 +909,7 @@ hb_codepoint_t first = arrayZ[i].startUnicodeValue; hb_codepoint_t last = hb_min ((hb_codepoint_t) (first + arrayZ[i].additionalCount), (hb_codepoint_t) HB_UNICODE_MAX); - out->add_range (first, last); + out->add_range (first, hb_min (last, 0x10FFFFu)); } } @@ -850,7 +965,9 @@ } else { - if (unlikely (!c->check_assign (out->len, (c->length () - init_len) / UnicodeValueRange::static_size))) return nullptr; + if (unlikely (!c->check_assign (out->len, + (c->length () - init_len) / UnicodeValueRange::static_size, + HB_SERIALIZE_ERROR_INT_OVERFLOW))) return nullptr; return out; } } @@ -871,28 +988,26 @@ } HBUINT24 unicodeValue; /* Base Unicode value of the UVS */ - HBGlyphID glyphID; /* Glyph ID of the UVS */ + HBGlyphID16 glyphID; /* Glyph ID of the UVS */ public: DEFINE_SIZE_STATIC (5); }; -struct NonDefaultUVS : SortedArrayOf +struct NonDefaultUVS : SortedArray32Of { void collect_unicodes (hb_set_t *out) const { - unsigned int count = len; - for (unsigned int i = 0; i < count; i++) - out->add (arrayZ[i].unicodeValue); + for (const auto& a : as_array ()) + out->add (a.unicodeValue); } void collect_mapping (hb_set_t *unicodes, /* OUT */ hb_map_t *mapping /* OUT */) const { - unsigned count = len; - for (unsigned i = 0; i < count; i++) + for (const auto& a : as_array ()) { - hb_codepoint_t unicode = arrayZ[i].unicodeValue; - hb_codepoint_t glyphid = arrayZ[i].glyphID; + hb_codepoint_t unicode = a.unicodeValue; + hb_codepoint_t glyphid = a.glyphID; unicodes->add (unicode); mapping->set (unicode, glyphid); } @@ -1041,9 +1156,9 @@ } HBUINT24 varSelector; /* Variation selector. */ - LOffsetTo + Offset32To defaultUVS; /* Offset to Default UVS Table. May be 0. */ - LOffsetTo + Offset32To nonDefaultUVS; /* Offset to Non-Default UVS Table. May be 0. */ public: DEFINE_SIZE_STATIC (11); @@ -1058,9 +1173,8 @@ void collect_variation_selectors (hb_set_t *out) const { - unsigned int count = record.len; - for (unsigned int i = 0; i < count; i++) - out->add (record.arrayZ[i].varSelector); + for (const auto& a : record.as_array ()) + out->add (a.varSelector); } void collect_variation_unicodes (hb_codepoint_t variation_selector, hb_set_t *out) const @@ -1076,7 +1190,7 @@ unsigned table_initpos = c->length (); const char* init_tail = c->tail; - if (unlikely (!c->extend_min (*this))) return; + if (unlikely (!c->extend_min (this))) return; this->format = 14; auto src_tbl = reinterpret_cast (base); @@ -1112,10 +1226,12 @@ return; int tail_len = init_tail - c->tail; - c->check_assign (this->length, c->length () - table_initpos + tail_len); + c->check_assign (this->length, c->length () - table_initpos + tail_len, + HB_SERIALIZE_ERROR_INT_OVERFLOW); c->check_assign (this->record.len, (c->length () - table_initpos - CmapSubtableFormat14::min_size) / - VariationSelectorRecord::static_size); + VariationSelectorRecord::static_size, + HB_SERIALIZE_ERROR_INT_OVERFLOW); /* Correct the incorrect write order by reversing the order of the variation records array. */ @@ -1180,7 +1296,7 @@ protected: HBUINT16 format; /* Format number is set to 14. */ HBUINT32 length; /* Byte length of this subtable. */ - SortedArrayOf + SortedArray32Of record; /* Variation selector records; sorted * in increasing order of `varSelector'. */ public: @@ -1235,6 +1351,20 @@ } } + unsigned get_language () const + { + switch (u.format) { + case 0: return u.format0 .get_language (); + case 4: return u.format4 .get_language (); + case 6: return u.format6 .get_language (); + case 10: return u.format10.get_language (); + case 12: return u.format12.get_language (); + case 13: return u.format13.get_language (); + case 14: + default: return 0; + } + } + template void serialize (hb_serialize_context_t *c, @@ -1338,70 +1468,169 @@ HBUINT16 platformID; /* Platform ID. */ HBUINT16 encodingID; /* Platform-specific encoding ID. */ - LOffsetTo + Offset32To subtable; /* Byte offset from beginning of table to the subtable for this encoding. */ public: DEFINE_SIZE_STATIC (8); }; +struct SubtableUnicodesCache { + + private: + const void* base; + hb_hashmap_t> cached_unicodes; + + public: + SubtableUnicodesCache(const void* cmap_base) + : base(cmap_base), cached_unicodes() {} + + hb_set_t* set_for (const EncodingRecord* record) + { + if (!cached_unicodes.has ((intptr_t) record)) + { + hb_set_t *s = hb_set_create (); + if (unlikely (s->in_error ())) + return hb_set_get_empty (); + + (base+record->subtable).collect_unicodes (s); + + if (unlikely (!cached_unicodes.set ((intptr_t) record, hb::unique_ptr {s}))) + return hb_set_get_empty (); + + return s; + } + return cached_unicodes.get ((intptr_t) record); + } + +}; + +static inline uint_fast16_t +_hb_symbol_pua_map (unsigned codepoint) +{ + if (codepoint <= 0x00FFu) + { + /* For symbol-encoded OpenType fonts, we duplicate the + * U+F000..F0FF range at U+0000..U+00FF. That's what + * Windows seems to do, and that's hinted about at: + * https://docs.microsoft.com/en-us/typography/opentype/spec/recom + * under "Non-Standard (Symbol) Fonts". */ + return 0xF000u + codepoint; + } + return 0; +} + struct cmap { static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap; template - void serialize (hb_serialize_context_t *c, + bool serialize (hb_serialize_context_t *c, Iterator it, EncodingRecIter encodingrec_iter, const void *base, - const hb_subset_plan_t *plan) + const hb_subset_plan_t *plan, + bool drop_format_4 = false) { - if (unlikely (!c->extend_min ((*this)))) return; + if (unlikely (!c->extend_min ((*this)))) return false; this->version = 0; unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0; + auto snap = c->snapshot (); + SubtableUnicodesCache unicodes_cache (base); for (const EncodingRecord& _ : encodingrec_iter) { + if (c->in_error ()) + return false; + unsigned format = (base+_.subtable).u.format; - if (!plan->glyphs_requested->is_empty ()) + if (format != 4 && format != 12 && format != 14) continue; + + hb_set_t* unicodes_set = unicodes_cache.set_for (&_); + + if (!drop_format_4 && format == 4) { - hb_set_t unicodes_set; - hb_map_t cp_glyphid_map; - (base+_.subtable).collect_mapping (&unicodes_set, &cp_glyphid_map); - - auto table_iter = - + hb_zip (unicodes_set.iter(), unicodes_set.iter() | hb_map(cp_glyphid_map)) - | hb_filter (plan->_glyphset, hb_second) - | hb_filter ([plan] (const hb_pair_t& p) - { - return plan->unicodes->has (p.first) || - plan->glyphs_requested->has (p.second); - }) - | hb_map ([plan] (const hb_pair_t& p_org) - { - return hb_pair_t (p_org.first, plan->glyph_map->get(p_org.second)); - }) - ; - - if (format == 4) c->copy (_, table_iter, 4u, base, plan, &format4objidx); - else if (format == 12) c->copy (_, table_iter, 12u, base, plan, &format12objidx); - else if (format == 14) c->copy (_, table_iter, 14u, base, plan, &format14objidx); + c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 4u, base, plan, &format4objidx); + if (c->in_error () && c->only_overflow ()) + { + // cmap4 overflowed, reset and retry serialization without format 4 subtables. + c->revert (snap); + return serialize (c, it, + encodingrec_iter, + base, + plan, + true); + } } - /* when --gids option is not used, we iterate input unicodes instead of - * all codepoints in each subtable, which is more efficient */ - else + + else if (format == 12) { - hb_set_t unicodes_set; - (base+_.subtable).collect_unicodes (&unicodes_set); + if (_can_drop (_, *unicodes_set, base, unicodes_cache, + it | hb_map (hb_first), encodingrec_iter)) continue; + c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 12u, base, plan, &format12objidx); + } + else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx); + } + c->check_assign(this->encodingRecord.len, + (c->length () - cmap::min_size)/EncodingRecord::static_size, + HB_SERIALIZE_ERROR_INT_OVERFLOW); + + // Fail if format 4 was dropped and there is no cmap12. + return !drop_format_4 || format12objidx; + } + + template + bool _can_drop (const EncodingRecord& cmap12, + const hb_set_t& cmap12_unicodes, + const void* base, + SubtableUnicodesCache& unicodes_cache, + Iterator subset_unicodes, + EncodingRecordIterator encoding_records) + { + for (auto cp : + subset_unicodes | hb_filter (cmap12_unicodes)) + { + if (cp >= 0x10000) return false; + } + + unsigned target_platform; + unsigned target_encoding; + unsigned target_language = (base+cmap12.subtable).get_language (); + + if (cmap12.platformID == 0 && cmap12.encodingID == 4) + { + target_platform = 0; + target_encoding = 3; + } else if (cmap12.platformID == 3 && cmap12.encodingID == 10) { + target_platform = 3; + target_encoding = 1; + } else { + return false; + } + + for (const auto& _ : encoding_records) + { + if (_.platformID != target_platform + || _.encodingID != target_encoding + || (base+_.subtable).get_language() != target_language) + continue; - if (format == 4) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx); - else if (format == 12) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx); - else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx); + hb_set_t* sibling_unicodes = unicodes_cache.set_for (&_); + + auto cmap12 = + subset_unicodes | hb_filter (cmap12_unicodes); + auto sibling = + subset_unicodes | hb_filter (*sibling_unicodes); + for (; cmap12 && sibling; cmap12++, sibling++) + { + unsigned a = *cmap12; + unsigned b = *sibling; + if (a != b) return false; } + + return !cmap12 && !sibling; } - c->check_assign(this->encodingRecord.len, (c->length () - cmap::min_size)/EncodingRecord::static_size); + return false; } void closure_glyphs (const hb_set_t *unicodes, @@ -1447,7 +1676,7 @@ unsigned format = (this + _.subtable).u.format; if (format == 12) has_format12 = true; - const EncodingRecord *table = hb_addressof (_); + const EncodingRecord *table = std::addressof (_); if (_.platformID == 0 && _.encodingID == 3) unicode_bmp = table; else if (_.platformID == 0 && _.encodingID == 4) unicode_ucs4 = table; else if (_.platformID == 3 && _.encodingID == 1) ms_bmp = table; @@ -1458,18 +1687,12 @@ if (unlikely (has_format12 && (!unicode_ucs4 && !ms_ucs4))) return_trace (false); auto it = - + hb_iter (c->plan->unicodes) - | hb_map ([&] (hb_codepoint_t _) - { - hb_codepoint_t new_gid = HB_MAP_VALUE_INVALID; - c->plan->new_gid_for_codepoint (_, &new_gid); - return hb_pair_t (_, new_gid); - }) + + c->plan->unicode_to_new_gid_list.iter () | hb_filter ([&] (const hb_pair_t _) { return (_.second != HB_MAP_VALUE_INVALID); }) ; - cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan); - return_trace (true); + + return_trace (cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan)); } const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const @@ -1505,7 +1728,7 @@ struct accelerator_t { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { this->table = hb_sanitize_context_t ().reference_table (face); bool symbol; @@ -1519,7 +1742,24 @@ this->get_glyph_data = subtable; if (unlikely (symbol)) - this->get_glyph_funcZ = get_glyph_from_symbol; + { + switch ((unsigned) face->table.OS2->get_font_page ()) { + case OS2::font_page_t::FONT_PAGE_NONE: + this->get_glyph_funcZ = get_glyph_from_symbol; + break; +#ifndef HB_NO_OT_SHAPER_ARABIC_FALLBACK + case OS2::font_page_t::FONT_PAGE_SIMP_ARABIC: + this->get_glyph_funcZ = get_glyph_from_symbol; + break; + case OS2::font_page_t::FONT_PAGE_TRAD_ARABIC: + this->get_glyph_funcZ = get_glyph_from_symbol; + break; +#endif + default: + this->get_glyph_funcZ = get_glyph_from; + break; + } + } else { switch (subtable->u.format) { @@ -1540,8 +1780,7 @@ } } } - - void fini () { this->table.destroy (); } + ~accelerator_t () { this->table.destroy (); } bool get_nominal_glyph (hb_codepoint_t unicode, hb_codepoint_t *glyph) const @@ -1602,6 +1841,7 @@ typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph); + typedef uint_fast16_t (*hb_pua_remap_func_t) (unsigned); template HB_INTERNAL static bool get_glyph_from (const void *obj, @@ -1612,7 +1852,7 @@ return typed_obj->get_glyph (codepoint, glyph); } - template + template HB_INTERNAL static bool get_glyph_from_symbol (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph) @@ -1621,15 +1861,8 @@ if (likely (typed_obj->get_glyph (codepoint, glyph))) return true; - if (codepoint <= 0x00FFu) - { - /* For symbol-encoded OpenType fonts, we duplicate the - * U+F000..F0FF range at U+0000..U+00FF. That's what - * Windows seems to do, and that's hinted about at: - * https://docs.microsoft.com/en-us/typography/opentype/spec/recom - * under "Non-Standard (Symbol) Fonts". */ - return typed_obj->get_glyph (0xF000u + codepoint, glyph); - } + if (hb_codepoint_t c = remap (codepoint)) + return typed_obj->get_glyph (c, glyph); return false; } @@ -1697,13 +1930,15 @@ protected: HBUINT16 version; /* Table version number (0). */ - SortedArrayOf + SortedArray16Of encodingRecord; /* Encoding tables. */ public: DEFINE_SIZE_ARRAY (4, encodingRecord); }; -struct cmap_accelerator_t : cmap::accelerator_t {}; +struct cmap_accelerator_t : cmap::accelerator_t { + cmap_accelerator_t (hb_face_t *face) : cmap::accelerator_t (face) {} +}; } /* namespace OT */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-cbdt-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-cbdt-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-cbdt-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-cbdt-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -360,6 +360,16 @@ struct IndexSubtableRecord { + /* XXX Remove this and fix by not inserting it into vector. */ + IndexSubtableRecord& operator = (const IndexSubtableRecord &o) + { + firstGlyphIndex = o.firstGlyphIndex; + lastGlyphIndex = o.lastGlyphIndex; + offsetToSubtable = (unsigned) o.offsetToSubtable; + assert (offsetToSubtable.is_null ()); + return *this; + } + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -508,9 +518,9 @@ offset, length, format); } - HBGlyphID firstGlyphIndex; - HBGlyphID lastGlyphIndex; - LOffsetTo offsetToSubtable; + HBGlyphID16 firstGlyphIndex; + HBGlyphID16 lastGlyphIndex; + Offset32To offsetToSubtable; public: DEFINE_SIZE_STATIC (8); }; @@ -672,15 +682,15 @@ } protected: - LNNOffsetTo + NNOffset32To indexSubtableArrayOffset; HBUINT32 indexTablesSize; HBUINT32 numberOfIndexSubtables; HBUINT32 colorRef; SBitLineMetrics horizontal; SBitLineMetrics vertical; - HBGlyphID startGlyphIndex; - HBGlyphID endGlyphIndex; + HBGlyphID16 startGlyphIndex; + HBGlyphID16 endGlyphIndex; HBUINT8 ppemX; HBUINT8 ppemY; HBUINT8 bitDepth; @@ -697,7 +707,7 @@ struct GlyphBitmapDataFormat17 { SmallGlyphMetrics glyphMetrics; - LArrayOf data; + Array32Of data; public: DEFINE_SIZE_ARRAY (9, data); }; @@ -705,14 +715,14 @@ struct GlyphBitmapDataFormat18 { BigGlyphMetrics glyphMetrics; - LArrayOf data; + Array32Of data; public: DEFINE_SIZE_ARRAY (12, data); }; struct GlyphBitmapDataFormat19 { - LArrayOf data; + Array32Of data; public: DEFINE_SIZE_ARRAY (4, data); }; @@ -738,7 +748,7 @@ cbdt_prime->length, HB_MEMORY_MODE_WRITABLE, cbdt_prime->arrayZ, - free); + hb_free); cbdt_prime->init (); // Leak arrayZ to the blob. bool ret = c->plan->add_table (HB_OT_TAG_CBDT, cbdt_prime_blob); hb_blob_destroy (cbdt_prime_blob); @@ -798,7 +808,7 @@ protected: FixedVersion<> version; - LArrayOf sizeTables; + Array32Of sizeTables; public: DEFINE_SIZE_ARRAY (8, sizeTables); }; @@ -809,15 +819,14 @@ struct accelerator_t { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { - cblc = hb_sanitize_context_t ().reference_table (face); - cbdt = hb_sanitize_context_t ().reference_table (face); + this->cblc = hb_sanitize_context_t ().reference_table (face); + this->cbdt = hb_sanitize_context_t ().reference_table (face); upem = hb_face_get_upem (face); } - - void fini () + ~accelerator_t () { this->cblc.destroy (); this->cbdt.destroy (); @@ -978,7 +987,10 @@ return_trace (CBLC::sink_cbdt (c, &cbdt_prime)); } -struct CBDT_accelerator_t : CBDT::accelerator_t {}; +struct CBDT_accelerator_t : CBDT::accelerator_t { + CBDT_accelerator_t (hb_face_t *face) : CBDT::accelerator_t (face) {} +}; + } /* namespace OT */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color.cc 2022-10-10 13:07:22.000000000 +0000 @@ -116,7 +116,7 @@ * @color_index: The index of the color * * Fetches the `name` table Name ID that provides display names for - * the specificed color in a face's `CPAL` color palette. + * the specified color in a face's `CPAL` color palette. * * Display names can be generic (e.g., "Background") or specific * (e.g., "Eye color"). @@ -256,6 +256,8 @@ * * Fetches the SVG document for a glyph. The blob may be either plain text or gzip-encoded. * + * If the glyph has no SVG document, the singleton empty blob is returned. + * * Return value: (transfer full): An #hb_blob_t containing the SVG document of the glyph, if available * * Since: 2.1.0 @@ -296,6 +298,8 @@ * as input. To get an optimally sized PNG blob, the UPEM value must be set on the @font * object. If UPEM is unset, the blob returned will be the largest PNG available. * + * If the glyph has no PNG image, the singleton empty blob is returned. + * * Return value: (transfer full): An #hb_blob_t containing the PNG image for the glyph, if available * * Since: 2.1.0 diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-colr-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-colr-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-colr-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-colr-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -29,6 +29,8 @@ #define HB_OT_COLOR_COLR_TABLE_HH #include "hb-open-type.hh" +#include "hb-ot-layout-common.hh" +#include "hb-ot-var-common.hh" /* * COLR -- Color @@ -36,14 +38,857 @@ */ #define HB_OT_TAG_COLR HB_TAG('C','O','L','R') +#ifndef HB_COLRV1_MAX_NESTING_LEVEL +#define HB_COLRV1_MAX_NESTING_LEVEL 100 +#endif + +#ifndef COLRV1_ENABLE_SUBSETTING +#define COLRV1_ENABLE_SUBSETTING 1 +#endif namespace OT { +struct COLR; +struct hb_colrv1_closure_context_t : + hb_dispatch_context_t +{ + template + return_t dispatch (const T &obj) + { + if (unlikely (nesting_level_left == 0)) + return hb_empty_t (); + + if (paint_visited (&obj)) + return hb_empty_t (); + + nesting_level_left--; + obj.closurev1 (this); + nesting_level_left++; + return hb_empty_t (); + } + static return_t default_return_value () { return hb_empty_t (); } + + bool paint_visited (const void *paint) + { + hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) paint - (uintptr_t) base); + if (visited_paint.in_error() || visited_paint.has (delta)) + return true; + + visited_paint.add (delta); + return false; + } + + const COLR* get_colr_table () const + { return reinterpret_cast (base); } + + void add_glyph (unsigned glyph_id) + { glyphs->add (glyph_id); } + + void add_layer_indices (unsigned first_layer_index, unsigned num_of_layers) + { layer_indices->add_range (first_layer_index, first_layer_index + num_of_layers - 1); } + + void add_palette_index (unsigned palette_index) + { palette_indices->add (palette_index); } + + public: + const void *base; + hb_set_t visited_paint; + hb_set_t *glyphs; + hb_set_t *layer_indices; + hb_set_t *palette_indices; + unsigned nesting_level_left; + + hb_colrv1_closure_context_t (const void *base_, + hb_set_t *glyphs_, + hb_set_t *layer_indices_, + hb_set_t *palette_indices_, + unsigned nesting_level_left_ = HB_COLRV1_MAX_NESTING_LEVEL) : + base (base_), + glyphs (glyphs_), + layer_indices (layer_indices_), + palette_indices (palette_indices_), + nesting_level_left (nesting_level_left_) + {} +}; + +struct LayerRecord +{ + operator hb_ot_color_layer_t () const { return {glyphId, colorIdx}; } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + HBGlyphID16 glyphId; /* Glyph ID of layer glyph */ + Index colorIdx; /* Index value to use with a + * selected color palette. + * An index value of 0xFFFF + * is a special case indicating + * that the text foreground + * color (defined by a + * higher-level client) should + * be used and shall not be + * treated as actual index + * into CPAL ColorRecord array. */ + public: + DEFINE_SIZE_STATIC (4); +}; + +struct BaseGlyphRecord +{ + int cmp (hb_codepoint_t g) const + { return g < glyphId ? -1 : g > glyphId ? 1 : 0; } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this))); + } + + public: + HBGlyphID16 glyphId; /* Glyph ID of reference glyph */ + HBUINT16 firstLayerIdx; /* Index (from beginning of + * the Layer Records) to the + * layer record. There will be + * numLayers consecutive entries + * for this base glyph. */ + HBUINT16 numLayers; /* Number of color layers + * associated with this glyph */ + public: + DEFINE_SIZE_STATIC (6); +}; + +template +struct Variable +{ + Variable* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + return_trace (c->embed (this)); + } + + void closurev1 (hb_colrv1_closure_context_t* c) const + { value.closurev1 (c); } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + if (!value.subset (c)) return_trace (false); + return_trace (c->serializer->embed (varIdxBase)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && value.sanitize (c)); + } + + protected: + T value; + VarIdx varIdxBase; + public: + DEFINE_SIZE_STATIC (4 + T::static_size); +}; + +template +struct NoVariable +{ + NoVariable* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + return_trace (c->embed (this)); + } + + void closurev1 (hb_colrv1_closure_context_t* c) const + { value.closurev1 (c); } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + return_trace (value.subset (c)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && value.sanitize (c)); + } + + T value; + public: + DEFINE_SIZE_STATIC (T::static_size); +}; + +// Color structures + +struct ColorStop +{ + void closurev1 (hb_colrv1_closure_context_t* c) const + { c->add_palette_index (paletteIndex); } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes->get (paletteIndex), + HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + F2DOT14 stopOffset; + HBUINT16 paletteIndex; + F2DOT14 alpha; + public: + DEFINE_SIZE_STATIC (2 + 2 * F2DOT14::static_size); +}; + +struct Extend : HBUINT8 +{ + enum { + EXTEND_PAD = 0, + EXTEND_REPEAT = 1, + EXTEND_REFLECT = 2, + }; + public: + DEFINE_SIZE_STATIC (1); +}; + +template class Var> +struct ColorLine +{ + void closurev1 (hb_colrv1_closure_context_t* c) const + { + for (const auto &stop : stops.iter ()) + stop.closurev1 (c); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (this); + if (unlikely (!out)) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + if (!c->serializer->check_assign (out->extend, extend, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false); + if (!c->serializer->check_assign (out->stops.len, stops.len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)) return_trace (false); + + for (const auto& stop : stops.iter ()) + { + if (!stop.subset (c)) return_trace (false); + } + return_trace (true); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + stops.sanitize (c)); + } + + Extend extend; + Array16Of> stops; + public: + DEFINE_SIZE_ARRAY_SIZED (3, stops); +}; + +// Composition modes + +// Compositing modes are taken from https://www.w3.org/TR/compositing-1/ +// NOTE: a brief audit of major implementations suggests most support most +// or all of the specified modes. +struct CompositeMode : HBUINT8 +{ + enum { + // Porter-Duff modes + // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators + COMPOSITE_CLEAR = 0, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_clear + COMPOSITE_SRC = 1, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_src + COMPOSITE_DEST = 2, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dst + COMPOSITE_SRC_OVER = 3, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcover + COMPOSITE_DEST_OVER = 4, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstover + COMPOSITE_SRC_IN = 5, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcin + COMPOSITE_DEST_IN = 6, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstin + COMPOSITE_SRC_OUT = 7, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcout + COMPOSITE_DEST_OUT = 8, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstout + COMPOSITE_SRC_ATOP = 9, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcatop + COMPOSITE_DEST_ATOP = 10, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstatop + COMPOSITE_XOR = 11, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_xor + COMPOSITE_PLUS = 12, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_plus + + // Blend modes + // https://www.w3.org/TR/compositing-1/#blending + COMPOSITE_SCREEN = 13, // https://www.w3.org/TR/compositing-1/#blendingscreen + COMPOSITE_OVERLAY = 14, // https://www.w3.org/TR/compositing-1/#blendingoverlay + COMPOSITE_DARKEN = 15, // https://www.w3.org/TR/compositing-1/#blendingdarken + COMPOSITE_LIGHTEN = 16, // https://www.w3.org/TR/compositing-1/#blendinglighten + COMPOSITE_COLOR_DODGE = 17, // https://www.w3.org/TR/compositing-1/#blendingcolordodge + COMPOSITE_COLOR_BURN = 18, // https://www.w3.org/TR/compositing-1/#blendingcolorburn + COMPOSITE_HARD_LIGHT = 19, // https://www.w3.org/TR/compositing-1/#blendinghardlight + COMPOSITE_SOFT_LIGHT = 20, // https://www.w3.org/TR/compositing-1/#blendingsoftlight + COMPOSITE_DIFFERENCE = 21, // https://www.w3.org/TR/compositing-1/#blendingdifference + COMPOSITE_EXCLUSION = 22, // https://www.w3.org/TR/compositing-1/#blendingexclusion + COMPOSITE_MULTIPLY = 23, // https://www.w3.org/TR/compositing-1/#blendingmultiply + + // Modes that, uniquely, do not operate on components + // https://www.w3.org/TR/compositing-1/#blendingnonseparable + COMPOSITE_HSL_HUE = 24, // https://www.w3.org/TR/compositing-1/#blendinghue + COMPOSITE_HSL_SATURATION = 25, // https://www.w3.org/TR/compositing-1/#blendingsaturation + COMPOSITE_HSL_COLOR = 26, // https://www.w3.org/TR/compositing-1/#blendingcolor + COMPOSITE_HSL_LUMINOSITY = 27, // https://www.w3.org/TR/compositing-1/#blendingluminosity + }; + public: + DEFINE_SIZE_STATIC (1); +}; + +struct Affine2x3 +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + HBFixed xx; + HBFixed yx; + HBFixed xy; + HBFixed yy; + HBFixed dx; + HBFixed dy; + public: + DEFINE_SIZE_STATIC (6 * HBFixed::static_size); +}; + +struct PaintColrLayers +{ + void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + return_trace (c->serializer->check_assign (out->firstLayerIndex, c->plan->colrv1_layers->get (firstLayerIndex), + HB_SERIALIZE_ERROR_INT_OVERFLOW)); + + return_trace (true); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + HBUINT8 format; /* format = 1 */ + HBUINT8 numLayers; + HBUINT32 firstLayerIndex; /* index into COLRv1::layerList */ + public: + DEFINE_SIZE_STATIC (6); +}; + +struct PaintSolid +{ + void closurev1 (hb_colrv1_closure_context_t* c) const + { c->add_palette_index (paletteIndex); } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes->get (paletteIndex), + HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + HBUINT8 format; /* format = 2(noVar) or 3(Var)*/ + HBUINT16 paletteIndex; + F2DOT14 alpha; + public: + DEFINE_SIZE_STATIC (3 + F2DOT14::static_size); +}; + +template class Var> +struct PaintLinearGradient +{ + void closurev1 (hb_colrv1_closure_context_t* c) const + { (this+colorLine).closurev1 (c); } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->colorLine.serialize_subset (c, colorLine, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && colorLine.sanitize (c, this)); + } + + HBUINT8 format; /* format = 4(noVar) or 5 (Var) */ + Offset24To> colorLine; /* Offset (from beginning of PaintLinearGradient + * table) to ColorLine subtable. */ + FWORD x0; + FWORD y0; + FWORD x1; + FWORD y1; + FWORD x2; + FWORD y2; + public: + DEFINE_SIZE_STATIC (4 + 6 * FWORD::static_size); +}; + +template class Var> +struct PaintRadialGradient +{ + void closurev1 (hb_colrv1_closure_context_t* c) const + { (this+colorLine).closurev1 (c); } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->colorLine.serialize_subset (c, colorLine, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && colorLine.sanitize (c, this)); + } + + HBUINT8 format; /* format = 6(noVar) or 7 (Var) */ + Offset24To> colorLine; /* Offset (from beginning of PaintRadialGradient + * table) to ColorLine subtable. */ + FWORD x0; + FWORD y0; + UFWORD radius0; + FWORD x1; + FWORD y1; + UFWORD radius1; + public: + DEFINE_SIZE_STATIC (4 + 6 * FWORD::static_size); +}; + +template class Var> +struct PaintSweepGradient +{ + void closurev1 (hb_colrv1_closure_context_t* c) const + { (this+colorLine).closurev1 (c); } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->colorLine.serialize_subset (c, colorLine, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && colorLine.sanitize (c, this)); + } + + HBUINT8 format; /* format = 8(noVar) or 9 (Var) */ + Offset24To> colorLine; /* Offset (from beginning of PaintSweepGradient + * table) to ColorLine subtable. */ + FWORD centerX; + FWORD centerY; + F2DOT14 startAngle; + F2DOT14 endAngle; + public: + DEFINE_SIZE_STATIC (4 + 2 * FWORD::static_size + 2 * F2DOT14::static_size); +}; + +struct Paint; +// Paint a non-COLR glyph, filled as indicated by paint. +struct PaintGlyph +{ + void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + if (! c->serializer->check_assign (out->gid, c->plan->glyph_map->get (gid), + HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + + return_trace (out->paint.serialize_subset (c, paint, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && paint.sanitize (c, this)); + } + + HBUINT8 format; /* format = 10 */ + Offset24To paint; /* Offset (from beginning of PaintGlyph table) to Paint subtable. */ + HBUINT16 gid; + public: + DEFINE_SIZE_STATIC (6); +}; + +struct PaintColrGlyph +{ + void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (c->serializer->check_assign (out->gid, c->plan->glyph_map->get (gid), + HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + HBUINT8 format; /* format = 11 */ + HBUINT16 gid; + public: + DEFINE_SIZE_STATIC (3); +}; + +template class Var> +struct PaintTransform +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + if (!out->transform.serialize_copy (c->serializer, transform, this)) return_trace (false); + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + src.sanitize (c, this) && + transform.sanitize (c, this)); + } + + HBUINT8 format; /* format = 12(noVar) or 13 (Var) */ + Offset24To src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */ + Offset24To> transform; + public: + DEFINE_SIZE_STATIC (7); +}; + +struct PaintTranslate +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 14(noVar) or 15 (Var) */ + Offset24To src; /* Offset (from beginning of PaintTranslate table) to Paint subtable. */ + FWORD dx; + FWORD dy; + public: + DEFINE_SIZE_STATIC (4 + 2 * FWORD::static_size); +}; + +struct PaintScale +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 16 (noVar) or 17(Var) */ + Offset24To src; /* Offset (from beginning of PaintScale table) to Paint subtable. */ + F2DOT14 scaleX; + F2DOT14 scaleY; + public: + DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size); +}; + +struct PaintScaleAroundCenter +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 18 (noVar) or 19(Var) */ + Offset24To src; /* Offset (from beginning of PaintScaleAroundCenter table) to Paint subtable. */ + F2DOT14 scaleX; + F2DOT14 scaleY; + FWORD centerX; + FWORD centerY; + public: + DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size + 2 * FWORD::static_size); +}; + +struct PaintScaleUniform +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 20 (noVar) or 21(Var) */ + Offset24To src; /* Offset (from beginning of PaintScaleUniform table) to Paint subtable. */ + F2DOT14 scale; + public: + DEFINE_SIZE_STATIC (4 + F2DOT14::static_size); +}; + +struct PaintScaleUniformAroundCenter +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } -struct LayerRecord + HBUINT8 format; /* format = 22 (noVar) or 23(Var) */ + Offset24To src; /* Offset (from beginning of PaintScaleUniformAroundCenter table) to Paint subtable. */ + F2DOT14 scale; + FWORD centerX; + FWORD centerY; + public: + DEFINE_SIZE_STATIC (4 + F2DOT14::static_size + 2 * FWORD::static_size); +}; + +struct PaintRotate { - operator hb_ot_color_layer_t () const { return {glyphId, colorIdx}; } + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 24 (noVar) or 25(Var) */ + Offset24To src; /* Offset (from beginning of PaintRotate table) to Paint subtable. */ + F2DOT14 angle; + public: + DEFINE_SIZE_STATIC (4 + F2DOT14::static_size); +}; + +struct PaintRotateAroundCenter +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 26 (noVar) or 27(Var) */ + Offset24To src; /* Offset (from beginning of PaintRotateAroundCenter table) to Paint subtable. */ + F2DOT14 angle; + FWORD centerX; + FWORD centerY; + public: + DEFINE_SIZE_STATIC (4 + F2DOT14::static_size + 2 * FWORD::static_size); +}; + +struct PaintSkew +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 28(noVar) or 29 (Var) */ + Offset24To src; /* Offset (from beginning of PaintSkew table) to Paint subtable. */ + F2DOT14 xSkewAngle; + F2DOT14 ySkewAngle; + public: + DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size); +}; + +struct PaintSkewAroundCenter +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 30(noVar) or 31 (Var) */ + Offset24To src; /* Offset (from beginning of PaintSkewAroundCenter table) to Paint subtable. */ + F2DOT14 xSkewAngle; + F2DOT14 ySkewAngle; + FWORD centerX; + FWORD centerY; + public: + DEFINE_SIZE_STATIC (4 + 2 * F2DOT14::static_size + 2 * FWORD::static_size); +}; + +struct PaintComposite +{ + void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + if (!out->src.serialize_subset (c, src, this)) return_trace (false); + return_trace (out->backdrop.serialize_subset (c, backdrop, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + src.sanitize (c, this) && + backdrop.sanitize (c, this)); + } + + HBUINT8 format; /* format = 32 */ + Offset24To src; /* Offset (from beginning of PaintComposite table) to source Paint subtable. */ + CompositeMode mode; /* If mode is unrecognized use COMPOSITE_CLEAR */ + Offset24To backdrop; /* Offset (from beginning of PaintComposite table) to backdrop Paint subtable. */ + public: + DEFINE_SIZE_STATIC (8); +}; +struct ClipBoxFormat1 +{ bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -51,45 +896,353 @@ } public: - HBGlyphID glyphId; /* Glyph ID of layer glyph */ - Index colorIdx; /* Index value to use with a - * selected color palette. - * An index value of 0xFFFF - * is a special case indicating - * that the text foreground - * color (defined by a - * higher-level client) should - * be used and shall not be - * treated as actual index - * into CPAL ColorRecord array. */ + HBUINT8 format; /* format = 1(noVar) or 2(Var)*/ + FWORD xMin; + FWORD yMin; + FWORD xMax; + FWORD yMax; public: - DEFINE_SIZE_STATIC (4); + DEFINE_SIZE_STATIC (1 + 4 * FWORD::static_size); }; -struct BaseGlyphRecord +struct ClipBoxFormat2 : Variable {}; + +struct ClipBox +{ + ClipBox* copy (hb_serialize_context_t *c) const + { + TRACE_SERIALIZE (this); + switch (u.format) { + case 1: return_trace (reinterpret_cast (c->embed (u.format1))); + case 2: return_trace (reinterpret_cast (c->embed (u.format2))); + default:return_trace (nullptr); + } + } + + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const + { + TRACE_DISPATCH (this, u.format); + if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { + case 1: return_trace (c->dispatch (u.format1, std::forward (ds)...)); + case 2: return_trace (c->dispatch (u.format2, std::forward (ds)...)); + default:return_trace (c->default_return_value ()); + } + } + + protected: + union { + HBUINT8 format; /* Format identifier */ + ClipBoxFormat1 format1; + ClipBoxFormat2 format2; + } u; +}; + +struct ClipRecord +{ + ClipRecord* copy (hb_serialize_context_t *c, const void *base) const + { + TRACE_SERIALIZE (this); + auto *out = c->embed (this); + if (unlikely (!out)) return_trace (nullptr); + if (!out->clipBox.serialize_copy (c, clipBox, base)) return_trace (nullptr); + return_trace (out); + } + + bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && clipBox.sanitize (c, base)); + } + + public: + HBUINT16 startGlyphID; // first gid clip applies to + HBUINT16 endGlyphID; // last gid clip applies to, inclusive + Offset24To clipBox; // Box or VarBox + public: + DEFINE_SIZE_STATIC (7); +}; + +struct ClipList +{ + unsigned serialize_clip_records (hb_serialize_context_t *c, + const hb_set_t& gids, + const hb_map_t& gid_offset_map) const + { + TRACE_SERIALIZE (this); + if (gids.is_empty () || + gid_offset_map.get_population () != gids.get_population ()) + return_trace (0); + + unsigned count = 0; + + hb_codepoint_t start_gid= gids.get_min (); + hb_codepoint_t prev_gid = start_gid; + + unsigned offset = gid_offset_map.get (start_gid); + unsigned prev_offset = offset; + for (const hb_codepoint_t _ : gids.iter ()) + { + if (_ == start_gid) continue; + + offset = gid_offset_map.get (_); + if (_ == prev_gid + 1 && offset == prev_offset) + { + prev_gid = _; + continue; + } + + ClipRecord record; + record.startGlyphID = start_gid; + record.endGlyphID = prev_gid; + record.clipBox = prev_offset; + + if (!c->copy (record, this)) return_trace (0); + count++; + + start_gid = _; + prev_gid = _; + prev_offset = offset; + } + + //last one + { + ClipRecord record; + record.startGlyphID = start_gid; + record.endGlyphID = prev_gid; + record.clipBox = prev_offset; + if (!c->copy (record, this)) return_trace (0); + count++; + } + return_trace (count); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + if (!c->serializer->check_assign (out->format, format, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false); + + const hb_set_t& glyphset = *c->plan->_glyphset_colred; + const hb_map_t &glyph_map = *c->plan->glyph_map; + + hb_map_t new_gid_offset_map; + hb_set_t new_gids; + for (const ClipRecord& record : clips.iter ()) + { + unsigned start_gid = record.startGlyphID; + unsigned end_gid = record.endGlyphID; + for (unsigned gid = start_gid; gid <= end_gid; gid++) + { + if (!glyphset.has (gid) || !glyph_map.has (gid)) continue; + unsigned new_gid = glyph_map.get (gid); + new_gid_offset_map.set (new_gid, record.clipBox); + new_gids.add (new_gid); + } + } + + unsigned count = serialize_clip_records (c->serializer, new_gids, new_gid_offset_map); + if (!count) return_trace (false); + return_trace (c->serializer->check_assign (out->clips.len, count, HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && clips.sanitize (c, this)); + } + + HBUINT8 format; // Set to 1. + Array32Of clips; // Clip records, sorted by startGlyphID + public: + DEFINE_SIZE_ARRAY_SIZED (5, clips); +}; + +struct Paint +{ + + template + bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const + { + TRACE_SANITIZE (this); + + if (unlikely (!c->check_start_recursion (HB_COLRV1_MAX_NESTING_LEVEL))) + return_trace (c->no_dispatch_return_value ()); + + return_trace (c->end_recursion (this->dispatch (c, std::forward (ds)...))); + } + + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const + { + TRACE_DISPATCH (this, u.format); + if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { + case 1: return_trace (c->dispatch (u.paintformat1, std::forward (ds)...)); + case 2: return_trace (c->dispatch (u.paintformat2, std::forward (ds)...)); + case 3: return_trace (c->dispatch (u.paintformat3, std::forward (ds)...)); + case 4: return_trace (c->dispatch (u.paintformat4, std::forward (ds)...)); + case 5: return_trace (c->dispatch (u.paintformat5, std::forward (ds)...)); + case 6: return_trace (c->dispatch (u.paintformat6, std::forward (ds)...)); + case 7: return_trace (c->dispatch (u.paintformat7, std::forward (ds)...)); + case 8: return_trace (c->dispatch (u.paintformat8, std::forward (ds)...)); + case 9: return_trace (c->dispatch (u.paintformat9, std::forward (ds)...)); + case 10: return_trace (c->dispatch (u.paintformat10, std::forward (ds)...)); + case 11: return_trace (c->dispatch (u.paintformat11, std::forward (ds)...)); + case 12: return_trace (c->dispatch (u.paintformat12, std::forward (ds)...)); + case 13: return_trace (c->dispatch (u.paintformat13, std::forward (ds)...)); + case 14: return_trace (c->dispatch (u.paintformat14, std::forward (ds)...)); + case 15: return_trace (c->dispatch (u.paintformat15, std::forward (ds)...)); + case 16: return_trace (c->dispatch (u.paintformat16, std::forward (ds)...)); + case 17: return_trace (c->dispatch (u.paintformat17, std::forward (ds)...)); + case 18: return_trace (c->dispatch (u.paintformat18, std::forward (ds)...)); + case 19: return_trace (c->dispatch (u.paintformat19, std::forward (ds)...)); + case 20: return_trace (c->dispatch (u.paintformat20, std::forward (ds)...)); + case 21: return_trace (c->dispatch (u.paintformat21, std::forward (ds)...)); + case 22: return_trace (c->dispatch (u.paintformat22, std::forward (ds)...)); + case 23: return_trace (c->dispatch (u.paintformat23, std::forward (ds)...)); + case 24: return_trace (c->dispatch (u.paintformat24, std::forward (ds)...)); + case 25: return_trace (c->dispatch (u.paintformat25, std::forward (ds)...)); + case 26: return_trace (c->dispatch (u.paintformat26, std::forward (ds)...)); + case 27: return_trace (c->dispatch (u.paintformat27, std::forward (ds)...)); + case 28: return_trace (c->dispatch (u.paintformat28, std::forward (ds)...)); + case 29: return_trace (c->dispatch (u.paintformat29, std::forward (ds)...)); + case 30: return_trace (c->dispatch (u.paintformat30, std::forward (ds)...)); + case 31: return_trace (c->dispatch (u.paintformat31, std::forward (ds)...)); + case 32: return_trace (c->dispatch (u.paintformat32, std::forward (ds)...)); + default:return_trace (c->default_return_value ()); + } + } + + protected: + union { + HBUINT8 format; + PaintColrLayers paintformat1; + PaintSolid paintformat2; + Variable paintformat3; + PaintLinearGradient paintformat4; + Variable> paintformat5; + PaintRadialGradient paintformat6; + Variable> paintformat7; + PaintSweepGradient paintformat8; + Variable> paintformat9; + PaintGlyph paintformat10; + PaintColrGlyph paintformat11; + PaintTransform paintformat12; + PaintTransform paintformat13; + PaintTranslate paintformat14; + Variable paintformat15; + PaintScale paintformat16; + Variable paintformat17; + PaintScaleAroundCenter paintformat18; + Variable paintformat19; + PaintScaleUniform paintformat20; + Variable paintformat21; + PaintScaleUniformAroundCenter paintformat22; + Variable paintformat23; + PaintRotate paintformat24; + Variable paintformat25; + PaintRotateAroundCenter paintformat26; + Variable paintformat27; + PaintSkew paintformat28; + Variable paintformat29; + PaintSkewAroundCenter paintformat30; + Variable paintformat31; + PaintComposite paintformat32; + } u; +}; + +struct BaseGlyphPaintRecord { int cmp (hb_codepoint_t g) const { return g < glyphId ? -1 : g > glyphId ? 1 : 0; } - bool sanitize (hb_sanitize_context_t *c) const + bool serialize (hb_serialize_context_t *s, const hb_map_t* glyph_map, + const void* src_base, hb_subset_context_t *c) const + { + TRACE_SERIALIZE (this); + auto *out = s->embed (this); + if (unlikely (!out)) return_trace (false); + if (!s->check_assign (out->glyphId, glyph_map->get (glyphId), + HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + + return_trace (out->paint.serialize_subset (c, paint, src_base)); + } + + bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); + return_trace (likely (c->check_struct (this) && paint.sanitize (c, base))); } public: - HBGlyphID glyphId; /* Glyph ID of reference glyph */ - HBUINT16 firstLayerIdx; /* Index (from beginning of - * the Layer Records) to the - * layer record. There will be - * numLayers consecutive entries - * for this base glyph. */ - HBUINT16 numLayers; /* Number of color layers - * associated with this glyph */ + HBGlyphID16 glyphId; /* Glyph ID of reference glyph */ + Offset32To paint; /* Offset (from beginning of BaseGlyphPaintRecord array) to Paint, + * Typically PaintColrLayers */ public: DEFINE_SIZE_STATIC (6); }; +struct BaseGlyphList : SortedArray32Of +{ + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + const hb_set_t* glyphset = c->plan->_glyphset_colred; + + for (const auto& _ : as_array ()) + { + unsigned gid = _.glyphId; + if (!glyphset->has (gid)) continue; + + if (_.serialize (c->serializer, c->plan->glyph_map, this, c)) out->len++; + else return_trace (false); + } + + return_trace (out->len != 0); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (SortedArray32Of::sanitize (c, this)); + } +}; + +struct LayerList : Array32OfOffset32To +{ + const Paint& get_paint (unsigned i) const + { return this+(*this)[i]; } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + for (const auto& _ : + hb_enumerate (*this) + | hb_filter (c->plan->colrv1_layers, hb_first)) + + { + auto *o = out->serialize_append (c->serializer); + if (unlikely (!o) || !o->serialize_subset (c, _.second, this)) + return_trace (false); + } + return_trace (true); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (Array32OfOffset32To::sanitize (c, this)); + } +}; + struct COLR { static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR; @@ -117,13 +1270,9 @@ struct accelerator_t { - accelerator_t () {} - ~accelerator_t () { fini (); } - - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { colr = hb_sanitize_context_t ().reference_table (face); } - - void fini () { this->colr.destroy (); } + ~accelerator_t () { this->colr.destroy (); } bool is_valid () { return colr.get_blob ()->length; } @@ -131,6 +1280,15 @@ hb_set_t *related_ids /* OUT */) const { colr->closure_glyphs (glyph, related_ids); } + void closure_V0palette_indices (const hb_set_t *glyphs, + hb_set_t *palettes /* OUT */) const + { colr->closure_V0palette_indices (glyphs, palettes); } + + void closure_forV1 (hb_set_t *glyphset, + hb_set_t *layer_indices, + hb_set_t *palette_indices) const + { colr->closure_forV1 (glyphset, layer_indices, palette_indices); } + private: hb_blob_ptr_t colr; }; @@ -147,33 +1305,88 @@ related_ids->add_array (&glyph_layers[0].glyphId, glyph_layers.length, LayerRecord::min_size); } + void closure_V0palette_indices (const hb_set_t *glyphs, + hb_set_t *palettes /* OUT */) const + { + if (!numBaseGlyphs || !numLayers) return; + hb_array_t baseGlyphs = (this+baseGlyphsZ).as_array (numBaseGlyphs); + hb_array_t all_layers = (this+layersZ).as_array (numLayers); + + for (const BaseGlyphRecord record : baseGlyphs) + { + if (!glyphs->has (record.glyphId)) continue; + hb_array_t glyph_layers = all_layers.sub_array (record.firstLayerIdx, + record.numLayers); + for (const LayerRecord layer : glyph_layers) + palettes->add (layer.colorIdx); + } + } + + void closure_forV1 (hb_set_t *glyphset, + hb_set_t *layer_indices, + hb_set_t *palette_indices) const + { + if (version != 1) return; + hb_set_t visited_glyphs; + + hb_colrv1_closure_context_t c (this, &visited_glyphs, layer_indices, palette_indices); + const BaseGlyphList &baseglyph_paintrecords = this+baseGlyphList; + + for (const BaseGlyphPaintRecord &baseglyph_paintrecord: baseglyph_paintrecords.iter ()) + { + unsigned gid = baseglyph_paintrecord.glyphId; + if (!glyphset->has (gid)) continue; + + const Paint &paint = &baseglyph_paintrecords+baseglyph_paintrecord.paint; + paint.dispatch (&c); + } + hb_set_union (glyphset, &visited_glyphs); + } + + const LayerList& get_layerList () const + { return (this+layerList); } + + const BaseGlyphList& get_baseglyphList () const + { return (this+baseGlyphList); } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && - (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) && - (this+layersZ).sanitize (c, numLayers))); + return_trace (c->check_struct (this) && + (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) && + (this+layersZ).sanitize (c, numLayers) && + (version == 0 || + (COLRV1_ENABLE_SUBSETTING && version == 1 && + baseGlyphList.sanitize (c, this) && + layerList.sanitize (c, this) && + clipList.sanitize (c, this) && + varIdxMap.sanitize (c, this) && + varStore.sanitize (c, this)))); } template - bool serialize (hb_serialize_context_t *c, - unsigned version, - BaseIterator base_it, - LayerIterator layer_it) + bool serialize_V0 (hb_serialize_context_t *c, + unsigned version, + BaseIterator base_it, + LayerIterator layer_it) { TRACE_SERIALIZE (this); if (unlikely (base_it.len () != layer_it.len ())) return_trace (false); - if (unlikely (!c->extend_min (this))) return_trace (false); this->version = version; numLayers = 0; numBaseGlyphs = base_it.len (); - baseGlyphsZ = COLR::min_size; - layersZ = COLR::min_size + numBaseGlyphs * BaseGlyphRecord::min_size; + if (numBaseGlyphs == 0) + { + baseGlyphsZ = 0; + layersZ = 0; + return_trace (true); + } + c->push (); for (const hb_item_type _ : + base_it.iter ()) { auto* record = c->embed (_); @@ -181,18 +1394,29 @@ record->firstLayerIdx = numLayers; numLayers += record->numLayers; } + c->add_link (baseGlyphsZ, c->pop_pack ()); + c->push (); for (const hb_item_type& _ : + layer_it.iter ()) _.as_array ().copy (c); + c->add_link (layersZ, c->pop_pack ()); + return_trace (true); } const BaseGlyphRecord* get_base_glyph_record (hb_codepoint_t gid) const { - if ((unsigned int) gid == 0) // Ignore notdef. - return nullptr; const BaseGlyphRecord* record = &(this+baseGlyphsZ).bsearch (numBaseGlyphs, (unsigned int) gid); + if (record == &Null (BaseGlyphRecord) || + (record && (hb_codepoint_t) record->glyphId != gid)) + record = nullptr; + return record; + } + + const BaseGlyphPaintRecord* get_base_glyph_paintrecord (hb_codepoint_t gid) const + { + const BaseGlyphPaintRecord* record = &(this+baseGlyphList).bsearch ((unsigned) gid); if ((record && (hb_codepoint_t) record->glyphId != gid)) record = nullptr; return record; @@ -203,9 +1427,16 @@ TRACE_SUBSET (this); const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map; + const hb_set_t& glyphset = *c->plan->_glyphset_colred; auto base_it = + hb_range (c->plan->num_output_glyphs ()) + | hb_filter ([&](hb_codepoint_t new_gid) + { + hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid); + if (glyphset.has (old_gid)) return true; + return false; + }) | hb_map_retains_sorting ([&](hb_codepoint_t new_gid) { hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid); @@ -213,7 +1444,6 @@ const BaseGlyphRecord* old_record = get_base_glyph_record (old_gid); if (unlikely (!old_record)) return hb_pair_t (false, Null (BaseGlyphRecord)); - BaseGlyphRecord new_record = {}; new_record.glyphId = new_gid; new_record.numLayers = old_record->numLayers; @@ -226,6 +1456,7 @@ auto layer_it = + hb_range (c->plan->num_output_glyphs ()) | hb_map (reverse_glyph_map) + | hb_filter (glyphset) | hb_map_retains_sorting ([&](hb_codepoint_t old_gid) { const BaseGlyphRecord* old_record = get_base_glyph_record (old_gid); @@ -245,6 +1476,7 @@ if (unlikely (!c->plan->new_gid_for_old_gid (out_layers[i].glyphId, &new_gid))) return hb_pair_t> (false, out_layers); out_layers[i].glyphId = new_gid; + out_layers[i].colorIdx = c->plan->colr_palettes->get (layers[i].colorIdx); } return hb_pair_t> (true, out_layers); @@ -253,23 +1485,54 @@ | hb_map_retains_sorting (hb_second) ; - if (unlikely (!base_it || !layer_it || base_it.len () != layer_it.len ())) + if (version == 0 && (!base_it || !layer_it)) return_trace (false); COLR *colr_prime = c->serializer->start_embed (); - return_trace (colr_prime->serialize (c->serializer, version, base_it, layer_it)); + if (unlikely (!c->serializer->extend_min (colr_prime))) return_trace (false); + + if (version == 0) + return_trace (colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)); + + auto snap = c->serializer->snapshot (); + if (!c->serializer->allocate_size (5 * HBUINT32::static_size)) return_trace (false); + if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this)) + { + if (c->serializer->in_error ()) return_trace (false); + //no more COLRv1 glyphs: downgrade to version 0 + c->serializer->revert (snap); + return_trace (colr_prime->serialize_V0 (c->serializer, 0, base_it, layer_it)); + } + + if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false); + + colr_prime->layerList.serialize_subset (c, layerList, this); + colr_prime->clipList.serialize_subset (c, clipList, this); + colr_prime->varIdxMap.serialize_copy (c->serializer, varIdxMap, this); + //TODO: subset varStore once it's implemented in fonttools + return_trace (true); } protected: HBUINT16 version; /* Table version number (starts at 0). */ HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */ - LNNOffsetTo> + NNOffset32To> baseGlyphsZ; /* Offset to Base Glyph records. */ - LNNOffsetTo> + NNOffset32To> layersZ; /* Offset to Layer Records. */ HBUINT16 numLayers; /* Number of Layer Records. */ + // Version-1 additions + Offset32To baseGlyphList; + Offset32To layerList; + Offset32To clipList; // Offset to ClipList table (may be NULL) + Offset32To varIdxMap; // Offset to DeltaSetIndexMap table (may be NULL) + Offset32To varStore; public: - DEFINE_SIZE_STATIC (14); + DEFINE_SIZE_MIN (14); +}; + +struct COLR_accelerator_t : COLR::accelerator_t { + COLR_accelerator_t (hb_face_t *face) : COLR::accelerator_t (face) {} }; } /* namespace OT */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-colrv1-closure.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-colrv1-closure.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-colrv1-closure.hh 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-colrv1-closure.hh 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,108 @@ +/* + * Copyright © 2018 Ebrahim Byagowi + * Copyright © 2020 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + */ + +#ifndef HB_OT_COLR_COLRV1_CLOSURE_HH +#define HB_OT_COLR_COLRV1_CLOSURE_HH + +#include "hb-open-type.hh" +#include "hb-ot-layout-common.hh" +#include "hb-ot-color-colr-table.hh" + +/* + * COLR -- Color + * https://docs.microsoft.com/en-us/typography/opentype/spec/colr + */ +namespace OT { + +HB_INTERNAL void PaintColrLayers::closurev1 (hb_colrv1_closure_context_t* c) const +{ + c->add_layer_indices (firstLayerIndex, numLayers); + const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList (); + for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++) + { + const Paint &paint = std::addressof (paint_offset_lists) + paint_offset_lists[i]; + paint.dispatch (c); + } +} + +HB_INTERNAL void PaintGlyph::closurev1 (hb_colrv1_closure_context_t* c) const +{ + c->add_glyph (gid); + (this+paint).dispatch (c); +} + +HB_INTERNAL void PaintColrGlyph::closurev1 (hb_colrv1_closure_context_t* c) const +{ + const COLR *colr_table = c->get_colr_table (); + const BaseGlyphPaintRecord* baseglyph_paintrecord = colr_table->get_base_glyph_paintrecord (gid); + if (!baseglyph_paintrecord) return; + c->add_glyph (gid); + + const BaseGlyphList &baseglyph_list = colr_table->get_baseglyphList (); + (&baseglyph_list+baseglyph_paintrecord->paint).dispatch (c); +} + +template class Var> +HB_INTERNAL void PaintTransform::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintTranslate::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintScale::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintScaleAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintScaleUniform::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintScaleUniformAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintRotate::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintRotateAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintSkew::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintSkewAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const +{ (this+src).dispatch (c); } + +HB_INTERNAL void PaintComposite::closurev1 (hb_colrv1_closure_context_t* c) const +{ + (this+src).dispatch (c); + (this+backdrop).dispatch (c); +} + +} /* namespace OT */ + + +#endif /* HB_OT_COLR_COLRV1_CLOSURE_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-cpal-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-cpal-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-cpal-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-cpal-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -39,7 +39,6 @@ */ #define HB_OT_TAG_CPAL HB_TAG('C','P','A','L') - namespace OT { @@ -74,6 +73,45 @@ } public: + bool serialize (hb_serialize_context_t *c, + unsigned palette_count, + unsigned color_count, + const void *base, + const hb_map_t *color_index_map) const + { + TRACE_SERIALIZE (this); + auto *out = c->allocate_size (static_size); + if (unlikely (!out)) return_trace (false); + + out->paletteFlagsZ = 0; + if (paletteFlagsZ) + out->paletteFlagsZ.serialize_copy (c, paletteFlagsZ, base, 0, hb_serialize_context_t::Head, palette_count); + + out->paletteLabelsZ = 0; + if (paletteLabelsZ) + out->paletteLabelsZ.serialize_copy (c, paletteLabelsZ, base, 0, hb_serialize_context_t::Head, palette_count); + + const hb_array_t colorLabels = (base+colorLabelsZ).as_array (color_count); + if (colorLabelsZ) + { + c->push (); + for (const auto _ : colorLabels) + { + const hb_codepoint_t *v; + if (!color_index_map->has (_, &v)) continue; + NameID new_color_idx; + new_color_idx = *v; + if (!c->copy (new_color_idx)) + { + c->pop_discard (); + return_trace (false); + } + } + c->add_link (out->colorLabelsZ, c->pop_pack ()); + } + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c, const void *base, unsigned int palette_count, @@ -87,15 +125,17 @@ } protected: - LNNOffsetTo> + // TODO(garretrieger): these offsets can hold nulls so we should not be using non-null offsets + // here. Currently they are needed since UnsizedArrayOf doesn't define null_size + NNOffset32To> paletteFlagsZ; /* Offset from the beginning of CPAL table to * the Palette Type Array. Set to 0 if no array * is provided. */ - LNNOffsetTo> + NNOffset32To> paletteLabelsZ; /* Offset from the beginning of CPAL table to * the palette labels array. Set to 0 if no * array is provided. */ - LNNOffsetTo> + NNOffset32To> colorLabelsZ; /* Offset from the beginning of CPAL table to * the color labels array. Set to 0 * if no array is provided. */ @@ -157,6 +197,98 @@ } public: + bool serialize (hb_serialize_context_t *c, + const hb_array_t &color_record_indices, + const hb_array_t &color_records, + const hb_vector_t& first_color_index_for_layer, + const hb_map_t& first_color_to_layer_index, + const hb_set_t &retained_color_indices) const + { + TRACE_SERIALIZE (this); + + // TODO(grieger): limit total final size. + + for (const auto idx : color_record_indices) + { + hb_codepoint_t layer_index = first_color_to_layer_index[idx]; + + HBUINT16 new_idx; + new_idx = layer_index * retained_color_indices.get_population (); + if (!c->copy (new_idx)) return_trace (false); + } + + c->push (); + for (unsigned first_color_index : first_color_index_for_layer) + { + for (hb_codepoint_t color_index : retained_color_indices) + { + if (!c->copy (color_records[first_color_index + color_index])) + { + c->pop_discard (); + return_trace (false); + } + } + } + + c->add_link (colorRecordsZ, c->pop_pack ()); + return_trace (true); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + if (!numPalettes) return_trace (false); + + const hb_map_t *color_index_map = c->plan->colr_palettes; + if (color_index_map->is_empty ()) return_trace (false); + + hb_set_t retained_color_indices; + for (const auto _ : color_index_map->keys ()) + { + if (_ == 0xFFFF) continue; + retained_color_indices.add (_); + } + if (retained_color_indices.is_empty ()) return_trace (false); + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + + out->version = version; + out->numColors = retained_color_indices.get_population (); + out->numPalettes = numPalettes; + + hb_vector_t first_color_index_for_layer; + hb_map_t first_color_to_layer_index; + + const hb_array_t colorRecordIndices = colorRecordIndicesZ.as_array (numPalettes); + for (const auto first_color_record_idx : colorRecordIndices) + { + if (first_color_to_layer_index.has (first_color_record_idx)) continue; + + first_color_index_for_layer.push (first_color_record_idx); + first_color_to_layer_index.set (first_color_record_idx, + first_color_index_for_layer.length - 1); + } + + out->numColorRecords = first_color_index_for_layer.length + * retained_color_indices.get_population (); + + const hb_array_t color_records = (this+colorRecordsZ).as_array (numColorRecords); + if (!out->serialize (c->serializer, + colorRecordIndices, + color_records, + first_color_index_for_layer, + first_color_to_layer_index, + retained_color_indices)) + return_trace (false); + + if (version == 1) + return_trace (v1 ().serialize (c->serializer, numPalettes, numColors, this, color_index_map)); + + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -173,7 +305,7 @@ HBUINT16 numPalettes; /* Number of palettes in the table. */ HBUINT16 numColorRecords; /* Total number of color records, combined for * all palettes. */ - LNNOffsetTo> + NNOffset32To> colorRecordsZ; /* Offset from the beginning of CPAL table to * the first ColorRecord. */ UnsizedArrayOf diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-sbix-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-sbix-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-sbix-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-sbix-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -145,7 +145,7 @@ auto* out = c->serializer->start_embed (); if (unlikely (!out)) return_trace (false); auto snap = c->serializer->snapshot (); - if (unlikely (!c->serializer->extend (*out, num_output_glyphs + 1))) return_trace (false); + if (unlikely (!c->serializer->extend (out, num_output_glyphs + 1))) return_trace (false); out->ppem = ppem; out->resolution = resolution; HBUINT32 head; @@ -185,7 +185,7 @@ HBUINT16 resolution; /* The device pixel density (in PPI) for which this * strike was designed. (E.g., 96 PPI, 192 PPI.) */ protected: - UnsizedArrayOf> + UnsizedArrayOf> imageOffsetsZ; /* Offset from the beginning of the strike data header * to bitmap data for an individual glyph ID. */ public: @@ -202,12 +202,12 @@ struct accelerator_t { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { table = hb_sanitize_context_t ().reference_table (face); num_glyphs = face->get_num_glyphs (); } - void fini () { table.destroy (); } + ~accelerator_t () { table.destroy (); } bool has_data () const { return table->has_data (); } @@ -298,6 +298,12 @@ const PNGHeader &png = *blob->as(); + if (png.IHDR.height >= 65536 || png.IHDR.width >= 65536) + { + hb_blob_destroy (blob); + return false; + } + extents->x_bearing = x_offset; extents->y_bearing = png.IHDR.height + y_offset; extents->width = png.IHDR.width; @@ -352,11 +358,11 @@ { TRACE_SERIALIZE (this); - auto *out = c->serializer->start_embed> (); + auto *out = c->serializer->start_embed> (); if (unlikely (!out)) return_trace (false); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); - hb_vector_t*> new_strikes; + hb_vector_t*> new_strikes; hb_vector_t objidxs; for (int i = strikes.len - 1; i >= 0; --i) { @@ -400,14 +406,17 @@ HBUINT16 version; /* Table version number — set to 1 */ HBUINT16 flags; /* Bit 0: Set to 1. Bit 1: Draw outlines. * Bits 2 to 15: reserved (set to 0). */ - LOffsetLArrayOf + Array32OfOffset32To strikes; /* Offsets from the beginning of the 'sbix' * table to data for each individual bitmap strike. */ public: DEFINE_SIZE_ARRAY (8, strikes); }; -struct sbix_accelerator_t : sbix::accelerator_t {}; +struct sbix_accelerator_t : sbix::accelerator_t { + sbix_accelerator_t (hb_face_t *face) : sbix::accelerator_t (face) {} +}; + } /* namespace OT */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-svg-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-svg-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-svg-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-color-svg-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -62,7 +62,7 @@ * this index entry. */ HBUINT16 endGlyphID; /* The last glyph ID in the range described by * this index entry. Must be >= startGlyphID. */ - LNNOffsetTo> + NNOffset32To> svgDoc; /* Offset from the beginning of the SVG Document Index * to an SVG document. Must be non-zero. */ HBUINT32 svgDocLength; /* Length of the SVG document. @@ -79,9 +79,9 @@ struct accelerator_t { - void init (hb_face_t *face) + accelerator_t (hb_face_t *face) { table = hb_sanitize_context_t ().reference_table (face); } - void fini () { table.destroy (); } + ~accelerator_t () { table.destroy (); } hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const { @@ -107,7 +107,7 @@ protected: HBUINT16 version; /* Table version (starting at 0). */ - LOffsetTo> + Offset32To> svgDocEntries; /* Offset (relative to the start of the SVG table) to the * SVG Documents Index. Must be non-zero. */ /* Array of SVG Document Index Entries. */ @@ -116,7 +116,9 @@ DEFINE_SIZE_STATIC (10); }; -struct SVG_accelerator_t : SVG::accelerator_t {}; +struct SVG_accelerator_t : SVG::accelerator_t { + SVG_accelerator_t (hb_face_t *face) : SVG::accelerator_t (face) {} +}; } /* namespace OT */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-deprecated.h openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-deprecated.h --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-deprecated.h 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-deprecated.h 2022-10-10 13:07:22.000000000 +0000 @@ -50,6 +50,21 @@ */ #define HB_MATH_GLYPH_PART_FLAG_EXTENDER HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER +/* https://github.com/harfbuzz/harfbuzz/pull/3417 */ +/** + * HB_OT_MATH_SCRIPT: + * + * Use #HB_SCRIPT_MATH or #HB_OT_TAG_MATH_SCRIPT instead. + * + * Previous versions of this documentation recommended passing + * #HB_OT_MATH_SCRIPT to hb_buffer_set_script() to enable math shaping, but this + * usage is no longer supported. Use #HB_SCRIPT_MATH instead. + * + * Since: 1.3.3 + * Deprecated: 3.4.0 + */ +#define HB_OT_MATH_SCRIPT HB_OT_TAG_MATH_SCRIPT + /* Like hb_ot_layout_table_find_script, but takes zero-terminated array of scripts to test */ HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_table_select_script) hb_bool_t diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-face.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-face.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-face.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-face.hh 2022-10-10 13:07:22.000000000 +0000 @@ -63,10 +63,13 @@ hb_face_t *face; /* MUST be JUST before the lazy loaders. */ #define HB_OT_TABLE(Namespace, Type) \ hb_table_lazy_loader_t Type; +#define HB_OT_CORE_TABLE(Namespace, Type) \ + hb_table_lazy_loader_t Type; #define HB_OT_ACCELERATOR(Namespace, Type) \ hb_face_lazy_loader_t Type; #include "hb-ot-face-table-list.hh" #undef HB_OT_ACCELERATOR +#undef HB_OT_CORE_TABLE #undef HB_OT_TABLE }; diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh 2022-10-10 13:07:22.000000000 +0000 @@ -32,6 +32,11 @@ #define HB_OT_FACE_TABLE_LIST_HH #endif /* HB_OT_FACE_TABLE_LIST_HH */ /* Dummy header guards */ +#ifndef HB_OT_CORE_TABLE +#define HB_OT_CORE_TABLE(Namespace, Type) HB_OT_TABLE (Namespace, Type) +#define _HB_OT_CORE_TABLE_UNDEF +#endif + #ifndef HB_OT_ACCELERATOR #define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type) #define _HB_OT_ACCELERATOR_UNDEF @@ -40,13 +45,14 @@ /* This lists font tables that the hb_face_t will contain and lazily * load. Don't add a table unless it's used though. This is not - * exactly free. */ + * exactly zero-cost. */ /* v--- Add new tables in the right place here. */ /* OpenType fundamentals. */ -HB_OT_TABLE (OT, head) +HB_OT_CORE_TABLE (OT, head) +HB_OT_CORE_TABLE (OT, maxp) #if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT) HB_OT_ACCELERATOR (OT, cmap) #endif @@ -67,17 +73,20 @@ #endif /* Vertical layout. */ +#ifndef HB_NO_VERTICAL HB_OT_TABLE (OT, vhea) HB_OT_ACCELERATOR (OT, vmtx) +HB_OT_TABLE (OT, VORG) +#endif /* TrueType outlines. */ +HB_OT_CORE_TABLE (OT, loca) // Also used to determine number of glyphs HB_OT_ACCELERATOR (OT, glyf) /* CFF outlines. */ #ifndef HB_NO_CFF HB_OT_ACCELERATOR (OT, cff1) HB_OT_ACCELERATOR (OT, cff2) -HB_OT_TABLE (OT, VORG) #endif /* OpenType variations. */ @@ -136,3 +145,7 @@ #ifdef _HB_OT_ACCELERATOR_UNDEF #undef HB_OT_ACCELERATOR #endif + +#ifdef _HB_OT_CORE_TABLE_UNDEF +#undef HB_OT_CORE_TABLE +#endif diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc 2022-10-10 13:07:22.000000000 +0000 @@ -30,6 +30,7 @@ #include "hb-ot.h" +#include "hb-cache.hh" #include "hb-font.hh" #include "hb-machinery.hh" #include "hb-ot-face.hh" @@ -58,6 +59,41 @@ * never need to call these functions directly. **/ +struct hb_ot_font_t +{ + const hb_ot_face_t *ot_face; + + /* h_advance caching */ + mutable hb_atomic_int_t cached_coords_serial; + mutable hb_atomic_ptr_t advance_cache; +}; + +static hb_ot_font_t * +_hb_ot_font_create (hb_font_t *font) +{ + hb_ot_font_t *ot_font = (hb_ot_font_t *) hb_calloc (1, sizeof (hb_ot_font_t)); + if (unlikely (!ot_font)) + return nullptr; + + ot_font->ot_face = &font->face->table; + + return ot_font; +} + +static void +_hb_ot_font_destroy (void *font_data) +{ + hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data; + + auto *cache = ot_font->advance_cache.get_relaxed (); + if (cache) + { + cache->fini (); + hb_free (cache); + } + + hb_free (ot_font); +} static hb_bool_t hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED, @@ -66,7 +102,8 @@ hb_codepoint_t *glyph, void *user_data HB_UNUSED) { - const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + const hb_ot_face_t *ot_face = ot_font->ot_face; return ot_face->cmap->get_nominal_glyph (unicode, glyph); } @@ -80,7 +117,8 @@ unsigned int glyph_stride, void *user_data HB_UNUSED) { - const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + const hb_ot_face_t *ot_face = ot_font->ot_face; return ot_face->cmap->get_nominal_glyphs (count, first_unicode, unicode_stride, first_glyph, glyph_stride); @@ -94,7 +132,8 @@ hb_codepoint_t *glyph, void *user_data HB_UNUSED) { - const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + const hb_ot_face_t *ot_face = ot_font->ot_face; return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph); } @@ -107,17 +146,86 @@ unsigned advance_stride, void *user_data HB_UNUSED) { - const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + const hb_ot_face_t *ot_face = ot_font->ot_face; const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx; - for (unsigned int i = 0; i < count; i++) +#ifndef HB_NO_VAR + const OT::HVARVVAR &HVAR = *hmtx.var_table; + const OT::VariationStore &varStore = &HVAR + HVAR.varStore; + OT::VariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr; + + bool use_cache = font->num_coords; +#else + OT::VariationStore::cache_t *varStore_cache = nullptr; + bool use_cache = false; +#endif + + hb_advance_cache_t *cache = nullptr; + if (use_cache) + { + retry: + cache = ot_font->advance_cache.get (); + if (unlikely (!cache)) + { + cache = (hb_advance_cache_t *) hb_malloc (sizeof (hb_advance_cache_t)); + if (unlikely (!cache)) + { + use_cache = false; + goto out; + } + + cache->init (); + if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache))) + { + hb_free (cache); + goto retry; + } + ot_font->cached_coords_serial.set (font->serial_coords); + } + } + out: + + if (!use_cache) { - *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font)); - first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); - first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font, varStore_cache)); + first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } + } + else + { /* Use cache. */ + if (ot_font->cached_coords_serial.get () != (int) font->serial_coords) + { + ot_font->advance_cache->init (); + ot_font->cached_coords_serial.set (font->serial_coords); + } + + for (unsigned int i = 0; i < count; i++) + { + hb_position_t v; + unsigned cv; + if (ot_font->advance_cache->get (*first_glyph, &cv)) + v = cv; + else + { + v = hmtx.get_advance (*first_glyph, font, varStore_cache); + ot_font->advance_cache->set (*first_glyph, v); + } + *first_advance = font->em_scale_x (v); + first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } } + +#ifndef HB_NO_VAR + OT::VariationStore::destroy_cache (varStore_cache); +#endif } +#ifndef HB_NO_VERTICAL static void hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, unsigned count, @@ -127,17 +235,48 @@ unsigned advance_stride, void *user_data HB_UNUSED) { - const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + const hb_ot_face_t *ot_face = ot_font->ot_face; const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; - for (unsigned int i = 0; i < count; i++) + if (vmtx.has_data ()) { - *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font)); - first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); - first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); +#ifndef HB_NO_VAR + const OT::HVARVVAR &VVAR = *vmtx.var_table; + const OT::VariationStore &varStore = &VVAR + VVAR.varStore; + OT::VariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr; +#else + OT::VariationStore::cache_t *varStore_cache = nullptr; +#endif + + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font, varStore_cache)); + first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } + +#ifndef HB_NO_VAR + OT::VariationStore::destroy_cache (varStore_cache); +#endif + } + else + { + hb_font_extents_t font_extents; + font->get_h_extents_with_fallback (&font_extents); + hb_position_t advance = -(font_extents.ascender - font_extents.descender); + + for (unsigned int i = 0; i < count; i++) + { + *first_advance = advance; + first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride); + first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride); + } } } +#endif +#ifndef HB_NO_VERTICAL static hb_bool_t hb_ot_get_glyph_v_origin (hb_font_t *font, void *font_data, @@ -146,25 +285,34 @@ hb_position_t *y, void *user_data HB_UNUSED) { - const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + const hb_ot_face_t *ot_face = ot_font->ot_face; *x = font->get_glyph_h_advance (glyph) / 2; -#ifndef HB_NO_OT_FONT_CFF const OT::VORG &VORG = *ot_face->VORG; if (VORG.has_data ()) { *y = font->em_scale_y (VORG.get_y_origin (glyph)); return true; } -#endif hb_glyph_extents_t extents = {0}; if (ot_face->glyf->get_extents (font, glyph, &extents)) { - const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; - hb_position_t tsb = vmtx.get_side_bearing (font, glyph); - *y = extents.y_bearing + font->em_scale_y (tsb); + if (ot_face->vmtx->has_data ()) + { + const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; + hb_position_t tsb = vmtx.get_side_bearing (font, glyph); + *y = extents.y_bearing + font->em_scale_y (tsb); + return true; + } + + hb_font_extents_t font_extents; + font->get_h_extents_with_fallback (&font_extents); + hb_position_t advance = font_extents.ascender - font_extents.descender; + int diff = advance - -extents.height; + *y = extents.y_bearing + (diff >> 1); return true; } @@ -174,6 +322,7 @@ return true; } +#endif static hb_bool_t hb_ot_get_glyph_extents (hb_font_t *font, @@ -182,7 +331,8 @@ hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { - const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + const hb_ot_face_t *ot_face = ot_font->ot_face; #if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR) if (ot_face->sbix->get_extents (font, glyph, extents)) return true; @@ -208,7 +358,9 @@ char *name, unsigned int size, void *user_data HB_UNUSED) { - const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + const hb_ot_face_t *ot_face = ot_font->ot_face; + if (ot_face->post->get_glyph_name (glyph, name, size)) return true; #ifndef HB_NO_OT_FONT_CFF if (ot_face->cff1->get_glyph_name (glyph, name, size)) return true; @@ -222,7 +374,9 @@ hb_codepoint_t *glyph, void *user_data HB_UNUSED) { - const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data; + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + const hb_ot_face_t *ot_face = ot_font->ot_face; + if (ot_face->post->get_glyph_from_name (name, len, glyph)) return true; #ifndef HB_NO_OT_FONT_CFF if (ot_face->cff1->get_glyph_from_name (name, len, glyph)) return true; @@ -242,6 +396,7 @@ _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap); } +#ifndef HB_NO_VERTICAL static hb_bool_t hb_ot_get_font_v_extents (hb_font_t *font, void *font_data HB_UNUSED, @@ -252,10 +407,26 @@ _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_DESCENDER, &metrics->descender) && _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap); } +#endif -#if HB_USE_ATEXIT -static void free_static_ot_funcs (); +#ifndef HB_NO_DRAW +static void +hb_ot_get_glyph_shape (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_draw_funcs_t *draw_funcs, void *draw_data, + void *user_data) +{ + hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy); + if (font->face->table.glyf->get_path (font, glyph, draw_session)) return; +#ifndef HB_NO_CFF + if (font->face->table.cff1->get_path (font, glyph, draw_session)) return; + if (font->face->table.cff2->get_path (font, glyph, draw_session)) return; #endif +} +#endif + +static inline void free_static_ot_funcs (); static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t { @@ -263,17 +434,27 @@ { hb_font_funcs_t *funcs = hb_font_funcs_create (); - hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr); - hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr); hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr); hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr); hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr); + + hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr); hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr); - hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr); //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr); + +#ifndef HB_NO_VERTICAL + hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr); + hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr); hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr); +#endif + +#ifndef HB_NO_DRAW + hb_font_funcs_set_glyph_shape_func (funcs, hb_ot_get_glyph_shape, nullptr, nullptr); +#endif + hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr); //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr); + #ifndef HB_NO_OT_FONT_GLYPH_NAMES hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr); hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr); @@ -281,21 +462,17 @@ hb_font_funcs_make_immutable (funcs); -#if HB_USE_ATEXIT - atexit (free_static_ot_funcs); -#endif + hb_atexit (free_static_ot_funcs); return funcs; } } static_ot_funcs; -#if HB_USE_ATEXIT -static +static inline void free_static_ot_funcs () { static_ot_funcs.free_instance (); } -#endif static hb_font_funcs_t * _hb_ot_get_font_funcs () @@ -315,10 +492,14 @@ void hb_ot_font_set_funcs (hb_font_t *font) { + hb_ot_font_t *ot_font = _hb_ot_font_create (font); + if (unlikely (!ot_font)) + return; + hb_font_set_funcs (font, _hb_ot_get_font_funcs (), - &font->face->table, - nullptr); + ot_font, + _hb_ot_font_destroy); } #ifndef HB_NO_VAR diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-gasp-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-gasp-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-gasp-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-gasp-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -71,7 +71,7 @@ protected: HBUINT16 version; /* Version number (set to 1) */ - ArrayOf + Array16Of gaspRanges; /* Number of records to follow * Sorted by ppem */ public: diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-glyf-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-glyf-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-glyf-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-glyf-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -30,1232 +30,6 @@ #ifndef HB_OT_GLYF_TABLE_HH #define HB_OT_GLYF_TABLE_HH -#include "hb-open-type.hh" -#include "hb-ot-head-table.hh" -#include "hb-ot-hmtx-table.hh" -#include "hb-ot-var-gvar-table.hh" -#include "hb-draw.hh" - -namespace OT { - - -/* - * loca -- Index to Location - * https://docs.microsoft.com/en-us/typography/opentype/spec/loca - */ -#define HB_OT_TAG_loca HB_TAG('l','o','c','a') - - -struct loca -{ - friend struct glyf; - - static constexpr hb_tag_t tableTag = HB_OT_TAG_loca; - - bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const - { - TRACE_SANITIZE (this); - return_trace (true); - } - - protected: - UnsizedArrayOf - dataZ; /* Location data. */ - public: - DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always - * check the size externally, allow Null() object of it by - * defining it _MIN instead. */ -}; - - -/* - * glyf -- TrueType Glyph Data - * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf - */ -#define HB_OT_TAG_glyf HB_TAG('g','l','y','f') - - -struct glyf -{ - static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf; - - bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const - { - TRACE_SANITIZE (this); - /* Runtime checks as eager sanitizing each glyph is costy */ - return_trace (true); - } - - template - static bool - _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets) - { - unsigned max_offset = - + padded_offsets - | hb_reduce (hb_add, 0) - ; - unsigned num_offsets = padded_offsets.len () + 1; - bool use_short_loca = max_offset < 0x1FFFF; - unsigned entry_size = use_short_loca ? 2 : 4; - char *loca_prime_data = (char *) calloc (entry_size, num_offsets); - - if (unlikely (!loca_prime_data)) return false; - - DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d " - "max_offset %d size %d", - entry_size, num_offsets, max_offset, entry_size * num_offsets); - - if (use_short_loca) - _write_loca (padded_offsets, 1, hb_array ((HBUINT16 *) loca_prime_data, num_offsets)); - else - _write_loca (padded_offsets, 0, hb_array ((HBUINT32 *) loca_prime_data, num_offsets)); - - hb_blob_t *loca_blob = hb_blob_create (loca_prime_data, - entry_size * num_offsets, - HB_MEMORY_MODE_WRITABLE, - loca_prime_data, - free); - - bool result = plan->add_table (HB_OT_TAG_loca, loca_blob) - && _add_head_and_set_loca_version (plan, use_short_loca); - - hb_blob_destroy (loca_blob); - return result; - } - - template - static void - _write_loca (IteratorIn it, unsigned right_shift, IteratorOut dest) - { - unsigned int offset = 0; - dest << 0; - + it - | hb_map ([=, &offset] (unsigned int padded_size) - { - offset += padded_size; - DEBUG_MSG (SUBSET, nullptr, "loca entry offset %d", offset); - return offset >> right_shift; - }) - | hb_sink (dest) - ; - } - - /* requires source of SubsetGlyph complains the identifier isn't declared */ - template - bool serialize (hb_serialize_context_t *c, - Iterator it, - const hb_subset_plan_t *plan) - { - TRACE_SERIALIZE (this); - unsigned init_len = c->length (); - for (const auto &_ : it) _.serialize (c, plan); - - /* As a special case when all glyph in the font are empty, add a zero byte - * to the table, so that OTS doesn’t reject it, and to make the table work - * on Windows as well. - * See https://github.com/khaledhosny/ots/issues/52 */ - if (init_len == c->length ()) - { - HBUINT8 empty_byte; - empty_byte = 0; - c->copy (empty_byte); - } - return_trace (true); - } - - /* Byte region(s) per glyph to output - unpadded, hints removed if so requested - If we fail to process a glyph we produce an empty (0-length) glyph */ - bool subset (hb_subset_context_t *c) const - { - TRACE_SUBSET (this); - - glyf *glyf_prime = c->serializer->start_embed (); - if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false); - - hb_vector_t glyphs; - _populate_subset_glyphs (c->plan, &glyphs); - - glyf_prime->serialize (c->serializer, hb_iter (glyphs), c->plan); - - auto padded_offsets = - + hb_iter (glyphs) - | hb_map (&SubsetGlyph::padded_size) - ; - - if (unlikely (c->serializer->in_error ())) return_trace (false); - return_trace (c->serializer->check_success (_add_loca_and_head (c->plan, - padded_offsets))); - } - - template - void - _populate_subset_glyphs (const hb_subset_plan_t *plan, - hb_vector_t *glyphs /* OUT */) const - { - OT::glyf::accelerator_t glyf; - glyf.init (plan->source); - - + hb_range (plan->num_output_glyphs ()) - | hb_map ([&] (hb_codepoint_t new_gid) - { - SubsetGlyph subset_glyph = {0}; - subset_glyph.new_gid = new_gid; - - /* should never fail: all old gids should be mapped */ - if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid)) - return subset_glyph; - - subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true); - if (plan->drop_hints) subset_glyph.drop_hints_bytes (); - else subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes (); - - return subset_glyph; - }) - | hb_sink (glyphs) - ; - - glyf.fini (); - } - - static bool - _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca) - { - hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table (plan->source); - hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob); - hb_blob_destroy (head_blob); - - if (unlikely (!head_prime_blob)) - return false; - - head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr); - head_prime->indexToLocFormat = use_short_loca ? 0 : 1; - bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob); - - hb_blob_destroy (head_prime_blob); - return success; - } - - struct CompositeGlyphChain - { - protected: - enum composite_glyph_flag_t - { - ARG_1_AND_2_ARE_WORDS = 0x0001, - ARGS_ARE_XY_VALUES = 0x0002, - ROUND_XY_TO_GRID = 0x0004, - WE_HAVE_A_SCALE = 0x0008, - MORE_COMPONENTS = 0x0020, - WE_HAVE_AN_X_AND_Y_SCALE = 0x0040, - WE_HAVE_A_TWO_BY_TWO = 0x0080, - WE_HAVE_INSTRUCTIONS = 0x0100, - USE_MY_METRICS = 0x0200, - OVERLAP_COMPOUND = 0x0400, - SCALED_COMPONENT_OFFSET = 0x0800, - UNSCALED_COMPONENT_OFFSET = 0x1000 - }; - - public: - unsigned int get_size () const - { - unsigned int size = min_size; - /* arg1 and 2 are int16 */ - if (flags & ARG_1_AND_2_ARE_WORDS) size += 4; - /* arg1 and 2 are int8 */ - else size += 2; - - /* One x 16 bit (scale) */ - if (flags & WE_HAVE_A_SCALE) size += 2; - /* Two x 16 bit (xscale, yscale) */ - else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4; - /* Four x 16 bit (xscale, scale01, scale10, yscale) */ - else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8; - - return size; - } - - void set_glyph_index (hb_codepoint_t new_gid) { glyphIndex = new_gid; } - hb_codepoint_t get_glyph_index () const { return glyphIndex; } - - void drop_instructions_flag () { flags = (uint16_t) flags & ~WE_HAVE_INSTRUCTIONS; } - bool has_instructions () const { return flags & WE_HAVE_INSTRUCTIONS; } - - bool has_more () const { return flags & MORE_COMPONENTS; } - bool is_use_my_metrics () const { return flags & USE_MY_METRICS; } - bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); } - void get_anchor_points (unsigned int &point1, unsigned int &point2) const - { - const HBUINT8 *p = &StructAfter (glyphIndex); - if (flags & ARG_1_AND_2_ARE_WORDS) - { - point1 = ((const HBUINT16 *) p)[0]; - point2 = ((const HBUINT16 *) p)[1]; - } - else - { - point1 = p[0]; - point2 = p[1]; - } - } - - void transform_points (contour_point_vector_t &points) const - { - float matrix[4]; - contour_point_t trans; - if (get_transformation (matrix, trans)) - { - if (scaled_offsets ()) - { - points.translate (trans); - points.transform (matrix); - } - else - { - points.transform (matrix); - points.translate (trans); - } - } - } - - protected: - bool scaled_offsets () const - { return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; } - - bool get_transformation (float (&matrix)[4], contour_point_t &trans) const - { - matrix[0] = matrix[3] = 1.f; - matrix[1] = matrix[2] = 0.f; - - int tx, ty; - const HBINT8 *p = &StructAfter (glyphIndex); - if (flags & ARG_1_AND_2_ARE_WORDS) - { - tx = *(const HBINT16 *) p; - p += HBINT16::static_size; - ty = *(const HBINT16 *) p; - p += HBINT16::static_size; - } - else - { - tx = *p++; - ty = *p++; - } - if (is_anchored ()) tx = ty = 0; - - trans.init ((float) tx, (float) ty); - - { - const F2DOT14 *points = (const F2DOT14 *) p; - if (flags & WE_HAVE_A_SCALE) - { - matrix[0] = matrix[3] = points[0].to_float (); - return true; - } - else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) - { - matrix[0] = points[0].to_float (); - matrix[3] = points[1].to_float (); - return true; - } - else if (flags & WE_HAVE_A_TWO_BY_TWO) - { - matrix[0] = points[0].to_float (); - matrix[1] = points[1].to_float (); - matrix[2] = points[2].to_float (); - matrix[3] = points[3].to_float (); - return true; - } - } - return tx || ty; - } - - protected: - HBUINT16 flags; - HBGlyphID glyphIndex; - public: - DEFINE_SIZE_MIN (4); - }; - - struct composite_iter_t : hb_iter_with_fallback_t - { - typedef const CompositeGlyphChain *__item_t__; - composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) : - glyph (glyph_), current (current_) - { if (!check_range (current)) current = nullptr; } - composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr) {} - - const CompositeGlyphChain &__item__ () const { return *current; } - bool __more__ () const { return current; } - void __next__ () - { - if (!current->has_more ()) { current = nullptr; return; } - - const CompositeGlyphChain *possible = &StructAfter (*current); - if (!check_range (possible)) { current = nullptr; return; } - current = possible; - } - bool operator != (const composite_iter_t& o) const - { return glyph != o.glyph || current != o.current; } - - bool check_range (const CompositeGlyphChain *composite) const - { - return glyph.check_range (composite, CompositeGlyphChain::min_size) - && glyph.check_range (composite, composite->get_size ()); - } - - private: - hb_bytes_t glyph; - __item_t__ current; - }; - - enum phantom_point_index_t - { - PHANTOM_LEFT = 0, - PHANTOM_RIGHT = 1, - PHANTOM_TOP = 2, - PHANTOM_BOTTOM = 3, - PHANTOM_COUNT = 4 - }; - - struct accelerator_t; - - struct Glyph - { - enum simple_glyph_flag_t - { - FLAG_ON_CURVE = 0x01, - FLAG_X_SHORT = 0x02, - FLAG_Y_SHORT = 0x04, - FLAG_REPEAT = 0x08, - FLAG_X_SAME = 0x10, - FLAG_Y_SAME = 0x20, - FLAG_RESERVED1 = 0x40, - FLAG_RESERVED2 = 0x80 - }; - - private: - struct GlyphHeader - { - bool has_data () const { return numberOfContours; } - - bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator, - hb_codepoint_t gid, hb_glyph_extents_t *extents) const - { - /* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */ - /* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */ - extents->x_bearing = font->em_scale_x (glyf_accelerator.hmtx->get_side_bearing (gid)); - extents->y_bearing = font->em_scale_y (hb_max (yMin, yMax)); - extents->width = font->em_scale_x (hb_max (xMin, xMax) - hb_min (xMin, xMax)); - extents->height = font->em_scale_y (hb_min (yMin, yMax) - hb_max (yMin, yMax)); - - return true; - } - - HBINT16 numberOfContours; - /* If the number of contours is - * greater than or equal to zero, - * this is a simple glyph; if negative, - * this is a composite glyph. */ - FWORD xMin; /* Minimum x for coordinate data. */ - FWORD yMin; /* Minimum y for coordinate data. */ - FWORD xMax; /* Maximum x for coordinate data. */ - FWORD yMax; /* Maximum y for coordinate data. */ - public: - DEFINE_SIZE_STATIC (10); - }; - - struct SimpleGlyph - { - const GlyphHeader &header; - hb_bytes_t bytes; - SimpleGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) : - header (header_), bytes (bytes_) {} - - unsigned int instruction_len_offset () const - { return GlyphHeader::static_size + 2 * header.numberOfContours; } - - unsigned int length (unsigned int instruction_len) const - { return instruction_len_offset () + 2 + instruction_len; } - - unsigned int instructions_length () const - { - unsigned int instruction_length_offset = instruction_len_offset (); - if (unlikely (instruction_length_offset + 2 > bytes.length)) return 0; - - const HBUINT16 &instructionLength = StructAtOffset (&bytes, instruction_length_offset); - /* Out of bounds of the current glyph */ - if (unlikely (length (instructionLength) > bytes.length)) return 0; - return instructionLength; - } - - const Glyph trim_padding () const - { - /* based on FontTools _g_l_y_f.py::trim */ - const char *glyph = bytes.arrayZ; - const char *glyph_end = glyph + bytes.length; - /* simple glyph w/contours, possibly trimmable */ - glyph += instruction_len_offset (); - - if (unlikely (glyph + 2 >= glyph_end)) return Glyph (); - unsigned int num_coordinates = StructAtOffset (glyph - 2, 0) + 1; - unsigned int num_instructions = StructAtOffset (glyph, 0); - - glyph += 2 + num_instructions; - - unsigned int coord_bytes = 0; - unsigned int coords_with_flags = 0; - while (glyph < glyph_end) - { - uint8_t flag = *glyph; - glyph++; - - unsigned int repeat = 1; - if (flag & FLAG_REPEAT) - { - if (unlikely (glyph >= glyph_end)) return Glyph (); - repeat = *glyph + 1; - glyph++; - } - - unsigned int xBytes, yBytes; - xBytes = yBytes = 0; - if (flag & FLAG_X_SHORT) xBytes = 1; - else if ((flag & FLAG_X_SAME) == 0) xBytes = 2; - - if (flag & FLAG_Y_SHORT) yBytes = 1; - else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2; - - coord_bytes += (xBytes + yBytes) * repeat; - coords_with_flags += repeat; - if (coords_with_flags >= num_coordinates) break; - } - - if (unlikely (coords_with_flags != num_coordinates)) return Glyph (); - return Glyph (bytes.sub_array (0, bytes.length + coord_bytes - (glyph_end - glyph))); - } - - /* zero instruction length */ - void drop_hints () - { - GlyphHeader &glyph_header = const_cast (header); - (HBUINT16 &) StructAtOffset (&glyph_header, instruction_len_offset ()) = 0; - } - - void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const - { - unsigned int instructions_len = instructions_length (); - unsigned int glyph_length = length (instructions_len); - dest_start = bytes.sub_array (0, glyph_length - instructions_len); - dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length); - } - - static bool read_points (const HBUINT8 *&p /* IN/OUT */, - contour_point_vector_t &points_ /* IN/OUT */, - const hb_bytes_t &bytes, - void (* setter) (contour_point_t &_, float v), - const simple_glyph_flag_t short_flag, - const simple_glyph_flag_t same_flag) - { - float v = 0; - for (unsigned i = 0; i < points_.length; i++) - { - uint8_t flag = points_[i].flag; - if (flag & short_flag) - { - if (unlikely (!bytes.check_range (p))) return false; - if (flag & same_flag) - v += *p++; - else - v -= *p++; - } - else - { - if (!(flag & same_flag)) - { - if (unlikely (!bytes.check_range ((const HBUINT16 *) p))) return false; - v += *(const HBINT16 *) p; - p += HBINT16::static_size; - } - } - setter (points_[i], v); - } - return true; - } - - bool get_contour_points (contour_point_vector_t &points_ /* OUT */, - bool phantom_only = false) const - { - const HBUINT16 *endPtsOfContours = &StructAfter (header); - int num_contours = header.numberOfContours; - if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours + 1]))) return false; - unsigned int num_points = endPtsOfContours[num_contours - 1] + 1; - - points_.resize (num_points); - for (unsigned int i = 0; i < points_.length; i++) points_[i].init (); - if (phantom_only) return true; - - for (int i = 0; i < num_contours; i++) - points_[endPtsOfContours[i]].is_end_point = true; - - /* Skip instructions */ - const HBUINT8 *p = &StructAtOffset (&endPtsOfContours[num_contours + 1], - endPtsOfContours[num_contours]); - - /* Read flags */ - for (unsigned int i = 0; i < num_points; i++) - { - if (unlikely (!bytes.check_range (p))) return false; - uint8_t flag = *p++; - points_[i].flag = flag; - if (flag & FLAG_REPEAT) - { - if (unlikely (!bytes.check_range (p))) return false; - unsigned int repeat_count = *p++; - while ((repeat_count-- > 0) && (++i < num_points)) - points_[i].flag = flag; - } - } - - /* Read x & y coordinates */ - return read_points (p, points_, bytes, [] (contour_point_t &p, float v) { p.x = v; }, - FLAG_X_SHORT, FLAG_X_SAME) - && read_points (p, points_, bytes, [] (contour_point_t &p, float v) { p.y = v; }, - FLAG_Y_SHORT, FLAG_Y_SAME); - } - }; - - struct CompositeGlyph - { - const GlyphHeader &header; - hb_bytes_t bytes; - CompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) : - header (header_), bytes (bytes_) {} - - composite_iter_t get_iterator () const - { return composite_iter_t (bytes, &StructAfter (header)); } - - unsigned int instructions_length (hb_bytes_t bytes) const - { - unsigned int start = bytes.length; - unsigned int end = bytes.length; - const CompositeGlyphChain *last = nullptr; - for (auto &item : get_iterator ()) - last = &item; - if (unlikely (!last)) return 0; - - if (last->has_instructions ()) - start = (char *) last - &bytes + last->get_size (); - if (unlikely (start > end)) return 0; - return end - start; - } - - /* Trimming for composites not implemented. - * If removing hints it falls out of that. */ - const Glyph trim_padding () const { return Glyph (bytes); } - - void drop_hints () - { - for (const auto &_ : get_iterator ()) - const_cast (_).drop_instructions_flag (); - } - - /* Chop instructions off the end */ - void drop_hints_bytes (hb_bytes_t &dest_start) const - { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); } - }; - - enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE }; - - public: - composite_iter_t get_composite_iterator () const - { - if (type != COMPOSITE) return composite_iter_t (); - return CompositeGlyph (*header, bytes).get_iterator (); - } - - const Glyph trim_padding () const - { - switch (type) { - case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding (); - case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding (); - default: return bytes; - } - } - - void drop_hints () - { - switch (type) { - case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return; - case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return; - default: return; - } - } - - void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const - { - switch (type) { - case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return; - case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return; - default: return; - } - } - - /* Note: Recursively calls itself. - * all_points includes phantom points - */ - bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator, - contour_point_vector_t &all_points /* OUT */, - bool phantom_only = false, - unsigned int depth = 0) const - { - if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false; - contour_point_vector_t points; - - switch (type) { - case COMPOSITE: - { - /* pseudo component points for each component in composite glyph */ - unsigned num_points = hb_len (CompositeGlyph (*header, bytes).get_iterator ()); - if (unlikely (!points.resize (num_points))) return false; - for (unsigned i = 0; i < points.length; i++) - points[i].init (); - break; - } - case SIMPLE: - if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only))) - return false; - break; - } - - /* Init phantom points */ - if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false; - hb_array_t phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT); - { - for (unsigned i = 0; i < PHANTOM_COUNT; ++i) phantoms[i].init (); - int h_delta = (int) header->xMin - glyf_accelerator.hmtx->get_side_bearing (gid); - int v_orig = (int) header->yMax + glyf_accelerator.vmtx->get_side_bearing (gid); - unsigned h_adv = glyf_accelerator.hmtx->get_advance (gid); - unsigned v_adv = glyf_accelerator.vmtx->get_advance (gid); - phantoms[PHANTOM_LEFT].x = h_delta; - phantoms[PHANTOM_RIGHT].x = h_adv + h_delta; - phantoms[PHANTOM_TOP].y = v_orig; - phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv; - } - -#ifndef HB_NO_VAR - if (unlikely (!glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ()))) - return false; -#endif - - switch (type) { - case SIMPLE: - all_points.extend (points.as_array ()); - break; - case COMPOSITE: - { - unsigned int comp_index = 0; - for (auto &item : get_composite_iterator ()) - { - contour_point_vector_t comp_points; - if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_glyph_index ()) - .get_points (font, glyf_accelerator, comp_points, - phantom_only, depth + 1) - || comp_points.length < PHANTOM_COUNT)) - return false; - - /* Copy phantom points from component if USE_MY_METRICS flag set */ - if (item.is_use_my_metrics ()) - for (unsigned int i = 0; i < PHANTOM_COUNT; i++) - phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i]; - - /* Apply component transformation & translation */ - item.transform_points (comp_points); - - /* Apply translation from gvar */ - comp_points.translate (points[comp_index]); - - if (item.is_anchored ()) - { - unsigned int p1, p2; - item.get_anchor_points (p1, p2); - if (likely (p1 < all_points.length && p2 < comp_points.length)) - { - contour_point_t delta; - delta.init (all_points[p1].x - comp_points[p2].x, - all_points[p1].y - comp_points[p2].y); - - comp_points.translate (delta); - } - } - - all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT)); - - comp_index++; - } - - all_points.extend (phantoms); - } break; - default: - all_points.extend (phantoms); - } - - if (depth == 0) /* Apply at top level */ - { - /* Undocumented rasterizer behavior: - * Shift points horizontally by the updated left side bearing - */ - contour_point_t delta; - delta.init (-phantoms[PHANTOM_LEFT].x, 0.f); - if (delta.x) all_points.translate (delta); - } - - return true; - } - - bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator, - hb_glyph_extents_t *extents) const - { - if (type == EMPTY) return true; /* Empty glyph; zero extents. */ - return header->get_extents (font, glyf_accelerator, gid, extents); - } - - hb_bytes_t get_bytes () const { return bytes; } - - Glyph (hb_bytes_t bytes_ = hb_bytes_t (), - hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_), gid (gid_), - header (bytes.as ()) - { - int num_contours = header->numberOfContours; - if (unlikely (num_contours == 0)) type = EMPTY; - else if (num_contours > 0) type = SIMPLE; - else type = COMPOSITE; /* negative numbers */ - } - - protected: - hb_bytes_t bytes; - hb_codepoint_t gid; - const GlyphHeader *header; - unsigned type; - }; - - struct accelerator_t - { - void init (hb_face_t *face_) - { - short_offset = false; - num_glyphs = 0; - loca_table = nullptr; - glyf_table = nullptr; -#ifndef HB_NO_VAR - gvar = nullptr; -#endif - hmtx = nullptr; - vmtx = nullptr; - face = face_; - const OT::head &head = *face->table.head; - if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0) - /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */ - return; - short_offset = 0 == head.indexToLocFormat; - - loca_table = hb_sanitize_context_t ().reference_table (face); - glyf_table = hb_sanitize_context_t ().reference_table (face); -#ifndef HB_NO_VAR - gvar = face->table.gvar; -#endif - hmtx = face->table.hmtx; - vmtx = face->table.vmtx; - - num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1; - num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ()); - } - - void fini () - { - loca_table.destroy (); - glyf_table.destroy (); - } - - protected: - template - bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const - { - if (gid >= num_glyphs) return false; - - /* Making this alloc free is not that easy - https://github.com/harfbuzz/harfbuzz/issues/2095 - mostly because of gvar handling in VF fonts, - perhaps a separate path for non-VF fonts can be considered */ - contour_point_vector_t all_points; - - bool phantom_only = !consumer.is_consuming_contour_points (); - if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, phantom_only))) - return false; - - if (consumer.is_consuming_contour_points ()) - { - for (unsigned point_index = 0; point_index + 4 < all_points.length; ++point_index) - consumer.consume_point (all_points[point_index]); - consumer.points_end (); - } - - /* Where to write phantoms, nullptr if not requested */ - contour_point_t *phantoms = consumer.get_phantoms_sink (); - if (phantoms) - for (unsigned i = 0; i < PHANTOM_COUNT; ++i) - phantoms[i] = all_points[all_points.length - PHANTOM_COUNT + i]; - - return true; - } - -#ifndef HB_NO_VAR - struct points_aggregator_t - { - hb_font_t *font; - hb_glyph_extents_t *extents; - contour_point_t *phantoms; - - struct contour_bounds_t - { - contour_bounds_t () { min_x = min_y = FLT_MAX; max_x = max_y = -FLT_MAX; } - - void add (const contour_point_t &p) - { - min_x = hb_min (min_x, p.x); - min_y = hb_min (min_y, p.y); - max_x = hb_max (max_x, p.x); - max_y = hb_max (max_y, p.y); - } - - bool empty () const { return (min_x >= max_x) || (min_y >= max_y); } - - void get_extents (hb_font_t *font, hb_glyph_extents_t *extents) - { - if (unlikely (empty ())) - { - extents->width = 0; - extents->x_bearing = 0; - extents->height = 0; - extents->y_bearing = 0; - return; - } - extents->x_bearing = font->em_scalef_x (min_x); - extents->width = font->em_scalef_x (max_x) - extents->x_bearing; - extents->y_bearing = font->em_scalef_y (max_y); - extents->height = font->em_scalef_y (min_y) - extents->y_bearing; - } - - protected: - float min_x, min_y, max_x, max_y; - } bounds; - - points_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_) - { - font = font_; - extents = extents_; - phantoms = phantoms_; - if (extents) bounds = contour_bounds_t (); - } - - void consume_point (const contour_point_t &point) { bounds.add (point); } - void points_end () { bounds.get_extents (font, extents); } - - bool is_consuming_contour_points () { return extents; } - contour_point_t *get_phantoms_sink () { return phantoms; } - }; - - public: - unsigned - get_advance_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const - { - if (unlikely (gid >= num_glyphs)) return 0; - - bool success = false; - - contour_point_t phantoms[PHANTOM_COUNT]; - if (likely (font->num_coords == gvar->get_axis_count ())) - success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms)); - - if (unlikely (!success)) - return is_vertical ? vmtx->get_advance (gid) : hmtx->get_advance (gid); - - float result = is_vertical - ? phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y - : phantoms[PHANTOM_RIGHT].x - phantoms[PHANTOM_LEFT].x; - return hb_clamp (roundf (result), 0.f, (float) UINT_MAX / 2); - } - - int get_side_bearing_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const - { - if (unlikely (gid >= num_glyphs)) return 0; - - hb_glyph_extents_t extents; - - contour_point_t phantoms[PHANTOM_COUNT]; - if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms)))) - return is_vertical ? vmtx->get_side_bearing (gid) : hmtx->get_side_bearing (gid); - - return is_vertical - ? ceilf (phantoms[PHANTOM_TOP].y) - extents.y_bearing - : floorf (phantoms[PHANTOM_LEFT].x); - } -#endif - - public: - bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const - { - if (unlikely (gid >= num_glyphs)) return false; - -#ifndef HB_NO_VAR - if (font->num_coords && font->num_coords == gvar->get_axis_count ()) - return get_points (font, gid, points_aggregator_t (font, extents, nullptr)); -#endif - return glyph_for_gid (gid).get_extents (font, *this, extents); - } - - const Glyph - glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const - { - if (unlikely (gid >= num_glyphs)) return Glyph (); - - unsigned int start_offset, end_offset; - - if (short_offset) - { - const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ; - start_offset = 2 * offsets[gid]; - end_offset = 2 * offsets[gid + 1]; - } - else - { - const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ; - start_offset = offsets[gid]; - end_offset = offsets[gid + 1]; - } - - if (unlikely (start_offset > end_offset || end_offset > glyf_table.get_length ())) - return Glyph (); - - Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset, - end_offset - start_offset), gid); - return needs_padding_removal ? glyph.trim_padding () : glyph; - } - - void - add_gid_and_children (hb_codepoint_t gid, hb_set_t *gids_to_retain, - unsigned int depth = 0) const - { - if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return; - /* Check if is already visited */ - if (gids_to_retain->has (gid)) return; - - gids_to_retain->add (gid); - - for (auto &item : glyph_for_gid (gid).get_composite_iterator ()) - add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth); - } - -#ifdef HB_EXPERIMENTAL_API - struct path_builder_t - { - hb_font_t *font; - draw_helper_t *draw_helper; - - struct optional_point_t - { - optional_point_t () { has_data = false; } - optional_point_t (float x_, float y_) { x = x_; y = y_; has_data = true; } - - bool has_data; - float x; - float y; - - optional_point_t lerp (optional_point_t p, float t) - { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); } - } first_oncurve, first_offcurve, last_offcurve; - - path_builder_t (hb_font_t *font_, draw_helper_t &draw_helper_) - { - font = font_; - draw_helper = &draw_helper_; - first_oncurve = first_offcurve = last_offcurve = optional_point_t (); - } - - /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287 - See also: - * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html - * https://stackoverflow.com/a/20772557 */ - void consume_point (const contour_point_t &point) - { - /* Skip empty contours */ - if (unlikely (point.is_end_point && !first_oncurve.has_data && !first_offcurve.has_data)) - return; - - bool is_on_curve = point.flag & Glyph::FLAG_ON_CURVE; - optional_point_t p (point.x, point.y); - if (!first_oncurve.has_data) - { - if (is_on_curve) - { - first_oncurve = p; - draw_helper->move_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y)); - } - else - { - if (first_offcurve.has_data) - { - optional_point_t mid = first_offcurve.lerp (p, .5f); - first_oncurve = mid; - last_offcurve = p; - draw_helper->move_to (font->em_scalef_x (mid.x), font->em_scalef_y (mid.y)); - } - else - first_offcurve = p; - } - } - else - { - if (last_offcurve.has_data) - { - if (is_on_curve) - { - draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y), - font->em_scalef_x (p.x), font->em_scalef_y (p.y)); - last_offcurve = optional_point_t (); - } - else - { - optional_point_t mid = last_offcurve.lerp (p, .5f); - draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y), - font->em_scalef_x (mid.x), font->em_scalef_y (mid.y)); - last_offcurve = p; - } - } - else - { - if (is_on_curve) - draw_helper->line_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y)); - else - last_offcurve = p; - } - } - - if (point.is_end_point) - { - if (first_offcurve.has_data && last_offcurve.has_data) - { - optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f); - draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y), - font->em_scalef_x (mid.x), font->em_scalef_y (mid.y)); - last_offcurve = optional_point_t (); - /* now check the rest */ - } - - if (first_offcurve.has_data && first_oncurve.has_data) - draw_helper->quadratic_to (font->em_scalef_x (first_offcurve.x), font->em_scalef_y (first_offcurve.y), - font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y)); - else if (last_offcurve.has_data && first_oncurve.has_data) - draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y), - font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y)); - else if (first_oncurve.has_data) - draw_helper->line_to (font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y)); - - /* Getting ready for the next contour */ - first_oncurve = first_offcurve = last_offcurve = optional_point_t (); - draw_helper->end_path (); - } - } - void points_end () {} - - bool is_consuming_contour_points () { return true; } - contour_point_t *get_phantoms_sink () { return nullptr; } - }; - - bool - get_path (hb_font_t *font, hb_codepoint_t gid, draw_helper_t &draw_helper) const - { return get_points (font, gid, path_builder_t (font, draw_helper)); } -#endif - -#ifndef HB_NO_VAR - const gvar_accelerator_t *gvar; -#endif - const hmtx_accelerator_t *hmtx; - const vmtx_accelerator_t *vmtx; - - private: - bool short_offset; - unsigned int num_glyphs; - hb_blob_ptr_t loca_table; - hb_blob_ptr_t glyf_table; - hb_face_t *face; - }; - - struct SubsetGlyph - { - hb_codepoint_t new_gid; - hb_codepoint_t old_gid; - Glyph source_glyph; - hb_bytes_t dest_start; /* region of source_glyph to copy first */ - hb_bytes_t dest_end; /* region of source_glyph to copy second */ - - bool serialize (hb_serialize_context_t *c, - const hb_subset_plan_t *plan) const - { - TRACE_SERIALIZE (this); - - hb_bytes_t dest_glyph = dest_start.copy (c); - dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length); - unsigned int pad_length = padding (); - DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length); - - HBUINT8 pad; - pad = 0; - while (pad_length > 0) - { - c->embed (pad); - pad_length--; - } - - if (unlikely (!dest_glyph.length)) return_trace (true); - - /* update components gids */ - for (auto &_ : Glyph (dest_glyph).get_composite_iterator ()) - { - hb_codepoint_t new_gid; - if (plan->new_gid_for_old_gid (_.get_glyph_index (), &new_gid)) - const_cast (_).set_glyph_index (new_gid); - } - - if (plan->drop_hints) Glyph (dest_glyph).drop_hints (); - - return_trace (true); - } - - void drop_hints_bytes () - { source_glyph.drop_hints_bytes (dest_start, dest_end); } - - unsigned int length () const { return dest_start.length + dest_end.length; } - /* pad to 2 to ensure 2-byte loca will be ok */ - unsigned int padding () const { return length () % 2; } - unsigned int padded_size () const { return length () + padding (); } - }; - - protected: - UnsizedArrayOf - dataZ; /* Glyphs data. */ - public: - DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always - * check the size externally, allow Null() object of it by - * defining it _MIN instead. */ -}; - -struct glyf_accelerator_t : glyf::accelerator_t {}; - -} /* namespace OT */ - +#include "OT/glyf/glyf.hh" #endif /* HB_OT_GLYF_TABLE_HH */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -52,7 +52,7 @@ unsigned length = it.len (); - if (unlikely (!c->extend (*this, length))) return_trace (false); + if (unlikely (!c->extend (this, length))) return_trace (false); this->pixelSize = pixelSize; this->maxWidth = @@ -110,7 +110,7 @@ for (const hb_item_type& _ : +it) c->start_embed ()->serialize (c, _.first, _.second); - return_trace (c->successful); + return_trace (c->successful ()); } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -72,12 +72,14 @@ UNDERLINE = 1u<<2, OUTLINE = 1u<<3, SHADOW = 1u<<4, - CONDENSED = 1u<<5 + CONDENSED = 1u<<5, + EXPANDED = 1u<<6, }; bool is_bold () const { return macStyle & BOLD; } bool is_italic () const { return macStyle & ITALIC; } bool is_condensed () const { return macStyle & CONDENSED; } + bool is_expanded () const { return macStyle & EXPANDED; } bool sanitize (hb_sanitize_context_t *c) const { diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -28,6 +28,7 @@ #define HB_OT_HMTX_TABLE_HH #include "hb-open-type.hh" +#include "hb-ot-maxp-table.hh" #include "hb-ot-hhea-table.hh" #include "hb-ot-var-hvar-table.hh" #include "hb-ot-metrics.hh" @@ -98,12 +99,12 @@ hb_requires (hb_is_iterator (Iterator))> void serialize (hb_serialize_context_t *c, Iterator it, - unsigned num_advances) + unsigned num_long_metrics) { unsigned idx = 0; for (auto _ : it) { - if (idx < num_advances) + if (idx < num_long_metrics) { LongMetric lm; lm.advance = _.first; @@ -127,9 +128,20 @@ T *table_prime = c->serializer->start_embed (); if (unlikely (!table_prime)) return_trace (false); - accelerator_t _mtx; - _mtx.init (c->plan->source); - unsigned num_advances = _mtx.num_advances_for_subset (c->plan); + accelerator_t _mtx (c->plan->source); + unsigned num_long_metrics; + { + /* Determine num_long_metrics to encode. */ + auto& plan = c->plan; + num_long_metrics = plan->num_output_glyphs (); + hb_codepoint_t old_gid = 0; + unsigned int last_advance = plan->old_gid_for_new_gid (num_long_metrics - 1, &old_gid) ? _mtx.get_advance (old_gid) : 0; + while (num_long_metrics > 1 && + last_advance == (plan->old_gid_for_new_gid (num_long_metrics - 2, &old_gid) ? _mtx.get_advance (old_gid) : 0)) + { + num_long_metrics--; + } + } auto it = + hb_range (c->plan->num_output_glyphs ()) @@ -142,15 +154,13 @@ }) ; - table_prime->serialize (c->serializer, it, num_advances); - - _mtx.fini (); + table_prime->serialize (c->serializer, it, num_long_metrics); - if (unlikely (c->serializer->ran_out_of_room || c->serializer->in_error ())) + if (unlikely (c->serializer->in_error ())) return_trace (false); // Amend header num hmetrics - if (unlikely (!subset_update_header (c->plan, num_advances))) + if (unlikely (!subset_update_header (c->plan, num_long_metrics))) return_trace (false); return_trace (true); @@ -160,49 +170,67 @@ { friend struct hmtxvmtx; - void init (hb_face_t *face, - unsigned int default_advance_ = 0) + accelerator_t (hb_face_t *face) { - default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face); + table = hb_sanitize_context_t ().reference_table (face, T::tableTag); + var_table = hb_sanitize_context_t ().reference_table (face, T::variationsTag); - num_advances = T::is_horizontal ? face->table.hhea->numberOfLongMetrics : face->table.vhea->numberOfLongMetrics; + default_advance = T::is_horizontal ? hb_face_get_upem (face) / 2 : hb_face_get_upem (face); - table = hb_sanitize_context_t ().reference_table (face, T::tableTag); + /* Populate count variables and sort them out as we go */ - /* Cap num_metrics() and num_advances() based on table length. */ unsigned int len = table.get_length (); - if (unlikely (num_advances * 4 > len)) - num_advances = len / 4; - num_metrics = num_advances + (len - 4 * num_advances) / 2; + if (len & 1) + len--; + + num_long_metrics = T::is_horizontal ? + face->table.hhea->numberOfLongMetrics : +#ifndef HB_NO_VERTICAL + face->table.vhea->numberOfLongMetrics +#else + 0 +#endif + ; + if (unlikely (num_long_metrics * 4 > len)) + num_long_metrics = len / 4; + len -= num_long_metrics * 4; + + num_bearings = face->table.maxp->get_num_glyphs (); + + if (unlikely (num_bearings < num_long_metrics)) + num_bearings = num_long_metrics; + if (unlikely ((num_bearings - num_long_metrics) * 2 > len)) + num_bearings = num_long_metrics + len / 2; + len -= (num_bearings - num_long_metrics) * 2; - /* We MUST set num_metrics to zero if num_advances is zero. + /* We MUST set num_bearings to zero if num_long_metrics is zero. * Our get_advance() depends on that. */ - if (unlikely (!num_advances)) - { - num_metrics = num_advances = 0; - table.destroy (); - table = hb_blob_get_empty (); - } + if (unlikely (!num_long_metrics)) + num_bearings = num_long_metrics = 0; - var_table = hb_sanitize_context_t ().reference_table (face, T::variationsTag); + num_advances = num_bearings + len / 2; + num_glyphs = face->get_num_glyphs (); + if (num_glyphs < num_advances) + num_glyphs = num_advances; } - - void fini () + ~accelerator_t () { table.destroy (); var_table.destroy (); } + bool has_data () const { return (bool) num_bearings; } + int get_side_bearing (hb_codepoint_t glyph) const { - if (glyph < num_advances) + if (glyph < num_long_metrics) return table->longMetricZ[glyph].sb; - if (unlikely (glyph >= num_metrics)) + if (unlikely (glyph >= num_bearings)) return 0; - const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances]; - return bearings[glyph - num_advances]; + const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics]; + return bearings[glyph - num_long_metrics]; } int get_side_bearing (hb_font_t *font, hb_codepoint_t glyph) const @@ -210,11 +238,11 @@ int side_bearing = get_side_bearing (glyph); #ifndef HB_NO_VAR - if (unlikely (glyph >= num_metrics) || !font->num_coords) + if (unlikely (glyph >= num_bearings) || !font->num_coords) return side_bearing; if (var_table.get_length ()) - return side_bearing + var_table->get_side_bearing_var (glyph, font->coords, font->num_coords); // TODO Optimize?! + return side_bearing + var_table->get_side_bearing_var (glyph, font->coords, font->num_coords); return _glyf_get_side_bearing_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx); #else @@ -224,31 +252,49 @@ unsigned int get_advance (hb_codepoint_t glyph) const { - if (unlikely (glyph >= num_metrics)) - { - /* If num_metrics is zero, it means we don't have the metrics table - * for this direction: return default advance. Otherwise, it means that the - * glyph index is out of bound: return zero. */ - if (num_metrics) - return 0; - else - return default_advance; - } + /* OpenType case. */ + if (glyph < num_bearings) + return table->longMetricZ[hb_min (glyph, (uint32_t) num_long_metrics - 1)].advance; + + /* If num_advances is zero, it means we don't have the metrics table + * for this direction: return default advance. Otherwise, there's a + * well-defined answer. */ + if (unlikely (!num_advances)) + return default_advance; + +#ifdef HB_NO_BORING_EXPANSION + return 0; +#endif + + if (unlikely (glyph >= num_glyphs)) + return 0; + + /* num_bearings <= glyph < num_glyphs; + * num_bearings <= num_advances */ + + /* TODO Optimize */ + + if (num_bearings == num_advances) + return get_advance (num_bearings - 1); - return table->longMetricZ[hb_min (glyph, (uint32_t) num_advances - 1)].advance; + const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics]; + const UFWORD *advances = (const UFWORD *) &bearings[num_bearings - num_long_metrics]; + + return advances[hb_min (glyph - num_bearings, num_advances - num_bearings - 1)]; } unsigned int get_advance (hb_codepoint_t glyph, - hb_font_t *font) const + hb_font_t *font, + VariationStore::cache_t *store_cache = nullptr) const { unsigned int advance = get_advance (glyph); #ifndef HB_NO_VAR - if (unlikely (glyph >= num_metrics) || !font->num_coords) + if (unlikely (glyph >= num_bearings) || !font->num_coords) return advance; if (var_table.get_length ()) - return advance + roundf (var_table->get_advance_var (glyph, font)); // TODO Optimize?! + return advance + roundf (var_table->get_advance_var (glyph, font, store_cache)); // TODO Optimize?! return _glyf_get_advance_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx); #else @@ -256,38 +302,16 @@ #endif } - unsigned int num_advances_for_subset (const hb_subset_plan_t *plan) const - { - unsigned int num_advances = plan->num_output_glyphs (); - unsigned int last_advance = _advance_for_new_gid (plan, - num_advances - 1); - while (num_advances > 1 && - last_advance == _advance_for_new_gid (plan, - num_advances - 2)) - { - num_advances--; - } - - return num_advances; - } - - private: - unsigned int _advance_for_new_gid (const hb_subset_plan_t *plan, - hb_codepoint_t new_gid) const - { - hb_codepoint_t old_gid; - if (!plan->old_gid_for_new_gid (new_gid, &old_gid)) - return 0; - - return get_advance (old_gid); - } - protected: - unsigned int num_metrics; - unsigned int num_advances; + // 0 <= num_long_metrics <= num_bearings <= num_advances <= num_glyphs + unsigned num_long_metrics; + unsigned num_bearings; + unsigned num_advances; + unsigned num_glyphs; + unsigned int default_advance; - private: + public: hb_blob_ptr_t table; hb_blob_ptr_t var_table; }; @@ -316,6 +340,8 @@ * the end. This allows a monospaced * font to vary the side bearing * values for each glyph. */ +/*UnsizedArrayOfadvancesX;*/ + /* TODO Document. */ public: DEFINE_SIZE_ARRAY (0, longMetricZ); }; @@ -331,8 +357,12 @@ static constexpr bool is_horizontal = false; }; -struct hmtx_accelerator_t : hmtx::accelerator_t {}; -struct vmtx_accelerator_t : vmtx::accelerator_t {}; +struct hmtx_accelerator_t : hmtx::accelerator_t { + hmtx_accelerator_t (hb_face_t *face) : hmtx::accelerator_t (face) {} +}; +struct vmtx_accelerator_t : vmtx::accelerator_t { + vmtx_accelerator_t (hb_face_t *face) : vmtx::accelerator_t (face) {} +}; } /* namespace OT */ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -134,11 +134,11 @@ switch (subtable_type) { case 0: return_trace (c->dispatch (u.format0)); #ifndef HB_NO_AAT_SHAPE - case 1: return_trace (u.header.apple ? c->dispatch (u.format1, hb_forward (ds)...) : c->default_return_value ()); + case 1: return_trace (u.header.apple ? c->dispatch (u.format1, std::forward (ds)...) : c->default_return_value ()); #endif case 2: return_trace (c->dispatch (u.format2)); #ifndef HB_NO_AAT_SHAPE - case 3: return_trace (u.header.apple ? c->dispatch (u.format3, hb_forward (ds)...) : c->default_return_value ()); + case 3: return_trace (u.header.apple ? c->dispatch (u.format3, std::forward (ds)...) : c->default_return_value ()); #endif default: return_trace (c->default_return_value ()); } @@ -325,9 +325,9 @@ unsigned int subtable_type = get_type (); TRACE_DISPATCH (this, subtable_type); switch (subtable_type) { - case 0: return_trace (c->dispatch (u.ot, hb_forward (ds)...)); + case 0: return_trace (c->dispatch (u.ot, std::forward (ds)...)); #ifndef HB_NO_AAT_SHAPE - case 1: return_trace (c->dispatch (u.aat, hb_forward (ds)...)); + case 1: return_trace (c->dispatch (u.aat, std::forward (ds)...)); #endif default: return_trace (c->default_return_value ()); } diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh 2022-10-10 13:07:22.000000000 +0000 @@ -41,7 +41,10 @@ struct BaseCoordFormat1 { - hb_position_t get_coord () const { return coordinate; } + hb_position_t get_coord (hb_font_t *font, hb_direction_t direction) const + { + return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate); + } bool sanitize (hb_sanitize_context_t *c) const { @@ -58,10 +61,10 @@ struct BaseCoordFormat2 { - hb_position_t get_coord () const + hb_position_t get_coord (hb_font_t *font, hb_direction_t direction) const { /* TODO */ - return coordinate; + return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate); } bool sanitize (hb_sanitize_context_t *c) const @@ -73,7 +76,7 @@ protected: HBUINT16 format; /* Format identifier--format = 2 */ FWORD coordinate; /* X or Y value, in design units */ - HBGlyphID referenceGlyph; /* Glyph ID of control glyph */ + HBGlyphID16 referenceGlyph; /* Glyph ID of control glyph */ HBUINT16 coordPoint; /* Index of contour point on the * reference glyph */ public: @@ -87,9 +90,10 @@ hb_direction_t direction) const { const Device &device = this+deviceTable; - return coordinate + (HB_DIRECTION_IS_VERTICAL (direction) ? - device.get_y_delta (font, var_store) : - device.get_x_delta (font, var_store)); + + return HB_DIRECTION_IS_HORIZONTAL (direction) + ? font->em_scale_y (coordinate) + device.get_y_delta (font, var_store) + : font->em_scale_x (coordinate) + device.get_x_delta (font, var_store); } @@ -103,7 +107,7 @@ protected: HBUINT16 format; /* Format identifier--format = 3 */ FWORD coordinate; /* X or Y value, in design units */ - OffsetTo + Offset16To deviceTable; /* Offset to Device table for X or * Y value, from beginning of * BaseCoord table (may be NULL). */ @@ -120,8 +124,8 @@ hb_direction_t direction) const { switch (u.format) { - case 1: return u.format1.get_coord (); - case 2: return u.format2.get_coord (); + case 1: return u.format1.get_coord (font, direction); + case 2: return u.format2.get_coord (font, direction); case 3: return u.format3.get_coord (font, var_store, direction); default:return 0; } @@ -173,11 +177,11 @@ protected: Tag tag; /* 4-byte feature identification tag--must * match feature tag in FeatureList */ - OffsetTo + Offset16To minCoord; /* Offset to BaseCoord table that defines * the minimum extent value, from beginning * of MinMax table (may be NULL) */ - OffsetTo + Offset16To maxCoord; /* Offset to BaseCoord table that defines * the maximum extent value, from beginning * of MinMax table (may be NULL) */ @@ -212,15 +216,15 @@ } protected: - OffsetTo + Offset16To minCoord; /* Offset to BaseCoord table that defines * minimum extent value, from the beginning * of MinMax table (may be NULL) */ - OffsetTo + Offset16To maxCoord; /* Offset to BaseCoord table that defines * maximum extent value, from the beginning * of MinMax table (may be NULL) */ - SortedArrayOf + SortedArray16Of featMinMaxRecords; /* Array of FeatMinMaxRecords, in alphabetical * order by featureTableTag */ @@ -247,7 +251,7 @@ Index defaultIndex; /* Index number of default baseline for this * script — equals index position of baseline tag * in baselineTags array of the BaseTagList */ - OffsetArrayOf + Array16OfOffset16To baseCoords; /* Number of BaseCoord tables defined — should equal * baseTagCount in the BaseTagList * @@ -275,7 +279,7 @@ protected: Tag baseLangSysTag; /* 4-byte language system identification tag */ - OffsetTo + Offset16To minMax; /* Offset to MinMax table, from beginning * of BaseScript table */ public: @@ -305,13 +309,13 @@ } protected: - OffsetTo + Offset16To baseValues; /* Offset to BaseValues table, from beginning * of BaseScript table (may be NULL) */ - OffsetTo + Offset16To defaultMinMax; /* Offset to MinMax table, from beginning of * BaseScript table (may be NULL) */ - SortedArrayOf + SortedArray16Of baseLangSysRecords; /* Number of BaseLangSysRecords * defined — may be zero (0) */ @@ -339,7 +343,7 @@ protected: Tag baseScriptTag; /* 4-byte script identification tag */ - OffsetTo + Offset16To baseScript; /* Offset to BaseScript table, from beginning * of BaseScriptList */ @@ -364,7 +368,7 @@ } protected: - SortedArrayOf + SortedArray16Of baseScriptRecords; public: @@ -426,12 +430,12 @@ } protected: - OffsetTo> + Offset16To> baseTagList; /* Offset to BaseTagList table, from beginning * of Axis table (may be NULL) * Array of 4-byte baseline identification tags — must * be in alphabetical order */ - OffsetTo + Offset16To baseScriptList; /* Offset to BaseScriptList table, from beginning * of Axis table * Array of BaseScriptRecords, in alphabetical order @@ -501,11 +505,11 @@ protected: FixedVersion<>version; /* Version of the BASE table */ - OffsetTohAxis; /* Offset to horizontal Axis table, from beginning + Offset16TohAxis; /* Offset to horizontal Axis table, from beginning * of BASE table (may be NULL) */ - OffsetTovAxis; /* Offset to vertical Axis table, from beginning + Offset16TovAxis; /* Offset to vertical Axis table, from beginning * of BASE table (may be NULL) */ - LOffsetTo + Offset32To varStore; /* Offset to the table of Item Variation * Store--from beginning of BASE * header (may be NULL). Introduced diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc 2022-10-10 13:07:22.000000000 +0000 @@ -46,7 +46,7 @@ #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" -#include "hb-ot-layout-base-table.hh" // Just so we compile it; unused otherwise. +#include "hb-ot-layout-base-table.hh" #include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise. #include "hb-ot-name-table.hh" #include "hb-ot-os2-table.hh" @@ -54,6 +54,9 @@ #include "hb-aat-layout-morx-table.hh" #include "hb-aat-layout-opbd-table.hh" // Just so we compile it; unused otherwise. +using OT::Layout::GSUB::GSUB; +using OT::Layout::GPOS; + /** * SECTION:hb-ot-layout * @title: hb-ot-layout @@ -131,7 +134,9 @@ AAT::hb_aat_apply_context_t c (plan, font, buffer, blob); + if (!buffer->message (font, "start table kern")) return; kern.apply (&c); + (void) buffer->message (font, "end table kern"); } #endif @@ -144,7 +149,7 @@ OT::GDEF::is_blocklisted (hb_blob_t *blob, hb_face_t *face) const { -#ifdef HB_NO_OT_LAYOUT_BLACKLIST +#ifdef HB_NO_OT_LAYOUT_BLOCKLIST return false; #endif /* The ugly business of blocklisting individual fonts' tables happen here! @@ -256,7 +261,6 @@ { _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint)); _hb_glyph_info_clear_lig_props (&buffer->info[i]); - buffer->info[i].syllable() = 0; } } @@ -331,6 +335,8 @@ * * Useful if the client program wishes to cache the list. * + * Return value: Total number of attachment points for @glyph. + * **/ unsigned int hb_ot_layout_get_attach_points (hb_face_t *face, @@ -357,6 +363,15 @@ * Fetches a list of the caret positions defined for a ligature glyph in the GDEF * table of the font. The list returned will begin at the offset provided. * + * Note that a ligature that is formed from n characters will have n-1 + * caret positions. The first character is not represented in the array, + * since its caret position is the glyph position. + * + * The positions returned by this function are 'unshaped', and will have to + * be fixed up for kerning that may be applied to the ligature glyph. + * + * Return value: Total number of ligature caret positions for @glyph. + * **/ unsigned int hb_ot_layout_get_ligature_carets (hb_font_t *font, @@ -376,20 +391,20 @@ */ bool -OT::GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED, +GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED, hb_face_t *face) const { -#ifdef HB_NO_OT_LAYOUT_BLACKLIST +#ifdef HB_NO_OT_LAYOUT_BLOCKLIST return false; #endif return false; } bool -OT::GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED, +GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED, hb_face_t *face HB_UNUSED) const { -#ifdef HB_NO_OT_LAYOUT_BLACKLIST +#ifdef HB_NO_OT_LAYOUT_BLOCKLIST return false; #endif return false; @@ -419,6 +434,8 @@ * Fetches a list of all scripts enumerated in the specified face's GSUB table * or GPOS table. The list returned will begin at the offset provided. * + * Return value: Total number of script tags. + * **/ unsigned int hb_ot_layout_table_get_script_tags (hb_face_t *face, @@ -585,6 +602,8 @@ * * Fetches a list of all feature tags in the given face's GSUB or GPOS table. * + * Return value: Total number of feature tags. + * **/ unsigned int hb_ot_layout_table_get_feature_tags (hb_face_t *face, @@ -603,7 +622,7 @@ * hb_ot_layout_table_find_feature: * @face: #hb_face_t to work upon * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS - * @feature_tag: The #hb_tag_t og the requested feature tag + * @feature_tag: The #hb_tag_t of the requested feature tag * @feature_index: (out): The index of the requested feature * * Fetches the index for a given feature tag in the specified face's GSUB table @@ -647,6 +666,8 @@ * Fetches a list of language tags in the given face's GSUB or GPOS table, underneath * the specified script index. The list returned will begin at the offset provided. * + * Return value: Total number of language tags. + * **/ unsigned int hb_ot_layout_script_get_language_tags (hb_face_t *face, @@ -676,8 +697,8 @@ * * Return value: %true if the language tag is found, %false otherwise * - * Since: ?? - * Deprecated: ?? + * Since: 0.6.0 + * Deprecated: 2.0.0 **/ hb_bool_t hb_ot_layout_script_find_language (hb_face_t *face, @@ -705,10 +726,14 @@ * @language_tags: The array of language tags * @language_index: (out): The index of the requested language * - * Fetches the index of a given language tag in the specified face's GSUB table - * or GPOS table, underneath the specified script index. + * Fetches the index of the first language tag fom @language_tags that is present + * in the specified face's GSUB or GPOS table, underneath the specified script + * index. * - * Return value: %true if the language tag is found, %false otherwise + * If none of the given language tags is found, %false is returned and + * @language_index is set to the default language index. + * + * Return value: %true if one of the given language tags is found, %false otherwise * * Since: 2.0.0 **/ @@ -734,7 +759,8 @@ if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index)) return false; - if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX; + if (language_index) + *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX; return false; } @@ -818,6 +844,8 @@ * Fetches a list of all features in the specified face's GSUB table * or GPOS table, underneath the specified script and language. The list * returned will begin at the offset provided. + * + * Return value: Total number of features. **/ unsigned int hb_ot_layout_language_get_feature_indexes (hb_face_t *face, @@ -850,6 +878,7 @@ * or GPOS table, underneath the specified script and language. The list * returned will begin at the offset provided. * + * Return value: Total number of feature tags. **/ unsigned int hb_ot_layout_language_get_feature_tags (hb_face_t *face, @@ -932,6 +961,8 @@ * the specified face's GSUB table or GPOS table. The list returned will * begin at the offset provided. * + * Return value: Total number of lookups. + * * Since: 0.9.7 **/ unsigned int @@ -960,6 +991,8 @@ * Fetches the total number of lookups enumerated in the specified * face's GSUB table or GPOS table. * + * Return value: Total number of lookups. + * * Since: 0.9.22 **/ unsigned int @@ -974,10 +1007,37 @@ { hb_collect_features_context_t (hb_face_t *face, hb_tag_t table_tag, - hb_set_t *feature_indexes_) + hb_set_t *feature_indices_, + const hb_tag_t *features) + : g (get_gsubgpos_table (face, table_tag)), - feature_indexes (feature_indexes_), - script_count (0),langsys_count (0), feature_index_count (0) {} + feature_indices (feature_indices_), + has_feature_filter (false), + script_count (0),langsys_count (0), feature_index_count (0) + { + compute_feature_filter (features); + } + + void compute_feature_filter (const hb_tag_t *features) + { + if (features == nullptr) + { + has_feature_filter = false; + return; + } + + has_feature_filter = true; + hb_set_t features_set; + for (; *features; features++) + features_set.add (*features); + + for (unsigned i = 0; i < g.get_feature_count (); i++) + { + hb_tag_t tag = g.get_feature_tag (i); + if (features_set.has (tag)) + feature_indices_filter.add(i); + } + } bool visited (const OT::Script &s) { @@ -1026,7 +1086,9 @@ public: const OT::GSUBGPOS &g; - hb_set_t *feature_indexes; + hb_set_t *feature_indices; + hb_set_t feature_indices_filter; + bool has_feature_filter; private: hb_set_t visited_script; @@ -1038,37 +1100,31 @@ static void langsys_collect_features (hb_collect_features_context_t *c, - const OT::LangSys &l, - const hb_tag_t *features) + const OT::LangSys &l) { if (c->visited (l)) return; - if (!features) + if (!c->has_feature_filter) { /* All features. */ if (l.has_required_feature () && !c->visited_feature_indices (1)) - c->feature_indexes->add (l.get_required_feature_index ()); + c->feature_indices->add (l.get_required_feature_index ()); + // TODO(garretrieger): filter out indices >= feature count? if (!c->visited_feature_indices (l.featureIndex.len)) - l.add_feature_indexes_to (c->feature_indexes); + l.add_feature_indexes_to (c->feature_indices); } else { - /* Ugh. Any faster way? */ - for (; *features; features++) + if (c->feature_indices_filter.is_empty()) return; + unsigned int num_features = l.get_feature_count (); + for (unsigned int i = 0; i < num_features; i++) { - hb_tag_t feature_tag = *features; - unsigned int num_features = l.get_feature_count (); - for (unsigned int i = 0; i < num_features; i++) - { - unsigned int feature_index = l.get_feature_index (i); + unsigned int feature_index = l.get_feature_index (i); + if (!c->feature_indices_filter.has (feature_index)) continue; - if (feature_tag == c->g.get_feature_tag (feature_index)) - { - c->feature_indexes->add (feature_index); - break; - } - } + c->feature_indices->add (feature_index); + c->feature_indices_filter.del (feature_index); } } } @@ -1076,8 +1132,7 @@ static void script_collect_features (hb_collect_features_context_t *c, const OT::Script &s, - const hb_tag_t *languages, - const hb_tag_t *features) + const hb_tag_t *languages) { if (c->visited (s)) return; @@ -1086,14 +1141,13 @@ /* All languages. */ if (s.has_default_lang_sys ()) langsys_collect_features (c, - s.get_default_lang_sys (), - features); + s.get_default_lang_sys ()); + unsigned int count = s.get_lang_sys_count (); for (unsigned int language_index = 0; language_index < count; language_index++) langsys_collect_features (c, - s.get_lang_sys (language_index), - features); + s.get_lang_sys (language_index)); } else { @@ -1102,8 +1156,8 @@ unsigned int language_index; if (s.find_lang_sys_index (*languages, &language_index)) langsys_collect_features (c, - s.get_lang_sys (language_index), - features); + s.get_lang_sys (language_index)); + } } } @@ -1134,7 +1188,7 @@ const hb_tag_t *features, hb_set_t *feature_indexes /* OUT */) { - hb_collect_features_context_t c (face, table_tag, feature_indexes); + hb_collect_features_context_t c (face, table_tag, feature_indexes, features); if (!scripts) { /* All scripts. */ @@ -1142,8 +1196,7 @@ for (unsigned int script_index = 0; script_index < count; script_index++) script_collect_features (&c, c.g.get_script (script_index), - languages, - features); + languages); } else { @@ -1153,8 +1206,7 @@ if (c.g.find_script_index (*scripts, &script_index)) script_collect_features (&c, c.g.get_script (script_index), - languages, - features); + languages); } } } @@ -1262,6 +1314,8 @@ * Fetches a list of feature variations in the specified face's GSUB table * or GPOS table, at the specified variation coordinates. * + * Return value: %true if feature variations were found, %false otherwise. + * **/ hb_bool_t hb_ot_layout_table_find_feature_variations (hb_face_t *face, @@ -1291,6 +1345,8 @@ * the specified face's GSUB table or GPOS table, enabled at the specified * variations index. The list returned will begin at the offset provided. * + * Return value: Total number of lookups. + * **/ unsigned int hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face, @@ -1337,7 +1393,8 @@ * @lookup_index: The index of the lookup to query * @glyphs: The sequence of glyphs to query for substitution * @glyphs_length: The length of the glyph sequence - * @zero_context: #hb_bool_t indicating whether substitutions should be context-free + * @zero_context: #hb_bool_t indicating whether pre-/post-context are disallowed + * in substitutions * * Tests whether a specified lookup in the specified face would * trigger a substitution on the given glyph sequence. @@ -1443,8 +1500,9 @@ unsigned int lookup_index, hb_set_t *glyphs /* OUT */) { - hb_map_t done_lookups; - OT::hb_closure_context_t c (face, glyphs, &done_lookups); + hb_map_t done_lookups_glyph_count; + hb_hashmap_t> done_lookups_glyph_set; + OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set); const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index); @@ -1467,14 +1525,16 @@ const hb_set_t *lookups, hb_set_t *glyphs /* OUT */) { - hb_map_t done_lookups; - OT::hb_closure_context_t c (face, glyphs, &done_lookups); - const OT::GSUB& gsub = *face->table.GSUB->table; + hb_map_t done_lookups_glyph_count; + hb_hashmap_t> done_lookups_glyph_set; + OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set); + const GSUB& gsub = *face->table.GSUB->table; unsigned int iteration_count = 0; unsigned int glyphs_length; do { + c.reset_lookup_visit_count (); glyphs_length = glyphs->get_population (); if (lookups) { @@ -1491,7 +1551,7 @@ } /* - * OT::GPOS + * GPOS */ @@ -1522,7 +1582,7 @@ void hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer) { - OT::GPOS::position_start (font, buffer); + GPOS::position_start (font, buffer); } @@ -1537,7 +1597,7 @@ void hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer) { - OT::GPOS::position_finish_advances (font, buffer); + GPOS::position_finish_advances (font, buffer); } /** @@ -1551,7 +1611,7 @@ void hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) { - OT::GPOS::position_finish_offsets (font, buffer); + GPOS::position_finish_offsets (font, buffer); } @@ -1586,7 +1646,7 @@ unsigned int *range_start, /* OUT. May be NULL */ unsigned int *range_end /* OUT. May be NULL */) { - const OT::GPOS &gpos = *face->table.GPOS->table; + const GPOS &gpos = *face->table.GPOS->table; const hb_tag_t tag = HB_TAG ('s','i','z','e'); unsigned int num_features = gpos.get_feature_count (); @@ -1737,28 +1797,28 @@ struct GSUBProxy { static constexpr unsigned table_index = 0u; - static constexpr bool inplace = false; + static constexpr bool always_inplace = false; typedef OT::SubstLookup Lookup; GSUBProxy (hb_face_t *face) : table (*face->table.GSUB->table), accels (face->table.GSUB->accels) {} - const OT::GSUB &table; + const GSUB &table; const OT::hb_ot_layout_lookup_accelerator_t *accels; }; struct GPOSProxy { static constexpr unsigned table_index = 1u; - static constexpr bool inplace = true; + static constexpr bool always_inplace = true; typedef OT::PosLookup Lookup; GPOSProxy (hb_face_t *face) : table (*face->table.GPOS->table), accels (face->table.GPOS->accels) {} - const OT::GPOS &table; + const GPOS &table; const OT::hb_ot_layout_lookup_accelerator_t *accels; }; @@ -1767,6 +1827,8 @@ apply_forward (OT::hb_ot_apply_context_t *c, const OT::hb_ot_layout_lookup_accelerator_t &accel) { + bool use_cache = accel.cache_enter (c); + bool ret = false; hb_buffer_t *buffer = c->buffer; while (buffer->idx < buffer->len && buffer->successful) @@ -1776,7 +1838,7 @@ (buffer->cur().mask & c->lookup_mask) && c->check_glyph_property (&buffer->cur(), c->lookup_props)) { - applied = accel.apply (c); + applied = accel.apply (c, use_cache); } if (applied) @@ -1784,6 +1846,10 @@ else (void) buffer->next_glyph (); } + + if (use_cache) + accel.cache_leave (c); + return ret; } @@ -1798,7 +1864,7 @@ if (accel.may_have (buffer->cur().codepoint) && (buffer->cur().mask & c->lookup_mask) && c->check_glyph_property (&buffer->cur(), c->lookup_props)) - ret |= accel.apply (c); + ret |= accel.apply (c, false); /* The reverse lookup doesn't "advance" cursor (for good reason). */ buffer->idx--; @@ -1824,27 +1890,20 @@ if (likely (!lookup.is_reverse ())) { /* in/out forward substitution/positioning */ - if (Proxy::table_index == 0u) + if (!Proxy::always_inplace) buffer->clear_output (); + buffer->idx = 0; + apply_forward (c, accel); - bool ret; - ret = apply_forward (c, accel); - if (ret) - { - if (!Proxy::inplace) - buffer->swap_buffers (); - else - assert (!buffer->has_separate_output ()); - } + if (!Proxy::always_inplace) + buffer->sync (); } else { /* in-place backward substitution/positioning */ - if (Proxy::table_index == 0u) - buffer->remove_output (); + assert (!buffer->have_output); buffer->idx = buffer->len - 1; - apply_backward (c, accel); } } @@ -1858,9 +1917,10 @@ const unsigned int table_index = proxy.table_index; unsigned int i = 0; OT::hb_ot_apply_context_t c (table_index, font, buffer); - c.set_recurse_func (Proxy::Lookup::apply_recurse_func); + c.set_recurse_func (Proxy::Lookup::template dispatch_recurse_func); - for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++) { + for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++) + { const stage_map_t *stage = &stages[table_index][stage_index]; for (; i < stage->last_lookup; i++) { @@ -1870,11 +1930,9 @@ c.set_lookup_mask (lookups[table_index][i].mask); c.set_auto_zwj (lookups[table_index][i].auto_zwj); c.set_auto_zwnj (lookups[table_index][i].auto_zwnj); - if (lookups[table_index][i].random) - { - c.set_random (true); - buffer->unsafe_to_break_all (); - } + c.set_random (lookups[table_index][i].random); + c.set_per_syllable (lookups[table_index][i].per_syllable); + apply_string (&c, proxy.table.get_lookup (lookup_index), proxy.accels[lookup_index]); @@ -1882,10 +1940,7 @@ } if (stage->pause_func) - { - buffer->clear_output (); stage->pause_func (plan, font, buffer); - } } } @@ -1915,17 +1970,88 @@ #ifndef HB_NO_BASE /** + * hb_ot_layout_get_horizontal_baseline_tag_for_script: + * @script: a script tag. + * + * Fetches the dominant horizontal baseline tag used by @script. + * + * Return value: dominant baseline tag for the @script. + * + * Since: 4.0.0 + **/ +hb_ot_layout_baseline_tag_t +hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script) +{ + /* Keep in sync with hb_ot_layout_get_baseline_with_fallback */ + switch ((int) script) + { + /* Unicode-1.1 additions */ + case HB_SCRIPT_BENGALI: + case HB_SCRIPT_DEVANAGARI: + case HB_SCRIPT_GUJARATI: + case HB_SCRIPT_GURMUKHI: + /* Unicode-2.0 additions */ + case HB_SCRIPT_TIBETAN: + /* Unicode-4.0 additions */ + case HB_SCRIPT_LIMBU: + /* Unicode-4.1 additions */ + case HB_SCRIPT_SYLOTI_NAGRI: + /* Unicode-5.0 additions */ + case HB_SCRIPT_PHAGS_PA: + /* Unicode-5.2 additions */ + case HB_SCRIPT_MEETEI_MAYEK: + /* Unicode-6.1 additions */ + case HB_SCRIPT_SHARADA: + case HB_SCRIPT_TAKRI: + /* Unicode-7.0 additions */ + case HB_SCRIPT_MODI: + case HB_SCRIPT_SIDDHAM: + case HB_SCRIPT_TIRHUTA: + /* Unicode-9.0 additions */ + case HB_SCRIPT_MARCHEN: + case HB_SCRIPT_NEWA: + /* Unicode-10.0 additions */ + case HB_SCRIPT_SOYOMBO: + case HB_SCRIPT_ZANABAZAR_SQUARE: + /* Unicode-11.0 additions */ + case HB_SCRIPT_DOGRA: + case HB_SCRIPT_GUNJALA_GONDI: + /* Unicode-12.0 additions */ + case HB_SCRIPT_NANDINAGARI: + return HB_OT_LAYOUT_BASELINE_TAG_HANGING; + + /* Unicode-1.1 additions */ + case HB_SCRIPT_HANGUL: + case HB_SCRIPT_HAN: + case HB_SCRIPT_HIRAGANA: + case HB_SCRIPT_KATAKANA: + /* Unicode-3.0 additions */ + case HB_SCRIPT_BOPOMOFO: + /* Unicode-9.0 additions */ + case HB_SCRIPT_TANGUT: + /* Unicode-10.0 additions */ + case HB_SCRIPT_NUSHU: + /* Unicode-13.0 additions */ + case HB_SCRIPT_KHITAN_SMALL_SCRIPT: + return HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT; + + default: + return HB_OT_LAYOUT_BASELINE_TAG_ROMAN; + } +} + +/** * hb_ot_layout_get_baseline: * @font: a font * @baseline_tag: a baseline tag * @direction: text direction. * @script_tag: script tag. * @language_tag: language tag, currently unused. - * @coord: (out): baseline value if found. + * @coord: (out) (nullable): baseline value if found. * * Fetches a baseline value from the face. * - * Return value: if found baseline value in the font. + * Return value: %true if found baseline value in the font. * * Since: 2.6.0 **/ @@ -1937,13 +2063,231 @@ hb_tag_t language_tag, hb_position_t *coord /* OUT. May be NULL. */) { - bool result = font->face->table.BASE->get_baseline (font, baseline_tag, direction, script_tag, language_tag, coord); + return font->face->table.BASE->get_baseline (font, baseline_tag, direction, script_tag, language_tag, coord); +} + +/** + * hb_ot_layout_get_baseline_with_fallback: + * @font: a font + * @baseline_tag: a baseline tag + * @direction: text direction. + * @script_tag: script tag. + * @language_tag: language tag, currently unused. + * @coord: (out): baseline value if found. + * + * Fetches a baseline value from the face, and synthesizes + * it if the font does not have it. + * + * Since: 4.0.0 + **/ +void +hb_ot_layout_get_baseline_with_fallback (hb_font_t *font, + hb_ot_layout_baseline_tag_t baseline_tag, + hb_direction_t direction, + hb_tag_t script_tag, + hb_tag_t language_tag, + hb_position_t *coord /* OUT */) +{ + if (hb_ot_layout_get_baseline (font, + baseline_tag, + direction, + script_tag, + language_tag, + coord)) + return; + + /* Synthesize missing baselines. + * See https://www.w3.org/TR/css-inline-3/#baseline-synthesis-fonts + */ + switch (baseline_tag) + { + case HB_OT_LAYOUT_BASELINE_TAG_ROMAN: + *coord = 0; // FIXME origin ? + break; + + case HB_OT_LAYOUT_BASELINE_TAG_MATH: + { + hb_codepoint_t glyph; + hb_glyph_extents_t extents; + if (HB_DIRECTION_IS_HORIZONTAL (direction) && + (hb_font_get_nominal_glyph (font, 0x2212u, &glyph) || + hb_font_get_nominal_glyph (font, '-', &glyph)) && + hb_font_get_glyph_extents (font, glyph, &extents)) + { + *coord = extents.y_bearing + extents.height / 2; + } + else + { + hb_position_t x_height = font->y_scale / 2; +#ifndef HB_NO_METRICS + hb_ot_metrics_get_position_with_fallback (font, HB_OT_METRICS_TAG_X_HEIGHT, &x_height); +#endif + *coord = x_height / 2; + } + } + break; + + case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT: + case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT: + { + hb_position_t embox_top, embox_bottom; - if (result && coord) - *coord = HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (*coord) : font->em_scale_x (*coord); + hb_ot_layout_get_baseline_with_fallback (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT, + direction, + script_tag, + language_tag, + &embox_top); + hb_ot_layout_get_baseline_with_fallback (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT, + direction, + script_tag, + language_tag, + &embox_bottom); - return result; + if (baseline_tag == HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT) + *coord = embox_top + (embox_bottom - embox_top) / 10; + else + *coord = embox_bottom + (embox_top - embox_bottom) / 10; + } + break; + + case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT: + if (hb_ot_layout_get_baseline (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT, + direction, + script_tag, + language_tag, + coord)) + *coord += HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale; + else + { + hb_font_extents_t font_extents; + hb_font_get_extents_for_direction (font, direction, &font_extents); + *coord = font_extents.ascender; + } + break; + + case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT: + if (hb_ot_layout_get_baseline (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT, + direction, + script_tag, + language_tag, + coord)) + *coord -= HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale; + else + { + hb_font_extents_t font_extents; + hb_font_get_extents_for_direction (font, direction, &font_extents); + *coord = font_extents.descender; + } + break; + + case HB_OT_LAYOUT_BASELINE_TAG_HANGING: + if (HB_DIRECTION_IS_HORIZONTAL (direction)) + { + hb_codepoint_t ch; + hb_codepoint_t glyph; + hb_glyph_extents_t extents; + + /* Keep in sync with hb_ot_layout_get_horizontal_baseline_for_script */ + switch ((int) script_tag) + { + /* Unicode-1.1 additions */ + case HB_SCRIPT_BENGALI: ch = 0x0995u; break; + case HB_SCRIPT_DEVANAGARI: ch = 0x0915u; break; + case HB_SCRIPT_GUJARATI: ch = 0x0a95u; break; + case HB_SCRIPT_GURMUKHI: ch = 0x0a15u; break; + /* Unicode-2.0 additions */ + case HB_SCRIPT_TIBETAN: ch = 0x0f40u; break; + /* Unicode-4.0 additions */ + case HB_SCRIPT_LIMBU: ch = 0x1901u; break; + /* Unicode-4.1 additions */ + case HB_SCRIPT_SYLOTI_NAGRI: ch = 0xa807u; break; + /* Unicode-5.0 additions */ + case HB_SCRIPT_PHAGS_PA: ch = 0xa840u; break; + /* Unicode-5.2 additions */ + case HB_SCRIPT_MEETEI_MAYEK: ch = 0xabc0u; break; + /* Unicode-6.1 additions */ + case HB_SCRIPT_SHARADA: ch = 0x11191u; break; + case HB_SCRIPT_TAKRI: ch = 0x1168cu; break; + /* Unicode-7.0 additions */ + case HB_SCRIPT_MODI: ch = 0x1160eu;break; + case HB_SCRIPT_SIDDHAM: ch = 0x11590u; break; + case HB_SCRIPT_TIRHUTA: ch = 0x1148fu; break; + /* Unicode-9.0 additions */ + case HB_SCRIPT_MARCHEN: ch = 0x11c72u; break; + case HB_SCRIPT_NEWA: ch = 0x1140eu; break; + /* Unicode-10.0 additions */ + case HB_SCRIPT_SOYOMBO: ch = 0x11a5cu; break; + case HB_SCRIPT_ZANABAZAR_SQUARE: ch = 0x11a0bu; break; + /* Unicode-11.0 additions */ + case HB_SCRIPT_DOGRA: ch = 0x1180au; break; + case HB_SCRIPT_GUNJALA_GONDI: ch = 0x11d6cu; break; + /* Unicode-12.0 additions */ + case HB_SCRIPT_NANDINAGARI: ch = 0x119b0u; break; + default: ch = 0; break; + } + + if (ch && + hb_font_get_nominal_glyph (font, ch, &glyph) && + hb_font_get_glyph_extents (font, glyph, &extents)) + *coord = extents.y_bearing; + else + *coord = font->y_scale * 6 / 10; // FIXME makes assumptions about origin + } + else + *coord = font->x_scale * 6 / 10; // FIXME makes assumptions about origin + break; + + case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL: + { + hb_position_t top, bottom; + hb_ot_layout_get_baseline_with_fallback (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT, + direction, + script_tag, + language_tag, + &top); + hb_ot_layout_get_baseline_with_fallback (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT, + direction, + script_tag, + language_tag, + &bottom); + *coord = (top + bottom) / 2; + + } + break; + + case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL: + { + hb_position_t top, bottom; + hb_ot_layout_get_baseline_with_fallback (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT, + direction, + script_tag, + language_tag, + &top); + hb_ot_layout_get_baseline_with_fallback (font, + HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT, + direction, + script_tag, + language_tag, + &bottom); + *coord = (top + bottom) / 2; + + } + break; + + case _HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE: + default: + *coord = 0; + break; + } } + #endif @@ -1961,14 +2305,14 @@ private: template auto _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN - ( obj.get_glyph_alternates (hb_forward (ds)...) ) + ( obj.get_glyph_alternates (std::forward (ds)...) ) template auto _dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN ( default_return_value () ) public: template auto dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN - ( _dispatch (obj, hb_prioritize, hb_forward (ds)...) ) + ( _dispatch (obj, hb_prioritize, std::forward (ds)...) ) }; /** @@ -1984,7 +2328,7 @@ * * Fetches alternates of a glyph from a given GSUB lookup index. * - * Return value: total number of alternates found in the specific lookup index for the given glyph id. + * Return value: Total number of alternates found in the specific lookup index for the given glyph id. * * Since: 2.6.8 **/ diff -Nru openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh --- openjdk-17-17.0.4+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh 2022-10-10 13:07:22.000000000 +0000 @@ -37,7 +37,7 @@ #ifndef HB_MAX_NESTING_LEVEL -#define HB_MAX_NESTING_LEVEL 6 +#define HB_MAX_NESTING_LEVEL 64 #endif #ifndef HB_MAX_CONTEXT_LENGTH #define HB_MAX_CONTEXT_LENGTH 64 @@ -60,6 +60,10 @@ #define HB_MAX_LANGSYS 2000 #endif +#ifndef HB_MAX_LANGSYS_FEATURE_COUNT +#define HB_MAX_LANGSYS_FEATURE_COUNT 50000 +#endif + #ifndef HB_MAX_FEATURES #define HB_MAX_FEATURES 750 #endif @@ -68,8 +72,8 @@ #define HB_MAX_FEATURE_INDICES 1500 #endif -#ifndef HB_MAX_LOOKUP_INDICES -#define HB_MAX_LOOKUP_INDICES 20000 +#ifndef HB_MAX_LOOKUP_VISIT_COUNT +#define HB_MAX_LOOKUP_VISIT_COUNT 35000 #endif @@ -87,12 +91,45 @@ static inline void ClassDef_serialize (hb_serialize_context_t *c, Iterator it); -static void ClassDef_remap_and_serialize (hb_serialize_context_t *c, - const hb_set_t &glyphset, - const hb_map_t &gid_klass_map, - hb_sorted_vector_t &glyphs, - const hb_set_t &klasses, - hb_map_t *klass_map /*INOUT*/); +static void ClassDef_remap_and_serialize ( + hb_serialize_context_t *c, + const hb_set_t &klasses, + bool use_class_zero, + hb_sorted_vector_t> &glyph_and_klass, /* IN/OUT */ + hb_map_t *klass_map /*IN/OUT*/); + + +struct hb_prune_langsys_context_t +{ + hb_prune_langsys_context_t (const void *table_, + hb_hashmap_t> *script_langsys_map_, + const hb_map_t *duplicate_feature_map_, + hb_set_t *new_collected_feature_indexes_) + :table (table_), + script_langsys_map (script_langsys_map_), + duplicate_feature_map (duplicate_feature_map_), + new_feature_indexes (new_collected_feature_indexes_), + script_count (0),langsys_feature_count (0) {} + + bool visitScript () + { return script_count++ < HB_MAX_SCRIPTS; } + + bool visitLangsys (unsigned feature_count) + { + langsys_feature_count += feature_count; + return langsys_feature_count < HB_MAX_LANGSYS_FEATURE_COUNT; + } + + public: + const void *table; + hb_hashmap_t> *script_langsys_map; + const hb_map_t *duplicate_feature_map; + hb_set_t *new_feature_indexes; + + private: + unsigned script_count; + unsigned langsys_feature_count; +}; struct hb_subset_layout_context_t : hb_dispatch_context_t @@ -119,22 +156,27 @@ bool visitLookupIndex() { lookup_index_count++; - return lookup_index_count < HB_MAX_LOOKUP_INDICES; + return lookup_index_count < HB_MAX_LOOKUP_VISIT_COUNT; } hb_subset_context_t *subset_context; const hb_tag_t table_tag; const hb_map_t *lookup_index_map; + const hb_hashmap_t> *script_langsys_map; const hb_map_t *feature_index_map; + unsigned cur_script_index; hb_subset_layout_context_t (hb_subset_context_t *c_, hb_tag_t tag_, hb_map_t *lookup_map_, - hb_map_t *feature_map_) : + hb_hashmap_t> *script_langsys_map_, + hb_map_t *feature_index_map_) : subset_context (c_), table_tag (tag_), lookup_index_map (lookup_map_), - feature_index_map (feature_map_), + script_langsys_map (script_langsys_map_), + feature_index_map (feature_index_map_), + cur_script_index (0xFFFFu), script_count (0), langsys_count (0), feature_index_count (0), @@ -178,9 +220,9 @@ template bool operator () (T&& offset) { + auto snap = subset_context->serializer->snapshot (); auto *o = out.serialize_append (subset_context->serializer); if (unlikely (!o)) return false; - auto snap = subset_context->serializer->snapshot (); bool ret = o->serialize_subset (subset_context, offset, base); if (!ret) { @@ -209,9 +251,9 @@ template bool operator () (T&& offset) { + auto snap = subset_context->serializer->snapshot (); auto *o = out.serialize_append (subset_context->serializer); if (unlikely (!o)) return false; - auto snap = subset_context->serializer->snapshot (); bool ret = o->serialize_subset (subset_context, offset, base, arg); if (!ret) { @@ -287,6 +329,43 @@ } HB_FUNCOBJ (subset_record_array); + +template +struct serialize_math_record_array_t +{ + serialize_math_record_array_t (hb_serialize_context_t *serialize_context_, + OutputArray& out_, + const void *base_) : serialize_context (serialize_context_), + out (out_), base (base_) {} + + template + bool operator () (T&& record) + { + if (!serialize_context->copy (record, base)) return false; + out.len++; + return true; + } + + private: + hb_serialize_context_t *serialize_context; + OutputArray &out; + const void *base; +}; + +/* + * Helper to serialize an array of MATH records. + */ +struct +{ + template + serialize_math_record_array_t + operator () (hb_serialize_context_t *serialize_context, OutputArray& out, + const void *base) const + { return serialize_math_record_array_t (serialize_context, out, base); } + +} +HB_FUNCOBJ (serialize_math_record_array); + /* * * OpenType Layout Common Table Formats @@ -325,7 +404,7 @@ } Tag tag; /* 4-byte Tag identifier */ - OffsetTo + Offset16To offset; /* Offset from beginning of object holding * the Record */ public: @@ -333,11 +412,11 @@ }; template -struct RecordArrayOf : SortedArrayOf> +struct RecordArrayOf : SortedArray16Of> { - const OffsetTo& get_offset (unsigned int i) const + const Offset16To& get_offset (unsigned int i) const { return (*this)[i].offset; } - OffsetTo& get_offset (unsigned int i) + Offset16To& get_offset (unsigned int i) { return (*this)[i].offset; } const Tag& get_tag (unsigned int i) const { return (*this)[i].tag; } @@ -356,7 +435,7 @@ } bool find_index (hb_tag_t tag, unsigned int *index) const { - return this->bfind (tag, index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX); + return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX); } }; @@ -407,6 +486,30 @@ } }; +struct Script; +struct RecordListOfScript : RecordListOf + """, """ """, @@ -684,21 +684,9 @@ checkFiles(expectedOutput, "search.js", "jquery-ui.overrides.css", - "script-dir/jquery-3.5.1.min.js", + "script-dir/jquery-3.6.0.min.js", "script-dir/jquery-ui.min.js", "script-dir/jquery-ui.min.css", - "script-dir/jquery-ui.structure.min.css", - "script-dir/images/ui-bg_glass_65_dadada_1x400.png", - "script-dir/images/ui-icons_454545_256x240.png", - "script-dir/images/ui-bg_glass_95_fef1ec_1x400.png", - "script-dir/images/ui-bg_glass_75_dadada_1x400.png", - "script-dir/images/ui-bg_highlight-soft_75_cccccc_1x100.png", - "script-dir/images/ui-icons_888888_256x240.png", - "script-dir/images/ui-icons_2e83ff_256x240.png", - "script-dir/images/ui-icons_cd0a0a_256x240.png", - "script-dir/images/ui-bg_glass_55_fbf9ee_1x400.png", - "script-dir/images/ui-icons_222222_256x240.png", - "script-dir/images/ui-bg_glass_75_e6e6e6_1x400.png", "resources/x.png", "resources/glass.png"); } diff -Nru openjdk-17-17.0.4+8/test/langtools/jdk/javadoc/tool/api/basic/APITest.java openjdk-17-17.0.5+8/test/langtools/jdk/javadoc/tool/api/basic/APITest.java --- openjdk-17-17.0.4+8/test/langtools/jdk/javadoc/tool/api/basic/APITest.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/test/langtools/jdk/javadoc/tool/api/basic/APITest.java 2022-10-10 13:07:22.000000000 +0000 @@ -200,21 +200,9 @@ "help-doc.html", "index-all.html", "index.html", - "script-dir/jquery-3.5.1.min.js", + "script-dir/jquery-3.6.0.min.js", "script-dir/jquery-ui.min.js", "script-dir/jquery-ui.min.css", - "script-dir/jquery-ui.structure.min.css", - "script-dir/images/ui-bg_glass_65_dadada_1x400.png", - "script-dir/images/ui-icons_454545_256x240.png", - "script-dir/images/ui-bg_glass_95_fef1ec_1x400.png", - "script-dir/images/ui-bg_glass_75_dadada_1x400.png", - "script-dir/images/ui-bg_highlight-soft_75_cccccc_1x100.png", - "script-dir/images/ui-icons_888888_256x240.png", - "script-dir/images/ui-icons_2e83ff_256x240.png", - "script-dir/images/ui-icons_cd0a0a_256x240.png", - "script-dir/images/ui-bg_glass_55_fbf9ee_1x400.png", - "script-dir/images/ui-icons_222222_256x240.png", - "script-dir/images/ui-bg_glass_75_e6e6e6_1x400.png", "member-search-index.js", "module-search-index.js", "overview-tree.html", diff -Nru openjdk-17-17.0.4+8/test/langtools/tools/javac/Paths/Util.sh openjdk-17-17.0.5+8/test/langtools/tools/javac/Paths/Util.sh --- openjdk-17-17.0.4+8/test/langtools/tools/javac/Paths/Util.sh 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/test/langtools/tools/javac/Paths/Util.sh 2022-10-10 13:07:22.000000000 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ jimage="${TESTJAVA+${TESTJAVA}/bin/}jimage${EXE_SUFFIX}" case `uname -s` in - Windows*|CYGWIN*) + Windows*|CYGWIN*|MSYS*|MINGW*) WindowsOnly() { "$@"; } UnixOnly() { :; } PS=";" ;; diff -Nru openjdk-17-17.0.4+8/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java openjdk-17-17.0.5+8/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java --- openjdk-17-17.0.4+8/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java 2022-07-14 08:05:38.000000000 +0000 +++ openjdk-17-17.0.5+8/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java 2022-10-10 13:07:22.000000000 +0000 @@ -121,6 +121,11 @@ Path filePath = Paths.get(UNIFIED.getPath(), file); try { String strVal = Files.lines(filePath).filter(l -> l.startsWith(metric)).collect(Collectors.joining()); + if (strVal.isEmpty()) { + // sometimes the match for the metric does not exist, e.g. cpu.stat's nr_periods iff the controller + // is not enabled + return UNLIMITED; + } String[] keyValues = strVal.split("\\s+"); String value = keyValues[1]; return convertStringToLong(value); diff -Nru openjdk-17-17.0.4+8/test/micro/org/openjdk/bench/java/security/SSLHandshake.java openjdk-17-17.0.5+8/test/micro/org/openjdk/bench/java/security/SSLHandshake.java --- openjdk-17-17.0.4+8/test/micro/org/openjdk/bench/java/security/SSLHandshake.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/test/micro/org/openjdk/bench/java/security/SSLHandshake.java 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.security; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; + +import java.nio.ByteBuffer; +import java.security.KeyStore; +import java.util.concurrent.TimeUnit; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManagerFactory; + +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +public class SSLHandshake { + + private SSLContext sslc; + + private SSLEngine clientEngine; + private ByteBuffer clientOut = ByteBuffer.allocate(5); + private ByteBuffer clientIn = ByteBuffer.allocate(1 << 15); + + private SSLEngine serverEngine; + private ByteBuffer serverOut = ByteBuffer.allocate(5); + private ByteBuffer serverIn = ByteBuffer.allocate(1 << 15); + + private ByteBuffer cTOs = ByteBuffer.allocateDirect(1 << 16); + private ByteBuffer sTOc = ByteBuffer.allocateDirect(1 << 16); + + @Param({"true", "false"}) + boolean resume; + + @Param({"TLSv1.2", "TLS"}) + String tlsVersion; + + @Setup(Level.Trial) + public void init() throws Exception { + KeyStore ks = TestCertificates.getKeyStore(); + KeyStore ts = TestCertificates.getTrustStore(); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, new char[0]); + + TrustManagerFactory tmf = + TrustManagerFactory.getInstance("SunX509"); + tmf.init(ts); + + SSLContext sslCtx = SSLContext.getInstance(tlsVersion); + sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + sslc = sslCtx; + } + + private HandshakeStatus checkResult(SSLEngine engine, SSLEngineResult result) { + + HandshakeStatus hsStatus = result.getHandshakeStatus(); + + if (hsStatus == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = engine.getDelegatedTask()) != null) { + runnable.run(); + } + hsStatus = engine.getHandshakeStatus(); + } + return hsStatus; + } + + /** + * This benchmark measures the time needed to perform a TLS handshake. + * Data is exchanged using a pair of ByteBuffers. + * The client and the server both operate on the same thread. + */ + @Benchmark + @Warmup(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) + @Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) + @Fork(3) + public SSLSession doHandshake() throws Exception { + + createSSLEngines(); + boolean isCtoS = true; + for (;;) { + HandshakeStatus result; + if (isCtoS) { + result = checkResult(clientEngine, + clientEngine.wrap(clientOut, cTOs) + ); + cTOs.flip(); + checkResult(serverEngine, + serverEngine.unwrap(cTOs, serverIn) + ); + cTOs.compact(); + if (result == HandshakeStatus.NEED_UNWRAP) { + isCtoS = false; + } else if (result == HandshakeStatus.FINISHED) { + break; + } else if (result != HandshakeStatus.NEED_WRAP) { + throw new Exception("Unexpected result "+result); + } + } else { + result = checkResult(serverEngine, + serverEngine.wrap(serverOut, sTOc) + ); + sTOc.flip(); + checkResult(clientEngine, + clientEngine.unwrap(sTOc, clientIn) + ); + sTOc.compact(); + if (result == HandshakeStatus.NEED_UNWRAP) { + isCtoS = true; + } else if (result == HandshakeStatus.FINISHED) { + break; + } else if (result != HandshakeStatus.NEED_WRAP) { + throw new Exception("Unexpected result "+result); + } + } + } + + SSLSession session = clientEngine.getSession(); + if (resume) { + // TLS 1.3 needs another wrap/unwrap to deliver a session ticket + serverEngine.wrap(serverOut, sTOc); + sTOc.flip(); + clientEngine.unwrap(sTOc, clientIn); + sTOc.compact(); + } else { + // invalidate TLS1.2 session. TLS 1.3 doesn't care + session.invalidate(); + } + return session; + } + + private void createSSLEngines() { + /* + * Configure the serverEngine to act as a server in the SSL/TLS + * handshake. + */ + serverEngine = sslc.createSSLEngine(); + serverEngine.setUseClientMode(false); + + /* + * Similar to above, but using client mode instead. + */ + clientEngine = sslc.createSSLEngine("client", 80); + clientEngine.setUseClientMode(true); + } +} diff -Nru openjdk-17-17.0.4+8/test/micro/org/openjdk/bench/java/security/TestCertificates.java openjdk-17-17.0.5+8/test/micro/org/openjdk/bench/java/security/TestCertificates.java --- openjdk-17-17.0.4+8/test/micro/org/openjdk/bench/java/security/TestCertificates.java 1970-01-01 00:00:00.000000000 +0000 +++ openjdk-17-17.0.5+8/test/micro/org/openjdk/bench/java/security/TestCertificates.java 2022-10-10 13:07:22.000000000 +0000 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.security; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.security.GeneralSecurityException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Base64; + +/** + * This class contains a 3-certificate chain for use in TLS tests. + * The method {@link #getKeyStore()} returns a keystore with a single entry + * containing one server+one intermediate CA certificate. + * Server's CN and subjectAltName are both set to "client" + * + * The method {@link #getTrustStore()} returns a keystore with a single entry + * containing the root CA certificate used for signing the intermediate CA. + */ +class TestCertificates { + + // "/C=US/ST=CA/O=Test Root CA, Inc." + // basicConstraints=critical, CA:true + // subjectKeyIdentifier = hash + // authorityKeyIdentifier = keyid:always + // keyUsage = keyCertSign + private static final String ROOT_CA_CERT = + "-----BEGIN CERTIFICATE-----\n" + + "MIIB0jCCAXigAwIBAgIUE+wUdx22foJXSQzD3hpCNCqITLEwCgYIKoZIzj0EAwIw\n" + + "NzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRswGQYDVQQKDBJUZXN0IFJvb3Qg\n" + + "Q0EsIEluYy4wIBcNMjIwNDEyMDcxMzMzWhgPMjEyMjAzMTkwNzEzMzNaMDcxCzAJ\n" + + "BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEbMBkGA1UECgwSVGVzdCBSb290IENBLCBJ\n" + + "bmMuMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBKye/mwO0V0WLr71tf8auFEz\n" + + "EmqhaYWauaP17Fb33fRAeG8aVp9c4B0isv/VgcqSTRMG0SJjbx7ttSYwR/JNhqNg\n" + + "MF4wDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUpfGt4bjadmVzWeXAiSMp9pLU\n" + + "RMkwHwYDVR0jBBgwFoAUpfGt4bjadmVzWeXAiSMp9pLURMkwCwYDVR0PBAQDAgIE\n" + + "MAoGCCqGSM49BAMCA0gAMEUCIBF8YyD5BBuhkFNV/3rNmvvMuvWUAECJ8rrUg8kr\n" + + "J8zpAiEAzbZQsC/IZ0wVNd4lqHn6/Ih5v7vhCgkg95KCP1NhBnU=\n" + + "-----END CERTIFICATE-----"; + + // "/C=US/ST=CA/O=Test Intermediate CA, Inc." + // basicConstraints=critical, CA:true, pathlen:0 + // subjectKeyIdentifier = hash + // authorityKeyIdentifier = keyid:always + // keyUsage = keyCertSign + private static final String CA_CERT = + "-----BEGIN CERTIFICATE-----\n" + + "MIIB3TCCAYOgAwIBAgIUQ+lTbsDcIQ1UUg0RGdpJB6JMXpcwCgYIKoZIzj0EAwIw\n" + + "NzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRswGQYDVQQKDBJUZXN0IFJvb3Qg\n" + + "Q0EsIEluYy4wIBcNMjIwNDEyMDcxMzM0WhgPMjEyMjAzMTkwNzEzMzRaMD8xCzAJ\n" + + "BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEjMCEGA1UECgwaVGVzdCBJbnRlcm1lZGlh\n" + + "dGUgQ0EsIEluYy4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ7DsKCSQkP5oT2\n" + + "Wx0gf40N+H/F75w1YmPm6dp2wiQ6JPMN/4En87Ylx0ISJkeXJLxrbLvu2xZ+aonM\n" + + "kckNh/ERo2MwYTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBTqP6hB5Ibr\n" + + "aivot/zWSMKr8ZkCVzAfBgNVHSMEGDAWgBSl8a3huNp2ZXNZ5cCJIyn2ktREyTAL\n" + + "BgNVHQ8EBAMCAgQwCgYIKoZIzj0EAwIDSAAwRQIhAM0vCIV938aqGAEmELIA8Kc4\n" + + "X+kOc4LGE0R7sMiBAbXuAiBlbNVaskKYRHIEGHEtIWet6Ufi3w9NMrycEbBZ+v5o\n" + + "gA==\n" + + "-----END CERTIFICATE-----"; + + // "/C=US/ST=CA/O=Test Server/CN=client" + // subjectKeyIdentifier = hash + // authorityKeyIdentifier = keyid:always + // keyUsage = digitalSignature + // subjectAltName = DNS:client + private static final String SERVER_CERT = + "-----BEGIN CERTIFICATE-----\n" + + "MIIB5TCCAYygAwIBAgIUNWe754lZoDc6wNs9Vsev/h9TMicwCgYIKoZIzj0EAwIw\n" + + "PzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMSMwIQYDVQQKDBpUZXN0IEludGVy\n" + + "bWVkaWF0ZSBDQSwgSW5jLjAgFw0yMjA0MTIwNzEzMzRaGA8yMTIyMDMxOTA3MTMz\n" + + "NFowQTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRQwEgYDVQQKDAtUZXN0IFNl\n" + + "cnZlcjEPMA0GA1UEAwwGY2xpZW50MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE\n" + + "o6zUz5QmzmfHL2xRifvaJenggck/Dlu6KC4v4rGXug69R7tWKWuRUsbSFLy29Rii\n" + + "F7V1wjFhsyGAzNyKf/KlmaNiMGAwHQYDVR0OBBYEFHz32VSnXBF4WdLDOe7e3hF9\n" + + "yDxmMB8GA1UdIwQYMBaAFOo/qEHkhutqK+i3/NZIwqvxmQJXMAsGA1UdDwQEAwIH\n" + + "gDARBgNVHREECjAIggZjbGllbnQwCgYIKoZIzj0EAwIDRwAwRAIgWsCn2LIElgVs\n" + + "VihcQznvBemWneEcmnp/Bw+lwk86KQ8CIA3loL7P/0/Ft/xXtClxJfyxEoZ/Az1n\n" + + "HTTjbe6ZnN0Y\n" + + "-----END CERTIFICATE-----"; + + private static final String serverkey = + //"-----BEGIN PRIVATE KEY-----\n" + + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgKb9cKLH++BgA9CL1\n" + + "cdCLHpD0poPJ/uAkafGXDJBR67ChRANCAASjrNTPlCbOZ8cvbFGJ+9ol6eCByT8O\n" + + "W7ooLi/isZe6Dr1Hu1Ypa5FSxtIUvLb1GKIXtXXCMWGzIYDM3Ip/8qWZ"; + // + "\n-----END PRIVATE KEY-----"; + + private TestCertificates() {} + + public static KeyStore getKeyStore() throws GeneralSecurityException, IOException { + KeyStore result = KeyStore.getInstance("JKS"); + result.load(null, null); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + Certificate serverCert = cf.generateCertificate( + new ByteArrayInputStream( + TestCertificates.SERVER_CERT.getBytes(StandardCharsets.ISO_8859_1))); + Certificate caCert = cf.generateCertificate( + new ByteArrayInputStream( + CA_CERT.getBytes(StandardCharsets.ISO_8859_1))); + KeyFactory kf = KeyFactory.getInstance("EC"); + PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec( + Base64.getMimeDecoder().decode(serverkey)); + Key key = kf.generatePrivate(ks); + Certificate[] chain = {serverCert, caCert}; + + result.setKeyEntry("server", key, new char[0], chain); + return result; + } + + public static KeyStore getTrustStore() throws GeneralSecurityException, IOException { + KeyStore result = KeyStore.getInstance("JKS"); + result.load(null, null); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + Certificate rootcaCert = cf.generateCertificate( + new ByteArrayInputStream( + ROOT_CA_CERT.getBytes(StandardCharsets.ISO_8859_1))); + + result.setCertificateEntry("testca", rootcaCert); + return result; + } +}